.
【作者声明】:只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
【调试环境】:WinXP、Ollydbg V1.10、PEiD、LordPE
―――――――――――――――――――――――――――――――――
【脱壳过程】:
anota2.exe是taos发布在exetools论坛上的UnPackMe。“I've working 3 months in this project. A new protection system that includes a packer,antidebugging tricks (old and new), selfmodifying code, compress code section,etc...”
nikita@work很快就搞定了脱壳。“anota2.exe was created with Thinstall v2.4.61-2.5.14。note.exe (YodaProtect v1.02)、DLL45.DLL (YodaProtect v1.02)、steelbox inicio.bmp (just bmp) 、DLL2.DLL (PECompact)”。
脱壳时注意Thinstall和yoda's Protector就行了。
―――――――――――――――――――――――――――――――――
一、黑名单
设置Ollydbg忽略所有异常选项。老规矩:用IsDebug插件去掉Ollydbg的调试器标志。
00401A95 55 push ebp
//进入Ollydbg后暂停在这
00401A96 8BEC mov ebp,esp
00401A98 B8 08E180C8 mov eax,C880E108
00401A9D BB E51AAC80 mov ebx,80AC1AE5
00401AA2 50 push eax
00401AA3 E8 00000000 call anota2.00401AA8
如果你跟踪Thinstall部分,就会发现Thinstall封装的anota2.exe原来是有13个区段的。
下断:BP Process32Next
中断后取消断点,Alt+F9返回
00413A98 FF12 call dword ptr ds:[edx]; kernel32.Process32Next
00413A9A 85C0 test eax,eax
//返回这里
00413A9C 0F84 95000000 je anota2.00413B37
00413AA2 33DB xor ebx,ebx
00413AA4 EB 03 jmp short anota2.00413AA9
00413AA6 3E:8D09 lea ecx,dword ptr ds:[ecx]
00413AA9 56 push esi
00413AAA 8BD5 mov edx,ebp
00413AAC 81C2 65664200 add edx,426665
00413AB2 8B42 08 mov eax,dword ptr ds:[edx+8]
00413AB5 8D72 24 lea esi,dword ptr ds:[edx+24]
00413AB8 8BFE mov edi,esi
00413ABA 56 push esi
00413ABB 57 push edi
00413ABC E8 E00B0000 call anota2.004146A1
00413AC1 83C4 08 add esp,8
00413AC4 57 push edi
00413AC5 56 push esi
00413AC6 E8 700D0000 call anota2.0041483B
00413ACB 83C4 08 add esp,8
00413ACE 8BF7 mov esi,edi
00413AD0 56 push esi
00413AD1 57 push edi
00413AD2 8BD5 mov edx,ebp
00413AD4 81C2 15664200 add edx,426615
00413ADA 8D3A lea edi,dword ptr ds:[edx]
00413ADC B9 0D000000 mov ecx,0D
00413AE1 33D2 xor edx,edx
00413AE3 F3:A6 repe cmps byte ptr es:[edi],byte ptr ds:[esi]
//ESI=00415A53 转存中保存的是黑名单
004159DF 45 58 50 4C 4F 52 45 52 2E 45 58 45 00 5C 5C 2E>EXPLORER.EXE.\\.
004159EF 5C 53 49 43 45 00 5C 5C 2E 5C 4E 54 49 43 45 00>\SICE.\\.\NTICE.
简便省事,我们可以顺手把这里用00填充,去掉壳的黑名单就行了。 ―――――――――――――――――――――――――――――――――
二、搞定输入表,不用ImportREC了 Ctrl+S搜索命令序列:
lods byte ptr ds:[esi]
ror al,4
stos byte ptr es:[edi]
当然,也可以BP LoadLibraryA跟踪到下面。
00414F3A AC lods byte ptr ds:[esi]
//找到这里,直接F4过来
00414F3B C0C8 04 ror al,4
00414F3E AA stos byte ptr es:[edi]
//解出DLL名、函数名
00414F3F 3E:803F 00 cmp byte ptr ds:[edi],0
00414F43 75 F5 jnz short anota2.00414F3A
00414F45 5F pop edi
00414F46 5E pop esi
00414F47 C3 retn
00414F48 53 push ebx
00414F49 8BD5 mov edx,ebp
00414F4B 81C2 423E4200 add edx,423E42
00414F51 FF12 call dword ptr ds:[edx]; 7FF66698
//加密的在里面,如果用ImportREC则进入修改
00414F53 85C0 test eax,eax
00414F55 0F84 46010000 je anota2.004150A1
00414F5B 52 push edx
00414F5C 50 push eax
00414F5D 8BD5 mov edx,ebp
00414F5F 81C2 3D654200 add edx,42653D
00414F65 F702 04000000 test dword ptr ds:[edx],4
00414F6B 74 12 je short anota2.00414F7F
00414F6D 8BD5 mov edx,ebp
00414F6F 81C2 B55B4200 add edx,425BB5
00414F75 8D02 lea eax,dword ptr ds:[edx]
00414F77 50 push eax
00414F78 8BC3 mov eax,ebx
00414F7A E9 14060000 jmp anota2.00415593
//跳下去清空DLL名和函数名
00414F7F 5B pop ebx
00414F80 5A pop edx
00414F81 3E:8B4E 08 mov ecx,dword ptr ds:[esi+8]
00414F85 0BC9 or ecx,ecx
00414F87 75 04 jnz short anota2.00414F8D
00414F89 3E:8B4E 04 mov ecx,dword ptr ds:[esi+4]
00414F8D 53 push ebx
00414F8E 8BDD mov ebx,ebp
00414F90 81C3 55624200 add ebx,426255
00414F96 030B add ecx,dword ptr ds:[ebx]
00414F98 3E:8B56 04 mov edx,dword ptr ds:[esi+4]
00414F9C 0313 add edx,dword ptr ds:[ebx]
00414F9E 5B pop ebx
00414F9F 3E:8339 00 cmp dword ptr ds:[ecx],0
00414FA3 0F84 ED000000 je anota2.00415096
00414FA9 F701 00000080 test dword ptr ds:[ecx],80000000
00414FAF 75 5C jnz short anota2.0041500D
00414FB1 8B01 mov eax,dword ptr ds:[ecx]
00414FB3 83C0 02 add eax,2
00414FB6 53 push ebx
00414FB7 8BDD mov ebx,ebp
00414FB9 81C3 55624200 add ebx,426255
00414FBF 0303 add eax,dword ptr ds:[ebx]
00414FC1 5B pop ebx
00414FC2 50 push eax
00414FC3 E8 6CFFFFFF call anota2.00414F34
00414FC8 58 pop eax
00414FC9 8BF8 mov edi,eax
00414FCB 52 push edx
00414FCC 51 push ecx
00414FCD 50 push eax
00414FCE 53 push ebx
00414FCF 8BD5 mov edx,ebp
00414FD1 81C2 463E4200 add edx,423E46
00414FD7 FF12 call dword ptr ds:[edx]
00414FD9 0BC0 or eax,eax
00414FDB 75 07 jnz short anota2.00414FE4
00414FDD 59 pop ecx
00414FDE 5A pop edx
00414FDF E9 BD000000 jmp anota2.004150A1
00414FE4 59 pop ecx
00414FE5 5A pop edx
00414FE6 52 push edx
00414FE7 60 pushad
00414FE8 8BD5 mov edx,ebp
00414FEA 81C2 3D654200 add edx,42653D
00414FF0 F602 04 test byte ptr ds:[edx],4
00414FF3 74 12 je short anota2.00415007
00414FF5 8BD5 mov edx,ebp
00414FF7 81C2 3D5C4200 add edx,425C3D
00414FFD 8D02 lea eax,dword ptr ds:[edx]
00414FFF 50 push eax
00415000 8BC7 mov eax,edi
00415002 E9 8C050000 jmp anota2.00415593
00415007 61 popad
00415008 5A pop edx
00415009 8902 mov dword ptr ds:[edx],eax
//API函数的系统地址(加密地址)填充到IAT中 NOP掉 ②!★
0041500B EB 1D jmp short anota2.0041502A
0041500D 52 push edx
0041500E 51 push ecx
0041500F 8B01 mov eax,dword ptr ds:[ecx]
00415011 2D 00000080 sub eax,80000000
00415016 50 push eax
00415017 53 push ebx
00415018 8BD5 mov edx,ebp
0041501A 81C2 463E4200 add edx,423E46
00415020 FF12 call dword ptr ds:[edx]
00415022 85C0 test eax,eax
00415024 74 7B je short anota2.004150A1
00415026 59 pop ecx
00415027 5A pop edx
00415028 8902 mov dword ptr ds:[edx],eax
0041502A 51 push ecx
0041502B 8BCD mov ecx,ebp
0041502D 81C1 3D654200 add ecx,42653D
00415033 F701 20000000 test dword ptr ds:[ecx],20
00415039 74 4F je short anota2.0041508A
0041503B 8BCD mov ecx,ebp
0041503D 81C1 45654200 add ecx,426545
00415043 8339 00 cmp dword ptr ds:[ecx],0
00415046 74 14 je short anota2.0041505C
00415048 81FB 00000070 cmp ebx,70000000
0041504E 72 08 jb short anota2.00415058
00415050 81FB FFFFFF77 cmp ebx,77FFFFFF
00415056 76 0E jbe short anota2.00415066
00415058 EB 30 jmp short anota2.0041508A
0041505A EB 0A jmp short anota2.00415066
0041505C 81FB 00000080 cmp ebx,80000000
00415062 73 02 jnb short anota2.00415066
00415064 EB 24 jmp short anota2.0041508A
00415066 57 push edi
00415067 56 push esi
00415068 8BCD mov ecx,ebp
0041506A 81C1 65664200 add ecx,426665
00415070 8D39 lea edi,dword ptr ds:[ecx]
00415072 3E:8B77 04 mov esi,dword ptr ds:[edi+4]
00415076 8932 mov dword ptr ds:[edx],esi
00415078 2BC6 sub eax,esi
0041507A 83E8 05 sub eax,5
0041507D C606 E9 mov byte ptr ds:[esi],0E9
00415080 8946 01 mov dword ptr ds:[esi+1],eax
00415083 3E:8347 04 05 add dword ptr ds:[edi+4],5
00415088 5E pop esi
00415089 5F pop edi
0041508A 59 pop ecx
0041508B 83C1 04 add ecx,4
0041508E 83C2 04 add edx,4
00415091 E9 09FFFFFF jmp anota2.00414F9F
00415096 83C6 0C add esi,0C
00415099 E9 6BFEFFFF jmp anota2.00414F09
//循环处理输入表
0041509E 33C0 xor eax,eax
//修改两处后直接F4到这里
004150A0 40 inc eax
004150A1 83F8 01 cmp eax,1
004150A4 74 02 je short anota2.004150A8
004150A6 61 popad
004150A7 C3 retn
00415593 EB 05 jmp short anota2.0041559A
00415595 3E:C600 00 mov byte ptr ds:[eax],0
//清空DLL名和函数名 NOP掉① ! ★
//可以看一下第一个处理的DLL名的保存地址: 4083BC
00415599 40 inc eax
0041559A 3E:8038 00 cmp byte ptr ds:[eax],0
0041559E 75 F5 jnz short anota2.00415595
004155A0 C3 retn
到达0041509E后,程序代码已经解开,直接用Ollydbg的插件OllyDump先生去掉“重建输入表”选项来抓取这个进程,另存为UnPacked.exe。修改其NumberOfSections为0D。
上面修改的两个地方是把壳解压的DLL/函数名保存起来,不让API函数的系统地址/加密地址填充进IAT,这样就无须使用ImportREC来修复输入表了,直接找到Import Table地址就行了。下面根据DLL名来反推IID结构地址。
ADVAPI32.DLL在4083BC(0X83BC)处:
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F
000083B0 41 44 56 41 ADVA
000083C0 50 49 33 32 2E 44 4C 4C 00 00 47 44 49 33 32 2E PI32.DLL..GDI32.
000083D0 44 4C 4C 00 4B 45 52 4E 45 4C 33 32 2E 44 4C 4C DLL.KERNEL32.DLL
用WinHex打开UnPacked.exe,在000083BC上面搜索16进制值:BC830000
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F
00007400 B4 80 00 00 00 00 00 00 00 00 00 00 BC 83 00 00
00007410 38 82 00 00 C0 80 00 00 00 00 00 00 00 00 00 00
00008000 B4 80 00 00 00 00 00 00 00 00 00 00 BC 83 00 00
00008010 38 82 00 00 C0 80 00 00 00 00 00 00 00 00 00 00
找到了两处,都可以用,选择00008000吧。
第一个IID数组地址就是输入表的地址,用LordPE修改UnPacked.exe的Import Table=00008000 ―――――――――――――――――――――――――――――――――
三、自校验 上面修改了几处,接着当然要干掉壳的自校验了。
在当前位置下Ctrl+F搜索命令:xor eax,ebx
找到在004150FF处,F4过去
004150F5 8BD5 mov edx,ebp
004150F7 81C2 41654200 add edx,426541
004150FD 8B1A mov ebx,dword ptr ds:[edx]
004150FF 33C3 xor eax,ebx
//EBX=000C61F5 检验值,修改EAX的值等于EBX,使其异或结果为0 ★
00415101 74 08 je short anota2.0041510B
//不跳就OVER了
00415103 EB 01 jmp short anota2.00415106 ―――――――――――――――――――――――――――――――――
四、飞向光明之巅 找个快点的方法吧,现在设置Ollydbg不忽略所有的内存异常选项
F9运行,中断在内存异常处
0041558B EB 01 jmp short anota2.0041558E
0041558E 0000 add byte ptr ds:[eax],al
//暂停在这里,看堆栈
0012E700 0012E7EC 指针到下一个 SEH 记录
0012E704 004152EA SE 句柄
BP 004152EA Shift+F9,中断下来
004152EA 55 push ebp
004152EB 8BEC mov ebp,esp
004152ED 57 push edi
004152EE 36:8B45 10 mov eax,dword ptr ss:[ebp+10]
004152F2 3E:8BB8 C4000000 mov edi,dword ptr ds:[eax+C4]
004152F9 3E:FF37 push dword ptr ds:[edi]
004152FC 33FF xor edi,edi
004152FE 64:8F07 pop dword ptr fs:[edi]
00415301 3E:8380 C4000000 >add dword ptr ds:[eax+C4],8
00415309 3E:8BB8 A4000000 mov edi,dword ptr ds:[eax+A4]
00415310 C1C7 07 rol edi,7
00415313 3E:89B8 B8000000 mov dword ptr ds:[eax+B8],edi ; anota2.0040E000
//EDI=0040E000
0041531A B8 00000000 mov eax,0
0041531F 5F pop edi
00415320 C9 leave
00415321 C3 retn
BP 0040E000 F9运行,中断下来
0040E000 EB 18 jmp short anota2.0040E01A
0040E01A 68 02E04000 push anota2.0040E002 ; ASCII "DLL2.dll"
0040E01F E8 44000000 call anota2.0040E068
0040E024 A3 12E04000 mov dword ptr ds:[40E012],eax
0040E029 68 0BE04000 push anota2.0040E00B ; ASCII "TestIt"
0040E02E FF35 12E04000 push dword ptr ds:[40E012]
0040E034 E8 29000000 call anota2.0040E062
0040E039 A3 16E04000 mov dword ptr ds:[40E016],eax
0040E03E FF15 16E04000 call dword ptr ds:[40E016]
//注册部分
0040E044 8BD0 mov edx,eax
0040E046 EB 04 jmp short anota2.0040E04C
0040E04C FF35 48E04000 push dword ptr ds:[40E048] ; anota2.00404100
//00404100就是OEP值了 ★
0040E052 C3 retn ―――――――――――――――――――――――――――――――――
五、代码修正 用PEDitor打开脱壳的文件,DumpFixer(RS=VS &RO=V0),修改EntryPoint=00004100,删除00009000(.rsrc)以下的壳区段,用WinHex移除壳数据。只保留LordPE的“Validate PE”选项,重建PE。
但是现在的UnPacked.exe还是无法运行的,再开一个Ollydbg载入看看。
00404128 68 00F04000 push 40F000
0040412D C3 retn
//出错了
带壳的anota2.exe还在上个Ollydbg里运行,直接去0040F000处看看:
0040F000 EB 0A jmp short anota2.0040F00C
0040F002 C783 08010000 284>mov dword ptr ds:[ebx+108],anota2.00404128
0040F00C 60 pushad
0040F00D BE 02F04000 mov esi,anota2.0040F002
//0040F002
0040F012 8B3D 08F04000 mov edi,dword ptr ds:[40F008] ; anota2.00404128
//目标地址
0040F018 B9 06000000 mov ecx,6
//长度
0040F01D F3:A4 rep movs byte ptr es:[edi],byte ptr ds:[esi]
//就是这里了
0040F01F 61 popad
0040F020 EB 19 jmp short anota2.0040F03B
把0040F002处的C78308010000六个字节复制粘贴进UnPacked.exe
00404128 C783 08010000 010>mov dword ptr ds:[ebx+108],1
还有几处需要处理:
004041A5 68 00004100 push 410000
004041AA C3 retn
004041B6 68 00104100 push 411000
004041BB C3 retn
004041CF 68 00204100 push 412000
004041D4 C3 retn
OK,可以正常运行了,脱壳完毕。
―――――――――――――――――――――――――――――――――
, _/
/| _.-~/ \_ , 青春都一晌
( /~ / \~-._ |\
`\\ _/ \ ~\ ) 忍把浮名
_-~~~-.) )__/;;,. \_ //'
/'_,\ --~ \ ~~~- ,;;\___( (.-~~~-. 换了破解轻狂
`~ _( ,_..--\ ( ,;'' / ~-- /._`\
/~~//' /' `~\ ) /--.._, )_ `~
" `~" " `" /~'`\ `\\~~\
" " "~' ""
UnPacked By : fly
2004-12-12 24:00
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)