unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class (TForm) Button1: TButton; Memo1: TMemo; Button2: TButton; Button3: TButton; procedure Button1Click (Sender: TObject); procedure Button2Click (Sender: TObject); procedure Button3Click (Sender: TObject); procedure FormDestroy (Sender: TObject); procedure FormCreate (Sender: TObject); private {Private declarations} procedure ShowMsg (s: string) Public {public declarations}}} END; VAR FORM1: TFORM1; Implementation {$ r * .dfm} Uses mlde32Unit; const despath = 'c: / program files / borland / delphi6 / projects / adv apihook / test / vt.exe'; Func2Hook = 'FreeLibrary'; var // must be a globle variable PtrReal: pointer; cbStolen: Cardinal; NtDllBase, NtDllLength: integer; p: pointer; h: dword; procedure TForm1.ShowMsg (s: string); begin Memo1.Lines .Add (s); end; procedure tform1.button1click (sender: TOBJECT); Label Fakecode, RtNCode; var // si: startupinfo; // pi: process_infor Mation; ORIGINALBYTES: ARRAY [0..4] of char; hookjmp: pchar; RTN: cardinal; Bytes: array [0..4] of char; tmp: cardinal; PEB, LDR, FLINK: POINTER; BS: DWORD; Begin Ptrreal: = NIL; NTDLLLENGTH: = 0; NTDLLBASE: = getModuleHandle ('NTDLL.DLL'); ASM MOV Eax, FS: [$ 30] MOV PEB, End; LDR: = Pointer (DWORD (Pointer (PEB ) 12) ^)); flink: = pointer (DWORD (Pointer 12) ^)); p: = flink; repeat bs: = dword (POINTER (P) $ 18) ^) ; if bs = NtDllBase then begin NtDllLength: = DWORD (pointer (dword (p) $ 20) ^); break; end; p: = pointer (dword (p ^)); until dword (flink) = dword (p ^ ); if ntdlllength = 0 Then ShowMSG ('can' '
T get NTDLL.DLL Image Size! '); {Showmsg (' Creating Suspended Process ... '); ZeromeMory (@SI, SIZEOF (STARTUPINFO); Si.cb: = SizeOf (StartupInfo); CreateProcess (Despath, NIL , NIL, NIL, FALSE, CREATE_SUSPENDED, NIL, NIL, SI, PI);} showMSG ('preplay hook' func2hook '...); ptrreal: = getProcaddress (GetModuleHandle (' kernel32.dll '), Func2hook ); if assigned (PTRREAL) THAN SHOWMSG ('Real' Func2Hook Addr: ' INTTOHEX (DWORD (PTRREAL), 8)) Else Begin Showmsg (' AddR: ' Func2hook ' IS Unreadable! EXIT! ') ; // resumethread (pi.hthread); exit; end; readprocessmemory (getcurrentprocess, ptrreal, @bytes, 5, rtn); // readprocessMemory (pi.hprocess, ptrreal, @bytes, 5, RTN); iftes [0 ] <> CHR ($ E9) Then Begin CopyMemory (@ORIGINALBYTES, @BYTES, 5); SHOWMSG (Func2Hook 'Havn''t Been Hooked!'); Else Begin Showmsg (Func2Hook 'Have Been Hooked! EXIT! '); // resumethread (PI.hthread); exit; end; cbstolen: = 0; While Cbstolen <5 do CBSTOLEN: = CBSTOLEN LDE32 (Pointer (PTRREAL) CBSTOLEN ); ShowMsg ( 'Let''s steal the first ' inttostr (cbStolen) ' bytes :) '); ShowMsg (' But make it writable first ... '); if VirtualProtect (PtrReal, cbStolen, PAGE_EXECUTE_READWRITE, @ TMP) THEN Showmsg ('Make' INTTOHEX (DWORD (PTRREAL), 8) 'WRITABLE SUCCEED!') Else Begin Showmsg ('Hoops! Make' INTTOHEX (DWORD (PTRREAL), 8) 'WRITABLE FAILED! EXIT !! '); // ResumeThread (PI.hthread); exit; end; showmsg (' assembly jmp code & hook ' func2hook "
... '); getMem (hookjmp, 5); try hookjmp [0]: = CHR ($ E9); ASM PUSH EAX LEA EAX, FAKECODE MOV TMP, EAX POP END; TMP: = Tmp - DWORD (PTRREAL) - 5; CopyMemory (@HookJmp [1], @tmp, 4); asm push eax lea eax, RtnCode mov tmp, eax pop eax end; VirtualProtect (Pointer (tmp), cbStolen, PAGE_EXECUTE_READWRITE, @Rtn); CopyMemory (Pointer (tmp), PtrReal, cbStolen); WriteProcessMemory (GetCurrentProcess, PtrReal, HookJmp, 5, Rtn); // WriteProcessMemory (pi.hProcess, PtrReal, HookJmp, 5, Rtn); ShowMsg ( 'Hook' Func2Hook 'succeed! Resume thread! '); Finally FreeMem (hookjmp); // resumethread (pi.hthread); end; exit; fakecode: // no strings from here on ASM INT 3 End; ASM PUSH EAX LEA EAX, [ESP 4] MOV P, EAX POP END; if DWORD (P ^) - NTDLLBASE