feat: cloud / mobile / binary-RE offensive loadouts (arsenal + detection benchmarks)
Three new category loadouts, each = arsenal + an offline-scorable benchmark, opt-in and
honestly scoped (roster marks all 🚧; pacu/frida stay catalog_only, unit-tested non-mintable):
- cloud: aws/az/gcloud + scoutsuite/cloudfox/pmapper; cloud:bench IaC-misconfig detection
- mobile: apkleaks/mobsfscan/drozer/objection/class-dump; mobile:bench static ruleset
- binary/RE: ghidra/objdump/checksec/strings/readelf/gdb; binary:bench decompiled-sink detector
Mobile/binary benches are DETECTOR REGRESSION CHECKS (rules+fixtures co-authored — a pass is a
floor, not a detection rate). No new headline numbers; verify-claims 24/24.
tsc clean; 337 tests; lint 0 errors.
This commit is contained in:
1 parent
a5667374bf
commit
537d5345dc
17 files changed
+1026
No files matched your search
@@ -56,6 +56,8 @@ describe('adapterToCustomTool — mint gate', () => {
|
||||
expect(adapterToCustomTool(adapter('metasploit'), deps)).toBeNull(); // catalog_only
|
||||
expect(adapterToCustomTool(adapter('hydra'), deps)).toBeNull(); // catalog_only
|
||||
expect(adapterToCustomTool(adapter('bloodhound'), deps)).toBeNull(); // import_only
|
||||
expect(adapterToCustomTool(adapter('pacu'), deps)).toBeNull(); // catalog_only (AWS exploitation framework)
|
||||
expect(adapterToCustomTool(adapter('frida'), deps)).toBeNull(); // catalog_only (runtime code injection)
|
||||
});
|
||||
|
||||
it('mints a command-ready adapter with a working name + category', () => {
|
||||
@@ -67,6 +69,30 @@ describe('adapterToCustomTool — mint gate', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('cloud/mobile category loadouts — presence + risk gating', () => {
|
||||
const deps = makeDeps();
|
||||
const execOf = (id: string) => adapter(id).execution;
|
||||
|
||||
it('cloud: assessment/recon tools are receipt-gated; the exploitation framework is catalog-only', () => {
|
||||
expect(execOf('scoutsuite')).toBe('receipt_required');
|
||||
expect(execOf('cloudfox')).toBe('receipt_required');
|
||||
expect(execOf('pmapper')).toBe('receipt_required');
|
||||
expect(execOf('pacu')).toBe('catalog_only');
|
||||
expect(adapter('scoutsuite').category).toBe('cloud');
|
||||
expect(adapterToCustomTool(adapter('pacu'), deps)).toBeNull(); // never callable
|
||||
});
|
||||
|
||||
it('mobile: static scanner is safe; dynamic/runtime tools are gated', () => {
|
||||
expect(execOf('apkleaks')).toBe('safe_command');
|
||||
expect(execOf('mobsfscan')).toBe('safe_command'); // static source scanner — safe
|
||||
expect(execOf('objection')).toBe('receipt_required');
|
||||
expect(execOf('frida')).toBe('catalog_only');
|
||||
expect(adapter('apkleaks').category).toBe('mobile');
|
||||
expect(adapterToCustomTool(adapter('frida'), deps)).toBeNull(); // never callable
|
||||
expect(adapterToCustomTool(adapter('apkleaks'), deps)).not.toBeNull(); // safe, mintable
|
||||
});
|
||||
});
|
||||
|
||||
describe('adapterToCustomTool — degrade / scope / execution', () => {
|
||||
it('a missing binary DEGRADES (does not throw) and surfaces the installHint', async () => {
|
||||
const deps = makeDeps({ isToolAvailable: async () => false });
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Locks the Binary/RE loadout's decompiled-vuln detector + benchmark into CI: the ruleset must catch
|
||||
* every seeded memory-safety / injection sink in the corpus and stay clean on the bounded-function
|
||||
* controls (strncpy/snprintf/fgets, literal printf). Deterministic + self-contained.
|
||||
*/
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { loadCorpus, detect, scoreCorpus, RULES } from '../../scripts/binary-vuln-bench.mjs';
|
||||
|
||||
describe('binary/RE decompiled-vuln benchmark', () => {
|
||||
const corpus = loadCorpus();
|
||||
const score = scoreCorpus(corpus);
|
||||
|
||||
it('corpus has seeded sinks + safe controls with ground truth', () => {
|
||||
expect(corpus.fixtures.length).toBeGreaterThanOrEqual(6);
|
||||
expect(corpus.fixtures.some((f) => f.clean)).toBe(true);
|
||||
expect(corpus.fixtures.every((f) => f.clean || f.expect.length > 0)).toBe(true);
|
||||
});
|
||||
|
||||
it('detects every seeded sink', () => {
|
||||
expect(score.detection.hits).toBe(score.detection.total);
|
||||
expect(score.detection.total).toBeGreaterThanOrEqual(6);
|
||||
});
|
||||
|
||||
it('does not false-positive on bounded-function controls', () => {
|
||||
expect(score.discrimination.falsePositives).toBe(0);
|
||||
// the bounded equivalents must NOT trip the unbounded rules
|
||||
expect(detect('strncpy(buf, src, sizeof(buf) - 1);').size).toBe(0);
|
||||
expect(detect('snprintf(out, sizeof(out), "%s", x);').size).toBe(0);
|
||||
expect(detect('fgets(name, sizeof(name), stdin);').size).toBe(0);
|
||||
// ...but the unbounded ones must
|
||||
expect(detect('strcpy(buf, src);').has('B-STRCPY')).toBe(true);
|
||||
expect(detect('printf(user);').has('B-FORMAT-STRING')).toBe(true);
|
||||
});
|
||||
|
||||
it('ruleset spans memory-safety + injection + integer-overflow', () => {
|
||||
expect(RULES.length).toBeGreaterThanOrEqual(6);
|
||||
expect(RULES.some((r) => r.id === 'B-CMD-INJECTION')).toBe(true);
|
||||
expect(RULES.some((r) => r.id === 'B-INT-OVERFLOW')).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Locks the Cloud loadout's IaC-misconfig benchmark scorer into CI: the parser must map checkov
|
||||
* findings to fixtures, every seeded misconfig must be detected, and the locked-down control must
|
||||
* produce zero misconfig false-positives — validated against the committed sample (no checkov needed).
|
||||
*/
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { readFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
// The benchmark logic is authored in the bench script (ESM .mjs); import its pure functions directly.
|
||||
import { loadCorpus, parseCheckov, scoreCorpus } from '../../scripts/cloud-misconfig-bench.mjs';
|
||||
|
||||
const sample = JSON.parse(readFileSync(join(process.cwd(), 'bench/cloud-misconfig/sample-checkov-output.json'), 'utf8'));
|
||||
|
||||
describe('cloud IaC-misconfig benchmark scorer', () => {
|
||||
const corpus = loadCorpus();
|
||||
const score = scoreCorpus(corpus, parseCheckov(sample));
|
||||
|
||||
it('the corpus has misconfigured fixtures + a clean control, all with ground truth', () => {
|
||||
expect(corpus.fixtures.length).toBeGreaterThanOrEqual(5);
|
||||
expect(corpus.fixtures.some((f: { clean?: boolean }) => f.clean)).toBe(true);
|
||||
expect((corpus.target_checks || []).length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('detects every seeded misconfiguration on the committed sample', () => {
|
||||
expect(score.detection.hits).toBe(score.detection.total);
|
||||
expect(score.detection.total).toBeGreaterThanOrEqual(5);
|
||||
});
|
||||
|
||||
it('does not false-positive on the locked-down control', () => {
|
||||
expect(score.discrimination.falsePositives).toBe(0);
|
||||
});
|
||||
|
||||
it('parser is tolerant of checkov multi-framework (array) output', () => {
|
||||
const asArray = parseCheckov([sample]);
|
||||
expect(Object.keys(asArray).length).toBe(Object.keys(parseCheckov(sample)).length);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Locks the Mobile loadout's static-analysis detector + benchmark into CI: the built-in ruleset must
|
||||
* catch every seeded manifest-misconfig / hardcoded-secret in the corpus and stay clean on the hardened
|
||||
* controls. Deterministic + self-contained (no external tool).
|
||||
*/
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { loadCorpus, detect, scoreCorpus, RULES } from '../../scripts/mobile-static-bench.mjs';
|
||||
|
||||
describe('mobile static-analysis benchmark', () => {
|
||||
const corpus = loadCorpus();
|
||||
const score = scoreCorpus(corpus);
|
||||
|
||||
it('corpus has seeded fixtures + hardened controls with ground truth', () => {
|
||||
expect(corpus.fixtures.length).toBeGreaterThanOrEqual(6);
|
||||
expect(corpus.fixtures.some((f) => f.clean)).toBe(true);
|
||||
expect(corpus.fixtures.every((f) => f.clean || f.expect.length > 0)).toBe(true);
|
||||
});
|
||||
|
||||
it('detects every seeded manifest/secret issue', () => {
|
||||
expect(score.detection.hits).toBe(score.detection.total);
|
||||
expect(score.detection.total).toBeGreaterThanOrEqual(6);
|
||||
});
|
||||
|
||||
it('does not false-positive on hardened controls', () => {
|
||||
expect(score.discrimination.falsePositives).toBe(0);
|
||||
});
|
||||
|
||||
it('ruleset spans manifest misconfig + hardcoded secrets, kind-scoped', () => {
|
||||
expect(detect('android:debuggable="true"', 'manifest').has('M-DEBUGGABLE')).toBe(true);
|
||||
expect(detect('String k = "AKIAIOSFODNN7EXAMPLE";', 'code').has('S-AWS-KEY')).toBe(true);
|
||||
// a manifest xmlns http:// must NOT trip the code-only cleartext-endpoint rule
|
||||
expect(detect('xmlns:android="http://schemas.android.com/apk/res/android"', 'manifest').has('E-HTTP-URL')).toBe(false);
|
||||
expect(RULES.length).toBeGreaterThanOrEqual(6);
|
||||
});
|
||||
});
|
||||
@@ -470,6 +470,118 @@ export const TOOL_ADAPTERS: ToolAdapter[] = [
|
||||
parserStatus: 'planned',
|
||||
notes: 'Cloud account assessment requires explicit account scope and credentials handling.',
|
||||
},
|
||||
{
|
||||
id: 'scoutsuite',
|
||||
binary: 'scout',
|
||||
name: 'ScoutSuite',
|
||||
category: 'cloud',
|
||||
families: CLOUD_FAMILIES,
|
||||
risk: 'active',
|
||||
execution: 'receipt_required',
|
||||
networked: true,
|
||||
evidenceKinds: ['cloud_control_finding', 'iam_misconfig'],
|
||||
outputFormats: ['json', 'html'],
|
||||
installHint: 'pipx install scoutsuite',
|
||||
commandHint: 'scout aws --report-dir ./scout (read-only posture; needs account creds + explicit scope)',
|
||||
parserStatus: 'planned',
|
||||
notes: 'Multi-cloud (AWS/Azure/GCP) posture assessment; read-only API reads under authorized credentials + account scope.',
|
||||
},
|
||||
{
|
||||
id: 'cloudfox',
|
||||
binary: 'cloudfox',
|
||||
name: 'CloudFox',
|
||||
category: 'cloud',
|
||||
families: CLOUD_FAMILIES,
|
||||
risk: 'active',
|
||||
execution: 'receipt_required',
|
||||
networked: true,
|
||||
evidenceKinds: ['cloud_attack_path', 'iam_misconfig'],
|
||||
outputFormats: ['json', 'text'],
|
||||
installHint: 'brew install cloudfox',
|
||||
commandHint: 'cloudfox aws all-checks (enumerates exploitable paths; needs creds + scope)',
|
||||
parserStatus: 'planned',
|
||||
notes: 'Offensive cloud enumeration — surfaces IAM/privesc/attack paths across AWS/Azure/GCP via read-only API calls under authorized credentials.',
|
||||
},
|
||||
{
|
||||
id: 'pmapper',
|
||||
binary: 'pmapper',
|
||||
name: 'PMapper',
|
||||
category: 'cloud',
|
||||
families: CLOUD_FAMILIES,
|
||||
risk: 'active',
|
||||
execution: 'receipt_required',
|
||||
networked: true,
|
||||
evidenceKinds: ['iam_privesc_path'],
|
||||
outputFormats: ['json', 'dot'],
|
||||
installHint: 'pipx install principalmapper',
|
||||
commandHint: 'pmapper graph create && pmapper query "preset privesc *" (read-only IAM introspection; needs AWS creds + scope)',
|
||||
parserStatus: 'planned',
|
||||
notes: 'Maps AWS IAM privilege-escalation paths from read-only IAM introspection under authorized credentials.',
|
||||
},
|
||||
{
|
||||
id: 'pacu',
|
||||
binary: 'pacu',
|
||||
name: 'Pacu',
|
||||
category: 'cloud',
|
||||
families: CLOUD_FAMILIES,
|
||||
risk: 'dangerous',
|
||||
execution: 'catalog_only',
|
||||
networked: true,
|
||||
evidenceKinds: ['exploit_validation'],
|
||||
outputFormats: ['session_export'],
|
||||
installHint: 'pipx install pacu',
|
||||
commandHint: 'Catalog-only until a narrow per-module runner and receipt gate exist.',
|
||||
parserStatus: 'planned',
|
||||
notes: 'AWS exploitation framework (privesc, persistence, exfil). Do not expose through generic command execution; needs per-module adapters + explicit approval — same gating as metasploit.',
|
||||
},
|
||||
{
|
||||
id: 'aws-cli',
|
||||
binary: 'aws',
|
||||
name: 'AWS CLI',
|
||||
category: 'cloud',
|
||||
families: CLOUD_FAMILIES,
|
||||
risk: 'active',
|
||||
execution: 'receipt_required',
|
||||
networked: true,
|
||||
evidenceKinds: ['cloud_enumeration', 'iam_state', 'resource_inventory'],
|
||||
outputFormats: ['json', 'text'],
|
||||
installHint: 'brew install awscli',
|
||||
commandHint: 'aws sts get-caller-identity / aws iam list-users / aws s3 ls (read enum; needs creds + scope)',
|
||||
parserStatus: 'planned',
|
||||
notes: 'Base AWS enumeration primitive. Read-only list/describe API calls under authorized credentials + account scope.',
|
||||
},
|
||||
{
|
||||
id: 'az-cli',
|
||||
binary: 'az',
|
||||
name: 'Azure CLI',
|
||||
category: 'cloud',
|
||||
families: CLOUD_FAMILIES,
|
||||
risk: 'active',
|
||||
execution: 'receipt_required',
|
||||
networked: true,
|
||||
evidenceKinds: ['cloud_enumeration', 'iam_state'],
|
||||
outputFormats: ['json'],
|
||||
installHint: 'brew install azure-cli',
|
||||
commandHint: 'az account show / az role assignment list / az storage account list (read enum; needs creds + scope)',
|
||||
parserStatus: 'planned',
|
||||
notes: 'Base Azure enumeration primitive. Read-only under authorized credentials + subscription scope.',
|
||||
},
|
||||
{
|
||||
id: 'gcloud-cli',
|
||||
binary: 'gcloud',
|
||||
name: 'gcloud CLI',
|
||||
category: 'cloud',
|
||||
families: CLOUD_FAMILIES,
|
||||
risk: 'active',
|
||||
execution: 'receipt_required',
|
||||
networked: true,
|
||||
evidenceKinds: ['cloud_enumeration', 'iam_state'],
|
||||
outputFormats: ['json', 'text'],
|
||||
installHint: 'brew install --cask google-cloud-sdk',
|
||||
commandHint: 'gcloud projects list / gcloud iam roles list / gcloud storage ls (read enum; needs auth + scope)',
|
||||
parserStatus: 'planned',
|
||||
notes: 'Base GCP enumeration primitive. Read-only under authorized credentials + project scope.',
|
||||
},
|
||||
{
|
||||
id: 'garak',
|
||||
binary: 'garak',
|
||||
@@ -694,6 +806,102 @@ export const TOOL_ADAPTERS: ToolAdapter[] = [
|
||||
parserStatus: 'planned',
|
||||
notes: 'Scriptable local reverse-engineering adapter for artifacts and firmware.',
|
||||
},
|
||||
{
|
||||
id: 'ghidra',
|
||||
binary: 'analyzeHeadless',
|
||||
name: 'Ghidra (headless)',
|
||||
category: 'reverse',
|
||||
families: REVERSE_FAMILIES,
|
||||
risk: 'local_read',
|
||||
execution: 'safe_command',
|
||||
networked: false,
|
||||
evidenceKinds: ['decompiled_pseudocode', 'function_graph', 'binary_analysis'],
|
||||
outputFormats: ['text', 'xml'],
|
||||
installHint: 'brew install ghidra # provides analyzeHeadless',
|
||||
commandHint: 'analyzeHeadless <proj> tmp -import artifact.bin -postScript DecompileScript.java',
|
||||
parserStatus: 'planned',
|
||||
notes: 'Headless decompiler — static pseudocode reconstruction from an owned/lab binary. Read-only, no execution.',
|
||||
},
|
||||
{
|
||||
id: 'objdump',
|
||||
binary: 'objdump',
|
||||
name: 'objdump',
|
||||
category: 'reverse',
|
||||
families: REVERSE_FAMILIES,
|
||||
risk: 'local_read',
|
||||
execution: 'safe_command',
|
||||
networked: false,
|
||||
evidenceKinds: ['disassembly', 'symbol_table', 'section_headers'],
|
||||
outputFormats: ['text'],
|
||||
installHint: 'binutils (brew install binutils)',
|
||||
commandHint: 'objdump -d -M intel artifact.bin',
|
||||
parserStatus: 'text',
|
||||
notes: 'Static disassembly + section/symbol inspection of an owned binary. Read-only.',
|
||||
},
|
||||
{
|
||||
id: 'gdb',
|
||||
binary: 'gdb',
|
||||
name: 'GDB',
|
||||
category: 'reverse',
|
||||
families: REVERSE_FAMILIES,
|
||||
risk: 'active',
|
||||
execution: 'receipt_required',
|
||||
networked: false,
|
||||
evidenceKinds: ['runtime_state', 'crash_analysis'],
|
||||
outputFormats: ['text'],
|
||||
installHint: 'brew install gdb',
|
||||
commandHint: 'gdb -batch -ex run -ex bt --args ./artifact (EXECUTES the target — owned/lab binary + approval)',
|
||||
parserStatus: 'text',
|
||||
notes: 'Debugger — runs/attaches to a target binary. Executes code, so gated: owned/lab binary + explicit approval.',
|
||||
},
|
||||
{
|
||||
id: 'checksec',
|
||||
binary: 'checksec',
|
||||
name: 'checksec',
|
||||
category: 'reverse',
|
||||
families: REVERSE_FAMILIES,
|
||||
risk: 'local_read',
|
||||
execution: 'safe_command',
|
||||
networked: false,
|
||||
evidenceKinds: ['binary_protections'],
|
||||
outputFormats: ['json', 'text'],
|
||||
installHint: 'brew install checksec',
|
||||
commandHint: 'checksec --file=./artifact',
|
||||
parserStatus: 'text',
|
||||
notes: 'Static triage of binary hardening (NX, PIE, stack canary, RELRO, Fortify). Read-only — the first RE step.',
|
||||
},
|
||||
{
|
||||
id: 'strings',
|
||||
binary: 'strings',
|
||||
name: 'strings',
|
||||
category: 'reverse',
|
||||
families: REVERSE_FAMILIES,
|
||||
risk: 'local_read',
|
||||
execution: 'safe_command',
|
||||
networked: false,
|
||||
evidenceKinds: ['string_reference'],
|
||||
outputFormats: ['text'],
|
||||
installHint: 'binutils (preinstalled on most systems)',
|
||||
commandHint: 'strings -n 6 artifact.bin',
|
||||
parserStatus: 'text',
|
||||
notes: 'Extract printable strings for triage (hardcoded creds, URLs, format specifiers). Read-only.',
|
||||
},
|
||||
{
|
||||
id: 'readelf',
|
||||
binary: 'readelf',
|
||||
name: 'readelf',
|
||||
category: 'reverse',
|
||||
families: REVERSE_FAMILIES,
|
||||
risk: 'local_read',
|
||||
execution: 'safe_command',
|
||||
networked: false,
|
||||
evidenceKinds: ['elf_headers', 'symbol_table'],
|
||||
outputFormats: ['text'],
|
||||
installHint: 'binutils (brew install binutils)',
|
||||
commandHint: 'readelf -a artifact.bin',
|
||||
parserStatus: 'text',
|
||||
notes: 'ELF header/section/symbol/dynamic inspection. Read-only, complements objdump.',
|
||||
},
|
||||
{
|
||||
id: 'apktool',
|
||||
binary: 'apktool',
|
||||
@@ -726,6 +934,102 @@ export const TOOL_ADAPTERS: ToolAdapter[] = [
|
||||
parserStatus: 'planned',
|
||||
notes: 'Android decompilation for scoped local APK review.',
|
||||
},
|
||||
{
|
||||
id: 'apkleaks',
|
||||
binary: 'apkleaks',
|
||||
name: 'APKLeaks',
|
||||
category: 'mobile',
|
||||
families: REVERSE_FAMILIES,
|
||||
risk: 'local_read',
|
||||
execution: 'safe_command',
|
||||
networked: false,
|
||||
evidenceKinds: ['mobile_secret', 'exposed_endpoint'],
|
||||
outputFormats: ['json', 'text'],
|
||||
installHint: 'pipx install apkleaks',
|
||||
commandHint: 'apkleaks -f app.apk -o out.json',
|
||||
parserStatus: 'planned',
|
||||
notes: 'Static scan of an APK for hardcoded secrets, URIs, and endpoints. Local read-only.',
|
||||
},
|
||||
{
|
||||
id: 'mobsfscan',
|
||||
binary: 'mobsfscan',
|
||||
name: 'mobsfscan',
|
||||
category: 'mobile',
|
||||
families: REVERSE_FAMILIES,
|
||||
risk: 'local_read',
|
||||
execution: 'safe_command',
|
||||
networked: false,
|
||||
evidenceKinds: ['mobile_static_finding', 'insecure_api_usage'],
|
||||
outputFormats: ['json', 'sarif'],
|
||||
installHint: 'pipx install mobsfscan',
|
||||
commandHint: 'mobsfscan --json <app-source-or-decompiled-dir>',
|
||||
parserStatus: 'planned',
|
||||
notes: 'Static analyzer for Android/iOS source + manifests (insecure API usage, weak crypto, hardcoded secrets). Local read-only. (The full MobSF framework is a separate server, not a PATH binary.)',
|
||||
},
|
||||
{
|
||||
id: 'objection',
|
||||
binary: 'objection',
|
||||
name: 'Objection',
|
||||
category: 'mobile',
|
||||
families: REVERSE_FAMILIES,
|
||||
risk: 'intrusive',
|
||||
execution: 'receipt_required',
|
||||
networked: true,
|
||||
evidenceKinds: ['runtime_hook', 'mobile_dynamic_finding'],
|
||||
outputFormats: ['text'],
|
||||
installHint: 'pipx install objection',
|
||||
commandHint: 'objection -g <app> explore (Frida-based runtime; needs an owned/rooted device + approval)',
|
||||
parserStatus: 'planned',
|
||||
notes: 'Runtime mobile exploration built on Frida (SSL-pinning/root-detection bypass, keychain dump). Requires an owned device + explicit approval.',
|
||||
},
|
||||
{
|
||||
id: 'frida',
|
||||
binary: 'frida',
|
||||
name: 'Frida',
|
||||
category: 'mobile',
|
||||
families: REVERSE_FAMILIES,
|
||||
risk: 'dangerous',
|
||||
execution: 'catalog_only',
|
||||
networked: true,
|
||||
evidenceKinds: ['runtime_hook'],
|
||||
outputFormats: ['script_output'],
|
||||
installHint: 'pipx install frida-tools',
|
||||
commandHint: 'Catalog-only: runtime code injection into a live process; needs a per-script receipt + a device you own.',
|
||||
parserStatus: 'planned',
|
||||
notes: 'Dynamic instrumentation toolkit — injects into running processes. Do not expose through generic execution; needs explicit approval + an owned device — same gating as metasploit.',
|
||||
},
|
||||
{
|
||||
id: 'drozer',
|
||||
binary: 'drozer',
|
||||
name: 'drozer',
|
||||
category: 'mobile',
|
||||
families: REVERSE_FAMILIES,
|
||||
risk: 'intrusive',
|
||||
execution: 'receipt_required',
|
||||
networked: true,
|
||||
evidenceKinds: ['mobile_attack_surface', 'ipc_exposure'],
|
||||
outputFormats: ['text'],
|
||||
installHint: 'pipx install drozer',
|
||||
commandHint: 'drozer console connect (probes exported IPC/content-providers; needs an owned device + agent + approval)',
|
||||
parserStatus: 'text',
|
||||
notes: 'Android attack-surface + IPC/content-provider testing via an on-device agent. Owned device + explicit approval.',
|
||||
},
|
||||
{
|
||||
id: 'class-dump',
|
||||
binary: 'class-dump',
|
||||
name: 'class-dump',
|
||||
category: 'mobile',
|
||||
families: REVERSE_FAMILIES,
|
||||
risk: 'local_read',
|
||||
execution: 'safe_command',
|
||||
networked: false,
|
||||
evidenceKinds: ['ios_class_headers', 'decompiled_source'],
|
||||
outputFormats: ['text'],
|
||||
installHint: 'brew install class-dump',
|
||||
commandHint: 'class-dump -H App.app/App -o headers/',
|
||||
parserStatus: 'text',
|
||||
notes: 'iOS static — dumps Objective-C class/method headers from a Mach-O binary for scoped review. Read-only.',
|
||||
},
|
||||
{
|
||||
id: 'exiftool',
|
||||
binary: 'exiftool',
|
||||
|
||||
Reference in new issue
Block a user