• 标 题:SoftDefender主程序脱壳
  • 作 者:shinegood
  • 时 间:2003年12月13日 10:52
  • 链 接:http://bbs.pediy.com

呵呵,昨天朋友过生日,玩的尽兴,今天早上6点才回来 :P ,休息好了,把关于SoftDefender 主程序脱壳手记附上

借Fly兄的格式用用,Fly兄的破文生成器能不能给我一份??
PS:这个壳实际是国产软件,我最近才知道的……

SoftDefender V1.12 DEMO 主程序脱壳
  
  
  
下载地址:  http://www.softdefender.com/setup.exe  
应用平台:  Win 98/ME/NT/2000/XP/2003  
软件大小:  600 K  

【软件简介】:Soft Defender is a powerful tool securing products against crackers.It was designed with ease of use and high speed as a priority without sacrificing high levels of protection.With Soft Defender, your application can have anticrack, antidebug, antidisassemble, antidump, anti-apihook, file integrity checking functions in seconds. It requires no source code editing or your registration algorithm changing. In addition, Soft Defender is a perfect exe file compressor, which can reduce the file size of 32-bit Windows programs by as much as 50%. 

【作者声明】:只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教! 

【调试环境】:WinXP、Ollydbg1.09、PEiD、LordPE、ImportREC 1.6.0 Final 

—————————————————————————————————  
【脱壳过程】: 

废话不说,直接进入主题,我这里的A和B都是必须的哟

          ★★★★★★★★★★★★ 
★★★★★ A、对于父进程的跟踪分析★★★★★ 
          ★★★★★★★★★★★★ 

用OD载入SoftDefender.exe,隐藏好IsDebuggerPresent标记,断在入口点:
<ModuleEn> /74 07           je short SoftDefe.004D1009      ;这实际就是个Jmp嘛~,这个壳里大量用到这样的变形Jmp
004D1002   |75 05           jnz short SoftDefe.004D1009      ;
004D1004   |1932            sbb dword ptr ds:[edx], esi
004D1006   |67:E8 E8741F75  call 756C84F4                            ; Superfluous prefix
004D100C    1D E8683944     sbb eax, 443968E8

直接下断 bp ZwQueryInformationProcess (嘿嘿,这个特殊,壳不检查前5个字节),F9,OD断下,这个我们不需要,再F9,OD又断下
ZwQueryIn>/$  B8 9A000000   mov eax, 9A                ;断在这
77F7603A  |.  BA 0003FE7F   mov edx, 7FFE0300
77F7603F  |.  FFD2          call edx
77F76041  .  C2 1400       retn 14

执行到返回,再F8到这
004D8FAE    85C0            test eaxeax          ;返回到这,F8
004D8FB0    75 08           jnz short SoftDefe.004D8FBA    ;这里一定要跳,在004D8FBA用New Origin here,或者用Fly兄的修改标志寄存器也可以,最好的方法自然是前面一步修改eax的值为非0
004D8FB2    8B4424 08       mov eaxdword ptr ss:[esp+8]
004D8FB6    85C0            test eaxeax
004D8FB8    75 0E           jnz short SoftDefe.004D8FC8
004D8FBA    E8 4BFFFFFF     call SoftDefe.004D8F0A    ;Jmp to here
004D8FBF    85C0            test eaxeax
004D8FC1    75 05           jnz short SoftDefe.004D8FC8

现在我们在命令栏里输入follow GetTickCount,反汇编窗口显示
GetTickCo>  BA 0000FE7F     mov edx, 7FFE0000                        
77E5A2A0    8B02            mov eaxdword ptr ds:[edx]
77E5A2A2    F762 04         mul dword ptr ds:[edx+4]
77E5A2A5    0FACD0 18       shrd eaxedx, 18
77E5A2A9    C3              retn         ;这里按F4,当然你也可以在这里做点小手脚 :twisted: 
F8返回
004D8171    894424 0C       mov dword ptr ss:[esp+C], eax
004D8175    8B4424 10       mov eaxdword ptr ss:[esp+10]
004D8179    83F8 04         cmp eax, 4

在[esp+C]处下内存访问断点,  注意这里开始有分岔路咯~F9 Go,OK,OD断在这
004D6F27    8A0411          mov albyte ptr ds:[ecx+edx]
004D6F2A    8801            mov byte ptr ds:[ecx], al
004D6F2C    41              inc ecx
004D6F2D    4E              dec esi
004D6F2E  ^ 75 F7           jnz short SoftDefe.004D6F27
004D6F30    8BC7            mov eaxedi

