首页
社区
课程
招聘
[原创]第二阶段第三题解答
发表于: 2007-9-3 23:00 9639

[原创]第二阶段第三题解答

2007-9-3 23:00
9639
先提交程序,随后给出分析。

程序是命令行下的,使用方法如下:

Usage: petiteunp <petited exe file> <unpacked exe file>

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 0
支持
分享
最新回复 (7)
雪    币: 99
活跃值: (2433)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
Petite没什么Anti-Debug的手段,只是使用SEH来指令跳转。首先把Petite本身的程序手动脱壳,然后用IDA反汇编,可以看到有两套压缩引擎,对应参数即-0是一种,-1到-9是一种。

首先来看-0模式:

.data:00418632                 lea     ebx, [eax+1644h]
.data:00418638                 push    eax
.data:00418639                 add     byte ptr [esp], 0Ch
.data:0041863D                 push    eax
.data:0041863E                 add     byte ptr [esp], 46h
.data:00418642                 push    eax
.data:00418643                 add     byte ptr [esp], 65h
.data:00418647                 push    eax
.data:00418648                 add     byte ptr [esp], 0A1h
.data:0041864C                 push    eax
.data:0041864D                 add     byte ptr [esp], 0BFh
.data:00418651
.data:00418651 loc_418651:                             
.data:00418651                                         
.data:00418651                                         
.data:00418651                 mov     ecx, [ebx]
.data:00418653                 add     ebx, 14h
.data:00418656                 mov     edx, [ebx-10h]
.data:00418659                 test    edx, edx
.data:0041865B                 jz      short loc_418651
.data:0041865D                 mov     eax, [esp+18h]
.data:00418661                 lea     esi, [ecx+eax]
.data:00418664                 mov     ebp, [esp+1Ch]
.data:00418668                 mov     ebp, [ebp+8]
.data:0041866B                 mov     ecx, [ebx-4]
.data:0041866E                 mov     edi, ebp
.data:00418670                 rep movsd
.data:00418672                 mov     esi, ebp
.data:00418674                 mov     edi, [ebx-0Ch]
.data:00418677                 add     edi, eax
.data:00418679                 push    ebx
.data:0041867A                 push    edx
.data:0041867B                 push    edi
.data:0041867C                 push    ebp
.data:0041867D                 call    sub_4186AF
.data:00418682                 test    eax, eax
.data:00418684                 jz      loc_418566
.data:0041868A                 pop     eax
.data:0041868B                 pop     eax
.data:0041868C                 pop     eax
.data:0041868D                 pop     ebx
.data:0041868E                 jmp     short loc_418651


[eax+1644h]地址指向了一个压缩数据的表,每个表项具体结构如下:

struct Petite_Section
{
  DWORD compressedRVA;
  DWORD uncompressedSize;
  DWORD orignalRVA;
  DWORD zeroSizeOrExecBit; 
  DWORD compressedSize;//= RealcompressedSize/4
};


zeroSizeOrExecBit的含义是最低位为是否是可执行代码段的标志位。其他位是段中后部连续为0的个数。

sub_4186AF是解压缩函数,参数有9个。前三个分别是压缩数据的地址,解压后的地址,解压后的长度。第四个参数未使用,其他参数都是常量数组。

sub_4186AF代码非常复杂,暂时没有时间研究,写脱壳程序只要把这个代码抽出来放进自己的程序里即可。

需要注意的是sub_4186AF开始的一条指令用时要去掉。

.data:004186AF                 push    ebp
.data:004186B0                 mov     ebp, esp
.data:004186B2                 mov     [edi], al ;去掉
.data:004186B4                 sub     esp, 0BAD8h
.data:004186BA                 lea     ecx, [ebp+var_8078]

当把每一个压缩块都解压之后,作者在这里有一个小trick,使得要尝试写PE的头,PE的头默认是不可写得,因此会产生一个异常,指令就跳转到在事先已经设置好的SEH地址,即开始从下面的指令执行:

.data:00419AE0 loc_419AE0:                             
.data:00419AE0                 call    loc_419B34
.data:00419AE5
.data:00419AE5 loc_419AE5:                             
.data:00419AE5                 pop     edi
.data:00419AE6                 rep stosb
.data:00419AE8                 popa
.data:00419AE9                 popfw
.data:00419AEB                 add     esp, 8
.data:00419AEE                 jmp     $+5
.data:00419AF3 aThisFileHasBee db 'This file has been tampered with and',0Ah
.data:00419AF3                 db 'MAY BE INFECTED BY A VIRUS!',0
.data:00419B34
.data:00419B34 loc_419B34:                             
.data:00419B34                 xor     eax, eax
.data:00419B36                 pop     esi
.data:00419B37                 mov     ebx, fs:[eax]
.data:00419B3A                 mov     ebx, [ebx]
.data:00419B3C                 lea     esp, [ebx-2Ah]
.data:00419B3F                 pop     ebp
.data:00419B40                 lea     ecx, [esi+2CBh]
.data:00419B46                 mov     [ebx+4], ecx
.data:00419B49                 mov     large fs:0, ebx
.data:00419B50                 mov     edi, [esp]
.data:00419B53                 push    dword ptr [edi+8]
.data:00419B56                 call    dword ptr [ebp+7A0h]
.data:00419B5C                 add     edi, 3Dh
.data:00419B62                 push    0Eh
.data:00419B64                 pop     ecx
.data:00419B65                 rep movsb
.data:00419B67                 push    dword ptr [ebx]
.data:00419B69                 push    esi
.data:00419B6A                 push    edi
.data:00419B6B                 lea     esi, [edi+155h]
.data:00419B71                 mov     ecx, esi
.data:00419B73                 sub     ecx, edi
.data:00419B75                 rep stosb
.data:00419B77                 pusha
.data:00419B78                 jmp     eax

最后的jmp eax因为eax为0,就会产生第二次异常,然后就会跳转到下面代码:

.data:00419DB0                 xor     eax, eax
.data:00419DB2                 mov     ebx, fs:[eax]
.data:00419DB5                 mov     ebx, [ebx]
.data:00419DB7                 lea     esp, [ebx-52h]
.data:00419DBA                 popa
.data:00419DBB
.data:00419DBB loc_419DBB:                             
.data:00419DBB                 cmp     dword ptr [esi], 0
.data:00419DBE                 jz      loc_419B7A
.data:00419DC4                 mov     edi, [esi+8]
.data:00419DC7                 add     edi, ebp
.data:00419DC9                 mov     ecx, [esi+0Ch]
.data:00419DCC                 sar     ecx, 1
.data:00419DCE                 push    ecx
.data:00419DCF                 jb      short loc_419DE6
.data:00419DD1
.data:00419DD1 loc_419DD1:                             
.data:00419DD1                 add     edi, [esi+4]
.data:00419DD4                 sar     ecx, 2
.data:00419DD7                 xor     eax, eax
.data:00419DD9                 rep stosd
.data:00419DDB                 pop     ecx
.data:00419DDC                 and     ecx, 3
.data:00419DDF                 rep stosb
.data:00419DE1                 add     esi, 14h
.data:00419DE4                 jmp     short loc_419DBB
.data:00419DE6
.data:00419DE6 loc_419DE6:                             
.data:00419DE6                 mov     ebx, [esi+4]
.data:00419DE9                 sub     ebx, 6
.data:00419DEC                 xor     edx, edx
.data:00419DEE
.data:00419DEE loc_419DEE:                             
.data:00419DEE                                         
.data:00419DEE                 cmp     edx, ebx
.data:00419DF0                 jge     short loc_419DD1
.data:00419DF2                 mov     al, [edx+edi]
.data:00419DF5                 inc     edx
.data:00419DF6                 cmp     al, 0E8h
.data:00419DF8                 jz      short loc_419E0C
.data:00419DFA                 cmp     al, 0E9h
.data:00419DFC                 jz      short loc_419E0C
.data:00419DFE                 cmp     al, 0Fh
.data:00419E00                 jnz     short loc_419DEE
.data:00419E02                 mov     al, [edx+edi]
.data:00419E05                 and     al, 0F0h
.data:00419E07                 cmp     al, 80h
.data:00419E09                 jnz     short loc_419DEE
.data:00419E0B                 inc     edx
.data:00419E0C
.data:00419E0C loc_419E0C:                             
.data:00419E0C                                         
.data:00419E0C                 mov     eax, [edx+edi]
.data:00419E0F
.data:00419E0F loc_419E0F:                             
.data:00419E0F                 cmp     al, 0
.data:00419E11                 jnz     short loc_419DEE
.data:00419E13                 shr     ax, 8
.data:00419E17                 rol     eax, 10h
.data:00419E1A                 xchg    al, ah
.data:00419E1C                 add     edx, 4
.data:00419E1F                 sub     eax, edx
.data:00419E21                 mov     [edx+edi-4], eax
.data:00419E25                 jmp     short loc_419DEE

