2026-10-15 12:34:26 -04:00
2026-10-15 12:34:26 -04:00
2026-10-15 12:34:26 -04:00
2026-10-15 12:34:26 -04:00
2026-10-15 12:34:26 -04:00
2026-10-15 12:34:26 -04:00
2026-10-15 12:34:26 -04:00
2026-10-15 12:34:26 -04:00

RPCScope

RPCScope is a small Python orchestrator and correlation engine for authorized SMB and Windows RPC audits. It combines evidence from NetExec, enum4linux-ng, Impacket's rpcdump, and an optional Metasploit scanner into one JSON schema and a readable report.

The normal CLI scan uses NetExec plus RPC endpoint collection. Full enum4linux-ng collection is now explicit with --deep, so broad enumeration does not delay dedicated checks. Add --no-rpcdump for SMB/check-only work. The Python API retains its earlier collector defaults for compatibility.

The differentiator is not “run four tools.” It is the evidence layer between collection and conclusions:

  • normalize changing console output into host, SMB, share, and RPC-interface facts;
  • match RPC UUIDs to security-relevant Windows protocols without claiming that exposure proves a CVE;
  • distinguish a confirmed scanner result from an inferred risk signal;
  • retain collector artifacts with supplied passwords redacted and report the evidence behind each finding;
  • support offline analysis and dry runs for safe development and demos.

Scope and safety

Use RPCScope only on systems you own or are explicitly authorized to assess. Live collection requires --i-am-authorized. Version banners and exposed interfaces are leads for validation, not automatic proof of vulnerability. The initial Metasploit integration uses only auxiliary/scanner/smb/smb_ms17_010; it does not run an exploit or payload.

NDRaider is useful architectural inspiration, but it solves a different problem: it extracts NDR grammars from Windows PE files and performs structure-aware RPC fuzzing. RPCScope starts with remote enumeration and correlation. A future integration could ingest NDRaider JSON from authorized lab-side binary analysis, but it should not be a hard dependency.

Install

python3 -m venv .venv
source .venv/bin/activate
python -m pip install -e .
rpcscope doctor

External collectors are optional for offline analysis. Install the adapters you intend to use: nxc (or netexec), enum4linux-ng, and impacket-rpcdump; msfconsole is required only when its check is enabled. The native LongLogon precondition check does not require NetExec.

Usage

Null-session discovery plus shares across one or more IPs/CIDRs:

rpcscope scan 10.10.10.25 10.10.20.0/24 \
  --shares --i-am-authorized -o engagement-a

No credential flags are required: omitted -u/-p values intentionally select null/anonymous collection.

Authenticated collection without placing the password in shell history:

rpcscope scan targets.txt -u 'ACME\auditor' --password-prompt \
  --shares --i-am-authorized -o engagement-a

Enable the non-exploit MS17-010 auxiliary scanner:

rpcscope scan 10.10.10.0/24 -u '' -p '' --shares \
  --msf-ms17-010 --i-am-authorized -o engagement-a

Run the credentialless vulnerability-check preset:

rpcscope scan 10.10.10.0/24 --checks credentialless --shares \
  --authorised -o engagement-a

List the checker registry and credential requirements with rpcscope catalog. The CLI batches the same NetExec module across live hosts, while unrelated modules run in separate processes so a module exception cannot suppress later checks. safe remains an alias for credentialless; it describes the authentication requirement, not a guarantee about probe impact.

For the expanded audit, --checks recommended adds these adapters to the original four credentialless checks:

Selector Evidence collected Positive label
petitpotam EFSRPC interface binding associated with PetitPotam EXPOSURE
dfscoerce DFS namespace RPC binding EXPOSURE
shadowcoerce File Server VSS Agent RPC binding EXPOSURE
printerbug Print Spooler RPC binding EXPOSURE
mseven Event Log RPC binding EXPOSURE
spooler Registered MS-RPRN endpoints INFO
oxid Anonymous IObjectExporter advertised interface IPs INFO
longlogon Guarded CLDAP naming-precondition estimate PRECONDITION

The five bind adapters use NetExec coerce_plus with only METHOD=.... When all five are selected, the batch engine uses one METHOD=All invocation and attributes each method's evidence separately; subsets run only their selected methods. RPCScope never supplies LISTENER or ALWAYS. Upstream's “VULNERABLE” bind markers are normalized to exposed, since an accepted bind does not prove an authenticated callback, relay opportunity, or CVE. The current PetitPotam lookup may activate EFS through endpoint resolution. Anonymous method access still depends on server policy. The spooler/OXID requests use TCP/135 through NetExec's SMB wrapper, so those two adapters require both ports reachable. OXID-reported addresses are recorded only and never become scan targets. Upstream implementation.

rpcscope scan 10.10.10.0/24 --checks recommended --shares --authorised -o audit-new
rpcscope scan 10.10.10.0/24 --checks exposure,info --authorised -o inventory-new
rpcscope scan 10.10.10.0/24 --checks recommended --deep --authorised -o deep-new

Omitting --checks still runs enumeration only. Presets exposure and info can be combined with explicit checks. Inventory results never cause NOT VULNERABLE by themselves. Each check attempt retains its backend and evidence; contradictory results appear as CONFLICT in minimal output.

The current SMBGhost module tests dialect/compression support, PrintNightmare uses a driver-permission probe, and noPac uses ticket-size behavior. Positive results from these adapters are labelled SUSPECTED pending validation. The old NTLM reflection adapter is disabled because NetExec removed that module; it is listed as unsupported instead of silently appearing to run. These adapter assumptions follow the primary upstream SMBGhost, PrintNightmare, noPac, and NTLM reflection implementations. Silence, access denial, and an unknown message format are inconclusive.

LongLogon is included in --checks recommended (12 checks total). It remains a precondition-only check and can also run separately:

rpcscope scan 10.10.10.25 --checks longlogon --authorised -o longlogon-lab

It uses unauthenticated UDP/389 CLDAP requests: an EX response identifies the DNS domain, then a guarded legacy baseline uses only the fixed tiny User=x value. It never sends an oversized payload. The response-size estimate is reported as PRECONDITION: [LONGLOGON:MET], NOT-MET, or BORDERLINE; missing or invalid evidence is UNKNOWN. None of these results establishes patch state, code execution, or a confirmed CVE, and none becomes VULN or NOT VULNERABLE. This adapter is informed by the MIT-licensed ADScanPro tester at revision 5c0b86f; attribution is retained in THIRD_PARTY_NOTICES.md.

-l/--lhost is recorded in report metadata for future callback-based checks. It is deliberately unused by the current collectors because share enumeration, endpoint mapping, and the MS17-010 scanner do not need a callback listener.

Preview collection without sending traffic:

rpcscope scan 10.10.10.0/24 -u '' -p '' --shares --dry-run

Analyze previously captured artifacts:

rpcscope analyze \
  --nxc evidence/nxc.txt \
  --rpcdump-dir evidence/rpcdump \
  --enum4linux-dir evidence/enum4linux \
  -o analysis

Outputs include a one-line-per-reachable-host report.txt, detailed report.json and report.md, and collector files under raw/. Progress, TXT, and Markdown omit unreachable addresses by default; JSON retains the expanded scope and its port outcomes. Unreachable hosts have no scheduled checks. Passwords are never included in report identity labels. Each live run requires an empty output directory to prevent stale evidence from earlier runs being mixed in. Files are written atomically, and reports refresh as hosts finish, with updates capped at twice per second.

Execution coverage and evidence certainty are separate. A completed heuristic check is SUSPECTED; an executed check without a reliable verdict is UNKNOWN. Both count as completed. Skips appear separately, for example CHECKS: 9/9 SKIPPED: 2 for eleven selected checks. Only real failures, unfinished work, or interruption produce partial coverage. A skipped or uncertain check still prevents an all-selected-checks clean claim: NOT VULNERABLE (SELECTED CHECKS) requires explicit negative vulnerability results and successful collection, with no unresolved selected checks. RPC tags describe endpoint-mapper registrations; bindings have not been independently tested for reachability. Conflicting evidence is preserved in the detailed report.

