本文共 17192 字,大约阅读时间需要 57 分钟。
周未一个朋友要求用Delphi做了一个东西,用到了API HOOK,于是写了个简单的
SetOnBefore把函数安装到API之前,可在真正的api执行之前先执行我们的函数 SetOnAfter把函数安装到API之后,可在真正的api执行之后再执行我们的函数 代码写得比较急,还有很多地方可以优化,功能上也有些地方可以于改进一下,如: 替换api,能改变api的返回值等。。。以后有时间玩的时候再升级,没时间就算了。。。 如果你有兴趣转成VC的代码请共享一份给我:) 具体代码如下,其中GetOpCodeSize可参考我早期的“”
{Name: API Hook Lib Version: 0.1 Author: coded by xIkUg/RCT/CCG HomePage: http://www.wintoolspro.com, http://debugman.wintoolspro.com CreateDate: 2006-12-03}unit uHookLib;interfaceuses Windows, SysUtils;type PBytes = ^Byte; TMaskTable = array [0..517] of LongWord;var MaskTable: TMaskTable = ( $00004000, $00004000, $00004000, $00004000, $00008000, $00008000, $00000000, $00000000, $00004000, $00004000, $00004000, $00004000, $00008000, $00008000, $00000000, $00000000, $00004000, $00004000, $00004000, $00004000, $00008000, $00008000, $00000000, $00000000, $00004000, $00004000, $00004000, $00004000, $00008000, $00008000, $00000000, $00000000, $00004000, $00004000, $00004000, $00004000, $00008000, $00008000, $00000008, $00000000, $00004000, $00004000, $00004000, $00004000, $00008000, $00008000, $00000008, $00000000, $00004000, $00004000, $00004000, $00004000, $00008000, $00008000, $00000008, $00000000, $00004000, $00004000, $00004000, $00004000, $00008000, $00008000, $00000008, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00004000, $00004000, $00000008, $00000008, $00001008, $00000018, $00002000, $00006000, $00000100, $00004100, $00000000, $00000000, $00000000, $00000000, $00000100, $00000100, $00000100, $00000100, $00000100, $00000100, $00000100, $00000100, $00000100, $00000100, $00000100, $00000100, $00000100, $00000100, $00000100, $00000100, $00004100, $00006000, $00004100, $00004100, $00004000, $00004000, $00004000, $00004000, $00004000, $00004000, $00004000, $00004000, $00004000, $00004000, $00004000, $00004000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00002002, $00000000, $00000000, $00000000, $00000000, $00000000, $00000020, $00000020, $00000020, $00000020, $00000000, $00000000, $00000000, $00000000, $00000100, $00002000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000100, $00000100, $00000100, $00000100, $00000100, $00000100, $00000100, $00000100, $00002000, $00002000, $00002000, $00002000, $00002000, $00002000, $00002000, $00002000, $00004100, $00004100, $00000200, $00000000, $00004000, $00004000, $00004100, $00006000, $00000300, $00000000, $00000200, $00000000, $00000000, $00000000, $00000000, $00000000, $00004000, $00004000, $00004000, $00004000, $00000100, $00000100, $00000000, $00000000, $00004000, $00004000, $00004000, $00004000, $00004000, $00004000, $00004000, $00004000, $00000100, $00000100, $00000100, $00000100, $00000100, $00000100, $00000100, $00000100, $00002000, $00002000, $00002002, $00000100, $00000000, $00000000, $00000000, $00000000, $00000008, $00000000, $00000008, $00000008, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00004000, $00004000, $00004000, $00004000, $00004000, $00004000, $FFFFFFFF, $FFFFFFFF, $00000000, $FFFFFFFF, $00000000, $00000000, $00000000, $00000000, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $00002000, $00002000, $00002000, $00002000, $00002000, $00002000, $00002000, $00002000, $00002000, $00002000, $00002000, $00002000, $00002000, $00002000, $00002000, $00002000, $00004000, $00004000, $00004000, $00004000, $00004000, $00004000, $00004000, $00004000, $00004000, $00004000, $00004000, $00004000, $00004000, $00004000, $00004000, $00004000, $00000000, $00000000, $00000000, $00004000, $00004100, $00004000, $FFFFFFFF, $FFFFFFFF, $00000000, $00000000, $00000000, $00004000, $00004100, $00004000, $FFFFFFFF, $00004000, $00004000, $00004000, $00004000, $00004000, $00004000, $00004000, $00004000, $00004000, $FFFFFFFF, $FFFFFFFF, $00004100, $00004000, $00004000, $00004000, $00004000, $00004000, $00004000, $00004000, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $00000000, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF );function SetOnBefore(const DllName: string; const ApiName: string; HookProc: Pointer): Boolean;function SetOnAfter(const DllName: string; const ApiName: string; HookProc: Pointer): Boolean; function GetOpCodeSize(Start: Pointer; Tlb: TMaskTable): integer; stdcall;implementationvar JMPGate: array [0..4] of byte = ( $E9, $00, $00, $00, $00 // JMP XXXXXXXX ); // HookProc offset is 36 // HookApi offset is 82 BeforeStub: array [0..93] of byte = ( $58, // 0 pop eax $EB, $08, // 1 jmp short 0040100B $00, $00, $00, $00, // 3 dd 00000000 $00, $00, $00, $00, // 7 dd 00000000 $E8, $00, $00, $00, $00, // 11 call 00401010 $59, // 16 pop ecx $81, $E9, $10, $10, $40, $00, // 17 sub ecx, 00401010 $89, $A1, $03, $10, $40, $00, // 23 mov [ecx+401003], esp $89, $81, $07, $10, $40, $00, // 29 mov [ecx+401007], eax $E8, $36, $01, $00, $00, // 35 call HookProc $8B, $44, $24, $FC, // 40 mov eax, [esp - 4] $E8, $00, $00, $00, $00, // 44 call 0040102D $59, // 49 pop ecx $89, $44, $24, $FC, // 50 mov [esp - 4], eax $81, $E9, $31, $10, $40, $00, // 54 sub ecx, 0040102D $8B, $A1, $03, $10, $40, $00, // 60 mov esp, [ecx+401003] $8B, $81, $07, $10, $40, $00, // 66 mov eax, [ecx+401007] $50, // 72 push eax $90, $90, $90, $90, // 73 $90, $90, $90, $90, $90, $90, $90, $90, $90, $90, $90, $90, $E9, $18, $01, $00, $00 // 89 jmp HookedApi ); AfterStub: array [0..129] of Byte = ( $58, // 00 pop eax $EB, $0C, // 01 jmp short 0040100F $00, $00, $00, $00, // 03 dd 00000000 $00, $00, $00, $00, // 07 add [eax], al $00, $00, $00, $00, // 0B add [eax], al $E8, $00, $00, $00, $00, // 0F call 00401014 $59, // 14 pop ecx $81, $E9, $14, $10, $40, $00, // 15 sub ecx, 00401014 $89, $A1, $03, $10, $40, $00, // 1B mov [ecx+401003], esp $89, $81, $07, $10, $40, $00, // 21 mov [ecx+401007], eax $8D, $89, $43, $10, $40, $00, // 27 lea ecx, [ecx+401043] $51, // 2D push ecx $90, // 2E nop $90, // 2F nop $90, // 30 nop $90, // 31 nop $90, // 32 nop $90, // 33 nop $90, // 34 nop $90, // 35 nop $90, // 36 nop $90, // 37 nop $90, // 38 nop $90, // 39 nop $90, // 3A nop $90, // 3B nop $90, // 3C nop $90, // 3D nop $E9, $57, $01, $00, $00, // 3E jmp 0040119A $8B, $5C, $24, $FC, // 43 mov ebx, [esp-4] $E8, $00, $00, $00, $00, // 47 call 0040104C $59, // 4C pop ecx $89, $5C, $24, $FC, // 4D mov [esp-4], ebx $81, $E9, $4C, $10, $40, $00, // 51 sub ecx, 0040104C $89, $81, $0B, $10, $40, $00, // 57 mov [ecx+40100B], eax $8B, $A1, $03, $10, $40, $00, // 5D mov esp, [ecx+401003] $E8, $32, $01, $00, $00, // 63 call 0040119A $E8, $00, $00, $00, $00, // 68 call 0040106D $59, // 6D pop ecx $81, $E9, $6D, $10, $40, $00, // 6E sub ecx, 0040106D $8B, $81, $07, $10, $40, $00, // 74 mov eax, [ecx+401007] $50, // 7A push eax $8B, $81, $0B, $10, $40, $00, // 7B mov eax, [ecx+40100B] $C3 // 81 retn );function GetOpCodeSize(Start: Pointer; Tlb: TMaskTable): integer;var pOPCode: PBytes; t, c: LongWord; dh, dl, al: byte;begin result := -1; t := 0; pOPCode := Start; repeat t := t and $F7; c := pOPCode^; pOpCode := Pointer((DWORD(pOpCode) + 1)); t := t or Tlb[c]; until ((t and $000000FF) and 8) = 0; if (c = $0F6) or (c = $0F7) then begin t := t or $00004000; if (pOpCode^ and $38) = 0 then t := t or $00008000; end else if (c = $0CD) then begin t := t or $00000100; if pOpCode^ = $20 then t := t or $00000400; end else if (c = $0F) then begin al := pOpCode^; pOpCode := Pointer((DWORD(pOpCode) + 1)); t := t or Tlb[al + $100]; if t = $FFFFFFFF then Exit; end; if (((t and $0000FF00) shr 8) and $80) <> 0 then begin dh := (t and $0000FF00) shr 8; dh := dh xor $20; if (c and 1) = 0 then dh := dh xor $21; t := t and $FFFF00FF; t := t or (dh shl 8); end; if (((t and $0000FF00) shr 8) and $40) <> 0 then begin al := pOpCode^; pOpCode := Pointer((DWORD(pOpCode) + 1)); c := al; c := c or (al shl 8); c := c and $C007; if (c and $0000FF00) <> $C000 then begin if ((t and $000000FF) and $10) = 0 then begin if (c and $000000FF) = 4 then begin al := pOpCode^; pOpCode := Pointer((DWORD(pOpCode) + 1)); al := al and 7; c := c and $0000FF00; c := c or al; end; if (c and $0000FF00) <> $4000 then begin if (c and $0000FF00) = $8000 then begin t := t or 4; end else if c = 5 then t := t or 4; end else begin t := t or 1; end; end else begin if (c <> 6) then begin if (c and $0000FF00) = $4000 then t := t or 1 else if (c and $0000FF00) = $8000 then t := t or 2; end else t := t or 2; end; end; end; if (((t and $000000FF)) and $20) <> 0 then begin dl := (t and $000000FF); dl := dl xor 2; t := t and $FFFFFF00; t := t or dl; if (dl and $10) = 0 then begin dl := dl xor 6; t := t and $FFFFFF00; t := t or dl; end; end; if (((t and $0000FF00) shr 8) and $20) <> 0 then begin dh := (t and $0000FF00) shr 8; dh := dh xor 2; t := t and $FFFF00FF; t := t or (dh shl 8); if (dh and $10) = 0 then begin dh := dh xor 6; t := t and $FFFFFF00; t := t or dh; end; end; result := DWORD(pOPCode) - DWORD(Start); t := t and $707; result := result + (t and $000000FF); //1条指令不可能大过255个字节 result := result + ((t and $0000FF00) shr 8);end;function HookCode(const DllName: string; const ApiName: string; HookProc: Pointer): Boolean;beginend;function SetOnBefore(const DllName: string; const ApiName: string; HookProc: Pointer): Boolean;var ApiEntry: Pointer; DllHandle: THandle; ReplaceCodeSize: Integer; OpCode: array [0..15] of byte; StubPtr: Pointer; Addr: LongWord; RetSize: LongWord; begin Result := False; DllHandle := GetModuleHandle(PChar(DllName)); if DllHandle = 0 then begin DllHandle := LoadLibrary(PChar(DllName)); if DllHandle = 0 then Exit; end; ApiEntry := GetProcAddress(DllHandle, PChar(ApiName)); if ApiEntry = nil then Exit; ReplaceCodeSize := GetOpCodeSize(ApiEntry, MaskTable); while ReplaceCodeSize < 5 do begin ReplaceCodeSize := ReplaceCodeSize + GetOpCodeSize(Pointer(LongWord(ApiEntry) + ReplaceCodeSize), MaskTable); end; if ReplaceCodeSize > 16 then Exit; if VirtualProtect(ApiEntry, ReplaceCodeSize, PAGE_READWRITE, nil) then Exit; CopyMemory(@OpCode, ApiEntry, ReplaceCodeSize); StubPtr := VirtualAlloc(nil, SizeOf(BeforeStub), MEM_COMMIT, PAGE_EXECUTE_READWRITE); if StubPtr = nil then Exit; CopyMemory(StubPtr, @BeforeStub, SizeOf(BeforeStub)); // 求HookProc的地址 Addr := LongWord(HookProc) - LongWord(StubPtr) - 35 - 5; // 写入HookProc的地址 PDWORD(LongWord(StubPtr) + 36)^ := Addr; // 求HookedApi的地址 Addr := LongWord(ApiEntry) + ReplaceCodeSize - LongWord(StubPtr) - 89 - 5; // 写入HookedApi的地址 PDWORD(LongWord(StubPtr) + 90)^ := Addr; // 写入被Hook掉的OpCode CopyMemory(Pointer(LongWord(StubPtr) + 73), @OpCode, ReplaceCodeSize); // 改写Api入口地址 Addr := LongWord(StubPtr) - LongWord(ApiEntry) - 5; PDWORD(LongWord(@JMPGate) + 1)^ := Addr; WriteProcessMemory(GetCurrentProcess, ApiEntry, @JMPGate, SizeOf(JMPGate), RetSize);// CopyMemory(ApiEntry, @JMPGate, SizeOf(JMPGate)); Result := True;end;function SetOnAfter(const DllName: string; const ApiName: string; HookProc: Pointer): Boolean;var ApiEntry: Pointer; DllHandle: THandle; ReplaceCodeSize: Integer; OpCode: array [0..15] of byte; StubPtr: Pointer; Addr: LongWord; RetSize: LongWord; begin Result := False; DllHandle := GetModuleHandle(PChar(DllName)); if DllHandle = 0 then begin DllHandle := LoadLibrary(PChar(DllName)); if DllHandle = 0 then Exit; end; ApiEntry := GetProcAddress(DllHandle, PChar(ApiName)); if ApiEntry = nil then Exit; ReplaceCodeSize := GetOpCodeSize(ApiEntry, MaskTable); while ReplaceCodeSize < 5 do begin ReplaceCodeSize := ReplaceCodeSize + GetOpCodeSize(Pointer(LongWord(ApiEntry) + ReplaceCodeSize), MaskTable); end; if ReplaceCodeSize > 16 then Exit; if VirtualProtect(ApiEntry, ReplaceCodeSize, PAGE_READWRITE, nil) then Exit; CopyMemory(@OpCode, ApiEntry, ReplaceCodeSize); StubPtr := VirtualAlloc(nil, SizeOf(AfterStub), MEM_COMMIT, PAGE_EXECUTE_READWRITE); if StubPtr = nil then Exit; CopyMemory(StubPtr, @AfterStub, SizeOf(AfterStub)); // 求HookProc的地址 Addr := LongWord(HookProc) - LongWord(StubPtr) - $63 - 5; // 写入HookProc的地址 PDWORD(LongWord(StubPtr) + $64)^ := Addr; // 求HookedApi的地址 Addr := LongWord(ApiEntry) + ReplaceCodeSize - LongWord(StubPtr) - $3E - 5; // 写入HookedApi的地址 PDWORD(LongWord(StubPtr) + $3F)^ := Addr; // 写入被Hook掉的OpCode CopyMemory(Pointer(LongWord(StubPtr) + $2E), @OpCode, ReplaceCodeSize); // 改写Api入口地址 Addr := LongWord(StubPtr) - LongWord(ApiEntry) - 5; PDWORD(LongWord(@JMPGate) + 1)^ := Addr; WriteProcessMemory(GetCurrentProcess, ApiEntry, @JMPGate, SizeOf(JMPGate), RetSize);// CopyMemory(ApiEntry, @JMPGate, SizeOf(JMPGate)); Result := True;end;end. |
转载地址:http://gesti.baihongyu.com/