关于用更改函数前5字节的方法来拦截API的问题!迷茫中。。。

aipingren 2003-06-03 02:29:04
书上说,在WIN98下以JMP方法(改前5个字节)来拦截某些API函数!但会影响到其他进程
。这样有时会出错!我想问一下,是不是所有的被拦截函数都会影响到其他的进程!我的理解是拦截系统的API函数才会影响到别的进程!比如,屏幕取词的TEXTOUT函数等,因为这样的系统函数会加载到0x80000000以上的地址空间!所以每个进程都是可见的!而如果我要拦截的是某些不是系统DLL函数如:WSOCK32。DLL里的SENDTO函数,是不是该函数不会影响到其他的进程!我试着拦截SENDTO函数了!也没有发现WIN98下出错啊!
...全文
89 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
ly_liuyang 2003-07-18
  • 打赏
  • 举报
回复
对于2000/XP有没有问题的,98就不Ok了

只对当前的Exe有效

unit Demo;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls, Menus;

type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Label1: TLabel;
Panel1: TPanel;
GroupBox1: TGroupBox;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
procedure API_Hookup; stdcall; external 'MYAPIDLL.dll';
procedure API_HookDown; stdcall; external 'MYAPIDLL.dll';
var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var
i:integer;
begin
API_Hookup;
Self.Repaint;
for i:=0 to self.ControlCount-1 do
begin
self.Controls[i].Refresh;
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
i:integer;
begin
API_HookDown;
Self.Repaint;
for i:=0 to self.ControlCount-1 do
begin
self.Controls[i].Refresh;
end;
end;

end.
ly_liuyang 2003-07-18
  • 打赏
  • 举报
回复

library MyAPIDLL;

{ Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }

uses
HookAPI, Windows;

type
TTextOutA = function(DC: HDC; X, Y: Integer; Str: PAnsiChar; Count: Integer): BOOL; stdcall;
TTextOutW = function(DC: HDC; X, Y: Integer; Str: PWideChar; Count: Integer): BOOL; stdcall;
TTextOut = function(DC: HDC; X, Y: Integer; Str: PChar; Count: Integer): BOOL; stdcall;
TDrawTextA = function(hDC: HDC; lpString: PAnsiChar; nCount: Integer; var lpRect: TRect; uFormat: UINT): Integer; stdcall;
TDrawTextW = function(hDC: HDC; lpString: PWideChar; nCount: Integer; var lpRect: TRect; uFormat: UINT): Integer; stdcall;
TDrawText = function(hDC: HDC; lpString: PChar; nCount: Integer; var lpRect: TRect; uFormat: UINT): Integer; stdcall;
var
OldTextOutA: TTextOutA;
OldTextOutW: TTextOutW;
OldTextOut: TTextOut;
OldDrawTextA: TDrawTextA;
OldDrawTextW: TDrawTextW;
OldDrawText: TDrawText;

function MyTextOutA(DC: HDC; X, Y: Integer; Str: PAnsiChar; Count: Integer): BOOL; stdcall;
begin
OldTextOutA(DC, X, Y, 'ABC', length('ABC'));
end;

function MyTextOutW(DC: HDC; X, Y: Integer; Str: PWideChar; Count: Integer): BOOL; stdcall;
begin
OldTextOutW(DC, X, Y, 'ABC', length('ABC'));
end;

function MyTextOut(DC: HDC; X, Y: Integer; Str: PChar; Count: Integer): BOOL; stdcall;
begin
OldTextOut(DC, X, Y, 'ABC', length('ABC'));
end;

function MyDrawTextA(hDC: HDC; lpString: PAnsiChar; nCount: Integer; var lpRect: TRect; uFormat: UINT): Integer; stdcall;
begin
OldDrawTextA(hDC, 'ABC', length('ABC'), lpRect, uFormat);
end;

function MyDrawTextW(hDC: HDC; lpString: PWideChar; nCount: Integer; var lpRect: TRect; uFormat: UINT): Integer; stdcall;
begin
OldDrawTextW(hDC, 'ABC', length('ABC'), lpRect, uFormat);
end;

function MyDrawText(hDC: HDC; lpString: PChar; nCount: Integer; var lpRect: TRect; uFormat: UINT): Integer; stdcall;
begin
OldDrawText(hDC, 'ABC', length('ABC'), lpRect, uFormat);
end;

