【文章标题】: 手脱PowerArchiverr的ExeCryprtor V2.XX
【文章作者】: dryzh(B.S)
【作者邮箱】: dryzh[at]163.com
【作者主页】: http://www.pediy.com/
【作者QQ号】: 最近没条件上Q :(
【软件名称】: PowerArchiver2007
【软件大小】: 138 KB (141,352 字节)
【下载地址】: http://www.powerarchiver.com/download/
【加壳方式】: ExeCryprtor V2.XX
【保护方式】: ExeCryprtor V2.XX
【编写语言】: Borland Delphi 6.0 - 7.0
【使用工具】: OLLYICE or OLLYDBG_Execryptor,PeID,ProtectionID_v5.2c,LordPE,ImpREC
【操作平台】: WinXP
【软件介绍】: 自己去看吧!
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
一, 了解程序相关信息:
用PeID查看是什么壳
EXECryptor 2.xx (compressed resources) -> www.strongbit.com
连接器版本Linker:2.25
可能是Borland Delphi 6.0 - 7.0写的程序
用ProtectionID_v5.2c查得
> Ready
Scanning -> D:\Program Files\PowerArchiver\POWERARC.EXE
File Type : Exe, Size : 7806752 (0771F20h) Bytes
-> File has 5408 (01520h) bytes of appended data starting at offset 0770A00h
[!] EXE Cryptor v2.3.0 - v2.3.9 protected !
[!] Possible CD/DVD-Check String -> InsertDisk
[!] Possible CD/DVD-Key or Serial Check -> evaluation copy
- Scan Took : 0.516 Seconds
二, 找OEP+IAT:
打开OD,ALT+O
在异常选项卡里,忽略所有异常和00000001-FFFFFFFE的范围异常
在事件选项卡里,设置第一次暂停于系统断点.
插件Hide OD 全勾,选mothed1(好像mothed2也可以)
OD载入停在系统断点处
7C921231 C3 retn
7C921232 8BFF mov edi, edi
7C921234 90 nop
7C921235 90 nop
7C921236 90 nop
7C921237 90 nop
7C921238 90 nop
7C921239 > CC int3
7C92123A C3 retn
7C92123B 90 nop
7C92123C 8BFF mov edi, edi
ALT+B删掉"仅一次"的断点(如还有别的断点,也删掉吧)
Breakpoints, 条目 0
地址=00CF9F16 POWERARC.<模块入口点>
模块=POWERARC
激活=仅一次
反汇编=jmp 00CDCA2E
从这里断下的语句代码JMP XXXXXXXX可以看出是DELPHI,如果是C++的话,这句应该是CALL XXXXXXXX.
ALT+M在.CODE区段下断F2,SHIFT+F9停在下面
7C948515 8B06 mov eax, dword ptr [esi] ; POWERARC.00CCDBCB
7C948517 3BC3 cmp eax, ebx
7C948519 0F85 3A2F0100 jnz 7C95B459
7C94851F 834D FC FF or dword ptr [ebp-4], FFFFFFFF
7C948523 E8 DA68FEFF call 7C92EE02
7C948528 C2 0800 retn 8
找到下面的retn 8 下断F2,再SHIFT+F9或F9断在retn 8处,F2取消断点
ALT+M在.CODE区段下断F2,F9停在下面
009AD305 8BD0 mov edx, eax ; 断在这里
009AD307 C1C8 10 ror eax, 10
009AD30A 66:C1C2 03 rol dx, 3
009AD30E 81F2 47D8B0B2 xor edx, B2B0D847
009AD314 - E9 041A3500 jmp 00CFED1D
009AD319 870424 xchg dword ptr [esp], eax
009AD31C 58 pop eax
009AD31D 57 push edi
009AD31E 68 2E56BE50 push 50BE562E
009AD323 - E9 D4153500 jmp 00CFE8FC
009AD328 E8 ECF03200 call 00CDC419
009AD32D - E9 B14F3400 jmp 00CF22E3
009AD332 - E9 F42A3300 jmp 00CDFE2B
009AD337 - E9 1DB73400 jmp 00CF8A59
009AD33C - E9 447A3400 jmp 00CF4D85
009AD341 8845 F3 mov byte ptr [ebp-D], al
009AD344 57 push edi
009AD345 E8 17FF3300 call 00CED261
009AD34A A6 cmps byte ptr [esi], byte ptr es:[edi>
009AD34B CA D98B retf 8BD9
CTRL+G到00401000处,查找->所有模块间调用
输入GetModuleHandleA,按目标文件排列后先第2个GetModuleHandleA,跟随到反汇编ENTER
00407986 C3 retn
00407987 90 nop
00407988 53 push ebx
00407989 8BD8 mov ebx, eax
0040798B 33C0 xor eax, eax
0040798D A3 C400A000 mov dword ptr [A000C4], eax
00407992 6A 00 push 0
00407994 E8 2BFFFFFF call <jmp.&kernel32.GetModuleHandleA>
00407999 A3 6866A200 mov dword ptr [A26668], eax
0040799E A1 6866A200 mov eax, dword ptr [A26668]
004079A3 A3 D000A000 mov dword ptr [A000D0], eax
004078C4=<jmp.&kernel32.GetModuleHandleA>
先记住这个头处的地址00407988
跟随这个call <jmp.&kernel32.GetModuleHandleA>来到
004078C4 - FF25 7013CA00 jmp dword ptr [<&kernel32.GetModuleH>; kernel32.GetModuleHandleA
即:jmp dword ptr [CA1370]
现在可以在命令行d CA1370,可向上向下找IAT开始和结束的地址(你也可以在F9009AD305处时,在.idata段F2再F9)
00CA1370 >7C80B6A1 kernel32.GetModuleHandleA
00CA1374 00000000
00CA1378 >77DA77B3 advapi32.SetSecurityDescriptorDacl
00CA137C >77DAD7CC advapi32.RegSetValueExW
00CA1380 >77DAEBE7 advapi32.RegSetValueExA
00CA1384 >77DBC8D6 advapi32.RegSetKeySecurity
00CA1388 >77DA6FC8 advapi32.RegQueryValueExW
00CA138C >77DA7883 advapi32.RegQueryValueExA
00CA1390 >77DCC1B5 advapi32.RegQueryInfoKeyA
00CA1394 >77DA6A78 advapi32.RegOpenKeyExW
确定IAT表
00CA1268 00000000
00CA126C >7C93188A ntdll.RtlDeleteCriticalSection
00CA1270 >7C9210ED ntdll.RtlLeaveCriticalSection
00CA1274 >7C921005 ntdll.RtlEnterCriticalSection
00CA1278 >7C809EF1 kernel32.InitializeCriticalSection
00CA127C >7C809AE4 kernel32.VirtualFree
00CA1280 >7C809A51 kernel32.VirtualAlloc
00CA1284 >7C80992F kernel32.LocalFree
00CA1288 >7C80998D kernel32.LocalAlloc
......
00CA1F04 >71A22BF4 WS2_32.inet_addr
00CA1F08 >71A22B66 WS2_32.ntohs
00CA1F0C >71A2951E WS2_32.getsockname
00CA1F10 >71A2406A WS2_32.connect
00CA1F14 >71A29639 WS2_32.closesocket
00CA1F18 >71A23E00 WS2_32.bind
00CA1F1C 00000000
00CA1F20 >77D1BFF3 user32.NotifyWinEvent
00CA1F24 00000000
00CA1F28 >74BFDC93 oleacc.LresultFromObject
00CA1F2C 00000000
00CA1F30 >77EFD7E6 GDI32.GetRandomRgn
00CA1F34 00000000
00CA1F38 >765EC256 crypt32.CertDuplicateCertificateContext
00CA1F3C >765F085A crypt32.CertFreeCertificateContext
00CA1F40 00000000
00CA1F44 >77DB8546 advapi32.CryptReleaseContext
00CA1F48 >77DBA544 advapi32.CryptDestroyKey
00CA1F4C 00000000
00CA1F50 6E72656B
00CA1F54 32336C65
00CA1F58 6C6C642E
00CA1F5C 00000000
得到后面修复要用的:
RVA=IAT_START-00400000=00cA1268-00400000=008A1268
IAT_SIZE=IAT_START-IAT_END
=(00CA1F50-00400000)-(00CA1268-00400000)=008A1F50-008A1268=00000CE8
呵呵,输入表没有加密处理,幸运哟.
在00407988这行(开头处)CTRL+F查找命令call 00407988看是哪里调用这里的,来到
注意:本来您是可以通过 Ctrl +↑ 或 Ctrl+↓ 对数据窗口翻动一个字节的,这里如果在你的OD失效,请你加上SHIFT三键一起按^_^
直到出现JMP <ModuleEntryPoint>,这里就是真真的OEP了.呵呵...开心吧....
009FF6C8 - E9 49A82F00 jmp <模块入口点> ; real OEP
009FF6CD 2D 24946A00 sub eax, 006A9424
009FF6D2 6A 00 push 0
009FF6D4 49 dec ecx
009FF6D5 ^ 75 F9 jnz short 009FF6D0
009FF6D7 51 push ecx
009FF6D8 53 push ebx
009FF6D9 56 push esi
009FF6DA 57 push edi
009FF6DB B8 E8E79F00 mov eax, 009FE7E8
009FF6E0 E8 A382A0FF call 00407988 ; 找到这里
可是上面的OEP被偷了:(
三, 还原OEP+DUMP:
现在我们来找OEP还原,在第一个PUSH 0处(009FF6D0)下断,F9跑,断下后看寄存器ECX的值为0E(这个还原OEP有用)
找个DELHPI未加壳程序来看一下就会明白了,程序目录里还有一个叫_PASETUP.EXE它没有加壳,就用这个作OEP参考吧
参考程序:
0040E084 > $ 55 push ebp
0040E085 . 8BEC mov ebp, esp
0040E087 . B9 45000000 mov ecx, 45
0040E08C > 6A 00 push 0
0040E08E . 6A 00 push 0
0040E090 . 49 dec ecx
0040E091 .^ 75 F9 jnz short 0040E08C
0040E093 . 51 push ecx
0040E094 . 53 push ebx
0040E095 . 56 push esi
0040E096 . 57 push edi
0040E097 . B8 B4DF4000 mov eax, 0040DFB4
0040E09C . E8 1766FFFF call 004046B8
0040E0A1 . 33C0 xor eax, eax
壳程序:
009FF6CE 24 94 and al, 94
009FF6D0 6A 00 push 0 ; 这里断下后.看ECX的值
009FF6D2 6A 00 push 0
009FF6D4 49 dec ecx
009FF6D5 ^ 75 F9 jnz short 009FF6D0
009FF6D7 51 push ecx
009FF6D8 53 push ebx
009FF6D9 56 push esi
009FF6DA 57 push edi
009FF6DB B8 E8E79F00 mov eax, 009FE7E8
009FF6E0 E8 A382A0FF call 00407988 ; 找到这里
009FF6E5 33C0 xor eax, eax
还原后的OEP在下面
009FF6C8 55 push ebp ; real OEP
009FF6C9 8BEC mov ebp, esp
009FF6CB B9 0E000000 mov ecx, 0E
009FF6D0 6A 00 push 0
009FF6D2 6A 00 push 0
009FF6D4 49 dec ecx
009FF6D5 ^ 75 F9 jnz short 009FF6D0
009FF6D7 51 push ecx
009FF6D8 53 push ebx
009FF6D9 56 push esi
009FF6DA 57 push edi
009FF6DB B8 E8E79F00 mov eax, 009FE7E8
009FF6E0 E8 A382A0FF call 00407988
009FF6E5 33C0 xor eax, eax
下面是二进制代码,复制去用吧^_^
55 8B EC B9 0E 00 00 00
还原好后,还用说吗,去掉009FF6D0处的断点,赶快新建EIP,DUMP啦......
就用OLLY DUMP插件吧,记住不要选重建输入表项(Rebuile Import),存为5FF6C8.exe
OD不要关,下面要修复用.
四, 修复IAT:
用ImpREC修复,选中进程,填上
OEP=009FF6C8-00400000=5FF6C8
RVA=00cA1268-00400000=008A1268
SIZE=(00CA1F50-00400000)-(00CA1268-00400000)=008A1F50-008A1268=00000CE8
因为输入表没有加密,你也可以点IAT AutoSearch
Get Import 后 Show Invalid 没有无效函数指针
Fix Dump! OK!
PeID查一下(你也可以用别的查壳工具,如ProtectionID_v5.2c,RDG Packer Detector v0.6.5 Beta,CFF Explorer VI等等)
Borland Delphi 6.0 - 7.0
运行修复后的5FF6C8_.exe文件,一切正常.
完工......
感谢:
kienmanowar
Teddy Roggers
haggar
why not bar
EvOiUtloN
kanxue
fly
VolX
linhanshi
machenglin
Isaiah
wynney
所有直接或间接帮助我和支持我的朋友和你
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2008年01月01日 0:54:44
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)