此时去掉内存断点。
呵呵,看到这个表示我们是在调试父进程,下面父进程要做的事是建立临时文件,写入前面GetTickCount所得值的加密值,再CreateProcessA建立子进程,随后自己退出,CreateProcessA我们没办法跟进去,不过主导思想是既然CreateProcessA是执行同一个文件,那么保存好现在的现场,用OD再次载入SoftDefender模拟子进程,OK,我们可以用follow CloseHandle
CloseHandl>  64:A1 18000000  mov eaxdword ptr fs:[18]   ;No BreakPoint here :wink: 
77E5A6F6     8B48 30         mov ecxdword ptr ds:[eax+30]
77E5A6F9     8B4424 04       mov eaxdword ptr ss:[esp+4]
77E5A6FD     83F8 F4         cmp eax, -0C
77E5A700   ^ 0F84 7E93FFFF   je kernel32.77E53A84
只要你不在第一句下断点就没问题,F9 Go,断在你下断的地方,这个CloseHandle实际是关闭临时文件的句柄,如果父进程始终不CloseHandle的话系统是不会取消这个内核的,这样也方便我们后面对子进程的调试嘛 :P 

到此,父进程的工作已经完成了,我们留着这个OD
==========================================
          ★★★★★★★★★★★★★ 
★★★★★ B、对于子进程的跟踪分析 ★★★★★ 
          ★★★★★★★★★★★★★ 


新开一个OD,再次载入SoftDefender.exe
前面的过程和父进程一样,绕过ZwQueryInformationProcess的Anti,到前面我说的分岔路口那,当你再[esp+C]处下内存访问断点后,F9 Go,稍等一会,OD会断在这
004D81E2    8B4C24 0C       mov ecxdword ptr ss:[esp+C]   ;Stop here
004D81E6    8B5424 08       mov edxdword ptr ss:[esp+8]
004D81EA    2BCA            sub ecxedx
004D81EC    81F9 401F0000   cmp ecx, 1F40
004D81F2    72 66           jb short SoftDefe.004D825A   ;一定要跳!
呵呵,这个父子进程的时间差,过长的话子进程就执行父进程的作用,写入新值,CreateProcessA另一个新的进程…………
004D81F4    83FF 03         cmp edi, 3
004D81F7    74 25           je short SoftDefe.004D821E
004D81F9    6A 00           push 0

跳到这里,怎么修改程序运行轨道我就不再说了
004D825A    5F              pop edi
004D825B    B8 08000000     mov eax, 8
004D8260    5E              pop esi
004D8261    81C4 40010000   add esp, 140
004D8267    C3              retn

OK,F9吧,程序运行了,我们成功模拟了子进程,兴奋不??
我们千辛万苦绕过那些Anti,这么一个F9就全完了????OEP,Import都还没搞定那…………
是的,全完了,不过我们也可以获得一个重要的情况,外壳会自己清除关键代码,向上翻,会发现有很长一段都是
004D137B    0000            add byte ptr ds:[eax], al
其实就是00,被清除了的代码,这里是我们找OEP的关键
重复子进程前面的过程,最后不要F9了,而是在其中某一个地方,比如
004D1487处下一个硬写断点(这个位置我没有试,我每次都是随机选的)
F9 Go,直到断在下面这个位置为止
004D5E78    F3:AA           rep stos byte ptr es:[edi]
004D5E7A    C3              retn
F8执行到retn,下面就是要返回到OEP了,如果你要是一高兴用F8按下去,那将是一个恶梦,因为我们这个时候看看栈堆
0012EB90   0044D3DD  SoftDefe.0044D3DD
0012EB94   0044D3A3  SoftDefe.0044D3A3
0012EB98   0044D399  SoftDefe.0044D399
0012EB9C   0044D374  RETURN to SoftDefe.0044D374 from SoftDefe.00447CF1
0012EBA0   0044D31C  RETURN to SoftDefe.0044D31C from SoftDefe.00403480

…… …… ……

0012FFB4   00429790  SoftDefe.00429790
0012FFB8   00429760  SoftDefe.00429760
0012FFBC   004296CA  SoftDefe.004296CA
0012FFC0   0042966D  SoftDefe.0042966D    ;这里才是目的地,飞向光明之颠?? :lol: 
0012FFC4   004D5748  SoftDefe.004D5748
0012FFC8   77D64F70  user32.77D64F70

OK,G 0042966D吧
0042966D    FF15 688F1400   call dword ptr ds:[148F68]   ;注意这个call,进去看看
00429673    64:A1 00000000  mov eaxdword ptr fs:[0]
00429679    50              push eax
0042967A    64:8925 0000000>mov dword ptr fs:[0], esp
00429681    83EC 58         sub esp, 58

