Skip to content

Releases: StrongWind1/NTDSWolf

v0.4.1

08 Jun 14:50
v0.4.1
93729a9

Choose a tag to compare

Unifies the generic fallback decoder with the v0.4.0 _unmapped passthrough, so dissect's internal columns are never surfaced and every class has a consistent shape.

Changed

  • The generic fallback decoder (used for object classes without a specialised decoder) no longer dumps a flat as_dict() at the top level. That leaked dissect's internal structural columns (Obj, Time, CNT, ...) because its column-exclusion list had the wrong casing, and it dropped every top-level attribute on objects with a single undecodable attribute (e.g. a schema attributeID). It now adds no class-specific fields and relies on the same robust _unmapped passthrough every class uses, so generic objects have the identical shape (common attributes + _unmapped) and dissect internals are never surfaced.

Install

uv tool install git+https://github.com/StrongWind1/NTDSWolf@v0.4.1

Full changelog: https://github.com/StrongWind1/NTDSWolf/blob/main/CHANGELOG.md · Docs: https://strongwind1.github.io/NTDSWolf/

v0.4.0

08 Jun 00:34
v0.4.0
f95eda2

Choose a tag to compare

Makes "dump everything" the default — every object now carries a complete _unmapped raw-attribute passthrough, bringing attribute coverage to parity with, and beyond, ntdissector.

