由 BCG 谈到 API Hook
来源:互联网 发布:jy外设淘宝店网址 编辑:程序博客网 时间:2024/04/29 02:26
BCG 就无需介绍了,业界相当有名的 Visual C++ 换肤专家,能完美模拟 Outlook、Office、Visual Studio 的界面,连 Microsoft 也是他们的客户,其实力可见一斑。
来张界面,这是他自己的 Outlook Demo 编译之后运行的效果:
上面那个 SysCommand 我用红色圈出来了,这么漂亮的一个 UI,居然还是那么老土的菜单(这个菜单在 MFC 的基本控件,比如 CEdit 等,点右键时也会出来),本来 VS2008 sp1 已经内置 BCG 的 CMFCPopupMenu 了,可是在这些地方没有换过来,算是点小瑕疵吧。于是我想给他换过来,和整体 UI 界面风格保持一致。
要达到这样的效果,基本思路有两个:
1、安装消息钩子,处理 WM_INITMENUPOPUP 和 WM_UNINITMENUPOPUP,自绘。一般采用 CMenu 的派生类;
2、Hook 系统 API 函数,处理 TrackPopupMenu 和 TrackPopupMenuEx,用自定义的其他菜单类完成显示。
像常见的一些第三方 skin 包,比如 Skin++,采用的就是第一种方式。
这里我想换成 CMFCPopupMenu,而 CMFCPopupMenu 并非派生于 CMenu,而是派生于 CWnd,所以第一条路行不通,走第二条路。
提到 API Hook,也是个老生常谈的话题了。要实现它,也有两种思路:
一种是找到该API在内存的入口地址,修改其入口前八字节数据为了一汇编的 jmp xxxxxxxx 无条件跳转指令,使其调用该API时会跳到指定的另一处函数入口处,即与这个API有着相同的参数与返回值的回调处理程序。
第二种是在进程的输入表(IAT 表)找到保存在这里的要调用的那个API地址,修改这个地址,使程序在输入表里找该API地址时取的是我们修改后的回调程序入口地址。
关于第一种方法,有例子:http://www.vckbase.com/document/viewdoc/?id=1378
两种方法的利弊也是显而易见的:采用第一种方式,功能上说可以确保万无一失,但是需要频繁的 hook 和 unhook,于效率和稳定性上有所欠缺;第二种在由于只修改一次 IAT 表,所以在效率很稳定性上很有优势,但是缺点就是:某些程序要调用某个 API 可以不通过输入表,造成 hook 不到。
好在 Microsoft 的核心 API 函数库 kernel32、user32、ntdll 好像并没有采用(或者是我理解有问题,至少我们这里 TrackPopupMenu 肯定不会漏),所以我还是采用第二种方式,通过修改进程每个模块的输入表来实现(用 Psapi 枚举进程模块就没必要细说了,都会)。
于是创建新类(比如 CXMenuHooker),用我以前写好的 Hook API 包,添加了两个公开的静态入口函数:
public:
static void HookPopupMenu();
static void RestorePopupMenu();
以便于安装和卸载 API 钩子。然后再给 Menu 加上自定义的弹出菜单函数:
protected:
static BOOL WINAPI TrackPopupMenu(HMENU hMenu, UINT uFlags, int x, int y, int nReserved, HWND hWnd, CONST RECT* prcRect);
static BOOL WINAPI TrackPopupMenuEx(HMENU hmenu, UINT fuFlags, int x, int y, HWND hwnd, LPTPMPARAMS lptpm);
注意参数需要和 SDK 的一致就是了。
关键函数:
这些代码工作的很好,成功 Hook 了 TrackPopupMenu 和 TrackPopupMenuEx 两个 API 函数,弹出了我想要的 CMFCPopupMenu,看图:
可是,等等,似乎有了新问题,这里的 CMFCPopupMenu 不能自动关闭,当我在其他地方点鼠标的时候应该要关闭这个菜单的,仔细翻了一遍 CMFCPopupMenu 的源码,也没发现我这里调用有啥不对的,极其郁闷中...
回头看看最上面的第一种方案,处理 WM_INITMENUPOPUP 的,可行倒是可行,但是自绘的话,效果没办法和 CMFC... 一套东西很好的保持一致,除非派生 CMenu 实现 2000/XP/Office2003/VisualStudio2005 的各种效果,这个代价就太大了,时间不够用啊...
所以最后,这个暂时就只有先搁置下来了,等以后有时间了再来完善了...
- 由 BCG 谈到 API Hook
- 由MCC MNC谈到TelephonyManager
- API HOOK
- Hook API
- hook api
- hook api
- API HOOK
- Hook API
- API HOOK
- HOOK API
- API HOOK
- API Hook
- API Hook
- API Hook
- API HOOK
- hook api
- API HOOK
- HOOK API
- B*树索引
- 串口类
- assert()和panic()
- 动态规划——最大乘积
- ADO.NET对象模型
- 由 BCG 谈到 API Hook
- JDK动态代理实现的思考
- nstools中信息窗显示方法和报文监视的显示方法
- 典意设计-案例欣赏
- Quartz CronTrigger最完整配置说明
- VC操作Excel(转载)
- 【我所認知的BIOS】—>PCI SCAN
- 联动天下空间集装箱----更灵活的虚拟主机
- 用SQLServer2008 画圆、画框