0%
毅种循环

模块 42 - 本地映射注入

恶意软件开发课程 - 本地映射注入


模块 42 - 本地映射注入#

[!IMPORTANT] 本知识库声明

本知识库由本人整理自互联网 MalDev Academy 泄露资源,并由本人手动翻译为中文,过程中增加了大量关键技术提示实践心得

  1. 内容完整性:并未修改任何核心代码与技术逻辑,仅做汉化与注释加强。
  2. 版权归属:原始知识产权归原作者/官方所有。
  3. 支持正版:本仓库仅供内部学习交流,如果您有经济能力,请务必支持正版课程
  4. 权利申诉:如相关内容侵犯了您的权益,请联系我,我将立即核实并删除。

本地映射注入#

简介#

到目前为止,在之前的所有实现中,我们都使用了“私有内存 (Private memory)”类型来在执行期间存储 Payload。私有内存是使用 VirtualAllocVirtualAllocEx 分配的。下图显示了在“本地线程劫持”实现中包含 Payload 的已分配私有内存。

图片
图片

映射内存 (Mapped Memory)#

由于私有内存分配在恶意软件中被广泛使用,因此安全解决方案对其进行了高度监控。为了避开这些通常被监控的 WinAPI(如 VirtualAlloc/ExVirtualProtect/Ex),映射注入(Mapping Injection)使用了 Mapped 内存类型。这种类型使用不同的 WinAPI,例如 CreateFileMappingMapViewOfFile

同样值得注意的是,VirtualProtect/Ex WinAPI 不能用于更改映射内存的内存权限。

💡 初学者提示:Private vs Mapped 内存

  • Private Memory(私有内存):就像是你在自己家里(进程内部)挖的一个坑,只有你能用。这是最常用的分配方式。
  • Mapped Memory(映射内存):就像是多个人共享的一块黑板。你可以把它映射到文件,也可以只在内存中创建。对于安全工具来说,监控“创建文件映射并映射视图”这种行为的频率通常比监控“分配私有内存”要低一些,因此更具隐蔽性。

本地映射注入#

本节解释执行本地映射注入所需的 WinAPI。

CreateFileMapping#

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   
);
c

此技术所需的 3 个参数解释如下。标记为不需要的参数可以设置为 NULL

  • hFile - 用于从中创建文件映射句柄的文件句柄。由于在实现中不需要从文件创建文件映射,因此可以改用 INVALID_HANDLE_VALUE 标志。微软对此标志的解释是:

如果 hFile 为 INVALID_HANDLE_VALUE,则调用进程还必须在 dwMaximumSizeHighdwMaximumSizeLow 参数中为文件映射对象指定大小。在这种情况下,CreateFileMapping 会创建一个指定大小的文件映射对象,该对象由系统分页文件(System Paging File)而不是文件系统中的文件支持。

设置此标志允许函数在不使用磁盘文件的情况下执行任务,而是根据 dwMaximumSizeHighdwMaximumSizeLow 参数指定的大小在内存中创建文件映射对象。

  • flProtect - 指定文件映射对象的页面保护。在此实现中,它将被设置为 PAGE_EXECUTE_READWRITE。请注意,这不会立即创建一个 RWX 段,而是指定它是可以在以后创建的。如果将其设置为 PAGE_READWRITE,那么以后就无法对映射的内存执行 Payload。
  • dwMaximumSizeLow - 返回的文件映射句柄的大小。该值将是 Payload 的大小。

MapViewOfFile#

MapViewOfFile 将文件映射对象的视图映射到进程的地址空间。它接受文件映射对象的句柄和所需的访问权限,并返回指向进程地址空间中映射起始位置的指针。

LPVOID MapViewOfFile(
  [in] HANDLE     hFileMappingObject,
  [in] DWORD      dwDesiredAccess,
  [in] DWORD      dwFileOffsetHigh,           // 不需要 - 设置为 NULL
  [in] DWORD      dwFileOffsetLow,            // 不需要 - 设置为 NULL
  [in] SIZE_T     dwNumberOfBytesToMap
);
c

此技术所需的 3 个参数解释如下。标记为不需要的参数可以设置为 NULL

  • hFileMappingObject - CreateFileMapping WinAPI 返回的句柄,即文件映射对象。
  • dwDesiredAccess - 对文件映射对象的访问类型,它决定了创建页面的页面保护。换句话说,即由 MapViewOfFile 调用分配的内存的权限。由于 CreateFileMapping 被设置为 PAGE_EXECUTE_READWRITE,因此此参数将同时使用 FILE_MAP_EXECUTEFILE_MAP_WRITE 标志,以返回有效的可执行且可写的内存,这正是复制 Payload 并在之后执行它所需的。

如果在 CreateFileMapping 中使用了 PAGE_READWRITE 标志,而在 MapViewOfFile 中使用了 FILE_MAP_EXECUTE 标志,那么 MapViewOfFile 将失败,因为尝试从一个仅标记为可读写的 CreateFileMapping 对象句柄创建可执行内存是不可能的。

  • dwNumberOfBytesToMap - Payload 的大小。

本地映射注入函数#

LocalMapInject 是执行本地映射注入的函数。它接受 3 个参数:

  • pPayload - Payload 的基地址。
  • sPayloadSize - Payload 的大小。
  • ppAddress - 指向接收映射内存基地址的 PVOID 的指针。

该函数分配一个本地映射的可执行缓冲区,并将 Payload 复制到该缓冲区,然后返回映射内存的基地址。

UnmapViewOfFile#

UnmapViewOfFile 是一个用于取消映射之前映射的内存的 WinAPI,此函数应在 Payload 完成执行后调用,而不是在它仍在运行时调用。UnmapViewOfFile 仅需要取消映射的视图的基地址,即上面函数中的 pMapAddress

演示#

分配映射内存缓冲区:

图片
图片

复制 Payload:

图片
图片

执行 Payload(为了简化演示,使用 CreateThread):

图片
图片


🎯 总结#

在本模块中,我们学习了:

  1. 映射内存 vs 私有内存:了解了规避传统内存分配监控的一种替代方法。
  2. 文件映射 API:掌握了 CreateFileMappingMapViewOfFile 的配合。
  3. 隐蔽性:映射内存通常被视为更“正常”的系统操作,相比 VirtualAlloc 具有更好的规避性。

💡 关键要点

  • 虽然我们在本地演示,但真正的威力在于多进程共享映射(下一个模块)。
  • 记住:映射内存的权限在 CreateFileMapping 时就决定了上限。
  • 勤于清理:Payload 执行完后,记得调用 UnmapViewOfFile

📚 下一步学习

下一个模块将介绍 Remote Mapping Injection。我们将学习如何利用这一机制将 Payload 跨进程映射到受害进程中,这是极其强大的注入手段!