安卓 day4
想吃蛋挞
@source: https://github.com/r0ysue/AndroidSecurityStudy/tree/master/FRIDA/B01
获取蓝牙设备
enumerateLoadedClasses() 枚举已加载的类
1 2 3 4 5 6 7 8 9 10 11 12 13
| 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 进程都能看到。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 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 可以拿到目标类实例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| setTimeout(function() { Java.perform(function() { const BluetoothDevice = Java.use("android.bluetooth.BluetoothDevice"); function bluetoothDeviceInfo(anyObj) { try { let dev = anyObj; if (anyObj.$className !== "android.bluetooth.BluetoothDevice") { dev = Java.cast(anyObj, BluetoothDevice); }
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 实例后马上开始扫。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| 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 { let dev = anyObj; if (anyObj.$className !== "android.bluetooth.BluetoothDevice") { dev = Java.cast(anyObj, BluetoothDevice); }
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); } catch (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 迭代出来。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
| Java.perform(function () { function jtype(o) { try { return o.$className || (typeof o); } catch (_) { return typeof o; } } function bluetoothDeviceInfo(anyObj) { try { let dev = anyObj; if (anyObj.$className !== "android.bluetooth.BluetoothDevice") { dev = Java.cast(anyObj, BluetoothDevice); }
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");
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); console.log("[*] bonded = " + bonded + " type=" + jtype(bonded)); } catch (e) { console.log("[!] getBondedDevices failed: " + e); return; }
try { const n = bonded.size.overload().call(bonded); console.log("[*] bonded size = " + n); } catch (e) { console.log("[!] bonded.size() failed: " + e); }
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; }
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 枚举类内所有方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| Java.perform(function () { function enumMethods(targetClass) { var hook = Java.use(targetClass); var ownMethods = hook.class.getDeclaredMethods(); hook.$dispose();
return ownMethods; }
var a = enumMethods("android.bluetooth.BluetoothDevice"); a.forEach(function (s) { console.log(s); });
})
|
.class 获取 Class 对象,.getDeclaredMthods() 获取所有声明的方法。