请问如何Hook一个Delphi的内置函数?比如Trim?(100分)

  • 主题发起人 主题发起人 dejoy
  • 开始时间 开始时间
D

dejoy

Unregistered / Unconfirmed
GUEST, unregistred user!
不是hook windows标准函数
而用自定义函数来替换delphi内置的函数,我想的不是直接写个同名函数来覆盖方法,而是二进制级别的hook.
 
无人回答?
 
麻烦就麻烦在找函数的入口上
 
给你一个函数:
var
SavedCode: array[0..4] of Byte;
Hooked: Boolean;

procedure Hook(OldProc, NewProc: Pointer
Hooking: Boolean = True);
var
dwFlag: DWORD;
NewCode: array[0..4] of Byte;
begin
VirtualProtect(OldProc, 5, PAGE_EXECUTE_READWRITE, dwFlag);
if Hooking then
begin
if Hooked then Exit;
Move(OldProc^, SavedCode, 5);
NewCode[0] := $E9;
PDWORD(@NewCode[1])^ := DWORD(NewProc) - DWORD(OldProc) - 5;
Move(NewCode, OldProc^, 5);
end
else
begin
if not Hooked then Exit;
Move(SavedCode, OldProc^, 5);
end;
VirtualProtect(OldProc, 5, dwFlag, dwFlag);
end;

测试:
function NewTrim(const S: string): string;
begin
ShowMessage(S);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Hook(@Trim, @NewTrim, True);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
Hook(@Trim, @NewTrim, False);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Trim(' haha ');
end;
 
高,对了,如果我想把原来的函数的代码换掉怎么弄啊
不是换地址的那种
 
直接Copy新函数的code到原函数的地址,不过要保证新函数的代码长度<=原函数的代码长度,不然覆盖了后面跟着的函数长度,呵呵,调用后面的函数可是要出错的
 
高,对了,如果我想把原来的函数的代码换掉怎么弄啊
不是换地址的那种
>>如果是代码级别的替换的话,直接在你的单元中写一个同名的函数就可以了
 
真是高人,你所说的限制就是新的函数代码不能多于原来的了?
 
再帮忙看看另一个问题:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=3340388
 
帮顶!

http://www.source520.com

站长开发推广同盟 站长朋友的终极驿站
同时拥有海量源码电子经典书籍下载

http://www.source520.com/search/search.asp

&quot;编程.站长&quot;论坛搜索引擎-----为中国站长注入动力!
 
完成,另外可以使用madCollection来实现.
贡献代码:
function YcInstallProcHook(ProcAddress, HookProc, OrgCallProc: Pointer): Boolean;
function YcUnInstallProcHook(OrgCallProc: Pointer): Boolean;

//--------------------------------------------------------------------------------------------------

function ReadProtectedMemory(Address: Pointer
var Buffer
Count: Cardinal): Boolean;
var
N: Cardinal;
begin
Result := ReadProcessMemory(GetCurrentProcess, Address, @Buffer, Count, N);
Result := Result and (N = Count);
end;

function WriteProtectedMemory(Address: Pointer
const Buffer
Count: Cardinal): Boolean;
var
N: Cardinal;
begin
Result := WriteProcessMemory(GetCurrentProcess, Address, @Buffer, Count, N);
Result := Result and (N = Count);
end;

type
TJumpCode = packed record
Jmp: Byte
// jmp Offset
Offset: Integer;
end;

TOrgCallCode = packed record
Code: array[0..SizeOf(TJumpCode) + 4] of Byte;
Jmp: Byte
// jmp Offset
Offset: Integer;
Address: Pointer;
end;

function YcGetRelocAddress(ProcAddress: Pointer): Pointer;
type
TRelocationRec = packed record
Jump: Word;
Address: PPointer;
end;
var
Relocation: TRelocationRec;
Data: Byte;
begin
Result := ProcAddress;
// the relocation table might be protected
if ReadProtectedMemory(ProcAddress, Data, SizeOf(Data)) then
if Data = $FF then // ProcAddress is in a DLL or package
if ReadProtectedMemory(ProcAddress, Relocation, SizeOf(Relocation)) then
Result := Relocation.Address^;
end;

function AllocateHWnd(Method: TWndMethod): HWND;
begin
Result := Forms.AllocateHWnd(Method);
end;

