【破解作者】 layper
【作者邮箱】 layper2002@yahoo.com.cn
【作者主页】 www.sy135.com
【使用工具】 peid,od,
【破解平台】 Win9x/NT/2000/XP
【软件名称】 壳乱弹(3)单步分析
【破解声明】 我是一只小菜鸟,偶得一点心得,愿与大家分享:)
--------------------------------------------------------------------------------
【破解内容】
接着上次的分析,上次我们分析到得到一个地址文件头部的"MZP"的地址,有个兄弟仙剑太郎说这是壳解码,
谢谢这位兄弟,虽然我的观点不太同,但是他也给我好的启发。原来我还不敢肯定接下来作什么,听了仙剑太郎的
说法跟我想的差不多,我们继续往下看:
005AC022 807D 4D 01 cmp byte ptr ss:[ebp+4D],1 ,ss:[005AC060]=00
与1比较
005AC026 75 0C jnz short CWoool.005AC034 ,不等则调,这里不等
005AC028 8B7424 28 mov esi,dword ptr ss:[esp+28] ;[ESP+28]=[12FFCC]=FFFFFFFF
005AC02C 83FE 01 cmp esi,1 ,与1比较
005AC02F 895D 4E mov dword ptr ss:[ebp+4E],ebx ;EBX=400000
005AC032 75 31 jnz short CWoool.005AC065
前面产生了两个分支,而且两个分支都是与1比较,估计是返回值之类的东西,(别怪我老是估计,我还很菜)
005AC034 8D45 53 lea eax,dword ptr ss:[ebp+53] ;[EBP+53]=5AC0066
005AC037 50 push eax
005AC038 53 push ebx ;ebx=00400000 (CWoool.00400000), ASCII "MZP"
005AC039 FFB5 ED090000 push dword ptr ss:[ebp+9ED] ;ss:[005ACA00]=7C80B529 (kernel32.GetModuleHandleA)哈哈,终于出来了
005AC03F 8D45 35 lea eax,dword ptr ss:[ebp+35] ;指向005AC048
005AC042 50 push eax ;压入堆栈
005AC043 E9 82000000 jmp CWoool.005AC0CA
005AC0CA 8BF3 mov esi,ebx ; CWoool.00400000
005AC0CC E8 08000000 call CWoool.005AC0D9 ;f7跟进
005AC0D9 50 push eax ;005AC048
005AC0DA 5F pop edi ; CWoool.005AC048,这两行代码也是常见的,利用堆栈传递参数
005AC0DB 5A pop edx ;把call的返回地址出栈
005AC0DC 8BFE mov edi,esi ;esi=00400000 (CWoool.00400000), ASCII "MZP"
;edi=005AC048 (CWoool.005AC048)
;奇怪,为什么传递参数没有用到,看来有可能是沉余代码
005AC0DE 81C2 5C080000 add edx,85C ;edx=005AC0D1 (CWoool.005AC0D1)+85c=005AC92D,到005AC92D看看,后面全部是
;零,看来005AC92D是一段代码的边界了.
005AC0E4 0F8D 00000000 jge CWoool.005AC0EA ;那么近也跳,垃圾
005AC0EA 68 00000000 push 0
005AC0EF 81E8 FC346B1E sub eax,1E6B34FC ;原eax=005AC048,这个地址减去一个数值,运算后eax=e1ef8b4c
005AC0F5 5B pop ebx ;ebx清零
005AC0F6 66:81D6 A649 adc si,49A6 ;注意这里,esi指向了004049A7
005AC0FB FF3413 push dword ptr ds:[ebx+edx] ;第一次取005AC92D的数据,注意前面已经提醒这个是一个边界
005AC0FE 51 push ecx ;ecx=0012FFB0
005AC0FF 68 39A5C040 push 40C0A539 ;又一个特殊数值
005AC104 81F7 FB2FA22D xor edi,2DA22FFB ;edi=00400000 , ASCII "MZP" DOS文件头地址异或
005AC10A 5F pop edi ;40C0A539传递给EDI,奇怪,又是上一步好象又是垃圾
005AC10B 5E pop esi ;esi指向指针堆栈 [0012FF8C]=0012FFB0
005AC10C 59 pop ecx ;哈哈,看看这个是005AC92D中的数据
005AC10D 66:B8 EB0D mov ax,0DEB ;005AC048运算结果改动低位为E1EF0DEB
005AC111 81E9 6CDCC50C sub ecx,0CC5DC6C ;005AC92D的数据减去0CC5DC6C=0212EC40
005AC117 B8 C79DDA2F mov eax,2FDA9DC7 ;EAX=2FDA9DC7修改了EAX的值
005AC11C 81F1 35F2EF20 xor ecx,20EFF235 ;005AC92D的数据再次运算(异或)=22FD1E75
005AC122 0F89 03000000 jns CWoool.005AC12B ;SF=0跳走
005AC128 0FBFF6 movsx esi,si
005AC12B 81E9 CA76F46B sub ecx,6BF476CA ;005AC92D的数据再次运算=B708A7AB
005AC131 890C1A mov dword ptr ds:[edx+ebx],ecx ;放回005AC92D
005AC134 E8 0C000000 call CWoool.005AC145 ;跟进
005AC145 E8 0B000000 call CWoool.005AC155 ;跟进
005AC155 80C0 16 add al,16 ;2FDA9DC7低位加16
005AC158 5F pop edi ;返回地址出栈堆栈 [0012FF8C]=005AC14A (CWoool.005AC14A)
005AC159 58 pop eax ;再往上出栈堆栈 [0012FF90]=005AC139 (CWoool.005AC139)
005AC15A E8 08000000 call CWoool.005AC167
005AC15F F0:69EE 8F1C25FA lock imul ebp,esi,FA251C8F ; 不允许锁定前缀
005AC166 AB stos dword ptr es:[edi]
005AC167 BE 87E9C62D mov esi,2DC6E987 ;ESI=2DC6E987
005AC16C 58 pop eax ;返回地址出栈EAX=005AC15F
005AC16D 83EB 04 sub ebx,4 ;EBX-4
005AC170 80D0 4C adc al,4C ;005AC15F ADC 4C
005AC173 81FB 7CF8FFFF cmp ebx,-784 ;EBX为计数器
005AC179 0F85 14000000 jnz CWoool.005AC193 ;为算完往下跳
005AC17F 0FB7F2 movzx esi,dx ;ESI低字节为005AC92D的低字节
005AC182 E9 26000000 jmp CWoool.005AC1AD ;循环出口
005AC193 0FB7C3 movzx eax,bx ;
005AC196 ^ E9 60FFFFFF jmp CWoool.005AC0FB ;往回跳
看到这里我们就知道是一个算法循环,我这样叙述:
以005AC92D为起始地址,往低每隔四个字节取地址数据进行运算,先是减去0CC5DC6C,然后与20EFF235异或,接着减去
6BF476CA所得的值放回原处,如此循环直到地址005AC1AD为止!
继续往下看:
005AC1AD 66:81C2 C5D5 add dx,0D5C5 ;EDX=5A9EF2
005AC1B2 E8 0F000000 call CWoool.005AC1C6 ;跟进
005AC1C6 68 58BB343C push 3C34BB58 ;3C34BB58入栈
005AC1CB E9 0C000000 jmp CWoool.005AC1DC ;跳转
005AC1D0 04 ED add al,0ED
005AC1D2 22B3 70E96E0F and dh,byte ptr ds:[ebx+F6EE970>
005AC1D8 9C pushfd
005AC1D9 A5 movs dword ptr es:[edi],dword p>
005AC1DA 7A 2B jpe short CWoool.005AC207
005AC1DC 59 pop ecx ;ECX=3C34BB58
005AC1DD 58 pop eax ;返回地址出栈堆栈 [0012FF90]=005AC1B7 (CWoool.005AC1B7)
005AC1DE E8 0C000000 call CWoool.005AC1EF ;跟进
005AC1E3 34 5D xor al,5D
005AC1E5 D2A3 A0591EFF shl byte ptr ds:[ebx+FF1E59A0],>
005AC1EF /E9 0B000000 jmp CWoool.005AC1FF ;跳转
005AC1F4 |F764CD 82 mul dword ptr ss:[ebp+ecx*8-7E]
005AC1FF 5E pop esi ; 返回地址出栈堆栈 [0012FF90]=005AC1E3 (CWoool.005AC1E3)
005AC200 81C0 75070000 add eax,775 ;005AC1B7+775=005AC92C
005AC206 66:81D9 940F sbb cx,0F94 ;3C34BB58低位减0F94
005AC20B 2BFF sub edi,edi ;EDI清零
005AC20D BE 39EDC518 mov esi,18C5ED39 ;ESI=18C5ED39
005AC212 8B1C38 mov ebx,dword ptr ds:[eax+edi] ;ds:[005AC92C]=08A7AB8A
005AC215 66:81D2 FB37 adc dx,37FB ;地址005A9EF2 ADC 37FB =005AD6ED
005AC21A 81C3 F860357D add ebx,7D3560F8 ;EBX=ds:[005AC92C]-7D3560F8=85DD0C82
005AC220 66:8BF0 mov si,ax ;005AC92C低位入si
005AC223 81F3 D109160B xor ebx,0B1609D1 ;EBX=(ds:[005AC92C]-7D3560F8) XOR 0B1609D1=8ECB0053
005AC229 81EB 360C0618 sub ebx,18060C36 ;EBX=((ds:[005AC92C]-7D3560F8) XOR 0B1609D1)-18060C36=76C4F91D
005AC22F 8ACE mov cl,dh ;FB放入cl
005AC231 891C38 mov dword ptr ds:[eax+edi],ebx ;计算值放回原处005AC92C
005AC234 E9 0C000000 jmp CWoool.005AC245 ;跳
005AC239 F4 hlt
005AC23A 1D 92636019 sbb eax,19606392
005AC23F DEBF 8CD5EADB fidivr word ptr ds:[edi+DBEAD58C]
005AC245 0FB7F2 movzx esi,dx ;dx=D6ED
005AC248 83EF 04 sub edi,4 ;D6ED-4
005AC24B 0FB7F3 movzx esi,bx
005AC24E 81FF 60F9FFFF cmp edi,-6A0 ;EDI为计数器
005AC254 0F85 13000000 jnz CWoool.005AC26D ;不等则跳
005AC25A B9 A713045D mov ecx,5D0413A7 ;ECX=5D0413A7
005AC25F E9 2C000000 jmp CWoool.005AC290 ;出口
005AC26D 68 D804010D push 0D0104D8 ;0D0104D8
005AC272 66:BA F096 mov dx,96F0 ;DX=96F0
005AC276 5E pop esi ;ESI=0D0104D8
005AC277 ^ E9 96FFFFFF jmp CWoool.005AC212 ;往回跳
这里也是一个循环:
以005AC92C为起始地址,往低每隔四个字节取地址数据进行运算,按以下运算
((ds:[005AC92C]-7D3560F8) XOR 0B1609D1)-18060C36
所得的值放回原处,如此循环直到地址005AC290为止!
注意005AC215和005AC21A时EDX=005ACEEB ASCII "iantChangeTypeEx",呵呵,这个有问题啊,我们分析一下他怎么来的,
我们用回溯法:
005AC272 66:BA F096 mov dx,96F0 ;DX=96F0
005AC215 66:81D2 FB37 adc dx,37FB ;
005AC1AD 66:81C2 C5D5 add dx,0D5C5 ;EDX=5A9EF2
005AC0DE 81C2 5C080000 add edx,85C ;edx=005AC0D1 (CWoool.005AC0D1)+85c=005AC92D,到005AC92D看看,后面全部是
;零,看来005AC92D是一段代码的边界了.
看到没有这个iantChangeTypeEx事先准备好后经过找到他的!
继续分析:
005AC290 8BF2 mov esi,edx ;edx=005ACEEB ASCII "iantChangeTypeEx"
005AC292 E8 12000000 call CWoool.005AC2A9 ;跟进
005AC297 22B3 70E96E0F and dh,byte ptr ds:[ebx+F6EE970]
005AC29D 9C pushfd
005AC2A9 5A pop edx ;返回地址出栈EDX=0059C297
005AC2AA E8 10000000 call CWoool.005AC2BF ;跟进
005AC2AF B8 91F6F764 mov eax,64F7F691
005AC2B4 CD 82 int 82
005AC2B6 93 xchg eax,ebx
005AC2B7 D0C9 ror cl,1
005AC2B9 CE into
005AC2BA EF out dx,eax
005AC2BB FC cld
005AC2BC 85DA test edx,ebx
005AC2BE 0B5F 81 or ebx,dword ptr ds:[edi-7F]
005AC2C1 C2 9506 retn 695
005AC2BF 5F pop edi ; 返回地址出栈堆栈 [0012FF90]=005AC2AF
005AC2C0 81C2 95060000 add edx,695 ;EDX=0059C297+695=0059C92C
005AC2C6 BE F5B53274 mov esi,7432B5F5 ;ESI=7432B5F5
005AC2CB BB 00000000 mov ebx,0 ;EBX=0
005AC2D0 E9 06000000 jmp CWoool.005AC2DB
005AC2DB 8B041A mov eax,dword ptr ds:[edx+ebx] ;又来了,肯定又是算法部分[0059C92C]=76C4F91D
005AC2DE 0F8D 17000000 jge CWoool.005AC2FB ;跳走
005AC2FB 81E8 BE7EF45B sub eax,5BF47EBE ;[0059C92C]-5BF47EBE=1AD07A5F
005AC301 81E8 1F0BAC6A sub eax,6AAC0B1F ;[0059C92C]-5BF47EBE-6AAC0B1F=B0246F40
005AC307 66:8BF2 mov si,dx ;SI=C92C,ESI=7432C92C
005AC30A 81C0 6C5E9E4F add eax,4F9E5E6C ;[0059C92C]-5BF47EBE-6AAC0B1F+4F9E5E6C=FFC2CDAC
005AC310 66:8BCF mov cx,di ;CX=C2AF
005AC313 50 push eax ;FFC2CDAC入栈
005AC314 68 66FEC94B push 4BC9FE66 ;4BC9FE66入栈
005AC319 80C5 C0 add ch,0C0 ;5D0482AF
005AC31C 5F pop edi ;EDI=4BC9FE66
005AC31D 8F041A pop dword ptr ds:[edx+ebx] ;换一种方法把[0059C92C]-5BF47EBE-6AAC0B1F+4F9E5E6C传回去
005AC320 66:8BF9 mov di,cx ;cx=82AF,di=FE66
005AC323 0F8E 08000000 jle CWoool.005AC331 ;
005AC329 68 97364C1D push 1D4C3697
005AC32E B1 A5 mov cl,0A5
005AC330 5E pop esi
005AC331 83EB 01 sub ebx,1
005AC334 4B dec ebx
005AC335 4B dec ebx
005AC336 4B dec ebx ;EBX=-4,其实就是上面的四个字节的变形
005AC337 E9 0C000000 jmp CWoool.005AC348 ;这里是出口
005AC348 81FB 24FAFFFF cmp ebx,-5DC ;比较是否为-5DC
005AC34E ^ 0F85 87FFFFFF jnz CWoool.005AC2DB ;往回跳
005AC354 59 pop ecx
005AC355 3102 xor dword ptr ds:[edx],eax
005AC357 77 71 ja short CWoool.005AC3CA
005AC359 E4 00 in al,0
005AC35B D7 xlat byte ptr ds:[ebx+al]
005AC35C 1D A1683647 sbb eax,473668A1
第三个算法是非常good的部分:
这个算法的起始地址为0059C92C,而结束地址为0059C354,呵呵,结束时正好紧接在我们这个算法之后,假如运算完变成了
005AC354 E8 05000000 call CWoool.005AC35E
005AC359 B9 FE5FAC75 mov ecx,75AC5FFE
005AC35E 66:BF D6AA mov di,0AAD6
005AC362 5E pop esi
005AC363 B3 9E mov bl,9E
005AC365 81C6 D2050000 add esi,5D2
005AC36B B9 6B767804 mov ecx,478766B
005AC370 81E9 21757804 sub ecx,4787521
005AC376 B0 A7 mov al,0A7
005AC378 FF36 push dword ptr ds:[esi]
知道这三个算法是什么了吗?就是解码,所以说那位兄弟说这三个算法之前的是解码部分,呵呵,应该是这里.总结第三个
算法为:
[0059C92C]-5BF47EBE-6AAC0B1F+4F9E5E6C
这部分的总结:
这部分利用了SMC技术加密代码后,再在壳中解码.(呵呵,不知下面还有没有)
--------------------------------------------------------------------------------
【版权声明】 本文纯属技术交流, 转载请注明作者并保持文章的完整, 谢谢!