Files
bulltron-ble-commands/tools/extract-ble-symbols.py
T

73 lines
1.8 KiB
Python

#!/usr/bin/env python3
"""Scan decompiled Android sources for BLE UUIDs and GATT-related calls."""
from __future__ import annotations
import argparse
import re
from pathlib import Path
UUID_RE = re.compile(
r"[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}"
)
GATT_TERMS = [
"BluetoothGatt",
"BluetoothGattCallback",
"BluetoothGattCharacteristic",
"BluetoothGattDescriptor",
"BluetoothLeScanner",
"startScan",
"startLeScan",
"connectGatt",
"createBond",
"discoverServices",
"getService",
"getCharacteristic",
"setCharacteristicNotification",
"writeCharacteristic",
"readCharacteristic",
"writeDescriptor",
"onCharacteristicChanged",
"onCharacteristicRead",
"onCharacteristicWrite",
]
def interesting(path: Path) -> bool:
return path.suffix.lower() in {".java", ".kt", ".xml", ".smali"}
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("source", type=Path, help="JADX/apktool output directory")
args = parser.parse_args()
for path in sorted(p for p in args.source.rglob("*") if p.is_file() and interesting(p)):
try:
text = path.read_text(errors="ignore")
except OSError:
continue
matches = sorted(set(UUID_RE.findall(text)))
terms = [term for term in GATT_TERMS if term in text]
if not matches and not terms:
continue
print(f"## {path}")
if matches:
print("UUIDs:")
for value in matches:
print(f"- {value.lower()}")
if terms:
print("GATT terms:")
for value in terms:
print(f"- {value}")
print()
return 0
if __name__ == "__main__":
raise SystemExit(main())