用户层注入:(3)DLL劫持注入
基本概念
Windows的应用程序在加载进程所需的动态库时,会根据导入表一一加载。但是,我们的导入表中只保存有动态库的名称,系统如何知道这个动态库的完整路径并将其加载呢? 其实,在加载动态库时,系统会按照一定的顺序搜索各个目录来寻找指定的Dll文件。一般搜索顺序为:
应用程序所在目录-->系统目录-->16位系统目录-->Windows目录-->运行程序的当前目录-->PATH环境变量。
这还与注册表项HKLMSystemCurrentControlSetControlSession ManagerSafeDllSearchMode有关,如果键值为1,则执行上述的搜索顺序。如果键值为0,则执行如下的搜索顺序:
应用程序所在目录-->运行程序的当前目录-->系统目录-->16位系统目录->Windows目录-->PATH环境变量。
注入原理
函数转发
#pragma comment(linker,"/EXPORT:MyMessageBox=User32.MessageBoxA")
函数调用
VOID _declspec(naked) MyMessageBox()
{
LPVOID MessageBoxAddress = NULL;
HMODULE ModuleHandle = NULL;
//加载真正的动态库
ModuleHandle = LoadLibrary(_T("User32.dll"));
if (ModuleHandle != NULL)
{
//获得导出函数的地址
MessageBoxAddress = GetProcAddress(ModuleHandle, "MessageBoxA");
if (MessageBoxAddress)
{
__asm
{
//跳转到真正的函数地址处
jmp MessageBoxAddress
}
}
//释放动态库
FreeLibrary(ModuleHandle);
}
}
局限性
(1)Windows7以上,系统没有了SafeDllSearchMode 这一选项,而是采用新的注册表项HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSession ManagerKnownDLLs,凡是此项下的DLL文件就会被禁止从应用程序自身所在的目录下调用,而只能从系统目录即SYSTEM32目录下调用。 (2)有些Dll文件在加载时需要检查签名等选项,如果是我们伪造的Dll,检查时就会出错,这也就导致了Dll劫持的失败。
