脱壳小白之ASPack
2020-03-23 01:41:05 Author: bbs.pediy.com(查看原文) 阅读量:433 收藏

                                                                            一个能走多远,不是他多会跑,而是他能否站在巨人的肩膀上!

                                                                                                                                                                        ----题记

         首先声明,本人是小白,大牛勿喷!ASPack教程很多,本文只是糟糠之作,记录一次脱壳小白的经历。

         某天,一个同是游戏爱好者的哥们笑滋滋的发我某游戏的一辅助,说想改点东西。一时好奇(在天朝,也只能对这些灰色产业好奇),手一痒拖进了PeiD,一看ASPack 2.12的壳;于是就花了点时间,继而有了本文。

         说起ASPack,大家都知道,是脱壳入门级的小壳,也是WIN32效率较高的壳。对于大牛,那时信手沾来,而且前辈们也总结了大量经验。比较有名的脱壳方式有两种:ESP定律和配对法。

         啥为ESP定律?这个得从WIN平台的函数说起。大家都知道,函数都是都是通过栈运来运行的,而栈有个特点,就是没出函数调用退出需平衡,所谓的平衡就是进去啥样,出来还得是啥样;而能做到这平衡操作的,就得用上两个比较特殊的寄存器:EBP和ESP,EBP是记录栈底的寄存器,是不动的;而ESP是活动,能上下移动;当函数操作完成后,ESP和EBP是相等的,这就是平衡,这里借用MallocFree的周老师的一张图来说明:


而所谓的加壳,无非是压缩,加花生指令来迷惑我们的眼睛,即便是这样,它也得释放执行函数,既然要执行函数,那么就必须得栈平衡,于是万能的ESP定律就是由此而来。

         对于匹配法(或许不太标准,姑且这么叫吧),通俗点将就是配对,既有进有去;对于ASPack,入口都是PUSHAP,既然有PUSH(进),那么必然有POP(出),不然不符合程序的规矩;所以咱们可以再程序中,搜索POPAD,一个程序中POPAD肯定很多,那么如何判断是我们要找的POPAD?对于这个问题,前辈们已有所总结:POPAD下有JP和RET的,是跳到OEP的概率很多。有了这经验,那么范围缩小了很多。

         了解了ASPack的脱壳流程,那么便可以开始脱壳了。脱壳前按照规矩,得说下环境,所用工具,壳类型等:

          脱壳环境:windowxp(为啥用XP,后面说)

         脱壳工具:OD,peid,exeinfope,DIE,IMPORTrec

         用到的工具:WINHEX,010EDIT,SISU,DEPENDS

         壳类型:ASPack 2.12 -> Alexey Solodovnikov

脱壳选择的系统之所以是XP,以方面是体积小配置低运行方便,更多是由于在XP以上的系统,微软为了防范那些大牛,加了两个号称历史转折点的大亮点:PG和ASLR(这两个是啥,可以问问度娘和必应)。这两个鸡肋的加入,无疑将80%的小白拦截在了破解的门外。

        说了那么多废话,那么便开始小白的脱壳之路:

        1.查壳。拖入PEID,壳类型如下:


        2.脱入OD。由于是DLL,拖入后会调用OD的loaddll.EXE来加载,点击是,然后会弹出如下框:

点否就行,然后就自动断在入口点,如下图:

        3. 看到熟悉的PUSHAD,为了方便,我们直接用匹配法(ESP定律教程很多,在此就不赘叙了)。在OD中CTRL+L,输入POPAD,寻找有JP和RET的地方,多次CTRL+L后,我们来到了如下地方:

很像,于是F2断点,F9运行,然后F8,走到RET,出掉断点,再F8跳出后数据如下:

我们看到的一串变量,别急,做如下操作,点击红框的菜单,就能看到熟悉的指令了:

抓换后,看到是不是很熟悉?第一条是push ebp,这基本上就能确定是此程序的OEP了(程序的OEP,一般是以 push ebp 和mov ebp esp这两句开始,由于程序是过程的,所以要确保堆栈平衡,为了保持平衡,要保存ESP的值,如果有疑问,可以用不同编译器,编译不同的EXE反汇编总结经验),然后可以单步调试继续确认。

        4.确定了OEP,下一步就该是DUMP。由于是DLL,OD自带的dump插件(直接不修改会DUMP失败)对新手来说理解有点困难(看篇幅,后面说);引用看雪老大的原话:DLL必须被相应的EXE进程加载到内存,OD里就是用loaddll.exe这个进程加载的。你Dump时,这个DLL进程必须到loaddll.exe所涉及到的DLL文件里找。这里也推荐使用loadPE。直接上LOADPE,操作如下:

转存后,生成了dump.dll(注意,DUMP时,必须OP必须停在OEP处)

        5.做到这一步,如果认为完成了,那么你就是高兴太早;不信,继续拖PEID,结果如下:


怎么还是显示ASPACK?难道他有两层ASPack壳?有疑问就对了,有疑问就有解决的动力和方向了。比较脱壳前的PEID数据后脱壳后的PEID数据,不难发现它们除了File Offset

不同,其他的显示的都一样,最重要的是Entrypoint(俗称入口点)也都一样了,这就有点说不过去了,那么肯定的要修复。如何修复?新的入口点又是啥?带着疑问我们回归OD和loadPE的dump界面。在OD中OEP一行的地址为009EEF90,这是壳解压后的绝对地址,而入口函数是一个偏移地址(如果用觉得地址,会存在被占用的情况),这个偏移地址要减除程序运行的基地址,基地址是多少?其实4中的图已经告诉我们了:镜像基地址,看到此行为00910000,那么到底是不是00910000?我们可以再OD中查看。输入命令:dd 00910000,并在数据窗口右键,如下选择:


