-
-
[翻译]haggar教程:PESpin 1.304 public - repairing IAT
-
发表于: 2019-2-16 21:56 7840
-
======================================
PESpin 1.304 public - 修复 IAT
======================================
原文地址:http://www.reversing.be/article.php?story=20060224214713516
这个版本的PESpin和以前的1.3完全无关。在这个公开版本中,对脱壳来说没有什么新的东西(除了新的重定向JMP-CMP),因为这个版本只是为了解决可兼容性问题。但是在前面的教程中,没有解释如何正确修复IAT,只是一些在用户机器上运行转储的技巧,所以这部分将在本教程中得到更好的介绍。
1. 工具和材料
工具是常见的:
- OllyDbg 1.10
- ImpREC
- LordPE
- Windows XP
- 目标在这: [http://www.reversing.be/binaries/articles/20060224214414479.rar]
本教程将是简短的,因此,您将检查前面的更详细的那些不会是坏事。
2. OEP and stolen code
如果您记得过去的教程,PESpin在跳转到OEP之前将使用的最后一个API是GetTickCount。 它可能会使用它来获取一些随机值,以破坏它不再需要的代码/数据。 因此,我们可以在该API的末尾放置断点(PESpin检查CC字节的第一个字节)并返回保护代码。 所以我们现在非常接近OEP跳转。 PESpin将使用远跳转到原始代码部分。 所以我们可以到这个PESpin部分的开始并搜索对应于远跳的字节E9 ?????? FF。 然后我们找到所有那些可能的跳转,并且在401000部分跳转的第一个是好的。 我发现了这个跳转:
00417BC4 -E9 0F9AFEFF JMP KeygenMe.004015D8
但是如前所述,PESpin也可以从OEP中窃取一些字节。 被窃取的代码被混淆了,但它始终以POPAD操作码开头,就是16进制的61。 因此向上滚动并搜索此字节。 你会发现它在调用操作码中被混淆:
00417AD8 E8 61F7D239 CALL 3A14723E
Patch第一个字节:
00417AD8 90 NOP 00417AD9 61 POPAD
现在将bp放在POPAD上,运行,你将在那里中断。 在POPAD之后就开始执行被盗代码。 但是被盗的字节被垃圾代码混淆了。 如果我们知道我们的目标是Visual C ++程序,那么找到它并不是什么大问题。 代码混淆并不难,我可以找到确切的字节:
00417B36 55 PUSH EBP 00417B3A 8BEC MOV EBP,ESP 00417B3F 6A FF PUSH -1 00417B44 68 3482111F PUSH 1F118234 <------------------ 这4个操作码只是两个PUSH的混淆。 00417B49 812C24 6421D11E SUB DWORD PTR SS:[ESP],1ED12164 00417B50 68 48F020F7 PUSH F720F048 00417B55 810424 B03D1F09 ADD DWORD PTR SS:[ESP],91F3DB0 00417B5C 64:A1 00000000 MOV EAX,DWORD PTR FS:[0] 00417B65 50 PUSH EAX 00417B69 64:8925 00000000 MOV DWORD PTR FS:[0],ESP 00417B73 83EC 58 SUB ESP,58 00417B79 53 PUSH EBX 00417B7D 56 PUSH ESI 00417B81 57 PUSH EDI 00417B85 8965 E8 MOV DWORD PTR SS:[EBP-18],ESP 00417B8B FF15 CDA44100 CALL DWORD PTR DS:[41A4CD] <---- 混淆的API调用! 00417B94 33D2 XOR EDX,EDX 00417B99 8AD4 MOV DL,AH 00417B9E 8915 5C764000 MOV DWORD PTR DS:[40765C],EDX 00417BA7 8BC8 MOV ECX,EAX 00417BAC 81E1 FF000000 AND ECX,0FF 00417BB5 890D 58764000 MOV DWORD PTR DS:[407658],ECX 00417BBE C1E1 08 SHL ECX,8 00417BC4 -E9 0F9AFEFF JMP KeygenMe.004015D8 <------ 没有被盗,它会跳到假的OEP.
我们可以稍后恢复这些字节。 但这4个:
PUSH 1F118234 SUB DWORD PTR SS:[ESP],1ED12164 PUSH F720F048 ADD DWORD PTR SS:[ESP],91F3DB0
有:
PUSH 4060D0 PUSH 402DF8
但所有这一切都没有必要。 我们可以在这一行上转储:
00417B36 55 PUSH EBP
并且转储会很好。 只是OEP将在PESpin部分,而不是在第一部分。
3. Redirected code(三种重定向到PE头)
如果我们执行OEP跳转:
00417BC4 -E9 0F9AFEFF JMP KeygenMe.004015D8
我们将在代码部分中看到第一种重定向的代码(CALL-JMP):特征码#E8??????FF#
004015EB . E8 E8EBFFFF CALL KeygenMe.004001D8
众所周知,从以前的版本中,CALL导致
004001D8 -E9 E6160000 JMP KeygenMe.004018C3
并且JMP只是返回某个位置。 所以CALL到PE头是原始文件CALL到某个地址。
第二种重定向如下所示(JMP-PUSH):特征码#E9??????FF#
0040169E .-E9 95EBFFFF JMP KeygenMe.00400238
跳转到
00400238 68 FF000000 PUSH 0FF <--------------- 这是重定向的操作码。 0040023D -E9 61140000 JMP KeygenMe.004016A3 <-- 回来了。 Jumps 替代了 pushes.
第三种我在1.3版本的PEspin中没有看到的新的重定向(JMP-CMP):特征码#E9??????FF9090#
00401687 $-E9 94EBFFFF JMP KeygenMe.00400220 0040168C 90 NOP 0040168D 90 NOP
跳转到
00400220 833D 38764000 01 CMP DWORD PTR DS:[407638],1 <------ 重定向的操作码。 00400227 -E9 62140000 JMP KeygenMe.0040168E <------------ 回来了。
现在我可以编写可以修复该代码的OllyScript插件的小脚本。 在附件中看到它。 该脚本适用于所有1.x版本的PEPsin(应该)。
在运行时解密的代码块,所谓的“清除和加密标记”将不在本教程中讨论。 检查最后一个。
这就是全部。 只是IAT需要修复 :)
4. Problem with IAT
这不是一个难题,但在之前的教程中我没有足够的知识来了解ImpREC,PE结构等。首先我们需要看看我们的导入发生了什么,然后我们会考虑如何修复它们。 我在LoadLibraryA和GetProcAddress上放置断点以捕获正在处理导入的位置,但我什么也没找到。 这意味着PESpin不会使用这些api来加载库并找到api,而是可能有自定义编码函数来完成这项工作。 然后我检查已经加载的模块,当olly打开目标并播种(已经被Windows加载器加载)所有需要的dll:
Executable modules Base Size Entry Name File version Path 00400000 0001C000 004160D4 KeygenMe D:\PESpin\PESpin v1.304\KeygenMe.exe 77340000 0008B000 773419ED COMCTL32 5.82 (xpsp1.0208 C:\WINDOWS\system32\COMCTL32.DLL 77D40000 0008C000 77D53A05 USER32 5.1.2600.1561 (x C:\WINDOWS\system32\USER32.DLL 77DD0000 0008D000 77DD1D3D ADVAPI32 5.1.2600.1106 (x C:\WINDOWS\system32\ADVAPI32.dll 77E60000 000E6000 77E7ADB3 kernel32 5.1.2600.1560 (x C:\WINDOWS\system32\kernel32.dll 77F50000 000A7000 ntdll 5.1.2600.1106 (x C:\WINDOWS\System32\ntdll.dll 78000000 00087000 78001E0D RPCRT4 5.1.2600.1361 (x C:\WINDOWS\system32\RPCRT4.dll 7F000000 00041000 GDI32 5.1.2600.1561 (x C:\WINDOWS\system32\GDI32.dll
如果我只是在olly中运行目标,则不会加载新模块。 这给了我们第一个可能的答案,为什么不使用LoadLibraryA。 实际上它使用了几次,但不是用于API重定向目的。 GetProcAddress也使用了几次,但不适用于我们的api。 所以我采用另一种方法来节省跟踪代码的时间。
让我们找到OEP,看看第一次导入跳转的位置。 这是第一次导入跳转,即。 call:
00401605 . FF15 C8A44100 CALL DWORD PTR DS:[41A4C8]
我们看到它指向PESpin壳段而不是406000的IAT(应该)段。 检查该地址的转储:
0041A4C8 4B 02 3B 00 00 6A 02 3B 00 00 8E 02 3B 00 00 A9 K.;..j.;....;..? 0041A4D8 02 3B 00 00 BD 02 3B 00 00 DD 02 3B 00 00 F9 02 .;....;....;.... 0041A4E8 3B 00 00 11 03 3B 00 00 30 03 3B 00 00 48 03 3B ;....;..0.;..H.; ...
我们看到PESpin创建了一个指向003B0000部分的表。 指针dwords用0字节分隔。 这可能会扰乱ImpREC获取表,因为指针分隔应该用零终止dword(就是什么也没有)。 指针导致混淆的api跳转,或整个模拟api(如果它非常小,只有一行):
003B024B EB 01 JMP SHORT 003B024E;跳到混淆的地方去了 003B024D D9A1 1476ED77 FLDENV (28-BYTE) PTR DS:[ECX+77ED7614] 003B0253 C3 RETN
为Olly编写可以重建新表的小脚本很容易,但我们可以从导入跳转中删除混淆。 作为easies选项,我决定将内存断点放在003B0000部分,这样我就可以找到PESpin在那里写入混淆代码的地方。 好的,在VirtualAlloc上bp,等待直到它分配该部分。 然后内存bp就可以了。 我在这里停了下来:
00416BCE 66:C706 EB01 MOV WORD PTR DS:[ESI],1EB 00416BD3 C646 02 D9 MOV BYTE PTR DS:[ESI+2],0D9 00416BD7 83C6 03 ADD ESI,3 00416BDA 2BD2 SUB EDX,EDX 00416BDC EB 01 JMP SHORT KeygenMe.00416BDF 00416BDE EA EB04EAEB 0400 JMP FAR 0004:EBEA04EB ... ...
PESpin在这里写了某些东西。 我们处于混淆正在进行中的代码的一部分。 如果我们从上一个教程中记得,这个过程(IAT重定向)从PUSHAD开始,以POPAD结束。 向上滚动以查找PUSHAD:
00416BAF 60 PUSHAD <----------------------- 呀,在这里。 00416BB0 EB 01 JMP SHORT KeygenMe.00416BB3 00416BB2 ^71 EB JNO SHORT KeygenMe.00416B9F 00416BB4 04 D5 ADD AL,0D5 00416BB6 EB 04 JMP SHORT KeygenMe.00416BBC 00416BB8 6BEB FB IMUL EBP,EBX,-5 ... ...
我们非常接近任务的结束,将硬件执行bp放在PUSHAD上并重新启动目标。 在Olly中运行它你应该会在那里中断。 再次,在之前的教程中,我们宣称这个步骤可以这样:从PUSHAD到POPAD NOP-ed,我们将杀死混淆:
00416BAF 60 PUSHAD 00416BB0 90 NOP 00416BB1 90 NOP 00416BB2 90 NOP ... ... ... 00416C95 90 NOP 00416C96 90 NOP 00416C97 90 NOP 00416C98 61 POPAD 00416C99 C9 LEAVE 00416C9A C2 0800 RETN 8
此代码也不会通过完整性检查进行检查,因此我们可以保留它。 现在我们找到了本教程第一部分所描述的被盗代码(注意,已经使用了GetTickCount,因此您需要在此步骤之前找到代码地址),然后我们在正确的OEP上恢复它:
00401591 /. 55 PUSH EBP 00401592 |. 8BEC MOV EBP,ESP 00401594 |. 6A FF PUSH -1 00401596 |. 68 D0604000 PUSH KeygenMe.004060D0 0040159B |. 68 F82D4000 PUSH KeygenMe.00402DF8 ; SE handler installation 004015A0 |. 64:A1 00000000 MOV EAX,DWORD PTR FS:[0] 004015A6 |. 50 PUSH EAX 004015A7 |. 64:8925 000000>MOV DWORD PTR FS:[0],ESP 004015AE |. 83EC 58 SUB ESP,58 004015B1 |. 53 PUSH EBX 004015B2 |. 56 PUSH ESI 004015B3 |. 57 PUSH EDI ; KeygenMe.004188EA 004015B4 |. 8965 E8 MOV DWORD PTR SS:[EBP-18],ESP 004015B7 |. FF15 CDA44100 CALL DWORD PTR DS:[41A4CD] ; kernel32.GetVersion 004015BD |. 33D2 XOR EDX,EDX 004015BF |. 8AD4 MOV DL,AH 004015C1 |. 8915 5C764000 MOV DWORD PTR DS:[40765C],EDX 004015C7 |. 8BC8 MOV ECX,EAX 004015C9 |. 81E1 FF000000 AND ECX,0FF 004015CF |. 890D 58764000 MOV DWORD PTR DS:[407658],ECX 004015D5 |. C1E1 08 SHL ECX,8
然后我们使用脚本来修复重定向的代码。
5. Fixing IAT
现在我们可以修复IAT了。 我为这个VC ++应用程序编写了一个小脚本,它将更改指向新选项卡的所有指针。 例如,这个call:
004015B7 |. FF15 CDA44100 CALL DWORD PTR DS:[41A4CD] ; kernel32.GetVersion
现在将指向新的地方:
004015B7 |. FF15 90604100 CALL DWORD PTR DS:[416090] ; kernel32.GetVersion
在那里我创建了新标签:
00416000 00 00 00 00 00 00 00 00 E0 56 D6 77 00 00 00 00 .........V.w.... 00416010 1F 97 D4 77 00 00 00 00 1D 5F D4 77 00 00 00 00 ...w....._.w.... 00416020 52 65 D6 77 00 00 00 00 52 65 D6 77 00 00 00 00 Re.w....Re.w.... 00416030 52 65 D6 77 00 00 00 00 E4 D9 D4 77 00 00 00 00 Re.w.......w.... 00416040 FE 65 D6 77 00 00 00 00 FE 65 D6 77 00 00 00 00 .e.w.....e.w.... 00416050 >FE 65 D6 77 00 00 00 00 0F 6E D5 77 00 00 00 00 .e.w.....n.w.... 00416060 >0F 6E D5 77 00 00 00 00 0F 6E D5 77 00 00 00 00 .n.w.....n.w.... 00416070 93 5A E7 77 00 00 00 00 0C 16 E6 77 00 00 00 00 .Z.w.......w.... 00416080 53 95 E7 77 00 00 00 00 A1 16 F5 77 00 00 00 00 S..w.......w.... 00416090 95 D0 E7 77 00 00 00 00 AB E2 E7 77 00 00 00 00 ...w.......w.... 004160A0 7E 17 E6 77 00 00 00 00 D9 AC E7 77 00 00 00 00 ~..w.......w.... 004160B0 63 98 E7 77 00 00 00 00 25 E2 E7 77 00 00 00 00 c..w....%..w.... 004160C0 7C 88 E7 77 00 00 00 00 A1 16 F5 77 00 00 00 00 |..w.......w.... 004160D0 6B 15 F5 77 00 00 00 00 5F 8C F5 77 00 00 00 00 k..w...._..w.... 004160E0 A1 16 F5 77 00 00 00 00 C5 AB E7 77 00 00 00 00 ...w.......w.... 004160F0 6B 15 F5 77 00 00 00 00 C5 AB E7 77 00 00 00 00 k..w.......w.... 00416100 0C E6 E7 77 00 00 00 00 B8 16 E6 77 00 00 00 00 ...w.......w.... 00416110 63 98 E7 77 00 00 00 00 95 9B E9 77 00 00 00 00 c..w.......w.... 00416120 FC AC E7 77 00 00 00 00 3B 95 E6 77 00 00 00 00 ...w....;..w.... 00416130 E8 E4 E7 77 00 00 00 00 3B 95 E6 77 00 00 00 00 ...w....;..w.... 00416140 2F E0 E9 77 00 00 00 00 7E 17 E6 77 00 00 00 00 /..w....~..w.... 00416150 4E E3 E7 77 00 00 00 00 E7 E3 E7 77 00 00 00 00 N..w.......w.... 00416160 4E E3 E7 77 00 00 00 00 A4 E2 E7 77 00 00 00 00 N..w.......w.... 00416170 FC AC E7 77 00 00 00 00 E7 E3 E7 77 00 00 00 00 ...w.......w.... 00416180 8D F0 E7 77 00 00 00 00 53 95 E7 77 00 00 00 00 ...w....S..w.... 00416190 1B E0 E7 77 00 00 00 00 7F C9 E6 77 00 00 00 00 ...w.......w.... 004161A0 7F C9 E6 77 00 00 00 00 4F A7 E7 77 00 00 00 00 ...w....O..w.... 004161B0 4F A7 E7 77 00 00 00 00 1B E0 E7 77 00 00 00 00 O..w.......w.... 004161C0 B1 E2 E7 77 00 00 00 00 B1 E2 E7 77 00 00 00 00 ...w.......w.... 004161D0 6B 15 F5 77 00 00 00 00 A1 16 F5 77 00 00 00 00 k..w.......w.... 004161E0 B4 D8 E7 77 00 00 00 00 D1 DD E7 77 00 00 00 00 ...w.......w.... 004161F0 84 9F E7 77 00 00 00 00 84 9F E7 77 00 00 00 00 ...w.......w.... 00416200 4F A7 E7 77 00 00 00 00 4F A7 E7 77 00 00 00 00 O..w....O..w.... 00416210 D1 DD E7 77 00 00 00 00 D1 DD E7 77 00 00 00 00 ...w.......w.... 00416220 D1 DD E7 77 00 00 00 00 9C A8 E7 77 00 00 00 00 ...w.......w.... 00416230 E8 D8 E7 77 00 00 00 00 23 5D E7 77 00 00 00 00 ...w....#].w.... 00416240 23 5D E7 77 00 00 00 00 B1 E2 E7 77 00 00 00 00 #].w.......w.... 00416250 4F A7 E7 77 00 00 00 00 4F A7 E7 77 00 00 00 00 O..w....O..w.... 00416260 E8 D8 E7 77 00 00 00 00 B4 90 E6 77 00 00 00 00 ...w.......w.... 00416270 A1 16 F5 77 00 00 00 00 5F 8C F5 77 00 00 00 00 ...w...._..w.... 00416280 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00416290 C2 25 E7 77 00 00 00 00 DE AF E7 77 00 00 00 00 .%.w.......w.... 004162A0 44 0C F6 77 00 00 00 00 00 00 00 00 00 00 00 00 D..w............ 004162B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ...............
现在我们有了thunk,每个导入值用4个零终止字节分隔,ImpREC可以很容易地读取它。 现在我们只运行ImpREC并修复转储文件。 保存文件,运行,...,呀,它工作起来了 :)
这不是完美的工作,因为属于同一个dll的thunk应该粘在一起,这会减少文件的大小,我们也可以删除PESpin部分,但是,嘿,现在dump工作在每台机器上 :)
再见!
haggar
快捷脱壳:
1、找回代码+OEP:忽略所有异常OD载入目标,ESP定律+F7单步+去除花指令找到被偷代码及伪OEP=004015D8
2、API 处理:HE 00416BAF重启OD并F9运行断下来,NOP掉00416BB0-00416C97(从PUSHAD到POPAD)
删掉硬件断点,M镜像401000处F2下断,F9运行到伪OEP=004015D8
3、修复代码:伪OEP=004015D8处上翻,空代码处二进制粘贴
55 8B EC 6A FF 68 D0 60 40 00 68 F8 2D 40 00 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 58 53 56 57 89 65 E8 FF 15 CD A4 41 00 33 D2 8A D4 89 15 5C 76 40 00 8B C8 81 E1 FF 00 00 00 89 0D 58 76 40 00 C1 E1 08
4、重定向处理+IAT修复:运行脚本PESpin 1.x - Code Fixer.txt及PESpin 1.304 - VC imports.txt
5、Dump修复:用LordPE来Dump,OEP=1591,ImportREC高级方式获取API,剪掉多余项,转存即可运行了。
PEspin各版本历史:
History历史 v1.33 (c101) ★双进程 Added support for vs2010 files--------添加了对vs2010文件的支持 Minor bugs fixed--------小错误已修复 v1.32 ★双进程 Added DLLs support--------添加了DLL支持 v1.304 ★可以双进程 Fixed compatible with VMWare--------修复了与VMWare的兼容 Updated aPlib--------更新了aPlib ★在这个公开版本中,对脱壳来说没有什么新的东西(除了新的重定向JMP-CMP),因为这个版本只是为了解决可兼容性问题。 它具有三种重定向到PE头: 第一种重定向(CALL-JMP):特征码#E8??????FF# 第二种重定向(JMP-PUSH):特征码#E9??????FF# 第三种重定向(JMP- CMP):特征码#E9??????FF9090# v1.3 Added Debug blocker option--------添加了阻止调试选项★双进程 ★1.3版本具有高级代码重定向选项,公共版本中没有该选项。 它具有两种重定向到PE头: 第一种重定向(call-jmp):特征码#E8??????FF# 第二种重定向(JMP-PUSH):特征码#E9??????FF# v1.2 Private version not available to public--------私人版本不向公众开放 v1.1 Added CRYPT_START & CRYPT_END markers--------添加了CRYPT_START和CRYPT_END标记 Added CLEAR_START & CLEAR_END markers--------添加了CLEAR_START和CLEAR_END标记 它具有两种重定向到PE头: 第一种重定向(call-jmp):特征码#E8??????FF# 第二种重定向(JMP-PUSH):特征码#E9??????FF# v1.0 Added Code redirection option--------添加了代码重定向选项 Added optimize MS-DOS header size option--------添加了优化MS-DOS标头大小选项 Cleaned up GUI a bit--------稍微清理了GUI ★在这个版本中,PESpin有两个新技巧:API bp检查和代码重定向。 它具有两种重定向到PE头: 第一种重定向(call-jmp):特征码#E8??????FF# 第二种重定向(JMP-PUSH):特征码#E9??????FF# v0.7 Added auto configuration saving--------添加了自动配置保存 Generally improve file protection--------常规改善文件保护 v0.41 Added Compress resources option--------添加了压缩资源选项 Win2003 bug fixed--------已修复Win2003错误 v0.3 Added compression--------添加压缩 Added Strip Overlays option--------添加了“剥离附加数据”选项 ★PESpin v0.3 有一些很好的功能; 良好的IAT重定向与一些仿真API操作码和被盗的OEP是它的最佳武器。 它也有一些基于异常的反调试技巧,但是Olly是免疫的,它检查SoftICE和NTICE,它有几个CRC校验,它有密码锁定和时间限制,但这不是问题。 在使用不同编译器编译的打包文件之间也存在一些小的差异 (VC++,Borland C++, Delphi, VB, ASM...). v0.2 Generally improve a little bit whole loader code--------整个加载器代码的一点点常规改进 v0.1 Added password protection option--------添加了密码保护选项 Added remove the OEP option--------添加抽离OEP选项 v0.b First official version--------第一个正式版
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
他的文章
看原图
赞赏
雪币:
留言: