一年多前,在汉化新世纪论坛看到Volx关于Aspr壳的pre-dip跟踪和处理的帖子,获益非浅。
汉化新世纪论坛多次被黑,资料也丢失了,实在可惜。
在这里只是把几个帖子内容重复叙述。
何谓pre-dip?我只能说一个大概,就是在程序代码解压后达到OEP之前壳在程序放入壳的地址指针,达到程序后返回壳执行相应的功能。
pre-dip按照分布的位置可分为四个部分,第一个部分有6个Call EAX和一个Call EBX(也有Call [xxxxxx]的形式。
位置在第21个异常(准确位置以堆栈窗出现硬盘指纹为准)
硬盘指纹在我的机子上看到是这样"mIjMiACQQJ8=",每部机子的代码都不一样,但字节长度一样,以“=”结尾。
到达异常后在下方设断点,按Shift+F9跳出异常后按F8单步往下走就能看到如下的结构,每个Aspr壳都有这样的结构,除了内存地址不同其它的结构都是一样的。
011BAA53 A1 1CC71B01 MOV EAX,DWORD PTR DS:[11BC71C]
011BAA58 8B40 0C MOV EAX,DWORD PTR DS:[EAX+C]
011BAA5B FFD0 CALL EAX <<==pre-dip1
011BAA5D A1 1CC71B01 MOV EAX,DWORD PTR DS:[11BC71C]
011BAA62 8B40 30 MOV EAX,DWORD PTR DS:[EAX+30]
011BAA65 85C0 TEST EAX,EAX
011BAA67 74 29 JE SHORT 011BAA92
011BAA69 8B15 1CC71B01 MOV EDX,DWORD PTR DS:[11BC71C]
011BAA6F E8 C8FCFFFF CALL 011BA73C
011BAA74 68 90551B01 PUSH 11B5590
011BAA79 A1 1CC71B01 MOV EAX,DWORD PTR DS:[11BC71C]
011BAA7E 8B40 30 MOV EAX,DWORD PTR DS:[EAX+30]
011BAA81 FFD0 CALL EAX <<==pre-dip2
011BAA83 68 90551B01 PUSH 11B5590
011BAA88 A1 1CC71B01 MOV EAX,DWORD PTR DS:[11BC71C]
011BAA8D 8B40 2C MOV EAX,DWORD PTR DS:[EAX+2C]
011BAA90 FFD0 CALL EAX <<==pre-dip3
011BAA92 A1 1CC71B01 MOV EAX,DWORD PTR DS:[11BC71C]
011BAA97 8378 28 00 CMP DWORD PTR DS:[EAX+28],0
011BAA9B 74 0F JE SHORT 011BAAAC
011BAA9D 68 60561B01 PUSH 11B5660
011BAAA2 A1 1CC71B01 MOV EAX,DWORD PTR DS:[11BC71C]
011BAAA7 8B40 28 MOV EAX,DWORD PTR DS:[EAX+28]
011BAAAA FFD0 CALL EAX <<==pre-dip4
011BAAAC A1 1CC71B01 MOV EAX,DWORD PTR DS:[11BC71C]
011BAAB1 8378 2C 00 CMP DWORD PTR DS:[EAX+2C],0
011BAAB5 74 0F JE SHORT 011BAAC6
011BAAB7 68 30561B01 PUSH 11B5630
011BAABC A1 1CC71B01 MOV EAX,DWORD PTR DS:[11BC71C]
011BAAC1 8B40 2C MOV EAX,DWORD PTR DS:[EAX+2C]
011BAAC4 FFD0 CALL EAX <<==pre-dip5
011BAAC6 A1 1CC71B01 MOV EAX,DWORD PTR DS:[11BC71C]
011BAACB 8378 30 00 CMP DWORD PTR DS:[EAX+30],0
011BAACF 74 0F JE SHORT 011BAAE0
011BAAD1 68 FC551B01 PUSH 11B55FC
011BAAD6 A1 1CC71B01 MOV EAX,DWORD PTR DS:[11BC71C]
011BAADB 8B40 30 MOV EAX,DWORD PTR DS:[EAX+30]
011BAADE FFD0 CALL EAX <<==pre-dip6
011BAAE0 8B15 C4C51B01 MOV EDX,DWORD PTR DS:[11BC5C4]
................
011BAB43 8B15 1CC71B01 MOV EDX,DWORD PTR DS:[11BC71C]
011BAB49 E8 EEFBFFFF CALL 011BA73C
011BAB4E 8B1D 1CC71B01 MOV EBX,DWORD PTR DS:[11BC71C]
011BAB54 8B1B MOV EBX,DWORD PTR DS:[EBX]
011BAB56 FFD3 CALL EBX <<==pre-dip7
011BAB58 8D55 C8 LEA EDX,DWORD PTR SS:[EBP-38]
011BAB5B E8 20C0FEFF CALL 011A6B80
011BAB60 8B55 C8 MOV EDX,DWORD PTR SS:[EBP-38]
011BAB63 A1 FCC51B01 MOV EAX,DWORD PTR DS:[11BC5FC]
011BAB68 E8 738AFEFF CALL 011A35E0
011BAB6D EB 0A JMP SHORT 011BAB79
跟进Call EAX 后是位置在程序领空,能看到类似的结构
004FE148 55 PUSH EBP
004FE149 8BEC MOV EBP,ESP
004FE14B 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
004FE14E A3 D4085200 MOV DWORD PTR DS:[5208D4],EAX <<=看EAX的值指向壳地址。
004FE153 5D POP EBP
004FE154 C2 0400 RETN 4
EAX的值就是壳的地址指针,越过OEP后会返回到壳地址执行相应的功能。
第一部分有7个pre-dip,有相应的7种功能。
pre-dip1(以在壳的位置排序)
硬盘指纹,越过OEP后会返回到壳检测是否有硬盘指纹,脱壳后没有这个地址,会造成异常。
有部分程序以硬盘指纹来计算注册码。
应对:在程序领空找一个空地,最好是块的最后,填入硬盘指纹,然后把这个地址放入相应的位置。
假设硬盘指纹放在521FF0处,那么5208D4填入F01F5200(注意高低位的顺序)。
pre-dip2
指向壳的一个RET(C3),如果单独使用是简单检测壳是否存在。
应对:在程序领空找一个RET让指针指向此处。
pre-dip3
同pre-dip2
pre-dip4
校验注册码,与硬盘指纹计算后生成一个密匙,在部分壳里,会解压N段代码起到防止脱壳的功能。
应对:越过OEP后对此地址设断点监视运行时是否解压代码,如果解压代码等代码解压完后,dump下这段代码,修补dump.exe相应的位置,并把指针指向程序的一个RET.如果没有解压代码,把指针指向当时的EIP例如上例在5208D4处填入4EE14F00.
pre-dip5
已经注册的程序在执行重要功能时返回壳解密N段关键代码,这是Aspr强悍之处,使用此功能如果没有key很难破解,曾经在001论坛看到zombieys放过一个例子,Awmaw1.55;Awmaw1.6;Awmaw1.81其中Awmaw1.81在不用key的情况下根据Awmaw1.55;Awmaw1.6还原Awmaw1.81的解密代码。
应对:越过OEP后对此地址设断监视,等N段代码解密完成后dump下这段代码修补dump.exe相应的代码,并把相应的指针指向程序的RET,但要注意堆栈值,如果有变必须做相应的调整。
pre-dip6
和pre-dip5是成对出现,功能是对解密代码重新加密。
应对:解密后的代码一般会出现pre-dip6的指针,跟踪加密完成后的堆栈值,然后做相应的处理,CALL RET
或nop掉或调整堆栈指针。如果有pre-dip5;pre-dip6就不必理会pre-dip2;pre-dip3因为地址是相同的。
pre-dip7
这个比较特别,起破坏作用,运行后修复难度加大,具体例子可参考jingulong在001论坛的《Afslock1.60a脱壳》的帖子。
第22个异常中断后是注册名的pre-dip
第23个异常后两个pre-dip第一个是时间计数,第二个是使用次数计数。
第24个异常有两个pre-dip这是生死转折,试用时间和使用次数已过会跳到第一个pre-dip,用工具脱壳往往也会
跳到第一个pre-dip。
另外还有一处隐藏的pre-dip(aspr强悍之处),例如水晶按钮在第22异常后如果是注册版会引发新的异常中断后有一排功能相同的pre-dip,像这种情况除非是能算出key了。
由于水平有限很难表达清楚,不足之处望各位指正。
再次感谢VolX的精彩帖子。