[C++] 纯文本查看 复制代码
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 | BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: //dll载入时执行 { g_hModule = hModule; //保存句柄到全局变量 hhk = StartHook(); break ; } case DLL_PROCESS_DETACH: //dll卸载时执行 { EndHook(); break ; } case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: break ; } return TRUE; } |
DllMain函数的ul_reason_for_call指明了函数被调用的原因,DLL_PROCESS_ATTACH指DLL被调用,DLL_PROCESS_DETACH指DLL被卸载,而case DLL_THREAD_ATTACH和case DLL_THREAD_DETACH分别表示线程被创建和销毁。我们在dll加载时调用StartHook函数,dll卸载时调用EndHook函数,下面我们看看这两个函数
[C++] 纯文本查看 复制代码
1 2 3 4 5 6 7 8 9 | HHOOK StartHook() { return SetWindowsHookEx(WH_CALLWNDPROC, HookProc, g_hModule, GetCurrentThreadId()); //设置hook,类型为WH_CALLWNDPROC,过程函数为HookProc,hook当前线程 } BOOL EndHook() { return UnhookWindowsHookEx(hhk); //结束hook } |
这两个函数只是很简单的封装了俩个API,重点在于SetWindowsHookEx的参数设置,由于我们hook的是WM_COMMAND消息,所以我们选择hook类型为WH_CALLWNDPROC,表明当窗口过程函数被调用时触发hook,并且我们是hook当前线程,hook过程函数在dll里,所以第三个参数填dll模块句柄或者NULL都行,第四个参赛则直接利用GetCurrentThreadId()获取当前线程id这里有一篇文章介绍hook的类型,写的很不错,有兴趣的可以看看http://blog.csdn.net/whatday/article/details/8006225重点还在hook过程函数,我们需要在这里过滤出我们需要的消息,并编写功能代码
[C++] 纯文本查看 复制代码
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 | LRESULT CALLBACK HookProc( int nCode, WPARAM wParam, LPARAM lParam) { if (nCode >= 0) { CWPSTRUCT* cwps = (CWPSTRUCT*)lParam; if (WM_COMMAND == cwps->message) { INT wmId = LOWORD(cwps->wParam); if (wmId == 1099) DialogBoxParam(g_hModule, ( LPCTSTR )IDD_DIALOG, NULL, DlgProc, NULL); } } return CallNextHookEx(hhk, nCode, wParam, lParam); } |
由于我们只需要添加按钮弹窗功能,所以我们只过滤WM_COMMAND消息,前面我们添加按钮资源的时候id填写的是1099,这里就派上用场了。这里我调用了DialogBoxParam函数来弹出对话框,弹出对话框需要添加对话框资源,并且编写过程函数。选择vs2013的菜单项->项目->添加资源->Dialog->新建<ignore_js_op> vs中出现我们新建的对话框资源<ignore_js_op> 我就不编辑资源了,直接开始编写对话框的过程函数,这里我没有添加任何功能代码
[C++] 纯文本查看 复制代码
01 02 03 04 05 06 07 08 09 10 | BOOL CALLBACK DlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_CLOSE: EndDialog(hDlg, NULL); } return FALSE; } |
到此为止,代码编写工作就完成了,但是这个dll没有一个导出函数,我们没法把它加到Scylla的导入表里,不过我们可以写一个空的导出函数
[C++] 纯文本查看 复制代码
1 2 3 4 | __declspec ( dllexport ) void EmptyFunc() { //Do nothing } |
3.编译dll接下来我们编译dll,将工具条上的编译选项设为release,点击编译。<ignore_js_op> 如果你用的也是vs2013,这里需要修改两个地方的设置,否则编译出来的dll在xp上不能运行。VS2013菜单->项目->属性->配置属性->常规->平台工具集->Visual Studio 2013 - Windows XP (v120_xp)VS2013菜单->项目->属性->配置属性->c/c++->代码生成->运行库->多线程 (/MT)在项目文件夹里找到HookMSG.dll,拷贝到Scylla目录下。三、修改Scylla导入表Stub_PE载入Scylla,选择“函数”选项卡,右键添加函数,选择HookMSG.dll,选择EmptyFunc函数,确定添加并保存。<ignore_js_op> 运行一下看结果,点击about按钮,对话框成功弹出,大功告成。<ignore_js_op> 写在最后:其实整个过程没有什么技术含量,懂Windows编程的人看一眼就懂,但是作为新手弄这些东西还是有点难,整个过程当中我也是遇到各种问题,不过结果总算是好的发这篇帖子的目的是希望与大家共勉,同时分享一下成功的喜悦,写的不好的地方希望大家多多包涵最后感谢论坛提供这个学习的机会,也感谢各位讲师 @Kido 的指导同时附上HookMSG.dll的完整源代码,链接:http://pan.baidu.com/s/1c0GvFOW 密码: v7umps:其实Scylla是开源软件,想要汉化或者改界面的可以下载源代码自己编译,https://github.com/NtQuery/Scylla