- UID
- 5204
注册时间2005-12-14
阅读权限20
最后登录1970-1-1
以武会友
TA的每日心情 | 开心 2016-8-5 08:23 |
---|
签到天数: 2 天 [LV.1]初来乍到
|
发表于 2006-6-23 15:50:05
|
显示全部楼层
标 题: PELock1.0x脱壳实例
发帖人:fxyang
时 间: 2005-05-24 11:12
原文链接:http://bbs.pediy.com/showthread.php?threadid=13924
详细信息:
PELock 1.0x -> Bartosz Wojcik脱壳实例之CryptCD Professional version 4.0.exe
下载地址:http://bbs.hanzify.org/index.php ... e=post&id=14354
1.借尸还魂--搞定iat表
用OD加载CryptCD Professional version 4.0.exe
OD的异常全部勾上,到壳的入口:
0049D05C >JMP SHORT CryptCD_.0049D060
0049D05E XCHG ESP,ESI
0049D060 CLC
0049D061 JNB SHORT CryptCD_.0049D064
Alt+E打开模块窗口,光标选择kernel32 (system) Ctrl+N打开函数窗口
找到LoadLibraryA这个函数,双击它:
77E5D8B4 >CMP DWORD PTR SS:[ESP+4],0
77E5D8B9 PUSH EBX
77E5D8BA PUSH ESI
77E5D8BB JE SHORT kernel32.77E5D8D6
在77E5D8B9 PUSH EBX 这行下内存访问中断,F9运行程序:
第二次中断在:
00374CD9 MOV EDX,DWORD PTR DS:[ECX+ESI]
00374CDC JMP SHORT 00374CE1
......
0037501D MOV EAX,DWORD PTR DS:[ESI]
0037501F MOV EDX,EAX
00375021 CMP AL,0CC
00375023 JNZ SHORT 00375054
......
00375B22 MOV AL,BYTE PTR DS:[ECX]
00375B24 INC ECX
00375B25 OR EDX,DWORD PTR DS:[EBX+EAX*4]
00375B28 TEST DL,8
00375B2B JNZ SHORT 00375B1F
壳会全程检查函数代码,所以int3中断不能使用。
Shift+F9继续运行,直到重新被中断在函数中
77E5D8B9 PUSH EBX
77E5D8BA PUSH ESI
77E5D8BB JE SHORT kernel32.77E5D8D6
堆栈中出现:
0012EA54 72F44841 返回到 72F44841 来自 kernel32.LoadLibraryA
0012EA58 72F1A978 ASCII "gdi32.dll"
回到壳代码中,F7运行到:
00374661 MOV DWORD PTR DS:[ECX],EBX
00374663 JMP SHORT 00374668
EAX 77D18ABC USER32.TranslateMessage
ECX 00426288 CryptCD_.00426288
EDX 77D10000 USER32.77D10000
EBX 003E193F
ESP 0012FFAC
EBP 0037062D
ESI 00380399
EDI 00380389 ASCII "USER32.dll"
EIP 00374661
分析代码发现,[ECX]是iat表中的地址,EBX是加密后的函数地址,再仔细分析发现,
这时候的EAX中就是未加密的函数,如果把:
00374661 MOV DWORD PTR DS:[ECX],EBX
修改成:
00374661 MOV DWORD PTR DS:[ECX],EAX
嘿嘿就可以得到正确的iat表了,修改看看
继续运行,出现Invalid version of library USER32.dll错误。是因为下面的CRC没有通过。
没有关系,用OllyScript来搞定它:
=======================================
//PELock 1.0x 脱壳实例之CryptCD Professional version 4.0
//获取iat表Script
//by fxyang 2005.5.20
//由于只想得到iat表,所以没有检查表的结束。
var index
#LOG
gpa "LoadLibraryA", "kernel32.dll"
bprm $RESULT,1
mov index,1
eob exp1
run
exp1:
cmp index,0
je exp2
dec index
esto
exp2:
bpmc
rtu
bprm 00374661,1
mov index,1
eob exp3
esto
exp3:
cmp index,0
je exp4
dec index
esto
exp4:
mov [ecx],eax
add eip,2
mov index,1
esto
=========================================
脚本完成后到iat表中看看:
00426000 D8 17 DA 77 9A 22 DA 77 ?趙?趙
00426008 68 6A DB 77 10 24 DA 77 hj踳$趙
00426010 00 00 00 00 A4 7F 33 77 ....?3w
......
00426370 CF 90 32 76 0F DA 33 76 蠍2v?v
00426378 00 00 00 00 59 58 F3 4F ....YX驩
00426380 0B 65 EE 4F 00 10 EF 4F e頞.颫
00426388 A8 12 EF 4F A6 F2 ED 4F ?颫︱鞳
00426390 00 00 00 00 00 00 00 00 ........
一个完整的表,用Import.Reconstructor得到完整的表,保存备用。
2.修复被壳转移的代码
重新OD加载程序,重新对LoadLibraryA函数的代码下内存访问中断。F9运行:
在第二次被中断在函数中时,Alt+M打开内存窗口,双击00401000段:
00401000 MOV EAX,DWORD PTR SS:[ESP+4]
00401004 MOV DWORD PTR DS:[440840],EAX
00401009 CALL CryptCD_.00401080
0040100E CALL CryptCD_.00401320
00401013 CALL CryptCD_.00403A20
00401018 TEST EAX,EAX
0040101A JNZ SHORT CryptCD_.00401033
0040101C PUSH 5BCD98
00401021 PUSH 6DE6CC
00401026 CALL CryptCD_.00403560
对0040101C PUSH 5BCD98下内存访问中断,Shift+F9运行:
003780F0 PUSHAD
003780F1 PUSH 4
003780F3 PUSH 3000
003780F8 PUSH 5D58
003780FD PUSH 0
003780FF CALL DWORD PTR SS:[EBP+4]
00378102 XCHG EAX,EDI
00378103 CALL 003780E9
00378108 LEA ESI,DWORD PTR SS:[EBP-5]
0037810B SUB ESI,0BAB
00378111 PUSH ESI
00378112 MOV EBX,101
00378117 XOR BYTE PTR DS:[EDI],DL
00378119 INC EDI
0037811A MOV EDX,DWORD PTR DS:[ESI]
0037811C ADD ESI,4
0037811F MOV BYTE PTR DS:[EDX],0E9
00378122 MOV EAX,EDI
00378124 SUB EAX,EDX
00378126 SUB EAX,5
00378129 MOV DWORD PTR DS:[EDX+1],EAX
0037812C MOV AL,BYTE PTR DS:[ESI]
0037812E INC ESI
0037812F MOVZX ECX,AL
00378132 AND EAX,3
00378135 SHR ECX,2
00378138 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
0037813A MOV ECX,EAX
0037813C REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
0037813E MOV AL,BYTE PTR DS:[ESI]
00378140 INC ESI
00378141 ADD EDX,EAX
00378143 MOV BYTE PTR DS:[EDI],0E9
00378146 SUB EDX,EDI
00378148 SUB EDX,5
0037814B MOV DWORD PTR DS:[EDI+1],EDX
0037814E ADD EDI,5
00378151 DEC EBX
00378152 JNZ SHORT 00378117
00378154 POP EDI
00378155 LEA ECX,DWORD PTR SS:[EBP+66]
00378158 SUB ECX,EDI
0037815A REP STOS BYTE PTR ES:[EDI]
0037815C POPAD
0037815D RETN
这段代码就是把程序的代码修改为调用到壳中转移的地址,分析这段代码
0037811F MOV BYTE PTR DS:[EDX],0E9
修改[EDX]指向的地址40101C为JMP
00378122 MOV EAX,EDI
00378124 SUB EAX,EDX
00378126 SUB EAX,5
00378129 MOV DWORD PTR DS:[EDX+1],EAX
计算跳转偏移,然后写入到程序中
0037812C MOV AL,BYTE PTR DS:[ESI]
0037812E INC ESI
0037812F MOVZX ECX,AL
00378132 AND EAX,3
00378135 SHR ECX,2
00378138 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
0037813A MOV ECX,EAX
0037813C REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
到[ESI]指向的地址看看:
0037753E 1C 10 40 00 05 68 C4 82 @.h膫
00377546 42 00 05 21 10 40 00 05 B.!@.
0037754E 68 B8 82 42 00 05 38 10 h競B.8
00377556 40 00 05 68 18 82 42 00 @.h侭.
0037755E 05 3D 10 40 00 05 68 08 =@.h
00377566 82 42 00 05 53 10 40 00 侭.S@.
0037756E 05 68 F0 81 42 00 05 58 h饋B.X
00377576 10 40 00 05 68 E4 81 42 @.h鋪B
0037757E 00 05 81 10 40 00 12 8D .?@.
这个地址中其实是一个表,表的组成是:
1.)需要修改的程序地址 :1C 10 40 00
2.)需要复制到壳申请临时空间的代码长度:05
3.)需要转移的代码:68 C4 82 42 00
4.)写入jump回程序中地址的偏移:05
0037813E MOV AL,BYTE PTR DS:[ESI]
00378140 INC ESI
00378141 ADD EDX,EAX
00378143 MOV BYTE PTR DS:[EDI],0E9
00378146 SUB EDX,EDI
00378148 SUB EDX,5
0037814B MOV DWORD PTR DS:[EDI+1],EDX
计算jump回到程序中的偏移,写入jump回的代码
分析完了上面的流程和方法后,就可以利用这段代码把转移的代码写回到程序中:
修改:
003780F0 PUSHAD
003780F1 PUSH 4
003780F3 PUSH 3000
003780F8 PUSH 5D58
003780FD PUSH 0
003780FF CALL DWORD PTR SS:[EBP+4]
00378102 XCHG EAX,EDI
00378103 CALL 003780E9
00378108 LEA ESI,DWORD PTR SS:[EBP-5]
0037810B SUB ESI,0BAB
00378111 PUSH ESI
00378112 MOV EBX,101
00378117 NOP
00378118 NOP
00378119 INC EDI
0037811A MOV EDX,DWORD PTR DS:[ESI]
0037811C ADD ESI,4
0037811F MOV EDI,EDX //关键,把壳的地址替换为程序的地址
00378121 NOP
00378122 MOV EAX,EDI
00378124 SUB EAX,EDX
00378126 SUB EAX,5
00378129 NOP
0037812A NOP
0037812B NOP
0037812C MOV AL,BYTE PTR DS:[ESI]
0037812E INC ESI
0037812F MOVZX ECX,AL
00378132 AND EAX,3
00378135 SHR ECX,2
00378138 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
0037813A MOV ECX,EAX
0037813C REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
0037813E MOV AL,BYTE PTR DS:[ESI]
00378140 INC ESI
00378141 ADD EDX,EAX
00378143 NOP
00378144 NOP
00378145 NOP
00378146 SUB EDX,EDI
00378148 SUB EDX,5
0037814B NOP
0037814C NOP
0037814D NOP
0037814E ADD EDI,5
00378151 DEC EBX
00378152 JNZ SHORT 00378117
00378154 POP EDI
00378155 LEA ECX,DWORD PTR SS:[EBP+66]
00378158 SUB ECX,EDI
0037815A REP STOS BYTE PTR ES:[EDI]
0037815C POPAD
0037815D RETN
修改完成后,F4到0037815D RETN
Alt+M打开内存窗口,在00401000的代码段下内存访问中断,Shift+F9运行程序:
0041B9D4 CALL DWORD PTR DS:[426124]
0041B9DA XOR EDX,EDX
0041B9DC MOV DL,AH
0041B9DE MOV DWORD PTR DS:[441C04],EDX
这是程序的伪OEP,在堆栈中检查:
0012FFA8 0012FFB8 指针到下一个 SEH 记录
0012FFAC 0041F270 SE 句柄
0012FFB0 004263F0 CryptCD_.004263F0
0012FFB4 FFFFFFFF
0012FFB8 0012FFE0 指针到下一个 SEH 记录
这个程序是VC++编译的,根据堆栈中的数据恢复代码:
0041B9AE >PUSH EBP
0041B9AF MOV EBP,ESP
0041B9B1 PUSH -1
0041B9B3 PUSH CryptCD_.004263F0
0041B9B8 PUSH CryptCD_.0041F270 ; SE handler installation
0041B9BD MOV EAX,DWORD PTR FS:[0]
0041B9C3 PUSH EAX
0041B9C4 MOV DWORD PTR FS:[0],ESP
0041B9CB SUB ESP,58
0041B9CE PUSH EBX
0041B9CF PUSH ESI
0041B9D0 PUSH EDI
0041B9D1 MOV DWORD PTR SS:[EBP-18],ESP
用LordPE dump下程序,修改程序的OEP为0041B9AE,保存备用.
3.还原IAT表
用Import.Reconstructor加载保存的iat表,去掉增加新的区段的勾,然后在新的输入表信息的
RVA 中填入原iat表的RVA 00026000 在OEP中填入0001B9AE 后,修复上面保存的dump程序.
看似修复好了iat表,运行看看,程序不见了:( 看来还是有问题.有什么问题呢?
用OD 加载原程序,直接运行,运行成功后来到imports段00426000
再用OD加载修复后的dump程序,比较imports段和原来的有些什么不同,发现原imports表中多了些数据:
00426390 00 00 00 00 00 00 00 00 9A 99 99 99 99 99 E9 3F ........殭櫃櫃?
004263A0 00 00 00 00 00 00 50 3F 00 00 80 3A 00 00 00 00 ......P?.. |
|