UPX对Android上ELF加壳使用过程中的若干问题总结

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
 
  1. if (/*jni_onload_sym ||*/ elf_find_dynamic(Elf32_Dyn::DT_INIT)) {  
  2. ......  

也就是说Dynamic段中必须有类型为DT_INIT的字段,它指向ELF文件初始化函数在文件中的偏移。一般的so都不会有这个函数,要加上很简单,只要在你的代码中加入下面代码:

[cpp]  view plain  copy
 
  1. #ifdef __cplusplus  
  2. extern "C" {  
  3. #endif  
  4.   
  5. void _init(void){}  
  6.   
  7. #ifdef __cplusplus  
  8. }  
  9. #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,如下图:

         clip_image090

5.5、使用UPX加壳的SO,在eclipse中启动Android程序时出现”Fatal signal…”错误,如图:

         clip_image092

         分析:此错误是因为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壳特征字符串,    如下图所示:

         UPX对Android上ELF加壳使用过程中的若干问题总结_第1张图片

         5.5.3、在UPX源码中查找这些特征字符串(建议使用Search and Replace),并一一删除,      如下图:

         UPX对Android上ELF加壳使用过程中的若干问题总结_第2张图片

         5.5.4、重新编译UPX(参考“创建加固环境”章节)

你可能感兴趣的:(android安全,SO安全)