9

Frida实战hook学习笔记

 4 years ago
source link: https://shingle.me/post/frida%E5%AE%9E%E6%88%98hook%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Frida实战hook学习笔记

2019-09-05 12:38:53 约 961 字 预计阅读 2 分钟 1298 次阅读

动态hook神器

电脑上安装好 frida 环境后,在 github 上 https://github.com/frida/frida/releases 下载你手机对应架构的frida-server ,解压然后

adb push frida-server-12.6.21-android-arm64 /data/local/tmp/

手机连接电脑,利用 adb shell 运行该服务

adb shell
cd /data/local/tmp/
chmod 755 frida-server-12.6.21-android-arm64
./frida-server-12.6.21-android-arm64

此时如果没有报错,手机上的frida-server就算启动了

接着再把frida-server的端口转发到电脑

adb forward tcp:27042 tcp:27042

编写 hook 代码

以下使用的 python 环境来运行 frida,记录了使用 frida 的学习过程,可能会不定期更新

目录结构:

hook.py

intent.js

入口代码:

import frida
import sys
import os

packageName = "com.xxx.xxx"

def messagesCallback(message, data):
    if message['type'] == 'send':
        print(message['payload'])
    elif message['type'] == 'error':
        print(message['stack'])

hookCode = None
with open(os.path.dirname(os.path.realpath(__file__)) + '/intent.js') as f:
    hookCode = f.read()

process = frida.get_remote_device().attach(packageName)
print(process)
process.enable_debugger()
script = process.create_script(hookCode)
script.on('message', messagesCallback)
script.load()
sys.stdin.read()

其中packageName是你要 hook 的 app 包名

intent.js是用 js编写的 hook 代码,注意这个是文件路径。我自己是用读取hook代码文件的方式,这样就不必把 js 代码混在 python 里,比较清晰明了。

先来写一个简单的 hook, 用来读取 intent 的传值

Java.perform(function () {
    var act = Java.use("android.app.Activity");
    var process = Java.use("android.os.Process");

    act.getIntent.overload().implementation = function () {

        send("act:" + this.getIntent().getExtras());
        return this.getIntent();

    };

    process.start.overload('java.lang.String', 'java.lang.String', 'int', 'int', '[I', 'int', 'int', 'int', 'java.lang.String', 'java.lang.String', 'java.lang.String', 'java.lang.String', 'java.lang.String', '[Ljava.lang.String;').implementation = function (a, b, c, d, e, f, g, h, j, k, l, m, n, o) {
        var id = 5;
        var flags = arguments[id];
        send("before arg:" + flags);
        arguments[5] = 1;
        send("after arg:" + arguments[id]);

        return this.start(a, b, c, d, e, f, g, h, j, k, l, m, n, o);
    };

})
  • Java.use用来寻找要 hook 的类

  • act.getIntent.overload().implementation = function () {}是重写该hook类的 getIntent()方法

  • 如果要 hook 的方法带参数,需要在overload里传对应类型

function传自定义的参数名字. 例如上面例子里的process.start.overload

或者可以不写 overload,但是function里面的参数个数需要和 hook 的函数一样

  process.start.implementation = function (a, b, c, d, e, f, g, h, j, k, l, m, n, o) {}
  • 参数为基本类型可以简写,比如byte -> B, int -> I, boolean -> Z

对于数组类型,要添加前缀[,例如int[] -> [I, String[] -> [Ljava.lang.String

  • 获取 hook 回调里对象的普通field 字段值
  this.myField.value

如果字段名字和函数名重复,需要加_访问

  class Test{
   public int a;
   public void a(){
   	return 0;
   }
  }
  this._a.value
  • 获取 hook 回调里对象的Map类型 field 字段值

https://github.com/frida/frida/issues/488

  var HashMapNode = Java.use('java.util.HashMap$Node');
  
  var iterator = this.myMap.value.entrySet().iterator();
  while (iterator.hasNext()) {
    var entry = Java.cast(iterator.next(), HashMapNode);
    console.log(entry.getKey());
    console.log(entry.getValue());
  }
  • 打印一个类的方法和字段

https://github.com/frida/frida-java-bridge/issues/44

  
  function describeJavaClass(className) {
      var jClass = Java.use(className);
      console.log(JSON.stringify({
          _name: className,
          _methods: Object.getOwnPropertyNames(jClass.__proto__).filter(function (m) {
              return !m.startsWith('$') // filter out Frida related special properties
                  || m == 'class' || m == 'constructor' // optional
          }),
          _fields: jClass.class.getFields().map(function (f) {
              return f.toString()
          })
      }, null, 2));
  }
  • 构造一个对象
  var array_list = Java.use("java.util.ArrayList");
  var k = array_list.$new();
  var hookCls = Java.use("java.util.Map");
  var map = Java.cast(obj,hookCls)

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK