首页
社区
课程
招聘
[原创]压缩壳之 Pohernah壳分析
发表于: 2008-11-17 16:36 8272

[原创]压缩壳之 Pohernah壳分析

2008-11-17 16:36
8272

Pohernah壳 加密算法分析

关于Pohernah壳的脱壳已经完成了,见链接http://bbs.pediy.com/showthread.php?t=75219,
由于很多事情,脱壳机一直拖着没有写完,现在对于这个的加壳流程和加密算法一探究竟。

首先,是入口
00469000 >  60              pushad
00469001    E8 00000000     call    00469006 ;F7步入,在壳中常见
00469006    5D              pop     ebp
00469007    81ED F1264000   sub     ebp, 004026F1
0046900D    8BBD 18284000   mov     edi, dword ptr ss:[ebp+402818]
00469013    8B8D 20284000   mov     ecx, dword ptr ss:[ebp+402820]

0046901E    01E8            add     eax, ebp
00469020    8030 05         xor     byte ptr ds:[eax], 5
00469023    83F9 00         cmp     ecx, 0   
; 这层有一个循环是用来判断是否读完区段的,循环是以区块数为循环层数,每次循环减一,也就是说这个壳是对每一个区块进行加密的
00469026    74 71           je      short 00469099   ; if ecx ==0 jump