procedure DeallocateHWnd(Wnd: HWND);
begin
Forms.DeallocateHWnd(Wnd);
end;

type
TModRM = record
Mode: Byte;
RegOp: Byte;
RM: Byte;
end;

function GetModRM(B: Byte): TModRM;
begin
Result.Mode := B shr 6;
Result.RegOp := (B shr 3) and $07;
Result.RM := B and $07;
end;

function GetDisassembledByteCount(const Bytes: array of Byte): Integer;
var
I, LastByteCount: Integer;
ModRM: TModRM;
begin
Result := 0;
LastByteCount := 0;
I := 0;
while I < Length(Bytes) do
begin
LastByteCount := Result;
case Bytes of
$53..$56:

// push reg
$8B, $3B: // mov/cmp
begin
Inc(I);
ModRM := GetModRM(Bytes);
case ModRM.Mode of
$00:
if ModRM.RM = $07 then
Inc(I, 2)
// mov reg, disp16
$01:
Inc(I)
// mov reg, [reg]+disp8
$02:
Inc(I, 2)
// mov reg, [reg]+disp16
end;
end;
$E8:
Inc(I, 4)
// call rel32
$5B..$5E:

// pop reg
$C3:

// ret
$E9:
Inc(I, 4)
// jmp rel32
$83: // add
Inc(I, 2);
$89:
Inc(I, 2);
end;
Inc(I);
Result := I;
end;
if I > Length(Bytes) then
Result := LastByteCount;
end;

function YcInstallProcHook(ProcAddress, HookProc, OrgCallProc: Pointer): Boolean;
var
Code: TJumpCode;
OrgCallCode: TOrgCallCode;
I, Count: Integer;
begin
ProcAddress := YcGetRelocAddress(ProcAddress);
Result := False;


if Assigned(ProcAddress) and Assigned(HookProc) then
begin
{$IFDEF madCodeHook}
Result := HookCode(ProcAddress, HookProc, OrgCallProc);
Exit;
{$ELSE}

if OrgCallProc <> nil then
begin
if ReadProtectedMemory(ProcAddress, OrgCallCode, SizeOf(OrgCallCode.Code)) then
begin
Count := GetDisassembledByteCount(OrgCallCode.Code);
for I := Count to SizeOf(OrgCallCode.Code) do
OrgCallCode.Code := $90
// NOP
OrgCallCode.Jmp := $E9;
OrgCallCode.Offset := (Integer(ProcAddress) {+ SizeOf(Code)} + Count) -
Integer(OrgCallProc) -
(SizeOf(OrgCallCode) - SizeOf(OrgCallCode.Address));
OrgCallCode.Address := ProcAddress;

WriteProtectedMemory(OrgCallProc, OrgCallCode, SizeOf(OrgCallCode));
FlushInstructionCache(GetCurrentProcess, OrgCallProc, SizeOf(OrgCallCode));
end;
end;

Code.Jmp := $E9;
Code.Offset := Integer(HookProc) - (Integer(ProcAddress)) - SizeOf(Code);

{ The strange thing is that something overwrites the $e9 with a &quot;PUSH xxx&quot
}
if WriteProtectedMemory(Pointer(Cardinal(ProcAddress)), Code, SizeOf(Code)) then
begin
FlushInstructionCache(GetCurrentProcess, ProcAddress, SizeOf(Code));
Result := True;
end;
{$ENDIF}
end;
end;

function YcUnInstallProcHook(OrgCallProc: Pointer): Boolean;
var
OrgCallCode: TOrgCallCode;
ProcAddress: Pointer;
begin
Result := False;
if Assigned(OrgCallProc) then
{$IFDEF madCodeHook}
Result := UnhookCode(OrgCallProc);
Exit;
{$ELSE}

if OrgCallProc <> nil then
if ReadProtectedMemory(OrgCallProc, OrgCallCode, SizeOf(OrgCallCode)) then
begin
ProcAddress := OrgCallCode.Address;

Result := WriteProtectedMemory(ProcAddress, OrgCallCode, SizeOf(TJumpCode));
FlushInstructionCache(GetCurrentProcess, ProcAddress, SizeOf(OrgCallCode));
end;
{$ENDIF}
end;
 
后退
顶部