目标程序:des.exe
程序名称:DES计算器
加壳程序:Obsidium.V1.3.4.2
加壳设置:默认(偷oep,iat加密)


用Ollyice载入程序运行,hideod,plantom插件隐藏od,hideod设置全部打勾

运行以后alt+m查看内存,发现msvcrt.dll和MFC42.dll,可以断定是一个VC程序

VC程序oep附近一般会调用2个函数GetVersion或者msvcrt.__set_app_type

在od中按ctrl+G输入GetVersion,定位以后在函数末尾retn处f2下断
按ctrl+G输入msvcrt.__set_app_type,定位以后在函数末尾retn处f2下断

ctrl+f2重载程序,shift+f9运行,每次断下来以后F8一下看是否回到程序领空

本程序在msvcrt.__set_app_type函数的retn处77C0538A断下

77C0537C >  8BFF            mov     edi, edi
77C0537E    55              push    ebp
77C0537F    8BEC            mov     ebp, esp
77C05381    8B45 08         mov     eax, dword ptr [ebp+8]
77C05384    A3 BC17C377     mov     dword ptr [77C317BC], eax
77C05389    5D              pop     ebp
77C0538A    C3              retn                                ;在这里断下来

F8返回以后回到程序领空
0040DADF    59              pop     ecx
0040DAE0    830D 38F24000 F>or      dword ptr [40F238], FFFFFFFF
0040DAE7    830D 3CF24000 F>or      dword ptr [40F23C], FFFFFFFF
0040DAEE    FF15 C0E14000   call    dword ptr [40E1C0]
0040DAF4    8B0D 2CF24000   mov     ecx, dword ptr [40F22C]
0040DAFA    8908            mov     dword ptr [eax], ecx
0040DAFC    FF15 BCE14000   call    dword ptr [40E1BC]

上下翻看一下,发现是一个典型的VC程序,只是oep部分被偷了一段代码

0040DAA6  - FF25 94E14000   jmp     dword ptr [40E194]
0040DAAC    8E82 976A18E9   mov     es, word ptr [edx+E9186A97]
0040DAB2    7B FF           jpo     short 0040DAB3
0040DAB4    CF              iretd
0040DAB5    E4 9F           in      al, 9F
0040DAB7    7A B0           jpe     short 0040DA69
0040DAB9    27              daa
0040DABA    73 64           jnb     short 0040DB20
0040DABC    A1 00000000     mov     eax, dword ptr [0]
///////////////上面部分被偷了,下面正常
0040DAC1    50              push    eax
0040DAC2    64:8925 0000000>mov     dword ptr fs:[0], esp
0040DAC9    83EC 68         sub     esp, 68
0040DACC    53              push    ebx
0040DACD    56              push    esi
0040DACE    57              push    edi
0040DACF    8965 E8         mov     dword ptr [ebp-18], esp
0040DAD2    33DB            xor     ebx, ebx
0040DAD4    895D FC         mov     dword ptr [ebp-4], ebx
0040DAD7    6A 02           push    2
0040DAD9    FF15 C4E14000   call    dword ptr [40E1C4]
0040DADF    59              pop     ecx
0040DAE0    830D 38F24000 F>or      dword ptr [40F238], FFFFFFFF
0040DAE7    830D 3CF24000 F>or      dword ptr [40F23C], FFFFFFFF
0040DAEE    FF15 C0E14000   call    dword ptr [40E1C0]
0040DAF4    8B0D 2CF24000   mov     ecx, dword ptr [40F22C]
0040DAFA    8908            mov     dword ptr [eax], ecx
0040DAFC    FF15 BCE14000   call    dword ptr [40E1BC]
0040DB02    8B0D 28F24000   mov     ecx, dword ptr [40F228]
0040DB08    8908            mov     dword ptr [eax], ecx
0040DB0A    A1 B8E14000     mov     eax, dword ptr [40E1B8]
0040DB0F    8B00            mov     eax, dword ptr [eax]
0040DB11    A3 34F24000     mov     dword ptr [40F234], eax
0040DB16    E8 16010000     call    0040DC31
0040DB1B    391D 70F04000   cmp     dword ptr [40F070], ebx

找一个vc6程序,比较一下,修复被偷掉的那部分,修复以后如下
0040DAAC    55              push    ebp
0040DAAD    8BEC            mov     ebp, esp
0040DAAF    6A FF           push    -1
0040DAB1    68 78E54000     push    0040E578
0040DAB6    68 32DC4000     push    0040DC32
0040DABB    64:A1 00000000  mov     eax, dword ptr fs:[0]
0040DAC1    50              push    eax
0040DAC2    64:8925 0000000>mov     dword ptr fs:[0], esp
0040DAC9    83EC 68         sub     esp, 68
好了,OEP=40DAAC

ok,现在来看看输入表,刚才这一个语句调用了msvcrt.__set_app_type函数
0040DAD9    FF15 C4E14000   call    dword ptr [40E1C4]
我们在数据窗口中看一下40E1C4
0040E1C4  003F0596
0040E1C8  003F05A3
0040E1CC  003F05B0
0040E1D0  003F05BD
0040E1D4  003F05CA
上下翻动一下找到开始是004E000
结束是004E210,里面只有少数IAT正常,其他都加密了
0040E1A0  003F0521
0040E1A4  003F052E
0040E1A8  77C317AC  offset msvcrt._acmdln     //没有加密的iat
0040E1AC  003F0548                            //加密的iat
0040E1B0  003F0555
0040E1B4  003F0562
0040E1B8  77C323D8  offset msvcrt._adjust_fdiv
0040E1BC  003F057C



现在我们要修复IAT表,用hideod插件申请一块内存,分配得到的地址是00C00000,长度1000
Ctrl+G,输入00C00000到达新分配的空间
patch以下代码来修复iat

00C00000    60              pushad                                        //设置这里为EIP
00C00001    9C              pushfd
00C00002    BE 00E04000     mov     esi, 40E000                                //IAT START
00C00007    BF 10E24000     mov     edi, 40E210                                //IAT END
00C0000C    8B06            mov     eax, dword ptr [esi]
00C0000E    3D 00004000     cmp     eax, 400000                         ; ASCII "MZP"
00C00013    77 0F           ja      short 00C00024
00C00015    83F8 00         cmp     eax, 0
00C00018    74 0A           je      short 00C00024
00C0001A    FFE0            jmp     eax
00C0001C    A1 FCDF4000     mov     eax, dword ptr [40DFFC]                //找一个临时地址存放
00C00021    90              nop
00C00022    8906            mov     dword ptr [esi], eax
00C00024    83C6 04         add     esi, 4
00C00027    3BF7            cmp     esi, edi
00C00029    74 02           je      short 00C0002D
00C0002B  ^ EB DF           jmp     short 00C0000C
00C0002D    9D              popfd
00C0002E    61              popad
00C0002F    C705 FCDF4000 0>mov     dword ptr [40DFFC], 0                //将临时地址复原清0
00C00039  - EB FE           jmp     short 00C00039
00C0003B    90              nop


60 9C BE 00 E0 40 00 BF 10 E2 40 00 8B 06 3D 00 00 40 00 77 0F 83 F8 00 74 0A FF E0 A1 FC DF 40
00 90 89 06 83 C6 04 3B F7 74 02 EB DF 9D 61 C7 05 FC DF 40 00 00 00 00 00 EB FE 90
设置00C00000    60              pushad为EIP
F8单步走
从这里进去就是壳解密iat的部分了
00C0001A    FFE0            jmp     eax
一路F8以后找到解密出IAT的地方,在那里patch代码用来和刚才那段代码互动解密
以下的地址每次运行都不同,贴出来是方便比较确认,我找到了一个特征码可以快速定位到需要修改的2处地方

iat特征码FF 37 FF 53 54 EB 03
00934440    FF53 54         call    dword ptr [ebx+54]
00934443   /EB 03           jmp     short 00934448

