吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4517|回复: 3
收起左侧

[其他转载] UPX源码粗略解析

  [复制链接]
fightingman 发表于 2020-4-20 15:40
源码的分析实际上很粗浅。起因就是每次想查看脱壳原理都是一段话或者几张图进行说明。虽然不否定这个对理解很有帮助,但是总感觉理论性比加强,实践性不高,所以就自己找源码进行分析
(我是萌新,大佬请绕过)

一、UPX原理

虽然在开头讲了(也算打自己的脸吧),但是理论确实能够帮助理解。

UPX这个壳的产生初始的目的起始是为了压缩,它产生的那个年代,机器的内存容量还很小,为了便于文件的传输,压缩文件是一个很有效的手段,UPX应运而生。到了后来才演变为为了安全为目的,当然对现在的一些分析工具,UPX的安全效能已经很低了

UPX的原理其实比较容易理解。假设原始程序是分为以下几个段 图片1.png


那么UPX会在程序入口点加上自己的壳代码,同时原来的123UPX压缩算法所压缩(假设压缩之后变为ABC 图片2.png
之后程序开始运行,这个时候会执行0处的代码,这个代码的功能是将ABC的代码解压,恢复成123,这样程序的执行与源程序是一样的。
二、源码分析
我们知道对应不同的压缩级别、不同的文件类型,对应的UPX解压缩算法是不同的,针对不同的目的可以选择不同级别的压缩算法。所以因为时间原因不可能把所有的压缩算法都审计一遍 图片3.png
这里就以一种压缩算法为例,这里是以文件类的形式写的,每种文件的压缩算法都是虚函数,然后再自己的类中再进行描述,这里以windows32的压缩算法为例。Windows32的压缩算法是 PackW32Pe::pack,文件路径是upx实例分析\源代码\upx-3.91-src\src\p_w32pe.cpp首先可以先看一下这个类的定义,可以看到几个比较关键的函数:
图片4.png
图片5.png
① virtual const int *getCompressionMethods(int method, int level) const;从函数的参数可以看出确实选择不同的方法和级别,压缩的算法是不同的。跟进去之后发现,这个函数又调用一个函数getDefaultCompressionMethods_le32 图片6.png

getDefaultCompressionMethods_le32这个函数里面就预先定义了一些方法,当然了目前还不清楚这些方法具体的压缩算法是什么。但是可以清楚确实有选择压缩算法这一功能 图片7.png
图片8.png
② virtual const int *getFilters() const;我们知道filtersUPX算法中代表着数据预处理的方法,而根据不同的数据处理方法,压缩算法的效率也不同。数据中的值可能代表着就是不同的数据处理方法 图片9.png 图片10.png
③ virtual void pack(OutputFile *fo);这个就是最关键的压缩算法了。首先是一个检查PE头,来判断是否能压缩,否则抛出异常
图片11.png
接着是对程序的一些保护措施进行处理,比如地址随机化之类的。这里还有对文件的大小进行限制,过于小的也不能压缩,限制区间是0x200

图片12.png
接着是处理绑定导入表,如果不符合压缩条件的也会抛出异常
图片13.png
然后通过调用程序内自己的API处理程序的一些段表,比如导入表、导出表、资源段等
图片14.png
还是对二进制程序的内存进行处理
图片15.png
接着开始压缩,先准备压缩后的PE头,以及确定压缩算法
图片16.png
接着调用了一个关键的函数compressWithFilters 图片17.png
这里跟进去进行分析,首先将原有结构进行一个拷贝,之后获取压缩方法
图片18.png
如果压缩方法有效那么会先分配一片空间为了接下来的压缩程序,然后会调用upx_compress 图片19.png
compress.cpp中找到这个函数(也找到了upx_decompress,在这里就可以看出来,这里还是先判断了一些选择的压缩算法,之后再用不同的API进行压缩
图片20.png
这里就以upx_lzma_compress为例子,可以找到这里又有一个比较重要的函数LzmaEncode。这个就是以lzma作为压缩算法进行压缩数据。 图片21.png
这里压缩算法比较明了了,由于这里调用其他文件中的API所以就不继续深入分析了,具体压缩算法网上都可以找得到 图片22.png
但是以lzma为例可以知道这个UPX比较粗浅的一个压缩流程:
图片23.png

④ virtual void buildLoader(const Filter *ft);这个函数是为了重建区段的。从UPX的原理可以知道,壳代码会插入在程序的入口点,插入之后为了能够成功运行程序,需要重建一下区段。可以看到这个函数里面调用了addloader()这个函数,这个函数的功能就是插入壳代码段
图片24.png

⑤ virtual unsigned processImports();我们知道一个程序基本上都会调用系统的API函数,为了调用这些函数需要在内存某个地方存放这些函数的地址----IAT表,但是再加壳之后,程序发生了变化,原有的函数地址就会被改变,这个时候就需要对导入表进行处理。这里截取一部分代码为例
图片25.png
三、后记

这个分析难免比较粗浅而且可能还有错误,虚心接受大佬批评
源码压缩包 upx实例分析.zip (1.43 MB, 下载次数: 53)

图片9.png
图片11.png
图片13.png

免费评分

参与人数 3吾爱币 +3 热心值 +3 收起 理由
lyl610abc + 1 + 1 我很赞同!
mzj21 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
zpy2 + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

跌宕起伏 发表于 2020-4-20 15:58
看不懂  就只会用UPX加个压缩壳
头像被屏蔽
庞晓晓 发表于 2020-4-20 16:59
xglys 发表于 2020-4-20 19:49
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-17 04:32

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表