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
发表回复