鱼C论坛

 找回密码
 立即注册
查看: 80|回复: 3

[技术交流] 终于找到全局钩子导致其它程序奔溃的原因

[复制链接]
发表于 4 天前 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
前几天突然心血来潮想写个全局钩子的小程序,期间遇到个一直无法解决的问题,就是程序设置钩子没问题一旦解除钩子就会导致其它运行的程序奔溃
短短几行代码,左改右改,该查的资料都查了,就是没有解决,中途时不时的想放弃不弄了,但是本着不找到问题原因不放弃的原则,最后终于找到问题所在。
费话不多说,本文目的是分享经验,没有技术含量,看到最后你才知道什么叫惊不惊喜意不意外。

主要代码:
dll
  1. // 传递消息
  2. function HookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
  3. begin
  4.   Result := CallNextHookEx(hhk, nCode, wParam, lParam);
  5. end;

  6. // 开始HOOK
  7. function StartHook(pid: DWORD):Boolean; stdcall;
  8. begin
  9.   hhk := SetWindowsHookEx(WH_CALLWNDPROC, @HookProc, HInstance, 0);
  10.   Result := hhk<>0;
  11. end;

  12. // 结束HOOK
  13. function EndHook:Boolean; stdcall;
  14. begin
  15.   Result := UnhookWindowsHookEx(hhk);
  16.   if Result then hhk := 0;
  17. end;
复制代码



症状:
运行的程序 一 一 奔溃,explorer.exe也不例外。
2025423_193744.png

主要过程:
  过程1:在项目中把所有无关的代码删除,只保留了设置钩子和取消钩子的代码
  1. // 传递消息
  2. function HookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
  3. begin
  4.   Result := CallNextHookEx(hhk, nCode, wParam, lParam);
  5. end;

  6. // 开始HOOK
  7. function StartHook(pid: DWORD):Boolean; stdcall;
  8. begin
  9.   hhk := SetWindowsHookEx(WH_CALLWNDPROC, @HookProc, HInstance, 0);
  10.   Result := hhk<>0;
  11. end;

  12. // 结束HOOK
  13. function EndHook:Boolean; stdcall;
  14. begin
  15.   Result := UnhookWindowsHookEx(hhk);
  16.   if Result then hhk := 0;
  17. end;
复制代码
结果:设置钩子没问题一旦解除钩子就会导致其它运行的程序奔溃


  过程2:另外新建项目把相关代码边复制边测试以便查找问题。
    结果是把所有代码都移过去后发现程序运行正常了(解除钩子不会导致其它程序崩溃)。
    心里想问题到底在哪里呀?这也不至于啊,就这样算了吧反正是正常了,再想想还是要找到问题,要是以后又遇到那不是又得折腾。

问题在这里:
  经过2个项目代码进行排查,终于找到这该死的问题。
  有问题的dll代码:
  1. library MyHookdll;

  2. uses
  3.   SysUtils,
  4.   Classes,
  5.   Windows, Vcl.Dialogs;

  6. var
  7.   hhk: HHOOK = 0;

  8. // 传递消息
  9. function HookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
  10. begin
  11.   Result := CallNextHookEx(hhk, nCode, wParam, lParam);
  12. end;

  13. // 开始HOOK
  14. function StartHook(pid: DWORD):Boolean; stdcall;
  15. begin
  16.   hhk := SetWindowsHookEx(WH_CALLWNDPROC, @HookProc, HInstance, 0);
  17.   Result := hhk<>0;
  18. end;

  19. // 结束HOOK
  20. function EndHook:Boolean; stdcall;
  21. begin
  22.   Result := UnhookWindowsHookEx(hhk);
  23.   if Result then hhk := 0;
  24. end;


  25. exports
  26.   StartHook, EndHook;

  27. begin

  28. end.
复制代码


  dll正常代码:
  1. library MyHookdll;

  2. uses
  3.   SysUtils,
  4.   Classes,
  5.   Windows;

  6. var
  7.   hhk: HHOOK = 0;

  8. // 传递消息
  9. function HookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
  10. begin
  11.   Result := CallNextHookEx(hhk, nCode, wParam, lParam);
  12. end;

  13. // 开始HOOK
  14. function StartHook(pid: DWORD):Boolean; stdcall;
  15. begin
  16.   hhk := SetWindowsHookEx(WH_CALLWNDPROC, @HookProc, HInstance, 0);
  17.   Result := hhk<>0;
  18. end;

  19. // 结束HOOK
  20. function EndHook:Boolean; stdcall;
  21. begin
  22.   Result := UnhookWindowsHookEx(hhk);
  23.   if Result then hhk := 0;
  24. end;


  25. exports
  26.   StartHook, EndHook;

  27. begin

  28. end.
复制代码


  对比2处代码,仅仅是引用了Vcl.Dialogs组件库便导致程序产生了致命的问题
  就问你们惊不惊喜意不意外。

评分

参与人数 1荣誉 +6 鱼币 +6 贡献 +6 收起 理由
不二如是 + 6 + 6 + 6 鱼C有你更精彩^_^

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 4 天前 | 显示全部楼层
全局钩子导致崩溃的原因分析及解决方案

通过对比两个DLL项目代码,发现问题根源在于Vcl.Dialogs单元的引用。以下是关键分析:

  • 崩溃原因:VCL单元包含消息循环机制,在全局钩子场景中会导致以下问题:
      1. 被注入进程加载该DLL时,会初始化VCL框架
      2. 不同进程共享VCL资源时产生冲突
      3. 卸载DLL时资源释放顺序异常
  • 致命影响:
      1. 调用UnhookWindowsHookEx时DLL卸载失败
      2. 残留的VCL资源导致宿主进程内存损坏
      3. 最终引发explorer.exe等进程崩溃


解决方案:

  1. // 正确的DLL单元引用应仅保留核心模块
  2. uses
  3.   Windows, SysUtils; // 移除非必要的VCL单元
复制代码


经验总结
1. 全局钩子DLL必须保持最小化依赖
2. 避免在DLL中使用任何GUI相关单元
3. 调试时建议用OutputDebugString代替弹窗
4. 推荐使用纯API实现钩子功能

这个案例印证了:在系统级编程中,看似无关的单元引用可能造成毁灭性后果。建议通过Process Monitor等工具监控DLL加载行为,能更快定位此类隐蔽问题。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 3 天前 | 显示全部楼层
太实用了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 3 天前 | 显示全部楼层

惭愧惭愧。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-27 04:58

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表