这段代码来负责压缩表需要清零的数据,然后恢复可执行代码中为了提高压缩绿而处理的跳转指令。这个算法和UPX基本一样。

接下来就会做还原OEP的一部分工作:

data:00419B84 loc_419B84:                             
.data:00419B84                 push    0
.data:00419B86                 push    ebx
.data:00419B87                 xor     ebx, ebx
.data:00419B89                 push    1234
.data:00419B8E                 mov     ecx, [esp]
.data:00419B91
.data:00419B91 loc_419B91:                             
.data:00419B91                 bt      ebx, 0
.data:00419B95                 jb      short loc_419BAD
.data:00419B97                 mov     esi, large fs:1Ch
.data:00419B9E                 btr     esi, 0
.data:00419BA2                 add     esi, large fs:22h
.data:00419BA9                 inc     esi
.data:00419BAA                 xor     bx, si
.data:00419BAD
.data:00419BAD loc_419BAD:                             
.data:00419BAD                 xor     bl, [ecx+edx]
.data:00419BB0                 rol     ebx, 3
.data:00419BB3                 dec     ecx
.data:00419BB4                 jge     short loc_419B91
.data:00419BB6                 lea     ecx, [eax+3Bh]
.data:00419BB9                 xor     [ecx], ebx
.data:00419BBB                 xor     [ecx+4], ebx
.data:00419BBE                 xor     [ecx+8], ebx
.data:00419BC1                 xor     [ecx+0Ch], ebx

Petite对PE文件OEP的做了繁琐的算法保护。首先通过自身代码的校验和来还原跳转到OEP代码,但此时最后那个JMP指令的偏移量仍然是密文,需要后面继续计算。

之后,就到了关键的Import表处理过程:

