墨锋
Published on 2025-03-29 / 6 Visits
0
0

[翻译]FRIDA官方文档-示例-Android

Android

CTF 竞赛工具示例

本示例推荐使用 Android 4.4 x86 模拟器镜像,基于 SECCON Quals CTF 2015 的 APK1 题目实现(APK 下载)。

保存为 ctf.py 后执行 python ctf.py

 import frida, sys
 ​
 def on_message(message, data):
     if message['type'] == 'send':
         print("[*] {0}".format(message['payload']))
     else:
         print(message)
 ​
 jscode = """
 Java.perform(() => {
   // 定义要挂钩的类
   const MainActivity = Java.use('com.example.seccon2015.rock_paper_scissors.MainActivity');
 ​
   // 挂钩按钮点击事件
   const onClick = MainActivity.onClick;
   onClick.implementation = function (v) {
     // 显示函数调用通知
     send('onClick 被触发');
 ​
     // 先执行原始 onClick 处理逻辑
     onClick.call(this, v);
 ​
     // 修改关键字段值
     this.m.value = 0;  // 注意必须使用 .value 访问字段
     this.n.value = 1;
     this.cnt.value = 999;
 ​
     // 输出日志提示获取flag
     console.log('操作完成:' + JSON.stringify(this.cnt));
   };
 });
 """
 ​
 process = frida.get_usb_device().attach('com.example.seccon2015.rock_paper_scissors')
 script = process.create_script(jscode)
 script.on('message', on_message)
 print('[*] 正在运行CTF破解工具')
 script.load()
 sys.stdin.read()

重要说明:必须使用 this.m.value = 0 而非 this.m = 0 来修改字段值。若类中存在同名方法 m(),则需改用 this._m.value = 0。在访问对象属性时,通常需要通过 .value 获取实际值。

Java 桥接功能示例

Frida 的 Java 桥接功能可实现以下操作:

 Java.perform(() => {
   // 创建并初始化 String 对象
   const JavaString = Java.use('java.lang.String');
   const exampleString1 = JavaString.$new('Java 环境中的示例字符串');
   console.log('[+] 字符串内容: ' + exampleString1);
   console.log('[+] 字符串长度: ' + exampleString1.length());
 ​
   // 获取默认字符集并转换字符串
   const Charset = Java.use('java.nio.charset.Charset');
   const charset = Charset.defaultCharset();
   // 将 JS 字符串转为字节数组
   const charArray = '待转换的JavaScript字符串'.split('').map(c => c.charCodeAt(0));
 ​
   // 通过重载构造器创建 String 对象
   const exampleString2 = JavaString.$new.overload('[B', 'java.nio.charset.Charset')
     .call(JavaString, charArray, charset);
   console.log('[+] 转换结果: ' + exampleString2);
 ​
   // 挂钩 StringBuilder 构造器
   const StringBuilder = Java.use('java.lang.StringBuilder');
   const ctor = StringBuilder.$init.overload('java.lang.String');
   ctor.implementation = function (arg) {
     const result = ctor.call(this, arg);
     const partial = arg ? arg.toString().slice(0, 10) : '';
     console.log('新建 StringBuilder: "' + partial + '"');
     return result;
   };
 ​
   // 挂钩 toString 方法
   StringBuilder.toString.implementation = function () {
     const result = this.toString();
     console.log('StringBuilder 内容预览: ' + result.slice(0, 10));
     return result;
   };
 });

堆栈追踪示例

 Java.perform(() => {
   const Cipher = Java.use('javax.crypto.Cipher');
   const Exception = Java.use('java.lang.Exception');
   const Log = Java.use('android.util.Log');
 ​
   // 挂钩 Cipher.init() 方法
   Cipher.init.overload('int', 'java.security.Key').implementation = function (opmode, key) {
     const result = this.init(opmode, key);
     console.log('加密模式:', opmode, '密钥:', key);
     // 打印当前调用堆栈
     console.log(Log.getStackTraceString(Exception.$new()));
     return result;
   };
 });

关键术语说明:

  1. Java.perform - Frida 的 Java 环境执行上下文

  2. implementation - 方法挂钩的实现体

  3. overload - 处理 Java 方法重载

  4. $new - 实例化 Java 对象

  5. getStackTraceString - 获取异常堆栈信息


原文链接:Android | Frida • A world-class dynamic instrumentation toolkit

翻译来源:DeepSeek


Comment