• 标 题:Asprotect1.23rc4之BadCopy脱壳+修复
  • 时 间:2004年2月22日 02:44
  • 时 间:David
  • 链 接:http://bbs.pediy.com

【脱文作者】 weiyi75[Dfcg]

【作者邮箱】 weiyi75@sohu.com

【作者主页】 Dfcg官方大本营
 
【使用工具】 Ollydbg1.10b,ImportREC1.6F,LoadPe
 
【破解平台】 Win2000/XP
 
【软件名称】 BadCopy v3.73.0106

【下载地址】 http://soft.winzheng.com/SoftView/SoftView_19156.htm

【软件简介】  BadCopy软件可以在不需要人工干预的情况下帮您读出CD-ROM或磁盘上的坏文件。效果显著,还具有智能修复的功能,最大程度挽回您的损失。新增或加强了以下特别功能:1、优化的算法,保证修复拯救数据更快更全。2、支持文件夹直接复制,您甚至可以直接把整个逻辑盘完整复制到另一个文件夹下。3、可以自由定制BadCopy的各项纠错参数,保证能高效,最大限度的挽救您的宝贵数据。4、可以直接对隐含或系统文件进行操作。5、文件操作安全性增强,危险操作先行提示,避免不必要的损失。6、可以直接在BadCopy里面运行或打开程序。 
 
【软件大小】 847K

【加壳方式】 ASProtect 1.23 RC4 - 1.3.08.24 -> Alexey Solodovnikov

【破解声明】 我是一只小菜鸟,偶得一点心得,愿与大家分享。

【破解目的】 模拟跟踪寻找Stolen Code具体内容或Oep入口。

通过二哥=weiyi75=David作品Asprotect1.23rc4之Dephi语言篇经验,脱壳修复这个软件易如反掌。

复习一下,寄存器EBP=0012FFF0   //这是程序停在入口点EBP的值,其它Dephi语言或编程语言这里的EBP值全部相同,这又说明什么,当Asprotect运行到这里或Stolen Code做手脚时EBP的值就为EBP=0012FFF0,我们来具体试试。

OD异常设置不忽略内存异常,其余全部忽略,载入程序,用插件隐藏OD。

00401000 >  68 0180BF00     PUSH BadCopy.00BF8001          //加壳程序入口点,F9运行

00401005    E8 01000000     CALL BadCopy.0040100B

0040100A    C3              RETN

0040100B    C3              RETN

0040100C    14 D4           ADC AL,0D4

0040100E    7B CD           JPO SHORT BadCopy.00400FDD

00401010    E7 4A           OUT 4A,EAX                               ; I/O 命令

00401012  - 77 95           JA SHORT BadCopy.00400FA9

00401014    E8 7AEB4A1A     CALL 1A8AFB93

00401019    D36B 0B         SHR DWORD PTR DS:[EBX+B],CL

0040101C    C8 C33A68       ENTER 3AC3,68

00401020  - E9 FB56C317     JMP 18036720

00401025    8C03            MOV WORD PTR DS:[EBX],ES

00401027    4D              DEC EBP

00401028    9D              POPFD

........................................................................

 

内存异常

 

015141A4    3100            XOR DWORD PTR DS:[EAX],EAX

015141A6    EB 01           JMP SHORT 015141A9

015141A8    68 648F0500     PUSH 58F64

015141AD    0000            ADD BYTE PTR DS:[EAX],AL

015141AF    00EB            ADD BL,CH

015141B1    02E8            ADD CH,AL

015141B3    0158 68         ADD DWORD PTR DS:[EAX+68],EBX

015141B6    6C              INS BYTE PTR ES:[EDI],DX                 ; I/O 命令

015141B7    AF              SCAS DWORD PTR ES:[EDI]

015141B8    50              PUSH EAX

015141B9    0168 14         ADD DWORD PTR DS:[EAX+14],EBP

015141BC    42              INC EDX

015141BD    51              PUSH ECX

015141BE    0168 88         ADD DWORD PTR DS:[EAX-78],EBP

015141C1    36:51           PUSH ECX                                 ; 多余的前缀

015141C3    0168 50         ADD DWORD PTR DS:[EAX+50],EBP

015141C6    3351 01         XOR EDX,DWORD PTR DS:[ECX+1]

015141C9    68 002D5101     PUSH 1512D00

015141CE    68 BC265101     PUSH 15126BC

