网上好不容易找了个大概能看得懂的代码,可是好像原先就是错的,谁能帮忙改一下啊?谢谢
装上钩子以后是正常的,但是卸载完之后就出错了,系统就不正常了--------------------------------------------------------------------------------------------------
apihook.pas
--------------------
unit APIHook ;interface uses 
 SysUtils, Windows, WinSock, Dialogs;type 
 { 要HOOK的API函数定义 }
  TCreatePW = function (lpApplicationName: PWideChar; lpCommandLine: PWideChar;
    lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
    bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer;
    lpCurrentDirectory: PWideChar; const lpStartupInfo: TStartupInfo;
    var lpProcessInformation: TProcessInformation): BOOL; stdcall;
 procedure HookAPI;
 procedure UnHookAPI;var
  ProcessHandle: HWND;
  BaseAddress: array [0..2] of Pointer;
  OldProc: array [0..2] of array [0..7] of Byte;
  NewPorc: array [0..2] of array [0..7] of Byte;implementation{ 自定义的函数,用于覆盖系统的CreateProcessW函数 }
function MyCreatePW(lpApplicationName: PWideChar; lpCommandLine: PWideChar;
    lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
    bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer;
    lpCurrentDirectory: PWideChar; const lpStartupInfo: TStartupInfo;
    var lpProcessInformation: TProcessInformation): BOOL; stdcall;
var
  nSize: Cardinal;
begin
  { 显示打开程序的命令行和文件名}
  MessageBoxW(0, lpCommandLine ,lpApplicationName , 0);
  WriteProcessMemory(ProcessHandle, BaseAddress[0], @OldProc[0], 8, nSize);//這一句是修改成原來函數的地址,讓程序能正常打開
  Result := CreateProcessW(lpApplicationName, lpCommandLine, lpProcessAttributes,
   lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment,
   lpCurrentDirectory, lpStartupInfo, lpProcessInformation);
  WriteProcessMemory(ProcessHandle, BaseAddress[0], @NewPorc[0], 8, nSize);//在程序正常打開後再修改成自定義函數的地址,使所有程序在下次打開時都要先調用自定義函數
end;procedure HookAPI;
var
  DLLModule: THandle;
  nSize: Cardinal;
  Dat: DWORD;
  Tmp : array [0..3] of Byte;
begin
  ProcessHandle := DWORD(-1);
  DLLModule := LoadLibrary('kernel32.dll');
  { 系统函数入口点地址 }
  BaseAddress[0] := GetProcAddress(DLLModule, 'CreateProcessW');
  Dat := DWORD(@MyCreatePW);
  Move(Dat, Tmp, 4);
  NewPorc[0][0] := $B8; { 汇编跳转指令 }
  NewPorc[0][1] := Tmp[0]; { 跳转到自身的函数 }
  NewPorc[0][2] := Tmp[1];
  NewPorc[0][3] := Tmp[2];
  NewPorc[0][4] := Tmp[3];
  NewPorc[0][5] := $FF;
  NewPorc[0][6] := $E0;
  NewPorc[0][7] := 0;
  { 读取系统函数内存地址 }
  ReadProcessMemory(ProcessHandle, BaseAddress[0], @OldProc[0], 8, nSize);
  { 用自己的函数地址覆盖系统的函数地址 }
  WriteProcessMemory(ProcessHandle, BaseAddress[0], @NewPorc[0], 8, nSize);
  CloseHandle(ProcessHandle);
end;procedure UnHookAPI;
var
  nSize: Cardinal;
begin
  { 恢复所修改的地址 }
  WriteProcessMemory(ProcessHandle, BaseAddress[0], @OldProc[0], 8, nSize); //主要是這句出了問題,為何無法恢復原來函數的地址??
end;end.
hook.dpr
//////////library hook;uses
  SysUtils,
  windows,
  Messages,
 APIHook  in 'apihook.pas';type