00469031    8B57 0C         mov     edx, dword ptr ds:[edi+C]        ;
00469034    0395 1C284000   add     edx, dword ptr ss:[ebp+<dword_40>
; .text的地址,也就是第一个区块的地址
0046903A    31C0            xor     eax, eax                         ; eax = 0
0046903C    51              push    ecx
0046903D    31C9            xor     ecx, ecx                         ; ecx = 0
0046903F    66:B9 FA00      mov     cx, 0FA                          ; ecx = FA
00469043    66:83F9 00      cmp     cx, 0                            ; if ecx ! = 0
00469047    74 49           je      short 00469092
00469049    8B57 0C         mov     edx, dword ptr ds:[edi+C]        ; 将基地址赋给edx
0046904C    0395 1C284000   add     edx, dword ptr ss:[ebp+<dword_40>; edx = 401000
00469052    8B85 24284000   mov     eax, dword ptr ss:[ebp+<dword_40>;
00469058    83F8 02         cmp     eax, 2                           ; if eax = = 2
0046905B    75 06           jnz     short 00469063

0046905D    81C2 00020000   add     edx, 200
00469063    51              push    ecx
00469064    8B4F 10         mov     ecx, dword ptr ds:[edi+10]       ; ecx = FA --> ecx = 00049200
00469067    83F8 02         cmp     eax, 2                           ; if ecx == 2
0046906A    75 06           jnz     short 00469072
0046906C    81E9 00020000   sub     ecx, 200
00469072    57              push    edi                              ; .text
00469073    BF C8000000     mov     edi, 0C8                         ; edi = 0c8
00469078    89CE            mov     esi, ecx                      ; esi = ecx =49200
0046907A    E8 27000000     call    004690A6
0046907F    89C1            mov     ecx, eax          ; 49200  .text 的原始大小
00469081    5F              pop     edi                              ; .text
00469082    B8 38284000     mov     eax, <dword_402838>              ;
00469087    01E8            add     eax, ebp        ; eax = 402838 ebp = 66915!!!!!!!!
00469089    E8 24000000     call    004690B2
{
    004690B2    60              pushad
004690B3    83F0 05         xor     eax, 5
004690B6    40              inc     eax
004690B7    90              nop
004690B8    48              dec     eax
004690B9    83F0 05         xor     eax, 5                        ;eax = 46914D 就是加密用的key ,后发现这个每次没有变化?
004690BC    89C6            mov     esi, eax                     ; esi 是 key
004690BE    89D7            mov     edi, edx
004690C0    60              pushad
004690C1    E8 0B000000     call    004690D1                    ;这个就是解密函数了
{
    push    edi
mov     ebx, [edi]      ; y = v[0] edi .text的基地址
mov     ecx, [edi+4]    ; z = v [1]
push    9E3779B9h
pop     edx
inc     edx             ; edx =0x9e3779ba
mov     eax, edx
dec     eax             ; eax = 0x9e3779b9   ----delta
shl     eax, 5          ; sum = delta<<5
mov     edi, 20h        ; while(n -- >0)  edi = 20h  32轮循环解密  n=32
dec     edx             ; edx = 0x9e3779b9
mov     ebp, ebx
shl     ebp, 4          ; y<<4
sub     ecx, ebp        ; v[1] - y
mov     ebp, [esi+8]    ; ebp = k [2]
xor     ebp, ebx        ; k [2] ^ v[0]
sub     ecx, ebp        ; (v [1] - y-(k [2] ^ v[0]) )
mov     ebp, ebx
shr     ebp, 5          ; v [0] >>5
xor     ebp, eax        ; v [0] >> 5 ^ sum
sub     ecx, ebp        ; ((v [1] - y-(k [2] ^ v[0]) )) - ((v[0]>>5) ^ sum)
sub     ecx, [esi+0Ch]  ; ((v [1] - (k [2] ^ v[0]) )) - ((v[0]>>5) ^ sum) - v [3]
mov     ebp, ecx        ; ebp = (((v [1] - y - (k [2] ^ v[0]) )) - ((v[0]>>5) ^ sum) - v [3])
shl     ebp, 4          ; (((v [1] - y - (k [2] ^ v[0]) )) - ((v[0]>>5) ^ sum) - v [3])<<4
sub     ebx, ebp        ; v [0] -((((v [1] - y -(k [2] ^ v[0]) )) - ((v[0]>>5) ^ sum) - v [3])<<4)
mov     ebp, [esi]      ; v[0]
xor     ebp, ecx        ; v [0] ^((v [1] - y) - ((v[0]>>5) ^ sum) - v [3])
sub     ebx, ebp        ; v [0] -((((v [1] -y - (k [2] ^ v[0]) )) - ((v[0]>>5) ^ sum) - v [3])<<4) -v [0] ^((v [1] - y) - ((v[0]>>5) ^ sum) - v [3])
mov     ebp, ecx        ; ebp = (v [1] - y) - ((v[0]>>5) ^ sum) - v [3]
shr     ebp, 5          ; ((v [1] - y) - ((v[0]>>5) ^ sum) - v [3])>>5
xor     ebp, eax        ; (((v [1] - y) - ((v[0]>>5) ^ sum) - v [3])>>5)  ^ sum
sub     ebx, ebp        ;
sub     ebx, [esi+4]    ;
sub     eax, edx        ; sum - = telta
dec     edi             ; n --
jnz     short loc_4690EA

pop     edi
mov     [edi], ebx      ; v[0] = y
mov     [edi+4], ecx    ; v[1]=z
retn                    ; 一轮加密结束
}
004690C6    61              popad
004690C7    83C7 08         add     edi, 8                   ;读取后面8个字节,因为DWORD类型,一次读两个
004690CA    83E9 07         sub     ecx, 7
004690CD  ^ E2 F1           loopd   short 004690C0         ;循环,进行解密
004690CF    61              popad
004690D0    C3              retn
   

}
0046908E    59              pop     ecx
0046908F    49              dec     ecx            
00469090  ^ EB B1           jmp     short 00469043     
00469092    59              pop     ecx
00469093    83C7 28         add     edi, 28                          ; .text + 8
00469096    49              dec     ecx       ; ecx = 5 代表5个区段
00469097  ^ EB 8A           jmp     short 00469023
00469099    8B85 14284000   mov     eax, dword ptr ss:[ebp+<dword_40>
0046909F    894424 1C       mov     dword ptr ss:[esp+1C], eax       ; eax 为OEP
004690A3    61              popad

到这里,壳的整个流程就走了一遍,壳的流程就是

因此我们的脱壳机的思路,就是将文件映射到内存,然后   
for (DWORD i = 0; i < dwSectionNum; i++)
进行循环解密
然后在循环中调用 DeCrypty函数,将数据解密出来,更改OEP 地址,重建文件… …
void DeCrypt(DWORD* v,DWORD* k)
{
    DWORD y=v[0],z=v[1],sum,delta=0x9e3779b9,n=32;
    sum=delta<<5;
    while (n-->0)
    {
        z-=((y<<4)+k[2])^(y+sum)^((y>>5)+k[3]);
        y-=((z<<4)+k[0])^(z+sum)^((z>>5)+k[1]);
        sum-=delta;        
    }
    v[0]=y;
    v[1]=z;
}
脱壳机写完后传到附件


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

上传的附件:
收藏
免费 7
支持
分享
最新回复 (18)
雪    币: 30
活跃值: (31)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
看不懂,谢谢了,做个记号,希望慢点会看得懂.
2008-11-17 17:10
0
雪    币: 846
活跃值: (221)
能力值: (RANK:570 )
在线值:
发帖
回帖
粉丝
3
你知道那是什么算法么?
2008-11-17 18:57
0
雪    币: 2368
活跃值: (81)
能力值: (RANK:300 )
在线值:
发帖
回帖
粉丝
4
期待笨笨熊揭谜底
2008-11-17 22:34
0
雪    币: 846
活跃值: (221)
能力值: (RANK:570 )
在线值:
发帖
回帖
粉丝
5
没谜底~~~他是要找工作的,按照目前来看,很难让人眼前一亮

如果他答不出,那可以说明下列问题之一:

1. 他不知道PEID那个算法识别插件
2. 他对常见标准加密算法不熟
2008-11-17 22:38
0
雪    币: 503
活跃值: (80)
能力值: (RANK:280 )
在线值:
发帖
回帖
粉丝
6
TEA...
记算法太辛苦,还是google好啊
2008-11-17 22:42
0
雪    币: 846
活跃值: (221)
能力值: (RANK:570 )
在线值:
发帖
回帖
粉丝
7
乌龟大师说明了一个问题,我一般是不用GOOGLE的
2008-11-17 22:51
0
雪    币: 2368
活跃值: (81)
能力值: (RANK:300 )
在线值:
发帖
回帖
粉丝
8
好在,我不是专业。
再看下个格式,下次看见也可以不用Google,baidu。就可以知道这个算法了......
2008-11-17 22:53
0
雪    币: 360
活跃值: (77)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
9
本程序使用的是TEA 算法
TEA 算法详解
采用Feistel网络,使用32次循环加密,即64轮,加密过程如下,k[0]-[3]为密钥v[0]-v[1]为待解密信息

加密算法如下

void TEA_Encrypt(DWORD* v,DWORD* k)
{
        DWORD y=v[0],z=v[1],sum=0,delta=0x9e3779b9,n=32;
        while (n-->0)
        {
                sum+=delta;
                y+=((z<<4)+k[0])^(z+sum)^((z>>5)+k[1]);
                z+=((y<<4)+k[2])^(y+sum)^((y>>5)+k[3]);
        }
        v[0]=y;
        v[1]=z;
}

解密算法如下

其中delta是黄金分割点,具体计算为delta = (√5-1 ) * 2^31
void TEA_Decrypt(DWORD* v,DWORD* k)
{
        DWORD y=v[0],z=v[1],sum,delta=0x9e3779b9,n=32;
        sum=delta<<5;
        while (n-->0)
        {
                z-=((y<<4)+k[2])^(y+sum)^((y>>5)+k[3]);
                y-=((z<<4)+k[0])^(z+sum)^((z>>5)+k[1]);
                sum-=delta;               
        }
        v[0]=y;
        v[1]=z;
}
2008-11-17 23:01
0
雪    币: 360
活跃值: (77)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
10
我汗啊,也不用这么快就接谜吧,我在写算法的时候竟然就给揭秘底了,乌龟大师啊........
2008-11-17 23:03
0
雪    币: 503
活跃值: (80)
能力值: (RANK:280 )
在线值:
发帖
回帖
粉丝
11
我也是偷师shoooo大牛的,google百度都是好东西啊

顺便再膜拜一下你的记忆力,我老了,记不住东西了
2008-11-17 23:06
0
雪    币: 282
活跃值: (31)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
12
Tea算法,也是有几个变种的。
那个常量变换一下,使用较好。
2008-11-17 23:11
0
雪    币: 503
活跃值: (80)
能力值: (RANK:280 )
在线值:
发帖
回帖
粉丝
13
somuch 很邪恶
2008-11-17 23:13
0
雪    币: 282
活跃值: (31)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
14
2008-11-17 23:16
0
雪    币: 846
活跃值: (221)
能力值: (RANK:570 )
在线值:
发帖
回帖
粉丝
15
问个问题,遇上SOMUCH这种变常量的,要怎么搜出算法?
像PEID那插件,也不全是用常量作特征的
2008-11-17 23:28
0
雪    币: 2368
活跃值: (81)
能力值: (RANK:300 )
在线值:
发帖
回帖
粉丝
16
专业领域不搅和了,旁听!
2008-11-17 23:33
0
雪    币: 503
活跃值: (80)
能力值: (RANK:280 )
在线值:
发帖
回帖
粉丝
17
我也想知道.
我的笨办法是把常见的算法都下载到本地,熟悉一下,如果只是改常量或是细微变化,比较一下还是有可能识别出来的
2008-11-17 23:38
0
雪    币: 282
活跃值: (31)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
18
算法简单了,咋变都没用。
算法即使复杂,碰上乌龟大师,还是没用
2008-11-18 00:28
0
雪    币: 846
活跃值: (221)
能力值: (RANK:570 )
在线值:
发帖
回帖
粉丝
19
那就把乌龟大师请回去当技术顾问吧
2008-11-18 01:06
0
游客
登录 | 注册 方可回帖
返回
//