Android加固little总结

Android软件加固概述

从2012年开始,移动互联网进入快速发展阶段,Android App开发热潮的兴起,也推动了Android平台软件保护技术的发展。

  • 为何做加固
  1. 保护核心代码
  2. 防止营销作弊的手段
  3. 防止代码被篡改 …

加固代际

根据不同的理解,现在加固代际基本上可以按照五代或者三代去区分。

第一代:动态加载类

Apk中没有完整原始的Dex,需要运行时动态的加载到内存中

原理
  • 落地加载
    我们拿到需要加密的Apk和自己的壳程序Apk,然后用加密算法对源Apk进行加密再将壳Apk进行合并得到新的Dex文件,最后替换壳程序中的dex文件即可,得到新的Apk,那么这个新的Apk我们也叫作脱壳程序Apk.他已经不是一个完整意义上的Apk程序了,他的主要工作是:负责解密源Apk.然后加载Apk,让其正常运行起来。运行时首先将我们的Dex文件或者Apk文件解密,然后利用DexClassLoader加载器将其加载进内存中,然后利用反射加载待加固的Apk的Appkication,然后运行待加固程序即可。
    file
    file

  • 不落地加载
    落地加载将Dex文件解密出来会保存到文件中,再通过DexClassLoader加载进内存中,而不落地加载直接重写DexClassLoader使其可以直接加载字节数组,避免写入文件中。我们要做的是重写DexClassLoader,而这涉及到三个函数defineClass、findClass、loadClass,在一个类被加载的时候,会先后调用这三个函数加载一个类,所以我们需要重写这三个函数。系统的DexClassLoader加载Dex进入内存的也必然是通过字节加载的,而在系统so中的libdvm.so中的openDexFile可以直接加载Dex文件,那么现在清楚了,我们可以通过编写so文件调用openDexFile函数加载Dex字节数组,值得注意的是,openDexFile函数返回值为一个int类型的cookie,可以简单理解成一个dex文件的’身份码’,通过该’身份码’即可操控这个dex文件,至于怎么调用该函数,可以通过dlopen和dlsym函数调用。

file

优劣
  • 优点
    比较容易实现,无明显的兼容性问题 能有效对抗静态分析和二次打包

  • 缺点
    启动时需要进行大量的解密运算,容易造成卡死的情况 在内存中的数据为完整的Dex,通过动态调试Dump内存即可获取完整的Dex

特点

file
Dex字符串加密 资源加密 对抗反编译 对抗调试 Dex动态加载 so加密

第二代:函数抽取类

原理

主要分为两个步骤指令抽取和指令还原

  • 指令抽取
    解析原始Dex文件格式,保存所有方法的代码结构体信息,通过传入需要置空指令的方法和类名,检索到其代码结构体信息。通过方法的代码结构体信息获取指令个数和偏移地址,构造空指令集,然后覆盖原始指令,重新计算dex文件的checksum和signature信息,回写到头部信息中。

file

file

  • 指令还原
    native层hook系统函数dexFindClass,获取类结构体信息(dexFindClass函数用于查找类的DexClassDef结构),获取类中所有的方法信息,通过指定方法名进行过滤,获取该方法的代码结构体信息,获取该方法被抽取的指令集,修改方法对应的内存地址为可读属性,直接进行指令还原。
优劣
  • 优点
    加密粒度变小,加密技术从Dex文件级变为方法级 按需解密,解密操作延迟到某类方法被执行前,如果方法不被执行,则不被解密 解密后的代码在内存不连续,克服了内存被Dump的缺点,有效保护了移动客户端的Java代码

  • 缺点
    使用大量的虚拟机内部结构,会出现兼容性问题,无法保护所有方法 无法对抗自定义虚拟机 它跟虚拟机的JIT优化出现冲突,达不到最佳的性能表现

特点

file

除一代有的特点外 内存中无完整、连续的Dex so代码混淆、膨胀

第三代:VMP、Dex2C类

原理
  • VMP
    执行到关键代码时进入壳so执行,关于这一点,不同的厂商有着不同的做法,比如把关键函数变成native函数,在壳so中动态或者静态注册

file

再比如更改关键方法的方法体

file

无论哪种方法其实都是为了能让壳函数代替原函数去执行 当执行该函数的指令时,解析出指令的OpCode,通过一个巨大的switch case找到处理对应OpCode的函数,然后执行

file

