[原创]UPX源码学习和简单修改加壳脱壳看雪

UPX的核心加壳代码是upx-3.96/src/p_unix.cpp文件的pack函数。

该函数调用了4个关键函数,分别为pack1、pack2、pack3和pack4,代表了加壳的四个步骤。

pack1函数功能是,写入新文件的elf头,写入程序头表,写入1个初始化的l_info结构。

pack2函数功能是,对所有类型为PT_LOAD的段进行压缩存储。

其中,在对第一个类型为PT_LOAD的段(该块一般包含原文件的文件头和程序头表)进行压缩时,会将该段分为两个部分分别压缩写入。这两部分为:一、原文件的elf头和程序头表;二、该段数据的其他部分。例如,demo文件中第一个PT_LOAD段如下

第一段文件偏移为0,大小为0x5F0。从图中可以看到文件头+程序头表的大小为0x270,这就是需要压缩的第一块数据。第二块数据就是文件偏移为0x270,大小为0x380。

pack3函数的功能是,写入loader,压缩原文件中除PT_LOAD段之外的其余数据并写入,修正程序头表内容

pack4函数的功能是,写入PackHeader和overlay_offset。这里overlay_offset值为p_info字段的文件偏移。本demo中为0xf4。

经过UPX处理后,压缩后的文件格式如下。

neweheader(64bytes)(文件头)+newpheader(56bytes)*3(程序头表)+l_info(12bytes)+p_info(12bytes)+b_info(12bytes)+compressedblock(原程序文件头和程序头表)+b_info(12bytes)+compressedblock(第一个类型为PT_LOAD的段中除原程序文件头和程序头表的部分)+b_info(12bytes)+compressedblock(第二个类型为PT_LOAD的段)+......+fpad8(8字节对齐)+int(4bytes)(第一个b_info的文件偏移)+int(4bytes)(当前位置的文件偏移,也就是之前所有数据总长度)+loader(加载器,也就是脱壳代码)+b_info(12bytes)+compressedblock(第一个PT_LOAD和第二个PT_LOAD中间的数据)+b_info(12bytes)+compressedblock(第二个PT_LOAD和第三个PT_LOAD中间的数据)+......+b_info(12bytes)+compressedblock(最后一个PT_LOAD到文件末尾之间的数据)+000000005550582100000000(b_info)+fpad4(4字节对齐)+PackHeader(32bytes)+int(4bytes)(p_info的文件偏移)

其中,b_info、l_info和p_info是三个结构体。

针对demo文件的loader生成代码在upx-3.96/src/p_lx_elf.cpp文件的PackLinuxElf64::buildLinuxLoader()函数中,loader中各section的相应顺序由函数PackLinuxElf::addStubEntrySections()确定。

除了"FOLDEXEC",其余section的汇编代码在upx-3.96/src/stub/src/amd64-linux.elf-entry.S文件中,编译后的二进制数据在文件upx-3.96/src/stub/amd64-linux.elf-entry.h中。loader直接使用*.h文件中的二进制数据。

最终,demo文件压缩后loader的结构如下

FOLDEXEC节存放的是压缩后的数据,源数据是编译后的二进制数据,存放在upx-3.96/src/stub/amd64-linux.elf-fold.h文件中。编译前的代码分为两部分,一部分是upx-3.96/src/stub/src/amd64-linux.elf-fold.S文件中的汇编代码,一部分是upx-3.96/src/stub/src/amd64-linux.elf-main.c文件中的C代码。该文件核心是upx_main()函数,此函数返回值为解压后程序(原程序)的入口点.

在阅读UPX源码过程中,经常需要对压缩后的文件格式进行分析,以验证自己的猜想。因为笔者经常使用010作为二进制分析工具,遂决定自己写一个010模板。这里是对标准的ELF.bt(V2.5.5)进行了修改。

首先,将上节所述的三个关键结构体加入到模板中,为了增加可读性,在个别字段添加属性值。添加的结构体代码如下:

最后,在file结构体中program_header_table结构体生成之后,添加l_info结构之后的数据解析代码。

最终效果如下,红框中是我们添加的新结构。

修改完成的模板见结尾文件upx.bt。因为文件格式问题,该模板只适用于demo文件压缩后的文件。大家有其他需求可以在此基础上自己修改。

之前做病毒分析时,碰到了一个无法使用标准UPX程序解压的程序。后来通过搜寻资料和学习,了解到有多种方式可实现该效果。基本思路是修改替换程序中的特征字符,常见的修改方法如下:

据此,笔者萌生直接对源码进行修改的想法,所以有以下两个简单尝试。

本次尝试主要是修改源程序的入口点位置,使常规的UPX解压程序后无法快速找到正确的入口点位置。

存储入口点之前,处理该值,这里异或一个常量0xdeafdeaf。文件upx-3.96/src/p_unix.cpp添加如下代码

解压得到入口点之后,处理该值,也是异或常量0xdeafdeaf。这里有两种方式,实现的功能一样。

xoreax,3736067759->35AFDEAFDE->53,175,222,175,222

上面对于入口点的修改虽然成功了,但是压缩后的程序仍然可被解压。而且从原理来看,解压后是可以看到原程序代码执行逻辑的。所以笔者有了第二次代码修改。主要修改思路是,对压缩之前的数据进行处理,然后再进行压缩。这样标准UPX就无法解压我们自己压缩的程序,比只对入口点的修改效果更好。

压缩前修改数据,我们做一个简单的异或处理,这里对所有的数据异或0xe9(十进制为233)文件:upx-3.96/src/compress.cppupx_compress函数修改,核心部分

upx_decompress函数修改,此处修改主要是因为在文件upx-3.96/src/packer.cpp的Packer::compress函数中,会对压缩后的数据进行解压验证,需要保持压缩和解压函数逻辑对称。

upx在加载loader是会对其进行压缩处理,而解压算法已写成汇编代码,修改起来比较麻烦。这里我就对loader数据多进行一次处理,以抵消upx-3.96/src/compress.cpp文件upx_compress函数中添加的异或处理。文件:upx-3.96/src/p_lx_elf.cpp

因为原数据压缩前进行了处理,为保证执行时程序逻辑不变,需要对解压后的数据进行逆处理。下面就是对loader的源码进行修改。文件:upx-3.96/src/stub/src/amd64-linux.elf-main.c

本文主要介绍了三个部分的内容:

WIN的加壳流程我不太清楚,得你自己阅读源码了。loader部分的话使用的是另外的文件,在目录upx-3.96/src/stub/src/可以看到

用vmtest师傅提到的工具就可以,根据说明配置好之后,编译的时候类似amd64-linux.elf-fold.h的.h文件都会重新生成的。

THE END
1.阅读源码的经验总结如何阅读第三方开源库 选择一些当下热门、学习价值高的第三方开源库,我认为最值得学习的第三方开源库是Volly,开源项目解析中也有对Volly的解析。 热门的第三方开源库,网上会有很多源码解析文章,首先在网上找一些源码解析文章来看看,不要忘记,我们的宗旨之一“高效”,这样就可以快速的对项目的整体框架有一个大体的了解https://www.jianshu.com/p/be86e5678252
2.如何学习源码如何学习优秀的源码如何学习源码 一、程序员的层次划分(本文只针对学习源码部分) 1、只关注项目本身,不懂就baidu一下。 2、除了做好项目,还会阅读和项目有关的技术书籍,看wikipedia。 3、找一些开源项目看看,大量试用第三方框架,还会写写demo。 (要解决什么问题?如何实现的?)https://blog.csdn.net/shengyin714959/article/details/142281091
3.如何较好的学习框架底层源码?都有自己的优势和特点,在国内TP确实用的很多,我想说的是具体学习哪个框架并不重要,我们需要选择一个安安心心的学好他的底层(如果您时间比较充裕的话,全部学习也是可以的,哈哈),因为你会了一个框架之后,其他框架你自学下很快就会上手,因为框架的核心思想基本是相通的,本文章我就拿TP来举例,我们如何学习他的源码呢https://www.imooc.com/article/284124
4.Vue源码学习之响应式是如何实现的vue.js最近接触了vue.js,一度非常好奇vue.js是如何监测数据更新并且重新渲染页面,这篇文章主要给大家介绍了关于Vue源码学习之响应式是如何实现的相关资料,需要的朋友可以参考下+ 目录 GPT4.0+Midjourney绘画+国内大模型 会员永久免费使用!【 如果你想靠AI翻身,你先需要一个靠谱的工具!】 前言 作为前端开发,我们的日常工作https://www.jb51.net/article/225377.htm
5.还不会Vue2.x源码本地调试!一前言由于自己最近准备学习vue的由于自己最近准备学习vue的源码,所以首先我得知道怎么样去本地调试vue得源码。后续也会把学习中遇到得问题、校验梳理成文章,也当作自己的学习笔记。 写在前面,我看的版本是"version":"2.6.14" 二、如何进行本地调试 首先我们找到vue2的源码地址进行本地clone https://juejin.cn/post/7081983962339508261
6.面向学生的.NET学习使用C#编程语言编程学习如何编写 C# 代码 嗨朋友们! 学习编码可能令人生畏。我们将随时为你提供帮助。 开始 获得认证 使用与freeCodeCamp合作进行的新基础 C# 认证,展示你的 C# 知识。该认证是全面的、可全球访问的,最重要的是,它是免费的,可确保世界各地的学习者都能从针对Microsoft Learn的可靠 C# 培训中获益。https://dotnet.microsoft.com/zh-cn/learntocode
7.RocketMQ消息积压,异步方案,缓存策略解决方案如何入手学习源码 最核心的一点就是查看官方文档 官方文档是所有技术中 最权威,最齐全的一个资料聚集地 有些翻译中文的网站,可能会做到更新不及时,所以还是建议直接看英文文档,借助翻译即可。也可以锻炼英文水平 首先要掌握这个技术的整体结构,有哪些功能特性,涉及到的关键技术、实现原理和生态系统等等。掌握了这些,对https://developer.aliyun.com/article/932643
8.idea看python源码mob64ca12f3496a的技术博客在上面的代码中,使用requests库获取API数据时,可以按住Ctrl并点击get函数,将打开get函数的源码,让你更好的了解它的实现逻辑。 第六步:理解和学习源码 在你打开Python源码后,仔细阅读代码及其注释,可以发现大多数库都包含详尽的解释。这会帮助你了解函数的功能与实现。 https://blog.51cto.com/u_16213443/12795867
9.源码时代成都IT培训重庆UIh5Java培训不敢去怎么办?毕业就拿近万元offer!现在的应届生都这么强?在源码毕业后,能进大厂吗?答案来了!狂欢7天7夜!源码时代11周年庆超燃来袭源码时代天府校区正式开课!2021源码时代课程更新、服务升级、就业加速:新价目标准将于4月1日正式执行 源码时代学习环境 硬核设施,舒适的环境,铸就你的美好未来https://www.itsource.cn/
10.人类高质量Java学习路线一条龙版做一个完整的项目的确很不容易,建议大家根据自己的时间、兴趣选择较新的、有配套源码的教程,保持耐心。 如何选择编程学习资源,可以看下我的原创文章:https://mp.weixin.qq.com/s/mlMql9RJCd7THt6rpGb8UA 下面推荐一些优质的、较新的项目实战视频教程 + 50 套项目源码。 https://xie.infoq.cn/article/a9fd4615c281e8ca41840ce37
11.北京大学金芝教授受邀出席云南省金芝专家工作站揭牌仪式并作学术金芝教授作源代码表示学习的报告 揭牌仪式结束后,金芝教授主要围绕源代码表示学习为软件学院师生作科研报告,详细介绍了深度学习技术如何赋能源代码分析工作。金芝教授通过主题突出的精彩报告,围绕代码表示学习发展历程及其重要意义和代码表示学习方法等方面同师生们进行了深入交流和研讨互动。针对师生提问,金芝教授给予了深入详http://www.sei.ynu.edu.cn/info/1056/2111.htm
12.macd指标背离公式源码(学习)博客macd指标背离公式源码(学习) 一、MACD顶底背离副图 DIFF:EMA(CLOSE,12) - EMA(CLOSE,26);DEA:EMA(DIFF,9);MACD:2*(DIFF-DEA),COLORSTICK;A1:=BARSLAST(REF(CROSS(DIFF,DEA),1));B1:=REF(C,A1 1)>C AND REF(DIFF,A1 1)A2:=BARSLAST(REF(CROSS("KDJ.K"(9,3,3),"KDJ.D"(9,3,3)),1))http://blog.eastmoney.com/yudi010/blog_220210785.html
13.助记词盗u秒u源码转地址转私钥可直接对接假钱包app端源码仅供学习交流使用,一切法律后果均与本站无关。 助记词转地址 + 余额更新 + 一键账号余额一键归集 大于多少u自动转走 可直接对接假钱包,具体方法已经写在教程里了 教程 本系统集合助记词转地址 + 余额更新 + 一键余额一键归集 安装教程php7.2 mysql5.6 php安装gmp扩展 安装nodehttps://www.jianshu.com/p/https://yiqucode.com/qukuailian-3696.html
14.Git--distributed-even-if-your-workflow-isnt Git is afree and open sourcedistributed version control system designed to handle everything from small to very large projects with speed and efficiency. Git iseasy to learnand has atiny footprint with lightning fast performance. It outclasses SCM tools https://git-scm.com/