• 标 题:Hying旧版壳的简单脱壳
  • 作 者:loveboom
  • 时 间:2004-12-02,14:10
  • 链 接:http://bbs.pediy.com

Hying旧版壳的简单脱壳
【目     标】:天堂xxxx(因为是外挂,所以不写全名)
【工     具】:Olydbg1.1(diy版)、LORDPE、ImportREC1.6F 
【任     务】:简单的脱一下目标的壳 
【操作平台】:WinXP sp2
【作     者】:loveboom[DFCG][FCG][US]
【相关链接】: 自己去上网搜搜
【简要说明】: 这个一个很旧的Hying的壳了,现在脱的话就非常简单了,不过看过新版的朋友就知道,新版BT很多,不过也不是那么神秘的:-)。介于关于他的壳的信息比较少,所以写一个大概的。
【详细过程】:
用peid直接看的话显示是的yc的壳,不过我之前接触过几个hying的壳,因此我用扩展方式可以看到是PELOCK ->Hying *,知道是什么壳就好办了,之前在大牛hexer的指导(不明之处看的他以前那篇文章)下跟了一个新版的壳,所以这个旧版相对来说很简单的.好了入主题先.
设置忽略全部异常,去除调试标志.
载入在ep处.
005D4DA8 >  60              PUSHAD                                   ; ep入口是伪yoda crypt的
005D4DA9    E8 00000000     CALL 005D4DAE
005D4DAE    5D              POP EBP
载入后直接在:code段下f2断点.
Memory map, item 14
 Address=00401000
 Size=001AC000 (1753088.)
 Owner=L2Walker 00400000
 Section=
 Contains=code
 Type=Imag 01001002
 Access=R
 Initial access=RWE
