此程序重新映射它的加载映像(image),避免映像中页面保护属性通过NtProtectVirtualMemory函数被修改。可以配合这篇博文一同食用。
这个技术可以用在防止调试和Dump方面。
重映射要经过以下几个过程:
-
原先加载的映像(image)被复制到一个可执行的缓冲区,被称为 "重映射区域"(RemapRegion)。
-
在重映射区域内的重映射函数被定位和调用。
-
重映射函数创建了一个page-file-backed的区域(section)来存储重新映射的映像(image)。
-
重映射函数将上一步获得的Section进行映射(NtMapViewOfSection)并将原先加载的映像(image)内容复制到这个新的视图(View)中,然后这个新的视图(View)被取消映射(Unmap)。
-
重映射函数为每一个PE节区的相对虚拟地址作为视图的段偏移都进行重新映射,每个视图都使用 “SEC_NO_CHANGE”分配类型进行映射,以防止页面保护的改变。
-
重映射函数执行完成后,返回到被重映射后的视图。
下表是一个Image在使用这种技术重新映射前后的内存布局例子:
Address Size Info Type Protect Initial ======================================================================================= 0000000140000000 0000000000001000 selfremappingcode.exe IMG -R--- ERWC- 0000000140001000 000000000000F000 Reserved (0000000140000000) IMG ERWC- 0000000140010000 0000000000002000 ".text" IMG ER--- ERWC- 0000000140012000 000000000000E000 Reserved (0000000140000000) IMG ERWC- 0000000140020000 0000000000002000 ".rdata" IMG -R--- ERWC- 0000000140022000 000000000000E000 Reserved (0000000140000000) IMG ERWC- 0000000140030000 0000000000001000 ".data" IMG -RW-- ERWC- 0000000140031000 000000000000F000 Reserved (0000000140000000) IMG ERWC- 0000000140040000 0000000000001000 ".pdata" IMG -R--- ERWC- 0000000140041000 000000000000F000 Reserved (0000000140000000) IMG ERWC- 0000000140050000 0000000000001000 ".rsrc" IMG -R--- ERWC- 0000000140051000 000000000000F000 Reserved (0000000140000000) IMG ERWC-
Address Size Info Type Protect Initial ======================================================================================= 0000000140000000 0000000000001000 MAP -R--- -R--- 0000000140010000 0000000000002000 MAP ER--- ER--- 0000000140020000 0000000000002000 MAP -R--- -R--- 0000000140030000 0000000000001000 MAP -RW-- -RW-- 0000000140040000 0000000000001000 MAP -R--- -R--- 0000000140050000 0000000000001000 MAP -R--- -R---
- 映像中的每个PE节区必须与系统分配粒度对齐。 该程序使用
/ALIGN
链接器选项来实现这种对齐。