Skip to content

v2.0.0

Choose a tag to compare

@uziii2208 uziii2208 released this 29 Aug 09:32
· 11 commits to master since this release

What's Changed

Important

v2.0.0 is a full architectural overhaul. The PwnShell REPL, auth layer, module system, and output pipeline are not backward-compatible with v1.x configuration files or session artifacts.


Core Architecture — Multi-Session Manager & Jump Graph (session_mgr.py)

  • !session — Concurrent PSRP Runspace orchestration across heterogeneous targets: Prior to v2.0.0, PwnRM maintained a single active Runspace per process, requiring the operator to re-authenticate on context switches between pivots. The new SessionManager holds an indexed pool of pypsrp.RunspacePool objects keyed by session ID, each tagged with target metadata (hostname, auth type, auth material hash). !session list renders the live pool with connection state; !session switch <id> performs a zero-reauth context switch by hot-swapping the active RunspacePool reference in PwnShell; !session exec-all <cmd> fans out a single command across all open sessions and aggregates structured results. Session metadata is serialized and persisted under ~/.pwnrm/sessions/ with strict 0o700 (POSIX) / icacls "%USERNAME%:(OI)(CI)F" /inheritance:r (Windows NTFS) permission enforcement, preventing multi-tenant credential leakage — consistent with the ACL hardening introduced in v1.2.1.

Tunneling — In-Band PSRP SOCKS5 Proxy & Port Forward Multiplexer (tunnel.py)

  • !socks — RFC 1928 compliant SOCKS5 server multiplexed through PowerShell streams: Conventional SOCKS pivoting requires a listener on the remote host (chisel, ligolo, etc.) and a firewall exception. PwnRM's SOCKS5 implementation runs a local asyncio server bound to 127.0.0.1:1080 (configurable) and tunnels TCP frames through the existing PSRP stdout/stdin stream pair using a length-prefixed framing protocol. No listener socket is opened on the remote host; traffic appears as normal WinRM WSManFault-shaped XML fragments to network inspection. Implementation is RFC 1928 §3–§6 compliant: CONNECT method, IPv4/IPv6/FQDN address types, and AUTH_NONE / USERNAME_PASSWORD sub-negotiation (§4).

  • !portfwd — Local-to-remote TCP port forwarding with lifecycle management: !portfwd <LPORT> <RHOST>:<RPORT> spawns an asyncio TCP listener on LPORT that proxies connections through the active PSRP session to RHOST:RPORT on the target network segment. !portfwd list enumerates active forward rules with their bound port and target; !portfwd stop <id> cleanly drains the asyncio transport and closes the listener without disrupting the parent PSRP session.


Loot — Structured & Encrypted Loot Pipeline (loot.py)

  • !loot — Atomic loot ingestion with per-target namespacing: Credentials, Kerberos tickets (.ccache, .kirbi), certificates (.pfx, .pem), DPAPI master keys, and memory dumps are stored under ~/.pwnrm/loot/<target>/ in per-artifact-type subdirectories. File creation uses O_CREAT | O_EXCL atomic semantics to prevent TOCTOU overwrites, and all written files are immediately chmod'd to 0o600. The ingestion pipeline accepts raw bytes from any command module and performs MIME sniffing to auto-classify artifact type before persistence, removing the need for manual file-type specification per loot operation.

OPSEC — Profile & Jitter Engine (opsec.py)

  • !opsec — Behavioural profile switching with per-request timing jitter: Four operational profiles are implemented: stealth (high jitter, low throughput, legitimate Microsoft WinRM Client User-Agent header, command fragment obfuscation), balanced (moderate jitter, no obfuscation), aggressive (minimal jitter, raw commands), and hybrid-cloud (tuned for Azure Arc / WinRM-over-HTTPS environments with cloud-specific User-Agent strings). Jitter is applied at the PSRP transport layer between requests using a per-profile (min_ms, max_ms) range sampled from a uniform distribution, making request cadence non-deterministic to timing-based EDR heuristics.

Modules — Pluggable Modular Engine (src/pwnrm/modules/)

  • BaseModule / ModuleManager — Hot-loadable plugin architecture: v2.0.0 introduces a BaseModule abstract class exposing name, aliases, help_text, run(shell, args), and optional tab_complete(shell, prefix) contract. ModuleManager performs filesystem discovery of *.py files under src/pwnrm/modules/, imports them, and registers all BaseModule subclasses into the PwnShell command dispatcher at startup. Third-party and user-authored modules drop into the modules directory with no changes to core — the loader handles registration, tab completion injection, and !help listing automatically.

Exploitation — Full ADCS Engine ESC1–ESC16+ (adcs.py)

  • !adcs — Deep ADCS template vulnerability audit without dropping binaries: Implements in-memory LDAP enumeration of Certificate Authority configuration and certificate template ACLs to audit for ESC1 (enrollee-supplied Subject), ESC2 (Any Purpose EKU), ESC3 (Certificate Request Agent), ESC4 (template write ACL), ESC6 (EDITF_ATTRIBUTESUBJECTALTNAME2), ESC7 (CA officer ACL), ESC9/ESC10 (no-security-extension / weak certificate mapping), ESC13 (OID group link), ESC15 (schema version 1 + Application Policy EKU), ESC16 (disabled szOID_NTDS_CA_SECURITY_EXT globally), and ESC17 (WSUS-to-ADCS abuse — enumerates WUServer registry value under HKLM\Software\Policies\Microsoft\Windows\WindowsUpdate to identify HTTP-only WSUS endpoints susceptible to MitM, where an attacker-controlled update package can trigger a certificate enrollment request to an internal CA under the machine account context, enabling domain privilege escalation). Enterprise CA discovery queries CN=Certification Authorities,CN=Public Key Services,CN=Services in the configuration naming context. All enumeration runs through PowerShell LDAP queries on the active PSRP session; no SharpADCS, Certify, or Certipy binary is staged to disk.

Kerberos — Advanced Suite (kerberos.py)

  • !kerberos — AES-priority Kerberoasting, AS-REP roasting, Diamond Tickets, and Server 2025 dMSA/BadSuccessor inspection: Kerberoasting requests are issued with etype=18 (AES256-CTS-HMAC-SHA1-96) preference before falling back to RC4, consistent with environments where RC4 is deprecated under Msds-SupportedEncryptionTypes. AS-REP roasting enumerates accounts with DONT_REQ_PREAUTH set via LDAP and pre-computes roastable target lists. Diamond Ticket workflow assistance provides step-by-step identity-swap guidance for environments where synthetic Golden/Silver Tickets trigger KDC anomaly detection on Defender for Identity. The BadSuccessor inspection block enumerates msDS-ManagedAccount / delegated Managed Service Account (dMSA) objects and surfaces misconfigured successor principal assignments introduced in Server 2025.

Cloud — Hybrid Entra ID / Azure AD PRT Pivot (entra.py)

  • !entra — Device join status inspection and WAM / Azure CLI / Az PowerShell credential cache extraction: Queries dsregcmd /status output via PSRP and parses AzureAdJoined, DomainJoined, and EnterpriseJoined fields to determine hybrid join topology. When AzureAdJoined: YES, the module enumerates Web Account Manager (WAM) token broker cache paths in the user profile for ms-deviceid and PRT-adjacent token blobs. Azure CLI token cache (~/.azure/msal_token_cache.json) and Azure PowerShell credential cache (~\AppData\Roaming\Windows Azure PowerShell\TokenCache.dat) paths are identified and flagged for extraction via !loot.

