gino 发表于 2007-12-19 18:02:23

Forgot的unpackme 1.7的简单脱壳

【软件名称】:forgot的unpackme 1.7
【下载地址】:见附件。
【脱壳声明】:初学Crack,只是感兴趣,没有其它目的。失误之处敬请诸位大侠赐教!
【操作系统】:winxp
【脱壳工具】:OD等传统工具

———————————————————————————————————————————
 
【脱壳过程】:

forgot的unpackme 1.7 和pack v0.1.6的变化不大,只是加了IAT简单加密。另外和1.6一样加了入口代码修改,但修改字节并不多。
如果看过我脱015版和016版的文章,那么可以省略相关的章节。


第一步,找d-process处:

用OD载入程序,忽略所有异常,bp WriteProcessMemory,F9运行程序,断下:

77E41A94 >55            PUSH EBP////断下。
77E41A95    8BEC            MOV EBP,ESP
77E41A97    51            PUSH ECX
77E41A98    51            PUSH ECX
77E41A99    8B45 0C      MOV EAX,DWORD PTR SS:
77E41A9C    53            PUSH EBX

观察堆栈数据:

0032797C0032B349/CALL 到 WriteProcessMemory 来自 0032B344
0032798000000034|hProcess = 00000034
003279840032CA56|Address = 32CA56////重要!记下备用。
003279880032C3C5|Buffer = 0032C3C5
0032798C0000029A|BytesToWrite = 29A (666.)////重要!记下备用。
0032799000000000\pBytesWritten = NULL

好,F9直接运行程序,等出现界面时,运行LordPE选中映像文件小的那个进程,然后部分DUMP,把从32CA56处开始大小为29A的数据DUMP下来,命名为32CA56.bin。

第二步,变双进程为单进程:

重新载入程序,bp CreateProcessA,运行程序,断下:

77E41BBC >55            PUSH EBP////断在这儿。
77E41BBD    8BEC            MOV EBP,ESP
77E41BBF    6A 00          PUSH 0
77E41BC1    FF75 2C      PUSH DWORD PTR SS:
77E41BC4    FF75 28      PUSH DWORD PTR SS:
77E41BC7    FF75 24      PUSH DWORD PTR SS:

观察堆栈数据:

003279680032A22C/CALL 到 CreateProcessA 来自 0032A227
0032796C00328F99|ModuleFileName = "C:\Documents and Settings\csjwaman\桌面\1.7\1.7.exe"
003279700032A21D|CommandLine = "X"////调试标志。
0032797400000000|pProcessSecurity = NULL
0032797800000000|pThreadSecurity = NULL
0032797C00000000|InheritHandles = FALSE
0032798000000003|CreationFlags = DEBUG_PROCESS|DEBUG_ONLY_THIS_PROCESS
0032798400000000|pEnvironment = NULL
0032798800000000|CurrentDir = NULL
0032798C00327CF4|pStartupInfo = 00327CF4
0032799000327CE4\pProcessInfo = 00327CE4

重新载入程序,bp GetCommandLineA,运行程序,断下:

77E5E358 >A1 1476EB77    MOV EAX,DWORD PTR DS:////断在这里。取消断点。
77E5E35D    C3            RETN////返回。

返回到:

0032837C    68 9F6F56B6    PUSH B6566F9F
00328381    50            PUSH EAX
00328382    E8 5D000000    CALL 003283E4
00328387    EB FF          JMP SHORT 00328388
00328389    71 78          JNO SHORT 00328403
0032838B    C2 5000      RETN 50
0032838E^ EB D3          JMP SHORT 00328363
00328390    5B            POP EBX
00328391    F3:            PREFIX REP:      ; 多余的前缀

搜索二进制字符“803e58”,找到:

00328617^\71 EB          JNO SHORT 00328604
00328619^ EB FA          JMP SHORT 00328615
0032861B^ EB 80          JMP SHORT 0032859D/////找到这里。这里有个花指令。
0032861D    3E:58          POP EAX      
0032861F    0F84 8A410000JE 0032C7AF
00328625    68 9F6F56B6    PUSH B6566F9F
0032862A    50            PUSH EAX
0032862B    E8 5D000000    CALL 0032868D
00328630    EB FF          JMP SHORT 00328631


NOP掉花指令后:

0032861B    90            NOP
0032861C    803E 58      CMP BYTE PTR DS:,58////58为调试标志。用于判断是否为子进程。
0032861F    0F84 8A410000JE 0032C7AF////此处改为JMP!可以变为单进程。
00328625    68 9F6F56B6    PUSH B6566F9F
0032862A    50            PUSH EAX
0032862B    E8 5D000000    CALL 0032868D


