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
本代码的着色效果由xTiNt自动完成
下载xTiNt http://211.90.75.84/web/kanaun/download/xTiNt.rar
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)