meishenm 发表于 2010-5-24 20:08:56

Themida/WinLicense V1.8.2.0 脱壳的祥细过程

标 题: 【分享】Themida/WinLicense V1.8.2.0 脱壳的祥细过程(不明白细节者适用)
作 者: redrose
时 间: 2007-07-26,22:22:03
链 接: http://bbs.pediy.com/showthread.php?t=48586

【文章标题】: Themida/WinLicense V1.8.2.0 + 脱壳的祥细过程(不明白细节者适用)
【文章作者】: redrose
【软件名称】: 未知
【软件大小】: 未知
【下载地址】: 自己搜索下载
【加壳方式】: Themida/WinLicense V1.8.2.0 +-> Oreans Technologies   * Sign.By.fly *
【编写语言】: Microsoft Visual C++ 7.0
【使用工具】: OllyICE v1.10汉化第二版,LordPE豪华版,SuperImportREC,peid0.94
【操作平台】: WinXP_SP2
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!感谢wynney兄的共享及okdodo兄的脚本!!
--------------------------------------------------------------------------------
【详细过程】
第一步:用peid查壳可得知加壳方法为:Themida/WinLicense V1.8.2.0 +-> Oreans Technologies   * Sign.By.fly *
          如果查不出是什么壳,请更新peid程序里userdb.txt的内容,看雪论坛有下载。
第二步:OllyICE v1.10设置--忽略在KERNEL32中的内存访问异常;隐藏调试工具;
第三步:加载被调试程序停在程序入口:
00730014 >B8 00000000   mov   eax, 0
00730019    60            pushad
0073001A    0BC0            or      eax, eax
0073001C    74 68         je      short 00730086
0073001E    E8 00000000   call    00730023
00730023    58            pop   eax
00730024    05 53000000   add   eax, 53
00730029    8038 E9         cmp   byte ptr , 0E9
0073002C    75 13         jnz   short 00730041
0073002E    61            popad
0073002F    EB 45         jmp   short 00730076
00730031    DB2D 37007300   fld   tbyte ptr
00730037    FFFF            ???               ; 未知命令 ,如果隐藏OD在调试过程中还是退出
请注意OD的浮点陷井(呵呵)
00730039    FFFF            ???                                    ; 未知命令
0073003B    FFFF            ???                                    ; 未知命令
0073003D    FFFF            ???                                    ; 未知命令
0073003F    3D 40E80000   cmp   eax, 0E840
00730044    0000            add   byte ptr , al
00730046    58            pop   eax

接着运行okdodo兄的脚本,脚本结束后到

脚本执行完毕!请注意OEP是否被偷代码!

0061C920    68 DC686100   push    006168DC                伪OEP,① call 0061c920 看堆栈
0061C925    64:A1 00000000mov   eax, dword ptr fs:
0061C92B    50            push    eax
0061C92C    8B4424 10       mov   eax, dword ptr
0061C930    896C24 10       mov   dword ptr , ebp
0061C934    8D6C24 10       lea   ebp, dword ptr
0061C938    2BE0            sub   esp, eax
0061C93A    53            push    ebx
0061C93B    56            push    esi
0061C93C    57            push    edi
0061C93D    8B45 F8         mov   eax, dword ptr
0061C940    8965 E8         mov   dword ptr , esp
0061C943    50            push    eax
0061C944    8B45 FC         mov   eax, dword ptr
0061C947    C745 FC FFFFFFF>mov   dword ptr , -1
0061C94E    8945 F8         mov   dword ptr , eax
0061C951    8D45 F0         lea   eax, dword ptr
0061C954    64:A3 00000000mov   dword ptr fs:, eax
0061C95A    C3            retn    ; 直接F4,F8到VM中
堆栈如下:
0012FF8C   0097480DSungame.0097480D   
0012FF90   006C15E8Sungame.006C15E8    ② push 006C15E8
0012FF94   00000060                      ③ push 60,在这里

直接F4,F8到VM中到
0097480D    68 CD05892B   push    2B8905CD    ; ALt+M在代码段00401000 F2下断后shift+F9
00974812^ E9 63B1FFFF   jmp   0096F97A
00974817    0AF3            or      dh, bl
00974819    F61429          not   byte ptr
0097481C    C6            ???                                    ; 未知命令
0097481D    CD C7         int   0C7
0097481F    BA 68476083   mov   edx, 83604768
00974824    53            push    ebx
00974825^ E9 50B1FFFF   jmp   0096F97A
到这里后按下ALt+M 在代码段00401000 F2下断 后shift+F9运行中断在
006169E0    3D 00100000   cmp   eax, 1000               ; ④Call 006169E0
006169E5    73 0E         jnb   short 006169F5
006169E7    F7D8            neg   eax
006169E9    03C4            add   eax, esp
006169EB    83C0 04         add   eax, 4
006169EE    8500            test    dword ptr , eax
006169F0    94            xchg    eax, esp
006169F1    8B00            mov   eax, dword ptr
006169F3    50            push    eax
006169F4    C3            retn                                     ; 直接F4,F8到VM中
直接F4,F8到VM中到
00974820    68 47608353   push    53836047                        
00974825^ E9 50B1FFFF   jmp   0096F97A
0097482A    399E 8C165657   cmp   dword ptr , ebx
00974830    09A2 9385E6EC   or      dword ptr , esp
00974836    15 688ED6FE   adc   eax, FED68E68
0097483B    26:E9 39B1FFFFjmp   0096F97A
Alt+M在代码段00401000 F2下断后shift+F9运行后中断在
00EA098D    FF33            push    dword ptr ;kernel32.GetVersionExA,ebx=0069D088
00EA098F    E9 A5830000   jmp   00EA8D39
00EA0994    01FB            add   ebx, edi
00EA0996    332B            xor   ebp, dword ptr
00EA0998    E9 ED520000   jmp   00EA5C8A
00EA099D    B8 01000000   mov   eax, 1
00EA09A2    21C1            and   ecx, eax
00EA09A4    E9 1BD20400   jmp   00EEDBC4
00EA09A9    81FA 000000F0   cmp   edx, F0000000

注意EDX里面的值(0069D088)得就是GetVersionExA所在的地址了

在寄存器窗口中在0069D088这里跟随到数据窗口,后到

0069D0887C812ADEkernel32.GetVersionExA
0069D08C7C809BF8kernel32.MultiByteToWideChar
0069D0907C80A0D4kernel32.WideCharToMultiByte
………………
往上看后往下看可知道
0069CFFC00000000
0069D00077DC1558ADVAPI32.CryptEncrypt         IAT开始地址
0069D00477DA7883ADVAPI32.RegQueryValueExA
0069D00877DCC41BADVAPI32.RegOpenKeyA
…………………………………………
0069D4901000F870wzSound.wzsnd_update_3d_source
0069D4941000F9A0wzSound.wzsnd_stop
0069D49800000000
0069D49C00000000                   IAT结束地址,好了这里不明白自动找的和手动找的怎么不一样。

Rav=0069CFFC-0040000=0029CFFC,Size=0069D49C-0069CFFC=4A0 这里在修复时可用到

第四步:找回Stolen Code(这里和wynney兄的一样了,我只写出重点部分)
Ctrl+B在数据窗口整个块中搜索33 C0 39 B1 E8 00 00 00 0F 95 C0 89 45 E4 6A 01
汇编代码就是下面一段:
0061874C    33C0            xor   eax, eax
0061874E    39B1 E8000000   cmp   dword ptr , esi
00618754    0F95C0          setne   al
00618757    8945 E4         mov   dword ptr , eax
0061875A    6A 01         push    1
找到所在地址为0061874C后,在反汇编中来到这个地址
0061874C    33C0            xor   eax, eax
0061874E    39B1 E8000000   cmp   dword ptr , esi
00618754    0F95C0          setne   al
00618757    8945 E4         mov   dword ptr , eax
0061875A    6A 01         push    1
往上仔细看看和没加壳的程序对比一下,确定006186A4就是真正的OEP
如果看不出来请仔细看没加壳的VC++7.0的OEP入口代码

