当前位置:主页>仓库管理软件> 列表

请问如何Hook一个Delphi的内置函数?比如Trim? 找p3项目管理软件下载

记账软件版1楼: 不是hook windows标准函数
而用自定义函数来替换delphi内置的函数,我想的不是直接写个同名函数来覆盖方法,而是二进制级别的hook.

2楼: 无人回答? 如p3项目管理软件下载

3楼: 麻烦就麻烦在找函数的入口上

4楼: 给你一个函数:
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;

5楼: 高,对了,如果我想把原来的函数的代码换掉怎么弄啊
不是换地址的那种

6楼: 直接Copy新函数的code到原函数的地址,不过要保证新函数的代码长度<=原函数的代码长度,不然覆盖了后面跟着的函数长度,呵呵,调用后面的函数可是要出错的

记账软件版7楼: 高,对了,如果我想把原来的函数的代码换掉怎么弄啊
不是换地址的那种
>>如果是代码级别的替换的话,直接在你的单元中写一个同名的函数就可以了

8楼: 真是高人,你所说的限制就是新的函数代码不能多于原来的了?

9楼: 再帮忙看看另一个问题:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=3340388

10楼: 帮顶!

http://www.source520.com

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

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



"编程.站长"论坛搜索引擎-----为中国站长注入动力!

11楼: 完成,另外可以使用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[I] of
$53..$56:
; // push reg
$8B, $3B: // mov/cmp
begin
Inc(I);
ModRM := GetModRM(Bytes[I]);
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[I] := $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 "PUSH xxx" }
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;