吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 45203|回复: 115
收起左侧

[原创] HOOK大法实现不修改程序代码给程序添加功能

    [复制链接]
0x18c0 发表于 2015-7-30 19:04
本帖最后由 0x18c0 于 2015-8-1 10:36 编辑


【文章标题】: HOOK大法实现不修改程序代码给程序添加功能
【文章作者】: 0x18c0
【软件名称】: Scylla
【使用工具】: OD、Stub_PE、ResHacker
【版权声明】: 本文原创于0x18c0, 转载请注明作者并保持文章的完整, 谢谢!

菜鸟第一次发帖,写的不好的地方请各位多多包含

本来是第三次培训的作业,要给Scylla加上弹窗
@Kido 老师在上课的时候也演示了,没什么难度,但是按照上课的方法来搞,程序一运行就弹个窗口,太粗暴,强迫症完全不能忍好吧,所以我想在窗口上加个按钮,等点击按钮的时候再弹出窗口,这样就感觉友好多了。
1.png
这么做其实也不难,方法就是找到窗口的过程函数,然后改写指令让程序先跳到我们自己写的函数里,最后再跳转回原窗口过程函数
比如@苏紫方璇 大牛这篇帖子的方法,无源码给程序添加功能-记事本标题添加当前时间
但是,这么搞太麻烦了,需要自己定位窗口过程,还要各种修改指令实现跳转,完全不适合我这种懒人
但是,懒人有懒人的方法,俗话说的好,懒是推动科技进步的根本动力——0x18c0
这里我已经忍不住要高喊一句——HOOK大法好!



先介绍一下方法,我修改了Scylla的导入表,添加了一个我自己编写的DLL,然后在DLL的DllMain函数里下消息hook,每当按钮被按下时,WM_COMMAND消息就会被hook住,从而弹出窗口。



基本方法介绍完了,下面介绍一下HOOK和DLL的基本知识
一、HOOK
        Hook,字面意思就是钩子,是windows系统提供给开发者用来改变windows消息处理流程的编程接口。hook也分好几种,拿下面我要用到的消息hook来举例,每当我们按下一个窗口上的按钮时,系统就会捕获到一个WM_COMMAND消息,消息会被Windows系统传递给软件提前编写好的一个函数,这个函数叫做窗口过程函数,过程函数会根据不同的消息做出不同的处理。但是当我们想在消息被操作系统传递给过程函数处理之前先处理怎么办呢?这个时候就要用到消息hook了,操作系统提供给了开发者改变消息的能力,我们只需要调用相关的API,在相应的消息上设置hook钩子,并且告诉操作系统当消息被钩子钩住的时候因该怎么办,操作系统就会按照我们的意愿来处理消息。
        比如我们hook按钮被按下的消息WM_COMMAND,并且告诉操作系统,当钩子被触发的时候把消息传递给我自己编写的函数HookMSG,于是我们每次按下按钮,钩子都会被触发,并且操作系统会自动
调用HookMSG函数。
二、DLL
        DLL,动态链接库,可以导出变量和函数供其他程序调用,也可以包含资源文件,DLL有一个DllMain函数,每当DLL被链接时都会被调用,并且不同的调用原因可以有不同的处理办法。所以我们用Stub_PE将一个DLL添加到Scylla的倒入表里,每次Scylla运行时操作系统都回自动载入我们添加的DLL,并且运行DllMain里的代码,所以我们在DllMain里写上我们的hook代码,那么每次Scylla运行都会被自动hook了,这样就达到了我们的目的。



方法和基本原理都说了,下面就应该开始实战
一、添加按钮资源
首先得给Scylla加一个按钮,用ResHacker打开Scylla,在对话框上要添加按钮的地方右键——>insert control,出现添加控件的窗口
2.png
选择控件类型为BUTTON,caption这里填写需要显示在按钮上的字,最后别忘了给按钮添加ID,ID需要和其他控件不同以免冲突,这里我填写1099
,点击ok后界面上了出现我们添加的按钮,接下来不要忘了编译和保存
3.png


二、编写DLL
接下来我们编写DLL,我电脑上只有vs2013,所以我就用它了,你们也可以用其他编译器,只要可以编写Windows系统上的DLL就可以。
1.新建工程
选择win32项目,填写工程名,点击确定
4.png
选择DLL和空项目,点击完成,项目创建完成,然后添加main.cpp到工程
5.png

2.编写代码
首先编写DllMain函数
[C++] 纯文本查看 复制代码
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++] 纯文本查看 复制代码
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++] 纯文本查看 复制代码
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->新建
6.png
vs中出现我们新建的对话框资源
7.png
我就不编辑资源了,直接开始编写对话框的过程函数,这里我没有添加任何功能代码
[C++] 纯文本查看 复制代码
BOOL CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
        switch (msg)
        {
        case WM_CLOSE:
                EndDialog(hDlg, NULL);
        }

        return FALSE;
}

到此为止,代码编写工作就完成了,但是这个dll没有一个导出函数,我们没法把它加到Scylla的导入表里,不过我们可以写一个空的导出函数
[C++] 纯文本查看 复制代码
__declspec(dllexport) void EmptyFunc()
{
        //Do nothing
}

3.编译dll
接下来我们编译dll,将工具条上的编译选项设为release,点击编译。
8.png
如果你用的也是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函数,确定添加并保存。
9.png