00618693    ED            in      eax, dx                        ; 真OEP;=③
00618694    C7            ???                                    ; 未知命令
00618695    1A05 165DAC93   sbb   al, byte ptr           ; (1)=②
0061869B    EF            out   dx, eax
0061869C    93            xchg    eax, ebx
0061869D    A0 1DED9822   mov   al, byte ptr
006186A2    7D 0C         jge   short 006186B0
006186A4    ED            in      eax, dx
006186A5    B1 19         mov   cl, 19
006186A7    32CE            xor   cl, dh
006186A9    85F3            test    ebx, esi
006186AB    FB            sti
006186AC    8CFD            mov   bp, seg?                         ; 未定义的段寄存器
006186AE    98            cwde
006186AF    52            push    edx
006186B0    8B91 BB7D6B9E   mov   edx, dword ptr
006186B6    4E            dec   esi
006186B7    2A30            sub   dh, byte ptr
006186B9    9E            sahf
006186BA    65:B7 2B      mov   bh, 2B
006186BD    6389 507206CA   arpl    word ptr , cx
006186C3    7A 95         jpe   short 0061865A
006186C5    A3 08927200   mov   dword ptr , eax          ; (5)=(7)+08
006186CA    8B56 08         mov   edx, dword ptr
006186CD    8915 0C927200   mov   dword ptr , edx          ; (6)=(7)+0C
006186D3    8B76 0C         mov   esi, dword ptr
006186D6    81E6 FF7F0000   and   esi, 7FFF
006186DC    8935 00927200   mov   dword ptr , esi          ; (7)
006186E2    83F9 02         cmp   ecx, 2
006186E5    74 0C         je      short 006186F3
006186E7    81CE 00800000   or      esi, 8000
006186ED    8935 00927200   mov   dword ptr , esi
006186F3    C1E0 08         shl   eax, 8
006186F6    03C2            add   eax, edx
006186F8    A3 04927200   mov   dword ptr , eax
006186FD    33F6            xor   esi, esi
006186FF    56            push    esi
00618700    8B3D 10D16900   mov   edi, dword ptr           ; kernel32.GetModuleHandleA
00618706    FFD7            call    edi
00618708    66:8138 4D5A    cmp   word ptr , 5A4D
0061870D    75 1F         jnz   short 0061872E
0061870F    8B48 3C         mov   ecx, dword ptr
00618712    03C8            add   ecx, eax
00618714    8139 50450000   cmp   dword ptr , 4550
0061871A    75 12         jnz   short 0061872E
0061871C    0FB741 18       movzx   eax, word ptr
00618720    3D 0B010000   cmp   eax, 10B
00618725    74 1F         je      short 00618746
00618727    3D 0B020000   cmp   eax, 20B
0061872C    74 05         je      short 00618733
0061872E    8975 E4         mov   dword ptr , esi
00618731    EB 27         jmp   short 0061875A
00618733    83B9 84000000 0>cmp   dword ptr , 0E
0061873A^ 76 F2         jbe   short 0061872E
0061873C    33C0            xor   eax, eax
0061873E    39B1 F8000000   cmp   dword ptr , esi
00618744    EB 0E         jmp   short 00618754
00618746    8379 74 0E      cmp   dword ptr , 0E
0061874A^ 76 E2         jbe   short 0061872E
0061874C    33C0            xor   eax, eax                      我们搜索的位置
0061874E    39B1 E8000000   cmp   dword ptr , esi
00618754    0F95C0          setne   al
00618757    8945 E4         mov   dword ptr , eax
0061875A    6A 01         push    1

好了,现在根据wynney兄所提到的各地址之间的关系
   引用:
    { 以 ⑺为基点有以下关系
      OEP位置=③
      ⑴=②,⑵=①,⑶=④
      ⑷=⑺-04,⑸=⑺+08,⑹=⑺+0C
      
      那么其他的都一样的啦
      对VC++ 7.0而言,以上关系是永远存在的
   }
找到我们标记的③的地方,改汇编后接着改⑴=②的地方,接着⑵=①的地方,下面两段代码就用原来没加壳前的代码,接着是⑶=④的地方,以下四段代码照原来没加壳的代码改写,接着
call    dword ptr 这里是从上面来的
接着有一段代码用原来没加壳的就可以,代码改好了现在要注意的是⑷=⑺-04,729200-04=7291FC得来;
⑸=⑺+08,⑹=⑺+0C,这两个的能看出来了,我就不写了