192.0.2.10 (LAB) SUSPECTED: [CVE-2020-0796/SMBGHOST] EXPOSURE: [SMB-SIGNING-NOT-REQUIRED] PORTS: 135/open,445/open CHECKS: 9/9 SKIPPED: 2
192.0.2.20 CHECKED UNKNOWN: [MS17-010] PORTS: 135/open,445/open CHECKS: 1/1

Progress and performance

The default progress display goes to stderr and shows the active stage/reachable host, completed task count, and elapsed time. Dead addresses advance discovery totals silently and never enter a host-check pipeline. Completed checks keep a compact result line. A heartbeat updates the display during slow collectors. Redirected output uses stable lines without terminal escape codes; stdout contains only the final minimal host report. A completed scan with no reachable SMB/RPC hosts prints a summary without per-IP lines; that is not itself an error.

[0/3] START discovery (elapsed 0s)
[1/3] DONE discovery success (0.3s) | 2 target(s)
[1/3] START batch:ms17-010 (elapsed 0s)
[2/3] DONE ms17-010 192.0.2.10 vulnerable (0.5s)
[3/3] DONE ms17-010 192.0.2.20 not-vulnerable (0.4s)
[3/3] SUMMARY check-batch complete (elapsed 1s) | ms17-010; 2 alive host(s)
[3/3] SUMMARY scan complete (elapsed 1s) | 2 target(s); 0 collection note(s)

Use --progress plain for log files or --no-progress for quiet operation. Lightweight TCP and NetExec inventory discovery use --discovery-workers 256, matching the reviewed NetExec thread default. --jobs 8 limits heavier checks and host collectors separately. Each NetExec check batch contains at most --jobs live hosts (capped at 128 targets), with the same NetExec thread limit. Only one check batch runs at a time, avoiding multiplied/nested concurrency. Dedicated checks precede optional broad enumeration; native checks, optional MSF, RPC dump and finally --deep enum4linux run in bounded host pipelines.

--timeout 120 bounds each collector or single-check batch. The five combined bind checks receive five check budgets in total; this is an invocation ceiling, not an independently enforced per-method deadline. --discovery-timeout 600 bounds discovery separately. Output is spooled to disk; the runner actively stops a noisy collector at its next poll once output exceeds 16 MiB, retains bounded output, and marks the invocation partial.

--jobs means maximum concurrent heavy hosts, whether handled by NetExec's batch threads or Python's collector pool. It is optional: omitting it uses eight; --jobs 1 runs heavy hosts sequentially. Tune discovery separately. Increasing either limit uses more local/network resources; it changes throughput, not detection criteria. --isolated-checks retains per-host/per-check execution for diagnosing backend compatibility, without automatic retries.

The installed NetExec SMB help is inspected once and cached. Supported versions use --no-admin-check to avoid unnecessary Service Control Manager checks; none of our adapters needs an admin-only callback. Share enumeration uses legacy --no-write-check where supported, or current ACL-only defaults where --file-write-check is an explicit opt-in. RPCScope never enables file-write testing; unknown share semantics cause an explicit skip/error rather than a guessed flag. Existing filenames supplied as literal credentials are rejected because NetExec would treat them as credential lists.

Accuracy safeguards include host/module/port-indexed output, explicit negative signatures, caught-host-exception detection even on exit zero, and IPv4-only gating for the reviewed upstream MS17-010/SMBGhost adapters. Missing output never implies patched. Failed batches are retained as unknown/partial without replaying probes. Local socket-resource exhaustion is a scan failure, not thousands of supposedly dead hosts.

The offline 32-host recommended test reduces NetExec check process invocations from 352 to 28 while retaining twelve per-host check records. This measures orchestration work, not live throughput or CVE-detection accuracy. NetExec and the other external collectors are not installed in the development environment, so live version interoperability and network timing still require an authorized lab. A twelve-check audit plus RPC/optional deep inventory cannot be expected to take the same time as a bare nxc smb banner scan. See the source review.

