dll劫持检测软件生成器 源码开放(纯WINDOWS SDK)+ 实例分析
本菜最近学习了什么DLL注入啊,hook啊(r3)的相关技术,觉得很好玩,于是深入发现还有DLL劫持这种东西觉得挺好玩的,加上最近看到各种木马分析报告中都还有发现有利用白加黑的现象。于是自己想找几个来玩玩,但是一个一个手动测试麻烦啊,于是想写个工具来测试目标是否存在DLL劫持漏洞的可能,于是就产生了写个工具的想法,上网一看,原来十年前都有大神写出来了,不过感觉有点麻烦,好多选项不知道干嘛的,加上本人只学了汇编和C,C++不太懂,平常都是做WINDOWS C编程,所以参考那位前辈的生成的代码改进成自己的,无奈不懂MFC ,他的源码我就没看,反正没事做,当作练练手,过程还真学了不少东西。可能有人说python三下五除二就出来。都说了无聊练习了,,,PS:本工具只生成常规的winowds调用方式的DLL代码,还添加了列出目标进程存在DLL劫持可能性的DLL。方便大家用来测试(sha)软(ren)件(fang)安(huo)全大神不喜勿喷啊,有错误的或者需要改进的还望指出。IIS7网站监控可以及时防控网站风险,快速准确监控网站是否遭到各种劫持攻击,网站在全国是否能正常打开(查看域名是否被墙),精准的DNS污染检测,具备网站打开速度检测功能,第一时间知道网站是否被黑、被入侵、被改标题、被挂黑链。精益求精的产品,缺陷为零数据提供!它可以做到以下功能:1、检测网站是否被黑2、检测网站是否被劫持3、检测域名是否被墙4、检测DNS是否被污染5、网站真实的完全打开时间(独家)6、拥有独立监控后台,24小时定时监控域名官方地址:http://wzjk.iis7.net/?dx官方图:
0x00 工具简介名称:FakeLib开发环境:VS 2013 、 win10 x64开发语言:C (纯windows sdk)作者:josegh0x01 功能和使用有两种模式:1.1 和aHeadLib一样,选择目标DLL直接生成这里我只生成常用的调用方式代码。
图 1-11.2 通过查看进程列表,选择一个你感兴趣的进程,然后列出其加载的且不在系统注册表KnownDlls中的DLL,然后选择一个目标来生成代码。1.2.1 选择侦察模式
图 1-21.2.2 选择你感兴趣的进程
图 1-31.2.3 选择目标DLL 生成代码
图 1-40x02 实际测试2.1 测试获取主进程函数调用参数和返回值。这里我自己写了一个测试程序2.1.1 正常 normal.dll,它导出一个函数123456EXPORT DWORD add(DWORD a, DWORD b){DWORD dwret = 0;dwret = a + b;return dwret;}2.1.2 一个正常的loader,去调用normal.dll的add函数1234567891011DWORD dwResult = 0;DWORD a = 5, b = 6;add = (DWORD)GetProcAddress(hDll, "add");if (add != NULL){dwResult = add(a, b);printf_s("loader:%d + %d = %d\n\n", a, b, dwResult);}elseprintf_s("loader:获取导出函数地址失败\n\n");printf_s("loader:重新获取控制权\n\n");2.1.3 用FakeLib工具去生成一个用来劫持的DLL利用代码图 2-12.1.4 重点部分在生成的代码中添加获取参数和返回值的代码12345678910111213141516171819202122232425262728293031323334353637383940414243444546void showArg(DWORD a, DWORD b){printf_s("fake_dll:截取到参数:a:%d b:%d\n\n", a, b);return;}void showRet(DWORD dwret){printf_s("fake_dll:截取到返回值:%d\n\n ", dwret);return;}/////////////////////////////////////////////////////////////////////////////////////导出函数 1DWORD c, d, dwret; //参数 a b,返回值dwret 在这里声明是为了不影响函数内部的堆栈ALCDECL Fake_add(){//以下注释经过OD调试得出 编译环境:win10 x64 vs2013,//一般情况下在这里为所欲为 注意堆栈平衡__asm{push eax //保存eax 以防目标函数用来做参数mov eax, [esp +0x08] //获取参数amov c,eaxmov eax, [esp + 0x0C] //获取参数bmov d,eaxpop eax //恢eax}showArg(c, d);//为什么不直接printf?printf是由调用者维护堆栈平衡,而我们现在这里的函数是naked声明的//不对自动维护堆栈,需要我们,为了方便,我们直接把它放到一个会维护堆栈平衡的函数里边执行//下边的同理GetAddress("add");//此时栈订保持的是返回地址,因为我们前面没有破坏堆栈__asm pop dwRetaddress[1]//弹出来,下面菜可以用call,为什么用call?因为如果用直接jmp的话 想获取执行返回值有点困难__asm call eax//把返回地址入栈,这时候就相当于原来的返回地址被我们call的下一条指令地址入栈,这样真实函数返回后我们重新夺回控制权//一般情况下在这里继续为所欲为 注意堆栈平衡__asm push eax //保存返回值__asm mov dwret ,eaxshowRet(dwret);__asm pop eax__asm jmp dword ptr dwRetaddress[1] //跳回原函数}///////////////////////////////////////////////////////////////////////////////现在我们把它改名为 normal_dll.dll 放到loader目录下,执行loader的效果:(此前你需要把之前正常的normal_dll.dll换个名字 如normal_dll_hide.dll)
图 2-1loader执行结果
图 2-3 执行结果可以看到先是我们的dll获取到返回结果。2.2略大家可以参考: http://www.freebuf.com/articles/78807.htmlhttp://drops.wooyun.org/tips/13238#!乌云上也有许多例子,大家可以自己去写个测试程序,或者直接找实际的应用来测试0x03 总结如果只是方便自己,我也许不会把工具的代码写得工整(自认为算是最工整的一次 - -),也不会去写界面程序。开始写导出函数的时候用的是常规的dllexport,运行的时候发现问题有点多,用OD调试发现原因是堆栈问题(菜得抠脚啊),都打算用生成汇编的算了,后面才发现有naked这种玩意,于是本着能用c就用用c的原则,最后还是选择生成c代码的方式。也算是涨姿势了。还有一点点小功能没添加,比如刷新什么的。还有,感觉自己菜得抠脚啊,有没有大神指点指点0x04 使用注意有时候不能列出目标DLL,应该是权限问题。