┌─────┐ ┌─────┐
│ 我的程序 │┅┅┅> │ ReadFile │
└─────┘ └─────┘
│
ˇ
┌─────┐ ┌──────┐ ┌─────┐
│ 控件A │┅┅┅>│ UTILITY.DLL│┅┅┅>│ ReadFile │
└─────┘ └──────┘ └─────┘
在“我的程序”中可以HOOK到“我的程序”中使用的ReadFile,我在
View-->Debug windows-->Event Log中查看“UTILITY.DLL”已经加载,但是“我的程序”
使用的“控件A”调用的“UTILITY.DLL”中的ReadFile却HOOK不了,为什么?
////====程序代码
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, OleCtrls, MapXLib_TLB;type
TReadFile = function(hFile: THandle; var Buffer; nNumberOfBytesToRead: DWORD; var lpNumberOfBytesRead: DWORD; lpOverlapped: POverlapped): BOOL; stdcall;
TReadFileEx = function(hFile: THandle; lpBuffer: Pointer; nNumberOfBytesToRead: DWORD; lpOverlapped: POverlapped; lpCompletionRoutine: TPROverlappedCompletionRoutine): BOOL; stdcall; PImage_Import_Entry = ^Image_Import_Entry; //定义一个入口结构
Image_Import_Entry = record
Characteristics: DWORD;
TimeDateStamp: DWORD;
MajorVersion: Word;
MinorVersion: Word;
Name: DWORD;
LookupTable: DWORD;
end; TSaveRedir = packed record
Addr: Pointer;
Bytes: array[0..4] of Byte;
end;
PSaveRedir = ^TSaveRedir; TImportCode = packed record //定义一个跳转的结构
JumpInstruction: Word; //定义跳转指令jmp,是$25FF,JUMP指令
AddressOfPointerToFunction: ^Pointer; //定义要跳转到的函数,//真正开始的地址
end;
PImportCode = ^TImportCode; TForm1 = class(TForm)
Map1: TMap;
Button1: TButton;
Button2: TButton;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1 : TForm1;implementation
var
OldReadFile : TReadFile;
OldReadFileEx : TReadFileEx; {$R *.dfm}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 //在这里设置断点,发现只有“我的程序”的才HOOK掉了
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); //这可以HOOK到“我的程序的代码”
Result := RepointAddrInModule(GetModuleHandle('UTILITY.DLL'), OldFunc, NewFunc);
finally
IsDone.Free;
end;
end;procedure MyDebug(Str: PChar);
var DC : HDC;
begin
Sleep(1000);
DC := GetDC(0);
try
Textout(Dc, 50, 50, PChar(Str + ' '), Length(PChar(Str + ' ')));
finally
ReleaseDC(0, DC);
end;
end;function MyReadFile(hFile: THandle; var Buffer; nNumberOfBytesToRead: DWORD; var lpNumberOfBytesRead: DWORD; lpOverlapped: POverlapped): BOOL; stdcall;
begin
MyDebug(PChar('OpenFile' + ' ' + IntToStr(hFile) + ' '));
Result := OldReadFile(hFile, Buffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
end;function MyReadFileEx(hFile: THandle; lpBuffer: Pointer; nNumberOfBytesToRead: DWORD; lpOverlapped: POverlapped; lpCompletionRoutine: TPROverlappedCompletionRoutine): BOOL; stdcall;
begin
MyDebug(PChar('OpenFileEx' + ' ' + IntToStr(hFile) + ' '));
Result := OldReadFileEx(hFile, lpBuffer, nNumberOfBytesToRead, lpOverlapped, lpCompletionRoutine);
end;procedure API_Hookup;
begin
if @OldReadFile = nil then
@OldReadFile := LocateFunctionAddress(@ReadFile);
RepointFunction(@OldReadFile, @MyReadFile); if @OldReadFileEx = nil then
@OldReadFileEx := LocateFunctionAddress(@ReadFileEx);
RepointFunction(@OldReadFileEx, @MyReadFileEx);
end;procedure API_HookDown;
begin
if @OldReadFile <> nil then
begin
RepointFunction(@MyReadFile, @OldReadFile);
end; if @OldReadFileEx <> nil then
begin
RepointFunction(@MyReadFileEx, @OldReadFileEx);
end;
end;procedure TForm1.Button1Click(Sender: TObject);
begin
API_Hookup;
end;procedure TForm1.Button2Click(Sender: TObject);
begin
API_HookDown;
end;end.
│ 我的程序 │┅┅┅> │ ReadFile │
└─────┘ └─────┘
│
ˇ
┌─────┐ ┌──────┐ ┌─────┐
│ 控件A │┅┅┅>│ UTILITY.DLL│┅┅┅>│ ReadFile │
└─────┘ └──────┘ └─────┘
在“我的程序”中可以HOOK到“我的程序”中使用的ReadFile,我在
View-->Debug windows-->Event Log中查看“UTILITY.DLL”已经加载,但是“我的程序”
使用的“控件A”调用的“UTILITY.DLL”中的ReadFile却HOOK不了,为什么?
////====程序代码
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, OleCtrls, MapXLib_TLB;type
TReadFile = function(hFile: THandle; var Buffer; nNumberOfBytesToRead: DWORD; var lpNumberOfBytesRead: DWORD; lpOverlapped: POverlapped): BOOL; stdcall;
TReadFileEx = function(hFile: THandle; lpBuffer: Pointer; nNumberOfBytesToRead: DWORD; lpOverlapped: POverlapped; lpCompletionRoutine: TPROverlappedCompletionRoutine): BOOL; stdcall; PImage_Import_Entry = ^Image_Import_Entry; //定义一个入口结构
Image_Import_Entry = record
Characteristics: DWORD;
TimeDateStamp: DWORD;
MajorVersion: Word;
MinorVersion: Word;
Name: DWORD;
LookupTable: DWORD;
end; TSaveRedir = packed record
Addr: Pointer;
Bytes: array[0..4] of Byte;
end;
PSaveRedir = ^TSaveRedir; TImportCode = packed record //定义一个跳转的结构
JumpInstruction: Word; //定义跳转指令jmp,是$25FF,JUMP指令
AddressOfPointerToFunction: ^Pointer; //定义要跳转到的函数,//真正开始的地址
end;
PImportCode = ^TImportCode; TForm1 = class(TForm)
Map1: TMap;
Button1: TButton;
Button2: TButton;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1 : TForm1;implementation
var
OldReadFile : TReadFile;
OldReadFileEx : TReadFileEx; {$R *.dfm}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 //在这里设置断点,发现只有“我的程序”的才HOOK掉了
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); //这可以HOOK到“我的程序的代码”
Result := RepointAddrInModule(GetModuleHandle('UTILITY.DLL'), OldFunc, NewFunc);
finally
IsDone.Free;
end;
end;procedure MyDebug(Str: PChar);
var DC : HDC;
begin
Sleep(1000);
DC := GetDC(0);
try
Textout(Dc, 50, 50, PChar(Str + ' '), Length(PChar(Str + ' ')));
finally
ReleaseDC(0, DC);
end;
end;function MyReadFile(hFile: THandle; var Buffer; nNumberOfBytesToRead: DWORD; var lpNumberOfBytesRead: DWORD; lpOverlapped: POverlapped): BOOL; stdcall;
begin
MyDebug(PChar('OpenFile' + ' ' + IntToStr(hFile) + ' '));
Result := OldReadFile(hFile, Buffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
end;function MyReadFileEx(hFile: THandle; lpBuffer: Pointer; nNumberOfBytesToRead: DWORD; lpOverlapped: POverlapped; lpCompletionRoutine: TPROverlappedCompletionRoutine): BOOL; stdcall;
begin
MyDebug(PChar('OpenFileEx' + ' ' + IntToStr(hFile) + ' '));
Result := OldReadFileEx(hFile, lpBuffer, nNumberOfBytesToRead, lpOverlapped, lpCompletionRoutine);
end;procedure API_Hookup;
begin
if @OldReadFile = nil then
@OldReadFile := LocateFunctionAddress(@ReadFile);
RepointFunction(@OldReadFile, @MyReadFile); if @OldReadFileEx = nil then
@OldReadFileEx := LocateFunctionAddress(@ReadFileEx);
RepointFunction(@OldReadFileEx, @MyReadFileEx);
end;procedure API_HookDown;
begin
if @OldReadFile <> nil then
begin
RepointFunction(@MyReadFile, @OldReadFile);
end; if @OldReadFileEx <> nil then
begin
RepointFunction(@MyReadFileEx, @OldReadFileEx);
end;
end;procedure TForm1.Button1Click(Sender: TObject);
begin
API_Hookup;
end;procedure TForm1.Button2Click(Sender: TObject);
begin
API_HookDown;
end;end.
解决方案 »
免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货