得到如下显示:


是不是看到了熟悉的味道?对PE结构,那么可以确定基地既是00910000。如是Entrypoint就出来了 Entrypoint = 009EEF90 – 00910000 = 00DEF90。拖入LordPE,修改如下,保存:


再次拖入PEID中,发现变了,变成了Nothing found,看到这个有人高兴有人心慌,高兴的是认为这个壳脱了,心慌的是可能PEID无法检测。换个工具试试?这里使用exeinfope,拖入之,结果显示Unknown DLL  - First section Delphi  NOT Packed,比PEID好点。至少显示了Delphi(PEID深度扫描也可显示),点击界面上的PE,可以看到Import还在.aspack段:


这个导入表肯定有问题,需要修复,如何修复,又的回到OD。

       6. 在程序中系统函数调用,如何找?只能单不,看到CALL F7(注意别脱离了用户空间,否则白找了),终于皇天不负有心人,N个F7后看到如下代码:

看到JMP 到系统函数了,那么地址多少?F7进入,显示0x9FE284,如是DD 0x9FE284,咋眼一看,好多啊:


那么什么是结束,什么是开始?这个时候可以借助Depends,将加壳的dll拖入:

可以看到这个DLL所依赖的所有系统DLL,可根据这个,在DD 0x9FE284后的数据窗口上下查找,知道包含依赖的DLL(上下都必须以00000开头或结束),找到开头地址为:009FE190,结束地址为:009FE8C8,大小为:009FE8C8 - 009FE190 = 738。

        7. 找到依赖库在009FE190处,接下来就是修复了,修复需借助工具ImportREC_fix,操作如下:

输入前面找的OEP:000DEF90,尝试自动找TAI(导入地址表,点击IAT AutoSearch),没办法,只能手动输入了,TAI的RAV = 009FE190 –基地址,而基地址是多少?正常情况下应该是00910000,但是输入DE190后,显示内存不能read。这是啥原因?仔细观察ImportRec,发现如下图所示(此处的分析是一个误区,后面会给出正确的处理方法):

Image Base 竟然是00400000(怎么会是400000?不应该是910000,暂且先不管,我们是为了找TAI),00400000就00400000吧,相减得到RVA为5FE190,写入RVA和大小,点击Get Imports,终于守得云开见月明,看到了数据:

兴奋的点击FIX DUMP,选择刚刚通过loadPE dump的dumped.dll,结果失望的发现打开失败显示不能match RVA,这是为啥?分析005FE190这个RVA都超过了dump的镜像大小,如何写的进,那么得修改,修复的方法很简单,点击Save Tree保存文件后,将5F换成00,然后Load Tree,如下:

OK,Fix Dump成功后生成一个dumped_.dll文件。拖入Exeinfo PE,竟然奇迹(为啥说奇迹,看完后面就知道)般的显示出了信息:

如是兴高采烈的替换文件,运行某辅助的主程序,结果很失望的显示加载XXX.dll失败。失败了竟然,难得DLL不能加载,于是写了个DEMO,这是load这个dll,可是DEMO load成功的啊,于是又猜测:难得主程序有效验?继而OD,IDA上主程序,可结果并未发现异常,尝试着用其他的dll替换加载的dll,竟然都能成功,于是茅塞顿开,脱壳的DLL可能有问题。拖入WINHEX,发现大量的FF,大量的FF是什么?拖入010EDIT,分析PE结构后,发现如下:

大量的FF是,reloc段,同时RelocTable大小为0。Reloc为重定位区,也就是说,脱壳后程序需要修复重定位。

        8.重定位的修复。继续上OD,修复重定位,那么我们就得找到修改重定位的地方,就得研究此壳的原理。好在大神很多,善良的大神也不少,直接给咱们小白找出了规律(这是个体力,运气和经验活,感兴趣的小白可以自行OD调试寻找),ASPack壳修改重定位的地方在

                    mov ecx,dword ptr ds:[esi+4]

                    sub ecx,8

                    shr ecx,1

此处。直接CTRL+s,搜索定位到此处,如下引用了某大神的分析和经验:

                           

将A7524C的代码指令NOP掉后,记录重定位表的RVA= 000F2000,起始地址结束地址得到重定位表大小为 00A12CB0 - 00A02000 = 10CB0。于是找到出掉断点,找到OEP,重新用LoadPE dump(注意00A7524C处的指令要NOP掉),拖入LoadPE,修改操作如下:

重新用用Import REC修复OEP和IAT,此处注意修改ImportRec的Option,出掉红框的地方

你会发现,红框的地方已经变成了DLL本身的基地址,这样修复不用再麻烦的修改了,直接点击IAT AutoSearch也不会提示错误了。

输入上面算到的地址,结果如下:

Fix Dump成功,拖入后PEID和Exeinfo PE,都显示正常,到这一步,差不多改完成了,可我们似乎忽略了什么?因为此时这样,还是load失败,拖入LoadPE,发现镜像基址为00400000,这显然不对,因为我们上门已经确认基地址为00910000,于是修改之,运行主程序,OK加载成功,拖入Sisu,看到了内部隐藏的庐山真面目:

         呼,泪流满面啊,接下来就是IDA的事了,于是继续塞尔达,拯救公主,保卫地球!

参考地址:

https://bbs.pediy.com/thread-28704.htm

https://bbs.pediy.com/thread-19497.htm

https://www.pediy.com/kssd/pediy06/pediy6738.htm

2020安全开发者峰会(2020 SDC)议题征集 中国.北京 7月!

最后于 8小时前 被loveOpal编辑 ,原因:


文章来源: https://bbs.pediy.com/thread-258265.htm
如有侵权请联系:admin#unsafe.sh