MoleBox 脱壳的一些总结 By:CCDebuger
标 题: MoleBox 脱壳的一些总结作 者: CCDebuger
时 间: 2007-04-14,09:41
链 接: http://bbs.pediy.com/showthread.php?t=42700
【文章标题】: MoleBox 脱壳的一些总结
【文章作者】: CCDebuger
【软件名称】: Ultra Video Converter
【下载地址】: http://www.zxmedia.com/ultra_videoconverter.exe
【作者声明】: 无他,仅是自己调试时的一些记录,方便查阅而已
--------------------------------------------------------------------------------
【详细过程】
论坛上写MoleBox脱壳教程的已经有不少了,大家应该知道MoleBox会加密输入表。我看了几个MoleBox加的壳和MoleBox的主程序,发现这个壳还是挺有意思的。只要你找好关键点,可以 dump 出来一个完整的未加壳前的程序,MoleBox的那个加密输入表的功能根本没用。这篇文章只是我自己的一个调试记录,只是为了方便自己查阅。大家可以参考一下。OK,现在进入正题。
一、主程序脱壳
在 OD 中忽略所有异常,载入程序:
00470B53 >E8 00000000 CALL Ultra_Vi.00470B58 ; OD载入后停在这
00470B58 60 PUSHAD
00470B59 E8 4F000000 CALL Ultra_Vi.00470BAD ; F8到这里的时候在命令行中输入hr esp
完成上面的操作后,直接按 F9,会断在这里:
00470731 58 POP EAX ; 断在这里
00470732 58 POP EAX
00470733 FFD0 CALL EAX ; 这里F7进去就是OEP
我们到 00470733 地址处时按 F7 进去,就到 OEP 了:
0042304E 55 PUSH EBP ; OEP
0042304F 8BEC MOV EBP,ESP
00423051 6A FF PUSH -1
00423053 68 90A74200 PUSH Ultra_Vi.0042A790
00423058 68 B8314200 PUSH Ultra_Vi.004231B8 ; JMP 到 msvcrt._except_handler3
0042305D 64:A1 00000000MOV EAX,DWORD PTR FS:
00423063 50 PUSH EAX
00423064 64:8925 0000000>MOV DWORD PTR FS:,ESP
0042306B 83EC 68 SUB ESP,68
0042306E 53 PUSH EBX
0042306F 56 PUSH ESI
00423070 57 PUSH EDI
00423071 8965 E8 MOV DWORD PTR SS:,ESP
00423074 33DB XOR EBX,EBX
00423076 895D FC MOV DWORD PTR SS:,EBX
00423079 6A 02 PUSH 2
0042307B FF15 38764200 CALL DWORD PTR DS: ; msvcrt.__set_app_type
看 OEP 开始的代码就知道这是个典型的 VC 程序。记住 OEP 的 RVA = 0042304E- 00400000 = 2304E。随便找个 API 调用,如 0042307B 处的这句。左键选择这句,按鼠标右键,选择弹出菜单 数据窗口中跟随->内存地址。现在在数据窗口中按CTR+G转到427638(这样做主要是为了便于OD记住这个地址),重新启动程序,在数据窗口中转到我们上次记住的地址,设内存写入断点。在数据窗口中按右键切换一下视图,选择长型->地址,这样便于观察。经过几次中断后,数据窗口中会看到这样的内容:
0042762473DC067BMFC42.#952_??_afxSOCK@@3UAFX_SOCK_CALL@@A@@YAXXZ
0042762873DCC3C8MFC42.#3716_?GetRuntimeClass@CSliderCtrl@@UBEPAUCRuntimeClass@@XZ
0042762C73D8ACCEMFC42.#541_??0CStringArray@@QAE@XZ
0042763000000000
0042763477C1EE2Fmsvcrt._controlfp
004276380002E8E4
0042763C0002E8D6
004276400002E8C6
004276440002E8B6
004276480002E8A2
0042764C0002E896
004276500002F52C
004276540002E87C
004276580002E874
0042765C0002E866
可见00427638下面的都没被填充,而上面已经填入了API函数的实际地址了。重来,在上面填充过地址的地方重设内存断点,直到输入表部分都显示为这样的:
004276380002E8E4
0042763C0002E8D6
004276400002E8C6
004276440002E8B6
004276480002E8A2
现在就可以dump了。用16进制工具打开dump后的文件,推荐用 010Editor。先定位到输入表所在区段,查找 ASCII 字串“.dll”,看看找到的地方,比如看到了 KERNEL32.dll。记下 KERNEL32.dll 的开始地址,逆序转换一下(可以用 Hpmbcalc Hex Calculator 来转换),再在输入表所在段中搜索 KERNEL32.dll 开始地址的逆序字串,一般只会找到一个地方。根据 IAT 的结构,名称在第四个字段,往前再数12个字节就是这个 DLL 调用信息开始的地方。再根据 IAT 最后以20个0结束,就可以确定输入表的开始地址和大小了。把我们找到的 OEP 和 IAT 信息用 PE 编辑工具填入 dump 后的文件就可以了。
--------------------------------------------------------------------------------------------------
上面说的是一种跟踪加壳程序处理输入表比较通用的方法。对于 MoleBox,为了得到完好的输入表,可以 BP VirtualProtect 设断点。这也分两种情况:
1、MoleBoxPro_2.6.1.2387主程序脱壳例子
先到MoleBox壳的EP,设断 BP VirtualProtect,中断两次后返回,来到下面的地方:
0043AB9D FF15 AC774400 CALL DWORD PTR DS: ; kernel32.VirtualProtect
0043ABA3 8B15 84764400 MOV EDX,DWORD PTR DS: ; =00CD1F00,地址00CD1F00中就是OEP
0043ABA9 8B45 E8 MOV EAX,DWORD PTR SS:
0043ABAC 0342 08 ADD EAX,DWORD PTR DS: ; =00027B00,输入表的RVA。这里直接dump文件
0043ABAF 8945 F4 MOV DWORD PTR SS:,EAX
0043ABB2 C705 14794400 0>MOV DWORD PTR DS:,0
0043ABBC 6A 00 PUSH 0
0043ABBE 68 246C4400 PUSH mbox2w.00446C24 ; ASCII "EXECUTABLE"
0043ABC3 8B0D 10794400 MOV ECX,DWORD PTR DS: ; mbox2w.00400108
0043ABC9 51 PUSH ECX
0043ABCA 8B55 E8 MOV EDX,DWORD PTR SS:
0043ABCD 52 PUSH EDX
0043ABCE 8B45 F4 MOV EAX,DWORD PTR SS:
0043ABD1 50 PUSH EAX
0043ABD2 E8 E9FAFFFF CALL mbox2w.0043A6C0
0043ABD7 83C4 14 ADD ESP,14
0043ABDA E8 B30F0000 CALL mbox2w.0043BB92
0043ABDF 25 FF000000 AND EAX,0FF
0043ABE4 85C0 TEST EAX,EAX
0043ABE6 74 15 JE SHORT mbox2w.0043ABFD
0043ABE8 E8 B60F0000 CALL mbox2w.0043BBA3
0043ABED 25 FF000000 AND EAX,0FF
0043ABF2 85C0 TEST EAX,EAX
0043ABF4 74 02 JE SHORT mbox2w.0043ABF8
0043ABF6^ EB F0 JMP SHORT mbox2w.0043ABE8
0043ABF8 E8 950F0000 CALL mbox2w.0043BB92
0043ABFD 68 846C4400 PUSH mbox2w.00446C84 ; ASCII "imm32.dll"
0043AC02 FF15 18774400 CALL DWORD PTR DS: ; kernel32.GetModuleHandleA
0043AC08 8945 E4 MOV DWORD PTR SS:,EAX
0043AC0B 837D E4 00 CMP DWORD PTR SS:,0
0043AC0F 74 0E JE SHORT mbox2w.0043AC1F
0043AC11 68 846C4400 PUSH mbox2w.00446C84 ; ASCII "imm32.dll"
0043AC16 8B4D E4 MOV ECX,DWORD PTR SS:
0043AC19 51 PUSH ECX
0043AC1A E8 31000000 CALL mbox2w.0043AC50
0043AC1F 68 746C4400 PUSH mbox2w.00446C74 ; ASCII "oleoaut32.dll"
0043AC24 FF15 18774400 CALL DWORD PTR DS: ; kernel32.GetModuleHandleA
0043AC2A 8945 F0 MOV DWORD PTR SS:,EAX
0043AC2D 837D F0 00 CMP DWORD PTR SS:,0
0043AC31 74 0E JE SHORT mbox2w.0043AC41
0043AC33 68 646C4400 PUSH mbox2w.00446C64 ; ASCII "oleaout32.dll"
2、极品时刻表的例子
如果未发现与上面代码类似的内容,可以结合堆栈来看。比如极品时刻表,Delphi 程序,里面是aspack的壳。BP VirtualProtect第一次断下来的时候看堆栈:
0012FDB8 004F621C/CALL 到 VirtualProtect 来自 JPSKB061.004F6216
0012FDBC 004E9F5C|Address = JPSKB061.004E9F5C
0012FDC0 00000004|Size = 4
0012FDC4 00000004|NewProtect = PAGE_READWRITE
0012FDC8 0012FDCC\pOldProtect = 0012FDCC
0012FDCC 00000000
0012FDD0 003D20EC
0012FDD4 005021B8JPSKB061.005021B8
0012FDD8 00000000
0012FDDC/0012FE30
0012FDE0|004F5AA6返回到 JPSKB061.004F5AA6 来自 JPSKB061.004F61D0
0012FDE4|004E9F5CJPSKB061.004E9F5C
0012FDE8|00501B44ASCII "EXECUTABLE"
0012FDEC|004E9F6CASCII "kernel32.dll"
0012FDF0|00000001
0012FDF4|00000000
0012FDF8|00000000
0012FDFC|0045AB2CJPSKB061.0045AB2C
0012FE00|00501B4EJPSKB061.00501B4E
0012FE04|00501B4EJPSKB061.00501B4E
0012FE08|C1CC0928
0012FE0C|39ADD078
0012FE10|004E9F79JPSKB061.004E9F79
0012FE14|004E9F6CASCII "kernel32.dll"
0012FE18|004E9F5CJPSKB061.004E9F5C
0012FE1C|004E9F6CASCII "kernel32.dll"
0012FE20|7C800000kernel32.7C800000
0012FE24|FA46F001
0012FE28|004E9F5CJPSKB061.004E9F5C
0012FE2C|00000000
0012FE30]0012FE74
0012FE34|004F5C54返回到 JPSKB061.004F5C54 来自 JPSKB061.004F58A0;右键选择这里,在反汇编窗口中跟随
0012FE38|004E9FACJPSKB061.004E9FAC
0012FE3C|00400000ASCII "MZP"
0012FE40|00400100ASCII "PE"
0012FE44|00501B44ASCII "EXECUTABLE"
0012FE48|00000000
0012FE4C|00000001
0012FE50|00000000
0012FE54|00000001
0012FE58|00000000
0012FE5C|004EF564ASCII ".adata"
0012FE60|003D0000
0012FE64|00400000ASCII "MZP"
0012FE68|0000000A
0012FE6C|004E9FACJPSKB061.004E9FAC
0012FE70|0000000A
0012FE74]0012FF94
0012FE78|004EFF6B返回到 JPSKB061.004EFF6B 来自 JPSKB061.004F5B10
0012FE7C|7C930738ntdll.7C930738
在堆栈中的第二个返回上右键选择反汇编窗口中跟随,会来到这样的地方:
004F5C16 E8 65000000 CALL JPSKB061.004F5C80
004F5C1B^ E9 4DFFFFFF JMP JPSKB061.004F5B6D
004F5C20 8B15 08255000 MOV EDX,DWORD PTR DS: ; 放OEP的地方
004F5C26 8B45 F0 MOV EAX,DWORD PTR SS:
004F5C29 0342 08 ADD EAX,DWORD PTR DS:
004F5C2C 8945 F8 MOV DWORD PTR SS:,EAX
004F5C2F C705 38275000 0>MOV DWORD PTR DS:,0
004F5C39 6A 00 PUSH 0
004F5C3B 68 441B5000 PUSH JPSKB061.00501B44 ; EXECUTABLE
004F5C40 8B0D 34275000 MOV ECX,DWORD PTR DS: ; JPSKB061.00400100
004F5C46 51 PUSH ECX
004F5C47 8B55 F0 MOV EDX,DWORD PTR SS:
004F5C4A 52 PUSH EDX
004F5C4B 8B45 F8 MOV EAX,DWORD PTR SS:
004F5C4E 50 PUSH EAX
004F5C4F E8 4CFCFFFF CALL JPSKB061.004F58A0
004F5C54 83C4 14 ADD ESP,14 ; 返回到这里
004F5C57 68 841B5000 PUSH JPSKB061.00501B84 ; imm32.dll
004F5C5C FF15 9C255000 CALL DWORD PTR DS: ; kernel32.GetModuleHandleA
004F5C62 8945 EC MOV DWORD PTR SS:,EAX
004F5C65 837D EC 00 CMP DWORD PTR SS:,0
004F5C69 74 0E JE SHORT JPSKB061.004F5C79
004F5C6B 68 841B5000 PUSH JPSKB061.00501B84 ; imm32.dll
004F5C70 8B4D EC MOV ECX,DWORD PTR SS:
004F5C73 51 PUSH ECX
004F5C74 E8 F7010000 CALL JPSKB061.004F5E70
004F5C79 8BE5 MOV ESP,EBP
004F5C7B 5D POP EBP
004F5C7C C3 RETN
004F5C20就是我们要找的地方。
对上面的第二种情况,根据上面看到的代码,也可以尝试搜索命令序列:
MOV EAX,DWORD PTR SS:
ADD EAX,DWORD PTR DS:
MOV DWORD PTR SS:,EAX
如极品时刻表,搜索以上命令序列时,会找到这样的地方:
004F5C16 E8 65000000 CALL JPSKB061.004F5C80
004F5C1B^ E9 4DFFFFFF JMP JPSKB061.004F5B6D
004F5C20 8B15 08255000 MOV EDX,DWORD PTR DS:
004F5C26 8B45 F0 MOV EAX,DWORD PTR SS: ; 找到的地方
004F5C29 0342 08 ADD EAX,DWORD PTR DS:
004F5C2C 8945 F8 MOV DWORD PTR SS:,EAX
004F5C2F C705 38275000 0>MOV DWORD PTR DS:,0
004F5C39 6A 00 PUSH 0
004F5C3B 68 441B5000 PUSH JPSKB061.00501B44 ; EXECUTABLE
004F5C40 8B0D 34275000 MOV ECX,DWORD PTR DS: ; JPSKB061.00400100
004F5C46 51 PUSH ECX
004F5C47 8B55 F0 MOV EDX,DWORD PTR SS:
004F5C4A 52 PUSH EDX
004F5C4B 8B45 F8 MOV EAX,DWORD PTR SS:
004F5C4E 50 PUSH EAX
004F5C4F E8 4CFCFFFF CALL JPSKB061.004F58A0
004F5C54 83C4 14 ADD ESP,14
004F5C57 68 841B5000 PUSH JPSKB061.00501B84 ; imm32.dll
004F5C5C FF15 9C255000 CALL DWORD PTR DS: ; kernel32.GetModuleHandleA
004F5C62 8945 EC MOV DWORD PTR SS:,EAX
004F5C65 837D EC 00 CMP DWORD PTR SS:,0
004F5C69 74 0E JE SHORT JPSKB061.004F5C79
004F5C6B 68 841B5000 PUSH JPSKB061.00501B84 ; imm32.dll
004F5C70 8B4D EC MOV ECX,DWORD PTR SS:
004F5C73 51 PUSH ECX
004F5C74 E8 F7010000 CALL JPSKB061.004F5E70
004F5C79 8BE5 MOV ESP,EBP
004F5C7B 5D POP EBP
004F5C7C C3 RETN
总体看来,MoleBox解压程序前字串“EXECUTABLE”是个非常重要的标志,而在 VirtualProtect 函数上设断点,是个不错的选择。
二、捆绑文件
1、文件数目
要知道捆绑文件的数目,可以通过 BP GetFileTime 设断得到。以 Ultra Video Converter 为例,中断后取消断点Alt+F9返回:
00476C8C FF15 84364800 CALL DWORD PTR DS: ; kernel32.GetFileTime
00476C92 C745 AC 00000000MOV DWORD PTR SS:,0 ; 返回到这里
00476C99 EB 09 JMP SHORT Ultra_Vi.00476CA4
00476C9B 8B4D AC MOV ECX,DWORD PTR SS:
00476C9E 83C1 01 ADD ECX,1
00476CA1 894D AC MOV DWORD PTR SS:,ECX
00476CA4 8B55 AC MOV EDX,DWORD PTR SS:
00476CA7 3B55 9C CMP EDX,DWORD PTR SS: ; 这里=1,就是捆绑文件的数目
00476CAA 0F83 E3000000 JNB Ultra_Vi.00476D93
00476CB0 8B45 AC MOV EAX,DWORD PTR SS:
00476CB3 C1E0 04 SHL EAX,4
00476CB6 8B4D E0 MOV ECX,DWORD PTR SS:
00476CB9 8B51 04 MOV EDX,DWORD PTR DS:
00476CBC 8B4D DC MOV ECX,DWORD PTR SS: ; =003D2370,数据窗口中可以看到文件名
00476CBF 030C02 ADD ECX,DWORD PTR DS:
00476CC2 8B55 AC MOV EDX,DWORD PTR SS:
00476CC5 C1E2 04 SHL EDX,4
2、参与运行的可执行文件
对于参与运行的可执行文件,可以通过以下三个断点获取文件:
(1) BP CreateFileA,断下后看堆栈,根据堆栈显示信息改文件名(在 BP CreateFileA 之前,可以通过 BP GetCurrentProcessId 看到对捆绑文件更名的处理)。
(2) BP GetModuleHandleA,断下后取消断点(BP VirtualProtect 在对付捆绑文件时好像也很有功效,能得到OEP地址。有空再仔细研究)。
(3) 在参与执行的 DLL 代码段上设内存访问断点,到达OEP。
而在第二步时dump下来,文件的输入表都是未被填充过的。只要修正一下OEP,重定位表、输入表的RVA和大小,必要时修正一下基址,就OK了。
对于采用上面的第三步找OEP无效的文件,这时可以在上面的第一步后 BP GetSystemTimeAsFileTime,中断两次后ALT+F9返回(以下都以 MoleBoxPro_2.6.1.2387 主程序为例):
00436FE1 FF15 2C774400 CALL DWORD PTR DS: ; kernel32.GetSystemTimeAsFileTime
00436FE7 8B45 C4 MOV EAX,DWORD PTR SS: ; 回到这里,中就是PE文件头
00436FEA 8B4D F0 MOV ECX,DWORD PTR SS:
00436FED 64:890D 00000000MOV DWORD PTR FS:,ECX
数据窗口中显示如下:
00D300984D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00MZ?...... 照着操作也不行。。。。郁闷 原帖由 senots 于 2007-10-6 01:09 发表 https://www.chinapyg.com/images/common/back.gif
照着操作也不行。。。。郁闷
这个软件我现在正在下,准备测试一下
OEP好找,就是完整的还原IAT表还不容易搞定
[ 本帖最后由 yunfeng 于 2007-10-6 07:16 编辑 ] 恩。OEP找到了。IAT也修复了。但是运行的时候还是会弹个对话框。确定后能正常运行程序 虽然我不太会,但好要好好的看看啊! 这个壳确实难啊~~~~ 是该好好学学-以前一直用它做单文件绿色版软件 原帖由 senots 于 2007-10-6 09:57 发表 https://www.chinapyg.com/images/common/back.gif
恩。OEP找到了。IAT也修复了。但是运行的时候还是会弹个对话框。确定后能正常运行程序
讲一下IAT表是如何修复的 参考了一下 看不懂啊 水平不行 这个壳真的要好好研究一下
最后一题了 赶在明天之前看看能不能完成了 这个壳确实难啊~~~~修复麻烦。有脚本跑吗?
页:
[1]
2