首页
论坛
课程
招聘
雪    币: 123
活跃值: 活跃值 (15)
能力值: ( LV12,RANK:330 )
在线值:
发帖
回帖
粉丝

[调试逆向] [原创]UPX解压缩算法逆向

2009-4-3 17:40 15547

[调试逆向] [原创]UPX解压缩算法逆向

2009-4-3 17:40
15547
逆解压缩算法之前 一直以为需要知道N多数学上的东西  逆了后才知道 只要知道基本的逻辑就可以了

初次逆解压缩算法的同学 感到最困难的应该是  跟标志位有关的 加减法 以及条件跳转

这些东西很难跟高级语言联系在一起 用高级语言表示特别麻烦 我在这个地方 也是绕了很大的一个圈子

注:因为水平比较菜 所以我所说的逆向只是 功能相同 逻辑相似  而非指令一模一样

面临失业  没有心情继续分析壳了  很久以前就想逆解压缩算法了  现在也有时间了

仔细看下 UPX的解压缩算法   里面最重要的就是两块指令

1:

0040ED1E    01DB            ADD EBX,EBX                                  ;EBX * 2
0040ED20    75 07           JNZ SHORT x.0040ED29                     ;检测EBX 是否为0
0040ED22    8B1E            MOV EBX,DWORD PTR DS:[ESI]           ;
0040ED24    83EE FC        SUB ESI,-4                                      ;ESI + 4
0040ED27    11DB            ADC EBX,EBX

0040ED29  ^ 72 ED          JB SHORT x.0040ED18

这块指令的 最阴的地方就是SUB ESI, –4       SUB 指令影响CF标志  下面紧跟着就是一个 跟标志位有关加法

C语言中要想知道SUB执行后 CF标志为多少 必须要把ESI的值 送到一个大于4字节的 数据中  这里我用了unsigned

__int64 8字节的数据来表示,而这块指令 我以getbit函数来表示(也可以用宏 或者inline 但是我偏向于函数)

int getbit(unsigned __int64 *pcom_dword, unsigned char **ppsrc)
{
    unsigned __int64 temp;
   
    *pcom_dword &= 0xffffffff;
    (*pcom_dword) *= 2;
    if(!(*pcom_dword & 0xffffffff))
    {
        *pcom_dword = *(unsigned int *)(*ppsrc);
        temp = (unsigned int)(*ppsrc);
        temp -= (unsigned int)(-4);//temp就是为了知道 SUB后的CF标志 定义的变量
        (*ppsrc) += 4;
        *pcom_dword = ((temp >> 32) & 1) + *pcom_dword + *pcom_dword;
    }
    return (int)((*pcom_dword >> 32) & 1);
}

几句汇编指令  变成 这么大一坨 惭愧
=================================================
根据4L高手的提示 修改了 下
int getbit(unsigned int *pcom_dword, unsigned int **ppsrc)
{
        int temp;

        temp = ((*pcom_dword)>>31)&1;//得到 符号位
        (*pcom_dword) <<= 1;
        if(0 == (*pcom_dword))
        {
                *pcom_dword = **ppsrc;
                temp = ((*pcom_dword) >> 31) & 1;
                (*pcom_dword) <<= 1;
                *pcom_dword += ((unsigned int)*ppsrc >= 0xFFFFFFFC ? 0 : 1);
                (*ppsrc)++;
        }
        return temp;
}

最初 想得到标志位 也是通过32位表示的  方法是后0~30位相加  再把 2个操作数 与 相加后的和  的第31位相加 就
知道CF了    后来觉得 这样相加 实际上就是模拟64位相加  索性用64位表示算了
这里修改成32位 简洁了很多   是因为 加法的2个操作数是一样的  向左移位就可以了

getbit函数改成这样 就可以直接替换原来的getbit解压了  果然我的思路过于狭窄
再次膜拜下 4L的高手
=========================================================
2:

0040ED30    01DB            ADD EBX,EBX
0040ED32    75 07           JNZ SHORT x.0040ED3B
0040ED34    8B1E            MOV EBX,DWORD PTR DS:[ESI]
0040ED36    83EE FC        SUB ESI,-4
0040ED39    11DB            ADC EBX,EBX
0040ED3B    11C0            ADC EAX,EAX
0040ED3D    01DB            ADD EBX,EBX
0040ED3F  ^ 73 EF          JNB SHORT x.0040ED30
0040ED41    75 09           JNZ SHORT x.0040ED4C
0040ED43    8B1E            MOV EBX,DWORD PTR DS:[ESI]
0040ED45    83EE FC        SUB ESI,-4
0040ED48    11DB            ADC EBX,EBX
0040ED4A  ^ 73 E4          JNB SHORT x.0040ED30

这块指令 没有用函数表示  只是同样是一坨   再次惭愧

//EBX 对应com_dword  ESI 对应psrc  EAX对应off

do
{
    do
    {
        off = off * 2 + getbit(&com_dword, &psrc);
    }while(com_dword =com_dword + com_dword, ((com_dword >> 32) & 1) == 0);
    if(com_dword & 0xffffffff)
    {
        break;
    }
    com_dword = *(unsigned int *)psrc;
    temp = (unsigned int)psrc;
    psrc += 4;
    temp -= (unsigned int)(-4);            
}while(com_dword = com_dword + com_dword + ((temp >> 32) & 1), ((com_dword >> 32) & 1) == 0);

这两块指令弄出来后 只剩下基本的逻辑了 没什么难度了
逆这个东西 的作用就是知道怎么用C语言来表示标志位了 再来 就是 现在瞄下 压缩算法 就知道 从哪里跳出来了 不用靠猜的了  

UPX的压缩级别不同 解压缩算法也是不同的  别指望 逆出来的能解压缩所有UPX加过壳的代码

解压缩算法一直是心里的一根刺  本来想好好写写 逆向过程中的收获  逆完后 发现 什么都写不出来只能寥寥几句

附件里x.exe就是UPX加过壳的EXE, upx_re.c里存放的就是 根据x.exe逆出来的算法

[公告]看雪论坛2020激励机制上线了!多多参与讨论可以获得积分快速升级?

上传的附件:
最新回复 (27)
雪    币: 965
活跃值: 活跃值 (744)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
kanxue 活跃值 8 2009-4-3 17:46
2
0
估计会有人联系你了,前段时间还碰到有公司在招人
雪    币: 123
活跃值: 活跃值 (15)
能力值: ( LV12,RANK:330 )
在线值:
发帖
回帖
粉丝
徐大力 活跃值 8 2009-4-3 17:56
3
0
外面形势似乎 不太好
公司里有个强人  2个星期前就投简历了  现在 还没面试消息

一个朋友说 3月份 是外企裁员高峰期  结果我就赶上了
生活还得继续  希望这段时间别过得太灰暗。。。
雪    币: 738
活跃值: 活跃值 (10)
能力值: ( LV12,RANK:320 )
在线值:
发帖
回帖
粉丝
Loka 活跃值 2 2009-4-3 19:17
4
0
应该不用这么麻烦,用32位足够了。
int getbit(unsigned int *pcom_dword, unsigned int *ppsrc)
{
    int temp;
    temp = ((*pcom_dword)>>31)&1;
    (*pcom_dword) <<= 1;
    if(0 != (*pcom_dword))
    {
        *pcom_dword = *ppsrc;
        temp = ((*pcom_dword)>>31)&1;
        (*pcom_dword) <<= 1;
        *pcom_dword += ((unsigned int)ppsrc>=0xFFFFFFFC ? 0 : 1);
        (unsigned int)ppsrc += 4;
    }
    return temp;
}
雪    币: 504
活跃值: 活跃值 (13)
能力值: (RANK:570 )
在线值:
发帖
回帖
粉丝
笨笨雄 活跃值 14 2009-4-3 19:30
5
0
楼主被裁了,让我想起某公司。。。。不过不是外企。。。
雪    币: 123
活跃值: 活跃值 (15)
能力值: ( LV12,RANK:330 )
在线值:
发帖
回帖
粉丝
徐大力 活跃值 8 2009-4-3 19:31
6
0
先遥拜下高手

我用 你的getbit函数  解不开  死循环一直
= =人品?
雪    币: 326
活跃值: 活跃值 (10)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
快雪时晴 活跃值 4 2009-4-3 19:42
7
0
不知道发起一个是否被裁+被裁几次的投票  会被踩
雪    币: 738
活跃值: 活跃值 (10)
能力值: ( LV12,RANK:320 )
在线值:
发帖
回帖
粉丝
Loka 活跃值 2 2009-4-3 19:49
8
0
int getbit(unsigned int *pcom_dword, unsigned int *ppsrc)
我把第二个参数略做了点改动
雪    币: 123
活跃值: 活跃值 (15)
能力值: ( LV12,RANK:330 )
在线值:
发帖
回帖
粉丝
徐大力 活跃值 8 2009-4-3 20:01
9
0
晕 没注意到这个 。。。。
thx

先吃饭  过会 出去 吃烧烤   散心
雪    币: 59
活跃值: 活跃值 (10)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
jjnet 活跃值 5 2009-4-3 20:54
10
0
病毒公司都裁员么
雪    币: 164
活跃值: 活跃值 (31)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
TeLeMan 活跃值 1 2009-4-3 21:23
11
0
UCL是开源的,为啥还要逆呢?
雪    币: 123
活跃值: 活跃值 (15)
能力值: ( LV12,RANK:330 )
在线值:
发帖
回帖
粉丝
徐大力 活跃值 8 2009-4-3 21:52
12
0
是有源码  不过  在好几个文件中找  解压缩代码  是个折磨= =

以前 逆另一个壳的时候   只剩压缩算法  没逆出来   后来只是嵌汇编 把压缩算法 嵌进去  做了个静态 脱壳机    心有不甘   现在有时间了  就把压缩算法逆了一遍   以偿宿愿

另外 其实一直想做 仿真机  可惜以前  对那些标志位 什么的  都不会弄   逆了这个 心里有点底了  积累啊积累
雪    币: 164
活跃值: 活跃值 (31)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
TeLeMan 活跃值 1 2009-4-4 09:29
13
0
你看的是asm?c的文件很少啊,n2b_d.c,n2d_d.c,n2e_d.c和getbit.h就行了。三个c文件是因为本来就有3种压缩算法。
雪    币: 123
活跃值: 活跃值 (15)
能力值: ( LV12,RANK:330 )
在线值:
发帖
回帖
粉丝
徐大力 活跃值 8 2009-4-4 10:06
14
0
怎么我这的源码  都是C文件               
刚刚仔细找了下  解压缩源码 都在compress*.cpp里面
版本不同应该
case M_NRV2B_8:
        r = ucl_nrv2b_decompress_safe_8(src,src_len,dst,dst_len,NULL);
        break;
    case M_NRV2B_LE16:
        r = ucl_nrv2b_decompress_safe_le16(src,src_len,dst,dst_len,NULL);
        break;
    case M_NRV2B_LE32:
        r = ucl_nrv2b_decompress_safe_le32(src,src_len,dst,dst_len,NULL);
        break;
    case M_NRV2D_8:
        r = ucl_nrv2d_decompress_safe_8(src,src_len,dst,dst_len,NULL);
        break;
    case M_NRV2D_LE16:
        r = ucl_nrv2d_decompress_safe_le16(src,src_len,dst,dst_len,NULL);
雪    币: 110
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
godisagirl 活跃值 2009-4-4 10:48
15
0
祝你好运
楼主不要灰心
雪    币: 164
活跃值: 活跃值 (31)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
TeLeMan 活跃值 1 2009-4-4 15:09
16
0
你要看UCL的源码,UPX源码中不包含压缩和解压缩代码。
雪    币: 123
活跃值: 活跃值 (15)
能力值: ( LV12,RANK:330 )
在线值:
发帖
回帖
粉丝
徐大力 活跃值 8 2009-4-5 11:28
17
0
多谢提点
雪    币: 201
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
王旭峰 活跃值 2009-4-5 16:58
18
0
这么巧 我也正在研究它  惭愧
雪    币: 2308
活跃值: 活跃值 (17)
能力值: (RANK:510 )
在线值:
发帖
回帖
粉丝
加百力 活跃值 12 2009-4-6 23:37
19
0
支持楼主。
别灰心。机会一定会有的!说不定,下个单位还更好呢!
雪    币: 335
活跃值: 活跃值 (10)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
人很老实 活跃值 2 2009-4-7 09:12
20
0
祝君好运
雪    币: 415
活跃值: 活跃值 (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
guobing 活跃值 2009-4-7 10:17
21
0
这么牛的人,竟然被裁,我们这小菜,怎么过啊。
趁现在在学校还有时间,还多多努力啊
雪    币: 123
活跃值: 活跃值 (15)
能力值: ( LV12,RANK:330 )
在线值:
发帖
回帖
粉丝
徐大力 活跃值 8 2009-4-7 16:52
22
0
已在主贴修改
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Xusually 活跃值 2009-4-8 18:01
23
0
高手都被裁,我等小菜怎么过啊
雪    币: 27
活跃值: 活跃值 (16)
能力值: ( LV9,RANK:970 )
在线值:
发帖
回帖
粉丝
wynney 活跃值 24 2009-4-12 18:58
24
0
LZ可以试试这里的
http://bbs.pediy.com/showthread.php?t=85011
雪    币: 184
活跃值: 活跃值 (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
霹雳狂风 活跃值 2009-4-13 00:25
25
0
IDA F5
雪    币: 123
活跃值: 活跃值 (15)
能力值: ( LV12,RANK:330 )
在线值:
发帖
回帖
粉丝
徐大力 活跃值 8 2009-4-13 13:51
26
0

抱歉  这2天 休假 没怎么上网          还有半个月 离开公司   走人了~~~

传说中的comodo吗?
简历 前一阵子已经寄过了   一直没消息  被KO的多了

看了下  只能勉强 符合职位:
工程师

要求:
1、1年以上工作经验
2、熟悉C++
3、对壳感兴趣,能手动脱压缩壳
4、学习能力强

工作经验 近1年
对壳感兴趣,能手动脱压缩壳
学习能力强
对C很熟悉   不用C++的高级特性  的话 应该可以
没碰过C++
雪    币: 558
活跃值: 活跃值 (10)
能力值: ( LV13,RANK:290 )
在线值:
发帖
回帖
粉丝
dge 活跃值 6 2009-4-13 14:06
27
0
换个环境更好。
雪    币: 140
活跃值: 活跃值 (10)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
runjin 活跃值 4 2009-4-13 14:55
28
0
支持一下lz
游客
登录 | 注册 方可回帖
返回