最近在研究安卓平台的加壳技术,以前以为只有原生层的代码才可以加壳,看了看网上的资料,才发现原来Java层也可以加壳,虽然与传统的壳有些区别,但就最终的效果来说,反静态分析的目的还是达到了的。

目前安卓市场上的大多数apk的保护方式都是对Java层进行代码混淆,将关键数据放在原生层,再用传统加壳手段对so文件进行加壳,这种方式的缺陷是Java层的代码安全完全依赖于代码混淆,实际上只要熟悉smali语法,代码混淆的意义就没有想象的那么大,对于那些资深的C/C++逆向工程师来说,逆向smali可比在一堆汇编代码里面按图索骥轻松多了。

传统的PE文件是怎么加壳的

看雪对PE文件的壳解释的很详尽,就不多作阐述了,大致原理是对源PE文件加密或压缩后,将数据嵌入外壳程序里面,外壳程序执行后将源PE文件解密加载,然后跳到源PE文件的入口(OEP)执行。静态分析加壳的程序,就只能看到外壳程序和加密的源PE文件。如果要获得源PE文件(脱壳),就只能运行外壳,让其将源PE文件解密,然后找到OEP,将解密后的PE文件从内存里dump下来,重建输入表,生成脱壳后的PE文件。软件安全工程师可以在壳上采用反调试(Anti-debug)和复杂化控制流等技术来阻止破解者寻找OEP。

可以看出,一个传统的“壳”需要具备以下特点:

1、源程序压缩或加密后内嵌在外壳程序内部;

2、外壳程序先于源程序运行,对源程序解密;

3、解密后的数据必须存放在内存中;

4、源程序加载后要能正常运行;

最为关键的是第3点,需要明白的是,只要投入足够的时间,壳最终是肯定会被破解的,壳的意义实际上在于增加破解成本,尽可能地拖延破解时间,要做到这一点,就必须把与破解者的对抗的关键点放到分析外壳程序的解密逻辑的困难性上,如果破解者有办法绕过分析外壳程序的步骤,直接拿到解密后的源程序,那么这个壳就是无效的。解密后的数据如果留在了文件系统里,破解者就能直接获取到源程序。为什么要单独把这个问题提出来说呢,传统的壳加载源程序,只要解密过后,重定位到OEP就可以了,安卓加载可执行文件却需要使用类加载器DexClassLoader,原型如下:

public DexClassLoader (String dexPath, String optimizedDirectory, String libraryPath, ClassLoader loader)

其中第一个参数dexPath是代表的一个路径,也就是说,DexClassLoader只能加载存放在文件系统里的可执行文件。问题就出来了,刚刚说,我们不能把解密后的源程序放在文件系统上,但是要用DexClassLoader 加载安卓可执行文件dex的话就必须先把它存放在文件系统上,这是对Dex文件进行加壳最大的难点。

为了解决这个问题,我想到了两个办法,第一个办法是减少暴露在文件系统里的时间,在DexClassLoader装载完源程序后,立即将其从文件系统中删除,这样破解者就必须动态调试,在源程序被删除之前断下来才能获得源程序。但是这种办法还是很不安全,我们需要一种彻底不在文件系统留下任何痕迹的方法。先回过头来看DexClassLoader,它虽然只提供路径作为参数,但其加载过程最终肯定有一个步骤是将文件转化成输入流,然后映射到内存,也就是说,DexClassLoader 最终还是要从内存中加载源程序。在网上查了资料,最终在http://www.strazzere.com/papers/DexEducation-PracticingSafeDex.pdf里找到了答案,原来安卓4.0以下的版本确实不支持内存加载Dex,4.0以上的版本实际上是提供了一个以byte数组为参数的接口openDexFile来从内存中加载类的,只不过这个接口并没有开放给SDK,因此需要利用Java反射机制来调用。细节等以后再说,本篇文章先讲讲怎么实现第一种方法。

将源APK嵌入外壳Dex中