Default discovery expands explicit IPs, CIDRs, DNS names, and UTF-8 target files, deduplicates them, and checks TCP/135 and TCP/445 independently. A host enters collection only if either port is open, retaining RPC-only systems. Closed and timed-out connections are completed reachability outcomes, not blanket partial coverage. For a reachable host, unavailable ports skip only dependent adapters; hosts with neither service reachable receive no collectors/checks. JSON retains all expanded addresses and discovery results. Files allow one IP/CIDR/hostname per line and # comments. Use --connect-timeout 1 to tune connection probing and --max-hosts 4096 to control the expansion cap. Discovery time is bounded by --discovery-timeout, including per-connection timeout clamping; unfinished probes remain distinguishable from completed timeouts. --discovery smb keeps an SMB-only workflow for environments where direct TCP probing is inappropriate. The Python ScanConfig API retains SMB-only discovery and isolated checks by default for compatibility; set tcp_discovery=True, batch_checks=True, use_enum4linux=False for the CLI's normal execution strategy.

Discovery does not test UDP/389: a UDP-only domain controller with neither TCP/135 nor TCP/445 reachable is outside this workflow's discovery coverage, even when longlogon is selected.

Recent advisory review and metadata sync

rpcscope catalog --advisories lists seven patch-review advisories: CVE-2020-1206, CVE-2022-26809, CVE-2022-37958, CVE-2024-49112, CVE-2025-47981, CVE-2025-49716, and CVE-2026-41089. These include SMBleed, RPC/NEGOEX, adjacent Active Directory LDAP, and newer Netlogon issues. The registry supplies metadata, never automatic per-host vulnerability claims. LongLogon has the precondition adapter above, included in recommended; it does not remotely verify patch state. The other entries have no executable remote adapter. No CVE is assigned to DFSCoerce or ShadowCoerce merely from its technique name.

rpcscope catalog --advisories
rpcscope sync-cves -o rpcscope-advisories.json

Sync refreshes the fixed CVE Program Microsoft CNA JSON records and preserves affected-version metadata and vendor references. It validates record identity and publisher, bounds response size, and replaces the cache only after every record validates. Downloads never install or execute scanner code. A published unauthenticated RCE advisory does not imply a validated scanner or working exploit; the Netlogon CVE-2026-41089 record remains patch-review metadata, separate from the precondition measurement. The original SMBleed scanner warns that it can crash some unpatched systems, so it has not been added as a default probe.

Ctrl+C stops active collector process groups and retains completed evidence. TCP/135 RPC enumeration runs without credentials, which also avoids an interactive prompt for named accounts with blank passwords. --shares uses the verified read-only mode described above, never file-write tests. With --deep, enum4linux JSON is exported in a private temporary directory and scrubbed before being retained. The external tools may maintain their own logs or credential databases outside RPCScope's output directory.

Exit codes: 0 completed, 1 real execution/collection failures or unfinished work, 2 invalid input, 130 interrupted. Findings, inconclusive results, normal skips, and an empty reachable-host set do not by themselves cause a nonzero exit. Offline analysis returns 1 for malformed inputs while retaining any valid artifacts it could analyze.

Tests

python3 -B -m unittest discover -s tests -v

Tests use synthetic artifacts, mocked tool invocations, and local subprocesses. No live network target is required.

Roadmap

  1. Harden parsers against a larger fixture corpus from different tool versions.
  2. Move UUID knowledge into signed/versioned data files with protocol references and tests.
  3. Add SARIF output and “compare two scans” drift reporting.
  4. Add explicit profiles (safe, standard, active) rather than silently adding intrusive modules.
  5. Optionally ingest NDRaider grammar JSON to correlate a remotely exposed UUID with a lab-analyzed vendor binary.
  6. Add a plugin API for new collectors and rules, keeping the core dependency-free.
S
Description
Evidence-driven SMB and Windows RPC exposure auditing
Readme MIT
229 KiB
0 Stars 1 Watchers 0 Forks
Languages
Python 100%