前言

本文仅供学习探讨之用,如果侵犯您的权益请联系我删除。

前几天研究某APP未果,中间稍微研究了一些Frida的RPC机制,做一下笔记。

Frida RPC简介

Frida RPC可以将APP中的函数暴露给加载器,方便在外部调用,相比于recvsend,使用起来更加方便。

示例hook脚本

rpc.exports = {
  add(a, b) {   //同步函数
    return a + b;
  },
  sub(a, b) {   //异步函数
    return new Promise(resolve => {
      setTimeout(() => {
        resolve(a - b);
      }, 100);
    });
  }
};

示例Python加载器

import codecs
import frida

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

session = frida.attach('iTunes')
with codecs.open('./agent.js', 'r', 'utf-8') as f:
    source = f.read()
script = session.create_script(source)
script.on('message', on_message)
script.load()
#调用rpc暴露出来的add和sub方法
print(script.exports.add(2, 3))
print(script.exports.sub(5, 3))
session.detach()

Frida RPC使用演示

Java层

Java函数的Hook又分为静态方法和实例方法,静态类直接用Java.use('类名')获取以后直接就可以调用,而实例方法需要先用Java.choose('类名'),在堆中查找到类的实例以后获取该实例,才能调用。

  • 静态方法
    静态方法

  • 实例方法
    实例方法

So层

SO层如果是静态方法也跟Java层的类似,只不过需要获取上下文对象,并作为第一个参数传入。

  • JNI方法

    JNI方法

演示代码

  • Hook代码
console.log("脚本载入成功");
Java.perform(function () {
    rpc.exports = {
        staticmethod() {
            var n1 = Java.use('com.max.xiaoheihe.utils.n1');
            return n1.E();
        },
        classmethod() {
            var result = undefined;
            Java.choose('com.max.xiaoheihe.bean.account.AccountDetailObj', {
                onMatch: function (instance) {
                    result = instance.getUserid();
                }, onComplete: function () {
                    if (result === undefined) {
                        return 'not found';
                    }
                }
            });
            return result;
        },
        jnimethod(urlpath, timestamp, nonce) {
            var currentApp = Java.use('android.app.ActivityThread').currentApplication();
            var context = currentApp.getApplicationContext();
            var NDKTools = Java.use('com.max.xiaoheihe.utils.NDKTools');
            return NDKTools.encode(context, urlpath, timestamp, nonce);
        },
    };
});
  • 加载器
import frida
device = frida.get_usb_device()
process = device.attach('小黑盒')
with open('demo.js', 'r', encoding='utf-8') as f:
    script = process.create_script(js.read())
script.load()

print('static method: ', script.exports.staticmethod())
print('class method: ', script.exports.classmethod())
print('jni method: ', script.exports.jnimethod(
    '/app/link/tree/', '1637135684', '00000000000000000000000000000000'))

运行结果如下:

运行结果

最后修改:2021 年 11 月 19 日
Null