还原Stolen Code后代码如下
/////////////////////////////////////////////////////////////////////////////
00618693    6A 60         push    60                               ; 真OEP;=③
00618695    68 E8156C00   push    006C15E8                         ; (1)=②
0061869A    E8 81420000   call    0061C920                         ; (2)=①
0061869F    BF 94000000   mov   edi, 94
006186A4    8BC7            mov   eax, edi
006186A6    E8 35E3FFFF   call    006169E0                         ; (3)=④
006186AB    8965 E8         mov   dword ptr , esp
006186AE    8BF4            mov   esi, esp
006186B0    893E            mov   dword ptr , edi
006186B2    56            push    esi
006186B3    FF15 88D06900   call    dword ptr    ; kernel32.GetVersionExA
006186B9    8B4E 10         mov   ecx, dword ptr
006186BC    890D FC917200   mov   dword ptr , ecx          ; (4)=(7)-04
006186C2    8B46 04         mov   eax, dword ptr
机器码如下:在这里也可以用机器码改写,我刚才一步步是为了给大家能看懂
6A 60 68 E8 15 6C 00 E8 81 42 00 00 BF 94 00 00 00 8B C7 E8 35 E3 FF FF 89 65 E8 8B F4 89    3E 56 FF 15 88 D0 69 00 8B 4E 10 89 0D FC 91 72 00 8B 46 04
///////////////////////////////////////////////////////////
006186C5    A3 08927200   mov   dword ptr , eax          ; (5)=(7)+08
006186CA    8B56 08         mov   edx, dword ptr
006186CD    8915 0C927200   mov   dword ptr , edx          ; (6)=(7)+0C
006186D3    8B76 0C         mov   esi, dword ptr
006186D6    81E6 FF7F0000   and   esi, 7FFF
006186DC    8935 00927200   mov   dword ptr , esi          ; (7)
006186E2    83F9 02         cmp   ecx, 2
006186E5    74 0C         je      short 006186F3
006186E7    81CE 00800000   or      esi, 8000
006186ED    8935 00927200   mov   dword ptr , esi
006186F3    C1E0 08         shl   eax, 8
006186F6    03C2            add   eax, edx
006186F8    A3 04927200   mov   dword ptr , eax
006186FD    33F6            xor   esi, esi
006186FF    56            push    esi
00618700    8B3D 10D16900   mov   edi, dword ptr           ; kernel32.GetModuleHandleA
00618706    FFD7            call    edi
00618708    66:8138 4D5A    cmp   word ptr , 5A4D
0061870D    75 1F         jnz   short 0061872E
0061870F    8B48 3C         mov   ecx, dword ptr
00618712    03C8            add   ecx, eax
00618714    8139 50450000   cmp   dword ptr , 4550
0061871A    75 12         jnz   short 0061872E
0061871C    0FB741 18       movzx   eax, word ptr
00618720    3D 0B010000   cmp   eax, 10B
00618725    74 1F         je      short 00618746
00618727    3D 0B020000   cmp   eax, 20B
0061872C    74 05         je      short 00618733
0061872E    8975 E4         mov   dword ptr , esi
00618731    EB 27         jmp   short 0061875A
00618733    83B9 84000000 0>cmp   dword ptr , 0E
0061873A^ 76 F2         jbe   short 0061872E
0061873C    33C0            xor   eax, eax
0061873E    39B1 F8000000   cmp   dword ptr , esi
00618744    EB 0E         jmp   short 00618754
00618746    8379 74 0E      cmp   dword ptr , 0E
0061874A^ 76 E2         jbe   short 0061872E
0061874C    33C0            xor   eax, eax
0061874E    39B1 E8000000   cmp   dword ptr , esi
00618754    0F95C0          setne   al
00618757    8945 E4         mov   dword ptr , eax
0061875A    6A 01         push    1


上面代码还原完成。
第五步:脱壳和修复。
在00618693,也就是OEP的地方,设置为新EIP后,用LordPE工具Dump得到1.exe(注意这里别连网线,网线接上就dump不出来的,原因我还没找,这次没接网线又不成功,晕了用OD自带的吧,好了有了)。
打开SuperImportREC,填入以下(这里上面已经说明怎么得到的了)
OEP=00618693-00400000=00218693
   Rav=0069CFFC-00400000=0029CFFC
Size=0069D498-0069D49C=4A0      
接着获取输入表,没有无效函数,修复1.exe完成得到1_.exe,现在我们看看有没有脱掉并且能不能运行,这里看到了不能运行了,方法就是上面的,请大家仔细点,别出错,我的可能是在那步出错了,我这是录第二次了,第一次录的已经可以运行,但没录下来,这次又不能运行了,晕了,小弟不才呀!!!好了可以运行了,脱壳完成,另外有朋友说壳脱了,但是在登陆后选角色时,和服务器断开连接了,对这点我再研究吧,谢谢各位了。

注:附件中有录像大家看看吧,上传不了,权限不够,如果那位朋友看出我错在哪里,请指出,谢谢。
http://www.love400.net/download/gametuoke.rar
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛及人世间论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2007年07月26日 18:51:21

仙剑奇侠 发表于 2010-5-26 00:10:38

lz正解,不过,可以直接用脱壳机托就好了

linj2000 发表于 2010-5-26 10:45:30

学习了,,,厉害,,交流下

ctt 发表于 2010-5-31 03:08:44

哈哈新手看多点

jy02318874 发表于 2010-8-30 22:55:46

我也新手!进来看看学习下!
页: [1]
查看完整版本: Themida/WinLicense V1.8.2.0 脱壳的祥细过程