Added

  • Every object now carries an _unmapped field in the structured formats (NDJSON/JSON/CSV): a raw passthrough of every stored LDAP attribute and linked attribute the curated decoders did not already parse, so nothing in the database is dropped (NTDSWolf's primary goal). Values are kept verbatim when printable ASCII (0x20-0x7E) and hex-encoded otherwise; dissect's internal structural columns and already-curated attributes are excluded. Enumeration is per-attribute and falls back to the raw value, so a single undecodable attribute (e.g. a schema attributeID with no OID mapping) no longer drops the rest. This brings attribute coverage to parity with, and beyond, ntdissector. The hashcat and pwdump outputs are unaffected.

Install

uv tool install git+https://github.com/StrongWind1/NTDSWolf@v0.4.0

Full changelog: https://github.com/StrongWind1/NTDSWolf/blob/main/CHANGELOG.md · Docs: https://strongwind1.github.io/NTDSWolf/

v0.3.0

07 Jun 22:56
v0.3.0
c836ea9

Choose a tag to compare

Reworks the credential output formats and brings the secretsdump-compatible pwdump/hashcat output to byte-for-byte parity.

Breaking: the John the Ripper format and the no-op --raw flag are removed, and the hashcat/pwdump output filenames change. See Removed / Changed below.

Added

  • --hashcat-username selects the username field in hashcat output lines: sam (sAMAccountName, the default), upn, rid, or sid.
  • Structured output (NDJSON/JSON/CSV) now captures the previous-password and service Kerberos key sets from supplementalCredentials -- the KERB_STORED_CREDENTIAL_NEW OldCredentials / OlderCredentials / ServiceCredentials arrays -- under kerberosOld / kerberosOlder / kerberosService, alongside the current kerberos keys. These were previously dropped, yet every computer account (and any password-changed user) carries them. The hashcat and pwdump outputs are unchanged: they still emit only the current key set, matching secretsdump.
  • Every credentialed object now includes supplementalCredentialsRaw: the complete decoded supplementalCredentials structure verbatim -- every package (including the legacy Primary:Kerberos and the Packages list), the default salt and iteration count, and all four key arrays, with byte values hex-encoded and nothing curated away.

Changed

  • Reworked the hashcat output into per-class username:hash files for hashcat --username (ntlm_<type>_current.txt, ntlm_<type>_history.txt, lm_<type>_current.txt, lm_<type>_history.txt), split by object class, hash type, and age. LM hashes are emitted as their two 8-byte halves (mode 3000). Kerberos keys are no longer written to the hashcat output -- they are pass-the-key material, not hashcat-crackable hashes.
  • The pwdump format now emits secretsdump's "newer pwdump" file set, byte-for-byte compatible with impacket-secretsdump -outputfile: hashes.ntds (username:rid:lm:nt::: with inline username_historyN lines), hashes.ntds.kerberos (username:<etype>:<key>, lowercase etypes, no RC4), and hashes.ntds.cleartext (username:CLEARTEXT:<password>).

Removed

  • The John the Ripper output format (--format john); use hashcat or pwdump.
  • The --raw flag, which never had any effect. The completeness it implied is now always on via supplementalCredentialsRaw (see Added).

Fixed

  • The pwdump hashes.ntds.kerberos file omitted the dec-cbc-crc (DES-CBC-CRC) and rc4_hmac Kerberos keys on Windows Server 2008 databases, which store five KeyTypes in supplementalCredentials (2016+ store three). The writer now keys on the numeric Kerberos KeyType, mirroring impacket's KERBEROS_TYPE table exactly (including the 0xFFFFFF74 RC4 marker and the dec-cbc-crc spelling), so hashes.ntds.kerberos is byte-identical to secretsdump across Server 2008-2022.
  • Password history (ntPwdHistory / lmPwdHistory) was silently dropped for every account, so hashes.ntds was missing all _history lines. dissect returns the blob wrapped in a one-element list (which failed an isinstance(bytes) check), and the AES PEK layer was PKCS7-unpadded, stripping the trailing block secretsdump keeps. History is now decrypted faithfully and hashes.ntds is byte-identical to secretsdump -history across the RC4 and AES eras (Windows Server 2008-2022). The AES padding block is kept for exact parity (secretsdump emits it as a history entry); because it is not a real password, NTDSWolf logs a stderr WARNING naming each account whose history decrypts to more hashes than its SecretLength declares.
  • Removed the redundant --exclude-deleted flag; --include-deleted is now a single switch (deleted objects are excluded by default).

Install

uv tool install git+https://github.com/StrongWind1/NTDSWolf@v0.3.0

Full changelog: https://github.com/StrongWind1/NTDSWolf/blob/main/CHANGELOG.md · Docs: https://strongwind1.github.io/NTDSWolf/

v0.2.0

07 Jun 15:32
v0.2.0
8f4f3ee

Choose a tag to compare

First public release of NTDSWolf — a pure-Python offline NTDS.dit parser and credential extractor for Active Directory forensics, penetration testing, and security auditing.

Added

  • Kerberos keys (AES256/AES128/RC4/DES), WDigest, cleartext, and NTLM-Strong-NTOWF extraction, surfaced from dissect's decoded supplementalCredentials. Verified against real databases (Windows Server 2012/2016/2019).
  • Kerberos keys are written to kerberos_keys.txt (principal:etype:key) in the hashcat and pwdump outputs for pass-the-key use.
  • Per-class decoder registry is now the live decode path (replacing the simplified inline decoder).
  • Working --workers N multiprocessing extraction (fork-based), verified to produce byte-identical output to single-threaded.
  • Inter-realm trust keys: decrypt trustAuthIncoming/trustAuthOutgoing and derive each trust account's RC4-HMAC (= NT hash) and AES-256/AES-128 keys (Kerberos string-to-key with the <REALM>krbtgt<FLATNAME> salt). Both-direction keys are written to kerberos_keys.txt. Verified against a real inter-forest trust.
  • LAPS extraction: v1 plaintext (ms-Mcs-AdmPwd), v2 cleartext (msLAPS-Password), and v2 encrypted (msLAPS-EncryptedPassword) decrypted offline through the MS-GKDI / DPAPI-NG chain (adds the dpapi-ng dependency, which provides the offline root-key derivation and CMS parsing the online-only RPC path lacks). Verified to reproduce the live LAPS password.
  • gMSA / dMSA managed passwords derived entirely offline from the KDS root key + msDS-ManagedPasswordId + account SID (MS-GKDI). The 256-byte managedPassword self-verifies (its MD4 is the account's NT hash). Standalone (sMSA), group (gMSA), and delegated (dMSA, Server 2025) accounts route to credential-aware decoders; their NT hash + Kerberos keys round-trip-authenticate against a live DC.
  • msDS-KeyCredentialLink parsing for Windows Hello for Business / FIDO2 / shadow-credential keys.

Changed

  • Lowered the minimum supported Python from 3.14 to 3.11, widening the install base; CI now tests the full 3.11-3.14 range. Two 3.14-only constructs were made portable: override now imports from typing-extensions (a new, lightweight dependency), and the unparenthesized multi-exception except clauses (PEP 758) are parenthesized.
  • Removed the impacket runtime dependency. The three primitives it provided -- Kerberos AES string-to-key (RFC 3961/3962), per-RID DES key derivation ([MS-SAMR] 2.2.11.1.2-2.2.11.1.3), and the LAPS v2 timestamp header -- are now implemented directly from their specifications and validated against the RFC 3962 Appendix B test vectors. This also drops flask, ldap3, pyasn1, pyopenssl, and six from the install footprint.
  • Output is now cross-validated as byte-identical to impacket-secretsdump on Windows Server 2008R2/2016/2022 (RC4 and AES eras).
  • No-password accounts (e.g. Guest) are emitted with the empty NT hash, matching impacket.
  • Structured output filenames now use a documented friendly-name map (user -> users.ndjson, trustedDomain -> trusts.ndjson) with a sanitized fallback for uncommon classes, replacing the naive objectClass + "s" pluralization (which produced names like dHCPClasss).
  • --extract now filters the hash formats (hashcat/john/pwdump) as well as the structured ones, so a users-only run no longer leaks machine-account hashes.

Fixed

  • --extract plural names (users, groups) and all now select correctly instead of silently matching nothing.
  • SID RID endianness: the last sub-authority is read big-endian, fixing both garbage RIDs and the NT hashes that depend on the RID for DES un-obfuscation.
  • A malformed --system hive no longer crashes boot-key resolution.

Install

uv tool install git+https://github.com/StrongWind1/NTDSWolf@v0.2.0

Full changelog: https://github.com/StrongWind1/NTDSWolf/blob/main/CHANGELOG.md · Docs: https://strongwind1.github.io/NTDSWolf/