我们知道Apk是安卓的安装包,本质是一个zip,需要安装后才能运行,APK里面的classes.dex才是真正的可执行文件,为什么要嵌入APK而不是classes.dex呢?因为classes.dex里并不包含资源文件,如果只加载classes.dex的话,运行后是没有任何资源的。

具体内嵌APK的方法参考了这篇博客:http://blog.csdn.net/androidsecurity/article/details/8678399。博主的做法是将APK加密后,添加到外壳的classes.dex尾部,然后加上APK的文件长度,最后修改classes.dex的dex文件头。这部分很简单,博主也提供了源代码,所以就不阐述了。

需要一提的是,如果把内嵌了源APK的外壳classes.dex直接放入外壳APK中,放进手机安装的话会出错,原因是这样破坏了APK签名,需要把外壳APK中的META-INF文件夹删掉,然后用signapk.jar重新签名,我的signapk.jar的下载地址如下:http://www.uzzf.com/soft/60860.html

在外壳中剥离源APK

外壳程序运行后,通过getApplicationInfo().sourceDir就能获取到外壳自身的APK地址,将其以文件形式打开后,输入到一个ZipInputStream流里,然后遍历zip找到classes.dex,将其输入到一个byte数组,利用byte数组的长度-4得到内嵌的源APK文件的长度,最后调用System.arraycopy将源apk拷贝出来,解密后,输出到文件系统里就可以了。读取壳自身apk的代码如下:

         ByteArrayOutputStream dexByteArrayOutputStream = new ByteArrayOutputStream();
ZipInputStream localZipInputStream = new ZipInputStream(
new BufferedInputStream(new FileInputStream(
this.getApplicationInfo().sourceDir)));

利用DexClassLoader动态加载源APK

安卓是允许在不安装apk的情况下调用apk的可执行文件的,要实现这个,就得利用DexClassLoader,这是安卓专用的类加载器,它以APK路径作为参数,找到APK中的classes.dex文件,将里面的类加载进来,这样我们就可以调用源APK中的代码了。需要注意的是,直接用DexClassLoader加载进来的安卓组件类是死的,不具有生命周期,跟普通的类没有区别,也就是说我们不能直接像普通调用安卓组件的方式去调用DexClassLoader加载进来的组件。网上找了一会儿,在http://blog.csdn.net/singwhatiwanna/article/details/22597587上找到了一种解决办法,该博主是将源APK中的组件与调用APK的组件的生命周期绑定在一起,相当于将源APK的生命周期模拟了出来,这种调用技术可用于实现APK插件化,但是存在很多限制,最有效的解决方案其实是360提出的Proxy/Delegate框架:http://blogs.360.cn/blog/proxydelegate-application/这种解决方案是将调用APK的Application动态替换为源APK的Application(Proxy与Delegate),将其运用在Dex文件加壳上的话,这样就相当于替换了应用程序运行环境,运行中的外壳就完全变成了源程序,这时候只要调用源程序的Application.onCreate(),源程序就启动了。此外,需要在源程序的Application.onCreate()里加入启动MainActivity的代码,否则MainActivity是不会主动启动的。

未完待续……

