1、Frida技术原理python
Android脱壳的目的是从内存中dump下解密的应用dex文件,为了实现这个目的咱们须要知道dex文件在内存中dex地址与dex文件大小。Android系统的libart.so库文件中提供了一个导出的OpenMemory函数用来加载dex文件。linux
这个函数的第一个参数指向了内存中的dex文件,若是咱们能够Hook 这个函数,就能够获得dex文件加载进内存时的起始地址,再根据dex文件格式计算获得文件头保存的dex文件的长度fileSize。android
2、获取函数签名git
在编写Frida脚本以前咱们须要在libart.so文件中找到OpenMemory的函数签名,这个签名根据android版本或者架构的不一样会有些许差别,下面介绍如何从运行待脱壳应用的设备中提取libart.so文件:github
$ adb pull /system/lib/libart.so /本地目录 $ adb pull /system/lib64/libart.so /本地目录
获取libart.so文件后有两个方法能够得到函数签名,第一种是利用IDA pro 分析so文件,搜索OpenMemory函数:安全
第二种方法实在linux系统下使用nm命令直接查看libart.so文件的函数签名:bash
$ nm libart.so | grep OpenMemory
3、编写脚本架构
Frida能够执行js脚本也能够执行python脚本:app
· JS脚本:ide
· Python脚本:
代码参考 https://github.com/dstmath/frida-unpack
4、准备Frida 环境
安装 frida客户端与服务端,建议使用Python的pip命令安装frida客户端:
$ pip install frida $ pip install frida-tools
下载完毕后查看下载的客户端版本:
$ frida –version
客户端与服务端都下载完毕后,先把frida-server推送到设备中:
$ adb push frida-server /data/local/tmp
设置frida-server的权限并运行:
$ su # cd /data/local/tmp # chmod 777 frida-server # ./frida-server
若是运行失败,能够尝试关闭android系统的SELinux:
# setenforce 0
咱们打开另外一个控制台,运行客户端命令查看与服务端的交互:
$ frida-ps -U
出现如下信息,则说明交互成功:
5、执行脱壳脚本
咱们先将一个简单的测试程序丢到腾讯乐固上去加固,咱们能够看到加固完成后的结果:
能够看到加固事后程序的本来代码被隐藏了,被替换成乐固的壳程序代码,将加固后的应用安装到手机上,赋予该应用读写sd卡权限:
在sd卡中建立unpack目录,执行命令运行JS脚本:
$ frida -U -f <被脱壳应用的包名> -l <js脚本名> –no-pause
-U参数表示咱们使用了USB server进行连接,-f 参数表示在设备中启动一个指定的android程序,须要配合 –no-pause参数来使进程恢复。-l参数表示须要注入的js脚本。
Python脚本的运行就简单得多了:
$ python unpack.py <应用包名>
另外注意一个问题,若是应用运行过程当中使用了64位的libart.so,脚本的这个地方须要进行一些小修改:
//dex起始位置 var begin = args[1]
获取dex起始位置的语句须要改为:
var begin = this.context.x0
否则可能会出现这样的问题:
脱壳完成后从sd卡中将unpack文件夹pull到本地:
$ adb pull /sdcard/unpack .
能够看到脱壳成功了。因为这一类脱壳法是将内存中的dex文件直接dump下来的,对于指令抽取等针对方法体进行处理的加固方式并无作对应的修复工做。若是应用通过了指令抽取或者dex2c处理,这种方法拿到的dex文件就是残缺不全的,对于那些加固就须要经过对Android源码进行修改的脱壳方法好比dexhunter或者是比较新的FART脱壳机。
做者简介:叶绍琛,Unix/Linux/Android操做系统内核技术专家,大中华区前50位RHCA系统架构师,曾任网易互娱云计算平台技术负责人。
《Android安全指南》系列文章,未完待续。