1. UPX中使用的压缩算法有三种,最早是UCL,然后加入了NRV,3.91版本又加入了LZMA。按照UPX源码中的文档来说,UCL压缩效率是相对较低的,但是好处是OpenSource的,NRV效率较高,但是不开源,而LZMA算是这三种中压缩效率最高的了,在7Zip中就是使用的这种压缩算法。但是从UCL的官网来看,UCL是对NRV中的一些算法的重实现,这样来说的话应该压缩效率更高才对。这里不纠结这个了,具体信息见相关链接:http://www.redhat.com/archives/blinux-list/2003-September/msg00030.html
2. Packed programs will be byte-identical to the original after uncompression. UPX是安全的、没有数据损失的压缩工具。
3. UPX对ELF文件加壳要求ELF文件必须有_init导出函数,否则会报"UnknownExecutableFormatException"错误,问题定位到UPX源码的p_lx_elf.cpp文件的canPack()函数中:
下面内容部分摘录自:http://www.cnblogs.com/fishou/p/4202061.html
5.1、编译UPX出现“cannot find -lz”错误。
分析:原因是链接器LD没有找到编译出来的zlib库libz.so或libz.a。
解决方法:将libz.so或libz.a拷贝到系统默认的动态链接库路径下,比如/usr/lib,/usr/lib64 等。
5.2、编译UPX出现“CantPackException: DT_TEXTREL found; re-compile with -fPIC”错误。
分析:这是早期NDK版本的BUG。
解决方案:使用NDK9或以上的版本
5.3、编译UPX出现“NotCompressibleException”错误。
分析:UPX对被加壳的二进制文件有最小限制,太小的文件将无法被加壳。
解决方案:在native代码中定义足够大的数据变量,使得编译出来的二进制文件容易达 到UPX的要求(参考《加固步骤》之《修改native代码》章节)。
5.4、编译UPX出现“UnknownExecutableFormatException”错误。
分析:被加壳的二进制文件必须存在init段,否则UPX将无法脱壳还原原始代码。
解决方案:在native代码中定义_init()方法,需要注意C和C++的区别(参考《加固步 骤》之《修改native代码》章节)。
备注:查看二进制文件是否存在init段的命令:readelf –dynamic xxx.so,如下图:
5.5、使用UPX加壳的SO,在eclipse中启动Android程序时出现”Fatal signal…”错误,如图:
分析:此错误是因为UPX解析某些特殊字符处理不当导致的,该BUG已经有人提交UPX 官方解决,但是当前官方正式发布的正式版本(V3.91)并没有fix该问题,而是在未正 式发布的V3.92才解决了该问题,因此本文档使用源代码版本为V3.92而非V3.91。
解决方案:下载使用V3.92源码,下载入口请参考《创建加固环境》章节。
5.6、为何删除UPX源码中的软件信息,以及如何定位查找这些信息。
分析:UPX对文件进行加壳时会把这些信息写入壳内,通过静态反汇编可查看到这些壳信息,进而寻找对应的脱壳机进行脱壳,使得攻击难度降低。
解决方案:在UPX源码中删除这些信息,并重新编译,步骤如下:
5.6.1、使用原始版本对文件进行加壳。
5.5.2、使用IDA反汇编加壳文件,在反汇编文件的上下文中查找UPX壳特征字符串, 如下图所示:
5.5.3、在UPX源码中查找这些特征字符串(建议使用Search and Replace),并一一删除, 如下图:
5.5.4、重新编译UPX(参考“创建加固环境”章节)