////////////////////////////////////////////////////////////////////////////////////////////
文件名称:手脱WinUpack 0.399壳
目标程序:病毒样本“泡泡”恶意程序
操作环境:Windows XP-SP2
使用工具:Ollydbg 1.10版
编写作者:Coderui
编写时间:2007年12月16日
联系方式:coderui@163.com
作者博客:
114K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3S2A6i4K6u0W2j5X3q4A6k6s2g2Q4x3X3g2U0L8$3#2Q4x3V1k6U0L8$3c8W2M7Y4g2A6
---------------------------------------------------------------------------------------------
介绍:
0.399版的WinUpack壳会使PEID在扫描时崩溃。使OD在加载时提示“错误:32 位可执行文件 'C:\auto.exe' 的格式错误或格式未知”,确定后OD停在ntdll里,无法返回到主程序领空。
一年前就遇到过这个壳,以前不知道叫什么名字,后来得到了这个壳的加壳程序,终于知道是什么壳了,但一直还是不会脱(因为无法跟,加载后停在系统DLL里,单步跟N久后还是在系统DLL里转,一生气想用[ALT+F9]返回主程序领空,结果程序就会跑飞运行了)。
今天因为要动态调试分析一个病毒,结果加的就是这个壳,郁闷。这个病毒会释放不只一个DLL恶意组件加载运行(超级流氓软件类),被我跑飞2次,呵呵。后来一个网上的朋友帮用脱壳机给脱掉了,然后发给了我。虽然把脱掉壳后的病毒分析完了,心理感觉不爽,既然脱壳机可以脱,我就一定要手脱。结果发现,原来使用对“GetProcAddress”API下断脱这个壳这么简单(使用类似技术的壳都可以拿这种方法去对付),所以就记录下了手脱的过程。在网上没找到0.399版WinUpack壳的脱文,为了方便就发出来与大家分享下吧,希望对需要的朋友有帮助~_~。
---------------------------------------------------------------------------------------------
重点:
方法1:OD设置:不忽略任何异常。
OD加载程序停在入口点->下命令bp GetProcAddress断点->[F9]运行(可能需要运行多次才能看到返回值是到主程序领空)->当返回值到主程序领空时,[F2]清除断点->下当前函数返回用户空间地址的断点(方法1:硬件断点hr esp值。方法2:在反汇编窗口按[SHIFT+G],输入“[esp]”包括大括号,而且esp是字母,不是esp值)->确定->返回到用户空间后,向下找2条指令,第一个retn指令(JMP指令后边的retn指令),它指向的就是入口点了->然后用工具修复输入表就可以了。
方法2:OD设置:不忽略任何异常。
OD加载程序停在入口点->下命令bp LoadLibraryA断点->[F9]运行->[F2]清除断点->下当前函数返回用户空间地址的断点(方法1:硬件断点hr esp值。方法2:在反汇编窗口按[SHIFT+G],输入“[esp]”包括大括号,而且esp是字母,不是esp值)->确定->返回到用户空间后,向下找(20条指令之内)第一个retn指令,它指向的就是入口点了->然后用工具修复输入表就可以了。
---------------------------------------------------------------------------------------------
OD设置:不忽略任何异常。
7C921231 C3 RETN ;载入后停在这里。我们对“GetProcAddress”API下断(BP GetProcAddress)后F9运行。
7C921232 8BFF MOV EDI,EDI
7C921234 90 NOP
7C921235 90 NOP
7C921236 90 NOP
7C921237 90 NOP
7C921238 90 NOP
7C921239 > CC INT3
7C92123A C3 RETN
7C92123B 90 NOP
7C92123C 8BFF MOV EDI,EDI
7C92123E 90 NOP
7C92123F 90 NOP
7C921240 90 NOP
7C921241 90 NOP
7C921242 90 NOP
7C921243 8B4424 04 MOV EAX,DWORD PTR SS:[ESP+4]
7C921247 CC INT3
7C921248 C2 0400 RETN 4
.
.
.
7C80ADA0 > 8BFF MOV EDI,EDI ;运行后停在这里。我们看 CALL GetProcAddress 的返回地址,当前是77C079C2(地址不唯一),不在主程序领空(如果地址开头是004这样的,在主程序领空的话,就不要F9了),我们继续F9一次。
7C80ADA2 55 PUSH EBP
7C80ADA3 8BEC MOV EBP,ESP
7C80ADA5 51 PUSH ECX
7C80ADA6 51 PUSH ECX
7C80ADA7 53 PUSH EBX
7C80ADA8 57 PUSH EDI
7C80ADA9 8B7D 0C MOV EDI,DWORD PTR SS:[EBP+C]
7C80ADAC BB FFFF0000 MOV EBX,0FFFF
7C80ADB1 3BFB CMP EDI,EBX
7C80ADB3 ^ 0F86 D1F2FFFF JBE kernel32.7C80A08A
7C80ADB9 57 PUSH EDI
7C80ADBA 8D45 F8 LEA EAX,DWORD PTR SS:[EBP-8]
7C80ADBD 50 PUSH EAX
7C80ADBE FF15 8812807C CALL DWORD PTR DS:[<&ntdll.RtlInitString>; ntdll.RtlInitString
.
.
.
7C80ADA0 > 8BFF MOV EDI,EDI ;运行后停在这里(老地方正常,因为我们就只在这一个地方下断了)。我们看 CALL GetProcAddress 的返回地址,当前是0041EEF4(地址不唯一),因为是004所以在主程序领空了,我们F2取消断点,然后跟随到返回地址处(快捷键按[Ctrl+G])输入0041EEF4,确定。
7C80ADA2 55 PUSH EBP
7C80ADA3 8BEC MOV EBP,ESP
7C80ADA5 51 PUSH ECX
7C80ADA6 51 PUSH ECX
7C80ADA7 53 PUSH EBX
7C80ADA8 57 PUSH EDI
7C80ADA9 8B7D 0C MOV EDI,DWORD PTR SS:[EBP+C]
7C80ADAC BB FFFF0000 MOV EBX,0FFFF
7C80ADB1 3BFB CMP EDI,EBX
7C80ADB3 ^ 0F86 D1F2FFFF JBE kernel32.7C80A08A
7C80ADB9 57 PUSH EDI
7C80ADBA 8D45 F8 LEA EAX,DWORD PTR SS:[EBP-8]
7C80ADBD 50 PUSH EAX
7C80ADBE FF15 8812807C CALL DWORD PTR DS:[<&ntdll.RtlInitString>; ntdll.RtlInitString
.
.
.
0041EEF4 AB STOS DWORD PTR ES:[EDI] ;跟随到这里后,在这里按F2下断,然后F9运行,运行后就会停在这里。现在终于来到主程序领空了,F2取消断点后F8单步向下走。
0041EEF5 ^ EB E7 JMP SHORT auto.0041EEDE ;到这里不要跳,回头看看上边的代码。因为怕混了,我把从这里分界的上下代码重新贴在下边,标注为“分界线处”。
0041EEF7 C3 RETN ;其实这里就是飞出壳,到程序真正入口的关键跳。看下边单拿出来的代码段有详细注解。
0041EEF8 0070 01 ADD BYTE PTR DS:[EAX+1],DH
0041EEFB 0000 ADD BYTE PTR DS:[EAX],AL
0041EEFD 1000 ADC BYTE PTR DS:[EAX],AL
.
.
.
0041EECF 5E POP ESI
0041EED0 5D POP EBP
0041EED1 59 POP ECX
0041EED2 46 INC ESI
0041EED3 AD LODS DWORD PTR DS:[ESI]
0041EED4 85C0 TEST EAX,EAX
0041EED6 74 1F JE SHORT auto.0041EEF7
0041EED8 51 PUSH ECX
0041EED9 56 PUSH ESI
0041EEDA 97 XCHG EAX,EDI
0041EEDB FFD1 CALL ECX
0041EEDD 93 XCHG EAX,EBX
0041EEDE AC LODS BYTE PTR DS:[ESI]
0041EEDF 84C0 TEST AL,AL
0041EEE1 ^ 75 FB JNZ SHORT auto.0041EEDE
0041EEE3 3806 CMP BYTE PTR DS:[ESI],AL
0041EEE5 ^ 74 EA JE SHORT auto.0041EED1
0041EEE7 8BC6 MOV EAX,ESI
0041EEE9 79 05 JNS SHORT auto.0041EEF0
0041EEEB 46 INC ESI
0041EEEC 33C0 XOR EAX,EAX
0041EEEE 66:AD LODS WORD PTR DS:[ESI]
0041EEF0 50 PUSH EAX
0041EEF1 53 PUSH EBX
0041EEF2 FFD5 CALL EBP
0041EEF4 AB STOS DWORD PTR ES:[EDI]
0041EEF5 ^ EB E7 JMP SHORT auto.0041EEDE ;分界线处。这里会回跳,不要跳。分析完这里回跳所牵扯到的所有跳转范围是从0041EED6到0041EEF5,里边也没有外调的CALL,所以可以在这里的下一行下断然后F9(分析完了,就不会跑飞了)。
0041EEF7 C3 RETN ;这里F2下断,F9运行(程序会运行一会才停下来,因为是在解被加密的输入表),然后停在这里。停下后F8单步一次,返回(跳转)。
0041EEF8 0070 01 ADD BYTE PTR DS:[EAX+1],DH
0041EEFB 0000 ADD BYTE PTR DS:[EAX],AL
0041EEFD 1000 ADC BYTE PTR DS:[EAX],AL
0041EEFF 00F0 ADD AL,DH
0041EF01 0100 ADD DWORD PTR DS:[EAX],EAX
0041EF03 0010 ADD BYTE PTR DS:[EAX],DL
0041EF05 0000 ADD BYTE PTR DS:[EAX],AL
.
.
.
0040338F 55 PUSH EBP ;返回(跳转)到了这里,这里就是程序的真正入口点了,DUMP保存、修复和优化吧。
00403390 8BEC MOV EBP,ESP
00403392 6A FF PUSH -1
00403394 68 68414000 PUSH auto.00404168
00403399 68 10354000 PUSH auto.00403510 ; JMP 到 MSVCRT._except_handler3
0040339E 64:A1 00000000 MOV EAX,DWORD PTR FS:[0]
004033A4 50 PUSH EAX
004033A5 64:8925 0000000>MOV DWORD PTR FS:[0],ESP
004033AC 83EC 68 SUB ESP,68
004033AF 53 PUSH EBX
004033B0 56 PUSH ESI
004033B1 57 PUSH EDI
004033B2 8965 E8 MOV DWORD PTR SS:[EBP-18],ESP
004033B5 33DB XOR EBX,EBX
004033B7 895D FC MOV DWORD PTR SS:[EBP-4],EBX
004033BA 6A 02 PUSH 2
004033BC FF15 DC404000 CALL DWORD PTR DS:[4040DC] ; MSVCRT.__set_app_type
004033C2 59 POP ECX
004033C3 830D 60524100 F>OR DWORD PTR DS:[415260],FFFFFFFF
004033CA 830D 64524100 F>OR DWORD PTR DS:[415264],FFFFFFFF
004033D1 FF15 E0404000 CALL DWORD PTR DS:[4040E0] ; MSVCRT.__p__fmode
004033D7 8B0D 5C524100 MOV ECX,DWORD PTR DS:[41525C]
004033DD 8908 MOV DWORD PTR DS:[EAX],ECX
004033DF FF15 E4404000 CALL DWORD PTR DS:[4040E4] ; MSVCRT.__p__commode
---------------------------------------------------------------------------------------------
总结:
上边是采用方法1手动脱壳的,对GetProcAddress下断后需要F9很多次(次数不固定,和调用的API个数成正比)。如果采用方法2的话,对LoadLibraryA下断后只要F9一次就可以了。都是脱壳的好方法,掌握多些比较好。本文描述的很详细,希望大家喜欢。
---------------------------------------------------------------------------------------------
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课