使用CreateRemoteThread进行DLL注入

Jam*_*ing 14 c++ dll visual-studio visual-c++ dll-injection

如果您看一下简单DLL注入的以下工作代码:

  //Open the target process with read , write and execute priviledges
   Process = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_VM_WRITE|PROCESS_VM_OPERATION, FALSE, ID); 

   //Get the address of LoadLibraryA
   LoadLibrary = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA"); 

   // Allocate space in the process for our DLL 
   Memory = (LPVOID)VirtualAllocEx(Process, NULL, strlen(dll)+1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 

   // Write the string name of our DLL in the memory allocated 
   WriteProcessMemory(Process, (LPVOID)Memory, dll, strlen(dll)+1, NULL); 

   // Load our DLL 
   CreateRemoteThread(Process, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibrary, (LPVOID)Memory, NULL, NULL); 

   //Let the program regain control of itself
   CloseHandle(Process); 
Run Code Online (Sandbox Code Playgroud)

令我困惑的是GetProcAddress返回当前进程LoadLibraryAfucntion地址,如何将其作为参数传递给并期望目标进程运行它?CreateRemoteThread

Han*_*ant 19

它是偶然的.这是一个非常普遍的事故,微软付出了大量努力来确保操作系统DLL(如kernel32.dll)具有不与任何其他DLL冲突的基址.kernel32.dll在进程初始化时很早就加载了进一步增强,因此它必须争取获得其首选基地址的可能性很小.

你很容易逃脱.值得注意的是,这已经出了错在过去,有导致GDI32.DLL得到重新安置,进行了大量的机器在开机翻倒的XP安全更新哎呀.正确的方法是相当痛苦的,CreateToolhelp32Snapshot()+ Module32First/Next()找到重定位偏移量并不是很大的乐趣.坦率地说,如果操作系统像这样"怪异",你可能根本不应该这样做.


小智 5

地址空间布局随机化 (ASLR) 是 Windows 处理的一项反利用缓解功能,它允许地址重定位,以帮助防止攻击者确定利用内存中某些内容的地址(停止对地址/偏移量进行硬编码)。但是,Windows 模块仅在每次会话时更改其地址。

如果您有一个使用 kernel32.dll 的进程(并非所有进程都使用 kernel32.dll,我将在几分钟内进一步解释这一点),例程的地址可能是 55AA1122 作为示例(这是一个无效的示例地址)。现在,具有 kernel32.dll 的下一个进程将具有与前一个相同例程的 55AA1122 相同的地址......仅当两个进程都具有相同的体系结构时。

32 位进程对于 kernel32.dll 导出以及其他 Windows 模块导出(例如 NTDLL、USER32 等)也将具有相同的地址。64 位进程将具有与 32 位进程不同的地址,但是 64 位进程的 Windows 模块也将具有相同的地址!

远程线程创建并不是一个“意外”,微软是有意实现的。为什么?Microsoft 在 Windows 本身中经常使用它,也用于异步过程调用。微软还经常为自己的例程进行热补丁,作为反逆向技巧,或者如果他们丢失了自己项目的源代码,哈哈。

现在关于将 kernel32.dll 加载到进程中,它仅加载到使用 Win32 API 的进程中。这包括世界上 99% 的程序,但是可以编译一个不使用它的本机进程。然而,这将迫使您完全使用本机 API 而不是 Win32 API,并且名为 smss.exe 的 Windows 进程正是执行此操作。您还可以编译甚至没有正常 Win32 API DLL 入口例程的本机 DLL。

简而言之,Windows 模块例程的地址每次启动都会更改一次。它将保持不变,直到下次重新启动,依此类推。32 位进程的每个进程都有自己的 Windows 模块共享地址,64 位进程也是如此。因此,在针对 32 位进程进行 DLL 注入时,不能使用 64 位进程的 LoadLibraryA 地址,除非使用 32 位 Kernel32.dll LoadLibraryA 地址。更好的想法是无论如何使用 LdrLoadDll,或者只是反射 DLL 加载器存根的 shell 代码注入。