下断后,f9运行。这样中断在这里:
00373670    AC              LODS BYTE PTR DS:[ESI]                   ; 中断在这里
00373671    D2C8            ROR AL,CL
00373673    32C1            XOR AL,CL
00373675    04 66           ADD AL,66
00373677    32C5            XOR AL,CH
00373679    02C6            ADD AL,DH
0037367B    2AC2            SUB AL,DL
0037367D    02C1            ADD AL,CL
0037367F    2AC5            SUB AL,CH
00373681    32C2            XOR AL,DL
00373683    04 23           ADD AL,23
00373685    32C6            XOR AL,DH
00373687    F6D0            NOT AL
00373689    D2C8            ROR AL,CL
0037368B    D3CA            ROR EDX,CL
0037368D    AA              STOS BYTE PTR ES:[EDI]
0037368E    49              DEC ECX
0037368F    0BC9            OR ECX,ECX
00373691  ^ 75 DD           JNZ SHORT 00373670
00373693    53              PUSH EBX
00373694    6A 04           PUSH 4
00373696    68 00100000     PUSH 1000
0037369B    FF342B          PUSH DWORD PTR DS:[EBX+EBP]
0037369E    6A 00           PUSH 0
003736A0    8D85 001D4000   LEA EAX,DWORD PTR SS:[EBP+401D00]
003736A6    50              PUSH EAX
003736A7    8B85 33374000   MOV EAX,DWORD PTR SS:[EBP+403733]
003736AD    E9 010E0000     JMP 003744B3
003736B2  - E9 897C24EC     JMP EC5BB340
003736B7    897424 E8       MOV DWORD PTR SS:[ESP-18],ESI
003736BB    FF85 47374000   INC DWORD PTR SS:[EBP+403747]
003736C1    8B9D 6B374000   MOV EBX,DWORD PTR SS:[EBP+40376B]
003736C7    83FB 01         CMP EBX,1
003736CA    75 0E           JNZ SHORT 003736DA
003736CC    61              POPAD
003736CD    8B4424 CC       MOV EAX,DWORD PTR SS:[ESP-34]
003736D1    8D78 02         LEA EDI,DWORD PTR DS:[EAX+2]
003736D4    55              PUSH EBP
003736D5    8BEC            MOV EBP,ESP
003736D7    50              PUSH EAX
003736D8    EB 20           JMP SHORT 003736FA
003736DA    83FB 02         CMP EBX,2
003736DD    75 15           JNZ SHORT 003736F4
003736DF    61              POPAD
003736E0    8B4424 C8       MOV EAX,DWORD PTR SS:[ESP-38]
003736E4    FFB0 6F374000   PUSH DWORD PTR DS:[EAX+40376F]
003736EA    8B4424 D0       MOV EAX,DWORD PTR SS:[ESP-30]
003736EE    50              PUSH EAX
003736EF    8D78 02         LEA EDI,DWORD PTR DS:[EAX+2]
003736F2    EB 06           JMP SHORT 003736FA
003736F4    61              POPAD
003736F5    8B4424 CC       MOV EAX,DWORD PTR SS:[ESP-34]
003736F9    50              PUSH EAX                                 ; 这里跳去oep
003736FA    C3              RETN
断下后经过几个跟踪发003736f9处就是push OEP .继续往下找,找到这里:
003737D3    87E6            XCHG ESI,ESP
003737D5    B9 7F0B0000     MOV ECX,0B7F
003737DA    58              POP EAX                                  ; 这里循环解压下面的代码
003737DB    F6D0            NOT AL
003737DD    50              PUSH EAX
003737DE    44              INC ESP
003737DF  ^ E2 F9           LOOPD SHORT 003737DA
003737E1    87E6            XCHG ESI,ESP                             ; 所以我们直接在这里下f4
003737E3    6A 04           PUSH 4
003737E5    68 00100000     PUSH 1000
003737EA    68 00200000     PUSH 2000
003737EF    6A 00           PUSH 0
003737F1    FF95 33374000   CALL DWORD PTR SS:[EBP+403733]           ; VirtualAlloc
003737F7    8985 3C3D4000   MOV DWORD PTR SS:[EBP+403D3C],EAX
003737FD    C785 403D4000 0>MOV DWORD PTR SS:[EBP+403D40],0
00373807    74 7A           JE SHORT 00373883
00373809    9C              PUSHFD
0037380A    C8 BFFFF4       ENTER 0FFBF,0F4
0037380E    3F              AAS
0037380F    F0:7A 42        LOCK JPE SHORT 00373854                  ; LOCK prefix is not allowed
00373812    FFFF            ???                                      ; Unknown command
直接F4到3737E1处后看看代码已经解压了,现在好看很多.
下面的部分跟过hying的壳的朋友就知道壳是通过.取出API函数先判断代码是否要抽API代码,如果要的话就抽部分代码到壳申请的指定地址里实现
push api
ret
的方式,如果没要抽代码的就直接push ret的方式。
所以我现在要找到跳去api的代码,这个很容易,看看代码里有很多这样的代码:
0037383B    8B85 2B374000   MOV EAX,DWORD PTR SS:[EBP+40372B]
00373841    E9 6D0C0000     JMP 003744B3                             ; 这里一个
00373846    81340B C0751E56 XOR DWORD PTR DS:[EBX+ECX],561E75C0
0037384D    8D85 661E4000   LEA EAX,DWORD PTR SS:[EBP+401E66]
00373853    50              PUSH EAX
00373854    8B85 2F374000   MOV EAX,DWORD PTR SS:[EBP+40372F]
0037385A    E9 540C0000     JMP 003744B3                             ; 这里又一个
所以可以判断003744b3处是处理API的.进去看看:
003744B3    50              PUSH EAX
003744B4    8B85 383D4000   MOV EAX,DWORD PTR SS:[EBP+403D38]
003744BA    50              PUSH EAX
003744BB    E8 08000000     CALL 003744C8
003744C0    8B85 383D4000   MOV EAX,DWORD PTR SS:[EBP+403D38]
003744C6    FFE0            JMP EAX                                  ; 跳去push api ret的地址
003744C8    60              PUSHAD                                   ; 这里开始处理API
003744C9    8B7C24 24       MOV EDI,DWORD PTR SS:[ESP+24]
003744CD    8B7424 28       MOV ESI,DWORD PTR SS:[ESP+28]
003744D1    66:8B06         MOV AX,WORD PTR DS:[ESI]
003744D4    3C 50           CMP AL,50
003744D6    72 0A           JB SHORT 003744E2                        ; ******
003744D8    3C 57           CMP AL,57                                ; 开始判断要不要特别"照顾"
003744DA    77 06           JA SHORT 003744E2
003744DC    8807            MOV BYTE PTR DS:[EDI],AL
003744DE    46              INC ESI
003744DF    47              INC EDI
……
003745F2   /E9 AD120000     JMP 003758A4
003745F7   |66:3D CD03      CMP AX,3CD
003745FB   |75 05           JNZ SHORT 00374602
003745FD   |E9 A2120000     JMP 003758A4
00374602   |C607 68         MOV BYTE PTR DS:[EDI],68                 ; 这里变成push api ret的方式
00374605   |8977 01         MOV DWORD PTR DS:[EDI+1],ESI
00374608   |C647 05 C3      MOV BYTE PTR DS:[EDI+5],0C3
0037460C   |83C7 06         ADD EDI,6
0037460F   |897C24 FC       MOV DWORD PTR SS:[ESP-4],EDI
00374613   |61              POPAD
00374614   |8B4424 DC       MOV EAX,DWORD PTR SS:[ESP-24]
00374618   |C2 0800         RETN 8
分析完代码后我们就要动“手术”了,在003744d6处改成:

003744D6   /E9 27010000     JMP 00374602            ;这里跳过就直接成了
push api 
retn
的方式防止壳抽代码
F4到了003737E1后,几个F8就到了处理IAT处了:
003738D8    0395 7F374000   ADD EDX,DWORD PTR SS:[EBP+40377F]
003738DE    8B3A            MOV EDI,DWORD PTR DS:[EDX]
003738E0    0BFF            OR EDI,EDI                               ; 判断有没有处理完iat
003738E2    75 05           JNZ SHORT 003738E9
003738E4    E9 53050000     JMP 00373E3C                             ; 处理完iat就跳
003738E9    03BD 37374000   ADD EDI,DWORD PTR SS:[EBP+403737]
003738EF    83C2 05         ADD EDX,5
003738F2    8BF2            MOV ESI,EDX
003738F4    56              PUSH ESI
003738F5    8D85 0E1F4000   LEA EAX,DWORD PTR SS:[EBP+401F0E]
003738FB    50              PUSH EAX
003738FC    8B85 2B374000   MOV EAX,DWORD PTR SS:[EBP+40372B]        ; GetModuleHandleA
00373902    E9 AC0B0000     JMP 003744B3
00373907    90              NOP
00373908    90              NOP
00373909    0BC0            OR EAX,EAX
0037390B    75 1E           JNZ SHORT 0037392B                       ; 判断有没有载入DLL如果没有就先LoadLibrary载入DLL
0037390D    56              PUSH ESI
0037390E    8D85 271F4000   LEA EAX,DWORD PTR SS:[EBP+401F27]
00373914    50              PUSH EAX
00373915    8B85 2F374000   MOV EAX,DWORD PTR SS:[EBP+40372F]
0037391B    E9 930B0000     JMP 003744B3                             ; LoadLibraryA
00373920    FF15 0BC07505   CALL DWORD PTR DS:[575C00B]
00373926    E9 9D0D0000     JMP 003746C8
0037392B    0FB64E FF       MOVZX ECX,BYTE PTR DS:[ESI-1]
0037392F    03F1            ADD ESI,ECX
00373931    8BD6            MOV EDX,ESI
00373933    8BF0            MOV ESI,EAX
00373935    42              INC EDX
00373936    8B0A            MOV ECX,DWORD PTR DS:[EDX]
00373938    81E1 00000080   AND ECX,80000000
0037393E    0BC9            OR ECX,ECX
00373940    0F85 87000000   JNZ 003739CD                             
00373946    8B0A            MOV ECX,DWORD PTR DS:[EDX]
……
003739CD    8B0A            MOV ECX,DWORD PTR DS:[EDX]
003739CF    81E1 FFFFFF7F   AND ECX,7FFFFFFF
003739D5    51              PUSH ECX
003739D6    52              PUSH EDX
003739D7    C1E1 05         SHL ECX,5
003739DA    6A 04           PUSH 4
003739DC    68 00100000     PUSH 1000
003739E1    51              PUSH ECX
003739E2    6A 00           PUSH 0
003739E4    8D85 FC1F4000   LEA EAX,DWORD PTR SS:[EBP+401FFC]
003739EA    50              PUSH EAX
003739EB    8B85 33374000   MOV EAX,DWORD PTR SS:[EBP+403733]        ; VirtualAlloc
003739F1    E9 BD0A0000     JMP 003744B3
……
00373A0A   /74 15           JE SHORT 00373A21
00373A0C   |03BD 37374000   ADD EDI,DWORD PTR SS:[EBP+403737]
00373A12   |EB 09           JMP SHORT 00373A1D
00373A14   |8907            MOV DWORD PTR DS:[EDI],EAX               ; 往原始IAT处填入第一层加密地址
00373A16   |83C0 20         ADD EAX,20
00373A19   |83C7 04         ADD EDI,4
00373A1C   |49              DEC ECX
00373A1D   |0BC9            OR ECX,ECX
00373A1F  ^|75 F3           JNZ SHORT 00373A14
00373A21   \59              POP ECX
00373A22    58              POP EAX
00373A23    8BF8            MOV EDI,EAX
00373A25    57              PUSH EDI
00373A26    51              PUSH ECX
00373A27    EB 2D           JMP SHORT 00373A56
00373A29    8D47 1C         LEA EAX,DWORD PTR DS:[EDI+1C]            ; 这里开始对第层加密地址变成
push [addr]
xor [esp],xorkey
ret
这里的ret就是返回到第真正去api的地址:
00373A2C    66:C707 FF35    MOV WORD PTR DS:[EDI],35FF
00373A31    C747 06 8134240>MOV DWORD PTR DS:[EDI+6],243481
00373A38    8947 02         MOV DWORD PTR DS:[EDI+2],EAX
00373A3B    C647 0D C3      MOV BYTE PTR DS:[EDI+D],0C3
00373A3F    52              PUSH EDX
00373A40    0F31            RDTSC
00373A42    32E0            XOR AH,AL
00373A44    C1C8 08         ROR EAX,8
00373A47    02E0            ADD AH,AL
00373A49    C1C8 08         ROR EAX,8
00373A4C    32E0            XOR AH,AL
00373A4E    8947 09         MOV DWORD PTR DS:[EDI+9],EAX
00373A51    5A              POP EDX
00373A52    83C7 20         ADD EDI,20
00373A55    49              DEC ECX
00373A56    0BC9            OR ECX,ECX
00373A58  ^ 75 CF           JNZ SHORT 00373A29                       ; 跳回去继续
00373A5A    59              POP ECX
为了方便我们后面的操作我把它变成:
push [addr]
xor [esp],xorkey
ret
的方式变成
PUSH [ADDR]
XOR [ESP],XORKEY
ADD ESP,4
RET
用于后面的操作,具体代码如下:
00373A38    8947 02         MOV DWORD PTR DS:[EDI+2],EAX
00373A3B    C647 0D C3      MOV BYTE PTR DS:[EDI+D],0C3
;这里用于处理成add esp,4的方式
00373A38  - E9 03C60000     JMP 00380040
00373A3D    90              NOP
00373A3E    90              NOP
在00380040处写上几句:
00380040    8947 02         MOV DWORD PTR DS:[EDI+2],EAX
00380043    C747 0D 83C404C>MOV DWORD PTR DS:[EDI+D],C304C483 ;变成add esp,4 ret的方式
0038004A  - E9 F039FFFF     JMP 00373A3F
0038004F    90              NOP
继续跟到这里:
00373ABB    8D95 C73B4000   LEA EDX,DWORD PTR SS:[EBP+403BC7]        ; 这里取出正确的函数
00373AC1    52              PUSH EDX
00373AC2    52              PUSH EDX
00373AC3    8D85 283A4000   LEA EAX,DWORD PTR SS:[EBP+403A28]        ; 这里取出特殊API函数,判断是否要特别"照顾"
00373AC9    50              PUSH EAX
00373ACA    8D85 E2204000   LEA EAX,DWORD PTR SS:[EBP+4020E2]
00373AD0    50              PUSH EAX
00373AD1    8B85 60384000   MOV EAX,DWORD PTR SS:[EBP+403860]        ; lstrcmpiA比较是否为特别函数
00373AD7    E9 D7090000     JMP 003744B3
00373ADC    90              NOP
00373ADD    5A              POP EDX
00373ADE    85C0            TEST EAX,EAX
00373AE0    75 0B           JNZ SHORT 00373AED                       ; 如果不是特别的函数就跳,后面还有很多这样的比较,所以我们这里又改改
00373AE2    8D85 E72F4000   LEA EAX,DWORD PTR SS:[EBP+402FE7]
00373AE8    E9 31030000     JMP 00373E1E
……
00373D9F    52              PUSH EDX                                 ; 没有特别函数最后就到这里
00373DA0    56              PUSH ESI
00373DA1    8D85 B9234000   LEA EAX,DWORD PTR SS:[EBP+4023B9]
00373DA7    50              PUSH EAX
00373DA8    8B85 27374000   MOV EAX,DWORD PTR SS:[EBP+403727]        ; GetProcAddress,获取API
00373DAE    E9 00070000     JMP 003744B3
00373DB3  ^ 75 8B           JNZ SHORT 00373D40
00373DB5    9D              POPFD
00373DB6    3C 3D           CMP AL,3D
00373DB8    40              INC EAX
00373DB9    0003            ADD BYTE PTR DS:[EBX],AL
00373DBB    9D              POPFD
00373DBC    40              INC EAX
00373DBD    3D 40005350     CMP EAX,50530040
00373DC2    53              PUSH EBX
00373DC3    E8 00070000     CALL 003744C8                            ; 这里进去就是壳放API的代码,前面已经跟过,所以不再跟进
好了,我们现在改一下,让壳“一律对待”。
00373AE0   /E9 BA020000     JMP 00373D9F        ;这里跳过就直接跳过特殊函数的加密
00373AE5   |90              NOP
……
00373DC8    2B85 3C3D4000   SUB EAX,DWORD PTR SS:[EBP+403D3C]
00373DCE    8985 403D4000   MOV DWORD PTR SS:[EBP+403D40],EAX
00373DD4    60              PUSHAD
00373DD5    3D C01F0000     CMP EAX,1FC0
00373DDA    76 3E           JBE SHORT 00373E1A                       ; 判断是否够空间放iat
00373DDC    6A 04           PUSH 4
00373DDE    68 00100000     PUSH 1000
00373DE3    68 00200000     PUSH 2000
00373DE8    6A 00           PUSH 0
00373DEA    8D85 0F244000   LEA EAX,DWORD PTR SS:[EBP+40240F]
00373DF0    50              PUSH EAX
00373DF1    8B85 33374000   MOV EAX,DWORD PTR SS:[EBP+403733]        ; VirtualAlloc
00373DF7    E9 B7060000     JMP 003744B3
00373DFC    EB 64           JMP SHORT 00373E62
00373DFE    8F05 00000000   POP DWORD PTR DS:[0]
00373E04    58              POP EAX
00373E05  ^ E9 8BFEFFFF     JMP 00373C95
00373E0A    8985 3C3D4000   MOV DWORD PTR SS:[EBP+403D3C],EAX
00373E10    C785 403D4000 0>MOV DWORD PTR SS:[EBP+403D40],0
00373E1A    61              POPAD
00373E1B    5B              POP EBX
00373E1C    8BC3            MOV EAX,EBX
00373E1E    3347 09         XOR EAX,DWORD PTR DS:[EDI+9]
00373E21    8947 1C         MOV DWORD PTR DS:[EDI+1C],EAX
00373E24    5A              POP EDX
00373E25    0FB642 FF       MOVZX EAX,BYTE PTR DS:[EDX-1]
00373E29    03D0            ADD EDX,EAX
00373E2B    42              INC EDX
00373E2C    83C7 20         ADD EDI,20
00373E2F    59              POP ECX
00373E30    49              DEC ECX
00373E31  ^ 0F85 28FCFFFF   JNZ 00373A5F                             ; 对指定的DLL没有处理完则回去继续
00373E37  ^ E9 A2FAFFFF     JMP 003738DE                             ; 处理完则指向下一个DLL
到了这里我们就不用再跟什么了,直接在003736f9处下断.
003736F9    50              PUSH EAX                                 ; 这里跳去oep
003736FA    C3              RETN
运行之.
00373F0E  ^\EB FA           JMP SHORT 00373F0A                       ; 第一个异常
00373F10    8985 43374000   MOV DWORD PTR SS:[EBP+403743],EAX
……
00373E94    6285 443D4000   BOUND EAX,QWORD PTR SS:[EBP+403D44]      ; 第二个异常
00373E9A  ^ EB F8           JMP SHORT 00373E94
过了第二个异常后在我们下断的地方断下来了.断下了,现在要再写一段程序来修复代码:
003736FA    60              PUSHAD                                   ; 保护现场
003736FB    9C              PUSHFD
003736FC    BE 28814D00     MOV ESI,4D8128                           ; 取原始IAT的地址
00373701    81FE F4824D00   CMP ESI,4D82F4                           ; 判断有没有结束
00373707    73 1F           JNB SHORT 00373728
00373709    8B1E            MOV EBX,DWORD PTR DS:[ESI]               ; 取出第一层加密地址
0037370B    83FB 00         CMP EBX,0                                ; 用于判断是否为0的情况
0037370E    74 13           JE SHORT 00373723
00373710    81FB 0000C000   CMP EBX,0C00000                          ; 判断是否加密后的地址
00373716    73 0B           JNB SHORT 00373723
00373718    FFD3            CALL EBX                                 ; call第一层的内容
0037371A    8B5C24 F8       MOV EBX,DWORD PTR SS:[ESP-8]             ; 第一次的3f0000这段是返回到第二层地址处
0037371E    8B5B 01         MOV EBX,DWORD PTR DS:[EBX+1]             ; 因为我们前面已经path 了代码,所以这里直接 [ebx+1]就是正确IAT地址
00373721    891E            MOV DWORD PTR DS:[ESI],EBX               ; 把API写入正确的位置
00373723    83C6 04         ADD ESI,4
00373726  ^ EB D9           JMP SHORT 00373701
00373728    9D              POPFD
00373729    61              POPAD
0037372A    C3              RETN
这样处理后,用IMP看一下,两有两个地方没有修复,这个简单,把上面的代码改几句就行了.具体的我修改很简单,我也不多讲了.
最后有一个无效的函数,直接CUT就行了.

Greetz:
 Fly.Jingulong,yock,tDasm.David.ahao.UFO(brother).alan(sister).all of my friends and you!

By loveboom[DFCG][FCG][US]
Email:bmd2chen#tom.com