ASPROTECT 2.0 脱壳示例

类别:编程语言 点击:0 评论:0 推荐:
ASPROTECT  2.0 脱壳示例【目    标】:Win98’s notepad
【工    具】:Olydbg1.1(diy版)、LORDPE、ImportREC1.6F
【任    务】:简单的脱一下asprotect的壳
【操作平台】:Windows Xp sp2
【作    者】:loveboom[DFCG][FCG][US]
【简要说明】:有一段时间没写文章了,这篇文章本来是想在奥运会那时写出来,因为公事比较多,有空的时候心情不好等原因,所以一直放到现在才写.【详细过程】:设置忽略全部异常,去掉调试标志。载入后到这里:00401000 >  68 01D040>PUSH 0040D001                            ; EP壳的入口00401005    E8 010000>CALL 0040100B载入后,直接g LoadLibraryA运行到LoadLibraryA这个API处.7C801D77 >  8BFF      MOV EDI,EDI                              ; LoadLibraryA7C801D79    55        PUSH EBP到了后,ALT+F9执行到返回:009884B7    8985 4D29>MOV DWORD PTR SS:[EBP+44294D],EAX        ; 返回到这里009884BD    C785 5129>MOV DWORD PTR SS:[EBP+442951],0……009885C1    61        POPAD009885C2    75 08     JNZ SHORT 009885CC                       ; 看到这里,跟过Aspack的朋友就是知道这里是什么了009885C4    B8 010000>MOV EAX,1009885C9    C2 0C00   RETN 0C009885CC    68 000000>PUSH 0                                   ; 如果解压完壳代码这里会push 一个返回的地址009885D1    C3        RETN返回到009884B7处后,右键查找全部字符串,然后在字符串窗中查找250这样就会看到这些东西:双击10那里到了cpu窗口处:0096CD66   /75 0A     JNZ SHORT 0096CD720096CD68   |68 C8D096>PUSH 96D0C8                              ; 双击到这里,这里向上找到代码开始处0096CD6D   |E8 BE6DFF>CALL 00963B30向上找到这里:0096CC70   /EB 01     JMP SHORT 0096CC730096CC72   |90        NOP0096CC73   \8B43 08   MOV EAX,DWORD PTR DS:[EBX+8]             ; 这里开始对IAT进行处理0096CC76    8B30      MOV ESI,DWORD PTR DS:[EAX]0096CC78    8343 08 0>ADD DWORD PTR DS:[EBX+8],40096CC7C    8B43 08   MOV EAX,DWORD PTR DS:[EBX+8]0096CC7F    8A00      MOV AL,BYTE PTR DS:[EAX]0096CC81    884424 07 MOV BYTE PTR SS:[ESP+7],AL0096CC85    FF43 08   INC DWORD PTR DS:[EBX+8]0096CC88    85F6      TEST ESI,ESI0096CC8A    75 1A     JNZ SHORT 0096CCA6                       ; 这里比较输入表是否处理完毕,如果没有就跳下去0096CC8C    EB 01     JMP SHORT 0096CC8F……0096CCC9    FF43 08   INC DWORD PTR DS:[EBX+8]0096CCCC    84C0      TEST AL,AL                               ; 这里开始对AL的值的不同而进行相关的处理0096CCCE    75 20     JNZ SHORT 0096CCF0……0096CD59    8B4424 14 MOV EAX,DWORD PTR SS:[ESP+14]0096CD5D    E8 DEECFF>CALL 0096BA40                            ; GetProcAddress0096CD62    8BE8      MOV EBP,EAX0096CD64    85ED      TEST EBP,EBP0096CD66    75 0A     JNZ SHORT 0096CD72                       ; 判断获取API是否成功0096CD68    68 C8D096>PUSH 96D0C8                              ; 双击到这里,这里向上找到代码开始处0096CD6D    E8 BE6DFF>CALL 00963B300096CD72    837C24 20>CMP DWORD PTR SS:[ESP+20],0……0096CDF7    E8 8469FF>CALL 00963780                            ; 当AL为2时对IAT的处理,跟进去0096CDFC  ^ E9 72FEFF>JMP 0096CC73                             ; 处理完跳回去……跟进看看:00963756    8BC0      MOV EAX,EAX00963758    55        PUSH EBP00963759    8BEC      MOV EBP,ESP0096375B    53        PUSH EBX0096375C    8BD8      MOV EBX,EAX0096375E    8BC2      MOV EAX,EDX00963760    8BD1      MOV EDX,ECX00963762    E8 79FFFF>CALL 009636E000963767    C603 E9   MOV BYTE PTR DS:[EBX],0E9                ; 先在这里也下个断,因为这里就是程序的OEP0096376A    8D53 01   LEA EDX,DWORD PTR DS:[EBX+1]             ; 这里原程跳就是壳抽程序代码的开始地方0096376D    8902      MOV DWORD PTR DS:[EDX],EAX0096376F    8B45 08   MOV EAX,DWORD PTR SS:[EBP+8]00963772    8910      MOV DWORD PTR DS:[EAX],EDX00963774    B8 050000>MOV EAX,500963779    5B        POP EBX0096377A    5D        POP EBP0096377B    C2 0400   RETN 40096377E    8BC0      MOV EAX,EAX00963780    53        PUSH EBX                                 ; 进到这里00963781    8BD8      MOV EBX,EAX00963783    8BC3      MOV EAX,EBX00963785    E8 56FFFF>CALL 009636E00096378A    C603 E8   MOV BYTE PTR DS:[EBX],0E8                ; 这里把IAT的改成call xxxxxx的样式,所以我们这里要进去处理0096378D    43        INC EBX0096378E    8903      MOV DWORD PTR DS:[EBX],EAX00963790    5B        POP EBX00963791    C3        RETN现在这里我们来修复一下:先自己申请两块空间,当然你也可以直接找空闲的地方来写代码,我分别申请了00B90000和00BA0000这个块内存空间,00b90000这块是用来写patch代码,00ba0000是用来保存临时要存放的数据。00BA0000用来保存DLL的基址,00BA0010用来保存要存放IAT的地址。搞清这些东西后,我们开始写代码:00963781    8BD8      MOV EBX,EAX00963783    8BC3      MOV EAX,EBX00963785    E8 56FFFF>CALL 009636E00096378A    E8 71C822>CALL 00B90000                            ; 调用我们改的代码处0096378F    90        NOP00963790    5B        POP EBX00963791    C3        RETN 00B90000用来写我们自己的修复代码:00B90000    51        PUSH ECX                                 ; 保护现场00B90001    52        PUSH EDX00B90002    8B5424 28 MOV EDX,DWORD PTR SS:[ESP+28]            ; 取出基址到EDX中00B90006    3B15 0000>CMP EDX,DWORD PTR DS:[BA0000]            ; 比较基址是否相同00B9000C    74 0D     JE SHORT 00B9001B00B9000E    8915 0000>MOV DWORD PTR DS:[BA0000],EDX            ; 如果不同就写入新的基址00B90014    8305 1000>ADD DWORD PTR DS:[BA0010],4              ; 并把填入IAT的地址再加上400B9001B    8B0D 1000>MOV ECX,DWORD PTR DS:[BA0010]            ; 如果是第一次我们要手工写一下保存IAT的地址,我选择的是40C00000B90021    8929      MOV DWORD PTR DS:[ECX],EBP               ; 写入正确的函数00B90023    66:C703 F>MOV WORD PTR DS:[EBX],15FF               ; 这里要看程序的情况而定,如果是DELPHI之类的,这果就可能是FF25了,因为是C的,所以这里是ff1500B90028    890E      MOV DWORD PTR DS:[ESI],ECX               ; 把存放IAT的地址放到程序里00B9002A    8305 1000>ADD DWORD PTR DS:[BA0010],4              ; 保存IAT的地址+400B90031    5A        POP EDX                                  ; 还原现场00B90032    59        POP ECX00B90033    C3        RETN                                     ; 返回到壳那边继续 继续到AL=1时的处理:0096CE07  ^\E9 67FEFF>JMP 0096CC730096CE0C    3C 01     CMP AL,1                                 ; 当AL=1的处理0096CE0E    0F85 B200>JNZ 0096CEC6……0096CE7E    A1 B8A697>MOV EAX,DWORD PTR DS:[97A6B8]0096CE83    8B00      MOV EAX,DWORD PTR DS:[EAX]0096CE85    FFD0      CALL EAX                                 ; GetProcAddress0096CE87    8BE8      MOV EBP,EAX0096CE89    85ED      TEST EBP,EBP0096CE8B    75 0A     JNZ SHORT 0096CE97                       ; 如果获取成功就跳0096CE8D    68 D8D096>PUSH 96D0D8                              ; ASCII "11"0096CE92    E8 996CFF>CALL 00963B300096CE97    8B0424    MOV EAX,DWORD PTR SS:[ESP]0096CE9A    50        PUSH EAX0096CE9B    68 08BC96>PUSH 96BC080096CEA0    8D4C24 20 LEA ECX,DWORD PTR SS:[ESP+20]0096CEA4    8BD5      MOV EDX,EBP0096CEA6    8BC3      MOV EAX,EBX0096CEA8    E8 BFF4FF>CALL 0096C36C0096CEAD    8B5424 0C MOV EDX,DWORD PTR SS:[ESP+C]             ; 这里壳又要对IAT破坏处理,我们这里又要自己修复一下0096CEB1    8902      MOV DWORD PTR DS:[EDX],EAX               ; 这里写上我们自己的代码0096CEB3    8B4424 0C MOV EAX,DWORD PTR SS:[ESP+C]0096CEB7    8906      MOV DWORD PTR DS:[ESI],EAX0096CEB9    0FB74424 >MOVZX EAX,WORD PTR SS:[ESP+4]0096CEBE    0143 08   ADD DWORD PTR DS:[EBX+8],EAX0096CEC1  ^ E9 ADFDFF>JMP 0096CC73                             ; 处理完就跳回去当AL=1时的修复代码:0096CEA8    E8 BFF4FF>CALL 0096C36C0096CEAD    E8 8E3122>CALL 00B900400096CEB2    90        NOP0096CEB3    90        NOP0096CEB4    90        NOP0096CEB5    90        NOP0096CEB6    90        NOP0096CEB7    90        NOP0096CEB8    90        NOP0096CEB9    0FB74424 >MOVZX EAX,WORD PTR SS:[ESP+4]0096CEBE    0143 08   ADD DWORD PTR DS:[EBX+8],EAX0096CEC1  ^ E9 ADFDFF>JMP 0096CC73 00B90040处的修复代码:00B90040    51        PUSH ECX                                 ; 保护现场00B90041    52        PUSH EDX00B90042    8B5424 20 MOV EDX,DWORD PTR SS:[ESP+20]            ; 取出当然要处理DLL的基址00B90046    3B15 0000>CMP EDX,DWORD PTR DS:[BA0000]            ; 比较基址是否相同00B9004C    74 0D     JE SHORT 00B9005B00B9004E    8915 0000>MOV DWORD PTR DS:[BA0000],EDX00B90054    8305 1000>ADD DWORD PTR DS:[BA0010],400B9005B    8B0D 1000>MOV ECX,DWORD PTR DS:[BA0010]            ; 1.0040C00400B90061    8929      MOV DWORD PTR DS:[ECX],EBP               ; 把IAT写到我们要指定的地址去也就是40c000那个段里00B90063    890E      MOV DWORD PTR DS:[ESI],ECX               ; 那保存函数的地址写入程序中00B90065    8305 1000>ADD DWORD PTR DS:[BA0010],400B9006C    5A        POP EDX00B9006D    59        POP ECX                                  ; 还原现场00B9006E    C3        RETN                                     ; 执行到返回到了AL=4的处理了:0096CEC6    3C 04     CMP AL,4                                 ; 当AL为4有两个分支0096CEC8    0F85 F400>JNZ 0096CFC20096CECE    EB 01     JMP SHORT 0096CED10096CED0    90        NOP0096CED1    8B43 08   MOV EAX,DWORD PTR DS:[EBX+8]0096CED4    8A00      MOV AL,BYTE PTR DS:[EAX]0096CED6    FF43 08   INC DWORD PTR DS:[EBX+8]0096CED9    84C0      TEST AL,AL0096CEDB    75 5B     JNZ SHORT 0096CF38                       ; 这里跳的话就和AL=1时的处理一样0096CEDD    8B43 08   MOV EAX,DWORD PTR DS:[EBX+8]             ; 这里是AL=4时的第一个分支0096CEE0    8B30      MOV ESI,DWORD PTR DS:[EAX]0096CEE2    8343 08 0>ADD DWORD PTR DS:[EBX+8],40096CEE6    8B43 08   MOV EAX,DWORD PTR DS:[EBX+8]0096CEE9    8B28      MOV EBP,DWORD PTR DS:[EAX]0096CEEB    8343 08 0>ADD DWORD PTR DS:[EBX+8],40096CEEF    8B43 08   MOV EAX,DWORD PTR DS:[EBX+8]0096CEF2    8B00      MOV EAX,DWORD PTR DS:[EAX]0096CEF4    894424 2C MOV DWORD PTR SS:[ESP+2C],EAX0096CEF8    8343 08 0>ADD DWORD PTR DS:[EBX+8],40096CEFC    837B 30 0>CMP DWORD PTR DS:[EBX+30],00096CF00    75 0A     JNZ SHORT 0096CF0C0096CF02    68 E8D096>PUSH 96D0E8                              ; ASCII "81"0096CF07    E8 246CFF>CALL 00963B300096CF0C    8D5424 30 LEA EDX,DWORD PTR SS:[ESP+30]0096CF10    8BC3      MOV EAX,EBX0096CF12    E8 8DF8FF>CALL 0096C7A4                            ; 这个CALL要进去,因为这里面就是计算将要保存IAT的地址进去看看先:0096C7A4    53        PUSH EBX0096C7A5    56        PUSH ESI0096C7A6    8BF2      MOV ESI,EDX0096C7A8    8BD8      MOV EBX,EAX0096C7AA    B8 040000>MOV EAX,40096C7AF    E8 985DFE>CALL 0095254C0096C7B4    8906      MOV DWORD PTR DS:[ESI],EAX               ; 这里把计算出来的地址填入[esi]中0096C7B6    8B43 40   MOV EAX,DWORD PTR DS:[EBX+40]0096C7B9    8946 04   MOV DWORD PTR DS:[ESI+4],EAX0096C7BC    5E        POP ESI0096C7BD    5B        POP EBX0096C7BE    C3        RETN这里处理第一个分支先,第二个分支我们可以完全调用AL=1时的代码,AL=4第一个分支的修复代码:0096C7A4    53        PUSH EBX0096C7A5    56        PUSH ESI0096C7A6    8BF2      MOV ESI,EDX0096C7A8    8BD8      MOV EBX,EAX0096C7AA    B8 040000>MOV EAX,40096C7AF    E8 985DFE>CALL 0095254C0096C7B4    E8 C13822>CALL 00B9007A0096C7B9    8946 04   MOV DWORD PTR DS:[ESI+4],EAX0096C7BC    5E        POP ESI0096C7BD    5B        POP EBX0096C7BE    C3        RETN 00B9007A的修复代码:00B9007A    51        PUSH ECX                                 ; 保护现场00B9007B    52        PUSH EDX00B9007C    8B5424 2C MOV EDX,DWORD PTR SS:[ESP+2C]            ; 取出当然要处理DLL的基址00B90080    3B15 0000>CMP EDX,DWORD PTR DS:[BA0000]            ; kernel32.7C80000000B90086    74 0D     JE SHORT 00B9009500B90088    8915 0000>MOV DWORD PTR DS:[BA0000],EDX00B9008E    8305 1000>ADD DWORD PTR DS:[BA0010],400B90095    8B0D 1000>MOV ECX,DWORD PTR DS:[BA0010]            ; 1.0040C02000B9009B    890E      MOV DWORD PTR DS:[ESI],ECX               ; 取出我们要保存IAT的址址到[ESI]中00B9009D    8305 1000>ADD DWORD PTR DS:[BA0010],400B900A4    5A        POP EDX00B900A5    59        POP ECX                                  ; 还原现场00B900A6    8B43 40   MOV EAX,DWORD PTR DS:[EBX+40]            ; 执行我们前面所"吃"掉一行代码00B900A9    C3        RETN                                                                          ;执行到返回……0096CF17    8B4424 2C MOV EAX,DWORD PTR SS:[ESP+2C]0096CF1B    50        PUSH EAX0096CF1C    8D4424 34 LEA EAX,DWORD PTR SS:[ESP+34]0096CF20    50        PUSH EAX0096CF21    55        PUSH EBP0096CF22    A1 70A597>MOV EAX,DWORD PTR DS:[97A570]0096CF27    8B00      MOV EAX,DWORD PTR DS:[EAX]0096CF29    50        PUSH EAX0096CF2A    56        PUSH ESI0096CF2B    8B4424 28 MOV EAX,DWORD PTR SS:[ESP+28]0096CF2F    50        PUSH EAX0096CF30    FF53 30   CALL DWORD PTR DS:[EBX+30]               ; 这里计算函数并写入地址0096CF33  ^ E9 3BFDFF>JMP 0096CC730096CF38    8B43 08   MOV EAX,DWORD PTR DS:[EBX+8]0096CF3B    8B00      MOV EAX,DWORD PTR DS:[EAX]0096CF3D    890424    MOV DWORD PTR SS:[ESP],EAX0096CF40    8343 08 0>ADD DWORD PTR DS:[EBX+8],40096CF44    8B43 08   MOV EAX,DWORD PTR DS:[EBX+8]0096CF47    66:8B00   MOV AX,WORD PTR DS:[EAX]0096CF4A    66:894424>MOV WORD PTR SS:[ESP+4],AX0096CF4F    8343 08 0>ADD DWORD PTR DS:[EBX+8],20096CF53    8B0C24    MOV ECX,DWORD PTR SS:[ESP]0096CF56    66:8B5424>MOV DX,WORD PTR SS:[ESP+4]0096CF5B    8B43 08   MOV EAX,DWORD PTR DS:[EBX+8]0096CF5E    E8 91ABFF>CALL 00967AF40096CF63    8B4424 10 MOV EAX,DWORD PTR SS:[ESP+10]0096CF67    E8 E055FE>CALL 0095254C0096CF6C    894424 0C MOV DWORD PTR SS:[ESP+C],EAX0096CF70    8B43 08   MOV EAX,DWORD PTR DS:[EBX+8]0096CF73    50        PUSH EAX0096CF74    8B4424 18 MOV EAX,DWORD PTR SS:[ESP+18]0096CF78    50        PUSH EAX0096CF79    A1 B8A697>MOV EAX,DWORD PTR DS:[97A6B8]0096CF7E    8B00      MOV EAX,DWORD PTR DS:[EAX]0096CF80    FFD0      CALL EAX                                 ; GetProcAddress0096CF82    8BE8      MOV EBP,EAX0096CF84    85ED      TEST EBP,EBP0096CF86    75 0C     JNZ SHORT 0096CF94                       ; 如果获取成功就跳0096CF88    68 F8D096>PUSH 96D0F8                              ; ASCII "250"0096CF8D    E8 9E6BFF>CALL 00963B300096CF92    EB 15     JMP SHORT 0096CFA90096CF94    A1 ECA597>MOV EAX,DWORD PTR DS:[97A5EC]0096CF99    3B28      CMP EBP,DWORD PTR DS:[EAX]0096CF9B    75 0C     JNZ SHORT 0096CFA90096CF9D    837B 34 0>CMP DWORD PTR DS:[EBX+34],00096CFA1    74 06     JE SHORT 0096CFA90096CFA3    8B6B 34   MOV EBP,DWORD PTR DS:[EBX+34]0096CFA6    036B 40   ADD EBP,DWORD PTR DS:[EBX+40]0096CFA9    8B4424 0C MOV EAX,DWORD PTR SS:[ESP+C]             ; 到这里就是和AL=1的处理一样,这里就是第二个分支0096CFAD    8928      MOV DWORD PTR DS:[EAX],EBP0096CFAF    8B4424 0C MOV EAX,DWORD PTR SS:[ESP+C]0096CFB3    8906      MOV DWORD PTR DS:[ESI],EAX0096CFB5    0FB74424 >MOVZX EAX,WORD PTR SS:[ESP+4]0096CFBA    0143 08   ADD DWORD PTR DS:[EBX+8],EAX0096CFBD  ^ E9 B1FCFF>JMP 0096CC73……第二个分支的处理,这里很简单我们只改几行代码就行了,改成这样子:0096CFA9    E8 923022>CALL 00B90040                                                ;和AL=1一样的处理0096CFAE    90        NOP0096CFAF    90        NOP0096CFB0    90        NOP0096CFB1    90        NOP0096CFB2    90        NOP0096CFB3    90        NOP0096CFB4    90        NOP这个程序里没有AL=3和AL=5的情况,所以我也就不多说了.好了,处理完IAT后我们记住这里:00963767    C603 E9   MOV BYTE PTR DS:[EBX],0E9直接在这00963767处下断,然后运行,中断在这里后,我们就知道这里的[EBX]就是保存我们的目标程序的OEP,这个对DELPHI的程序就可能不止在这里中断一次,但跳去的地方一定是壳抽程序的代码。00963756    8BC0      MOV EAX,EAX00963758    55        PUSH EBP00963759    8BEC      MOV EBP,ESP0096375B    53        PUSH EBX0096375C    8BD8      MOV EBX,EAX0096375E    8BC2      MOV EAX,EDX00963760    8BD1      MOV EDX,ECX00963762    E8 79FFFF>CALL 009636E000963767    C603 E9   MOV BYTE PTR DS:[EBX],0E90096376A    8D53 01   LEA EDX,DWORD PTR DS:[EBX+1]             ; 这里原程跳就是壳抽程序代码的开始地方0096376D    8902      MOV DWORD PTR DS:[EDX],EAX0096376F    8B45 08   MOV EAX,DWORD PTR SS:[EBP+8]00963772    8910      MOV DWORD PTR DS:[EAX],EDX00963774    B8 050000>MOV EAX,500963779    5B        POP EBX0096377A    5D        POP EBP0096377B    C2 0400   RETN 4                                   ; 直接执行到这里,然后到4010cc处看看……004010CC  - E9 48F177>JMP 00B80219                             ; 这里跳去的地方就是壳抽程序的代码的开始处004010D1    7D 5E     JGE SHORT 00401131004010D3    FF15 00C0>CALL DWORD PTR DS:[40C000]               ; kernel32.GetCommandLineA00B80219就是壳执行原程序的开始处.所以我们直接在00B80219处下个断,然后运行,再次中断后我们就可以比较直观的看到被抽的代码。00B80219    55        PUSH EBP                                 ; 在这里下断,这就是程序的第一行代码00B8021A    336C24 08 XOR EBP,DWORD PTR SS:[ESP+8]00B8021E    336C24 28 XOR EBP,DWORD PTR SS:[ESP+28]00B80222    8BEC      MOV EBP,ESP                              ; 第二行……00B80273    83EC 44   SUB ESP,44                               ; 第三行00B80276    56        PUSH ESI                                 ; 最后一行代码00B80277  ^ E9 ADFFFF>JMP 00B80229这样程序被抽的代码就找回来的,当然,如果是加的DELPHI或其它的C的程序抽的代码就不是这么少了。好了,现在我们被上代码,然后DUMP和修复一下就行了. Greetz: Fly.Jingulong,yock,tDasm.David.ahao.UFO(brother).alan(sister).all of my friends and you! By loveboom[DFCG][FCG]Email:[email protected] 

本文地址:http://com.8s8s.com/it/it22376.htm