简单讲就是壳将原本的指令进行一次封装,将原本的指令转换为另一种表现形式

  • Dex2C
    首先也是将关键代码注册为native函数,主要借助于JNI反射技术,将Java层的方法全部反射为native层,增大分析难度。之后再通过混淆、字符串加密等操作生成so,最后将so进行加固保护。
优劣
  • 优点
    加固强度高,目前没有公开的脱壳工具 经过混淆加密后很难还原原函数

  • 缺点
    效率较低,启动、运行时都比较耗时稳定性、可控性差,容易产生崩溃

特点

file

除一、二代全部特点外 so代码虚拟化 对抗之前所有的脱壳方法

so加密

section加密
  • 原理
    将关键方法,存放在自定义的section中,通过解析每个section,将我们自定义的section进行加密。因为so在加载时会优先加载.init_array,所以将解密方法放在.init_array中,获取内存中各个section的起始地址和大小,将需要解密的section还原。
函数加密
  • 原理
    解析so,根据方法名找到指定的方法,将方法进行加密。加载so时,获取指定方法的地址,通过解密方法将指定方法解密。
特点

file

file

由于原本的指令已经被加密成其他的字节,IDA等静态分析工具中会出现大段无法识别的代码

各厂商特征

除此外还有很多大佬们可以自行总结

某梆

lib/libDexHelper.so、lib/libDexHelper-x86.so、

某加密

assets/ijiami.ajm、assets/ijiami.dat、assets/ijm_lib/libexec.so、assets/ijm_lib/libexecmain.so

某企鹅

lib/libshell-super.2019.so、lib/libshella-4.1.0.29.so

某数字

assets/libjiagu.so、assets/libjiagu_x86.so

某迦

lib/libxloader.so

assets/libvdog、assets/libvdog64、assets/libvdog-x86

某付盾

lib/libegis.so、lib/libegis-x86.so

脱壳工具

FRIDA-DEXDump

原理

通过Frida在内存中搜索dex\n035,因为Dex的头部都会存在一个dex\n035的模数,所以通过在内存中搜索dex\n035可以搜索到Dex文件。对于一些Dex它们被抹去了头部信息,对于这样的情况,FRIDA-DEXDump也提供了对应的方法,通过遍历当前进程中所有可以读的内存段,通过判断这个段的大小和Dex文件中一些关键区域的关系可以判断是否为一个Dex。

使用

在FRIDA-DEXDumpGitHub中下载代码到本地或者通过pip3 install frida-dexdump 安装

file

用法就是首先打开,我们需要脱壳的软件,然后执行python main.py -d程序执行开始检索内存中的Dex

file

检索到后会保存在SavePath对应的目录下

也可以通过python main.py -h查看它的其他使用方法

file

最终得到它脱出来的Dex,可以看下它脱壳效果

file

Youpk

原理

从ClassLinker中遍历所有DexFile对象,在虚拟机中Dex文件都用DexFile对象来表示,并Dump出所有Dex文件。此时只是整体Dump,Dex中的方法还未还原。遍历DexFile中的ClassDef结构,获取到所有Class,主动调用Class中的所有的方法,让程序强制走switch解释器执行,在解释器中添加Hook代码,当方法执行时自动保存CodeItem。根据保存的CodeItem和Dump下来的Dex进行合并,还原Dex中被抽取的指令。

使用

首先下载刷机包和还原工具,目前仅支持刷pixel 1手机

file

解压相关的镜像,fastboot flash xxx /Download/xxx.img依次刷入

file

配置待脱壳的App包名adb shell "echo com.xxx >> /data/local/tmp/unpacker.config"

启动Apk等待脱壳,每隔10秒将自动重新脱壳(已完全dump的dex将被忽略), 当日志打印unpack end时脱壳完成

dump文件路径为/data/data/包名/unpacker,使用adb命令将文件pull出

file

使用dexfixer.jar修复Dex,java -jar dexfixer.jar /path/unpacker /path/output

最后我们对比一下还原前后的代码

还原前

file

还原后

file

总结

本文简单地总结了一下Android加固的背景和发展历史,也介绍了一些目前常见的脱壳工具。对于so加密的情况,目前也有许多方法应对,比如ida动态调试dump内存中的so,GG模拟器dump内存,frida dump so,unidbg等等。对于混淆的so,也有jnitrace,unidbg,还有hluwa大佬的大作obpo等工具辅助我们分析。除此以外还有还有一些优秀的脱壳工具如Fart等,我也没有再做介绍了。总之感谢这些大佬们的努力和开源,没有你们就没有白嫖的我们,哈哈…

猜你喜欢

转载自blog.csdn.net/u010671061/article/details/134454805
今日推荐