Pocket Pentester — A Native Offensive Security Toolkit That Fits in Your Pocket

rust dev.to

TL;DR

I built Pocket Pentester — a native offensive security toolkit for Android. 21 modules, 34MB APK, no root, fully offline-first. Pure Rust + Tauri + Vue.

👉 Repo: https://github.com/tegal1337/PocketPentester
👉 Download APK: https://github.com/tegal1337/PocketPentester/releases/latest/download/PocketPentester.apk


Why?

Most mobile pentest tools fall into one of three categories:

  1. Web wrappers — basically a browser pointing at a web service. Useless offline.
  2. Termux scripts — power-user only, requires sideloading binaries, breaks when Android updates.
  3. Root-only tools — needs Magisk, voids warranty, doesn't run on stock devices.

I wanted something that:

  • Runs native code for real performance (async port scans, regex-heavy fingerprinting)
  • Works offline — no API key, no callback server, no telemetry
  • Installs from a single APK, no setup
  • Doesn't need root

So I shipped this. 21 modules, all native Rust under the hood.


The Stack

Layer Tech
Frontend Vue 3 + TypeScript + Vite
Native shell Tauri 2
Backend Pure Rust (tokio + reqwest + rustls + hickory-dns)
Build Gradle splits.abi → 4 ABIs + universal
CI GitHub Actions, signed with v1+v2+v3 schemes

Tauri 2's Android support landed officially in mid-2024. It compiles your Rust crate to a .so, embeds a WebView for the UI, and exposes IPC commands via #[tauri::command]. The result is fast: a port scan over 1000 ports finishes in seconds, and the SQLi engine runs sqlmap-style detection without network calls home.


What's Inside

Recon

  • Port scan — async TCP probe with service hints
  • Subdomain enum — 16 passive sources (crt.sh, certspotter, c99, VT, Anubis, etc.) + brute
  • HTTP probe — fingerprint live hosts, status, title, tech stack
  • Domain grab — bulk harvest by TLD from web sources + IANA
  • DNS — A/AAAA/MX/TXT/NS/CNAME/SOA/CAA/SRV + AXFR + DNSSEC
  • SSL scan — TLS chain, SANs, expiry, weak sig audit
  • Banner grab — TCP banner + service fingerprint
  • LAN map — TCP sweep + mDNS + SSDP/UPnP
port scan subdomain enum http probe
dns ssl scan lan map

Exploitation

  • SQLi — sqlmap-style: heuristic, error, boolean-blind, UNION (with auto column count + position detection), time-blind. Includes a full dump engine for databases → tables → columns → rows.
  • XSS — context-aware reflection (HTML/attr/JS/URL) with canary detection
  • JWTalg:none, kid injection, HMAC weak-secret brute, admin forgery
  • Xploiter — YAML template engine (variables, payloads, matchers, chains)
  • Auto-pwn — full chain pipeline: recon → probe → exploit, one button
  • Dir-fuzz — recursion + wildcard calibration
  • Admin-finder — 320+ paths, CMS fingerprint, login form detection
  • Form-brute — CSRF aware, regex matchers, baseline delta
  • Takeover — 18 service fingerprints (S3, GitHub Pages, Heroku, Azure, etc.)
sqli scanner xss scanner jwt attacker
auto-pwn dir-fuzz admin-finder
xploiter (yaml) form-brute takeover

Manual & Utility

  • Repeater — Burp-lite. Edit method/URL/headers/body, preview, export curl
  • Payload-gen — 50+ reverse/bind shells + webshells + msfvenom + encoders
  • Encoder — chainable b64/url/hex/html/rot13/morse/jwt pipeline
  • Hash-tools — identify 28+ hash types + compute MD5/SHA/CRC32
repeater (Burp-lite) payload-gen encoder chain

A War Story: The UNION That Wasn't

Real example of how building offline-first forced cleaner engineering.

When I tested the SQLi scanner against my own vuln lab (https://insecure.newploit.com/profile.php?id=1), the scan correctly detected error-based injection but missed UNION-based every time. Even though I could prove UNION worked manually with curl.

Looked at the scanner code:

// test_union_based() — old version
let full = format!("{}{} UNION SELECT {}-- -",
    point.base_value, prefix, fields.join(","));
Enter fullscreen mode Exit fullscreen mode

Spotted it: the scanner used the original base_value (1) when injecting UNION. The PHP target was running this query:

SELECT id, user, ... FROM users WHERE id=1 UNION SELECT marker,...
Enter fullscreen mode Exit fullscreen mode

The DB returned two rows: the real user (id=1) first, then the UNION row. PHP's fetch_assoc() only returned the first row. The marker was never rendered → scanner thought UNION failed.

The fix is a classic sqlmap technique:

let null_bases = if base_value.chars().all(|c| c.is_ascii_digit()) {
    vec![format!("-{}", base_value), "0".into(), "999999999".into(),
         format!("{} AND 1=2", base_value)]
} else {
    vec![format!("{} AND 1=2", base_value)]
};
Enter fullscreen mode Exit fullscreen mode

Use -1, 0, or AND 1=2 to make the original WHERE clause return zero rows. Now the UNION row is the only row, and the marker reflects.

After the fix:

[+] error-based   GET:id [DBMS:MySQL]  payload: 1' -- -
[+] union-based   GET:id [DBMS:MySQL]  4col @ 2
    version = 10.11.16-MariaDB-ubu2204
    user    = root@%
    db      = newploit
[*] scan done: 2 injection point(s)
Enter fullscreen mode Exit fullscreen mode

Then the dump engine clean-fires:

id username password email role api_key
1 admin admin123 admin@... admin sk_admin_AKIAIOSFODNN7EXAMPLE
2 root toor root@... admin sk_root_deadbeefcafebabe
... ... ... ... ... ...

The lesson: build with a real vuln target on day one. If I had only relied on unit tests with mocked DB responses, this would have shipped broken to every user.



Lessons

  1. Native > web wrapper for tools. Async Rust port scans crush JavaScript-in-WebView every time.
  2. Test against real targets early. Mocked tests would have hidden the UNION bug indefinitely.
  3. Pick one split mechanism. Tauri's --split-per-abi and Gradle's splits.abi don't coexist. Pick one.
  4. Sanity check artifact sizes in CI. A < 5MB check would have caught the empty-shell bug before release.
  5. Pentest tools have weird requirements. Cleartext HTTP, root-free port scans, offline operation — none of which match Android's default app profile.

What's Next

  • Bluetooth/BLE recon module
  • Local AI model for response analysis (offline LLM via candle-rs)
  • More tamper scripts for SQLi WAF bypass
  • Burp-style intercepting proxy

If you've got an idea, drop it as an issue: https://github.com/tegal1337/PocketPentester/issues


Repo: https://github.com/tegal1337/PocketPentester
Download: https://github.com/tegal1337/PocketPentester/releases/latest

Free and open source. MIT license. Built so you never miss the next train.

Source: dev.to

arrow_back Back to Tutorials