现在搜索特征码FF 37 FF 53 54 EB 03
找到以后是下面这个样子(有2处)
009343CC    6A 01           push    1
009343CE    50              push    eax
009343CF    6A 00           push    0
009343D1    FF76 04         push    dword ptr [esi+4]
009343D4    FF37            push    dword ptr [edi]
009343D6    FF53 54         call    dword ptr [ebx+54]

我们从call语句后面一行开始patch,修改成如下样子

009343D9    A3 FCDF4000     mov     dword ptr [40DFFC], eax          ; 40DFCC是我们用来临时存放iat的地方,原来的值是0
009343DE    9D              popfd
009343DF    61              popad
009343E0  - E9 37BC2C00     jmp     00C0001C                             ; 返回我们写的代码处理解密出来的iat

同样修改另外一处(call后面开始patch)
下面是我修改前后2处贴出来的对比代码

第一处:
009343CC    6A 01           push    1
009343CE    50              push    eax
009343CF    6A 00           push    0
009343D1    FF76 04         push    dword ptr [esi+4]
009343D4    FF37            push    dword ptr [edi]
009343D6    FF53 54         call    dword ptr [ebx+54]
--------
009343D9    EB 03           jmp     short 009343DE                   ; 原代码
009343DB    95              xchg    eax, ebp
009343DC    4E              dec     esi
009343DD    8885 C0EB0316   mov     byte ptr [ebp+1603EBC0], al
009343E3    D4 FB           aam     0FB
009343E5    75 72           jnz     short 00934459
------------------------------------------------------------------------------
009343D9    A3 FCDF4000     mov     dword ptr [40DFFC], eax          ; 修改代码
009343DE    9D              popfd
009343DF    61              popad
009343E0  - E9 37BC2C00     jmp     00C0001C

二进制代码:6A 01 50 6A 00 FF 76 04 FF 37 FF 53 54 A3 FC DF 40 00 9D 61 E9 37 BC 2C 00

第二处:
00934435    6A 01           push    1
00934437    6A 00           push    0
00934439    FF76 04         push    dword ptr [esi+4]
0093443C    6A 00           push    0
0093443E    FF37            push    dword ptr [edi]
00934440    FF53 54         call    dword ptr [ebx+54]
--------
00934443   /EB 03           jmp     short 00934448                   ; 原代码
00934445   |37              aaa
00934446   |B8 1285C0EB     mov     eax, EBC08512
0093444B    01A6 0F842D01   add     dword ptr [esi+12D840F], esp
-------------------------------------------------------------------------------
00934443    A3 FCDF4000     mov     dword ptr [40DFFC], eax          ; 修改代码
00934448    9D              popfd
00934449    61              popad
0093444A  - E9 CDBB2C00     jmp     00C0001C

二进制代码:6A 01 6A 00 FF 76 04 6A 00 FF 37 FF 53 54 A3 FC DF 40 00 9D 61 E9 CD BB 2C 00

现在代码patch好了,不着急f9运行 我们Ctrl+G输入00C00000回到新分配空间,最开始patched的那段代码
,在这里F2下断
00C00039  - EB FE           jmp     short 00C00039
然后shift+F9运行,断下来以后iat已经修复完毕了
现在alt+m,在401000区段上设置访问权限为所有,然后打开loadpe,dump程序,保存为dumped.exe
打开ImportREC,选择des.exe输入前面得到的oep:40daac-40000=daac,rva=40e000-400000=e000,长度210
点get import,指针全部有效,fix dump得到dumped_.exe
运行正常!到此脱壳完毕
此时程序140kb,我们来减减肥
loadpe打开dumped_.exe 清除长度为d000那个区段,然后重建,运行正常,大小61.6kb

一个小插曲:dump程序以后卡巴斯基报警,ImportREC fix dump以后就不报警了,呵呵

第一次写脱文,如有不妥之处请见谅,希望能加个精华啦:-)