股市风暴4.0的外壳分析与脱壳方法(一) (7千字)
标题:股市风暴4.0的外壳分析与脱壳方法所用工具:trw2000,Procdump
等级:手动脱壳入门
前言:股市风暴这个软件本身对我没有多大用处,但是它的外壳让我花费了相当长的时间,现在终于基本明白了它的流程,写下来,与那些对脱壳感兴趣的同志共同交流。
正文:
对于一个加壳的程序,常见的暴力破解方法一般有两种,一种是直接地脱壳,另外一种是利用SMC,即在外壳程序中加入一段额外的代码,当外壳对程序处理完毕后改变外壳的流程,跳转到加入的额外代码中,在内存中对生成的原程序进行修改,达到暴破的目的。对付SMC的常见方法也是运用SMC,即外壳程序也是在运行中动态生成,使破解者无法在外壳运行结束后轻易改变流程。这点在这个外壳中可以说有很充分的表现。当程序载入后可以看到如下代码:
0167:005E3000 PUSHA <-入口
0167:005E3001 CALL 005E40F3
0167:005E3006 RET
0167:005E3007 AND DWORD [EDI-22],BYTE +21
0167:005E300B ADD BH,[EDI-3E]
0167:005E300E SCASB
0167:005E300F XCHG BH,[EBX+54]
当程序运行到5E3006后会RET到另一处执行一段程序,运行完后又回到5E3007,此时代码已经变为:
0167:005E3000 PUSHA
0167:005E3001 CALL 005E40F3
0167:005E3006 RET
0167:005E3007 ADD EBX,BYTE +07
0167:005E300A REP JMP SHORT 005E300C
0167:005E300D JECXZ 005E2F92
0167:005E300F RET
0167:005E3010 SBB EDX,[EBX-18]
可以看到下面的代码已经完全改变,这就是SMC。如果你很好奇跟进那段SMC代码你会发现,那段代码执行完后会自行销毁,看来外壳作者实在很小心谨慎。
SMC代码由此开始直到5E3197有近十重之多。当一个外壳运用SMC动态生成代码有3重以上时一般用SMC来暴破就很困难了。十重!天哪,还是放弃用SMC暴破的念头吧。
当这些SMC工作全部完成后(事实上后面还有),是对外壳做一些初始(希望我没有搞错),包括对一些函数取他们的入口值,比如ExitProcess、LoadLibraryA等,等这些完成后就进入了外壳中真正重要的部分。
对于一个保护良好的外壳,antidebug是必须的,不在这方面留心一下的话恐怕连自己怎么被干掉都不知道了。下面就是他的antidebug代码。
:005E3468 8D8539040000 lea eax, dword ptr [ebp+00000439]
:005E346E 50 push eax <-EAX=5E3479,异常处理程序地址
:005E346F 33C0 xor eax, eax
:005E3471 64FF30 push dword ptr fs:[eax]
:005E3474 648920 mov dword ptr fs:[eax], esp <-建立SEH链
:005E3477 EB10 jmp 005E3489
:005E3479 8B642408 mov esp, dword ptr [esp+08] <-异常处理程序入口,在此下断点
:005E347D 8B6C2408 mov ebp, dword ptr [esp+08]
:005E3481 8D854F040000 lea eax, dword ptr [ebp+0000044F]
:005E3487 50 push eax
:005E3488 C3 ret <-到5E348F继续执行
:005E3489 CC int 03 <-下faults off,经过时产生异常可中断在上面入口,如不下faults off,经过时不产生异常就debugger detected了
:005E348A E911010000 jmp 005E35A0
:005E348F 8D8561040000 lea eax, dword ptr [ebp+00000461]
:005E3495 89442404 mov dword ptr [esp+04], eax
:005E3499 646789260000 mov fs:[0000], esp
:005E349F EB10 jmp 005E34B1
:005E34A1 8B642408 mov esp, dword ptr [esp+08]
:005E34A5 8B6C2408 mov ebp, dword ptr [esp+08]
:005E34A9 8D85A8040000 lea eax, dword ptr [ebp+000004A8]
:005E34AF 50 push eax
:005E34B0 C3 ret
:005E34B1 0F018D8E120000 sidt [ebp+0000128E] <-取IDTR的内容
:005E34B8 8B8590120000 mov eax, dword ptr [ebp+00001290] <-取IDT表的基地址
:005E34BE 83C04E add eax, 0000004E
:005E34C1 668B18 mov bx, word ptr [eax]
:005E34C4 C1E310 shl ebx, 10
:005E34C7 668B5802 mov bx, word ptr [eax+02] <-EBX为INT10的入口偏移
:005E34CB B8000C0000 mov eax, 00000C00
:005E34D0 813B45524548 cmp dword ptr [ebx], 48455245
:005E34D6 0F84C4000000 je 005E35A0
:005E34DC 813B524F4753 cmp dword ptr [ebx], 53474F52
:005E34E2 74F2 je 005E34D6
以INT10的入口为起点,在C00长度范围内查找字符串"EREH"和"ROGS",如找到则判断为有DEBUG程序驻留。why?
:005E34E4 43 inc ebx
:005E34E5 48 dec eax
:005E34E6 7FE8 jg 005E34D0 <-没有找到,继续往下
:005E34E8 8D85BA040000 lea eax, dword ptr [ebp+000004BA]
:005E34EE 89442404 mov dword ptr [esp+04], eax
:005E34F2 646789260000 mov fs:[0000], esp
:005E34F8 EB10 jmp 005E350A
:005E34FA 8B642408 mov esp, dword ptr [esp+08] <-又是一个异常处理程序入口,可下断点
:005E34FE 8B6C2408 mov ebp, dword ptr [esp+08]
:005E3502 8D85DE040000 lea eax, dword ptr [ebp+000004DE]
:005E3508 50 push eax
:005E3509 C3 ret <-跳到5E351E
:005E350A 9C pushfd \
:005E350B 810C2400010000 or dword ptr [esp], 00000100 \
:005E3512 7502 jne 005E3516 >注意
:005E3514 CD20 int 20 /
:005E3516 9D popfd /
上面这几行作用是将单步执行标志TF置真,然后在执行下一句时产生单步异常,就会中断在上面异常处理程序入口,如果在这还单步走或在下面两句下断点的话,破坏了单步标志,不产生异常就GAME OVER了;
:005E3517 F8 clc
:005E3518 0F8382000000 jnb 005E35A0
:005E351E 8D85F0040000 lea eax, dword ptr [ebp+000004F0]
:005E3524 89442404 mov dword ptr [esp+04], eax
:005E3528 646789260000 mov fs:[0000], esp
:005E352E EB10 jmp 005E3540
:005E3530 8B642408 mov esp, dword ptr [esp+08]
:005E3534 8B6C2408 mov ebp, dword ptr [esp+08]
:005E3538 8D8517050000 lea eax, dword ptr [ebp+00000517]
:005E353E 50 push eax
:005E353F C3 ret
:005E3540 66B80043 mov ax, 4300 \
:005E3544 CD68 int 68 \
:005E3546 80BDC410000000 cmp byte ptr [ebp+000010C4], 00 \检测softice
:005E354D 7408 je 005E3557 /
:005E354F 66057B0C add ax, 0C7B /
:005E3553 6648 dec ax /
:005E3555 7449 je 005E35A0 <-检测到就跳
:005E3557 8D8529050000 lea eax, dword ptr [ebp+00000529]
:005E355D 89442404 mov dword ptr [esp+04], eax
:005E3561 646789260000 mov fs:[0000], esp
:005E3567 EB10 jmp 005E3579
:005E3569 8B642408 mov esp, dword ptr [esp+08]
:005E356D 8B6C2408 mov ebp, dword ptr [esp+08]
:005E3571 8D8554050000 lea eax, dword ptr [ebp+00000554]
:005E3577 50 push eax
:005E3578 C3 ret
:005E3579 F685C4100000FF test byte ptr [ebp+000010C4], FF
:005E3580 7412 je 005E3594
:005E3582 7501 jne 005E3585
:005E3585 BD4B484342 MOV EBP,4243484B \
:005E358A 6A04 PUSH BYTE +04 \
:005E358C 58 POP EAX >再次检测softice
:005E358D CC INT3 /
:005E358E 663D0400 CMP AX,04 /
:005E3592 750C jne 005E35A0 <-检测到就跳
:005E3594 64678F060000 pop word ptr fs:[0000]
:005E359A 83C404 add esp, 00000004
:005E359D 5D pop ebp
:005E359E EB16 jmp 005E35B6 <-一切正常
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:005E348A(U), :005E34D6(C), :005E3518(C), :005E3555(C), :005E3592(C)
|
:005E35A0 64678F060000 pop word ptr fs:[0000]<-debugger detected,退出
:005E35A6 83C404 add esp, 00000004
:005E35A9 5D pop ebp
:005E35AA 81ED06D24000 sub ebp, 0040D206
:005E35B0 E9D8070000 jmp 005E3D8D
:005E35B5 C3 ret
:005E35B6 8BDD mov ebx, ebp <-如果没发现DEBUG程序就到这儿
:005E35B8 81ED06D24000 sub ebp, 0040D206
:005E35BE 8DBD3AE34000 lea edi, dword ptr [ebp+0040E33A]
