How Bugbane works

This page explains what happens under the hood, for the technically curious and for analysts who want to know exactly where the data comes from. It describes Bugbane 0.2.3; the source code is the final reference.

The pieces #

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 — a shell with 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 — which is why turning it off after each session matters.

What acquisition collects #

Acquisition runs 16 modules, each producing one artifact in the archive. Every module boils down 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/kmsglogs/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 it has — 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 — 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. And because analysis is repeatable, the same acquisition can be scanned again whenever indicators improve.

Where things live #

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.