书上说,在WIN98下以JMP方法(改前5个字节)来拦截某些API函数!但会影响到其他进程
。这样有时会出错!我想问一下,是不是所有的被拦截函数都会影响到其他的进程!我的理解是拦截系统的API函数才会影响到别的进程!比如,屏幕取词的TEXTOUT函数等,因为这样的系统函数会加载到0x80000000以上的地址空间!所以每个进程都是可见的!而如果我要拦截的是某些不是系统DLL函数如:WSOCK32。DLL里的SENDTO函数,是不是该函数不会影响到其他的进程!我试着拦截SENDTO函数了!也没有发现WIN98下出错啊!
。这样有时会出错!我想问一下,是不是所有的被拦截函数都会影响到其他的进程!我的理解是拦截系统的API函数才会影响到别的进程!比如,屏幕取词的TEXTOUT函数等,因为这样的系统函数会加载到0x80000000以上的地址空间!所以每个进程都是可见的!而如果我要拦截的是某些不是系统DLL函数如:WSOCK32。DLL里的SENDTO函数,是不是该函数不会影响到其他的进程!我试着拦截SENDTO函数了!也没有发现WIN98下出错啊!
函数都会跳入你设定的地址。这是一个比较全面的解决方法,但问题是在你修改的时候
不能保证别的程序不会调用此函数,如果线程切换,而你并没有结束修改动作,恰好有
程序调用了这个函数,结果当然可想而知了。
不过这种情况也很极端,jeffery的《windows核心编程》中提到了jmp的方法,也说了它的问题。但是他没给出解决这种问题的办法。
但是现在很多程序都是用jmp来hookapi的,而且运行的也很好。不知道用了什么办法,难道仅仅是线程同步?
为什么是前5个字节??
它的结构是什么样子??
我很想知道啊..
TCode5 = packed record
jcode: shortint;
Address: DWORD;
end;
.........
jmp.jcode := ShortInt($E9); //jmp 机器码
jmp.Address := DWORD(@SecondTest) - DWORD(@FirstTest) - 5;
//目的地址-原地址
//地址偏移-结构大小
用 WriteProcessMemory 写到目标函数的地址处。
//目的地址-原地址
//地址偏移-结构大小
是什么意思?没看明白,哪位给解释一下??????
unit HookAPI;interfaceuses
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;
implementationfunction 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.
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.
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.