frida B01
安卓 day4 想吃蛋挞
@source: https://github.com/r0ysue/AndroidSecurityStudy/tree/master/FRIDA/B01
获取蓝牙设备#
enumerateLoadedClasses() 枚举已加载的类
setTimeout(function() {
Java.perform(function() {
console.log("\n[*] enumerating classes...");
Java.enumerateLoadedClasses({
onMatch: function(_className) {
console.log("[*] found instance of '" + _className + "'");
},
onComplete: function() {
console.log("[*] class enumeration complete");
}
});
});
});
加个判断可以定位目标类。蓝牙相关类属于系统框架,被 zygote 预加载进进程内存,几乎所有 app 进程都能看到。
setTimeout(function() {
Java.perform(function() {
console.log("\n[*] enumerating classes...");
Java.enumerateLoadedClasses({
onMatch: function(instance) {
if (instance.split(".")[1] == "bluetooth") {
console.log("[->]\t" + instance);
}
},
onComplete: function() {
console.log("[*] class enumeration complete");
}
});
});
});
配合 Java.choose 可以拿到目标类实例。
setTimeout(function() {
Java.perform(function() {
const BluetoothDevice = Java.use("android.bluetooth.BluetoothDevice");
function bluetoothDeviceInfo(anyObj) {
try {
// 如果不是 BluetoothDevice,先尝试 cast
let dev = anyObj;
if (anyObj.$className !== "android.bluetooth.BluetoothDevice") {
dev = Java.cast(anyObj, BluetoothDevice); // cast 失败会抛异常
}
console.log(" name=" + dev.getName() +
", address=" + dev.getAddress() +
", type=" + dev.getType());
} catch (e) {
console.log(" [!] not a BluetoothDevice / cast failed: " + anyObj.$className + " => " + e);
}
}
console.log("\n[*] enumerating classes...");
Java.enumerateLoadedClasses({
onMatch: function(instance) {
if (instance.split(".")[1] == "bluetooth") {
console.log("[->]\t" + instance);
}
},
onComplete: function() {
console.log("[*] class enumeration complete");
}
});
console.log("[*] finding android.bluetooth.BluetoothDevice instance...");
Java.choose("android.bluetooth.BluetoothDevice", {
onMatch: function(instance) {
console.log("[*] android.bluetooth,BluetoothDevice" + idx + " instance found" + " :=> '" + instance + "'");
console.log("class=" + instance.$className);
bluetoothDeviceInfo(instance);
},
onComplete: function() {
console.log("[*] -----")
}
})
});
});
对原文代码做了一些修改,但是本质差不多。以上脚本在安卓12下扫不到蓝牙设备,可能和注入时机有关(实例已经被gc),那么我们可以通过调用 BluetoothAdapter.getBondedDevices() 在进程中创建 BluetoothDevice 实例后马上开始扫。
setTimeout(function () {
Java.perform(function () {
const BluetoothDevice = Java.use("android.bluetooth.BluetoothDevice");
const BluetoothAdapter = Java.use("android.bluetooth.BluetoothAdapter");
function jtype(o) {
try { return o.$className || (typeof o); } catch (_) { return typeof o; }
}
function bluetoothDeviceInfo(anyObj) {
try {
// 如果不是 BluetoothDevice,先尝试 cast
let dev = anyObj;
if (anyObj.$className !== "android.bluetooth.BluetoothDevice") {
dev = Java.cast(anyObj, BluetoothDevice); // cast 失败会抛异常
}
console.log(" name=" + dev.getName() +
", address=" + dev.getAddress() +
", type=" + dev.getType());
} catch (e) {
console.log(" [!] not a BluetoothDevice / cast failed: " + anyObj.$className + " => " + e);
}
}
let adapter;
try {
adapter = BluetoothAdapter.getDefaultAdapter.overload().call(BluetoothAdapter);
console.log("[*] adapter = " + adapter + " type=" + jtype(adapter));
} catch (e) {
console.log("[!] getDefaultAdapter failed: " + e);
return;
}
if (adapter === null) {
console.log("[!] No Bluetooth adapter");
return;
}
let bonded;
try {
bonded = adapter.getBondedDevices.overload().call(adapter); // returns java.util.Set
// console.log("[*] bonded = " + bonded + " type=" + jtype(bonded));
} catch (e) {
// console.log("[!] getBondedDevices failed: " + e);
return;
}
console.log("[*] finding android.bluetooth.BluetoothDevice" + idx + " instance...");
Java.choose("android.bluetooth.BluetoothDevice", {
onMatch: function (instance) {
console.log("[*] android.bluetooth,BluetoothDevice instance found" + " :=> '" + instance + "'");
console.log("class=" + instance.$className);
bluetoothDeviceInfo(instance);
},
onComplete: function () {
console.log("[*] -----")
}
})
});
});
直接 Java.choose 扫比较暴力,其实可以直接把拿到的 bonded 迭代出来。
Java.perform(function () {
function jtype(o) {
try { return o.$className || (typeof o); } catch (_) { return typeof o; }
}
function bluetoothDeviceInfo(anyObj) {
try {
// 如果不是 BluetoothDevice,先尝试 cast
let dev = anyObj;
if (anyObj.$className !== "android.bluetooth.BluetoothDevice") {
dev = Java.cast(anyObj, BluetoothDevice); // cast 失败会抛异常
}
console.log(" name=" + dev.getName() +
", address=" + dev.getAddress() +
", type=" + dev.getType());
} catch (e) {
console.log(" [!] not a BluetoothDevice / cast failed: " + anyObj.$className + " => " + e);
}
}
const BluetoothAdapter = Java.use("android.bluetooth.BluetoothAdapter");
const BluetoothDevice = Java.use("android.bluetooth.BluetoothDevice");
// 1) getDefaultAdapter (static)
let adapter;
try {
adapter = BluetoothAdapter.getDefaultAdapter.overload().call(BluetoothAdapter);
console.log("[*] adapter = " + adapter + " type=" + jtype(adapter));
} catch (e) {
console.log("[!] getDefaultAdapter failed: " + e);
return;
}
if (adapter === null) {
console.log("[!] No Bluetooth adapter");
return;
}
// 2) getBondedDevices (instance)
let bonded;
try {
bonded = adapter.getBondedDevices.overload().call(adapter); // returns java.util.Set
console.log("[*] bonded = " + bonded + " type=" + jtype(bonded));
} catch (e) {
console.log("[!] getBondedDevices failed: " + e);
return;
}
// 3) size()
try {
const n = bonded.size.overload().call(bonded);
console.log("[*] bonded size = " + n);
} catch (e) {
console.log("[!] bonded.size() failed: " + e);
}
// 4) iterator + loop
let it;
try {
it = bonded.iterator.overload().call(bonded);
console.log("[*] iterator type=" + jtype(it));
} catch (e) {
console.log("[!] bonded.iterator() failed: " + e);
return;
}
while (true) {
let has;
try {
has = it.hasNext.overload().call(it);
} catch (e) {
console.log("[!] it.hasNext() failed: " + e);
break;
}
if (!has) break;
let dev;
try {
dev = it.next.overload().call(it);
console.log(" dev=" + dev + " type=" + jtype(dev));
} catch (e) {
console.log("[!] it.next() failed: " + e);
break;
}
// 5) getName/getAddress(同样强制 overload 调用)
try {
const name = BluetoothDevice.getName.call(dev);
const addr = BluetoothDevice.getAddress.call(dev);
console.log(" name=" + name + ", addr=" + addr);
} catch (e) {
console.log(" [!] getName/getAddress failed: " + e);
}
console.log("[*] finding android.bluetooth.BluetoothDevice instance...");
}
});
非常多代码,使我的眼睛发炎。
利用反射 api 枚举类内所有方法#
Java.perform(function () {
function enumMethods(targetClass) {
var hook = Java.use(targetClass);
var ownMethods = hook.class.getDeclaredMethods();
hook.$dispose(); // 释放 wrapper 内部引用
return ownMethods;
}
var a = enumMethods("android.bluetooth.BluetoothDevice");
a.forEach(function (s) {
console.log(s);
});
})
.class 获取 Class 对象,.getDeclaredMthods() 获取所有声明的方法。
Read other posts