SkillAgentSearch skills...

Dexbgd

A native Android DEX debugger with bytecode-level stepping, live variable inspection, and runtime manipulation for reverse engineering, CTFs, and security analysis

Install / Use

/learn @arkup/Dexbgd
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

dexbgd - DEX Debugger

<p align="center"> <img src="img/dexbgd_joke.png" alt="BGD Logo" width="300"> </p>

A real debugger for Android apps. Not a hooking framework, not JDWP - a native JVMTI debugger that lets you pause any Java method, step through Dalvik bytecode one instruction at a time, inspect every local variable and register, search the live heap, and force methods to return whatever you want.

Built for CTF, malware analysis and reverse engineering. Thin C++ agent inside the app, Rust TUI on the host.

<p align="center"> <img src="img/demo.gif" alt="BGD Screenshot"> </p>

How It Differs from Frida?

Frida replaces functions with JavaScript hooks. dexbgd pauses execution and lets you look around. Different tools for different problems.

| | dexbgd | Frida | |---|---|---| | Stop at any bytecode | Yes | No (method-level only) | | Step instruction by instruction | Yes | No | | Read every local/register while paused | Yes | Only what your hook captures | | Force a return value on the fly |Yes, fr false | Yes (write a hook script) | | Built-in DEX disassembler | Yes, live PC & frames | Need external tools (jadx, baksmali) | | Live heap search | heap SecretKey | Custom scripting required | | Auto-intercept dynamic class loading | Built-in | Requires scripting | | Native code | JNI monitor + redirect | Yes (multi-arch native) | | Detection surface | Standard debug API + optional ptrace | frida-server, gadget, ptrace | | Requires debuggable | Yes (or bypass via root + ptrace) | No (needs root or repackage) |

Use dexbgd when you need fine-grained visibility into execution - stepping through root checks, observing crypto state during execution, tracing dynamic class loading, or bypassing logic instruction-by-instruction.

What can it do / Quick Start

// Terminal 1
> adb forward tcp:12345 localabstract:dexbgd
> adb shell cmd activity attach-agent com.sketchy.apkapp libart_jit_tracer.so

// Terminal 2 (server TUI)
> launch com.sketchy.apkapp
  (same as adb shell am start -n com.sketchy.apkapp/.MainActivity)
  Connected (pid=12847, Android 14, arm64)
  Loaded APK: 847 classes, 6203 methods

> bp-detect
  Set 14 breakpoints on root/tamper detection APIs

> c
  Breakpoint #3 hit: Debug.isDebuggerConnected @0

> fr false
  [forced return false, paused at caller]

> c
  Breakpoint #7 hit: RootBeer.isRooted @0

> fr false
  [app thinks device is clean, continues]

> bp-crypto
> c
  Breakpoint #31 hit: Cipher.init @0

> locals
  opmode = 1 (ENCRYPT)
  key = SecretKeySpec{AES, [4b 65 79 31 32 33 ...]}

> eval v2.getAlgorithm()
  "AES/CBC/PKCS5Padding"

> strings http
  [apk] "https://c2server.evil.com/exfil"
  [apk] "http://license.check.net/verify"

> xref-bp c2server
  Set bp on MainActivity.sendData (loads "https://c2server.evil.com/exfil")

Features

Breakpoint profiles

One command covers an entire attack surface:

bp-crypto       Cipher, SecretKeySpec, IvParameterSpec, Mac, MessageDigest, KeyGenerator, KeyStore
bp-network      URL, HttpURLConnection, HttpsURLConnection, Socket, OkHttp
bp-exec         Runtime.exec, ProcessBuilder, DexClassLoader, PathClassLoader, InMemoryDexClassLoader, Method.invoke, Class.forName, ClassLoader.loadClass
bp-detect       Debug.isDebuggerConnected, SafetyNet, Play Integrity, File.exists, SystemProperties, ActivityManager, Settings$Secure, signature checks
bp-exfil        TelephonyManager, ContentResolver, SMS, Location, PackageManager.getInstalledPackages
bp-ssl          NetworkSecurityTrustManager, SSLContext.init, HttpsURLConnection, OkHttp CertificatePinner, Conscrypt TrustManagerImpl
bp-all          All of the above

Force return

Make any method return whatever you want while it's suspended. The agent figures out the return type automatically.

fr true         isRooted() -> true? Not anymore.
fr false        isDebuggerConnected() -> false.
fr null         getSignature() -> null. Signature check bypassed.
fr 42           getRetryCount() -> 42. Why not.

After forcing the return, execution pauses at the caller's next instruction so you can see the effect before continuing.

Silent anti-tamper bypass (anti)

bypass-ssl silently intercepts SSL pinning. anti does the same for any method — it sets a ghost breakpoint that auto-ForceEarlyReturns a neutral value without pausing or showing anything to the user.

Three ways to find what to hook:

// Direct: name the method
anti com.example.Security isRooted

// xref: find methods that load a suspicious string constant
anti xref su
anti xref test-keys
anti xref Superuser

// callers: find methods that invoke a specific API
anti callers android.os.Debug isDebuggerConnected

Example against the test app on a rooted device:

> attach com.test.profiletest
  [press Detect button -> "Root: DETECTED (1)"]

> anti xref su
  anti xref "su": 1 unique method(s) - setting anti hooks...
    MainActivity.testDetect ("/system/xbin/su")

  [press Detect button -> "Root: not detected (0)"]
  [anti] MainActivity.testDetect()I -> 0/false/null

> anti list
  1 active anti hook(s):
    #3 MainActivity.testDetect

> anti clear

Return value is auto-detected from the JNI signature (Z/B/I/... -> false/0, V -> void). Override with an explicit value:

anti com.example.License check true      // always pass
anti com.example.Integrity verify void   // silently swallow

Dynamic DEX interception

When bp-exec is active and the app loads code at runtime (DexClassLoader, InMemoryDexClassLoader), dexbgd automatically:

  1. Dumps the loaded DEX bytes
  2. Parses class/method/string tables
  3. Merges them into the searchable symbol data

So strings and xref cover both the original APK and dynamically loaded payloads - the stuff malware actually tries to hide.

Conditional breakpoints

bp Cipher init --when "v1 == 1"         Break only on ENCRYPT mode
bp HttpURLConnection connect --every 5   Break every 5th call
bp LicenseCheck verify --hits 3          Break only on 3rd hit

See doc/breakpoint_cond.md for the full expression syntax and more examples.

Call recording

Record security-relevant API calls as an indented call tree:

> record
> c
  [app runs for a while]
> record
  Cipher.getInstance("AES/CBC/PKCS5Padding")
    SecretKeySpec.<init>([...], "AES")
    Cipher.init(1, SecretKeySpec)
    Cipher.doFinal([...]) -> [encrypted bytes]
  URL.<init>("https://c2server.evil.com/exfil")
    HttpURLConnection.connect()

AI-assisted analysis (experimental)

Point an LLM at the debugger and let it drive:

> ai Find all crypto keys used by this app and trace where the ciphertext goes
> ai ask Bypass root detection              (confirms each tool call)
> ai explain What is this method doing?     (read-only inspection)

The AI gets access to all debugger tools - it can set breakpoints, step, inspect variables, search strings, and build a report. Supports Claude API and local Ollama models.

See doc/ai_setup.md for setup instructions.

Command reference

See doc/all_commands.md for the full, up-to-date list of commands.

Connection

procs / ps              List debuggable processes
attach <pkg>            Inject agent + connect + load symbols
launch <pkg>            Start app + attach
connect                 Manual connect (127.0.0.1:12345)
disconnect / dc         Disconnect

Exploration

cls [pattern]           Search loaded classes
methods / m <class>     List methods
fields / f <class>      List fields
threads / thd           List all threads
dis <class> <m>         Disassemble method
u <class.method>        Navigate to method (WinDbg-style unassemble)
strings <pattern>       Search DEX constant pool
xref <pattern>          Find code referencing a string
xref-bp <pattern>       xref + set breakpoints
apk <path|pkg>          Load APK symbols

Breakpoints

bp <cls> <method> [sig] [@loc]   Set breakpoint
bp2 <cls> <method> [sig] [@loc]  Set breakpoint + force deopt (for repacked APKs)
  --hits N / --every N / --when "expr"
bc / bd <id>            Clear breakpoint
bc / bd *               Clear all
bl                      List breakpoints

bp2: On repacked APKs, ART may silently fail to deoptimize methods — bp succeeds but never fires. bp2 forces deoptimization via RetransformClasses after setting the breakpoint. Use bp2 instead of bp when debugging repacked apps.

Execution

c / g / F5              Continue
si / F7                 Step into
s / n / F8              Step over
sout / finish / F9      Step out
pause / F6              Suspend thread
fr <value>              Force return (true/false/null/void/0/1/<int>)

Inspection

locals / l              Local variables
stack / bt              Call stack
inspect / i <vN>        Object fields
eval / e <expr>         Evaluate (v3.getAlgorithm())
hexdump / hd <vN>       Hex dump arrays/strings
hexdump / hd <vN> full  Extended hex dump (32 rows)
heap <class>            Search heap instances
heapstr <pattern>       Search live strings
r / regs                Dump registers

Watch

watch <expr>        Add expression to watch list (re-evaluated on every suspension)
unwatch <n|expr>    Remove watch by index or expression
unwatch *           Remove all watches
watch clear         Same as unwatch *

e.g.
watch key
watch v3
watch v3.getAlgorithm()

Bookmarks

Ctrl+B              Toggle bookmark at bytecode cursor
bm <label>          Rename selected bookmark (or press Enter in Bookmarks tab)

Session (per-app persistent state)

Aliases, comments, bookmarks, and hooks are saved per app in sessions/<package>.json next to the server binary.

Ctrl+S              Save session for current app
Ctrl+L              Launch session picker (select saved app, start and attach agent)

n                   Rename current class (IDA-style, bytecodes pane

Related Skills

View on GitHub
GitHub Stars31
CategoryProduct
Updated23m ago
Forks6

Languages

Rust

Security Score

80/100

Audited on Apr 3, 2026

No findings