进入call [148F68]后
00169BB0    58              pop eax---------------------------------------
00169BB1    55              push ebp
00169BB2    8BEC            mov ebpesp
00169BB4    6A FF           push -1                     Stolen Byte!!!
00169BB6    68 E02C4500     push 452CE0
00169BBB    68 48C74200     push 42C748
00169BC0    FFE0            jmp eax   -------------------------------------

而pop eax和jmp eax实际就是retn的变形,将Stolen Byte还原
00429664    55              push ebp
00429665    8BEC            mov ebpesp
00429667    6A FF           push -1
00429669    68 E02C4500     push 00452CE0
0042966E    68 48C74200     push 0042C748
00429673    64:A1 00000000  mov eaxdword ptr fs:[0]
00429679    50              push eax
0042967A    64:8925 0000000>mov dword ptr fs:[0], esp

好了,这个时候可以用LordPE来Dump了

下面让我们看看输入表,基本都被修改了,除了几个只有一个引用函数的Dll没有被加密,我们的目标就是————修复它 :lol: 
用ImportRec的trace Level 3还有17个没有修复,自己模拟跟踪一下就知道了 :wink: 
我是通过修改程序里的一个内存值达到防止ImportTable被破坏的
这里就是恢复并修改ImportTable的代码了
004D88E7    52              push edx
004D88E8    50              push eax
004D88E9    57              push edi
004D88EA    E8 6DF5FFFF     call SoftDefe.004D7E5C
004D88EF    8B8424 40040000 mov eaxdword ptr ss:[esp+440]   ;我要改这个地址的值为0 :o  :o 
004D88F6    85C0            test eaxeax
004D88F8    0F84 BA010000   je SoftDefe.004D8AB8   ;这里跳的话就不会破坏Import Table了
004D88FE    8B4424 18       mov eaxdword ptr ss:[esp+18]
004D8902    85C0            test eaxeax
004D8904    74 10           je short SoftDefe.004D8916
004D8906    8B4C24 10       mov ecxdword ptr ss:[esp+10]
004D890A    57              push edi
004D890B    51              push ecx
004D890C    E8 90160000     call SoftDefe.004D9FA1
004D8911    E9 AD010000     jmp SoftDefe.004D8AC3

…… …… ……

004D8A90    E8 24E5FFFF     call SoftDefe.004D6FB9
004D8A95    85C0            test eaxeax
004D8A97    75 0C           jnz short SoftDefe.004D8AA5
004D8A99    68 8E764000     push SoftDefe.0040768E
004D8A9E    E8 E0D3FFFF     call SoftDefe.004D5E83
004D8AA3    EB 1E           jmp short SoftDefe.004D8AC3
004D8AA5    8B5424 10       mov edxdword ptr ss:[esp+10]
004D8AA9    57              push edi
004D8AAA    52              push edx
004D8AAB    E8 35EAFFFF     call SoftDefe.004D74E5
004D8AB0    50              push eax
004D8AB1    E8 B3F8FFFF     call SoftDefe.004D8369
004D8AB6    EB 0B           jmp short SoftDefe.004D8AC3
004D8AB8    8B4424 10       mov eaxdword ptr ss:[esp+10]
004D8ABC    57              push edi
004D8ABD    50              push eax
004D8ABE    E8 22EAFFFF     call SoftDefe.004D74E5
004D8AC3    33C9            xor ecxecx
004D8AC5    8906            mov dword ptr ds:[esi], eax    ;这里就写入了

所以要想办法让它在那能断下来,在
004D81E2    8B4C24 0C       mov ecxdword ptr ss:[esp+C]   ;Stop here
004D81E6    8B5424 08       mov edxdword ptr ss:[esp+8]
004D81EA    2BCA            sub ecxedx
004D81EC    81F9 401F0000   cmp ecx, 1F40
004D81F2    72 66           jb short SoftDefe.004D825A   ;一定要跳!

跳完以后,如果在004D88EF处直接下硬执行断点有问题,估计和OD本身有关,可能是个Bug,要先在0044E000处下内存断点,F9,会断下,之后按4次F9后再在004D88EF处下硬执行断点,再F9,等断在004D88EF时,修改[esp+440]的值为0,取消硬断点以及内存断点,再g 42966d,如果程序停住了就暂停一下再继续执行,就能到OEP了,这个时候就可以用ImportREC来修复了,一个坏的都没有,是不是很爽啊 :lol: 

OK,Fix Dump吧,然后优化一下