来源:安全中国
ACProtect 1.22b脱壳手记----NOTEPAD.EXE
目标:NOTEPAD.EXE,自己用ACProtect 1.22b专业版加壳,Compress Opetions里选Opetion1,Advanced Opetions的六个选项全选;加壳前49.7 KB,加壳后143 KB
工具:OllyDbg Beta110b原版; ImportREC 1.6 FINAL
破解平台:Win2000SP4 Chinese
主要目的:跳过IAT加密,快速到达伪OEP,Replace Code的一些处理;
由于ASProtect的Stolen code已经被各位老大们搞的很透彻了,ACProtect的Stolen code的分析和修复没多大差别,所以我就不在罗嗦了(省的敲不少字呢,呵呵)
废话少说,开工
———————————————————————————————————
用OllyDbg加载目标后,忽略所有异常,用插件IsDebuggerPresent隐藏调试器标志,程序停在这:
01010000 > 60 PUSHAD
01010001 66:8BCA MOV CX,DX
01010004 87C8 XCHG EAX,ECX
01010006 41 INC ECX
01010007 72 01 JB SHORT NOTEPAD_.0101000A
01010009 43 INC EBX
0101000A 48 DEC EAX
0101000B FC CLD
0101000C 50 PUSH EAX
0101000D E8 01000000 CALL NOTEPAD_.01010013
01010012 7A 83 JPE SHORT NOTEPAD_.0100FF97
01010014 C40458 LES EAX,FWORD PTR DS:[EAX+EBX*2]
01010017 66:8BEE MOV BP,SI
0101001A E8 01000000 CALL NOTEPAD_.01010020
. ;从开头到01010BB6都是壳的分段解密,可以看准
. ;每段循环结束位置0F85 xxFFFFFF,用F4直接跳到下一循环
.
.
.
.
01010BB6 4F DEC EDI
01010BB7 81F3 0503C769 XOR EBX,69C70305
01010BBD 68 4F460000 PUSH 464F
01010BC2 4E DEC ESI
01010BC3 59 POP ECX ;ECX=464Fh,这段循环解密的dword数
01010BC4 8B28 MOV EBP,DWORD PTR DS:[EAX] ;循环开始,这是一个大循环,解密了从01010BEA
01010BC6 03EB ADD EBP,EBX ;开始的(464Fh-1)*4=11938h字节
01010BC8 C1C5 12 ROL EBP,12
01010BCB 83C0 04 ADD EAX,4
01010BCE 0328 ADD EBP,DWORD PTR DS:[EAX]
01010BD0 83C0 FC ADD EAX,-4
01010BD3 8928 MOV DWORD PTR DS:[EAX],EBP
01010BD5 81F3 B2A9C00F XOR EBX,0FC0A9B2
01010BDB 81C0 04000000 ADD EAX,4
01010BE1 83E9 01 SUB ECX,1
01010BE4 ^ 0F85 DAFFFFFF JNZ NOTEPAD_.01010BC4
01010BEA 116C95 AB ADC DWORD PTR SS:[EBP+EDX*4-55],EBP ;在这下硬件执行断点
01010BEE 53 PUSH EBX
01010BEF ^ 79 91 JNS SHORT NOTEPAD_.01010B82
上面的循环结束后01010BEA处变为
01010BEA /E9 A9180100 JMP NOTEPAD_.01022498 ;这个JMP远距离跳到壳真正开始工作的地方
01010BEF |0000 ADD BYTE PTR DS:[EAX],AL
01010BF1 |0000 ADD BYTE PTR DS:[EAX],AL
01010BF3 |0000 ADD BYTE PTR DS:[EAX],AL
01010BF5 |0000 ADD BYTE PTR DS:[EAX],AL
01010BF7 |0000 ADD BYTE PTR DS:[EAX],AL
在01010BEA上点右键,Folllow Dump->Selection,在内存窗口里搜索HEX:4D4D4D4D,找到如下:
01010F19 4D 4D 4D 4D C5 73 FE FF D2 73 FE FF 00 00 00 00 MMMM舠?襰?....
01010F29 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
01010F39 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
01010F49 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
01010F59 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
01010F19就是ACProtect在后面开始处理Stolen code时放置0006FFF0(即OD刚加载程序时的EBP,一般程序多数是0012FFF0,NOTEPAD.EXE有点特殊),在01010F19下硬件访问断点,目的是快速到达处理Stolen code的地方
———————————————————————————————————
2.跳过IAT加密
在GetProcAddress入口处下硬件断点,也可以在GetProcAddress入口处跳过一字节后用F2下普通断点.F9运行,会在GetProcAddress上断下,堆栈显示的是GlobalAlloc,这是壳自己用到的API,一共23个,依次是
GlobalAlloc.GlobalFree.GetCurrentProcessId.CreateToolhelp32Snapshot.Process32First.Process32Next.CloseHandle.CreateFileA.TerminateProcess.IsDebuggerPresent.OpenProcess.ReadFile.WriteFile.FreeLibrary.GetTempPathA.UnhandledExceptionFilter.GetThreadContext.SetThreadContext.GetCurrentThread.EnumWindows.GetWindowTextA.GetClassNameA.PostMessageA
一直按F9运行,在处理过PostMessageA后,就开始处理程序的API,堆栈和寄存器都会有个较大的变化,断下后,是处IsProcessorFeaturePresent,Return to msvcrt.78001EAA,继续F9,直到堆栈第一次显示Return to NOTEPAD.XXXXX,这时处理的是FindTextW,取消GetProcAddress的硬件执行断点,Ctrl+F9运行返回到壳里
PS:如果被加壳的程序是用Delphi或BCB写的话,在PostMessageA后处理的下一个API,堆栈显示就是返回到壳程序,但VC++的程序在处理完PostMessageA后还会由Kenrel调用GetProcAddress处理一些msvcrt,COMCTL32等里的一
些API,所以必须等处理完这些API后,在壳调用GetProcAddress处理程序原来的API时才能Ctrl+F9返回到壳里
Ctrl+F9运行返回后:
0102201B 53 PUSH EBX
0102201C FFB5 29DE4000 PUSH DWORD PTR SS:[EBP+40DE29]
01022022 FF95 80B04100 CALL DWORD PTR SS:[EBP+41B080] ;Call GetProcAddress
01022028 3B9D 31DE4000 CMP EBX,DWORD PTR SS:[EBP+40DE31];Ctrl+F9返回到这里,EBP=00C0F000
0102202E 7C 0F JL SHORT NOTEPAD_.0102203F ;所以GetProcAddress的地址是
01022030 90 NOP ;EBP+41B080=102A080,记下这个地址!
01022031 90 NOP
01022032 90 NOP
01022033 90 NOP
01022034 60 PUSHAD
01022035 2BC0 SUB EAX,EAX
01022037 8803 MOV BYTE PTR DS:[EBX],AL
01022039 43 INC EBX
0102203A 3803 CMP BYTE PTR DS:[EBX],AL
0102203C ^ 75 F9 JNZ SHORT NOTEPAD_.01022037
0102203E 61 POPAD
0102203F 0BC0 OR EAX,EAX
01022041 ^ 0F84 21FFFFFF JE NOTEPAD_.01021F68 ;EAX=刚才GetProcAddress得到的API的入口
01022047 3B85 90B04100 CMP EAX,DWORD PTR SS:[EBP+41B090];EBP+41B090指向MessageBox
0102204D 75 0A JNZ SHORT NOTEPAD_.01022059 ;① 这里把得到的API入口与MessageBox
0102204F 90 NOP ;比较,相等就用壳的MessageBox来代替
01022050 90 NOP ;程序的MessageBox,把①处的JNZ改为JMP
01022051 90 NOP ;即可跳过ACProtect对MessageBox作的手脚
01022052 90 NOP
01022053 8D85 D4E34000 LEA EAX,DWORD PTR SS:[EBP+40E3D4]
01022059 56 PUSH ESI
0102205A FFB5 29DE4000 PUSH DWORD PTR SS:[EBP+40DE29]
01022060 5E POP ESI
01022061 39B5 FA234000 CMP DWORD PTR SS:[EBP+4023FA],ESI
01022067 74 15 JE SHORT NOTEPAD_.0102207E
01022069 90 NOP
0102206A 90 NOP
0102206B 90 NOP
0102206C 90 NOP
0102206D 39B5 FE234000 CMP DWORD PTR SS:[EBP+4023FE],ESI
01022073 74 09 JE SHORT NOTEPAD_.0102207E
01022075 90 NOP
01022076 90 NOP
01022077 90 NOP
01022078 90 NOP
01022079 EB 63 JMP SHORT NOTEPAD_.010220DE
0102207B 90 NOP
0102207C 90 NOP
0102207D 90 NOP
0102207E 80BD 90304100 00 CMP BYTE PTR SS:[EBP+413090],0
01022085 74 57 JE SHORT NOTEPAD_.010220DE
01022087 90 NOP
01022088 90 NOP
01022089 90 NOP
0102208A 90 NOP
0102208B EB 07 JMP SHORT NOTEPAD_.01022094
0102208D 90 NOP
0102208E 90 NOP
0102208F 90 NOP
01022090 0100 ADD DWORD PTR DS:[EAX],EAX
01022092 0000 ADD BYTE PTR DS:[EAX],AL
01022094 8BB5 F6DE4000 MOV ESI,DWORD PTR SS:[EBP+40DEF6] ;EBP+40DEF6指向Acpr要转移API的地方
0102209A 83C6 0D ADD ESI,0D
0102209D 81EE EA1B4000 SUB ESI,401BEA
010220A3 2BF5 SUB ESI,EBP
010220A5 83FE 00 CMP ESI,0
010220A8 7F 34 JG SHORT NOTEPAD_.010220DE ;② 不跳就把API转移到[EBP+40DEF6]
010220AA 90 NOP ;所以把②处的JG改为JMP即可跳过Acpr
010220AB 90 NOP ;对IAT的加密!