015141D3    68 4C3A5101     PUSH 1513A4C

015141D8    C3              RETN

........................................................................

 

继续Shift+F9 25次来到Asprotect典型的最后一次异常。

 

015139EC    3100            XOR DWORD PTR DS:[EAX],EAX    //特征码,这里先用Loadpe脱壳,避开后面的反脱壳代码。

015139EE    64:8F05 0000000>POP DWORD PTR FS:[0]

015139F5    58              POP EAX

015139F6    833D B07E5101 0>CMP DWORD PTR DS:[1517EB0],0

015139FD    74 14           JE SHORT 01513A13

015139FF    6A 0C           PUSH 0C

01513A01    B9 B07E5101     MOV ECX,1517EB0

01513A06    8D45 F8         LEA EAX,DWORD PTR SS:[EBP-8]

01513A09    BA 04000000     MOV EDX,4

01513A0E    E8 2DD1FFFF     CALL 01510B40

01513A13    FF75 FC         PUSH DWORD PTR SS:[EBP-4]

01513A16    FF75 F8         PUSH DWORD PTR SS:[EBP-8]

01513A19    8B45 F4         MOV EAX,DWORD PTR SS:[EBP-C]

01513A1C    8338 00         CMP DWORD PTR DS:[EAX],0

01513A1F    74 02           JE SHORT 01513A23

01513A21    FF30            PUSH DWORD PTR DS:[EAX]

01513A23    FF75 F0         PUSH DWORD PTR SS:[EBP-10]

01513A26    FF75 EC         PUSH DWORD PTR SS:[EBP-14]

01513A29    C3              RETN  //这里下断点,Shift+F9中断后取消断点。

........................................................................

 

我这次没有用内存镜像断点到OEP,下面的这个方法可以发现Stolen Code(如果有)+Oep二合一。

 

仍然是命令行断点

 

tc ebp==12fff0       //当前EBP内容为12fff0就被中断,略微看看就可以找到Stolen Code(如果有)或Oep

 

01525262    F2:             PREFIX REPNE:  //一会就来到这里,呵呵,Dephi语言就开始有Stolen Code,往下全部用F7步过,转标签1                              ; 多余的前缀

01525263    EB 01           JMP SHORT 01525266

01525265    F3:             PREFIX REP:    //这样的语句其实是一些变形Jmp    ; 多余的前缀

01525266    EB 01           JMP SHORT 01525269

01525268    9A 8D6424EF F3E>CALL FAR EBF3:EF24648D                   ; 远距呼叫

0152526F    02CD            ADD CL,CH

01525271    208D 64246F8D   AND BYTE PTR SS:[EBP+8D6F2464],CL

01525277    64:24 9E        AND AL,9E                                ; 多余的前缀

0152527A    EB 02           JMP SHORT 0152527E

0152527C    CD 20           INT 20

0152527E    894424 00       MOV DWORD PTR SS:[ESP],EAX

01525282    26:EB 02        JMP SHORT 01525287                       ; 多余的前缀

01525285    CD 20           INT 20

01525287    8B4424 18       MOV EAX,DWORD PTR SS:[ESP+18]

0152528B    EB 01           JMP SHORT 0152528E

.......................................................................

 

标签1

 

01525266   /EB 01           JMP SHORT 01525269

 

01525269    8D6424 EF       LEA ESP,DWORD PTR SS:[ESP-11]

0152526D    F3:             PREFIX REP:                              ; 多余的前缀

 

01525272    8D6424 6F       LEA ESP,DWORD PTR SS:[ESP+6F]

01525276    8D6424 9E       LEA ESP,DWORD PTR SS:[ESP-62]

0152527A    EB 02           JMP SHORT 0152527E

 

0152527E    894424 00       MOV DWORD PTR SS:[ESP],EAX

01525282    26:EB 02        JMP SHORT 01525287                       ; 多余的前缀

 

01525287    8B4424 18       MOV EAX,DWORD PTR SS:[ESP+18]

0152528B    EB 01           JMP SHORT 0152528E

 

0152528E   /64:EB 02        JMP SHORT 01525293                       ; 多余的前缀

 

01525293    0FBCC0          BSF EAX,EAX

01525296    F2:             PREFIX REPNE:                            ; 多余的前缀

 

0152529A    81E8 FF942BC5   SUB EAX,C52B94FF

015252A0    2E:EB 01        JMP SHORT 015252A4                       ; 多余的前缀

 

015252A4    8D83 AB525201   LEA EAX,DWORD PTR DS:[EBX+15252AB]

015252AA    2BC3            SUB EAX,EBX

015252AC    FF50 07         CALL DWORD PTR DS:[EAX+7]

 

015252BA    58              POP EAX                                  ; 015252AF

015252BB    26:EB 01        JMP SHORT 015252BF                       ; 多余的前缀

 

015252BF    23C7            AND EAX,EDI

015252C1    58              POP EAX

015252C2    F3:             PREFIX REP:                              ; 多余的前缀

 

015252C7    55              PUSH EBP      //Stolen Code第一句。

015252C8    8BEC            MOV EBP,ESP   //执行完它后,EBP=ESP=12FFC0,打破了从跟踪到这里EBP的值一直为12fff0的情况,同时也让我们也可以知道入口代码就在附近。Stolen Code第二句。

015252CA    81EC 10000000   SUB ESP,10    //第三句,这句要改为ADD ESP,10 标准化。

015252D0    F3:             PREFIX REP:                              ; 多余的前缀

 

后面有无数条小跳转,全部都是垃圾,我跟踪了40分钟,还没走完,已经吐血了。跟据经验三句代码靠一切抽的一般要抽11个字节,不必往下浪费时间跟踪了。

 

一般抽11字节的Dephi头部特征码 

 

PUSH EBP

MOV EBP,ESP

ADD ESP,-10   

MOV EAX,xxxxxxxx

 

这个程序一共抽掉11字节。

 

前面三句我们已经得到,现在的问题是MOV EAX,xxxxxxxx

 

EAX的值是多少?  

 

ALT+M 打开内存镜像。

 

内存镜像, 项目 12

地址=00401000  //对401000 Code段下内存断点。

大小=00100000 (1048576.)

Owner=BadCopy  00400000

区段=

Contains=code

类型=Imag 01001002

访问=R

初始访问=RWE

 

00406EE0  - FF25 78B2B700   JMP DWORD PTR DS:[B7B278] //中断在这里,清除内存断点。

00406EE6    8BC0            MOV EAX,EAX

00406EE8  - FF25 74B2B700   JMP DWORD PTR DS:[B7B274]

00406EEE    8BC0            MOV EAX,EAX

00406EF0  - FF25 70B2B700   JMP DWORD PTR DS:[B7B270]

00406EF6    8BC0            MOV EAX,EAX

00406EF8  - FF25 6CB2B700   JMP DWORD PTR DS:[B7B26C]

00406EFE    8BC0            MOV EAX,EAX

00406F00    50              PUSH EAX

00406F01    6A 40           PUSH 40

00406F03    E8 E0FFFFFF     CALL BadCopy.00406EE8

00406F08    C3              RETN

....................................................

 

01511C64    55              PUSH EBP //F8返回壳中。

01511C65    8BEC            MOV EBP,ESP

01511C67    8B45 08         MOV EAX,DWORD PTR SS:[EBP+8]

01511C6A    85C0            TEST EAX,EAX

01511C6C    75 13           JNZ SHORT 01511C81

01511C6E    813D A47A5101 0>CMP DWORD PTR DS:[1517AA4],400000        ; ASCII "MZP"

01511C78    75 07           JNZ SHORT 01511C81

01511C7A    A1 A47A5101     MOV EAX,DWORD PTR DS:[1517AA4]

01511C7F    EB 06           JMP SHORT 01511C87

01511C81    50              PUSH EAX

01511C82    E8 3135FFFF     CALL 015051B8                            ; JMP to kernel32.GetModuleHandleA

01511C87    5D              POP EBP

01511C88    C2 0400         RETN 4 //Ctrl+F9返回。

......................................................

 

00406FB5    A3 14775000     MOV DWORD PTR DS:[507714],EAX            ; BadCopy.00400000

00406FBA    A1 14775000     MOV EAX,DWORD PTR DS:[507714]

00406FBF    A3 B4105000     MOV DWORD PTR DS:[5010B4],EAX

00406FC4    33C0            XOR EAX,EAX

00406FC6    A3 B8105000     MOV DWORD PTR DS:[5010B8],EAX

00406FCB    33C0            XOR EAX,EAX

00406FCD    A3 BC105000     MOV DWORD PTR DS:[5010BC],EAX

00406FD2    E8 C1FFFFFF     CALL BadCopy.00406F98

00406FD7    BA B0105000     MOV EDX,BadCopy.005010B0

00406FDC    8BC3            MOV EAX,EBX       //这里EBX就是我们要的EAX的数值。00500638 记下来。

00406FDE    E8 65D7FFFF     CALL BadCopy.00404748

00406FE3    5B              POP EBX

00406FE4    C3              RETN

......................................................

 

00500997    0000            ADD BYTE PTR DS:[EAX],AL  确定真Oep为00500998

00500999    0000            ADD BYTE PTR DS:[EAX],AL

0050099B    0000            ADD BYTE PTR DS:[EAX],AL

0050099D    0000            ADD BYTE PTR DS:[EAX],AL

0050099F    0000            ADD BYTE PTR DS:[EAX],AL

005009A1    0000            ADD BYTE PTR DS:[EAX],AL

005009A3    E8 FC65F0FF     CALL BadCopy.00406FA4

005009A8    B0 01           MOV AL,1         //临时Oep,滚动条往上看。

005009AA    84C0            TEST AL,AL

005009AC    74 59           JE SHORT BadCopy.00500A07

005009AE    A1 D8615000     MOV EAX,DWORD PTR DS:[5061D8]

005009B3    8B00            MOV EAX,DWORD PTR DS:[EAX]

005009B5    E8 FE0CF7FF     CALL BadCopy.004716B8

005009BA    A1 D8615000     MOV EAX,DWORD PTR DS:[5061D8]

005009BF    8B00            MOV EAX,DWORD PTR DS:[EAX]

005009C1    BA 140A5000     MOV EDX,BadCopy.00500A14                 ; ASCII "BadCopy Pro"

005009C6    E8 F908F7FF     CALL BadCopy.004712C4

005009CB    8B0D D45D5000   MOV ECX,DWORD PTR DS:[505DD4]            ; BadCopy.00B6A1F8

005009D1    A1 D8615000     MOV EAX,DWORD PTR DS:[5061D8]

005009D6    8B00            MOV EAX,DWORD PTR DS:[EAX]

005009D8    8B15 D4C24E00   MOV EDX,DWORD PTR DS:[4EC2D4]            ; BadCopy.004EC320

005009DE    E8 ED0CF7FF     CALL BadCopy.004716D0

......................................................

 

现在我们已经得到了

 

1.  脱壳文件

 

2.  被抽11个字节代码

 

PUSH EBP

MOV EBP,ESP

ADD ESP,-10   

MOV EAX,00500638

 

剩下IAT修复,关闭OD,打开加壳程序,呵呵OEP填1000,ImportREC把Size认为000000B4太小了,改为1000,点获得输入表。显示无效,先用等级1方式跟踪,然后用Asprtect1.22插件再减轻一下压力。还剩563个指针没修复。

 

现在的问题是,这563个指针是有用的吗?ImpRec 1.6会告诉你

 

点击show invalid并右键单击选择其中的一个,让我们来修复它                        

 

0077b234<- 右键单击选择DeasmHexView查看:  

 

ImpRec 1.6提示你,read error!好,够了,只要有这个提示的一律可以安全的Cut。

 

如果这个指针有效,里面会显示汇编指令。

 

找了一会,发现0077B3A0处的指针是唯一一个没识别的指针。

 

右键单击选择DeasmHexView查看,究竟它是Kernel32.dll中的哪个函数呢,按Page Down两次,看到

 

01511D2E    call 01505158    // = kernel32.dll/00B3/FindResourceA

 

第一个看到的Api函数就是要修复的指针。

 

呵呵,修复它吧,双击0077B3A0这行,填入Api函数FindResourceA。

 

拿起剪刀,将剩下562个垃圾指针全部Cut,IAT全部修复,爽啊。修正Oep 为 100998 最后修复文件,最后Od载入脱壳修复的程序,补上11个字节代码,保存为一个文件,正常运行。


【破解总结】发现Dephi语言的Asprotect1.23Rc4的壳开始用Stolen Code,并且有变形指令,反脱壳代码,最麻烦,tc ebp==12fff0还不错吧。作者没有使用Asprotect内置的RSA算法保护,而采用自己的注册算法,任然是RSA1024,破解参考二哥=weiyi75=David的再次分析坏盘拷贝破文,感谢你耐心看完。

 

--------------------------------------------------------------------------------

 

【版权声明】 本文纯属技术交流, 转载请注明作者并保持文章的完整, 谢谢!