目标程序AlfaClock 1.60a(华军下载)
工具 OllyDbg 1.09d
LordPE
ImportRec 1.60
一、脱壳:
用OD加载后去掉调试器标志(IsDebuggerPresent),F9执行,异常后按21次SHIFT+F9,
将Hex Dump窗口转到4D6420,会看到如下数据,这里从4D6420到4D6453是Aspr要修改的
地方,主要是:
1.4D6420 字符串指针,若这个指针指向空串,表示未注册
2.4D6428 字符串指针,这个指针不能指向空串,Aspr让它指向7Rk1OABg9ag=
3.4D6430-4D643B是三个函数的入口地址,Aspr会修改这三个指针,使其指向
壳中的三个函数!
4.4D6440 Share 版的使用天数,4D6444 剩下的天数
5.从4D6448-4D6453是程序验证壳存在的标记
004D6420 00 00 00 00 00 00 00 00 00 00 00 00 00 8D 40 00 .............岪.
004D6430 70 1B 4D 00 9C 1B 4D 00 9C 1B 4D 00 00 00 00 00 pM.?M.?M.....
004D6440 FE FF FF FF FE FF FF FF 00 00 00 00 FE FF FF FF ??....?
004D6450 FE FF FF FF
(从上面的叙述你应该知道修复程序时你要干什么了吧)go on
再按 5次SHIFT+F9,程序停在这里:
00FD3D03 XOR DWORD PTR DS:[EAX],EAX
00FD3D05 POP DWORD PTR FS:[0]
00FD3D0C POP EAX
00FD3D0D CMP DWORD PTR DS:[FD7EBC],0
00FD3D14 JE SHORT 00FD3D2A
00FD3D16 PUSH 0C
00FD3D18 MOV ECX,0FD7EBC
00FD3D1D LEA EAX,DWORD PTR SS:[EBP-8]
00FD3D20 MOV EDX,4
00FD3D25 CALL 00FD1010
00FD3D2A PUSH DWORD PTR SS:[EBP-4]
00FD3D2D PUSH DWORD PTR SS:[EBP-8]
00FD3D30 MOV EAX,DWORD PTR SS:[EBP-C]
00FD3D33 CMP DWORD PTR DS:[EAX],0
00FD3D36 JE SHORT 00FD3D3A
00FD3D38 PUSH DWORD PTR DS:[EAX]
00FD3D3A PUSH DWORD PTR SS:[EBP-10]
00FD3D3D PUSH DWORD PTR SS:[EBP-14]
00FD3D40 RETN
我们马上要进入原程序了,再看看Hex Dump窗口:
004D6420 51 39 FC 00 00 00 00 00 30 A3 FE 00 00 8D 40 00 Q9?....0 ̄..岪.
004D6430 A4 14 FD 00 40 14 FD 00 74 14 FD 00 FE FF FF FF ??@?t??
004D6440 1E 00 00 00 0D 00 00 00 FE FF FF FF 00 00 00 00 .......?....
004D6450 00 00 00 00
看到修改了?这时,可以DUMP程序了,用LordPE,操作就不讲了吧。
二、修复IAT:
在上面的RETN处设断,SHIFT+F9,断点处停下后F2清除断点再F8,来到:
00FE7CF0 PUSH EAX ;停在这里
00FE7CF1 POP ESI
00FE7CF2 CALL 00FE7D01
00FE7CF7 PUSH 5B
00FE7CF9 CLC
00FE7CFA SAL DWORD PTR DS:[ESI],1
稍往下滚动鼠标,看到
00FE7D5F MOV EDI,ECX
00FE7D61 MOV DWORD PTR DS:[EAX],EBX
00FE7D63 MOV DX,0DC32
00FE7D67 SUB EAX,4
00FE7D6A MOV DX,CX
00FE7D6D SUB ECX,1
00FE7D73 JNZ 00FE7D90
00FE7D79 JPE 00FE7D84 <-光标移到这里按F4
00FE7D7F OR DX,0DEAD
00FE7D84 JMP 00FE7DB6
光标移到FE7D79(JPE 00FE7D84)再F4,下面,Aspr下面要执行是
1.执行Stolen code
2.销毁来到这里的程序段
有兴趣的可以跟,我选择的是直接进入原程序。于是再稍往下滚动鼠标,看到
00FE7DC0 PUSHAD
00FE7DC1 PUSHFD
00FE7DC2 CLD
00FE7DC3 MOV EDI,0
00FE7DC8 MOV ECX,0
00FE7DCD REP STOS BYTE PTR ES:[EDI]
00FE7DCF POPFD
00FE7DD0 POPAD
00FE7DD1 RETN
光标移到RETN处F4,再F8就进入原程序了:
00406324 JMP DWORD PTR DS:[4D9280] <-停在这里
0040632A MOV EAX,EAX
0040632C JMP DWORD PTR DS:[4D927C]
00406332 MOV EAX,EAX
00406334 JMP DWORD PTR DS:[4D9278]
显然,我们处在程序执行了一段代码的位置,但这并不妨碍修复IAT,看看堆栈:
0012FF6C 004063F9 RETURN to AlfaCloc.004063F9 from AlfaCloc.00406324
0012FF70 00000000
0012FF74 0000071D
0012FF78 004D2FD5 RETURN to AlfaCloc.004D2FD5 from AlfaCloc.004063E8
0012FF7C 005885C3 AlfaCloc.005885C3
0012FF80 0000071D
0012FF84 00000000
0012FF88 00000000
0012FF8C 00000000
0012FF90 0000071D
0012FF94 00B37CEE
0012FF98 00FE7E99
0012FF9C 00B37CEE
0012FFA0 00B37CEE
0012FFA4 00000000
0012FFA8 00000000
0012FFAC 0012FFF0
0012FFB0 0012FFC4
0012FFB4 7FFDF000
0012FFB8 FFFFFFFF
0012FFBC 00010101
0012FFC0 00000000
0012FFC4 77E67903 RETURN to kernel32.77E67903
容易找到被删除了Stolen code的oep,就是4D2FD5上一条语句的位置,鼠标选中
堆栈区0012FF78处的004D2FD5,回车后再向上滚动鼠标,看到
004D2FCA ADD BYTE PTR DS:[EAX],AL
004D2FCC ADD BYTE PTR DS:[EAX],AL
004D2FCE ADD BYTE PTR DS:[EAX],AL
004D2FD0 CALL AlfaCloc.004063E8
004D2FD5 MOV EBX,DWORD PTR DS:[4D69C0]
004D2FDB XOR EAX,EAX
004D2FDD PUSH EBP
004D2FDE PUSH AlfaCloc.004D3248
好,就把 D2FD0作为oep吧。启动ImportREC,选中目标,就绪后在OEP处填上D2FD0,
点击IAT AutoSearch得到RVA: 000D9274 Size: 0000000C,从Size值知道这里有误,
把Hex Dump区转到4D9000往下翻页,看到
004D9190 C7 E6 60 A5 5E 88 19 A0 D5 48 A7 3D BD A9 03 F3 擎`?_誋?僵
004D91A0 78 92 22 D4 70 05 FE 00 A0 05 FE 00 AC 05 FE 00 x?詐 ?????
004D91B0 5C 92 FE 00 B8 05 FE 00 D0 05 FE 00 EC 05 FE 00 \揀.??????
004D91C0 1C 06 FE 00 4C 06 FE 00 58 06 FE 00 28 15 FD 00 ?L ?X ?( ?
004D91D0 68 06 FE 00 78 06 FE 00 84 06 FE 00 90 06 FE 00 h ?x ?????
004D91E0 A8 06 FE 00 B8 06 FE 00 C8 06 FE 00 F4 06 FE 00 ????????
004D91F0 24 07 FE 00 34 07 FE 00 44 07 FE 00 AC 10 FD 00 $?4?D???
004D9200 00 15 FD 00 7C 07 FE 00 94 07 FE 00 74 15 FD 00 . ?|???t ?
004D9210 A4 07 FE 00 B0 07 FE 00 C0 07 FE 00 F0 07 FE 00 ????????
004D9220 1C 08 FE 00 4C 08 FE 00 70 08 FE 00 A0 08 FE 00 ?L ?p ???
004D9230 CC 08 FE 00 DC 08 FE 00 EC 08 FE 00 C6 8B D1 6F ??????茓裲
004D9240 7E FB DF 77 AF E3 DF 77 68 3D E2 77 04 CF DF 77 ~w遷h=鈝 线w
004D9250 38 5B C5 63 8E 85 D9 77 AC 82 D9 77 4D 7D D9 77 8[與巺賥瑐賥M}賥
004D9260 02 5F 8A FD 33 15 99 77 A6 3F 99 77 59 14 99 77 _婟3 檞?檞Y 檞
004D9270 36 D7 A2 D9 00 09 FE 00 18 09 FE 00 2C 09 FE 00 6注?.? .?,.?
004D9280 00 15 FD 00 26 A3 03 CD 54 94 D9 77 8E 85 D9 77 . ?&?蚑斮w巺賥
可以看出D91A4是RVA值,Size值?再往下翻页直到
004D9830 BA 22 99 77 94 23 99 77 39 99 00 34 B0 30 A3 77 ?檞?檞9?4?
004D9840 E0 4F A3 77 84 69 A3 77 1A 69 A3 77 D5 BF FC 06 郞刬 i湛?
004D9850 54 10 FE 00 64 10 FE 00 70 10 FE 00 88 10 FE 00 T ?d ?p ???
004D9860 A0 10 FE 00 AC 10 FE 00 BC 10 FE 00 CC 10 FE 00 ????????
004D9870 E4 10 FE 00 F0 10 FE 00 00 11 FE 00 0C 11 FE 00 ????. ?. ?
004D9880 1C 11 FE 00 28 11 FE 00 38 11 FE 00 48 11 FE 00 ?( ?8 ?H ?
004D9890 58 11 FE 00 64 11 FE 00 70 11 FE 00 80 11 FE 00 X ?d ?p ? ?
004D98A0 90 11 FE 00 9C 11 FE 00 A8 11 FE 00 C8 11 FE 00 ????????
004D98B0 9C AE 54 F4 6C 5A 7C 77 5C 63 7C 77 81 59 7C 77 湲T鬺Z|w\c|w乊|w
004D98C0 CC 45 7C 77 02 61 67 9F 72 C3 5F 77 4B 71 19 5F 蘀|w ag焤胈wKq _
004D98D0 45 6D B0 76 60 EF AF 76 CD A5 AF 76 27 BC D1 4E Em皏`锆v庭痸'佳N
004D98E0 A6 AF 4A 77 E8 12 4A 77 78 7D 79 13 E9 34 53 77 ΟJw?Jwx}y ?Sw
004D98F0 B6 C6 36 8E 69 27 FB 74 6A 4A FB 74 24 58 FB 74 镀6巌'鹴jJ鹴$X鹴
004D9900 71 66 11 68 09 EB FB 3C 09 75 91 84 E5 61 CF D6 qf h.臌<.u憚錫现
显然D9900是中止值,于是Size:900-1A4=75C
把D91A4和75C分别填好后,就可以Get Imports了。对于unresolved pointers,
1.Show Invalid 后 Trace Level1(Disasm)
2.Show Invalid 后 Plugin Tracers -> Asprotect 1.22
以上两步之后就只有 rva: 000D93AC ptr: 000FD158C 是真的unresolved pointer了。
选中本行后选择Disassemble/HexView,看到
00FD158C PUSH EBP
00FD158D MOV EBP,ESP
00FD158F MOV EAX,DWORD PTR DS:[FD7CF0] // DWORD value : 00133938
00FD1595 POP EBP
00FD1596 RETN 4
这是Aspr制造的一个的unresolved的"API",
(如果RETN 4 换成RETN,就是GetCommandLineA,嘿嘿)
因此这个函数应该resolved成LockResource,为什么?嘿嘿!
好了,对于剩下的unresolved pointers就全是Invalid了,Show Invalid,Cut Thunks。
三、修复
这是最麻烦的一步。
(一)修改Aspr修改过的 D6420开始的几个指针,主要思想是:
1.还原原来的三个函数指针
2.让两个字符串指针指向程序内部某处,我选定的是589800和5797F0,在这两个
位置放入字符串Pediy001和7Rk1OABg9ag=。呵呵
下面是我修改过的情况
004D6420 00 98 58 00 00 00 00 00 F0 97 58 00 00 8D 40 00 .榅.....饤X..岪.
004D6430 70 1B 4D 00 9C 1B 4D 00 9C 1B 4D 00 FE FF FF FF pM.?M.?M.?
004D6440 1E 00 00 00 10 00 00 00 FE FF FF FF 00 00 00 00 ......?....
004D6450 00 00 00 00 ....
(二)仿真stolen code
主要是根据EIP的位置(00406324 JMP DWORD PTR DS:[4D9280]),参照此时程序
到要执行的“明码”、堆栈结构和寄存器的情况来仿真
明码是:
004063E8 PUSH EBX
004063E9 MOV EBX,EAX
004063EB XOR EAX,EAX
004063ED MOV DWORD PTR DS:[4D40A0],EAX
004063F2 PUSH 0
004063F4 CALL AlfaCloc.00406324 <- 正常情况下程序应从这里到达00406324
004063F9 MOV DWORD PTR DS:[4D7664],EAX
堆栈结构前面已列出,寄存器的情况这时是:
EAX=0 ECX=FE787F EDX=FE7F98 EBX=4D2B48
ESP=12FF6C EBP=12FFA0 ESI=5885C3 EDI=1
因此,程序在调用函数时,这几个量是重要的:
EAX=4D2B48、ESI=58853、EBP=12FFA0,来到这里,应有相似的堆栈结构,怎样仿真我想这
是一件仁者见仁的事吧。我在程序中构造了一个函数来完成,函数后面给出。
(三)去除暗桩:暗桩的查找太麻烦就免了,只说修改吧。使用 Hex编辑器作下列修改:
1.004D1E05 处的 FF 33和 004D1E0A 的 8F 03 全改成 90 90
2.004D1DD4 的 74 改为 EB
3.004D63E3 的 FC 2D 8C FD 改为 8D 8D 8D 8D
4.004D63F7 的 88 B9 18 89 改为 19 19 19 19
5.004D6413 的 63 94 F3 64 改为 F4 F4 F4 F4
(四)申请局部堆,仿真Aspr的验证数据
以前对付Aspr加壳程序都没有这一步,包括AlfaClock的1.60版,现在Aspr玩的花样是越
来越多了!
在修复的前两步完成后程序仍然不能正常执行,发现它要到139XXX去取数据,再次跟踪加
壳的程序,发现了这些“无聊”的数据,它们唯一的作用就是让你脱壳后的程序不能执行。
于是你也得在局部堆有相似的数据结构,哈,就在堆中申请一点内存来仿真吧!这些工作一
并交给我构造的函数来完成。不过说清这个函数的事就算了,函数如下
004D3330 PUSH EBP
004D3331 MOV EBP,ESP
004D3333 PUSHAD
004D3334 PUSH 0FF8 /Size = FF8 (4088.)
004D3339 PUSH 40 |Flags = LPTR
004D333B CALL \LocalAlloc
004D3340 PUSH EAX
004D3341 PUSH 664 /Size = 664 (1636.)
004D3346 PUSH 0 |Flags = LMEM_FIXED
004D3348 CALL \LocalAlloc
004D334D POP EDX
004D334E MOV DWORD PTR DS:[4D7620],EDX
004D3354 MOV DWORD PTR DS:[4D75E0],EAX
004D3359 MOV DWORD PTR DS:[EAX],0
004D335F MOV ECX,60
004D3364 MOV EDI,DWORD PTR DS:[4D75E0]
004D336A ADD EDI,14
004D336D MOV EBX,EDI
004D336F SUB EBX,10
004D3372 MOV DWORD PTR DS:[EDI],EBX
004D3374 ADD EDI,10
004D3377 ADD EBX,10
004D337A LOOPD SHORT dumped_.004D3372
004D337C ADD EBX,20
004D337F MOV DWORD PTR DS:[EDI],EBX
004D3381 ADD EDI,10
004D3384 ADD EBX,10
004D3387 MOV DWORD PTR DS:[EDI],EBX
004D3389 ADD EDI,10
004D338C SUB EBX,30
004D338F MOV DWORD PTR DS:[EDI],EBX
004D3391 MOV EDI,DWORD PTR DS:[4D75E0]
004D3397 ADD EDI,614
004D339D MOV DWORD PTR DS:[4D75E4],EDI
004D33A3 XOR EAX,EAX
004D33A5 MOV DWORD PTR DS:[4D75C8],EAX
004D33AA MOV DWORD PTR SS:[EBP+10],EAX
004D33AD MOV DWORD PTR SS:[EBP+14],EAX
004D33B0 MOV DWORD PTR SS:[EBP+18],EAX
004D33B3 POPAD
004D33B4 MOV EBX,71D
004D33B9 MOV DWORD PTR SS:[EBP+C],EBX
004D33BC MOV DWORD PTR SS:[EBP+1C],EBX
004D33BF POP EBP
004D33C0 ADD EBP,30
004D33C3 MOV DWORD PTR SS:[EBP-44],EBP
004D33C6 SUB EBP,50
004D33C9 RETN
注:CALL 是 CALL 401388
最后在4D2FBA键入下面代码,再用LordPE把EntryPoint的值改成000D2FBA,Over!
004D2FBA PUSH EBP
004D2FBB MOV EBP,ESP
004D2FBD ADD ESP,-40
004D2FC0 MOV EAX,dumped_.004D2B48
004D2FC5 MOV ESI,dumped_.005885C3
004D2FCA PUSH ESI
004D2FCB CALL dumped_.004D3330
这是我在001的第一篇,难免错误,请各位高手指点