Frida 学习之路

2018年12月20日 · 1093 字 · 3 分钟 · Android Frida

Frida 简介

贴一段官方介绍

It’s Greasemonkey for native apps, or, put in more technical terms, it’s a dynamic code instrumentation toolkit. It lets you inject snippets of JavaScript or your own library into native apps on Windows, macOS, GNU/Linux, iOS, Android, and QNX. Frida also provides you with some simple tools built on top of the Frida API. These can be used as-is, tweaked to your needs, or serve as examples of how to use the API.

frida 是一款基于 python + javascript 的 hook 框架,可运行在 android、iOS、linux、win、osx 等各平台,主要使用动态二进制插桩技术。

安装环境

pip install frida frida-tools

然后去官网下载对应版本的手机端程序 frida-server:https://github.com/frida/frida/releases

注意这里一定要把 frida-server 版本和上面 PC 端安装的 frida 版本一致,我是用的是frida-server-12.2.27-android-arm64

# 下载完成之后记得先解压
xz -d frida-server-12.2.27-android-arm64.xz

# push 到手机上
adb push frida-server-12.2.27-android-arm64 /data/local/tmp/frida-server

开发流程

1. 启动 server

# 启动服务端
adb shell "chmod 755 /data/local/tmp/frida-server"
adb shell "su -c '/data/local/tmp/frida-server &'"

# 端口转发
adb forward tcp:27042 tcp:27042
adb forward tcp:27043 tcp:27043

# 查看 frida-server 是否启动成功,执行下面命令之后出现进程列表则表明启动成功
frida-ps -U

# 重启 frida
ps | grep frida
su kill -9 fridapid
./frida &

2. 编写 py 脚本

# 这是一个查看当前 app 的脚本
import frida

rdev = frida.get_remote_device()
front_app = rdev.get_frontmost_application()
print front_app

3. 运行脚本

python xxx.py

开发经验

1. Java 层 Hook 操作

Hook 之前 我们需要先了解一下 JavaApi

Java.perform(function () {});

// obtain a Javascript obj capable of handling interactions with each class
var myClass = Java.use(com.mypackage.name.class);

// Create a new instance of a class
var myClassInstance = myClass.$new();

// Access methods and attributes of the class
var result = myClassInstance.myMethod("param");

// overwrite the implementation of a method
myClass.myMethod.implementation = function (param) {};

Hook 的操作主要包括以下几点:

1、hook 方法包括构造方法和对象方法,构造方法固定写法是$init,普通方法直接是方法名,参数可以自己定义也可以使用系统隐含的变量 arguments 获取。

// hook 构造方法
myClass.$init.overload().implementation = function () {
  send("arguments: " + arguments);
};

// hook 普通方法
myClass.myMethod.overload().implementation = function () {};

2、修改方法的参数和返回值,直接调用原始方法通过传入想要修改的参数来做到修改参数的目的,以及修改返回值即可。

myClass.myMethod.overload("java.lang.String").implementation = function () {
  return this.myMethod("test") + "test";
};

3、构造对象和修改对象的属性值,直接用反射进行操作,构造对象用固定写法的 $new 即可。

// 构造对象
var myClassInstance = myClass.$new();

// 修改对象字段
val name = Java.cast(myClass.getClass(), clazz).getDeclaredField("name");
name.setAccessible(true);
name.get(myClass);
name.set(myClass, "new_name");

4、打印堆栈信息

var threadef = Java.use("java.lang.Thread");
var threadinstance = threadef.$new();
var stack = threadinstance.currentThread().getStackTrace();
send("Full call stack:" + Where(stack));

2. Native 层 Hook 操作

因为目前我在逆向分析分析的 app 里大部分破解工作在 java 层就完成了,所以 native 层的 hook 我暂时还没有用到过,推荐看一下四哥的Android 逆向之旅—Hook 神器家族的 Frida 工具使用详解

工具

这部分其实主要是为了更方便找到 Hook Point

可以参考 Xposed 学习之路 中的工具相关部分

实例

推荐插件及项目

其他

Frida 与 Xposed 相比感觉比较适合破解分析的工作,而且对 native hook 支持的也比较好,但是不能独立运行,xposed 插件开发完毕之后可以一直运行在手机里。

目前还在探索阶段,后续继续完善更多技巧..

参考