劫持DLL就是要制作一个“假”的DLL,但是功能又不能失真。
可执行文件在调用某函数时,要加载该函数所在的DLL。如果我们伪造一个DLL,让它包含所有被劫持DLL的导出函数。可执行文件会运行加载伪造的DLL,在伪造DLL里面做我们自己想做的事情。
DLL注入与DLL劫持的比较:
DLL劫持相当于一个定时的炸弹,只等待可执行文件双击运行,拔出导火线,而DLL注入,目标必须处于运行状态,而且DLL注入很容易被拦截。
DLL注入需要一个跳板,也就是发射导弹的发射器,让其注入到目标进程,
而DLL劫持不需要,只需要埋地雷一样,埋在目标文件目录下,可以埋一堆雷。
伪造的DLL需要构造与真实DLL一样的。
本篇文章分享我找DLL劫持的方法,不一定是最佳,不过很方便。
首先,通过windbg启动软件,设置(默认开启的):
Debug->Event Filters->Load module,勾选Output
1
然后go运行。这样我们可以看到运行后,软件导入表导入的DLL,以及LoadLibrary加载的DLL的所有文件,如下所示:
ModLoad: 75090000 750cb000 C:\Windows\system32\rsaenh.dll
ModLoad: 757c0000 757cc000 C:\Windows\system32\CRYPTBASE.dll
ModLoad: 778b0000 778da000 C:\Windows\system32\imagehlp.dll
ModLoad: 77860000 778a5000 C:\Windows\system32\WLDAP32.dll
写一个测试的DLL,只用下面的代码:
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
char path[MAX_PATH] = { 0 };
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
OutputDebugStringA(path);
OutputDebugStringA("success!");
MessageBoxA(NULL, "success!", "Tips", MB_OK);
ExitProcess(0);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
然后讲DLL改名成劫持目标DLL,放到软件目录下,运行验证即可。
如果出现提示success则表示该目标DLL劫持成功。
3
如果DLL太多了,一一验证排除肯定很麻烦,所以程序员又要写代码了。
写一个自动批量验证的工具,基本思路如下:
把windbg拿到的dll列表保存下来
准备好测试DLL,DLL中加入写log功能
分析dll列表,一一把测试DLL拷贝为目标dll,启动软件
然后把log提取出来,可以看到成功劫持的dll。