DLL Injection with CreateRemoteThread

DLL Injection with CreateRemoteThread

本文关键字:CreateRemoteThread with Injection DLL      更新时间:2023-10-16

如果你看一下以下简单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); 

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

它偶然起作用。 这是一个非常常见的事故,Microsoft付出了很大的努力来确保操作系统 DLL(如 kernel32.dll(具有不与任何其他 DLL 冲突的基址。 kernel32 进一步增强了.dll在进程初始化时很早就加载了,几率如此之低,以至于它必须争取获得其首选的基址。

你很容易逃脱。 值得注意的是,这在过去已经出错了,有一个XP安全更新导致gdi32.dll被重新定位,并使许多机器在启动时倒塌。 正确的方法是相当痛苦的,CreateToolhelp32Snapshot(( + Module32First/Next(( 找到重新定位偏移量并不是一件大事。 坦率地说,如果操作系统像这样"奇怪",您可能根本不应该这样做。

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

如果你有一个使用 kernel32

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

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

远程线程创建不是"意外",Microsoft有意实现它。为什么?Microsoft在Windows本身期间经常使用它,也用于异步过程调用。Microsoft也经常为自己的例程热补丁,作为一种反逆转技巧,或者如果他们丢失了自己的项目的源代码,哈哈。

现在关于内核32.dll被加载到进程中,它只加载到使用Win32 API的进程中。这包括世界上99%的程序,但是可以编译一个不会使用它的本机进程。然而,这将迫使你完全使用本机API,而不是Win32 API,而一个名为smss.exe的Windows进程正是这样做的。您还可以编译甚至没有正常 Win32 API DLL 条目例程的本机 DLL

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

LoadLibraryA存在于kernel32.dll中,这是一个总是加载到每个进程中的模块,并且恰好在每个进程中也加载到同一地址。

如果启动Visual Studio,创建一个空项目,添加新的主.cpp文件,记下:

#include <windows.h>
void main()
{
}

然后编译这个程序,不要指望创建的可执行文件什么都不做,它没有。

也许 Visual C++ 编译器没有在目标文件中写下任何命令,因为源代码中没有命令,但链接器确实在可执行文件的主过程的开头写下了对user32.dllkernel32.dllgdi32.dllLoadLibrary调用

因此,在 Visual Studio 中编写的每个应用程序最初C++以相同的顺序对LoadLibrary进行多次相同的调用,而不管此可执行文件的源代码是什么。

源代码仅确定应在LoadLibrary调用之后出现的命令。

因此,每个Visual Studio C++应用程序在执行开始时加载LoadLibrary kernel32.dll,因此LoadLibrary在所有进程中相对于进程地址具有相同的入口点或地址。

从理论上讲,如果您链接一些不将 kernel32.dll 的 LoadLibrary 过程加载到程序内存中的某个 kernel32.lib,则可以使尝试注入程序的恶意程序注入器失败。

如果程序在执行期间

无法动态加载 dll,则注入器不能使程序在执行期间动态加载某些 dll,因为假定执行此操作的过程 LoadLibrary 中不存在。

因此,注入器创建的远程线程无法执行受害者内存中不存在的LoadLibrary

但攻击者有可能将VirtualAllocEx在受害者的内存中创建一些块,WriteProcessMemory一些可执行代码,然后CreateRemoteThread来执行它。

相关文章:
  • 没有找到相关文章