安卓Dex壳技术探讨(1)的更多相关文章

  1. 安卓 dex 通用脱壳技术研究(一)

    注:以下4篇博文中,部分图片引用自DexHunter作者zyqqyz在slide.pptx中的图片,版本归原作者所有: 0x01 背景介绍 安卓 APP 的保护一般分为下列几个方面: JAVA/C代码 ...

  2. 【腾讯Bugly干货分享】Android Linker 与 SO 加壳技术

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57e3a3bc42eb88da6d4be143 作者:王赛 1. 前言 Andr ...

  3. AndroidLinker与SO加壳技术之上篇

    1. 前言 Android 系统安全愈发重要,像传统pc安全的可执行文件加固一样,应用加固是Android系统安全中非常重要的一环.目前Android 应用加固可以分为dex加固和Native加固,N ...

  4. android apk 防止反编译技术第一篇-加壳技术

    做android framework方面的工作将近三年的时间了,现在公司让做一下android apk安全方面的研究,于是最近就在网上找大量的资料来学习.现在将最近学习成果做一下整理总结.学习的这些成 ...

  5. 七雄Q传封包辅助技术探讨回忆贴

    前言 网页游戏2013年左右最火的类型最烧钱游戏,当年的我也掉坑了.为了边玩还满足码农精神我奋力的学习如何来做外挂.2013年我工作的第二个年头.多一半…介绍下游戏<七雄Q传>是北京游戏谷 ...

  6. Android Linker 与 SO 加壳技术

    1. 前言 Android 系统安全愈发重要,像传统pc安全的可执行文件加固一样,应用加固是Android系统安全中非常重要的一环.目前Android 应用加固可以分为dex加固和Native加固,N ...

  7. AndroidLinker与SO加壳技术之下篇

    点此查看上篇<AndroidLinker与SO加壳技术之上篇> 2.4 链接 链接过程由 soinfo_link_image 函数完成,主要可以分为四个主要步骤: 1. 定位 dynami ...

  8. Oracle数据库容灾备份技术探讨

    Oracle数据库容灾备份技术探讨 三种Oracle灾备技术 对于Oracle数据库的灾备技术,我们可以从Data Guard,GoldenGate和CDP角度去考虑. Oracle Data Gua ...

  9. 新华三孟丹:NFV资源池实现中的技术探讨

    近日,在第三届未来网络发展大会SDN/NFV技术与应用创新分论坛上,新华三解决方案部架构师孟丹女士发表了主题为<NFV资源池实现中的技术探讨>的主题演讲. 孟丹指出,新华三的NFV核心理念 ...

随机推荐

  1. April 6 2017 Week 14 Thursday

    If you smile when no one else is around, you really mean it. 独处时的微笑,才是发自内心的. Recently I found I seld ...

  2. Makedown语法说明

    Markdown 语法说明 (简体中文版) / (点击查看快速入门) 概述 宗旨 兼容 HTML 特殊字符自动转换 区块元素 段落和换行 标题 区块引用 列表 代码区块 分隔线 区段元素 链接 强调 ...

  3. MySQL数据库实验二:单表查询

    实验二   单表查询 一.实验目的 理解SELECT语句的操作和基本使用方法. 二.实验环境 是MS SQL SERVER 2005的中文客户端. 三.实验示例 1.查询全体学生的姓名.学号.所在系. ...

  4. *204. Count Primes (siecing prime)

    Count the number of prime numbers less than a non-negative number, n. Example: Input: 10 Output: 4 E ...

  5. 自定义报告,用Java写一个html文件

    因为testng不满足我们的展示,所以我们会自己定义一个报告,实施步骤是,把静态页面做好后,放在Java项目中,其实和生成一个日志文件类似,只是该了后缀,Java中需要使用到PrintStream,案 ...

  6. 20145238-荆玉茗 《Java程序设计》第10周学习总结

    20145238 <Java程序设计>第10周学习总结 网络编程 ·网络编程就是在两个或两个以上的设备(例如计算机)之间传输数据.程序员所作的事情就是把数据发送到指定的位置,或者接收到指定 ...

  7. EF 集合版 增删查改

  8. Mysql常见的引擎

    常用的引擎是:Innodb和Myiasm这两种引擎: innodb: 提供了对事务的ACID操作,还提供了行级锁和外键约束,,他的优势就是处理大量数据,在msql启动的时候,首先会建立一个缓存池,主要 ...

  9. B3942 Censoring

    爆炸入口 有一个S串和一个T串,长度均小于1,000,000,设当前串为U串,然后从前往后枚举S串一个字符一个字符往U串里添加,若U串后缀为T,则去掉这个后缀继续流程. 这道题确乎是个很好的联系kmp ...

  10. machine learning trends from nips14

    from John Platt, Deputy Managing Director and Distinguished Scientist at Microsoft Research http://b ...