运行一下看结果,点击about按钮,对话框成功弹出,大功告成。
10.png


写在最后:
其实整个过程没有什么技术含量,懂Windows编程的人看一眼就懂,但是作为新手弄这些东西还是有点难,整个过程当中我也是遇到各种问题,不过结果总算是好的
发这篇帖子的目的是希望与大家共勉,同时分享一下成功的喜悦,写的不好的地方希望大家多多包涵
最后感谢论坛提供这个学习的机会,也感谢各位讲师@Hmily @Kido 的指导
同时附上HookMSG.dll的完整源代码,链接:http://pan.baidu.com/s/1c0GvFOW  密码: v7um
ps:其实Scylla是开源软件,想要汉化或者改界面的可以下载源代码自己编译,https://github.com/NtQuery/Scylla




点评

小老鼠,小老鼠,小老鼠  发表于 2015-8-3 15:11
不错,值得学习  发表于 2015-7-31 15:11
都忘记了消息钩子了,感谢楼主点拨  发表于 2015-7-30 20:36

免费评分

参与人数 44热心值 +44 收起 理由
qaz003 + 1 用心讨论,共获提升!
BlackNWhite + 1 我很赞同!
chenyanlin + 1 谢谢@Thanks!
Dowson小菜 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩.
mrli_agl + 1 我很赞同!
971204169 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩.
773827986 + 1 我很赞同!
LadyGaga + 1 谢谢@Thanks!
悟空不悟 + 1 方法好!
微笑嘻嘻 + 1 漂亮
peter_king + 1 谢谢@Thanks!
唯唯 + 1 谢谢@Thanks!
dagangwood + 1 谢谢@Thanks!
小生我怕怕 + 1 不错的DIY
Seper + 1 我很赞同!
丶木屐帽子 + 1 作为一个新手,看了很受用
逝者如斯 + 1 我很赞同!
zf616545 + 1 我很赞同!
ed0352 + 1 我很赞同!
我love破戒 + 1 谢谢@Thanks!
316655906 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩.
我要学 + 1 热心回复!
布吉岛葫芦娃 + 1 谢谢@Thanks!
幻梦丶诡瞳 + 1 我很赞同!
LoongKing + 1 感谢发布原创作品,吾爱破解论坛因你更精彩.
lxj8378 + 1 没想到楼主还能想到这么加
海盗小K + 1 我很赞同!
蚯蚓翔龙 + 1 学习
吾爱扣扣 + 1 膜拜会C的,先收藏后细读
ll007 + 1 还可以这样,受教了
yuluo5566 + 1 我很赞同!
逍遥枷锁 + 1 谢谢@Thanks!
fengyr + 1 谢谢@Thanks!
taichao + 1 楼主6666,收藏学习
ljrlove2008 + 1 我很赞同!
alccc + 1 谢谢@Thanks!
寒枫雨雪 + 1 谢谢@Thanks!
wulongxiang2009 + 1 很棒,受益良多
showking + 1 我很赞同!
Monitor + 1 感谢发布原创作品,吾爱破解论坛因你更精彩.
苏紫方璇 + 1 懒是推动科技进步的根本动力,有点道理
Cizel + 1 很棒,学会了这种方法
xouou + 1 我很赞同!
by厕所 + 1 谢谢@Thanks!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| 0x18c0 发表于 2015-7-31 11:37
蚯蚓翔龙 发表于 2015-7-31 10:47
全局钩子,虽然看起来有点大材小用了,但是看得出不失为一种通用的解决方法

SetWindowsHookEx(WH_CALLWNDPROC, HookProc, g_hModule, GetCurrentThreadId())
我这里只用了进程内hook,为了加个按钮下全局钩子太浪费

免费评分

参与人数 1热心值 +1 收起 理由
浅唱小男人 + 1 你已经在最后一个参数上加上了被挂钩的线程.

查看全部评分

 楼主| 0x18c0 发表于 2015-8-5 23:41
Amaya° 发表于 2015-8-5 23:06
ResHacker在查看易语言的软件的适合不会出现易语言的窗口 有办法解决吗

E语言编写的程序资源不能用ResHacker编辑,只能用改代码的方式修改,目前也没有看到过有人公开相关的方法
qbnw 发表于 2015-7-30 19:10
 楼主| 0x18c0 发表于 2015-7-30 19:15
qbnw 发表于 2015-7-30 19:10
有个别图片失效了,我这里看不完整

现在能看到了吗?
by厕所 发表于 2015-7-30 19:21
精前留名
 楼主| 0x18c0 发表于 2015-7-30 19:34

{:1_903:}并不是什么厉害的东西,精不了
丶夜猫 发表于 2015-7-30 19:35

精前留名

函数 代码   压力山大。
niuniu919 发表于 2015-7-30 19:43
真是大神啊
苏紫方璇 发表于 2015-7-30 20:34
懒是推动科技进步的根本动力  哈哈  hook多了api倒是把消息钩子忘记了  膜拜
asd7asd123 发表于 2015-7-30 21:23 来自手机
谢谢分享
 楼主| 0x18c0 发表于 2015-7-30 21:40
苏紫方璇 发表于 2015-7-30 20:34
懒是推动科技进步的根本动力  哈哈  hook多了api倒是把消息钩子忘记了  膜拜

其实API hook也可以做到同样的效果

点评

是的 没错HookAPI也可以  发表于 2015-7-30 21:53
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-23 07:37

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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