How Bugbane works

This page describes Bugbane’s internal operation, for readers interested in the technical details and for analysts who want to know exactly where the data comes from. It describes Bugbane 0.2.3; the source code is the authoritative reference.

Components #

Bugbane is made of the main application and a set of libraries, all open source:

  • bugbane — the app itself: the UI, the wizard, the encryption (crypto module), and the acquisition logic, a reimplementation of AndroidQF’s collection that produces the same artifact layout.
  • libmvt — a Kotlin/Java library implementing MVT-style analysis, used for on-device scanning.
  • libadb-android-bc — the ADB client library, a fork of libadb-android adapted to use Bouncy Castle. It speaks the ADB protocol over TLS, like adb on a computer does.
  • libohttp — an Oblivious HTTP client, used to download indicator updates, with its backends libbhttp (binary HTTP encoding) and libohttp-hpke-bc (HPKE, based on Bouncy Castle).

All components are written in Kotlin/Java: the app currently has no native dependencies, which makes the build easy to reproduce.

Everything runs on a single device because Android’s Wireless Debugging accepts connections from the network, and the phone is on its own network. Bugbane pairs with the device’s own ADB interface and issues the same commands an analyst would type. The ADB shell has more privileges than a normal app.

Pairing #

  1. When you enable Wireless Debugging and tap “Pair device with pairing code”, Android starts a pairing service and announces it on the local network (mDNS).
  2. Bugbane discovers the service and shows the “Enter pairing code” notification.
  3. The 6-digit code you type authenticates a TLS pairing, after which Android remembers Bugbane’s ADB key (an RSA-2048 key the app generated, stored wrapped by the hardware keystore).

From then on, Bugbane can connect to the ADB interface directly whenever Wireless Debugging is on; this is why turning it off after each session is important.

What acquisition collects #

Acquisition runs 16 modules, each producing one artifact in the archive. Each module corresponds to a standard command or file read, the same ones AndroidQF uses. Modules that need the most storage run last, so a nearly-full device skips them rather than failing everything.

ModuleArtifactWhat it runs / reads
Envenv.txtenv
Dumpsysdumpsys.txtdumpsys
Logslogs/copies log files: /data/anr/, /data/log/, /data/system/uiderrors.txt, kernel logs (/proc/kmsg → logs/kmsg.txt, /proc/last_kmsg, ramoops)
Logcatlogcat.txt, logcat_old.txtlogcat -d -b all (current and last-boot buffers)
GetPropgetprop.txtgetprop
Mountsmounts.jsonmount
Processesps.txtps -A
RootBinariesroot_binaries.jsonsearches $PATH and common locations (/system/bin, /system/xbin, /sbin, /su/bin, /vendor/bin) for known rooting binaries and apps
Servicesservices.txtservice list
Settingssettings_<namespace>.txtcmd settings list <namespace> for each namespace (system, secure, global)
SELinuxselinux.txtgetenforce
Temptmp/copies /data/local/tmp/
Filesfiles.jsonfind <dir> -type f -printf … over accessible directories: path, timestamps, size, permissions, SELinux context per file
OldBugreportsbugreports/copies previously generated bugreports (/data/user_de/0/com.android.shell/files/bugreports/)
Bugreportbugreport.zipbugreportz -p
Packagespackages.json, apks/pm list packages -U -u -i plus pm path; records install source and APK SHA-256 hashes, and copies non-system APKs

Alongside the artifacts, the archive contains acquisition.json (UUID, timestamps, app version, per-module status), hashes.csv (SHA-256 of every artifact, for integrity), and adb_host_key.pub (Bugbane’s own ADB key, so analysis can tell it apart from unknown keys).

Every artifact is encrypted while it is written: the archive on disk is never in cleartext.

What analysis does #

When you tap “Run Analysis”, Bugbane:

  1. Loads the newest indicators available: the bundled set shipped with the app, plus any privately-fetched updates from mvt-indicators.
  2. Streams the encrypted archive, decrypting in memory, and feeds each artifact to libmvt, which uses the same parsing and matching approach as mvt-android.
  3. Matches records against the indicators (STIX2: domains, processes, file names and paths, hashes, app ids, URLs…) and applies heuristics, for example flagging sideloaded packages with no known installer.
  4. Stores the result next to the acquisition, with the date, the indicator version used, and every match with its severity: CRITICAL, HIGH, MEDIUM, LOW, INFO, LOG.

A failed artifact does not abort the scan: each file is analyzed independently. Because analysis is repeatable, the same acquisition can be scanned again when updated indicators are available.

Where data is stored #

Everything stays inside the app’s private storage: the encrypted archives, the analysis results, the wrapped keys. The complete data-protection picture is in the Security architecture.