#upx #packer
近期见到不少UPX魔改壳,需要走linux手脱,这里简单记录一个demo和一个实例的手脱例子
我脱ELF的UPX壳主要有两条路径。
第一条是常规分析,跟踪到几个特征点就能判断当前脱壳到了哪一步。如特殊的jmp点,连续的几个循环和call调用,
第二条是入口点判断,ELF的UPX壳基本会走到call _dl_start、init、fini函数,或者说这是ELF程序函数头的特征,那么我们只需要调试到call _dl_start等初始化函数时,就能知道脱壳已完成了。
上述两条思路均有在下文中体现。
demo手脱
简单写一个测试程序
1 |
|
普通编译指令
1 | gcc test.c -o test |
下载upx-linux版
1 | wget https://github.com/upx/upx/releases/download/v4.2.4/upx-4.2.4-amd64_linux.tar.xz |
这里同时测试一下-1和-9命令,对应两种压缩效果
1 | ./upx -1 ../test -o test_compress_faster |
ida看看
函数结构差别不大
无其它段,只有load段
upx的-1~-9压缩级别不影响基本的解压缩方式,这里用-9 compress better做一个手动脱壳演示。
首先在start处下个断点一路f7,单步跟入后可发现如下地方:
upx linux的特点是,其会用到不少syscall来执行sys_open、sys_mmap等函数,以此来新建段、解密并执行。就像windows shellcode的VirtualAlloc+VirtualProtect一样
于是一直f7我们很容易看到:
新建段
这里我们还可以看一下段视图(ctrl+s)
调用之前:
调用之后(若是没显示是ida的问题,需要run一下才能刷新段视图,但其实段已经新建了):
修改段属性
紧跟着的jmp r13
会跳转到新建的debug002段
依旧f7,f7之后会遇到三个循环体,这里没什么东西可以直接跳过
这个函数的下面还有一些函数
这些是会真正进行解密操作的函数,确定这一点是根据接下来的两种分析思路:
①一般这种小程序的入口点都是401000,我们可以在401000下硬件读、写断点或者执行断点,再或者接下来的几个call都f8,f8之后看看401000函数有没有变化.
如第一个call
执行后:
可看到解密成功。
②UPX的linux版有一些固定的规律,比如
看到最底下的这一句
你一直f8到这里也差不多,总之到这里后继续跟进
可发现:
进入初始化函数了。
再一跳转
哟,start
魔改实例脱壳
这是一个4.01版本的魔改壳
需要注意的是,有的UPX打包的程序,其程序类型可能是DYN,ida动调时会提示:”Inputfile is a dynamic file。。。”然后不让你调试,这时候可以修改文件头信息从03->DYN改为02->EXEC
照样开头下断点
该程序运行起来时的段信息和我们正常的不太一样,于是就不太能像前面说的,对可能的开头代码下执行断点。
按照步骤执行到此处:
熟悉的地方
简易脱壳
1 | from ida_bytes import * |