尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Self-Remapping-Code 内存布局前后对比:一张图看懂 IMG 与 MAP 页面的关键区别

Self-Remapping-Code 内存布局前后对比:一张图看懂 IMG 与 MAP 页面的关键区别 Self-Remapping-Code 内存布局前后对比一张图看懂 IMG 与 MAP 页面的关键区别【免费下载链接】Self-Remapping-CodeThis program remaps its image to prevent the page protection of pages contained in the image from being modified via NtProtectVirtualMemory.项目地址: https://gitcode.com/gh_mirrors/se/Self-Remapping-CodeSelf-Remapping-Code 是一款面向 Windows 的 PE 映像自我重映射安全工具它的核心能力是程序启动后将自己搬进一个全新的内存位置并让NtProtectVirtualMemory 再也无法修改映像内任何页面的保护属性。本文将用内存布局的前后对比表带你从零看懂VirtualQuery输出中IMG 与 MAP 两种页面的关键区别理解这项反调试、反转储anti-dumping技术的工作原理。什么是 Self-Remapping-Code一页看懂自我重映射原理 一句话概括普通程序把自己的代码以文件映像IMG的方式映射到内存而 Self-Remapping-Code 会把自己卸载掉再以节区视图MAP的方式重新映射回来并且在映射时加上SEC_NO_CHANGE标志——从此页面保护被焊死任何修改保护属性的 API 调用都会失败。这套技术通常用于反调试调试器常用VirtualProtect给代码页开写权限来下断点重映射后这一步直接失败️反转储dump 工具依赖改写页面权限来读取受保护数据同样会被挡在门外。重映射前内存布局IMG 页面全景表重映射之前进程内存里躺着一份标准的 PE 映像。用VirtualQuery查询效果与调试器中!address类似能看到如下布局数据来自项目 README 中的实测输出地址大小信息类型保护属性初始保护0x00000001400000000x1000selfremappingcode.exeIMG-R---ERWC-0x00000001400010000xF000Reserved (0x…140000000)IMG未提交ERWC-0x00000001400100000x2000.textIMGER---ERWC-0x00000001400120000xE000Reserved (0x…140000000)IMG未提交ERWC-0x00000001400200000x2000.rdataIMG-R---ERWC-0x00000001400220000xE000Reserved (0x…140000000)IMG未提交ERWC-0x00000001400300000x1000.dataIMG-RW--ERWC-0x00000001400310000xF000Reserved (0x…140000000)IMG未提交ERWC-0x00000001400400000x1000.pdataIMG-R---ERWC-0x00000001400410000xF000Reserved (0x…140000000)IMG未提交ERWC-0x00000001400500000x1000.rsrcIMG-R---ERWC-0x00000001400510000xF000Reserved (0x…140000000)IMG未提交ERWC-三个值得新手注意的细节类型全是 IMG这块内存是加载器从磁盘映像文件直接映射出来的来源是 exe 文件本身。节与节之间隔着一段 Reserved 内存这是链接器/ALIGN:0x10000选项的作用让每个 PE 节都按系统分配粒度对齐main.cpp里通过#pragma comment(linker, /ALIGN:0x10000)设置对齐后节之间用保留页填充。初始保护是 ERWC-可执行可读可写这是关键伏笔——映像提交时初始保护非常宽松意味着之后可以被NtProtectVirtualMemory反复改写。重映射后内存布局MAP 页面全景表重映射完成后再次查询同一地址范围输出变成这样地址大小信息类型保护属性初始保护0x00000001400000000x1000PE 头MAP-R----R---0x00000001400100000x2000.textMAPER---ER---0x00000001400200000x2000.rdataMAP-R----R---0x00000001400300000x1000.dataMAP-RW---RW--0x00000001400400000x1000.pdataMAP-R----R---0x00000001400500000x1000.rsrcMAP-R----R---变化一目了然类型全部变为MAP——内存不再来自文件映像而是来自一个**页面文件支撑的节区section**的视图Reserved 间隙全部消失每个 PE 节独立映射、边界紧凑保护属性 初始保护且两者都被SEC_NO_CHANGE标志锁定。一张图看懂IMG 与 MAP 页面的 4 个关键区别 重映射前IMG整块文件映像映射 重映射后MAP页面文件节区视图 0x000000 ┌──────────────────────────┐ 0x000000 ┌──────────────────────────┐ │ PE 头 -R--- 初始ERWC- │ │ │ PE 头 -R--- ≡ 初始 -R--- │ ├──────────────────────────┤ ├────────┤ .text ER--- ≡ 初始 ER--- │ │ .text ER---可被改写 │ │ .text │SEC_NO_CHANGE 焊死 │ ┊ ├──────┬───────────────────┤ ├────────┤ .rdata -R--- ≡ 初始 -R--- │ ┊保留页 │ .rdata │ Reserved 未提交 │ ├────────┤ .data -RW-- ≡ 初始 -RW-- │ ┊(对齐填充) ├──────┴───────────────┤ ├────────┤ .pdata -R--- │ ┊ │ .data -RW-- │ │ .rsrc │──────────────────────────┤ ├──────────────────────────┤ └──────────────────────────────────┘ │ .pdata / .rsrc -R--- │ 类型 MAP6 个独立节区视图 └──────────────────────────┘ 无保留间隙VirtualProtect 必然失败 类型 IMG整块映射初始保护 ERWC- NtProtectVirtualMemory 可随时改写对比维度重映射前IMG重映射后MAP内存来源磁盘 exe 文件映像页面文件支撑的节区NtCreateSection映射粒度整个映像一次映射节间有 Reserved 间隙每个 PE 节独立映射为视图间隙消失初始保护统一的 ERWC-宽松与最终保护一致且更精确如 .text 为 ER---能否改保护✅NtProtectVirtualMemory可随时改写❌ 视图以SEC_NO_CHANGE映射改写直接失败核心结论IMG 页面的初始保护只是出厂默认值之后想怎么改就怎么改MAP 页面因为映射时带了SEC_NO_CHANGE保护属性在映射瞬间就被锁定之后任何修改尝试都会被系统拒绝。自我重映射 6 步走从复制映像到锁定保护整个重映射流程在SelfRemappingCode/remap.cpp的RmpRemapImage中实现策略共 6 步复制映像把整个 PE 映像复制到一块可执行可写的缓冲区称为 remap region因为接下来的操作需要在别处执行自己的代码定位并调用重映射例程找到缓冲区里的重映射例程副本并调用它此时跑的是拷贝原映像还在原地创建节区用NtCreateSection创建一个页面文件支撑的节区标志为SEC_COMMIT | SEC_NO_CHANGE作为新家整块拷贝数据把节区完整映射为一个视图把映像内容拷进去随后解映射按节重建映像先解映射原始映像然后对每个 PE 节分别调用NtMapViewOfSection用节的 RVA 作为节区偏移、SEC_NO_CHANGE作为分配类型将每个节映射回原来的基址 RVA 位置验证并返回程序会主动尝试VirtualProtect每个节——预期全部失败以此自证保护已锁定然后执行流交还给重映射后的映像临时缓冲区释放。应用场景反调试与反转储怎么用 ️挡调试器断点调试器给.text页加写权限PAGE_EXECUTE_READWRITE才能下硬件/软件断点。重映射后.text的视图保护不可更改此类操作直接失败。挡内存转储很多 dump 方案先改页面权限再整体读出映像。重映射后每个节都是独立 MAP 视图且保护被锁常规手段难以还原一份完整可执行的映像文件。自我保护验证程序自带校验逻辑RmppValidateRemappedImageProtection运行时就会自测一遍保护是否真的锁死日志里能看到结果。需要留意该机制依赖 PE 节按系统分配粒度对齐项目已用/ALIGN:0x10000处理且目前仅支持 x64 映像。源码导读3 个文件读懂核心逻辑文件职责SelfRemappingCode/main.cpp入口取模块基址 → 调用RmpRemapImage同时用#pragma comment(linker, /ALIGN:0x10000)强制节对齐SelfRemappingCode/remap.cpp核心校验对齐、复制节区、创建SEC_NO_CHANGE节区、按节重建映像、最后用VirtualProtect自测保护SelfRemappingCode/remap.h对外接口声明唯一的公开函数RmpRemapImage辅助文件还有SelfRemappingCode/ntdll.h声明NtCreateSection/NtMapViewOfSection等未公开 API和SelfRemappingCode/log.h简单的日志宏。工程文件为SelfRemappingCode/SelfRemappingCode.vcxproj解决方案为SelfRemappingCode.sln。快速上手编译运行 Self-Remapping-Code 教程 第 1 步获取源码git clone https://gitcode.com/gh_mirrors/se/Self-Remapping-Code第 2 步编译在 Windows 上安装 Visual Studio含 C 桌面开发工作负载然后msbuild SelfRemappingCode.sln /p:ConfigurationRelease /p:Platformx64⚠️ 必须使用x64平台——项目明确只支持 x64 映像。第 3 步运行并观察运行SelfRemappingCode.exe控制台会依次打印对齐校验、节复制、重映射例程执行、保护验证等日志。重点看最后一步程序对每个节尝试VirtualProtect并预期失败——日志中所有验证通过说明你的映像已经完成了从 IMG 到 MAP 的蜕变。第 4 步选做自己验证内存布局用调试器加载该程序在重映射例程执行前下断用内存查看功能对比重映射前后的区域你会亲眼看到类型从 IMG 变成 MAP、Reserved 间隙消失——和本文开头的两张表完全一致。总结记住这 3 句话IMG 页面来自文件映像、初始保护宽松ERWC-、保护可被NtProtectVirtualMemory随意改写MAP 页面来自节区视图、按 PE 节独立映射、保护与初始保护一致Self-Remapping-Code 的精髓在于用SEC_NO_CHANGE把保护属性在映射时锁死从而让反调试、反转储手段失效。看懂了这两张内存布局表你就掌握了这个项目最核心的安全思想——不是让页面更难改而是让页面改不动。【免费下载链接】Self-Remapping-CodeThis program remaps its image to prevent the page protection of pages contained in the image from being modified via NtProtectVirtualMemory.项目地址: https://gitcode.com/gh_mirrors/se/Self-Remapping-Code创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表