UPX是一种古老的压缩壳,因为高压缩比使用方便,常被各个黑产组织使用,为了防止恶意程序被UPX程序正常解压,分析程序本体。因此UPX压缩壳的变形方法层出不穷,被花式修改。
这篇文章主要总结Linux平台下,遇到过的UPX变形壳类型以及对应脱壳技巧Tips,方便以后快速脱壳。
UPX压缩原理与文件结构,可参考以下文章,不再赘述:
https://bbs.kanxue.com/thread-275753.htm
1. UPX变形手法
变形手法包括不限于以下方式:
修改UPX两个区段名称
修改三个UPX特征码
修改或去除UPX!相关字符串
修改或去除p_info结构信息
添加冗余数据至文件尾部
2. UPX脱壳Tips
2.1 快速识别变形类型
利用UPX原生程序直接尝试脱壳,根据报错信息快速识别变形类型。
大致分为三种告警:
need a newer version of UPX
p_info corrupted
not packed by UPX
提示 need a newer version of UPX ,使用新版本的UPX程序即可。

提示 p_info corrupted,p_info结构被破坏需要修复后脱壳。

提示 not packed by UPX,推测是否修改了UPX节区信息/l_magic结构/增加冗余数据,需要进一步确认后修复。

2.2 修复UPX特征码
Winhex中发现UPX被修改。

全局替换为UPX!。

即可利用UPX原生程序成功脱壳。

2.3 修复p_info结构信息
p_info头部结构体成员p_blocksize信息被抹去。

p_filesize与p_blocksize值相同,p_filesize记录在文件末尾偏移8字节的位置。

复制p_blocksize值到p_info中。

即可利用UPX原生程序成功脱壳。

2.4 删除冗余数据
winhex中发现最后一个UPX!节区超过32字节。

删除此节区超过32字节后面的冗余数据。

其余部分利用UPX原生程序即可修复,并成功脱壳。

2.5 使用IDA脱壳
开启IDA调试,F7步入第一个Call。

F8跳过三个循环。

IDA识别到ELF头部信息,即将跳转值ELF程序入口点。

跳转找到ELF入口点。

dump脱壳后的文件。

dumpfile.idc
static main(void){auto ImageBase,StartImg,EndImg;auto e_phoff;auto e_phnum,p_offset;auto i,dumpfile;ImageBase=0x400000;StartImg=0x400000;EndImg=0x0;if (Dword(ImageBase)==0x7f454c46 || Dword(ImageBase)==0x464c457f ){if(dumpfile = fopen("C:\\Users\\admin\\Desktop\\infected\\20240327\\DumpFile","wb")){e_phoff=ImageBase+Qword(ImageBase+0x20);Message("e_phoff = 0x%x\n", e_phoff);e_phnum=Word(ImageBase+0x38);Message("e_phnum = 0x%x\n", e_phnum);for(i=0;i{if (Dword(e_phoff)==PT_LOAD || Dword(e_phoff)==PT_DYNAMIC){p_offset=Qword(e_phoff+0x8);StartImg=Qword(e_phoff+0x10);EndImg=StartImg+Qword(e_phoff+0x28);Message("start = 0x%x, end = 0x%x, offset = 0x%x\n", StartImg, EndImg, p_offset);dump(dumpfile,StartImg,EndImg,p_offset);Message("dump segment %d ok.\n",i);}e_phoff=e_phoff+0x38;}fseek(dumpfile,0x3c,0);fputc(0x00,dumpfile);fputc(0x00,dumpfile);fputc(0x00,dumpfile);fputc(0x00,dumpfile);fseek(dumpfile,0x28,0);fputc(0x00,dumpfile);fputc(0x00,dumpfile);fputc(0x00,dumpfile);fputc(0x00,dumpfile);fputc(0x00,dumpfile);fputc(0x00,dumpfile);fputc(0x00,dumpfile);fputc(0x00,dumpfile);fclose(dumpfile);}else Message("dump err.");}}static dump(dumpfile,startimg,endimg,offset){auto i;auto size;size = endimg-startimg;fseek(dumpfile,offset,0);for ( i=0; i < size; i=i+1 ){fputc(Byte(startimg+i),dumpfile);}}
2.6 使用修复工具
upx-recovery-tool使用方法参考Github。
https://github.com/NozomiNetworks/upx-recovery-tool

upxfix使用方法参考Github。
https://github.com/srozb/upxfix