00A19217    90            NOP
00A19218    803E 58      CMP BYTE PTR DS:,58
00A1921B    0F84 CA3F0000JE 00A1D1EB
00A19221    68 9F6F56B6    PUSH B6566F9F
00A19226    50            PUSH EAX
00A19227    E8 5D000000    CALL 00A19289


第三步,修补程序:

修改上面这个跳转后,用十六进制工具把32CA56.bin的数据复盖掉OD的DUMP区从0032CA56处开始的29A个字节数据。

第四步,查找入口:

做完上述工作后,在OD的CPU窗口,Ctrl+G,输入0032CA56,点确定后来到:

0032CA4D^\71 EB          JNO SHORT 0032CA3A
0032CA4F^ EB FA          JMP SHORT 0032CA4B
0032CA51^ EB F0          JMP SHORT 0032CA43////NOP掉。
0032CA53    0FC7C8          CMPXCHG8B EAX////NOP掉。
0032CA56    FFC3            INC EBX/////来到这里。
0032CA58    FFC8            DEC EAX
0032CA5A    F7D8            NEG EAX
0032CA5C    F7C1 2DF16825TEST ECX,2568F12D
0032CA62    8BD9            MOV EBX,ECX
0032CA64    01CB            ADD EBX,ECX
0032CA66    85CB            TEST EBX,ECX
0032CA68    8BDA            MOV EBX,EDX
0032CA6A    C1CB F3      ROR EBX,0F3                              ; 移动常数超出 1..31 的范围
0032CA6D    C7C3 BE948305MOV EBX,58394BE
0032CA73    87D8            XCHG EAX,EBX
0032CA75    0FA5D3          SHLD EBX,EDX,CL
0032CA78    87C0            XCHG EAX,EAX

搜索二进制字符“6150C3”,找到:

0032FDFE^\71 EB          JNO SHORT 0032FDEB
0032FE00^ EB FA          JMP SHORT 0032FDFC
0032FE02    EB 50          JMP SHORT 0032FE54
0032FE04    8D78 02      LEA EDI,DWORD PTR DS:
0032FE07    EB 02          JMP SHORT 0032FE0B////在这里F2下断。
0032FE09    61            POPAD////找到这里。
0032FE0A    50            PUSH EAX
0032FE0B    C3            RETN////返回入口!

在0032FE07处断下后,EAX=403A3F,这就是入口地址。

00403A3F    FFD7            CALL NEAR EDI////返回到这里。入口代码被修改了。
00403A41    58            POP EAX
00403A42    90            NOP
00403A43    90            NOP
00403A44    E8 63910000    CALL 1_7.0040CBAC
00403A49    85C0            TEST EAX,EAX
00403A4B    74 26          JE SHORT 1_7.00403A73
00403A4D    68 00000200    PUSH 20000
00403A52    6A 40          PUSH 40
00403A54    E8 2F910000    CALL 1_7.0040CB88
00403A59    A3 C0E14000    MOV DWORD PTR DS:,EAX
00403A5E    68 BCE04000    PUSH 1_7.0040E0BC
00403A63    E8 10000000    CALL 1_7.00403A78

到入口后观察堆栈区:

00327D680040E0341_7.0040E034////这就是被偷的代码。
00327D6C0042F73C返回到 1_7.0042F73C

补回代码后:

00403A3F    68 34E04000    PUSH 1_7.0040E034////这才象入口嘛:)
00403A44    E8 63910000    CALL 1_7.0040CBAC
00403A49    85C0            TEST EAX,EAX
00403A4B    74 26          JE SHORT 1_7.00403A73
00403A4D    68 00000200    PUSH 20000
00403A52    6A 40          PUSH 40
00403A54    E8 2F910000    CALL 1_7.0040CB88
00403A59    A3 C0E14000    MOV DWORD PTR DS:,EAX
00403A5E    68 BCE04000    PUSH 1_7.0040E0BC
00403A63    E8 10000000    CALL 1_7.00403A78
00403A68    FF35 C0E14000PUSH DWORD PTR DS:
00403A6E    E8 1B910000    CALL 1_7.0040CB8E

第五步,查找IAT加密处

到入口后F7跟踪:

00403A3F    68 34E04000    PUSH 1_7.0040E034////F7
00403A44    E8 63910000    CALL 1_7.0040CBAC////F7进入!
00403A49    85C0            TEST EAX,EAX
00403A4B    74 26          JE SHORT 1_7.00403A73

进入后:

0040CB6A    68 F0A6E577    PUSH kernel32.CloseHandle
0040CB6F    C3            RETN
0040CB70    68 76B4E577    PUSH kernel32.CreateFileA
0040CB75    C3            RETN
0040CB76    68 FD98E577    PUSH kernel32.ExitProcess
0040CB7B    C3            RETN
0040CB7C    68 6416E677    PUSH kernel32.GetFileSize
0040CB81    C3            RETN
0040CB82    68 9BA2E577    PUSH kernel32.GetTickCount
0040CB87    C3            RETN
0040CB88    68 9E56E577    PUSH kernel32.GlobalAlloc
0040CB8D    C3            RETN
0040CB8E    68 D957E577    PUSH kernel32.GlobalFree
0040CB93    C3            RETN
0040CB94    68 4EABE577    PUSH kernel32.ReadFile                  ; ASCII "j h"
0040CB99    C3            RETN
0040CB9A    68 2EF0E577    PUSH kernel32.SetFilePointer
0040CB9F    C3            RETN
0040CBA0    68 3AF1E577    PUSH kernel32.WriteFile
0040CBA5    C3            RETN
0040CBA6    68 0AB0D377    PUSH user32.MessageBoxA
0040CBAB    C3            RETN
0040CBAC    68 90233276    PUSH comdlg32.GetOpenFileNameA////到这里。
0040CBB1    C3            RETN

跳转表都被改成 PUSH XXXXXXXX 然后 RETN 的形式了!看开始处是40CB6A。

好,重新载入程序,按上述方法到第四步后,在40CB6A处下内存访问断点,然后F9运行程序,断下几次后会来到:

0032F976    03BD 66CB4000ADD EDI,DWORD PTR SS:
0032F97C    81C7 00100000ADD EDI,1000
0032F982    66:8139 FF25    CMP WORD PTR DS:,25FF////会断在这里。这里开始处理IAT跳转表。
0032F987    74 02          JE SHORT 0032F98B////修改为JMP 32F9C8
0032F989    EB 05          JMP SHORT 0032F990
0032F98B    3941 02      CMP DWORD PTR DS:,EAX
0032F98E    72 07          JB SHORT 0032F997
0032F990    41            INC ECX
0032F991    3BCF            CMP ECX,EDI
0032F993^ 72 ED          JB SHORT 0032F982
0032F995    EB 27          JMP SHORT 0032F9BE
0032F997    8B59 02      MOV EBX,DWORD PTR DS:
0032F99A    8B1B            MOV EBX,DWORD PTR DS:
0032F99C    C601 68      MOV BYTE PTR DS:,68////IAT跳转改为PUSH xxxxxxxx,然后再RETN的形式。
0032F99F    8959 01      MOV DWORD PTR DS:,EBX
0032F9A2    C641 05 C3      MOV BYTE PTR DS:,0C3////RETN
0032F9A6    83C1 06      ADD ECX,6
0032F9A9    66:8139 FF25    CMP WORD PTR DS:,25FF
0032F9AE    75 04          JNZ SHORT 0032F9B4
0032F9B0    3BCF            CMP ECX,EDI
0032F9B2^ 72 CE          JB SHORT 0032F982
0032F9B4    83C1 02      ADD ECX,2
0032F9B7    66:8139 FF25    CMP WORD PTR DS:,25FF
0032F9BC^ 74 D9          JE SHORT 0032F997
0032F9BE    83C1 24      ADD ECX,24
0032F9C1    66:8139 FF25    CMP WORD PTR DS:,25FF
0032F9C6^ 74 CF          JE SHORT 0032F997
0032F9C8    61            POPAD

把0032F987处直接修改为JMP 32F9C8 就可以得到完整的IAT跳转表了。

到入口后就可以用PETOOLS来DUMP了(因为用LORDPE不行!),再用ImportREC v142+修复IAT, OK完工!

glts 发表于 2007-12-19 18:36:25

把脱壳对像也发上来让大家练习下.

tianxj 发表于 2007-12-19 19:20:32

飞哥,这是转贴,怎么也加威望和PYB??

darling995 发表于 2007-12-19 19:59:16

原帖由 tianxj 于 2007-12-19 19:20 发表 https://www.chinapyg.com/images/common/back.gif
飞哥,这是转贴,怎么也加威望和PYB??
   转帖,请注明来自哪。要不建议把脱壳对象传上来。

[ 本帖最后由 darling995 于 2007-12-19 20:01 编辑 ]

iawen 发表于 2007-12-19 20:14:10

写的确实精彩,谢谢楼主,希望能提供试炼程序!
页: [1]
查看完整版本: Forgot的unpackme 1.7的简单脱壳