.data:00419C02                 lea     esi, [ebp+12345678h]
.data:00419C08                 lea     ecx, [ebp+800h]
.data:00419C0E                 mov     ebx, eax
.data:00419C10
.data:00419C10 loc_419C10:                             
.data:00419C10                 cmp     dword ptr [esi], 0
.data:00419C13                 jz      loc_419E27
.data:00419C19                 push    ecx
.data:00419C1A                 push    ecx
.data:00419C1B                 call    dword ptr [ebp+7A4h]
.data:00419C21                 test    eax, eax
.data:00419C23                 jnz     short loc_419C36
.data:00419C25                 sub     esp, 4
.data:00419C28                 call    dword ptr [ebp+790h]
.data:00419C2E                 test    eax, eax
.data:00419C30                 jz      loc_419D15
.data:00419C36
.data:00419C36 loc_419C36:                            
.data:00419C36                 mov     edi, eax
.data:00419C38                 add     eax, [eax+3Ch]
.data:00419C3B                 mov     eax, [eax+78h]
.data:00419C3E                 push    dword ptr [eax+edi+18h]
.data:00419C42                 mov     ecx, [eax+edi+24h]
.data:00419C46                 add     ecx, edi
.data:00419C48                 push    ecx
.data:00419C49                 mov     ecx, [eax+edi+20h]
.data:00419C4D                 add     ecx, edi
.data:00419C4F                 push    ecx
.data:00419C50                 push    dword ptr [eax+edi+10h]
.data:00419C54                 push    dword ptr [eax+edi+14h]
.data:00419C58                 mov     eax, [eax+edi+1Ch]
.data:00419C5C                 add     eax, edi
.data:00419C5E                 push    eax
.data:00419C5F                 push    esi
.data:00419C60                 mov     esi, [esi]
.data:00419C62                 add     esi, ebp
.data:00419C64
.data:00419C64 loc_419C64:                             
.data:00419C64                                         
.data:00419C64                 mov     eax, [esi]
.data:00419C66                 test    eax, eax
.data:00419C68                 jz      loc_419CEF
.data:00419C6E                 jns     short loc_419C9F
.data:00419C70                 bt      eax, 30
.data:00419C74                 jb      short loc_419C9F
.data:00419C76                 movzx   eax, ax
.data:00419C79                 sub     eax, [esp+0Ch]
.data:00419C7D                 jb      loc_419D2E
.data:00419C83                 cmp     eax, [esp+8]
.data:00419C87                 jnb     loc_419D2E
.data:00419C8D                 shl     eax, 2
.data:00419C90                 add     eax, [esp+4]
.data:00419C94                 mov     eax, [eax]
.data:00419C96                 add     eax, edi
.data:00419C98                 mov     [esi], eax
.data:00419C9A                 add     esi, 4
.data:00419C9D                 jmp     short loc_419C64
.data:00419C9F
.data:00419C9F loc_419C9F:                            
.data:00419C9F                                        
.data:00419C9F                 add     eax, esi
.data:00419CA1                 push    eax
.data:00419CA2                 push    eax
.data:00419CA3                 push    edi
.data:00419CA4                 call    dword ptr [ebp+794h]
.data:00419CAA                 test    eax, eax
.data:00419CAC                 jz      short loc_419D2D
.data:00419CAE
.data:00419CAE loc_419CAE:                             
.data:00419CAE                 dec     dword ptr [esp+28h]
.data:00419CB2                 jge     short loc_419CD3
.data:00419CB4                 mov     edx, [esp+24h]
.data:00419CB8                 mov     byte ptr [edx], 0E9h
.data:00419CBB                 sub     eax, edx
.data:00419CBD                 sub     eax, 5
.data:00419CC0                 mov     [edx+1], eax
.data:00419CC3                 mov     eax, edx
.data:00419CC5                 add     edx, 5
.data:00419CC8                 mov     [esp+24h], edx
.data:00419CCC                 and     edx, 7
.data:00419CCF                 mov     [esp+28h], edx
.data:00419CD3
.data:00419CD3 loc_419CD3:                             
.data:00419CD3                 mov     [esi], eax
.data:00419CD5                 xchg    edi, [esp]
.data:00419CD8                 or      ecx, 0FFFFFFFFh
.data:00419CDB                 xor     eax, eax
.data:00419CDD                 repne scasb
.data:00419CDF                 std
.data:00419CE0                 not     ecx
.data:00419CE2                 dec     edi
.data:00419CE3                 rep stosb
.data:00419CE5                 pop     edi
.data:00419CE6                 cld
.data:00419CE7                 add     esi, 4
.data:00419CEA                 jmp     loc_419C64
.data:00419CEF
.data:00419CEF loc_419CEF:                             
.data:00419CEF                 pop     esi
.data:00419CF0                 add     esp, 18h
.data:00419CF3                 mov     edx, [esi]
.data:00419CF5                 add     edx, ebp
.data:00419CF7                 lea     eax, [ebx+47h]
.data:00419CFA                 mov     ecx, [esp+4]
.data:00419CFE
.data:00419CFE loc_419CFE:                             
.data:00419CFE                 cmp     dword ptr [edx], 0
.data:00419D01                 jz      short loc_419D15
.data:00419D03                 cmp     ebx, [edx]
.data:00419D05                 sbb     dword ptr [eax], 0
.data:00419D08                 cmp     [edx], ecx
.data:00419D0A                 sbb     dword ptr [eax], 0
.data:00419D0D                 add     edx, 4
.data:00419D10                 ror     dword ptr [eax], 3
.data:00419D13                 jmp     short loc_419CFE
.data:00419D15
.data:00419D15 loc_419D15:                             
.data:00419D15                                         
.data:00419D15                 mov     dword ptr [esi], 0
.data:00419D1B                 pop     edi
.data:00419D1C                 or      ecx, 0FFFFFFFFh
.data:00419D1F                 xor     eax, eax
.data:00419D21                 repne scasb
.data:00419D23                 mov     ecx, edi
.data:00419D25                 add     esi, 4
.data:00419D28                 jmp     loc_419C10


Petite清除了原来程序的IID表,只使用了对应IAT的一个表,压缩后的Import表的DLL名字和这个表依次对应。如果IAT是序号的话,loader自己从模块的地址空间获取地址。如果是名字指针的话,还原时需要加上当前的RVA再减2。如果以-m1参数压缩,loader还要把某些IAT地址抽走,至于抽走哪些地址,作者使用了一个简单而巧妙的算法来实现。然后根据IAT地址的个数和是否被抽走来解密OEP。

如果PE文件中包含重定向信息,而且并没有strip,loader将执行到如下代码:

.data:00419E27                 lea     ecx, [ebp+12345678h]
.data:00419E2D                 mov     edi, ecx
.data:00419E2F                 mov     edx, ebp
.data:00419E31
.data:00419E31 loc_419E31:                             
.data:00419E31                                         
.data:00419E31                 mov     eax, [ecx]
.data:00419E33                 test    eax, eax
.data:00419E35                 jz      short loc_419E51
.data:00419E37                 cmp     al, 0FFh
.data:00419E39                 jnz     short loc_419E45
.data:00419E3B                 shr     eax, 8
.data:00419E3E                 add     edx, eax
.data:00419E40                 add     ecx, 4
.data:00419E43                 jmp     short loc_419E31
.data:00419E45
.data:00419E45 loc_419E45:                             
.data:00419E45                 inc     ecx
.data:00419E46                 and     eax, 0FFh
.data:00419E4B                 add     edx, eax
.data:00419E4D                 add     [edx], ebp
.data:00419E4F                 jmp     short loc_419E31

这个重定向表的转换也和UPX类似。

最后loader将执行到OEP,壳的执行到此结束。

-1到-9模式:

除了压缩算法不一样之外,其他都基本一样。这个压缩算法类似于UPX的算法,作者把算法做了一些变化。但是作者实现的压缩算法确实很烂,-9模式好像进入死循环了,从来就没成功过。

还原:

Petite对资源没有进行太大动作,解压缩后无需再进行重建。

对于Import表,就是把IID表清除了,需要恢复这个表,IAT也做了简单的变换。再就是抽取了DLL的名字,只要把这个数据放到它添加的Section中即可。

对于重定向表,只要得到重定向的地址,即可恢复重定向表。

对于Export表,可以原地不动,因为如果Export表被抽走,

Petite对于OEP的保护最复杂,需要耐心的写逆算法。

其他的就是做一些Section大小的优化,因为本次比赛没要求,就不去实现了。
2007-9-4 00:37
0
雪    币: 47147
活跃值: (20450)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
3
有要求的,看一下计分公式,如果脱壳后体积大,要减些分。
不过,再提交时间因素影响也大,得权衡一下。
2007-9-4 10:02
0
雪    币: 99
活跃值: (2433)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
是啊,早上才看到这个要求.
没仔细看题目的要求,吃亏只能认倒霉了.

再提交一个完美优化section大小的程序.能不能看哪个分高,取哪个啊?
上传的附件:
2007-9-4 10:58
0
雪    币: 47147
活跃值: (20450)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
5
还有就是要提供源码。
2007-9-4 11:01
0
雪    币: 99
活跃值: (2433)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
sorry!
2007-9-4 11:30
0
雪    币: 99
活跃值: (2433)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
请不要公开我的源码
2007-9-4 11:32
0
雪    币: 5340
活跃值: (598)
能力值: (RANK:170 )
在线值:
发帖
回帖
粉丝
8
样本序号 执行结果 原始大小 解压大小
1 pass 20480 10240
2 pass 20480 10240
3 failed
4 failed
5 failed
6 failed
7 failed
8 failed

做题时间:
2007-9-2 12:00 - 2007-09-04, 10:58
2818

得分:
24.255074346171127103721405041381
2007-9-9 23:08
0
游客
登录 | 注册 方可回帖
返回
//