upx加壳源码
⑴ upx技术原理
在保护程序资源方面,利用UPX技术进行可执行文件的压缩是一种常见的手段,也被称为文件"加壳"。加壳的目的是为了隐藏程序的原始源代码,使其在不被直接查看的情况下运行。
加壳的过程实际上是一个特殊的编码过程,它运用了一种类似于WINZIP的压缩算法,但区别在于,压缩后的文件无需解压即可直接执行。压缩操作在内存中悄悄进行,不暴露给用户任何解压的迹象。这个过程在文件的头部嵌入了一段指令,该指令向CPU提供了解压的线索。当程序被加壳时,就像给文件穿上了无形的外壳,用户实际上执行的是这个外壳程序。
外壳程序在运行时会负责在内存中解压真正的程序。解压完成后,程序的真正执行交给解包后的部分。这种方式不仅保护了代码的隐私,还提高了程序的运行效率,因为无需在磁盘上进行解压缩操作。
(1)upx加壳源码扩展阅读
UPX (the Ultimate Packer for eXecutables)是一款先进的可执行程序文件压缩器,压缩过的可执行文件体积缩小50%-70% ,这样减少了磁盘占用空间、网络上传下载的时间和其它分布以及存储费用。 通过 UPX 压缩过的程序和程序库完全没有功能损失和压缩之前一样可正常地运行,对于支持的大多数格式没有运行时间或内存的不利后果。 UPX 支持许多不同的可执行文件格式 包含 Windows 95/98/ME/NT/2000/XP/CE 程序和动态链接库、DOS 程序、 Linux 可执行文件和核心。
⑵ 使用x64dbg脱壳之开源壳upx
大家好,我是蓝铁,你们的老铁,^_^ 我们知道在分析病毒的时候,最常见的一种壳就是upx,使用upx的好处就是压缩率还不错,可以让原程序缩小一倍,便于在网络中传输。本节就是以开源壳upx为例讲解x64dbg中的脱壳方法。
脱壳中的一些常见概念
首先我向大家介绍一下脱壳相关的概念。
脱壳中的一些方法
脱壳算是软件逆向技术中一种比较难的技术,方法也有很多,我在这里先介绍有代表性的方法:
单步跟踪(踏踏实实法)
一步一步分析每一条汇编指令,吃透每一行汇编背后所代表的意思,将壳代码读懂,从而找到原始OEP然后脱壳。这种方法是最锻炼人的,也是最难的。即使一个有经验的逆向分析者在对一个陌生的加壳程序分析时也需要花费很多时间,但这就是逆向工程的魅力,挑战自我,挑战才能突破。一般这种方法是在我们学习逆向工程时或是不能使用技巧时才会用的方法,耐心是这个方法的关键。
平衡堆栈(又称ESP定律,技巧法)
一般加壳程序在运行时,会先执行壳代码,然后在内存中恢复还原原程序,再跳转回原始OEP,执行原程序的代码,我们可以把壳代码理解为一个大的函数,既然是函数,那么进入函数和退出函数时,堆栈应该就是平衡的,基于这样的一种特性,我们可以在壳代码操作了堆栈之后,对堆栈设置访问断点,然后让程序跑起来,当程序暂停的时候,就是壳代码即将执行完的时候,然后在其附近单步跟踪,就可以找到原始OEP了。这种方法比较适用于upx这种只对代码和数据压缩了的壳,如果还对代码加密了,那么就不是太好找了。加密的话就需要结合单步跟踪法。
脱壳三步法
不管是哪种脱壳方法,都需要遵循脱壳三步法,脱壳三步法分为以下三步: ① 寻找原始OEP 这一步骤的主要作用就是要确定原始程序代码到底在哪里,能找到原始程序的代码,说明壳代码执行完了,我们只有找到原始OEP才能进行下一步的动作。 ② mp内存到文件 当我们找到原始OEP,调试运行到原始OEP时,只要代码被还原,我们就可以在这个地方进行mp内存,将内存中被还原的代码和数据抓取下来,重新保存成一个文件,这样脱完壳时,我们就可以用静态分析工具分析程序了。
③ 修复文件 这一步主要就是修复IAT,对从内存中转储到本地的文件进行修复。
下载upx与使用upx对文件加壳
下载upx
upx壳的官网是: upx.github.io/ 下载最新版的upx: github.com/upx/upx/rele... 本次实验使用的是windows版的upx,所以下载的版本是:
使用upx对文件加壳
下载完之后,解压开可以找到upx加壳的主程序upx.exe,我们可以对任意程序进行加壳,可以使用命令行进行加壳。 以VC6.0编写的一个程序为例,对其进行加壳,加壳之前我们先使用x64dbg查看一下其OEP:
可以观察一下OEP有什么特点? 然后我们使用命令行对vc6.0的demo程序加壳
可以看到,加壳之后,文件大小从200多K变成了90多K。 再使用x64dbg观察加壳后程序的OEP:
可以发现,加壳之后的程序和加壳前真的很不一样,所以我们才要进行脱壳。
使用x64dbg脱壳之寻找OEP
寻址OEP的方法有多种,这里我们使用前面介绍的平衡堆栈法,我们使用x64dbg调试加壳后的程序,观察oep处的指令,可以发现OEP的第一条指令是pushad,其作用一般是保存寄存器环境,可以将8个通用寄存器都压入堆栈,那么我们可以单步程序(F8),执行pushad,这样堆栈就会发生变化,而后我们可以在堆栈栈顶处,即ESP指向的内存处,设置硬件访问断点,
我们可以在x64dbg中的寄存器窗口处,选中esp,然后右键选中在内存窗口中转到
然后在内存窗口处,右键设置硬件访问断点
之后,可以使用快捷键F9运行程序,程序会再次暂停下来,我们观察附近指令
可以发现我们暂停的指令上方就是popad指令,一般遇到popad指令,就离原始OEP不远了,因为执行完popad指令意味着壳代码告一段落了。 继续单步,可以发现一个比较大的jmp跳转。这个jmp其实就会跳转到原始OEP。
实际上在分析时,我们是先单步到jmp跳转到的代码进行观察之后得出是否是原始OEP的结论的,这个部分需要我们对未加壳程序的OEP要有所了解,比如VC6.0的程序一般OEP最开始的一个API调用是GetVersion,看OEP见到GetVersion就如见到了vc6.0程序。 我们单步到跳转之后的代码处,409376,这个地方就是原始OEP,而后我们要做的就是在这个地方进行mp。
使用x64dbg脱壳之mp内存
当我们找到原始OEP时,我们运行到此处,然后对当前程序的内存进行mp,需要使用x64dbg中的一个插件:Scylla。
打开插件Scylla
使用快捷键Ctrl+I可以直接打开插件,进行mp。
Scylla的使用
注意,mp时需要填写正确的原始OEP地址,然后点击Dump按钮保存文件。
保存完毕之后,最后就是修复文件了。
使用x64dbg脱壳之修复文件
修复文件,本质上就是修复IAT,所以还是使用插件Scylla,先对当前程序的IAT进行扫描,如果能找到就可以使用工具修复,不能就需要手动修复。 为了能更好的获取IAT,我们需要对插件Scylla进行设置。
使用x64dbg单步跟踪,发现出现异常的地方
根据这个地址以及经验可以猜出,可能是这个地址所在的区段的属性不可写。使用LordPE,可以查看区段属性,如下图,果然是没有可写的属性。
将其可写属性打钩,保存文件即可添加属性,这样就完成了脱壳。
测试结果
最后我们可以运行已经脱壳修复完成的程序,先使用PEID查看一下区段,然后运行。
总结
脱壳这门技术在任何一个平台下都是比较难的技术,想要练成这项技术,除了对汇编语言要非常熟悉之外,还需要对可执行文件的格式很熟悉,并且对可执行文件的加载流程还有一定认识,比如在这一节中,我们讲到了一个名词,修复IAT,只有对可执行文件加载流程理解了,修复IAT才会真正理解。综上,脱壳技术的练习是综合练习,我们从Upx开始,一步一步去分析现在主流的病毒混淆壳吧!希望大家可以跟着我尝试练习^_^。