用户层注入:(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劫持的失败。

经验分享 程序员 微信小程序 职场和发展