frida 与objectionfrida

  • 内容
  • 评论
  • 相关

objection可快速将apk注入frida.so无需繁琐的操作

安装
pip install objection
objection patchapk --source  1.apk

这里是mac,提示Unable to find aapt. Install it with: apt install aapt (Kali Linux) before continuing.

export PATH=$PATH:/Users/voidcat/Library/Android/sdk/build-tools/35.0.0

测试js

Java.perform(function() {
    try {
        // 获取当前Activity
        Java.choose("android.app.Activity", {
            onMatch: function(instance) {
                console.log("[*] 找到 Activity 实例");
                
                // 在主线程中执行
                Java.scheduleOnMainThread(function() {
                    // 创建 AlertDialog
                    var AlertDialogBuilder = Java.use("android.app.AlertDialog$Builder");
                    var builder = AlertDialogBuilder.$new(instance);
                    
                    // 创建 Java 字符串
                    var JavaString = Java.use("java.lang.String");
                    var title = JavaString.$new("Frida 测试");
                    var message = JavaString.$new("这是一个测试弹窗");
                    var positiveBtn = JavaString.$new("确定");
                    var negativeBtn = JavaString.$new("取消");
                    
                    // 设置弹窗属性
                    builder.setTitle(title);
                    builder.setMessage(message);
                    builder.setPositiveButton(positiveBtn, null);
                    builder.setNegativeButton(negativeBtn, null);
                    builder.show();
                    
                    console.log("[+] 弹窗已显示");
                });
            },
            onComplete: function() {
                console.log("[*] Activity 搜索完成");
            }
        });
        
    } catch(e) {
        console.log("错误: " + e.stack);
    }
});

直接运行的话会卡主界面,等待链接

我们先看下包名

frida-ps -Uai

然后运行,比如

frida -U -n RooketTrade -l show_dialog.js

设置脚本模式

创建配置文件 config.json

{
  "interaction": {
    "type": "script",
    "path": "libfrida-gadget.script.so"
  }
}

创建脚本文件 index.js

Java.perform(function() {
    try {
        console.log('[*] 脚本开始执行');
        setTimeout(function() {
            Java.choose('android.app.Activity', {
                onMatch: function(instance) {
                    console.log('[*] 找到 Activity 实例');
                    Java.scheduleOnMainThread(function() {
                        var AlertDialogBuilder = Java.use('android.app.AlertDialog$Builder');
                        var builder = AlertDialogBuilder.$new(instance);
                        var title = Java.use('java.lang.String').$new('Frida 测试');
                        var message = Java.use('java.lang.String').$new('这是一个测试弹窗');
                        builder.setTitle(title);
                        builder.setMessage(message);
                        builder.setPositiveButton('确定', null);
                        builder.setNegativeButton('取消', null);
                        builder.show();
                        console.log('[+] 弹窗已显示');
                    });
                },
                onComplete: function() {
                    console.log('[*] Activity 搜索完成');
                }
            });
        }, 1000);
    } catch(e) {
        console.log('错误: ' + e.stack);
    }
});
objection patchapk -s 原始.apk -c config.json -l index.js

加载子apk

# 反编译宿主 APK
apktool d host.apk -o host

# 复制目标 APK 到 assets
mkdir -p host/assets/
cp target.apk host/assets/plugin.apk

# 重新打包
apktool b host -o new.apk
Java.perform(function () {
    try {
        // 获取 Context
        Java.choose('android.app.Activity', {
            onMatch: function(instance) {
                var context = instance;
                
                // 复制 assets 中的 APK 到可读取目录
                var assetManager = context.getAssets();
                var inputStream = assetManager.open('plugin.apk');
                var outputFile = context.getDir('dex', 0) + '/plugin.apk';
                
                // 写入文件
                var fileOutputStream = Java.use('java.io.FileOutputStream').$new(outputFile);
                var buffer = Java.array('byte', Array(1024).fill(0));
                var length;
                while ((length = inputStream.read(buffer)) > 0) {
                    fileOutputStream.write(buffer, 0, length);
                }
                fileOutputStream.close();
                inputStream.close();
                
                // 使用 DexFile 列出所有类
                var DexFile = Java.use('dalvik.system.DexFile');
                var dexFile = DexFile.loadDex(outputFile, context.getDir('dex', 0) + '/opt', 0);
                var enumeration = dexFile.entries();
                
                console.log('====================');
                console.log('===== 类列表开始 =====');
                console.log('====================');
                
                var count = 0;
                // 遍历所有类
                while(enumeration.hasMoreElements()) {
                    var className = enumeration.nextElement().toString();
                    count++;
                    console.log('[类名 ' + count + '] ' + className);
                }
                
                console.log('====================');
                console.log('总共找到 ' + count + ' 个类');
                console.log('====================');
                
            },
            onComplete: function() {}
        });
    } catch(e) {
        console.log('[错误] ' + e.stack);
    }
});
 4503  objection patchapk /Users/voidcat/Downloads/RooketTrade1.apk
 4504  objection patchapk -s /Users/voidcat/Downloads/RooketTrade1.apk
 4505  frida -U -n RooketTrade -l _agent.js
 4506  apktool d host.apk -o host
 4507  mkdir -p host/assets/
 4508  cp target.apk host/assets/plugin.apk
 4509  apktool b host -o new.apk
 4510  objection patchapk -s new.apk

调用子apk函数

Java.perform(function(){
    let Color = {
        Reset: '\x1b[39;49;00m',
        Green: '\x1b[32;01m',
        Red: '\x1b[31;01m',
        Yellow: '\x1b[33;01m'
    };

    console.log(Color.Green + "[*] 开始加载子 APK..." + Color.Reset);

    try {
        // 获取 Context
        var currentApplication = Java.use('android.app.ActivityThread').currentApplication();
        var context = currentApplication.getApplicationContext();
        
        // 从 assets 加载子 APK
        var assetManager = context.getAssets();
        var inputStream = assetManager.open('plugin.apk');
        var cacheDir = context.getCacheDir().getAbsolutePath();
        var pluginPath = cacheDir + '/plugin.apk';
        
        // 写入子 APK
        var fileOutputStream = Java.use('java.io.FileOutputStream').$new(pluginPath);
        var buffer = Java.array('byte', Array(1024).fill(0));
        var length;
        while ((length = inputStream.read(buffer)) > 0) {
            fileOutputStream.write(buffer, 0, length);
        }
        fileOutputStream.close();
        inputStream.close();
        
        console.log(Color.Green + "[+] 子 APK 已保存到: " + pluginPath + Color.Reset);
        
        // 创建 DexClassLoader
        var dexOutputDir = context.getDir('dex', 0).getAbsolutePath();
        var DexClassLoader = Java.use('dalvik.system.DexClassLoader');
        var classLoader = DexClassLoader.$new(
            pluginPath,
            dexOutputDir,
            null,
            context.getClassLoader()
        );
        
        // 切换到插件的 ClassLoader
        Java.classFactory.loader = classLoader;
        
        try {
            // 先列出所有类
            let DexFile = Java.use('dalvik.system.DexFile');
            let dexFile = DexFile.$new(pluginPath);
            let entries = dexFile.entries();
            
            console.log(Color.Yellow + "\n[*] DEX 文件中的类:" + Color.Reset);
            while(entries.hasMoreElements()) {
                let className = entries.nextElement().toString();
                if(className.includes('com.example')) {
                    console.log("    - " + className);
                }
            }
            
            // 加载 Utils 类
            let class_ref = Java.use("com.example.myapplication.Utils");
            console.log(Color.Green + "[+] 成功加载 Utils 类" + Color.Reset);
            
            // 获取所有方法
            let methods = class_ref.class.getDeclaredMethods();
            console.log(Color.Yellow + "\n[*] Utils 类的方法:" + Color.Reset);
            for(let i = 0; i < methods.length; i++) {
                console.log("    - " + methods[i].toString());
            }
            
            // Hook add 方法
            class_ref.add.implementation = function(a, b){
                console.log(Color.Yellow + "[*] add 方法被调用" + Color.Reset);
                console.log("    参数: a = " + a + ", b = " + b);
                
                let result = this.add(a, b);
                console.log("    结果: " + result);
                
                return result;
            }
            
            // Hook sayHello 方法
            class_ref.sayHello.implementation = function(name){
                console.log(Color.Yellow + "[*] sayHello 方法被调用" + Color.Reset);
                console.log("    参数: name = " + name);
                
                let result = this.sayHello(name);
                console.log("    结果: " + result);
                
                return result;
            }
            
            // Hook encrypt 方法
            class_ref.encrypt.implementation = function(text){
                console.log(Color.Yellow + "[*] encrypt 方法被调用" + Color.Reset);
                console.log("    参数: text = " + text);
                
                let result = this.encrypt(text);
                console.log("    结果: " + result);
                
                return result;
            }
            
            // 测试调用
            console.log(Color.Green + "\n[*] 测试调用方法:" + Color.Reset);
            let result1 = class_ref.add(10, 20);
            let result2 = class_ref.sayHello("Frida");
            let result3 = class_ref.encrypt("test");
            
            console.log(Color.Green + "[+] 测试完成" + Color.Reset);
            
        } catch(e) {
            console.log(Color.Red + "[!] Hook 失败: " + e + Color.Reset);
            if(e.stack) {
                console.log(Color.Red + "[堆栈] " + e.stack + Color.Reset);
            }
        }
        
    } catch(e) {
        console.log(Color.Red + "[错误] " + e + Color.Reset);
        if(e.stack) {
            console.log(Color.Red + "[堆栈] " + e.stack + Color.Reset);
        }
    }
});

ipa

可能需要安装
npm install -g applesign

查看证书命令

security find-identity -v -p codesigning

然后

objection patchipa --source my-app.ipa --codesign-signature 0C2E8200Dxxxx

如果是自己的工程直接把FridaGadget.dylib 扔进去。

frida -U -f com.aaa

评论

0条评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注