Credential Hunting — Deep Credential & Token Hunter (creds.py)

  • !creds — DPAPI master key enumeration, browser credential store detection, and token privilege audit: Enumerates %APPDATA%\Microsoft\Protect\<SID>\ for DPAPI master key files. Browser credential store detection covers Chrome, Edge, and Brave Login Data (SQLite) and Local State (AES-GCM key blob) paths under %LOCALAPPDATA%. Token privilege audit inspects the current runspace token for SeDebugPrivilege, SeImpersonatePrivilege, and SeTcbPrivilege, flagging each with its enable/disable state and a note on the relevant abuse primitive.

Evasion — Polymorphic Evasion & EDR Scout (evasion.py)

  • !evasion — Randomized polymorphic AMSI/ETW patching and EDR driver fingerprinting: AMSI bypass patches AmsiScanBuffer in amsi.dll using a randomized stub (variable nop-sled length, randomized jmp displacement encoding) to avoid static signature matching on the patch bytes. ETW bypass patches EtwEventWrite in ntdll.dll with a ret / xor eax, eax; ret stub selected at random. EDR driver detection queries \\.\ device namespace and the SCM service list for csagent.sys (CrowdStrike), SentinelAgent.sys (SentinelOne), WdFilter.sys (Windows Defender), CbDefenseW64.sys (Carbon Black), and cylance.sys (Cylance Protect), reporting detected products with their loaded driver path.

Reconnaissance — In-Memory BloodHound AD Graph Collector (bloodhound.py)

  • !bloodhound — 100% in-memory LDAP-based AD graph collection, BloodHound CE / v4–v5 compatible: Performs LDAP enumeration of Users, Computers, Domain Controllers, and High-Value Groups (Domain Admins, Enterprise Admins, Schema Admins, etc.) through the active PSRP session without staging SharpHound, AzureHound, or any binary to disk. Output is serialized to BloodHound CE / v4–v5 JSON format and ingested directly into the !loot pipeline. The collection scope mirrors SharpHound's Default collection method: ACLs, Group Memberships, ObjectProperties, and Trusts.

Lateral Movement — Subnet Scout & Dispatcher (lateral.py)

  • !lateral — In-memory subnet sweep targeting WinRM, SMB, and RDP: Issues PowerShell Test-NetConnection fan-out jobs across the target's subnet (inferred from active NIC config or operator-supplied CIDR) probing ports 5985/5986 (WinRM HTTP/S), 445 (SMB), and 3389 (RDP). Results are returned as a structured host/port/state table. Reachable WinRM hosts can be immediately promoted to new sessions via !session integration.

Automation — Declarative Playbook Runner (playbook.py)

  • !playbook — Structured multi-step automation with built-in red team playbooks: The PlaybookRunner parses a simple YAML DSL defining ordered steps (module name + args + conditionals). Built-in playbooks: default_triage (hostname, whoami, privilege, AV check, network adapters), ad_recon (domain info, SPNs, AS-REP candidates, ADCS quick scan), stealth_audit (switches to stealth OPSEC profile, runs triage + recon with jitter, loot ingestion). Custom playbooks load from ~/.pwnrm/playbooks/*.yml.

Tests — Automated Regression & Security Unit Test Suite (tests/)

  • 15 unit tests covering session integrity, tunnel correctness, loot atomicity, OPSEC profile switching, and module discovery: Test suite covers: session manager CRUD + state machine transitions, SOCKS5 handshake negotiation (RFC 1928 VER/METHOD/CONNECT frames), loot pipeline atomic write + permission assertions, OPSEC profile activation + jitter range bounds, module discovery + BaseModule contract validation, and security guard checks (path traversal in loot keys, O_EXCL collision handling, permission enforcement post-write). Run via pytest tests/ -v.

Changed

  • PwnShell REPL refactored with dynamic prompt status bar: PwnRM[S:<session_count>|<active_host>]|<cwd>> — session count and active target visible at all times.
  • ui.py banner, color scheme, and tab completion lists updated to reflect all v2.0 command surface.
  • cli.py enforces UTF-8 console output reconfiguration at startup via sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace') for cross-platform and Windows Terminal compatibility.

Full Changelog: v1.2.6...v2.0.0