mirror of
https://github.com/CyberSecurityUP/NeuroSploit.git
synced 2026-09-30 21:19:49 +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
@@ -374,6 +374,26 @@ enum Cmd {
|
||||
},
|
||||
/// Infra/host: scan an IP/host and run Linux/Windows/AD agents. SSH/Windows
|
||||
/// 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 {
|
||||
/// Target host or IP.
|
||||
target: String,
|
||||
@@ -868,6 +888,18 @@ async fn main() -> anyhow::Result<()> {
|
||||
let mode = if repo.is_some() { Mode::Grey } else { Mode::Black };
|
||||
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 } => {
|
||||
let mut cfg = RunConfig::new(&target);
|
||||
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)]
|
||||
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> {
|
||||
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!(" └─ 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 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::Ai => harness::pipeline::run_ai(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,
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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
|
||||
//! 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();
|
||||
println!("\x1b[1m");
|
||||
println!(" ███╗ ██╗███████╗██╗ ██╗██████╗ ██████╗");
|
||||
println!(" ████╗ ██║██╔════╝██║ ██║██╔══██╗██╔═══██╗ NeuroSploit v4.1.0");
|
||||
println!(" ████╗ ██║██╔════╝██║ ██║██╔══██╗██╔═══██╗ NeuroSploit v4.2.0");
|
||||
println!(" ██╔██╗ ██║█████╗ ██║ ██║██████╔╝██║ ██║ interactive harness");
|
||||
println!(" ██║╚██╗██║██╔══╝ ██║ ██║██╔══██╗██║ ██║ by Joas A Santos");
|
||||
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
|
||||
//! 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 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();
|
||||
|
||||
// ---- 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::Ai => harness::pipeline::run_ai(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,
|
||||
}
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user