开始是一道CTF题加了UPX壳,利用堆栈平衡脱壳,import rec进行IAT修复后,程序不能正常打开。 后来才知道是开启了ASLR, 关闭后即可打开。 但有一个问题。 为什么开启了ASLR的程序在有壳时可以打开, 脱壳后就打不开了。 应该是加壳会对PE文件的重定位表进行压缩,在OD直接dump出的程序是丢失重定位表的, 而程序又是开启了ASLR,那程序自然会访问到没有进行重定位操作无效的地址而打不开
ASLR(地址空间布局随机化), 一种针对缓冲区溢出的安全保护技术. 从Windows Vsita(内核版本6.0)开始采用, 而Windows XP的内核版本是5.1, 所以我们在Windows XP下脱开启了ASLR 的壳是不会有这个问题的.
ASLR就是使我们的PE文件在每次载入内存时起始地址都会变得随机化, 增加恶意用户编写漏洞利用代码的难度(在之前知道dll文件在理想地址空间被占用了才会进行重定位)
对于ASLR功能我们系统(win10)是默认关闭的, 我们可以在设置的安全中心打开.
另外就是可执行文件的ASLR, 我们在我们的编译器上也可以选择是否引用该功能.
以VS编译器写一个程序, 分别生成开启了随机基址与未开启的的版本来分析. (一共有三个地方不同)
(1)未开启ASLR的程序的文件头的Characteristics会多一个 IMAGE_FILE_RELOCS_STRIPPED 0X0001 的属性, 经过查看官方文档可以看得到属性解释, 所以我们开启ASLR的程序不会有这个属性
下面看程序对比:
(2)开启了ASLR的程序的可选头的DllCharacteristics多了IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
0X0040的属性. 同样查看官方文档. 即重定位时需要的属性.
程序对比:
(3)开启了ASLR的程序会多一个 .reloc 节(一般普通的exe文件是不需要该节的, 用于开启ASLR的程序进行重定位, 当然我们关闭了ASLR也可以把这个节删了)
由上面的分析知道有3处不同, 其中上面的(1)中是开启了ASLR的程序少了 IMAGE_FILE_RELOCS_STRIPPED 0X0001属性, 我们增加上这个属性即可关闭ASLR(即 0102 -> 0103 / 对应属性打上勾即可). 另外(2)中是多了DLL can move的属性,删除这个属性,同样可以关闭ASLR(即 8140 -> 8100 / 对应属性取消打勾即可 )
下面示例在010编译器中修改数值来关闭ASLR.
以上是关于ASLR的分析及关闭, 如果开启了ASLR, 我们在脱壳之前还是先关闭它最好,也方便调试时IDA与OD中地址的对应(如果只是想地址对应, 也可以在IDA中启动时把Manual load勾上, 手动输入加载的基地址即可), 既然关闭了ASLR, 那多出的.reloc节也就没用了, 下面手动删除该节区(虽然有很多工具可以直接实现, 还是手动熟悉下PE结构)
首先每个节都对应一个节区头的, 那先从节区头开始. 使用010editor可以轻松在最后一节区头找到. 我们将其全部用0覆盖填充即可.(注: 不能直接删除了, 不然PE文件的很多属性会对应不上)
下面删除.reloc整个节区(一般这个节区都是新加的,所以在最后, 我们只要找到偏移地址直接删除到最后即可), 如图, 直接删除到最后即可. (这里的Size: 600h, 下面有用)
删除完后, 我们知道PE文件头的_IMAGE_FILE_HEADER的NumberOfSections的值一定要严格的与实际节区对应, 所以去修改 _IMAGE_FILE_HEADER的NumberOfSections使其减一.
最后还有修改一个属性, 就是PE文件头 _IMAGE_OPTIONAL_HEADER
的SizeOfImage, 修改为减去 .reloc节区后的大小 从上面我们知道.reloc大小是600h, 而该PE文件SectionAlignment(节在内存中的最小单位 (对齐单位) 一般为: 1000h)为1000h, 1000h > 600h. 以1000h对齐, 所以我们直接将SizeOfImage减去1000h即可. %20
如果想增加一个节区, 也可以使用同样的方法
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2020-8-19 14:18
被BIX编辑
,原因: