关于全局API Hook的一个问题,请大家帮忙。
kook 2006-12-31 03:08:32 以下是我的代码,并不算很长,应该也是写得很清楚的了。代码后面有文字说明
以下是DLL的代码
library dll;
uses
SysUtils,
Windows,
Classes,
Dialogs,
APIHook in 'APIHook.pas';
var
Hook:HHOOK;
function GetMsgProc(nCode:Integer;wParam:wParam;lParam:lParam):LRESULT;stdcall;
begin
Result := 0;
end;
procedure SetHook;
begin
Hook := SetWindowsHookEx(WH_GETMESSAGE,@GetMsgProc,hInstance,0);
end;
procedure RemoveHook;
begin
UnHookWindowsHookEx(Hook);
end;
exports
SetHook, RemoveHook;
{$R *.res}
begin
APIHook_Up;
end.
以下是APIHook单元的代码
unit APIHook;
interface
uses
Windows, Messages, Classes, SysUtils, Dialogs;
type
PImage_Import_Entry = ^Image_Import_Entry;
Image_Import_Entry = record
Characteristics: DWORD;
TimeDateStamp: DWORD;
MajorVersion: Word;
MinorVersion: Word;
Name: DWORD;
LookupTable: DWORD;
end;
TImportCode = packed record
JumpInstruction: Word;
AddressOfPointerToFunction: ^Pointer;
end;
PImportCode = ^TImportCode;
//TSetFocus = function(hWnd: HWND): HWND; stdcall;
TDeleteFileW = function(lpFileName: PWideChar): BOOL; stdcall;
TDeleteFileA = function(lpFileName: PAnsiChar): BOOL; stdcall;
TDeleteFile = function(lpFileName: PChar): BOOL; stdcall;
function LocateFunctionAddress(Code: Pointer): Pointer;stdcall;
function RepointFunction(OldFunc, NewFunc: Pointer): Integer;stdcall;
procedure APIHook_Up;stdcall;
procedure APIHook_Off;stdcall;
var
OldDeleteFileW:TDeleteFileW;
OldDeleteFileA:TDeleteFileA;
OldDeleteFile:TDeleteFile;
FuncDeleteFileW: PImportCode;
FuncDeleteFileA: PImportCode;
FuncDeleteFile: PImportCode;
implementation
////////////////////////////////////////////////////////////////////////
function MyDeleteFileW(lpFileName: PWideChar): BOOL; stdcall;
begin
MessageBox(0,'qqq','qqq',mb_ok);
Result:= true;
end;
function MyDeleteFileA(lpFileName: PAnsiChar): BOOL; stdcall;
begin
MessageBox(0,'qqq','qqq',mb_ok);
Result:= true;
end;
function MyDeleteFile(lpFileName: PChar): BOOL; stdcall;
begin
MessageBox(0,'qqq','qqq',mb_ok);
Result:= true;
end;
////////////////////////////////////////////////////////////////////////
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;
Procedure PermuteFunction(OldFunc:Pointer; NewFunc:Pointer);
var
written: DWORD;
begin
WriteProcessMemory(GetCurrentProcess,OldFunc,@NewFunc,4,written);
end;
procedure APIHook_Up;
begin
if @OldDeleteFileW = nil then
@OldDeleteFileW := LocateFunctionAddress(@DeleteFileW);
if @OldDeleteFileA = nil then
@OldDeleteFileA := LocateFunctionAddress(@DeleteFileA);
if @OldDeleteFile = nil then
@OldDeleteFile := LocateFunctionAddress(@DeleteFile);
PermuteFunction(funcDeleteFileW.AddressOfPointerToFunction, @MyDeleteFileW);
PermuteFunction(funcDeleteFileA.AddressOfPointerToFunction, @MyDeleteFileA);
PermuteFunction(funcDeleteFile.AddressOfPointerToFunction, @MyDeleteFile);
end;
procedure APIHook_Off;
begin
If @OldDeleteFileW <> nil then
begin
PermuteFunction(funcDeleteFileW.AddressOfPointerToFunction, @OldDeleteFileW);
end;
If @OldDeleteFileA <> nil then
begin
PermuteFunction(funcDeleteFileA.AddressOfPointerToFunction, @OldDeleteFileA);
end;
If @OldDeleteFile <> nil then
begin
PermuteFunction(funcDeleteFile.AddressOfPointerToFunction, @OldDeleteFile);
end;
end;
initialization
FuncDeleteFile := @DeleteFile;
FuncDeleteFileA := @DeleteFileA;
FuncDeleteFileW := @DeleteFileW;
finalization
APIHook_Off;
end.
本来我用新函数替换旧函数的时候调用的是RepointFunction函数
不知道为什么总是提示内存读取错误的信息。后来我用PermuteFunction做转换,发现对全局进程不管用。
我是这么操作的:
首先把APIHook这个单元放到我自己的一个程序中,然后再我自己的程序中调用DeleteFile函数来删除一个文件,结果是成功的。但是这并不是全局钩子,现在我要做全局钩子的话,把上面的代码放入DLL中。启动钩子后,我直接在桌面上删除一个文件,居然一点反映都没有,这到底是怎么回事啊,请问各位大哥我的代码到底哪里出了问题。或者哪里还没有考虑到的东西。
如果有可能的话,给一个DeleteFile的全局钩子的详细代码的话更好,小弟不胜感激。