Mapping injection
字数 1743 2025-08-06 12:20:51
映射注入(Mapping Injection)技术详解
1. 映射注入概述
映射注入是一种内存注入技术,通过创建内存映射对象来绕过传统的进程注入方法。其核心思想是:
- 创建内存映射对象本质上属于申请一块物理内存
- 申请的物理内存可以通过系统函数直接映射到进程的虚拟内存
- 避免了使用
VirtualAllocEx和WriteProcessMemory等传统注入函数
2. 用户层函数实现
2.1 核心API函数
CreateFileMappingA
HANDLE CreateFileMappingA(
[in] HANDLE hFile,
[in, optional] LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
[in] DWORD flProtect,
[in] DWORD dwMaximumSizeHigh,
[in] DWORD dwMaximumSizeLow,
[in, optional] LPCSTR lpName
);
hFile: 文件句柄,通常填INVALID_HANDLE_VALUE创建匿名映射对象flProtect: 内存映像保护类型(如PAGE_EXECUTE_READWRITE)dwMaximumSizeHigh/Low: 文件映射对象大小(高/低32位)lpName: 文件映射对象名称(可选)
OpenFileMappingA
HANDLE OpenFileMappingA(
[in] DWORD dwDesiredAccess,
[in] BOOL bInheritHandle,
[in] LPCSTR lpName
);
- 打开已命名的文件映射对象
lpName必须与CreateFileMappingA中指定的名称匹配
MapViewOfFile
LPVOID MapViewOfFile(
[in] HANDLE hFileMappingObject,
[in] DWORD dwDesiredAccess,
[in] DWORD dwFileOffsetHigh,
[in] DWORD dwFileOffsetLow,
[in] SIZE_T dwNumberOfBytesToMap
);
- 将内存空间映射到调用进程的内存空间
hFileMappingObject:CreateFileMappingA或OpenFileMappingA返回的句柄dwDesiredAccess: 保护类型(如FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE)dwNumberOfBytesToMap: 映射的字节数(0表示映射整个文件)
UnmapViewOfFile
BOOL UnmapViewOfFile(
[in] LPCVOID lpBaseAddress
);
- 解除文件映射对象的映射
2.2 基本实现示例
写入程序(Write.cpp)
#include <windows.h>
#include <iostream>
using namespace std;
int main() {
unsigned char buf[] = "HelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHello";
// 创建文件映射对象
HANDLE CreateFileM = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, 0, sizeof(buf), "Mapping");
// 映射到当前进程
LPVOID Address = MapViewOfFile(CreateFileM, FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
// 写入数据
memcpy(Address, buf, sizeof(buf));
// 清理
UnmapViewOfFile(Address);
CloseHandle(CreateFileM);
}
读取程序(Read.cpp)
#include <windows.h>
#include <iostream>
using namespace std;
int main(){
// 打开映射对象
HANDLE OpenFileM = OpenFileMappingA(FILE_MAP_READ, FALSE, "Mapping");
// 映射到当前进程
LPVOID Address = MapViewOfFile(OpenFileM, FILE_MAP_READ, 0, 0, 0);
// 读取数据
wcout << "[+] Success read: " << (char*)Address << endl;
// 清理
UnmapViewOfFile(Address);
CloseHandle(OpenFileM);
}
2.3 进程注入实现
基本流程:
- 使用
CreateFileMappingA创建文件映射对象 - 使用
MapViewOfFile映射到本地进程内存空间 - 将shellcode写入内存空间
- 使用
MapViewOfFile2或MapViewOfFile3映射到目标进程 - 执行shellcode
示例代码:
#include <windows.h>
#include <iostream>
#pragma comment(lib, "onecore.lib")
using namespace std;
int main() {
unsigned char buf[] = ""; // shellcode
// 创建目标进程
STARTUPINFO si;
PROCESS_INFORMATION pi;
CreateProcessA(NULL, (LPSTR)"notepad.exe", NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
// 创建文件映射对象
HANDLE CreateFileM = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, 0, sizeof(buf), NULL);
// 映射到当前进程
LPVOID MapView = MapViewOfFile(CreateFileM, FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
// 写入shellcode
memcpy(MapView, buf, sizeof(buf));
// 映射到目标进程
LPVOID MapView2 = MapViewOfFile2(CreateFileM, pi.hProcess, 0, NULL, 0, 0, PAGE_EXECUTE_READWRITE);
// 执行shellcode
// ...
// 清理
UnmapViewOfFile(MapView2);
UnmapViewOfFile(MapView);
CloseHandle(CreateFileM);
CloseHandle(pi.hProcess);
}
3. 内核层实现
3.1 核心系统调用
NtCreateSection
__kernel_entry NTSYSCALLAPI NTSTATUS NtCreateSection(
[out] PHANDLE SectionHandle,
[in] ACCESS_MASK DesiredAccess,
[in, optional] POBJECT_ATTRIBUTES ObjectAttributes,
[in, optional] PLARGE_INTEGER MaximumSize,
[in] ULONG SectionPageProtection,
[in] ULONG AllocationAttributes,
[in, optional] HANDLE FileHandle
);
SectionHandle: 接收节对象句柄DesiredAccess: 访问权限MaximumSize: 内存映射文件对象的最大大小SectionPageProtection: 页面保护属性AllocationAttributes: 分配属性标志(SEC_XXX)FileHandle: 文件对象句柄(可为NULL)
NtMapViewOfSection
NTSYSAPI NTSTATUS NtMapViewOfSection(
[in] HANDLE SectionHandle,
[in] HANDLE ProcessHandle,
[in, out] PVOID *BaseAddress,
[in] ULONG_PTR ZeroBits,
[in] SIZE_T CommitSize,
[in, out, optional] PLARGE_INTEGER SectionOffset,
[in, out] PSIZE_T ViewSize,
[in] SECTION_INHERIT InheritDisposition,
[in] ULONG AllocationType,
[in] ULONG Win32Protect
);
SectionHandle: 节对象句柄ProcessHandle: 目标进程句柄BaseAddress: 接收视图基址的指针CommitSize: 初始提交区域大小Win32Protect: 保护属性(如PAGE_READWRITE)
3.2 直接系统调用实现
由于EDR可能挂钩这些API,可以直接进行系统调用:
NtCreateSection的系统调用号:0x4ANtMapViewOfSection的系统调用号:0x28
实现思路:
- 使用
NtCreateSection创建内存映射对象 - 使用
NtMapViewOfSection映射到本地进程并写入数据 - 再次使用
NtMapViewOfSection映射到目标进程 - 执行shellcode
4. 防御与检测
映射注入技术的防御和检测点:
-
监控内存映射行为:
- 异常的内存映射对象创建
- 跨进程的内存映射操作
-
检测系统调用:
- 直接系统调用(特别是
NtCreateSection和NtMapViewOfSection) - 不寻常的系统调用序列
- 直接系统调用(特别是
-
行为分析:
- 创建内存映射后立即写入可执行代码
- 将内存映射映射到多个进程
-
保护措施:
- 限制进程创建内存映射的权限
- 监控跨进程的内存操作