PData = ^TData;
TData = record
Hook: THandle;
Hooked: Boolean;
end;var
DLLData: PData;{------------------------------------}
{过程名:HookProc
{过程功能:HOOK过程
{过程参数:nCode, wParam, lParam消息的相
{ 关参数
{------------------------------------}
procedure HookProc(nCode, wParam, lParam: LongWORD);stdcall;
begin
if not DLLData^.Hooked then
begin
HookAPI;
DLLData^.Hooked := True;
end;
//调用下一个Hook
CallNextHookEx(DLLData^.Hook, nCode, wParam, lParam);
end;
{------------------------------------}
{函数名:InstallHook
{函数功能:在指定窗口上安装HOOK
{函数参数:sWindow:要安装HOOK的窗口
{返回值:成功返回TRUE,失败返回FALSE
{------------------------------------}
function InstallHook(SWindow: LongWORD):Boolean;stdcall;
var
ThreadID: LongWORD;
begin
Result := False;
DLLData^.Hook := 0;
ThreadID := GetWindowThreadProcessId(sWindow, nil);
//给指定窗口挂上钩子                                                  
DLLData^.Hook := SetWindowsHookEx(WH_GETMESSAGE, @HookProc, Hinstance, 0);//ThreadID
if DLLData^.Hook > 0 then
Result := True //是否成功HOOK
else
exit;
end;{------------------------------------}
{过程名:UnHook
{过程功能:卸载HOOK
{过程参数:无
{------------------------------------}
procedure UnHook;stdcall;
begin
UnHookAPI;
//卸载Hook
UnhookWindowsHookEx(DLLData^.Hook);
end;{------------------------------------}
{过程名:DLL入口函数
{过程功能:进行DLL初始化,释放等
{过程参数:DLL状态
{------------------------------------}
procedure MyDLLHandler(Reason: Integer);
var
FHandle: LongWORD;
begin
case Reason of
DLL_PROCESS_ATTACH:
begin //建立文件映射,以实现DLL中的全局变量
FHandle := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, $ffff, 'MYDLLDATA');
if FHandle = 0 then
if GetLastError = ERROR_ALREADY_EXISTS then
begin
FHandle := OpenFileMapping(FILE_MAP_ALL_ACCESS, False, 'MYDLLDATA');
if FHandle = 0 then Exit;
end else Exit;
DLLData := MapViewOfFile(FHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if DLLData = nil then
CloseHandle(FHandle);
end;
DLL_PROCESS_DETACH:
begin
if Assigned(DLLData) then
begin
UnmapViewOfFile(DLLData);
DLLData := nil;
end;
end;
end;
end;{$R *.res}
exports
InstallHook, UnHook, HookProc;begin
DLLProc := @MyDLLHandler;
MyDLLhandler(DLL_PROCESS_ATTACH);
DLLData^.Hooked := False;
end.

解决方案 »

  1.   

    讲讲原理吧,假设A为你的进程,B为被HOOK的进程
    SetWindowsHookEx后,目标进程B收到消息,DLL被映射到B进程并调用HookProc
    目标进程B里的HookProc调用InstallHook并把原始地址存到B.DLLData
    两个进程DLL中的变量DLLData不是共享的,即调用SetWindowsHookEx的A进程里的DLLData<>被映射进程B里的DLLData
    而UnHook时你访问的是A.DllData,在A里调用UnHook是不正确的解决方案:
    1.定义两个消息,MSG_Hook  MSG_UnHook;
    2.修改HookProc,判断消息是MSG_Hook则装载API HOOK,是MSG_UnHook则卸载API HOOK;
    3.A进程用SetWindowsHookEx装载Msg Hook后,发MSG_Hook给目标窗口,由B进程的HookProc装载API HOOK;
    4.需要卸载API HOOK,A进程向目标窗口发MSG_UnHook,由B进程的HookProc收到并卸载API HOOK,然后A进程SetWindowsHookEx还原目标进程的Msg Hook
      

  2.   

    此类方法都不好用的
    用MadHookCode吧~或类似的动态编码方法
      

  3.   

    谢谢,再请问下,这是条汇编指令吧?
    $B8 xxxxx  $FF  $E0 0那些16进制数代表哪些汇编命令啊?