感谢 DFCG 和 看雪 的大侠.
我在春节前还是一个脱壳菜鸟,
连 UPX 的手动脱壳也不会.
春节的时候我看了DFCG的 13 章手动脱壳入门
11章手动脱壳提高, 总算有点进步了.
谢谢David大侠的貂:
http://bbs2.pediy.com/viewtopic.php?t=4448
// 用 OD 跟踪脱壳后OEP=432D4的程序, 执行到 443399 时出错
00443389 FF15 88874400 CALL DWORD PTR DS:[<&msvcrt.__getmainargs>] ; MSVCRT.__getmainargs
0044338F 68 80404500 PUSH net.00454080 ; // End Address
00443394 68 00404500 PUSH net.00454000 ; // Start Address
00443399 E8 DC000000 CALL <JMP.&msvcrt._initterm> ; // 解密代码
// F7 跟进去看看, 注意 454000,454080 这两个参数
// d 454000
// 原来都是函数入口
00454000 00 00 00 00 51 41 44 00 10 11 40 00 60 11 40 00 ....QAD.@.`@.
00454010 E0 12 40 00 10 14 40 00 70 93 40 00 C0 93 40 00 ?@.@.p揁.罁@.
00454020 10 94 40 00 60 94 40 00 00 D0 40 00 30 19 41 00 擛.`擛..蠤.0A.
00454030 70 19 41 00 F0 1F 41 00 30 20 41 00 70 20 41 00 pA.?A.0 A.p A.
00454040 B0 20 41 00 F0 20 41 00 30 21 41 00 70 21 41 00 ?A.?A.0!A.p!A.
00454050 20 22 41 00 50 B8 41 00 D0 C7 41 00 F0 C7 41 00 "A.P窤.星A.鹎A.
00454060 10 C8 41 00 30 C8 41 00 50 C8 41 00 70 C8 41 00 華.0華.P華.p華.
00454070 90 C8 41 00 F0 2F 42 00 36 30 42 00 6B 72 42 00 惾A.?B.60B.krB.
00454080 00 00 00 00
//msvcrt._initterm
7800119B > 56 PUSH ESI
7800119C 8B7424 08 MOV ESI,DWORD PTR SS:[ESP+8] ; // 取出 454000
780011A0 EB 03 JMP SHORT MSVCRT.780011A5
780011A2 83C6 04 ADD ESI,4 ; // 下一个
780011A5 3B7424 0C CMP ESI,DWORD PTR SS:[ESP+C] ; // >454080 吗?
780011A9 73 0A JNB SHORT MSVCRT.780011B5 ; // 是则结束
780011AB 8B06 MOV EAX,DWORD PTR DS:[ESI] ; // 取出一个函数入口
780011AD 85C0 TEST EAX,EAX
780011AF ^ 74 F1 JE SHORT MSVCRT.780011A2
780011B1 FFD0 CALL EAX ; // 执行用户的函数
780011B3 ^ EB ED JMP SHORT MSVCRT.780011A2
780011B5 5E POP ESI
780011B6 C3 RETN
// bp 780011B1, F9 运行
// 当 EAX = 00423036 时出错
// 从新来过
// bp 00423036, F9 断下,
// 接下来一大段花指令, SMC, 注意循环,
// 用户指令 F7 过, 系统函数 F8 过, 循环 F4 过
00423036 E8 05000000 CALL net.00423040
0042303B E9 18000000 JMP net.00423058
00423040 55 PUSH EBP
00423041 8BEC MOV EBP,ESP
00423043 51 PUSH ECX
00423044 8D45 FF LEA EAX,DWORD PTR SS:[EBP-1]
00423047 B9 00834500 MOV ECX,net.00458300
.
.
.
.
00423A9A E8 47F10100 CALL <JMP.&mfc42.#823_??2@YAPAXI@Z>
00423A9F 8970 04 MOV DWORD PTR DS:[EAX+4],ESI
00423AA2 8958 14 MOV DWORD PTR DS:[EAX+14],EBX
00423AA5 8947 04 MOV DWORD PTR DS:[EDI+4],EAX
00423AA8 E8 30B60800 CALL net.004AF0DD ; // Call 004AF0DD, F7跟进
00423AAD 8B47 04 MOV EAX,DWORD PTR DS:[EDI+4] ; // 返回到 00423AAD, 下面有用
.
.
.
.
004AF0DD
.
.
004AF25E /E9 0B000000 JMP net.004AF26E
004AF263 |79 03 JNS SHORT net.004AF268
004AF265 |66:D3EA SHR DX,CL
004AF268 |81F5 5D54168F XOR EBP,8F16545D
004AF26E 4B DEC EBX
004AF26F ^ 0F85 7FFFFFFF JNZ net.004AF1F4 ; // 一个望回跳的循环
004AF275 50 PUSH EAX ; // F4 到这里
004AF27D 58 POP EAX ; net.004AF348
004AF27E E9 05000000 JMP net.004AF288
004AF283 4A DEC EDX
004AF284 76 02 JBE SHORT net.004AF288
004AF286 13D7 ADC EDX,EDI
004AF288 E8 7EBE0000 CALL net.004BB10B ; // F8 过
004AF28D 8B4424 20 MOV EAX,DWORD PTR SS:[ESP+20] ; // EAX = 00423AAD, 返回地址
004AF291 33C9 XOR ECX,ECX
004AF293 8B9C8D 8D234000 MOV EBX,DWORD PTR SS:[EBP+ECX*4+40238D] ; // 4AF38D 开始放返回地址的RVA
004AF29A 039D 55CF4000 ADD EBX,DWORD PTR SS:[EBP+40CF55] ; // RVA + 400000
004AF2A0 3BC3 CMP EAX,EBX
004AF2A2 74 07 JE SHORT net.004AF2AB
004AF2A4 90 NOP
004AF2A5 90 NOP
004AF2A6 90 NOP
004AF2A7 90 NOP
004AF2A8 41 INC ECX ; // 不匹配, 下一个
004AF2A9 ^ EB E8 JMP SHORT net.004AF293
004AF2AB C7848D 8D234000>MOV DWORD PTR SS:[EBP+ECX*4+40238D],0 ; // 找到了, ECX=49
004AF2B6 8DB5 6D524000 LEA ESI,DWORD PTR SS:[EBP+40526D] ; // 4B226D 放加密后的代码
004AF2BC B8 0A000000 MOV EAX,0A ; // 加密代码 10 字节一段
004AF2C1 F7E1 MUL ECX
004AF2C3 03F0 ADD ESI,EAX ; // 对应该返回地址的加密代码
004AF2C5 51 PUSH ECX
004AF2C6 56 PUSH ESI ; // ESI=4B226D+A*49=4B2547
004AF2C7 8A85 CD204000 MOV AL,BYTE PTR SS:[EBP+4020CD]
004AF2CD 0AC0 OR AL,AL
004AF2CF 75 28 JNZ SHORT net.004AF2F9
004AF2D1 90 NOP
004AF2D2 90 NOP
004AF2D3 90 NOP
004AF2D4 90 NOP
004AF2D5 8B85 55CF4000 MOV EAX,DWORD PTR SS:[EBP+40CF55] ; // 400000
004AF2DB 8B70 3C MOV ESI,DWORD PTR DS:[EAX+3C] ; // 40003C, PE头
004AF2DE 03B5 55CF4000 ADD ESI,DWORD PTR SS:[EBP+40CF55] ; // 400100
004AF2E4 83C6 28 ADD ESI,28 ; // 400128, OEP
004AF2E7 AD LODS DWORD PTR DS:[ESI] ; // OEP值
004AF2E8 8AD8 MOV BL,AL
004AF2EA 02DC ADD BL,AH
004AF2EC C1E8 10 SHR EAX,10
004AF2EF 02D8 ADD BL,AL
004AF2F1 02DC ADD BL,AH ; // OEP 四字节相加
004AF2F3 889D CD204000 MOV BYTE PTR SS:[EBP+4020CD],BL ; // 放到 4AF0CD
004AF2F9 8A9D CD204000 MOV BL,BYTE PTR SS:[EBP+4020CD] ; // 也到 BL
004AF2FF B9 0A000000 MOV ECX,0A
004AF304 5E POP ESI
004AF305 8BFE MOV EDI,ESI
004AF307 AC LODS BYTE PTR DS:[ESI]
004AF308 32C3 XOR AL,BL ; // 加密代码 XOR BL
004AF30A AA STOS BYTE PTR ES:[EDI] ; // 得到明码
004AF30B ^ E2 FA LOOPD SHORT net.004AF307
004AF30D 83EE 0A SUB ESI,0A
004AF310 59 POP ECX
004AF311 56 PUSH ESI
004AF312 8B7424 24 MOV ESI,DWORD PTR SS:[ESP+24]
004AF316 83EE 04 SUB ESI,4
004AF319 AD LODS DWORD PTR DS:[ESI] ; // 423AA8处函数入口 4AF0DD
004AF31A 50 PUSH EAX
004AF31B BB 6D524000 MOV EBX,net.0040526D
004AF320 81EB DD204000 SUB EBX,net.004020DD
004AF326 B8 0A000000 MOV EAX,0A
004AF32B F7E1 MUL ECX
004AF32D 03D8 ADD EBX,EAX
004AF32F 58 POP EAX
004AF330 03C3 ADD EAX,EBX
004AF332 8946 FC MOV DWORD PTR DS:[ESI-4],EAX ; // 修改423AA8 处函数入口为 4B2547
004AF335 5E POP ESI ; net.004B2547
004AF356 83EE 06 SUB ESI,6
.
.
// 调整Stack
// SMC
.
.
004AF38A 61 POPAD
004AF38B 61 POPAD
004AF38C C3 RETN ; // 返回到4B2547执行
// 从上面的过程可以看到, 如果OEP变了, 那么加密代码解密出来就不对