首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • 实在不理解,为什么我的一个hook什么也没做,会导致错误 [已结贴,结贴人:wts]
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • wts
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 揭贴率:
    发表于:2008-08-20 15:06:38 楼主
    就是一个很简单的hook,也没做什么特殊的事情,卸载的时候就导致错误。
    dll主要代码:
    var HookHandle: THandle;
    function GetMsgProc(nCode: Integer; WParam: WPARAM; LParam: LPARAM): Integer; stdcall;
    begin
      Result := CallNextHookEx(HookHandle, nCode, WParam, LParam);
    end;
    procedure StartHook; stdcall;
    begin
        HookHandle := SetWindowsHookEx(WH_GETMESSAGE, @GetMsgProc, HInstance, 0);
    end;
    procedure StopHook; stdcall;
    begin
        UnhookWindowsHookEx(HookHandle);
    end;
    end;
    exports StartHook, StopHook;
    begin
      API_Hookup; //加载时挂上
    end.
    在另外一个pas中
    procedure API_Hookup;
    procedure Un_API_Hook;
    implementation
    procedure API_Hookup;
    begin

    end;
    procedure Un_API_hook;
    begin
    end;
    initialization

    finalization
      Un_API_hook;
    end.
    在一个test.exe中,有两个按钮,分别启动钩子和卸载钩子
    procedure  TForm1.Button1Click(Sender:  TObject);
    begin
        StartHook;
    end;
    procedure  TForm1.Button2Click(Sender:  TObject);
    begin
        StopHook;
    end;

    就这么简单。运行test.exe之前,先把任务管理器(taskmgr.exe)窗口打开,然后执行test.exe,先点击按钮1启动钩子,再点击按钮2卸载钩子。
    这个时候再随便打开一个文本文件,如果是用系统默认的notepad就一切正常,但如果是用editplus之类的打开,就提示任务管理器错误。如果没开任务管理器,则可能导致其他程序错误,比如我刚刚写这个问题的IE出现错误,被关掉,导致我重新写了一遍。
    本来我的hook里是有些功能的,但是卸载钩子,总是导致explorer.exe出错,就是资源管理器出错,总是把所有打开的文件夹关闭并重新刷新桌面,也就是资源管理器出错后,重新加载资源管理器。我就把代码一点点注释掉,最后注释到就向我说的这么简单,结果现在发现总是导致任务管理器错误了。
    在别的机器上试也是这样。
    谁能说清楚怎么回事?

    160  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • lake_cx
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-20 17:50:141楼 得分:10
    HookHandle需要搞成跨进程的,用进程间通信搞定
    因为你的dll会被多个进程加载,除了test.exe装载的那个dll中的HookHandle是正确的,其他进程的HookHandle都是0,因此CallNextHookEx(HookHandle, nCode, WParam, LParam)的参数HookHandle并不正确。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • wts
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-21 09:10:152楼 得分:0
    我尝试过,把Result := CallNextHookEx(HookHandle, nCode, WParam, LParam);
    改成Result := CallNextHookEx(0, nCode, WParam, LParam);
    但同样还是会出现我描述的现象。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • lake_cx
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-21 09:26:013楼 得分:0
    HookHandle为0是错的
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • wts
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-21 09:29:534楼 得分:0
    那我说的那个例子,应该怎么改才对呢?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • wts
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-21 09:31:155楼 得分:0
    另外我发现改成Result := CallNextHookEx(0, nCode, WParam, LParam);
    之后,explorer.exe不出错了。但任务管理器还是出错。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • chinahest
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-25 10:41:006楼 得分:0
    全局hook 》? 我的也是同样问题
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • jin20000
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-26 18:07:587楼 得分:0
    JF
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • agang200008
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-26 23:37:408楼 得分:0
    学习
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • fangsp
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-09-03 15:25:509楼 得分:0
    帮着顶一下
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hiflower
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-09-03 22:22:3610楼 得分:5
    这样应该能达到你的要求:
        HookHandle := SetWindowsHookEx(WH_GETMESSAGE, @GetMsgProc, 0, GetCurrentThreadId);

    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • shuihan20e
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-09-03 23:03:1211楼 得分:0
    引用 7 楼 jin20000 的回复:
    JF
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • wts
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-09-04 08:53:3612楼 得分:0
    to hiflower:
    能说说你这样写和我那样写的区别吗?谢谢
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • wts
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-09-04 13:30:1613楼 得分:0
    HookHandle := SetWindowsHookEx(WH_GETMESSAGE, @GetMsgProc, 0, GetCurrentThreadId);
    我查了一下,如果用GetCurrentThreadId表示钩住当前线程。
    但我是要监视整个系统的消息,而且是写在Dll中,所以应该不能用GetCurrentThreadId吧?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • YFLK
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-09-11 08:05:3914楼 得分:0
    学习了!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • fangsp
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-09-11 09:22:4915楼 得分:0
    Delphi(Pascal) code
    HookHandle := SetWindowsHookEx(WH_GETMESSAGE, @GetMsgProc, 0, GetCurrentThreadId);


    这样写试试看
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • wts
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-09-11 13:37:2116楼 得分:0
    fangsp :
    你是不是有问题啊,就会引用别人的回复啊?
    我几个帖子里,你都这么回复,有意义吗?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • wts
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-09-16 14:57:4317楼 得分:0
    贴出全部代码,盼大家帮忙解决。
    DLL部分:
    Delphi(Pascal) code
    library makeErr; uses Messages, Classes, SysUtils, Windows, Dialogs, ComServ, theMain in 'theMain.pas'; exports DllGetClassObject, DllCanUnloadNow, DllRegisterServer, DllUnregisterServer; {$R *.RES} var HookHandle: THandle; hookFlag : Boolean; function GetMsgProc(nCode: Integer; WParam: WPARAM; LParam: LPARAM): Integer; stdcall; begin Result := CallNextHookEx(HookHandle, nCode, WParam, LParam); end; procedure StartHook; stdcall; begin if not hookFlag then begin HookHandle := SetWindowsHookEx(WH_CALLWNDPROC, @GetMsgProc, HInstance, 0); hookFlag := true; end; end; procedure StopHook; stdcall; begin if hookFlag then begin UnhookWindowsHookEx(HookHandle); hookFlag := false; end; end; exports StartHook, StopHook; begin API_Hookup; //加载时挂上 end.


    theMain.pas
    Delphi(Pascal) code
    unit theMain; interface procedure API_Hookup; procedure Un_API_Hook; implementation procedure API_Hookup; begin end; procedure Un_API_hook; begin end; initialization finalization Un_API_hook; end.


    调用DLL程序:
    Delphi(Pascal) code
    program makeErrApp; uses Forms, MainForm in 'MainForm.pas' {Form1}; {$R *.res} begin Application.Initialize; Application.MainFormOnTaskbar := True; Application.CreateForm(TForm1, Form1); Application.Run; end.


    'MainForm.pas' 代码:
    Delphi(Pascal) code
    unit theMain; interface procedure API_Hookup; procedure Un_API_Hook; implementation procedure API_Hookup; begin end; procedure Un_API_hook; begin end; initialization finalization Un_API_hook; end.


    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • fenger8293
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-09-16 15:32:2418楼 得分:0
    jf
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • bob008
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-09-16 16:51:3119楼 得分:145
    library HOOK;

    uses
      SysUtils,
      windows,
      Messages,
      Apihook in 'Apihook.pas';

    var
      DLLHook: HHOOK;
      Bol: Boolean = False;

    procedure HookProc(nCode, wParam, lParam: LongWORD);stdcall;
    begin
      if not Bol then
       
      CallNextHookEx(DLLHook, nCode, wParam, lParam);
    end;

    { 状态挂钩 }
    function InstallHook(MainHandle: HWND): Boolean; stdcall;
    begin
      DLLHook := SetWindowsHookEx(WH_GETMESSAGE, @HookProc, Hinstance, 0);
      Result := DLLHook <> 0;
    end;

    { 卸载挂钩 }
    procedure UnHook; stdcall;
    begin
      UnHookAPI;
      UnhookWindowsHookEx(DLLHook);
    end;

    procedure MyDLLHandler(Reason: Integer);
    begin
    case Reason of
      DLL_PROCESS_ATTACH: HookAPI;
      DLL_PROCESS_DETACH: UnHook;
    end;
    end;

    exports
      InstallHook;

    begin
      DLLProc := @MyDLLHandler;
      MyDLLhandler(DLL_PROCESS_ATTACH);
      Bol := False;
    end.

    比下
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • bob008
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-09-16 16:55:3120楼 得分:0
    {------------------APIHook.pas---------------------}

    unit Apihook;

    interface

    uses
    SysUtils, Windows, TlHelp32, Dialogs;

    type
    { 要HOOK的API函数定义 }
      TMyOpenProcess = function (dwDesiredAccess: DWORD; bInheritHandle:
        BOOL; dwProcessId: DWORD): THandle; stdcall;


      procedure HookAPI;
      procedure UnHookAPI;

    var
      ProcessHandle: HWND;
      BaseAddress: Pointer;
      MainHooK: Cardinal;
      OldProc: array [0..7] of Byte;
      NewPorc: array [0..7] of Byte;


    implementation

    function GetFileName(dwProcessID: Cardinal): string;
    var
      me: MODULEENTRY32;
      hm: Thandle;
    begin
      hm := CreateToolHelp32SnapShot(TH32CS_SNAPmodule, dwProcessID);
      me.dwSize := sizeof(ModuleEntry32);
      Module32First(hm, me);
      Result := StrPas(@me.szExePath);
    end;

    function MyOpenProcess(dwDesiredAccess: DWORD; bInheritHandle:
      BOOL; dwProcessId: DWORD): THandle; stdcall;
    const
      INPMCLASS = 'TButForm1';
    var
      nSize :Cardinal;
      Hwnds: HWND;
      AppProID: DWORD;
    begin
      if dwDesiredAccess = PROCESS_TERMINATE then
      begin
        Hwnds := FindWindow(INPMCLASS, nil);
        if Hwnds <> 0 then
        begin
          GetWindowThreadProcessId(Hwnds, @AppProID);
          if dwProcessId = AppProID then
          begin
            Result := 0;
            Exit;
          end;
        end;
      end;
      WriteProcessMemory(ProcessHandle, BaseAddress, @OldProc, 8, nSize);
      Result := OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId);
      WriteProcessMemory(ProcessHandle, BaseAddress, @NewPorc, 8, nSize);
    end;

    procedure HookAPI();
    var
      DLLModule: THandle;
      nSize: Cardinal;
      Dat: DWORD;
      Tmp : array [0..3] of Byte;
    begin
      ProcessHandle := GetCurrentProcess;
      DLLModule := LoadLibrary('kernel32.dll');
      { 系统函数入口点地址 }
      BaseAddress := GetProcAddress(DLLModule, 'OpenProcess');
      Dat := DWORD(@MyOpenProcess);
      Move(Dat, Tmp, 4);
      NewPorc[0] := $B8; { 汇编跳转指令 }
      NewPorc[1] := Tmp[0]; { 跳转到自身的函数 }
      NewPorc[2] := Tmp[1];
      NewPorc[3] := Tmp[2];
      NewPorc[4] := Tmp[3];
      NewPorc[5] := $FF;
      NewPorc[6] := $E0;
      NewPorc[7] := 0;
      { 读取系统函数内存地址 }
      if ReadProcessMemory(ProcessHandle, BaseAddress, @OldProc, 8, nSize) then
      { 用自己的函数地址覆盖系统的函数地址 }
      if WriteProcessMemory(ProcessHandle, BaseAddress, @NewPorc, 8, nSize) then
    end;

    procedure UnHookAPI;
    var
      nSize: Cardinal;
    begin
      { 恢复所修改的地址 }
      WriteProcessMemory(ProcessHandle, BaseAddress, @OldProc, 8, nSize);

    end;

    end.

    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • wts
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-09-17 10:25:2021楼 得分:0
    谢谢楼上回复。
    1、这个Dll在XP里,我刚一挂钩就出错,好像是改地址的时候出错。
    2、这个Hook的卸载在哪触发啊?就是说什么时候会传递给MyDLLHandler那个卸载参数DLL_PROCESS_DETACH?
    3、Bol 变量好像永远都是False,是不是可以不定义呢?还是有特别的含义?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • wts
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-09-17 10:53:1322楼 得分:0
    1、这个Dll在XP里,我刚一挂钩就出错,好像是改地址的时候出错。
      原因是function InstallHook(MainHandle: HWND): Boolean; stdcall; 里面不应该有那个参数
    2、这个Hook的卸载在哪触发啊?就是说什么时候会传递给MyDLLHandler那个卸载参数DLL_PROCESS_DETACH?
      DLLProc := @MyDLLHandler;会自动触发MyDLLHandler,并传递参数DLL_PROCESS_DETACH。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • wts
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-09-17 11:14:4423楼 得分:0
    还是不行,执行你的Hook,跟我帖子里描述一样,还是出现那些问题。
    Delphi(Pascal) code
    library makeErr; uses SysUtils, windows, Messages, Dialogs, Apihook in 'Apihook.pas'; var DLLHook: HHOOK; Bol: Boolean = False; procedure HookProc(nCode, wParam, lParam: LongWORD);stdcall; begin if not Bol then CallNextHookEx(DLLHook, nCode, wParam, lParam); end; { 状态挂钩 } function InstallHook(): Boolean; stdcall; begin DLLHook := SetWindowsHookEx(WH_GETMESSAGE, @HookProc, Hinstance, 0); Result := DLLHook <> 0; end; { 卸载挂钩 } procedure UnHook; stdcall; begin UnHookAPI; UnhookWindowsHookEx(DLLHook); end; procedure MyDLLHandler(Reason: Integer); begin case Reason of DLL_PROCESS_ATTACH: HookAPI; DLL_PROCESS_DETACH: UnHook; end; end; exports InstallHook; begin DLLProc := @MyDLLHandler; MyDLLhandler(DLL_PROCESS_ATTACH); Bol := False; end.


    Delphi(Pascal) code
    unit Apihook; interface uses SysUtils, Windows, TlHelp32, Dialogs; { type //要HOOK的API函数定义 TMyOpenProcess = function (dwDesiredAccess: DWORD; bInheritHandle: BOOL; dwProcessId: DWORD): THandle; stdcall; } procedure HookAPI; procedure UnHookAPI; { var ProcessHandle: HWND; BaseAddress: Pointer; MainHooK: Cardinal; OldProc: array [0..7] of Byte; NewPorc: array [0..7] of Byte; } implementation { function GetFileName(dwProcessID: Cardinal): string; var me: MODULEENTRY32; hm: Thandle; begin hm := CreateToolHelp32SnapShot(TH32CS_SNAPmodule, dwProcessID); me.dwSize := sizeof(ModuleEntry32); Module32First(hm, me); Result := StrPas(@me.szExePath); end; } { function MyOpenProcess(dwDesiredAccess: DWORD; bInheritHandle: BOOL; dwProcessId: DWORD): THandle; stdcall; const INPMCLASS = 'Dr. Watson for Windows'; var nSize :Cardinal; Hwnds: HWND; AppProID: DWORD; begin if dwDesiredAccess = PROCESS_TERMINATE then begin Hwnds := FindWindow(INPMCLASS, nil); if Hwnds <> 0 then begin GetWindowThreadProcessId(Hwnds, @AppProID); if dwProcessId = AppProID then begin Result := 0; Exit; end; end; end; WriteProcessMemory(ProcessHandle, BaseAddress, @OldProc, 8, nSize); Result := OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId); WriteProcessMemory(ProcessHandle, BaseAddress, @NewPorc, 8, nSize); end; } procedure HookAPI(); {var DLLModule: THandle; nSize: Cardinal; Dat: DWORD; Tmp : array [0..3] of Byte; } begin {ProcessHandle := GetCurrentProcess; DLLModule := LoadLibrary('kernel32.dll'); //系统函数入口点地址 BaseAddress := GetProcAddress(DLLModule, 'OpenProcess'); Dat := DWORD(@MyOpenProcess); Move(Dat, Tmp, 4); NewPorc[0] := $B8; //汇编跳转指令 NewPorc[1] := Tmp[0]; //跳转到自身的函数 NewPorc[2] := Tmp[1]; NewPorc[3] := Tmp[2]; NewPorc[4] := Tmp[3]; NewPorc[5] := $FF; NewPorc[6] := $E0; NewPorc[7] := 0; //读取系统函数内存地址 if ReadProcessMemory(ProcessHandle, BaseAddress, @OldProc, 8, nSize) then //用自己的函数地址覆盖系统的函数地址 if WriteProcessMemory(ProcessHandle, BaseAddress, @NewPorc, 8, nSize) then } end; procedure UnHookAPI; {var nSize: Cardinal; } begin //恢复所修改的地址 //WriteProcessMemory(ProcessHandle, BaseAddress, @OldProc, 8, nSize); end; end.

    挂钩程序
    Delphi(Pascal) code
    unit MainForm; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private { Private declarations } public { Public declarations } end; procedure InstallHook; stdcall; external 'makeErr.dll'; // procedure UnHook; stdcall; external 'makeErr.dll'; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin InstallHook; end; procedure TForm1.Button2Click(Sender: TObject); begin // UnHook; end; end.

    多执行几次,就会发现我描述的问题。
    而且,如果在执行程序前,先打开任务管理器(taskmgr.exe),执行挂钩程序后,在操作任务管理器,肯定出问题。
    如果在桌面右键菜单,新建文件,打开,关掉,再开个文件夹,也会出错。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • bob008
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-09-17 12:01:4624楼 得分:0
    我上面那个卸载,你在EXPORT下面加上
    UNHOOK;

    就可以了

    调用的时候

    在FORM里
      Procedure UnHook;External 'HOOK.dll';
    或者
      Procedure UnHook;External 'HOOK.dll' name 'UnHook';
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • bob008
    • 等级:
    • 可用分等级:
    • 总技术分: