UPX对Android上ELF加壳使用过程中的若干问题总结
2016-07-12 16:08
1631 查看
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()函数中:
[cpp] view
plain copy
if (/*jni_onload_sym ||*/ elf_find_dynamic(Elf32_Dyn::DT_INIT)) {
......
也就是说Dynamic段中必须有类型为DT_INIT的字段,它指向ELF文件初始化函数在文件中的偏移。一般的so都不会有这个函数,要加上很简单,只要在你的代码中加入下面代码:
[cpp] view
plain copy
#ifdef __cplusplus
extern "C" {
#endif
void _init(void){}
#ifdef __cplusplus
}
#endif
下面内容部分摘录自:http://www.cnblogs.com/fishou/p/4202061.html
分析:原因是链接器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(参考“创建加固环境”章节)
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()函数中:
[cpp] view
plain copy
if (/*jni_onload_sym ||*/ elf_find_dynamic(Elf32_Dyn::DT_INIT)) {
......
也就是说Dynamic段中必须有类型为DT_INIT的字段,它指向ELF文件初始化函数在文件中的偏移。一般的so都不会有这个函数,要加上很简单,只要在你的代码中加入下面代码:
[cpp] view
plain copy
#ifdef __cplusplus
extern "C" {
#endif
void _init(void){}
#ifdef __cplusplus
}
#endif
下面内容部分摘录自:http://www.cnblogs.com/fishou/p/4202061.html
5、相关问题总结
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(参考“创建加固环境”章节)
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories