mirror of
https://github.com/CyberSecurityUP/NeuroSploit.git
synced 2026-09-30 13:09:36 +02:00
feat(mobile): binary/APK/IPA testing mode + 12 RE skills — v4.2.0
New `mobile` engagement mode: `neurosploit mobile <app.apk|app.ipa|binary>` reverse-engineers a local artifact with a dedicated `mobile` agent set, all headless and provisioned on demand (Ghidra analyzeHeadless, MobSF REST/Docker, Frida, apktool/jadx, radare2). Twelve original, generic skills (agents_md/mobile/, English): static binary triage, APK static analysis, IPA static analysis, RASP & anti-tamper mapping, root/jailbreak detection + bypass, TLS pinning detection + bypass, anti-debug detection + bypass, obfuscation analysis & deobfuscation, code-integrity / tamper-check bypass, hardcoded-secrets extraction, insecure local storage, and mobile network traffic analysis. Findings are proven from the artifact (decompilation or Frida trace), non-destructively. - agents.rs: new `mobile` Library category (loaded, counted). - pipeline.rs: run_mobile() mirroring the host pipeline with a mobile recon and headless tooling doctrine; exported from the crate. - CLI: `Cmd::Mobile` + `Mode::Mobile`, wired in main and the TUI. - README + TUTORIAL document the new test type; engagement-modes badge + table updated; "New in v4.2.0" note. Version bumped to 4.2.0 across the workspace. 383 tests. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
a4afd784c7
commit
4b71ac63a0
30 files changed
+416
-26
No files matched your search
@@ -1,4 +1,4 @@
|
|||||||
<h1 align="center">🧠 NeuroSploit v4.1.0</h1>
|
<h1 align="center">🧠 NeuroSploit v4.2.0</h1>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/JoasASantos/NeuroSploit/stargazers"><img src="https://img.shields.io/github/stars/JoasASantos/NeuroSploit?style=for-the-badge&logo=github&color=8b5cf6" alt="Stars"></a>
|
<a href="https://github.com/JoasASantos/NeuroSploit/stargazers"><img src="https://img.shields.io/github/stars/JoasASantos/NeuroSploit?style=for-the-badge&logo=github&color=8b5cf6" alt="Stars"></a>
|
||||||
@@ -8,12 +8,12 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://img.shields.io/badge/Version-4.1.0-blue?style=flat-square">
|
<img src="https://img.shields.io/badge/Version-4.2.0-blue?style=flat-square">
|
||||||
<img src="https://img.shields.io/badge/Harness-Rust%20%7C%20tokio-e6b673?style=flat-square">
|
<img src="https://img.shields.io/badge/Harness-Rust%20%7C%20tokio-e6b673?style=flat-square">
|
||||||
<img src="https://img.shields.io/badge/License-MIT-green?style=flat-square">
|
<img src="https://img.shields.io/badge/License-MIT-green?style=flat-square">
|
||||||
<img src="https://img.shields.io/badge/MD%20Agents-446-red?style=flat-square">
|
<img src="https://img.shields.io/badge/MD%20Agents-458-red?style=flat-square">
|
||||||
<img src="https://img.shields.io/badge/Models-18%20providers-success?style=flat-square">
|
<img src="https://img.shields.io/badge/Models-18%20providers-success?style=flat-square">
|
||||||
<img src="https://img.shields.io/badge/Modes-Black%20%7C%20White%20%7C%20Grey%20%7C%20Host%20%7C%20AI-9cf?style=flat-square">
|
<img src="https://img.shields.io/badge/Modes-Black%20%7C%20White%20%7C%20Grey%20%7C%20Host%20%7C%20AI%20%7C%20Mobile-9cf?style=flat-square">
|
||||||
<img src="https://img.shields.io/badge/Auth-API%20key%20%7C%20Subscription-orange?style=flat-square">
|
<img src="https://img.shields.io/badge/Auth-API%20key%20%7C%20Subscription-orange?style=flat-square">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -45,11 +45,22 @@ Control TUI**.
|
|||||||
| **Host/Infra** | `neurosploit host <ip> --creds creds.yaml` | Linux / Windows / AD **and cloud** (AWS/GCP/Azure) testing |
|
| **Host/Infra** | `neurosploit host <ip> --creds creds.yaml` | Linux / Windows / AD **and cloud** (AWS/GCP/Azure) testing |
|
||||||
| **AI / LLM red-team** | `neurosploit aitest <ai-url>` | jailbreaks & prompt injection + OWASP LLM Top 10 / MCP against a live AI agent |
|
| **AI / LLM red-team** | `neurosploit aitest <ai-url>` | jailbreaks & prompt injection + OWASP LLM Top 10 / MCP against a live AI agent |
|
||||||
| **AI Skills / n8n** | `neurosploit skills <file\|folder>` | white-box audit of Skill/plugin & n8n workflow definitions |
|
| **AI Skills / n8n** | `neurosploit skills <file\|folder>` | white-box audit of Skill/plugin & n8n workflow definitions |
|
||||||
|
| **Mobile / Binary** | `neurosploit mobile <app.apk\|app.ipa\|binary>` | reverse-engineer a local artifact: RASP, root/JB, pinning, anti-debug, obfuscation, secrets (Ghidra headless / MobSF / Frida) |
|
||||||
| **Mission Control** | `neurosploit tui <url>` | live TUI panels + composer during the run |
|
| **Mission Control** | `neurosploit tui <url>` | live TUI panels + composer during the run |
|
||||||
| **Interactive** | `neurosploit` | persistent REPL session (resumes per project) |
|
| **Interactive** | `neurosploit` | persistent REPL session (resumes per project) |
|
||||||
|
|
||||||
### Highlights
|
### Highlights
|
||||||
|
|
||||||
|
> **New in v4.2.0** — **binary / APK / IPA testing**: a new `mobile` mode analyses
|
||||||
|
> a local artifact with 12 reverse-engineering skills (static binary triage,
|
||||||
|
> APK/IPA static analysis, RASP & anti-tamper mapping, root/jailbreak, TLS
|
||||||
|
> pinning, anti-debug, obfuscation deobfuscation, integrity/tamper checks,
|
||||||
|
> hardcoded-secret extraction, insecure storage, traffic analysis) driven by
|
||||||
|
> Ghidra headless, MobSF, Frida and apktool/jadx. Plus NeuroSploit as an **MCP
|
||||||
|
> server** (`neurosploit mcp`), a **pluggable decision backend** (TypeSafe or
|
||||||
|
> local Laya), **context tool-discovery** (AD/web/cloud/exploitation), and
|
||||||
|
> **CVE→PoC sourcing** (searchsploit/Exploit-DB/GitHub, compile & run).
|
||||||
|
|
||||||
> **New in v4.1.0** — evidence-graded CVSS computed from the FIRST v3.1 equation
|
> **New in v4.1.0** — evidence-graded CVSS computed from the FIRST v3.1 equation
|
||||||
> (not guessed by class); a **target-authorization gate** (default-deny, refuses a
|
> (not guessed by class); a **target-authorization gate** (default-deny, refuses a
|
||||||
> target outside the capability grant before any recon); **audit anchoring** that
|
> target outside the capability grant before any recon); **audit anchoring** that
|
||||||
@@ -681,6 +692,27 @@ Critical is not a Critical.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 📱 Mobile / binary testing
|
||||||
|
|
||||||
|
Point it at a local artifact and it reverse-engineers it headless:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
neurosploit mobile app.apk --subscription --model anthropic:claude-opus-4-8 -v
|
||||||
|
neurosploit mobile app.ipa
|
||||||
|
neurosploit mobile ./some_binary
|
||||||
|
```
|
||||||
|
|
||||||
|
Twelve RE skills, all headless (Ghidra `analyzeHeadless`, MobSF REST/Docker,
|
||||||
|
Frida, apktool/jadx, radare2), provisioned on demand: static binary triage,
|
||||||
|
APK/IPA static analysis, **RASP & anti-tamper mapping**, **root/jailbreak
|
||||||
|
detection + bypass**, **TLS pinning detection + bypass**, anti-debug bypass,
|
||||||
|
**obfuscation analysis & deobfuscation**, code-integrity/tamper-check bypass,
|
||||||
|
hardcoded-secret extraction, insecure local storage, and mobile traffic
|
||||||
|
analysis. Findings are proven from the artifact (decompilation or Frida trace),
|
||||||
|
non-destructively.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 🔌 Run it as an MCP server
|
## 🔌 Run it as an MCP server
|
||||||
|
|
||||||
Drive NeuroSploit from Claude Code, Codex or Cursor as tools:
|
Drive NeuroSploit from Claude Code, Codex or Cursor as tools:
|
||||||
|
|||||||
+17
@@ -487,6 +487,23 @@ engagement needs (a model API key or `--subscription`).
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 8a. Mobile / binary testing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
neurosploit mobile <app.apk | app.ipa | binary> --subscription --model anthropic:claude-opus-4-8 -v
|
||||||
|
```
|
||||||
|
|
||||||
|
Analyses a LOCAL artifact with the `mobile` agent set — 12 reverse-engineering
|
||||||
|
skills covering static triage, APK/IPA analysis, RASP/anti-tamper mapping,
|
||||||
|
root/jailbreak, TLS pinning, anti-debug, obfuscation deobfuscation, integrity
|
||||||
|
checks, secret extraction, insecure storage and traffic analysis. Every tool
|
||||||
|
runs HEADLESS (Ghidra `analyzeHeadless`, MobSF REST/Docker, Frida, apktool,
|
||||||
|
jadx, radare2) and is provisioned on demand. Best run with `--sandbox` (Kali
|
||||||
|
container) so the heavy toolchain installs off your host. Findings are proven
|
||||||
|
from the artifact itself, non-destructively.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 8b. Web console
|
## 8b. Web console
|
||||||
|
|
||||||
A browser UI for the same harness — one `node` process serves the SPA and drives the compiled
|
A browser UI for the same harness — one `node` process serves the SPA and drives the compiled
|
||||||
|
|||||||
Generated
+2
-2
@@ -929,7 +929,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "neurosploit"
|
name = "neurosploit"
|
||||||
version = "4.1.0"
|
version = "4.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
@@ -946,7 +946,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "neurosploit-harness"
|
name = "neurosploit-harness"
|
||||||
version = "4.1.0"
|
version = "4.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64",
|
"base64",
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ members = ["crates/harness", "app"]
|
|||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "4.1.0"
|
version = "4.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://github.com/JoasASantos/NeuroSploit"
|
repository = "https://github.com/JoasASantos/NeuroSploit"
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Anti-Debug Detection and Bypass
|
||||||
|
## User Prompt
|
||||||
|
You are analysing **{target}** (a binary, APK or IPA on disk) for: Anti-Debug Detection and Bypass. CWE-388
|
||||||
|
|
||||||
|
**Context:**
|
||||||
|
{recon_json}
|
||||||
|
|
||||||
|
All tools run HEADLESS (no GUI). Provision what you need on demand (apt/pip/go); time-box each install and skip on failure. Only test artifacts you are authorized to test.
|
||||||
|
|
||||||
|
### Method
|
||||||
|
1. Find anti-debug primitives: iOS/macOS `ptrace(PT_DENY_ATTACH)`, `sysctl(KERN_PROC→P_TRACED)`, `getppid`, `isatty`, exception-port checks; Android `TracerPid` in `/proc/self/status`, `Debug.isDebuggerConnected`, native `ptrace` self-attach, timing checks.
|
||||||
|
2. Map each to its abort/branch (xrefs + decompile).
|
||||||
|
3. Bypass: Frida stubs (`ptrace` no-op, `sysctl` clear P_TRACED, spoof `TracerPid` read, force `isDebuggerConnected` false), or patch the binary branch.
|
||||||
|
4. Prove a debugger/instrumentation now attaches where it was blocked; report detection + bypassability.
|
||||||
|
|
||||||
|
Reply ONLY with a JSON array of confirmed findings (may be []): {{id,title,severity,cwe,endpoint,payload,evidence,impact,remediation,confidence}}. `endpoint` = the file path / class / method / offset the finding lives at. Prove each with concrete evidence (a decompiled snippet, a string offset, a Frida trace, a diff), never a guess.
|
||||||
|
## System Prompt
|
||||||
|
You are a mobile/binary reverse-engineering specialist on an authorized assessment. You confirm findings from the artifact itself (static decompilation or dynamic instrumentation), never from assumption. Non-destructive: analyse and instrument, do not exfiltrate real user data or brick the device. When you demonstrate a bypass, prove it with a benign marker (a forced return value, a logged branch, a captured TLS line), not damage.
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# APK Static Analysis
|
||||||
|
## User Prompt
|
||||||
|
You are analysing **{target}** (a binary, APK or IPA on disk) for: APK Static Analysis. CWE-919
|
||||||
|
|
||||||
|
**Context:**
|
||||||
|
{recon_json}
|
||||||
|
|
||||||
|
All tools run HEADLESS (no GUI). Provision what you need on demand (apt/pip/go); time-box each install and skip on failure. Only test artifacts you are authorized to test.
|
||||||
|
|
||||||
|
### Method
|
||||||
|
1. Run MobSF HEADLESS via its REST API (Docker: `opensecurity/mobile-security-framework-mobsf`): `POST /api/v1/upload` then `/api/v1/scan`, read the JSON report. In parallel: `apktool d <apk>` and `jadx -d out <apk>` for source.
|
||||||
|
2. Manifest: parse `AndroidManifest.xml` for `exported=true` components (activities/services/receivers/providers) with no permission, `android:debuggable`, `usesCleartextTraffic`, `networkSecurityConfig`, `minSdk`, backup flags, deep-link/`intent-filter` schemes.
|
||||||
|
3. Secrets & endpoints: grep decompiled source + `resources.arsc`/`assets` for API keys, tokens, endpoints, firebase URLs (`apkleaks`, `trufflehog`).
|
||||||
|
4. Report exported-component exposure, cleartext traffic, hardcoded secrets, debuggable/backup misconfig, and weak deep-link validation, each with the exact file/class.
|
||||||
|
|
||||||
|
Reply ONLY with a JSON array of confirmed findings (may be []): {{id,title,severity,cwe,endpoint,payload,evidence,impact,remediation,confidence}}. `endpoint` = the file path / class / method / offset the finding lives at. Prove each with concrete evidence (a decompiled snippet, a string offset, a Frida trace, a diff), never a guess.
|
||||||
|
## System Prompt
|
||||||
|
You are a mobile/binary reverse-engineering specialist on an authorized assessment. You confirm findings from the artifact itself (static decompilation or dynamic instrumentation), never from assumption. Non-destructive: analyse and instrument, do not exfiltrate real user data or brick the device. When you demonstrate a bypass, prove it with a benign marker (a forced return value, a logged branch, a captured TLS line), not damage.
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Code Integrity / Tamper-Check Bypass
|
||||||
|
## User Prompt
|
||||||
|
You are analysing **{target}** (a binary, APK or IPA on disk) for: Code Integrity / Tamper-Check Bypass. CWE-354
|
||||||
|
|
||||||
|
**Context:**
|
||||||
|
{recon_json}
|
||||||
|
|
||||||
|
All tools run HEADLESS (no GUI). Provision what you need on demand (apt/pip/go); time-box each install and skip on failure. Only test artifacts you are authorized to test.
|
||||||
|
|
||||||
|
### Method
|
||||||
|
1. Find integrity checks: signature verification (`PackageManager` signature on Android, `SecCode`/`codesign` on iOS), CRC/hash-over-self, DEX/class checksum, resource integrity, server-attestation (SafetyNet/Play Integrity, DeviceCheck/App Attest).
|
||||||
|
2. For local checks: patch the binary/repack, then bypass the check with Frida (force the compare to pass) to prove the tamper gate is client-side and defeatable.
|
||||||
|
3. For server-attestation: note it as a stronger control; test whether the app degrades safely when attestation is missing/failed, and whether the verdict is enforced server-side.
|
||||||
|
4. Report each integrity mechanism and whether tampering is detected and enforced.
|
||||||
|
|
||||||
|
Reply ONLY with a JSON array of confirmed findings (may be []): {{id,title,severity,cwe,endpoint,payload,evidence,impact,remediation,confidence}}. `endpoint` = the file path / class / method / offset the finding lives at. Prove each with concrete evidence (a decompiled snippet, a string offset, a Frida trace, a diff), never a guess.
|
||||||
|
## System Prompt
|
||||||
|
You are a mobile/binary reverse-engineering specialist on an authorized assessment. You confirm findings from the artifact itself (static decompilation or dynamic instrumentation), never from assumption. Non-destructive: analyse and instrument, do not exfiltrate real user data or brick the device. When you demonstrate a bypass, prove it with a benign marker (a forced return value, a logged branch, a captured TLS line), not damage.
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Hardcoded Secrets Extraction
|
||||||
|
## User Prompt
|
||||||
|
You are analysing **{target}** (a binary, APK or IPA on disk) for: Hardcoded Secrets Extraction. CWE-798
|
||||||
|
|
||||||
|
**Context:**
|
||||||
|
{recon_json}
|
||||||
|
|
||||||
|
All tools run HEADLESS (no GUI). Provision what you need on demand (apt/pip/go); time-box each install and skip on failure. Only test artifacts you are authorized to test.
|
||||||
|
|
||||||
|
### Method
|
||||||
|
1. Extract from every layer: decompiled code, string tables, `resources.arsc`/`assets`/plist, native `.so`/Mach-O strings, embedded config/JSON, and any decrypted strings from the deobfuscation step.
|
||||||
|
2. Classify hits: API keys, cloud credentials (AKIA..., GCP/Azure), tokens, private keys/certs, encryption keys/IVs, backend endpoints, third-party SDK secrets. Use `trufflehog`/`gitleaks`/`apkleaks` plus targeted regex.
|
||||||
|
3. Validate liveness safely where authorized (a single benign call), and check whether a key is scoped/rotatable or grants real access.
|
||||||
|
4. Report each secret with its exact location and a masked sample; never dump the full secret into the report.
|
||||||
|
|
||||||
|
Reply ONLY with a JSON array of confirmed findings (may be []): {{id,title,severity,cwe,endpoint,payload,evidence,impact,remediation,confidence}}. `endpoint` = the file path / class / method / offset the finding lives at. Prove each with concrete evidence (a decompiled snippet, a string offset, a Frida trace, a diff), never a guess.
|
||||||
|
## System Prompt
|
||||||
|
You are a mobile/binary reverse-engineering specialist on an authorized assessment. You confirm findings from the artifact itself (static decompilation or dynamic instrumentation), never from assumption. Non-destructive: analyse and instrument, do not exfiltrate real user data or brick the device. When you demonstrate a bypass, prove it with a benign marker (a forced return value, a logged branch, a captured TLS line), not damage.
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Insecure Local Data Storage
|
||||||
|
## User Prompt
|
||||||
|
You are analysing **{target}** (a binary, APK or IPA on disk) for: Insecure Local Data Storage. CWE-312
|
||||||
|
|
||||||
|
**Context:**
|
||||||
|
{recon_json}
|
||||||
|
|
||||||
|
All tools run HEADLESS (no GUI). Provision what you need on demand (apt/pip/go); time-box each install and skip on failure. Only test artifacts you are authorized to test.
|
||||||
|
|
||||||
|
### Method
|
||||||
|
1. Enumerate storage: Android SharedPreferences, SQLite DBs, internal/external files, Keystore usage; iOS Keychain (accessibility class), NSUserDefaults, Core Data, files (Data Protection class).
|
||||||
|
2. Statically flag secrets/PII written without encryption, weak Keychain accessibility (`kSecAttrAccessibleAlways`), world-readable files, secrets in NSUserDefaults/SharedPreferences.
|
||||||
|
3. Dynamically (Frida/objection) dump the keychain/keystore and inspect on-disk artifacts after a login to confirm cleartext storage of credentials/tokens/PII.
|
||||||
|
4. Report each item with what is stored, where, and its protection class.
|
||||||
|
|
||||||
|
Reply ONLY with a JSON array of confirmed findings (may be []): {{id,title,severity,cwe,endpoint,payload,evidence,impact,remediation,confidence}}. `endpoint` = the file path / class / method / offset the finding lives at. Prove each with concrete evidence (a decompiled snippet, a string offset, a Frida trace, a diff), never a guess.
|
||||||
|
## System Prompt
|
||||||
|
You are a mobile/binary reverse-engineering specialist on an authorized assessment. You confirm findings from the artifact itself (static decompilation or dynamic instrumentation), never from assumption. Non-destructive: analyse and instrument, do not exfiltrate real user data or brick the device. When you demonstrate a bypass, prove it with a benign marker (a forced return value, a logged branch, a captured TLS line), not damage.
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# IPA Static Analysis
|
||||||
|
## User Prompt
|
||||||
|
You are analysing **{target}** (a binary, APK or IPA on disk) for: IPA Static Analysis. CWE-919
|
||||||
|
|
||||||
|
**Context:**
|
||||||
|
{recon_json}
|
||||||
|
|
||||||
|
All tools run HEADLESS (no GUI). Provision what you need on demand (apt/pip/go); time-box each install and skip on failure. Only test artifacts you are authorized to test.
|
||||||
|
|
||||||
|
### Method
|
||||||
|
1. Unzip the IPA; locate `Payload/<App>.app`. Run MobSF HEADLESS (REST) for the automated report. Read `Info.plist` (`plutil -p`), the embedded `.mobileprovision` and entitlements (`codesign -d --entitlements :-`).
|
||||||
|
2. Check: App Transport Security (`NSAppTransportSecurity`, `NSAllowsArbitraryLoads`), URL schemes / universal links (`applinks`), keychain-access-groups, background modes, `get-task-allow` (debuggable), missing PIE/ARC.
|
||||||
|
3. Binary: `otool -L` (linked frameworks, outdated/vulnerable), `strings`/`nm` on the Mach-O, `class-dump`/objc runtime for the class surface.
|
||||||
|
4. Report ATS weakening, over-broad entitlements, insecure URL-scheme handling, and outdated frameworks with CVEs.
|
||||||
|
|
||||||
|
Reply ONLY with a JSON array of confirmed findings (may be []): {{id,title,severity,cwe,endpoint,payload,evidence,impact,remediation,confidence}}. `endpoint` = the file path / class / method / offset the finding lives at. Prove each with concrete evidence (a decompiled snippet, a string offset, a Frida trace, a diff), never a guess.
|
||||||
|
## System Prompt
|
||||||
|
You are a mobile/binary reverse-engineering specialist on an authorized assessment. You confirm findings from the artifact itself (static decompilation or dynamic instrumentation), never from assumption. Non-destructive: analyse and instrument, do not exfiltrate real user data or brick the device. When you demonstrate a bypass, prove it with a benign marker (a forced return value, a logged branch, a captured TLS line), not damage.
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Mobile Network Traffic Analysis
|
||||||
|
## User Prompt
|
||||||
|
You are analysing **{target}** (a binary, APK or IPA on disk) for: Mobile Network Traffic Analysis. CWE-319
|
||||||
|
|
||||||
|
**Context:**
|
||||||
|
{recon_json}
|
||||||
|
|
||||||
|
All tools run HEADLESS (no GUI). Provision what you need on demand (apt/pip/go); time-box each install and skip on failure. Only test artifacts you are authorized to test.
|
||||||
|
|
||||||
|
### Method
|
||||||
|
1. Route the app through an intercepting proxy (mitmproxy headless / Burp) after handling pinning (see the pinning skill). Capture the full request/response set.
|
||||||
|
2. Inspect: cleartext HTTP, weak TLS config, sensitive data in URLs/params/bodies, missing auth on API calls, IDOR/BOLA on mobile-only endpoints, tokens without expiry, and secrets in headers.
|
||||||
|
3. Optionally hook TLS with a Frida keylog (`SSL_CTX`/`SSLWrite`) to read plaintext when a proxy is impractical.
|
||||||
|
4. Report cleartext transmission, weak transport, and any server-side API flaw reachable from the app, each with a captured (redacted) exchange.
|
||||||
|
|
||||||
|
Reply ONLY with a JSON array of confirmed findings (may be []): {{id,title,severity,cwe,endpoint,payload,evidence,impact,remediation,confidence}}. `endpoint` = the file path / class / method / offset the finding lives at. Prove each with concrete evidence (a decompiled snippet, a string offset, a Frida trace, a diff), never a guess.
|
||||||
|
## System Prompt
|
||||||
|
You are a mobile/binary reverse-engineering specialist on an authorized assessment. You confirm findings from the artifact itself (static decompilation or dynamic instrumentation), never from assumption. Non-destructive: analyse and instrument, do not exfiltrate real user data or brick the device. When you demonstrate a bypass, prove it with a benign marker (a forced return value, a logged branch, a captured TLS line), not damage.
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Obfuscation Analysis and Deobfuscation
|
||||||
|
## User Prompt
|
||||||
|
You are analysing **{target}** (a binary, APK or IPA on disk) for: Obfuscation Analysis and Deobfuscation. CWE-656
|
||||||
|
|
||||||
|
**Context:**
|
||||||
|
{recon_json}
|
||||||
|
|
||||||
|
All tools run HEADLESS (no GUI). Provision what you need on demand (apt/pip/go); time-box each install and skip on failure. Only test artifacts you are authorized to test.
|
||||||
|
|
||||||
|
### Method
|
||||||
|
1. Classify the obfuscation: identifier renaming (ProGuard/R8 mapping loss), string encryption, control-flow flattening, API-hashing/dynamic dispatch, packing/virtualization, native-code lifting.
|
||||||
|
2. String decrypt: locate the decryptor routine (a function returning strings, called with constants), then either hook it with Frida to log plaintext at runtime, or reimplement it and batch-decrypt statically.
|
||||||
|
3. Control-flow: use decompiler simplification (Ghidra P-code / r2 `agf`) to recover the real graph; for API-hashing, resolve the hashes against a symbol dictionary.
|
||||||
|
4. Report the obfuscation techniques present, whether they meaningfully impede analysis, and recover the sensitive logic (auth, crypto, endpoints) as evidence.
|
||||||
|
|
||||||
|
Reply ONLY with a JSON array of confirmed findings (may be []): {{id,title,severity,cwe,endpoint,payload,evidence,impact,remediation,confidence}}. `endpoint` = the file path / class / method / offset the finding lives at. Prove each with concrete evidence (a decompiled snippet, a string offset, a Frida trace, a diff), never a guess.
|
||||||
|
## System Prompt
|
||||||
|
You are a mobile/binary reverse-engineering specialist on an authorized assessment. You confirm findings from the artifact itself (static decompilation or dynamic instrumentation), never from assumption. Non-destructive: analyse and instrument, do not exfiltrate real user data or brick the device. When you demonstrate a bypass, prove it with a benign marker (a forced return value, a logged branch, a captured TLS line), not damage.
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# RASP and Anti-Tamper Mapping
|
||||||
|
## User Prompt
|
||||||
|
You are analysing **{target}** (a binary, APK or IPA on disk) for: RASP and Anti-Tamper Mapping. CWE-693
|
||||||
|
|
||||||
|
**Context:**
|
||||||
|
{recon_json}
|
||||||
|
|
||||||
|
All tools run HEADLESS (no GUI). Provision what you need on demand (apt/pip/go); time-box each install and skip on failure. Only test artifacts you are authorized to test.
|
||||||
|
|
||||||
|
### Method
|
||||||
|
A client-side protection layer (RASP/anti-tamper/app-hardening) runs in-process and is attacker-controllable. First MAP it, then the bypass skills neutralize it.
|
||||||
|
1. Fingerprint the protection: unusual native libs (`lib*.so` with high entropy), packer stubs, JNI `System.loadLibrary` early in the lifecycle, large obfuscated init routines, integrity/telemetry callbacks.
|
||||||
|
2. Enumerate what it gates: startup abort, feature disable, screenshot block, screen-recording block, overlay/tap-jacking defense, keyboard hardening, emulator/root/debug gates.
|
||||||
|
3. List every enforcement site (these layers are redundant on purpose): each function whose verdict drives an abort/disable, so a later hook set is complete.
|
||||||
|
4. Report the protection surface as an informational map plus any layer that is trivially bypassable; hand the site list to the detection/bypass skills.
|
||||||
|
|
||||||
|
Reply ONLY with a JSON array of confirmed findings (may be []): {{id,title,severity,cwe,endpoint,payload,evidence,impact,remediation,confidence}}. `endpoint` = the file path / class / method / offset the finding lives at. Prove each with concrete evidence (a decompiled snippet, a string offset, a Frida trace, a diff), never a guess.
|
||||||
|
## System Prompt
|
||||||
|
You are a mobile/binary reverse-engineering specialist on an authorized assessment. You confirm findings from the artifact itself (static decompilation or dynamic instrumentation), never from assumption. Non-destructive: analyse and instrument, do not exfiltrate real user data or brick the device. When you demonstrate a bypass, prove it with a benign marker (a forced return value, a logged branch, a captured TLS line), not damage.
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Root/Jailbreak Detection and Bypass
|
||||||
|
## User Prompt
|
||||||
|
You are analysing **{target}** (a binary, APK or IPA on disk) for: Root/Jailbreak Detection and Bypass. CWE-919
|
||||||
|
|
||||||
|
**Context:**
|
||||||
|
{recon_json}
|
||||||
|
|
||||||
|
All tools run HEADLESS (no GUI). Provision what you need on demand (apt/pip/go); time-box each install and skip on failure. Only test artifacts you are authorized to test.
|
||||||
|
|
||||||
|
### Method
|
||||||
|
1. Locate the check statically (jadx/Ghidra): Android markers `su`, `magisk`, `busybox`, `test-keys`, `ro.debuggable`, `Build.TAGS`, RootBeer; iOS markers `/Applications/Cydia.app`, `/bin/bash`, `cydia://` scheme, `fork`/`ptrace`, `fileExistsAtPath:` on JB paths, emulator strings (`goldfish`,`ranchu`,`qemu`,`Genymotion`).
|
||||||
|
2. Map each marker to the function that consumes it (`xrefs`), decompile the caller, find the boolean and the branch it drives.
|
||||||
|
3. Bypass with Frida (`frida -U -f <id>`): `Interceptor.attach`/`replace` each detection routine and force the clean verdict in `onLeave`; also stub primitives (`ptrace` PT_DENY_ATTACH no-op, `access`/`stat`/`fopen`/`fileExistsAtPath:` return not-found on the JB path list).
|
||||||
|
4. Verify no anti-Frida tripwire re-arms the gate. Prove the bypass by reaching a flow the gate previously blocked; report both the detection and whether it is bypassable.
|
||||||
|
|
||||||
|
Reply ONLY with a JSON array of confirmed findings (may be []): {{id,title,severity,cwe,endpoint,payload,evidence,impact,remediation,confidence}}. `endpoint` = the file path / class / method / offset the finding lives at. Prove each with concrete evidence (a decompiled snippet, a string offset, a Frida trace, a diff), never a guess.
|
||||||
|
## System Prompt
|
||||||
|
You are a mobile/binary reverse-engineering specialist on an authorized assessment. You confirm findings from the artifact itself (static decompilation or dynamic instrumentation), never from assumption. Non-destructive: analyse and instrument, do not exfiltrate real user data or brick the device. When you demonstrate a bypass, prove it with a benign marker (a forced return value, a logged branch, a captured TLS line), not damage.
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# TLS Certificate Pinning Detection and Bypass
|
||||||
|
## User Prompt
|
||||||
|
You are analysing **{target}** (a binary, APK or IPA on disk) for: TLS Certificate Pinning Detection and Bypass. CWE-295
|
||||||
|
|
||||||
|
**Context:**
|
||||||
|
{recon_json}
|
||||||
|
|
||||||
|
All tools run HEADLESS (no GUI). Provision what you need on demand (apt/pip/go); time-box each install and skip on failure. Only test artifacts you are authorized to test.
|
||||||
|
|
||||||
|
### Method
|
||||||
|
1. Detect pinning statically: Android `NetworkSecurityConfig` `<pin-digest>`, OkHttp `CertificatePinner`, TrustManager overrides, `checkServerTrusted` custom logic; iOS `SecTrustEvaluate`/`SecTrustEvaluateWithError`, `URLSession` delegate `didReceiveChallenge`, AFNetworking `AFSecurityPolicy` pinning.
|
||||||
|
2. Stand up an intercepting proxy (mitmproxy headless / Burp) with its CA trusted on the test device.
|
||||||
|
3. Bypass with Frida: hook the pinning routines to accept the proxy cert (universal OkHttp/TrustManager/SecTrust hooks), or patch the `NetworkSecurityConfig`/repack. Confirm by observing decrypted app traffic through the proxy.
|
||||||
|
4. Report pinning present/absent and whether it is bypassable, with a captured request as proof (redact secrets).
|
||||||
|
|
||||||
|
Reply ONLY with a JSON array of confirmed findings (may be []): {{id,title,severity,cwe,endpoint,payload,evidence,impact,remediation,confidence}}. `endpoint` = the file path / class / method / offset the finding lives at. Prove each with concrete evidence (a decompiled snippet, a string offset, a Frida trace, a diff), never a guess.
|
||||||
|
## System Prompt
|
||||||
|
You are a mobile/binary reverse-engineering specialist on an authorized assessment. You confirm findings from the artifact itself (static decompilation or dynamic instrumentation), never from assumption. Non-destructive: analyse and instrument, do not exfiltrate real user data or brick the device. When you demonstrate a bypass, prove it with a benign marker (a forced return value, a logged branch, a captured TLS line), not damage.
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Static Binary Triage
|
||||||
|
## User Prompt
|
||||||
|
You are analysing **{target}** (a binary, APK or IPA on disk) for: Static Binary Triage. CWE-1329
|
||||||
|
|
||||||
|
**Context:**
|
||||||
|
{recon_json}
|
||||||
|
|
||||||
|
All tools run HEADLESS (no GUI). Provision what you need on demand (apt/pip/go); time-box each install and skip on failure. Only test artifacts you are authorized to test.
|
||||||
|
|
||||||
|
### Method
|
||||||
|
1. Identify format/arch: `file`, `lipo -info` (Mach-O fat), `readelf -h` (ELF). For Mach-O/ELF/PE run Ghidra HEADLESS: `analyzeHeadless <proj_dir> tmp -import <bin> -postScript <script> -scriptPath .` (no GUI); or `r2 -A <bin>` / `rizin`.
|
||||||
|
2. Surface: imports/exports (`nm`, `objdump -T`, r2 `ii`/`iE`), strings (`strings -a`, r2 `izz`), sections and entropy (`binwalk -E`, high entropy => packed/encrypted).
|
||||||
|
3. Mitigations: `checksec --file=<bin>` (PIE, NX, RELRO, canary, ARC) and, for Mach-O, `codesign -dv`, `otool -hv` (PIE flag), restrict segment presence.
|
||||||
|
4. Report missing exploit mitigations, dangerous imports (`system`, `dlopen`, `exec*`, `NSTask`), and packer/obfuscation indicators as findings; feed the map to the deeper skills.
|
||||||
|
|
||||||
|
Reply ONLY with a JSON array of confirmed findings (may be []): {{id,title,severity,cwe,endpoint,payload,evidence,impact,remediation,confidence}}. `endpoint` = the file path / class / method / offset the finding lives at. Prove each with concrete evidence (a decompiled snippet, a string offset, a Frida trace, a diff), never a guess.
|
||||||
|
## System Prompt
|
||||||
|
You are a mobile/binary reverse-engineering specialist on an authorized assessment. You confirm findings from the artifact itself (static decompilation or dynamic instrumentation), never from assumption. Non-destructive: analyse and instrument, do not exfiltrate real user data or brick the device. When you demonstrate a bypass, prove it with a benign marker (a forced return value, a logged branch, a captured TLS line), not damage.
|
||||||
@@ -374,6 +374,26 @@ enum Cmd {
|
|||||||
},
|
},
|
||||||
/// Infra/host: scan an IP/host and run Linux/Windows/AD agents. SSH/Windows
|
/// Infra/host: scan an IP/host and run Linux/Windows/AD agents. SSH/Windows
|
||||||
/// credentials come from --creds (creds.yaml ssh:/windows: blocks).
|
/// credentials come from --creds (creds.yaml ssh:/windows: blocks).
|
||||||
|
/// Mobile / binary: analyse a LOCAL artifact (a binary, APK or IPA) with the
|
||||||
|
/// mobile RE agents (Ghidra headless, MobSF, Frida, apktool/jadx).
|
||||||
|
Mobile {
|
||||||
|
/// Path to the artifact on disk (.apk / .ipa / a binary).
|
||||||
|
path: String,
|
||||||
|
#[arg(long = "model")]
|
||||||
|
models: Vec<String>,
|
||||||
|
#[arg(long, default_value_t = 0)]
|
||||||
|
max_agents: usize,
|
||||||
|
#[arg(long, default_value_t = 1)]
|
||||||
|
vote_n: usize,
|
||||||
|
#[arg(long)]
|
||||||
|
offline: bool,
|
||||||
|
#[arg(long)]
|
||||||
|
subscription: bool,
|
||||||
|
#[arg(long)]
|
||||||
|
focus: Option<String>,
|
||||||
|
#[arg(short, long)]
|
||||||
|
verbose: bool,
|
||||||
|
},
|
||||||
Host {
|
Host {
|
||||||
/// Target host or IP.
|
/// Target host or IP.
|
||||||
target: String,
|
target: String,
|
||||||
@@ -868,6 +888,18 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
let mode = if repo.is_some() { Mode::Grey } else { Mode::Black };
|
let mode = if repo.is_some() { Mode::Grey } else { Mode::Black };
|
||||||
tui::run(&base, cfg, mcp, mode).await?;
|
tui::run(&base, cfg, mcp, mode).await?;
|
||||||
}
|
}
|
||||||
|
Cmd::Mobile { path, models, max_agents, vote_n, offline, subscription, focus, verbose } => {
|
||||||
|
let mut cfg = RunConfig::new(&path);
|
||||||
|
cfg.max_agents = max_agents;
|
||||||
|
cfg.vote_n = vote_n;
|
||||||
|
cfg.offline = offline;
|
||||||
|
cfg.subscription = subscription;
|
||||||
|
cfg.verbose = verbose;
|
||||||
|
cfg.instructions = focus;
|
||||||
|
if !models.is_empty() { cfg.models = models; }
|
||||||
|
let out = run_mode(&base, cfg, false, Mode::Mobile).await?;
|
||||||
|
print_findings(&out);
|
||||||
|
}
|
||||||
Cmd::Host { target, models, creds, focus, max_agents, vote_n, chain_depth, recon, offline, subscription, verbose } => {
|
Cmd::Host { target, models, creds, focus, max_agents, vote_n, chain_depth, recon, offline, subscription, verbose } => {
|
||||||
let mut cfg = RunConfig::new(&target);
|
let mut cfg = RunConfig::new(&target);
|
||||||
cfg.max_agents = max_agents;
|
cfg.max_agents = max_agents;
|
||||||
@@ -1072,7 +1104,7 @@ pub(crate) async fn apply_creds(cfg: &mut RunConfig, path: Option<&str>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
pub(crate) enum Mode { Black, White, Grey, Host, Ai, Skills }
|
pub(crate) enum Mode { Black, White, Grey, Host, Ai, Skills, Mobile }
|
||||||
|
|
||||||
pub(crate) async fn run_greybox_engagement(base: &Path, cfg: RunConfig, mcp: bool) -> anyhow::Result<RunOutput> {
|
pub(crate) async fn run_greybox_engagement(base: &Path, cfg: RunConfig, mcp: bool) -> anyhow::Result<RunOutput> {
|
||||||
run_mode(base, cfg, mcp, Mode::Grey).await
|
run_mode(base, cfg, mcp, Mode::Grey).await
|
||||||
@@ -1172,7 +1204,7 @@ pub(crate) fn spawn_engagement(base: &Path, mut cfg: RunConfig, mcp: bool, mode:
|
|||||||
println!(" │ repo : {}", cfg.repo.clone().unwrap_or_default());
|
println!(" │ repo : {}", cfg.repo.clone().unwrap_or_default());
|
||||||
}
|
}
|
||||||
println!(" └─ mode : {}{}{}",
|
println!(" └─ mode : {}{}{}",
|
||||||
match mode { Mode::White => "white-box", Mode::Grey => "greybox", Mode::Host => "host/infra", Mode::Ai => "ai/llm", Mode::Skills => "skills/n8n audit", Mode::Black => "black-box" },
|
match mode { Mode::White => "white-box", Mode::Grey => "greybox", Mode::Host => "host/infra", Mode::Ai => "ai/llm", Mode::Skills => "skills/n8n audit", Mode::Mobile => "mobile/binary", Mode::Black => "black-box" },
|
||||||
if cfg.subscription { " · subscription" } else { " · api" },
|
if cfg.subscription { " · subscription" } else { " · api" },
|
||||||
if mcp { " · mcp" } else { "" });
|
if mcp { " · mcp" } else { "" });
|
||||||
|
|
||||||
@@ -1211,6 +1243,7 @@ pub(crate) fn spawn_engagement(base: &Path, mut cfg: RunConfig, mcp: bool, mode:
|
|||||||
Mode::Host => harness::run_host(cfg, &lib, &pool, tx).await,
|
Mode::Host => harness::run_host(cfg, &lib, &pool, tx).await,
|
||||||
Mode::Ai => harness::pipeline::run_ai(cfg, &lib, &pool, tx).await,
|
Mode::Ai => harness::pipeline::run_ai(cfg, &lib, &pool, tx).await,
|
||||||
Mode::Skills => harness::pipeline::run_skills_audit(cfg, &lib, &pool, tx).await,
|
Mode::Skills => harness::pipeline::run_skills_audit(cfg, &lib, &pool, tx).await,
|
||||||
|
Mode::Mobile => harness::run_mobile(cfg, &lib, &pool, tx).await,
|
||||||
Mode::Black => harness::run(cfg, &lib, &pool, tx).await,
|
Mode::Black => harness::run(cfg, &lib, &pool, tx).await,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//! NeuroSploit v4.1.0 — interactive session (Claude-Code / Codex / Cursor-CLI style).
|
//! NeuroSploit v4.2.0 — interactive session (Claude-Code / Codex / Cursor-CLI style).
|
||||||
//!
|
//!
|
||||||
//! Launched when `neurosploit` runs with no subcommand. A persistent REPL with
|
//! Launched when `neurosploit` runs with no subcommand. A persistent REPL with
|
||||||
//! real line editing (arrow-key history recall, Ctrl-A/E/K, paste), model
|
//! real line editing (arrow-key history recall, Ctrl-A/E/K, paste), model
|
||||||
@@ -440,7 +440,7 @@ pub async fn repl(base: &Path, auth: SessionAuth) -> anyhow::Result<()> {
|
|||||||
let backends = harness::installed_cli_backends();
|
let backends = harness::installed_cli_backends();
|
||||||
println!("\x1b[1m");
|
println!("\x1b[1m");
|
||||||
println!(" ███╗ ██╗███████╗██╗ ██╗██████╗ ██████╗");
|
println!(" ███╗ ██╗███████╗██╗ ██╗██████╗ ██████╗");
|
||||||
println!(" ████╗ ██║██╔════╝██║ ██║██╔══██╗██╔═══██╗ NeuroSploit v4.1.0");
|
println!(" ████╗ ██║██╔════╝██║ ██║██╔══██╗██╔═══██╗ NeuroSploit v4.2.0");
|
||||||
println!(" ██╔██╗ ██║█████╗ ██║ ██║██████╔╝██║ ██║ interactive harness");
|
println!(" ██╔██╗ ██║█████╗ ██║ ██║██████╔╝██║ ██║ interactive harness");
|
||||||
println!(" ██║╚██╗██║██╔══╝ ██║ ██║██╔══██╗██║ ██║ by Joas A Santos");
|
println!(" ██║╚██╗██║██╔══╝ ██║ ██║██╔══██╗██║ ██║ by Joas A Santos");
|
||||||
println!(" ██║ ╚████║███████╗╚██████╔╝██║ ██║╚██████╔╝ & Red Team Leaders");
|
println!(" ██║ ╚████║███████╗╚██████╔╝██║ ██║╚██████╔╝ & Red Team Leaders");
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//! NeuroSploit v4.1.0 — TUI "Mission Control" mode.
|
//! NeuroSploit v4.2.0 — TUI "Mission Control" mode.
|
||||||
//!
|
//!
|
||||||
//! Concurrent panels that update live while the engagement runs in the
|
//! Concurrent panels that update live while the engagement runs in the
|
||||||
//! background, with a composer input that stays active during execution:
|
//! background, with a composer input that stays active during execution:
|
||||||
@@ -148,7 +148,7 @@ pub async fn run(base: &Path, mut cfg: RunConfig, mcp: bool, mode: Mode) -> anyh
|
|||||||
|
|
||||||
let (tx, mut rx) = tokio::sync::mpsc::channel::<String>(512);
|
let (tx, mut rx) = tokio::sync::mpsc::channel::<String>(512);
|
||||||
let models = cfg.models.join(", ");
|
let models = cfg.models.join(", ");
|
||||||
let mode_s = match mode { Mode::White => "white-box", Mode::Grey => "greybox", Mode::Host => "host/infra", Mode::Ai => "ai/llm", Mode::Skills => "skills/n8n", Mode::Black => "black-box" };
|
let mode_s = match mode { Mode::White => "white-box", Mode::Grey => "greybox", Mode::Host => "host/infra", Mode::Ai => "ai/llm", Mode::Skills => "skills/n8n", Mode::Mobile => "mobile/binary", Mode::Black => "black-box" };
|
||||||
let target_s = cfg.target.clone();
|
let target_s = cfg.target.clone();
|
||||||
|
|
||||||
// ---- terminal setup FIRST: on a non-TTY this errors before we spawn any
|
// ---- terminal setup FIRST: on a non-TTY this errors before we spawn any
|
||||||
@@ -165,6 +165,7 @@ pub async fn run(base: &Path, mut cfg: RunConfig, mcp: bool, mode: Mode) -> anyh
|
|||||||
Mode::Host => harness::run_host(cfg, &lib, &pool, tx).await,
|
Mode::Host => harness::run_host(cfg, &lib, &pool, tx).await,
|
||||||
Mode::Ai => harness::pipeline::run_ai(cfg, &lib, &pool, tx).await,
|
Mode::Ai => harness::pipeline::run_ai(cfg, &lib, &pool, tx).await,
|
||||||
Mode::Skills => harness::pipeline::run_skills_audit(cfg, &lib, &pool, tx).await,
|
Mode::Skills => harness::pipeline::run_skills_audit(cfg, &lib, &pool, tx).await,
|
||||||
|
Mode::Mobile => harness::run_mobile(cfg, &lib, &pool, tx).await,
|
||||||
Mode::Black => harness::run(cfg, &lib, &pool, tx).await,
|
Mode::Black => harness::run(cfg, &lib, &pool, tx).await,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -27,12 +27,13 @@ pub struct Library {
|
|||||||
pub chains: Vec<Agent>,
|
pub chains: Vec<Agent>,
|
||||||
/// AI/LLM/agent/MCP/skills security agents (OWASP LLM Top 10, MCP risks…).
|
/// AI/LLM/agent/MCP/skills security agents (OWASP LLM Top 10, MCP risks…).
|
||||||
pub ai: Vec<Agent>,
|
pub ai: Vec<Agent>,
|
||||||
|
pub mobile: Vec<Agent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Library {
|
impl Library {
|
||||||
pub fn total(&self) -> usize {
|
pub fn total(&self) -> usize {
|
||||||
self.vulns.len() + self.meta.len() + self.recon.len() + self.code.len()
|
self.vulns.len() + self.meta.len() + self.recon.len() + self.code.len()
|
||||||
+ self.infra.len() + self.chains.len() + self.ai.len()
|
+ self.infra.len() + self.chains.len() + self.ai.len() + self.mobile.len()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,6 +48,7 @@ pub fn load(base: &Path) -> Library {
|
|||||||
infra: load_dir(&root.join("infra"), "infra"),
|
infra: load_dir(&root.join("infra"), "infra"),
|
||||||
chains: load_dir(&root.join("chains"), "chain"),
|
chains: load_dir(&root.join("chains"), "chain"),
|
||||||
ai: load_dir(&root.join("ai"), "ai"),
|
ai: load_dir(&root.join("ai"), "ai"),
|
||||||
|
mobile: load_dir(&root.join("mobile"), "mobile"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ pub use models::{
|
|||||||
cli_binary_for, ensure_playwright_mcp, installed_cli_backends, mcp_supported, provider_for,
|
cli_binary_for, ensure_playwright_mcp, installed_cli_backends, mcp_supported, provider_for,
|
||||||
providers, write_mcp_config, ChatClient, ModelRef, Provider,
|
providers, write_mcp_config, ChatClient, ModelRef, Provider,
|
||||||
};
|
};
|
||||||
pub use pipeline::{run_greybox, run_host, run_whitebox, RunOutput};
|
pub use pipeline::{run_greybox, run_host, run_mobile, run_whitebox, RunOutput};
|
||||||
pub use pipeline::run;
|
pub use pipeline::run;
|
||||||
pub use knowledge_graph::{EdgeKind, KnowledgeGraph, NodeKind};
|
pub use knowledge_graph::{EdgeKind, KnowledgeGraph, NodeKind};
|
||||||
pub use memory::{Memory, Query as MemoryQuery, Tier as MemoryTier};
|
pub use memory::{Memory, Query as MemoryQuery, Tier as MemoryTier};
|
||||||
|
|||||||
@@ -3242,6 +3242,94 @@ fn collect_repo_context(root: &Path, max_files: usize, max_bytes: usize) -> Stri
|
|||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MOBILE_RECON_SYS: &str = "You are a mobile/binary reverse-engineering recon specialist on an AUTHORIZED assessment of a LOCAL artifact (a binary, APK or IPA on disk). Identify format/arch, package metadata, entry points, protection layers (RASP/anti-tamper, root/JB and anti-debug detection, TLS pinning, obfuscation/packing), the attack surface (exported components, URL schemes, entitlements, linked frameworks) and hardcoded secrets/endpoints. Run everything HEADLESS (MobSF REST/Docker, Ghidra analyzeHeadless, apktool, jadx, otool/nm, r2). Do not ask permission; proceed. Reply with a compact JSON object (format, arch, package, protections, surface, secrets). No prose.";
|
||||||
|
|
||||||
|
const MOBILE_TOOLING: &str = "TOOLING (all HEADLESS; provision on demand, time-box installs): APK/IPA static -> MobSF via its REST API (Docker image), `apktool`, `jadx`, `apkleaks`; binaries -> Ghidra `analyzeHeadless`, `radare2`/`rizin`, `binwalk`, `checksec`, `nm`/`otool`/`objdump`, `class-dump`; dynamic -> `frida`/`objection` for detection/pinning/anti-debug bypass; secrets -> `trufflehog`/`gitleaks`. Never require a GUI or an X display. Analyse and instrument non-destructively; never exfiltrate real user data.\n\n";
|
||||||
|
|
||||||
|
/// Mobile / binary engagement: analyse a LOCAL artifact (binary, APK or IPA) and
|
||||||
|
/// run the mobile RE agents. Mirrors the host pipeline but the target is a file
|
||||||
|
/// and the agent set is `mobile`.
|
||||||
|
pub async fn run_mobile(cfg: RunConfig, lib: &Library, pool: &ModelPool, tx: Sender<String>) -> RunOutput {
|
||||||
|
pool.set_progress(tx.clone());
|
||||||
|
let _ = tx.send(format!("MOBILE/BINARY - artifact: {} - {} mobile agents - models: {}", cfg.target, lib.mobile.len(),
|
||||||
|
pool.candidates.iter().map(|m| m.label()).collect::<Vec<_>>().join(", "))).await;
|
||||||
|
|
||||||
|
let recon = if cfg.offline {
|
||||||
|
"{}".to_string()
|
||||||
|
} else {
|
||||||
|
let user = format!("{}{}Artifact path: {}", operator_directives(&cfg), MOBILE_TOOLING, cfg.target);
|
||||||
|
match pool.complete_routed(Task::Recon, "recon", MOBILE_RECON_SYS, &user).await {
|
||||||
|
Ok((m, t)) => { let _ = tx.send(format!("recon complete via {}", m.label())).await; t }
|
||||||
|
Err(e) => { let _ = tx.send(format!("recon failed ({e})")).await; "{}".to_string() }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut rl = cfg.rl_path.as_ref().map(|p| RlState::load(Path::new(p))).unwrap_or_default();
|
||||||
|
let mut ranked: Vec<Agent> = lib.mobile.clone();
|
||||||
|
ranked.sort_by(|a, b| rl.weight(&b.name).partial_cmp(&rl.weight(&a.name)).unwrap_or(std::cmp::Ordering::Equal));
|
||||||
|
let cap = if cfg.max_agents > 0 { cfg.max_agents.min(ranked.len()) } else { ranked.len() };
|
||||||
|
let focus = cfg.instructions.clone().unwrap_or_default();
|
||||||
|
|
||||||
|
if cfg.offline {
|
||||||
|
let selected: Vec<Agent> = ranked.into_iter().take(cap).collect();
|
||||||
|
let _ = tx.send(format!("offline: selected {} mobile agent(s); no live analysis", selected.len())).await;
|
||||||
|
let artifacts = persist(&cfg, &recon, "", &[]);
|
||||||
|
return RunOutput { target: cfg.target.clone(), workdir: cfg.workdir.clone().unwrap_or_default(), findings: vec![],
|
||||||
|
agents_ran: selected.iter().map(|a| a.name.clone()).collect(), candidates: 0, recon, artifacts, denied: None };
|
||||||
|
}
|
||||||
|
|
||||||
|
let chosen = select_agents(pool, &recon, &focus, &ranked, &tx).await;
|
||||||
|
let selected: Vec<Agent> = if !chosen.is_empty() {
|
||||||
|
let sel: Vec<Agent> = ranked.iter().filter(|a| chosen.iter().any(|c| c == &a.name)).cloned().collect();
|
||||||
|
if sel.is_empty() { ranked.iter().take(cap).cloned().collect() } else { sel.into_iter().take(cap).collect() }
|
||||||
|
} else {
|
||||||
|
ranked.iter().take(cap).cloned().collect()
|
||||||
|
};
|
||||||
|
let selected: Vec<Agent> = { let mut seen = std::collections::HashSet::new();
|
||||||
|
selected.into_iter().filter(|a| seen.insert(a.name.clone())).collect() };
|
||||||
|
let _ = tx.send(format!("selected {} mobile agent(s): {}", selected.len(),
|
||||||
|
selected.iter().map(|a| a.name.clone()).collect::<Vec<_>>().join(", "))).await;
|
||||||
|
|
||||||
|
let target = cfg.target.clone();
|
||||||
|
let verbose = cfg.verbose;
|
||||||
|
let directives = operator_directives(&cfg);
|
||||||
|
let recon_ctx: String = recon.chars().take(3000).collect();
|
||||||
|
let raw: Vec<(String, String, Vec<Finding>)> = stream::iter(selected.iter().cloned())
|
||||||
|
.map(|ag| {
|
||||||
|
let target = target.clone();
|
||||||
|
let recon = recon_ctx.clone();
|
||||||
|
let directives = directives.clone();
|
||||||
|
let txc = tx.clone();
|
||||||
|
async move {
|
||||||
|
if pool.stop_exploiting() { return (ag.name.clone(), String::new(), vec![]); }
|
||||||
|
if verbose { let _ = txc.send(format!(" launching agent: {} ({})", ag.name, ag.title.replace(" Agent", ""))).await; }
|
||||||
|
let user = format!(
|
||||||
|
"AUTHORIZED mobile/binary assessment of {target}. Proceed and PROVE each issue from the artifact itself.\n\n{directives}{tooling}{react}{safety}{body}\n\nReply ONLY a JSON array of confirmed findings (may be []): {{id,title,severity,cwe,endpoint,payload,evidence,impact,remediation,confidence}}.",
|
||||||
|
target = target, directives = directives, tooling = MOBILE_TOOLING, react = REACT_DOCTRINE, safety = SAFETY_DOCTRINE,
|
||||||
|
body = ag.user.replace("{target}", &target).replace("{recon_json}", &recon),
|
||||||
|
);
|
||||||
|
match pool.complete_routed(Task::Exploit, &ag.name, &ag.system, &user).await {
|
||||||
|
Ok((m, text)) => {
|
||||||
|
let f = extract_findings(&text, &ag.name);
|
||||||
|
let _ = txc.send(format!("test {} via {} -> {} candidate(s)", ag.name, m.label(), f.len())).await;
|
||||||
|
for c in &f { if let Ok(j) = serde_json::to_string(c) { let _ = txc.send(format!("finding_json: {j}")).await; } }
|
||||||
|
(ag.name.clone(), text, f)
|
||||||
|
}
|
||||||
|
Err(e) => { let _ = txc.send(format!("test {} failed: {e}", ag.name)).await; (ag.name.clone(), format!("ERROR: {e}"), vec![]) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.buffer_unordered(cfg.concurrency)
|
||||||
|
.collect::<Vec<_>>().await;
|
||||||
|
|
||||||
|
let transcript = transcript_of(&raw);
|
||||||
|
let candidates = dedup_findings(raw.iter().flat_map(|(_, _, f)| f.clone()).collect());
|
||||||
|
let _ = tx.send(format!("{} candidate finding(s) (deduped) - validating", candidates.len())).await;
|
||||||
|
let findings = validate(candidates, pool, VOTE_SYS, effective_vote_n(&cfg), &tx).await;
|
||||||
|
let findings = refute_pass(findings, pool, effective_vote_n(&cfg), &tx).await;
|
||||||
|
finish(cfg, lib, pool, recon, transcript, findings, selected, &mut rl, crate::grounding::GroundMode::Empirical, String::new(), tx).await
|
||||||
|
}
|
||||||
|
|
||||||
const HOST_RECON_SYS: &str = "You are an infrastructure recon specialist on an AUTHORIZED engagement against a HOST/IP. Actively scan with rustscan/nmap (and netexec/smbclient where relevant) to map open ports, services, versions and auth surfaces. Use any provided SSH/Windows credentials to enumerate from inside. Do not ask permission; proceed. Reply with a compact JSON object (host, os, ports, services, auth, ad). No prose.";
|
const HOST_RECON_SYS: &str = "You are an infrastructure recon specialist on an AUTHORIZED engagement against a HOST/IP. Actively scan with rustscan/nmap (and netexec/smbclient where relevant) to map open ports, services, versions and auth surfaces. Use any provided SSH/Windows credentials to enumerate from inside. Do not ask permission; proceed. Reply with a compact JSON object (host, os, ports, services, auth, ad). No prose.";
|
||||||
|
|
||||||
const HOST_TOOLING: &str = "TOOLING (best on Kali): nmap/rustscan (ports), netexec/crackmapexec + smbclient (SMB/AD), ssh/sshpass + linpeas (Linux), evil-winrm + winPEAS + impacket (Windows), bloodhound-python/SharpHound (AD), hashcat (offline cracking). Use only supplied credentials; never brute force or run destructive/DoS actions.\n\n";
|
const HOST_TOOLING: &str = "TOOLING (best on Kali): nmap/rustscan (ports), netexec/crackmapexec + smbclient (SMB/AD), ssh/sshpass + linpeas (Linux), evil-winrm + winPEAS + impacket (Windows), bloodhound-python/SharpHound (AD), hashcat (offline cracking). Use only supplied credentials; never brute force or run destructive/DoS actions.\n\n";
|
||||||
|
|||||||
@@ -242,7 +242,7 @@ pub fn html_with_pocs(target: &str, findings: &[Finding], meta: &EngagementMeta,
|
|||||||
<h2>Executive Summary</h2><div class=summary-grid>{summary_grid}</div>\
|
<h2>Executive Summary</h2><div class=summary-grid>{summary_grid}</div>\
|
||||||
{vuln_summary}\
|
{vuln_summary}\
|
||||||
<h2>Findings ({n})</h2>{body}\
|
<h2>Findings ({n})</h2>{body}\
|
||||||
<p class=footer>Authorized testing only. Confirmed findings passed multi-model voting, receipt grounding and adversarial refute; \"needs-review\" are flagged for a human.<br>NeuroSploit v4.1.0 · by <b>Joas A Santos</b> & <b>Red Team Leaders</b><br><span style=\"font-family:ui-monospace,monospace\">{provenance}</span></p></body></html>",
|
<p class=footer>Authorized testing only. Confirmed findings passed multi-model voting, receipt grounding and adversarial refute; \"needs-review\" are flagged for a human.<br>NeuroSploit v4.2.0 · by <b>Joas A Santos</b> & <b>Red Team Leaders</b><br><span style=\"font-family:ui-monospace,monospace\">{provenance}</span></p></body></html>",
|
||||||
t = esc(target), n = sorted.len(), body = body, summary_grid = summary_grid, vuln_summary = vuln_summary,
|
t = esc(target), n = sorted.len(), body = body, summary_grid = summary_grid, vuln_summary = vuln_summary,
|
||||||
// Which build produced this document. A report that circulates without
|
// Which build produced this document. A report that circulates without
|
||||||
// it is a report nobody can trace back to the run that made it.
|
// it is a report nobody can trace back to the run that made it.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// NeuroSploit v4.1.0 — Typst report template (blank, structured).
|
// NeuroSploit v4.2.0 — Typst report template (blank, structured).
|
||||||
//
|
//
|
||||||
// The harness generates `report.typ` per run by prepending a `findings` array
|
// The harness generates `report.typ` per run by prepending a `findings` array
|
||||||
// and a `meta` dict, then including this template's rendering logic. This file
|
// and a `meta` dict, then including this template's rendering logic. This file
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
|
|
||||||
#set page(margin: 2cm, numbering: "1", footer: context [
|
#set page(margin: 2cm, numbering: "1", footer: context [
|
||||||
#set text(size: 8pt, fill: gray)
|
#set text(size: 8pt, fill: gray)
|
||||||
NeuroSploit v4.1.0 · #meta.target · confidential
|
NeuroSploit v4.2.0 · #meta.target · confidential
|
||||||
#h(1fr)
|
#h(1fr)
|
||||||
// Build+run identity, so a page that circulates on its own still says which
|
// Build+run identity, so a page that circulates on its own still says which
|
||||||
// engagement produced it.
|
// engagement produced it.
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ run this only on a trusted machine/network, same trust model as the CLI itself.
|
|||||||
Server/version info.
|
Server/version info.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{ "version": "4.1.0", "binary": "/opt/neurosploit-rs/neurosploit-rs/target/release/neurosploit", "root": "/opt/neurosploit-rs" }
|
{ "version": "4.2.0", "binary": "/opt/neurosploit-rs/neurosploit-rs/target/release/neurosploit", "root": "/opt/neurosploit-rs" }
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
# NeuroSploit v4.1.0 — web console
|
# NeuroSploit v4.2.0 — web console
|
||||||
|
|
||||||
A browser UI for the `neurosploit` CLI harness: a 5-step engagement wizard (Asset → Scope & Auth
|
A browser UI for the `neurosploit` CLI harness: a 5-step engagement wizard (Asset → Scope & Auth
|
||||||
→ Leads → Model & Run → Review), a live structured findings view with a generative attack-path
|
→ Leads → Model & Run → Review), a live structured findings view with a generative attack-path
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
/* NeuroSploit v4.1.0 — web console frontend. Vanilla JS, no build step. */
|
/* NeuroSploit v4.2.0 — web console frontend. Vanilla JS, no build step. */
|
||||||
|
|
||||||
const $ = (sel, root = document) => root.querySelector(sel);
|
const $ = (sel, root = document) => root.querySelector(sel);
|
||||||
const $$ = (sel, root = document) => Array.from(root.querySelectorAll(sel));
|
const $$ = (sel, root = document) => Array.from(root.querySelectorAll(sel));
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<title>NeuroSploit v4.1.0 — Console</title>
|
<title>NeuroSploit v4.2.0 — Console</title>
|
||||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🧠</text></svg>">
|
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🧠</text></svg>">
|
||||||
<link rel="stylesheet" href="/vendor/xterm.css" />
|
<link rel="stylesheet" href="/vendor/xterm.css" />
|
||||||
<link rel="stylesheet" href="/style.css" />
|
<link rel="stylesheet" href="/style.css" />
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
<div class="sb-groups" id="sbGroups"><!-- populated by app.js --></div>
|
<div class="sb-groups" id="sbGroups"><!-- populated by app.js --></div>
|
||||||
|
|
||||||
<div class="sb-bottom">
|
<div class="sb-bottom">
|
||||||
<span class="sb-version" id="sbVersion">v4.1.0</span>
|
<span class="sb-version" id="sbVersion">v4.2.0</span>
|
||||||
<div class="sb-bottom-actions">
|
<div class="sb-bottom-actions">
|
||||||
<button class="icon-btn" id="btnOpenAuth" title="Auth & API keys">🔑</button>
|
<button class="icon-btn" id="btnOpenAuth" title="Auth & API keys">🔑</button>
|
||||||
<button class="icon-btn" id="btnOpenRepl" title="Open terminal (Ctrl+`)">❭_</button>
|
<button class="icon-btn" id="btnOpenRepl" title="Open terminal (Ctrl+`)">❭_</button>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* NeuroSploit v4.1.0 — web console.
|
/* NeuroSploit v4.2.0 — web console.
|
||||||
Visual direction: dense security-operations console (not a marketing SaaS
|
Visual direction: dense security-operations console (not a marketing SaaS
|
||||||
page). Borders over shadows, typography over color, two radii, one accent.
|
page). Borders over shadows, typography over color, two radii, one accent.
|
||||||
*/
|
*/
|
||||||
|
|||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
'use strict';
|
'use strict';
|
||||||
/**
|
/**
|
||||||
* NeuroSploit v4.1.0 — web console backend.
|
* NeuroSploit v4.2.0 — web console backend.
|
||||||
*
|
*
|
||||||
* Zero-dependency Node HTTP server that:
|
* Zero-dependency Node HTTP server that:
|
||||||
* - serves the static SPA in ./public
|
* - serves the static SPA in ./public
|
||||||
@@ -1223,7 +1223,7 @@ const server = http.createServer(async (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
server.listen(PORT, () => {
|
server.listen(PORT, () => {
|
||||||
console.log(`NeuroSploit v4.1.0 web console → http://localhost:${PORT}`);
|
console.log(`NeuroSploit v4.2.0 web console → http://localhost:${PORT}`);
|
||||||
console.log(` binary : ${BIN || '(not found — build neurosploit-rs first)'}`);
|
console.log(` binary : ${BIN || '(not found — build neurosploit-rs first)'}`);
|
||||||
console.log(` agents : ${AGENTS_DIR}`);
|
console.log(` agents : ${AGENTS_DIR}`);
|
||||||
console.log(` runs : ${RUNS_DIR}`);
|
console.log(` runs : ${RUNS_DIR}`);
|
||||||
|
|||||||
Reference in new issue
Block a user