procedure API_Hookup; stdcall;
begin
//µ÷ÓÃʱÎÒÃÇÒª°ÑÔ­À´µÄº¯ÊýµØÖ·±£´æÏÂÀ´£º
if @OldTextOutA = nil then
@OldTextOutA := LocateFunctionAddress(@TextOutA);
if @OldTextOutW = nil then
@OldTextOutW := LocateFunctionAddress(@TextOutW);
if @OldTextOut = nil then
@OldTextOut := LocateFunctionAddress(@TextOut);
if @OldDrawTextA = nil then
@OldDrawTextA := LocateFunctionAddress(@DrawTextA);
if @OldDrawTextW = nil then
@OldDrawTextW := LocateFunctionAddress(@DrawTextW);
if @OldDrawText = nil then
@OldDrawText := LocateFunctionAddress(@DrawText);
//È»ºóºÜ˳Æä×ÔÈ»µÄÓÃ×Ô¼ºµÄº¯ÊýÌæ»»µôÔ­À´µÄº¯Êý
RepointFunction(@OldTextOutA, @MyTextOutA);
RepointFunction(@OldTextOutW, @MyTextOutW);
RepointFunction(@OldTextOut, @MyTextOut);
RepointFunction(@OldDrawTextA, @MyDrawTextA);
RepointFunction(@OldDrawTextW, @MyDrawTextW);
RepointFunction(@OldDrawText, @MyDrawText);
end;

procedure API_HookDown; stdcall;
begin
if @OldTextOutA <> nil then
begin
RepointFunction(@MyTextOutA, @OldTextOutA);
@OldTextOutA := nil;
end;
if @OldTextOutW <> nil then
begin
RepointFunction(@MyTextOutW, @OldTextOutW);
@OldTextOutW := nil;
end;
if @OldTextOut <> nil then
begin
RepointFunction(@MyTextOut, @OldTextOut);
@OldTextOut := nil;
end;
if @OldDrawTextA <> nil then
begin
RepointFunction(@MyDrawTextA, @OldDrawTextA);
@OldDrawTextA := nil;
end;
if @OldDrawTextW <> nil then
begin
RepointFunction(@MyDrawTextW, @OldDrawTextW);
@OldDrawTextW := nil;
end;
if @OldDrawText <> nil then
begin
RepointFunction(@MyDrawText, @OldDrawText);
@OldDrawText := nil;
end;
end;

Exports
API_Hookup, API_HookDown;
end.
东八泰 2003-07-18
  • 打赏
  • 举报
回复
应该不是吧,挂钩程序可以指定要挂接哪个线称(过程)吧,只是在内存中替换了被调用的dll副本的函数入口地址,应该不会对全局产生影响。
ly_liuyang 2003-07-18
  • 打赏
  • 举报
回复
相关Unit
unit HookAPI;

interface

uses
Windows, Classes;
function LocateFunctionAddress(Code: Pointer): Pointer;
function RepointFunction(OldFunc, NewFunc: Pointer): Integer;

type //¶¨ÒåÒ»¸öÈë¿Ú½á¹¹
PImage_Import_Entry = ^Image_Import_Entry;
Image_Import_Entry = record
Characteristics: DWORD;
TimeDateStamp: DWORD;
MajorVersion: Word;
MinorVersion: Word;
Name: DWORD;
LookupTable: DWORD;
end;

type //¶¨ÒåÒ»¸öÌø×ªµÄ½á¹¹
TImportCode = packed record
JumpInstruction: Word; //¶¨ÒåÌø×ªÖ¸Áîjmp
AddressOfPointerToFunction: ^Pointer; //¶¨ÒåÒªÌø×ªµ½µÄº¯Êý
end;
PImportCode = ^TImportCode;
implementation

function LocateFunctionAddress(Code: Pointer): Pointer;
var
func: PImportCode;
begin
Result := Code;
if Code = nil then exit;
try
func := code;
if (func.JumpInstruction = $25FF) then
begin
Result := func.AddressOfPointerToFunction^;
end;
except
Result := nil;
end;
end;

function RepointFunction(OldFunc, NewFunc: Pointer): Integer;
var
IsDone: TList;
function RepointAddrInModule(hModule: THandle; OldFunc, NewFunc: Pointer): Integer;
var
Dos: PImageDosHeader;
NT: PImageNTHeaders;
ImportDesc: PImage_Import_Entry;
RVA: DWORD;
Func: ^Pointer;
DLL: string;
f: Pointer;
written: DWORD;
begin
Result := 0;
Dos := Pointer(hModule);
if IsDone.IndexOf(Dos) >= 0 then exit;
IsDone.Add(Dos);

OldFunc := LocateFunctionAddress(OldFunc);

if IsBadReadPtr(Dos, SizeOf(TImageDosHeader)) then exit;
if Dos.e_magic <> IMAGE_DOS_SIGNATURE then exit;
NT := Pointer(Integer(Dos) + dos._lfanew);

RVA := NT^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
.VirtualAddress;

if RVA = 0 then exit;
ImportDesc := pointer(integer(Dos) + RVA);
while (ImportDesc^.Name <> 0) do
begin
DLL := PChar(Integer(Dos) + ImportDesc^.Name);
RepointAddrInModule(GetModuleHandle(PChar(DLL)), OldFunc, NewFunc);
Func := Pointer(Integer(DOS) + ImportDesc.LookupTable);
while Func^ <> nil do
begin
f := LocateFunctionAddress(Func^);
if f = OldFunc then
begin
WriteProcessMemory(GetCurrentProcess, Func, @NewFunc, 4, written);
if Written > 0 then Inc(Result);
end;
Inc(Func);
end;
Inc(ImportDesc);
end;
end;

begin
IsDone := TList.Create;
try
Result := RepointAddrInModule(GetModuleHandle(nil), OldFunc, NewFunc);
finally
IsDone.Free;
end;
end;

end.
zhuangbx220 2003-07-17
  • 打赏
  • 举报
回复
Up
shuixin13 2003-07-17
  • 打赏
  • 举报
回复
也来热闹一下!!
hansion3406 2003-07-16
  • 打赏
  • 举报
回复
偶再提提..
nzh517 2003-07-08
  • 打赏
  • 举报
回复
这个东西找个源码看看,,

看了一下以前的贴子,好象说这个拦截网络函数不好使,不知是不是真的,,,
terrace 2003-07-08
  • 打赏
  • 举报
回复
jmp.Address := DWORD(@SecondTest) - DWORD(@FirstTest) - 5;
//目的地址-原地址
//地址偏移-结构大小
是什么意思?没看明白,哪位给解释一下??????
yansea 2003-07-08
  • 打赏
  • 举报
回复
type
TCode5 = packed record
jcode: shortint;
Address: DWORD;
end;
.........
jmp.jcode := ShortInt($E9); //jmp 机器码
jmp.Address := DWORD(@SecondTest) - DWORD(@FirstTest) - 5;
//目的地址-原地址
//地址偏移-结构大小
用 WriteProcessMemory 写到目标函数的地址处。
ly_liuyang 2003-07-08
  • 打赏
  • 举报
回复
APIHook技术
hansion3406 2003-07-07
  • 打赏
  • 举报
回复
KAO..还是没有反应..怎么回事?
为什么是前5个字节??
它的结构是什么样子??
我很想知道啊..
zjy6631 2003-07-03
  • 打赏
  • 举报
回复
up
zhksoft 2003-07-03
  • 打赏
  • 举报
回复
up
hansion3406 2003-07-03
  • 打赏
  • 举报
回复
怎么这么久了都没有反应..
我准备学习呢??!!!!
hansion3406 2003-06-04
  • 打赏
  • 举报
回复
收了..建立上头条..
yansea 2003-06-04
  • 打赏
  • 举报
回复
amd没问题,Alpha的就不行了。
aipingren 2003-06-03
  • 打赏
  • 举报
回复
请问在AMD CPU下能用吗
myling 2003-06-03
  • 打赏
  • 举报
回复
这个问题我好像以前看过一个牛人写的文章,
说是仿照变速齿轮写了一个修改系统时钟的程序

好像就是说的这个问题

只有该程序截获的程序的始终才修改,其他的包括系统时钟都不受影响
很早了,好像是在程序员2001合订本上看的?记不清了,也好象是2003,忘了

呵呵,惭愧,没看懂
yansea 2003-06-03
  • 打赏
  • 举报
回复
恐怕不行。SENDTO就是在WSOCK32.dll中实现的,而jmp修改的是sendto的前5个字节,也就是说修改了WSOCK32.dll。那么任何调用此函数的程序得到的都是修改后的结果。也就是说,这是一种系统级的解决方案。有两个问题:一个是jmp的硬编码使得移植性不好,另一个是在你修改sendto的时候刚好有别的程序调用这个函数。
不过这种情况也很极端,jeffery的《windows核心编程》中提到了jmp的方法,也说了它的问题。但是他没给出解决这种问题的办法。
但是现在很多程序都是用jmp来hookapi的,而且运行的也很好。不知道用了什么办法,难道仅仅是线程同步?
加载更多回复(5)

1,184

社区成员

发帖
与我相关
我的任务
社区描述
Delphi Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