Frida使用

基础语法

API名称描述
Java.use(className)获取指定的Java类并使其在JavaScript代码中可用。
Java.perform(callback)确保回调函数在Java的主线程上执行。
Java.choose(className, callbacks)枚举指定类的所有实例。
Java.cast(obj, cls)将一个Java对象转换成另一个Java类的实例。
Java.enumerateLoadedClasses(callbacks)枚举进程中已经加载的所有Java类。
Java.enumerateClassLoaders(callbacks)枚举进程中存在的所有Java类加载器。
Java.enumerateMethods(targetClassMethod)枚举指定类的所有方法。
日志方法描述区别
console.log()使用JavaScript直接进行日志打印多用于在CLI模式中,console.log()直接输出到命令行界面,使用户可以实时查看。在RPC模式中,console.log()同样输出在命令行,但可能被Python脚本的输出内容掩盖。
send()Frida的专有方法,用于发送数据或日志到外部Python脚本多用于RPC模式中,它允许JavaScript脚本发送数据到Python脚本,Python脚本可以进一步处理或记录这些数据

基本使用

列出运行的APP:frida-ps -Ua

列表所有的APP:frida-ps -Uai

查看进程:frida-ps -U

杀死进程:frida-kill -U 包名

检测frida端口

解决:端口转发

1.移动端frida-server自定义端口启动./frida-server -l 0.0.0.0:6666

2.端口转发到本地adb forward tcp:6666 tcp:6666

3.通过frida命令行执行脚本frida -H 127.0.0.1:6666 packageName(包名) -l xxx.js

4.python脚本中使用自定义端口进行连接

#-*- coding: utf-8 -*-

import frida
import sys

PACKAGE = 'com.xxx.xxx.xxx'
HOST = '127.0.0.1:6666'

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

if __name__ == '__main__':
    try:
        manager = frida.get_device_manager()
        device = manager.add_remote_device(HOST)
        jscode = open('script.js','r',encoding='UTF-8').read()
        pid = device.spawn([PACKAGE])
        session = device.attach(pid)

        script = session.create_script(jscode)
        script.on('message',on_message)
        script.load()
        device.resume(pid)

        sys.stdin.read()
    except Exception as e:
        print('frida hook error')

启动脚本

常用命令:frida -U -l myhook.js -f com.xxx.xxxx --no-paus

  • -U 指定对USB设备操作
  • -l 指定加载一个Javascript脚本
  • -f 指定一个进程,重启它并注入脚本,不加-f则不会重启
  • –no-pause 自动运行程序

脚本编写

关键词解析

  1. Java.use():该方法用于获取 Java 类对象,以便于在 JavaScript 中对其进行操作。例如:Java.use(‘java.util.ArrayList’) 会返回访问和修改该类的属性和方法。
  2. Java.perform():该方法用于在 Frida 的 JavaScript 环境中执行代码块。这个代码块中可以包含对 Java 类的修改、Hook 方法的实现等操作。
  3. implementation:属性:用于指定要 Hook 的方法的新实现。通过设置可以在方法执行前后添加自定义的逻辑。
  4. this和arguments:在自定义的方法实现中,可以使用this 关键字表示原始方法的调用和属性访问。

变量类型区别

Hook

启动main

function main() {
    Java.perform(function () {
        demo()
    })
}
setImmediate(main)

打印堆栈信息

在上面的hook方法中通过特定的参数进行判断,并添加下面的代码,来打印堆栈然后再进行分析。

function showStacks() {
    Java.perform(function () {
        console.log(Java.use("android.util.Log").getStackTraceString(
            Java.use("java.lang.Throwable").$new()
        ));
    })
}

showStacks()

Python调用

使用Python注入Frida主要有以下几种模式:

  1. Spawn 模式:在目标设备上启动一个新的应用程序进程,并在该进程中运行Frida脚本。这种模式非常适用于对未安装的应用程序进行注入。
  2. Attach 模式:在目标设备上附加到已经运行的应用程序进程,并在该进程中运行Frida脚本。这种模式非常适用于对已经运行的应用程序进行调试和分析。
  3. USB 模式:将目标设备通过USB连接到计算机上,并使用Frida通过USB进行通信。这种模式比较适用于对物理上可访问的设备进行注入,但需要确保设备已经打开了USB调试模式。
  4. Remote 模式:在远程设备上运行Frida,并使用Frida提供的远程API进行通信。这种模式适用于需要对无法直接访问的设备进行注入,例如云服务器、虚拟机等。在使用Python注入Frida时,需要根据具体的情况选择合适的注入模式

代码样例

监听脚本

其实就是获取到脚本输出的内容。

hook代码中添加send,python代码中添加script.on

import frida


def on_message(message, data):
    if message['type'] == 'send':
        print("[*] {0}".format(message['payload']))
    else:
        print(message)


js_code = '''
Java.perform(function () {
    var Utils = Java.use(包名.类名);
    // 应用 hook 函数到静态方法
    Utils.方法名.implementation = function () {
        // 调用原始方法
        var result = this.方法名(方法参数);
        send("11111");
        return result;
    }
})
'''

device = frida.get_usb_device()
session = device.attach("包名")
script = session.create_script(js_code)
script.on('message', on_message)
script.load()
sys.stdin.read()

上一篇
下一篇