查看原文
其他

加密壳之ACProtect系列通杀

Risks@MR安全团队 看雪学苑 2022-07-01

本文为看雪论坛精华文章

看雪论坛作者ID:Risks





背景


在经过几天的研究和之前脱壳学习的积淀,终于是把ACProtect系列的脱壳方法和IAT修复部分给搞定了,趁着研究有些成果,将整个脱壳和IAT修复过程做个记录,整理整理就有了本文的诞生。

ACProtect是个很老的加密壳了,现在也已经挂掉不再更新了,更多的是做研究脱壳的一个基础,经过深入研究和学习,让我对加壳概念有了更深入的理解,欢迎各位大佬一起讨论脱壳手法。

值得额外提一点的是,ACProtect是Delphi编写的,经过测试发现对Delphi程序的支持是最好的,其他语言编写的程序经过ACProtect加壳后可能导致程序本身异常退出,这可能也是ACProtect没落的原因之一吧。

有网络喷子可能会喷,ACProtect系列的脱壳机也有了,为啥还要研究啊?如果只是过来扯淡的,请绕道,我只是做脱壳研究,并不想扯皮。别人的东西始终是别人的,只有自己的东西才是自己的,好好体会这句话你就知道了。





两次断点法


首先来看一下原始delphi程序的oep情况。



接下来将一下两次断点法,也被称为内存断点。其原理是利用内存断点修改对应内存的访问权限,当程序执行的时候,由于内存的访问权限问题而出发异常被调试器捕获进而成功中断在对应的内存区域,这是我自己对内存断点的看法,欢迎大家讨论研究。

现在脱壳开始,第一次内存断点一般选择rsrc或者idata段,可以使用快捷键f2设置内存断点,然后shift+F9让程序执行起来。



当内存断点出发后,程序停留的位置如下所示。



紧接着在code段设置第二个内存断点,同样的shift+f9执行。



接下来就是见证奇迹的时刻了~


对比之前原始的oep发现好像少了一部分,原来是存在stolen code。



暂时先不管被偷取的oep,使用importrec先来看看IAT的情况,发现有很多无效,看样子应该是IAT被加密处理了。



于是现在就面临着这样两个问题,一个是存在stolen code,另一个是IAT被加密保护了。

当然是选择迎难而上了。





Stolen code


首先来看一看stolencode,不过之前从没有搞过,怎么入手呢?这个时候前人的研究就显得额外的有意义了。

论坛一搜,一大堆关于ACProtect相关的资料。



在这些众多的资料,找到了几份关于stolencode的,其中以wynney大佬针对ACProtect1.09版本的精华帖为例子ACProtect1.09。

其中使用了两种技术,一种是利用了CreateToolhelp32SnapshotAPI来进行反调试,另外一种是利用异常来实现。经过测试后,感觉利用异常来更稳定,可以符合ACProtect的多个版本。

首先设置od的异常属性,除了int3以外的,其他全选。



首先程序入口点典型的可以esp定律。



单步执行之后,这里为了好操作,在下方命令栏输入hr esp。


将程序运行起来,会中断在一个int3断点附近,这时注意栈上的数据,这里栈顶是SHE异常处理链的指针,SE句柄,就是异常处理函数。

如果不知为什的么小伙伴可以去查一下异常处理相关联的东西就会明白啦。



通过SE句柄,定位到内存,设置内存访问断点。



同样的使用shift+f9,程序停留在这样的一个地方。



在当前位置设置f2断点,并shift+f9继续执行,中断在这样的地方。



继续在当前位置继续设置f2断点,同样shift+f9执行,停留在这个位置。



当f2断点执行后,会在od下方看到一个提示框,其中应该还有之前设置的内存断点的作用,其实我自己对这两个f2断点不是很理解为什么,是为了追溯到来源还是什么?这是我没弄明白的地方,知道为什么的兄弟,可以帮我提点我一下么~,感激不尽。


最后取消两个f2断点,清除掉内存断点。在retn处f4。



此时由于开始头部下了硬件断点,接下来运行后,就会停留在被抽取的代码位置处。



这时就可以dump文件了,不过这个时候的oep却不能写这个位置,否则找不到对应的IAT信息,但是如果是通过修补oep数据的方式会导致程序出问题,所以最好是在这里dump文件,然后手动修复IAT即可。


到这里基本上关于ACProtect的stolen code部分就算结束了。





IAT加密处理


相比之前的stolen code,手动处理IAT加密才是真的难搞,其一有现成的importrec的修复插件,但是这插件怎么说呢,老容易卡死,就让我萌生了自己处理IAT的想法,其二是找了很久都没有找到相关IAT加密处理的资料。

通过google,终于还是找到了IAT加密处理的部分,不过这帖子是全英的,我看完之后还是有所感悟,终于还是通过各方面的调试成功破开了ACProtect的IAT加密部分。

修改od的调试选择,全部选择:



同样的还是先使用内存断点法进行rsrc段的解密,同时查看0x401000段,发现存在一些有意思的东西:



这应该就是IAT存储的位置了,随意选择一个,以0x4050d8为例子,设置内存写入断点,执行起来。(不要问我为什么不用硬件断点,我肯定用了啊,当然是没效果,不然我为什么用内存断点)



这里就是IAT写入的关键点,经过多次调试发现,这部分代码还需要二次解密,如果这里下断点f2断点,之后是无法中断下来的,那么现在怎么办?通过我对acptotect1.09g、ACProtect1.32、ACProtect1.41以及ACProtect2.0四个版本的测试发现了一个通用的定位方法。

找到IAT写入关键点之后,往上找,找到第一次出现retn的地方,不要问我为什么,问就是不知道(bbll而已)。真不要问,我是自己测试出来的,就像被人给你一个特征码是一样的道理。



通过这个retn之后,单步缓慢执行,等待之后的代码解码。当你看到cmp eax和MessageBoxA做比较的时候,那么恭喜你,你已经找到了IAT加密的部分了,修改掉je跳转为jmp,不过这个地址可能需要做更改。

具体改不改,看之后跳转的地址是不是lea eax开始,如果不是则不需要修改je的跳转地址,如果是则需要修改地址为lea eax地址下一条指令的地址。



接下来的je就是整个IAT的magic jmp了,处理掉这个je,所有的IAT就不会被加密了,特征就是通过cmp [ebp+address],0。

不确定的话,可以看下是否是跳转到mov dword ptr ds:[edi],eax。如果是就表示这就是magic jmp跳转。



这个时候,就可以放任程序跑起来了,毕竟我只是要一个完整的IAT信息而已。



ok,全部有效,修复下文件,完美~。





总结


作为曾经对新手极具杀伤力壳,现如今却成为了练手的基本功,脱壳与加壳就如同加密与解密,彼此相辅相成,亦或是盾与矛的关系。从ACProtect中也学到了一些关于脱壳的心得,也是略有所成吧。有缘我们下次还会再见面。

加壳后的各个版本文件,我己经打包放在附件中了,想自己测试的可以自行下载。

(本文经授权转载自 安全分析与研究)



- End -



看雪ID:Risks

https://bbs.pediy.com/user-home-830514.htm

  *本文由看雪论坛 Risks 原创。



推荐文章++++

* 对一篇反沙箱文章的分析学习小记

* 使用msfvenom生成恶意APP并对该APK进行拆包分析

* 内核APC调用Risks过程学习笔记

* 探究 Process Explorer 进程树选项灰色问题

* Linux Kernel Pwn 学习笔记(栈溢出)







公众号ID:ikanxue
官方微博:看雪安全
商务合作:wsc@kanxue.com



求分享

求点赞

求在看


“阅读原文”一起来充电吧!

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存