Skip to content

Output Formats

Select an output format with --format / -f. Output is written to the directory given by --output / -o (default ntdswolf-output/).

For the structured formats (NDJSON, JSON, CSV), each object class is written to its own file. Common classes get friendly names (userusers.ndjson, computercomputers.csv, trustedDomaintrusts.json, groupPolicyContainergpos.ndjson, domainDNSdomains.ndjson); any other class name is lowercased and sanitized to a filesystem-safe form (so dHCPClassdhcpclass.ndjson, never the awkward dHCPClasss).

Every object also includes an _unmapped field: a complete passthrough of every stored LDAP attribute and linked attribute that the curated decoders do not already parse, so nothing in the database is dropped. Each value is kept verbatim when it is printable ASCII (0x200x7E) and hex-encoded otherwise. The hashcat and pwdump cracking formats are unaffected — they emit only credential material.

NDJSON (default)

One JSON object per line, one file per object class. Compatible with jq, SIEM ingestion, and streaming parsers.

ntdswolf ntds.dit --system SYSTEM --format ndjson
# Output: users.ndjson, computers.ndjson, groups.ndjson, ...
{"_object_class": "user", "_dnt": 3802, "sAMAccountName": "Administrator", "objectSid": "S-1-5-21-...-500", "credentials": {"ntHash": "..."}}

JSON

Pretty-printed JSON arrays, one file per object class.

ntdswolf ntds.dit --system SYSTEM --format json

CSV

Flat CSV with one row per object. Nested fields are flattened with dot notation; multi-valued fields are pipe-delimited.

ntdswolf ntds.dit --system SYSTEM --format csv

hashcat

NT and LM hashes as username:hash lines for hashcat --username. Files are split by object class, hash type (NT/LM), and age (current/history), and are written only when the corresponding hashes are present:

File Contents
ntlm_<type>_current.txt Current NT hashes, username:nt_hash (mode 1000).
ntlm_<type>_history.txt Historical NT hashes (only if any account has password history).
lm_<type>_current.txt Current LM hashes, split into their two 8-byte halves, username:lm_half (mode 3000).
lm_<type>_history.txt Historical LM hash halves.

<type> is the object class: user, computer, gmsa, smsa, dmsa (any other class is lowercased and sanitized to a filesystem-safe name). Files are ASCII with \n line endings. Kerberos keys are intentionally not emitted — they are pass-the-key material, not hashcat-crackable hashes; use the pwdump format for those.

By default username is the sAMAccountName. Use --hashcat-username to switch it to the UPN (upn), the RID (rid), or the full objectSid (sid):

ntdswolf ntds.dit --system SYSTEM --format hashcat
ntdswolf ntds.dit --system SYSTEM --format hashcat --hashcat-username rid
# ntlm_user_current.txt
Administrator:7facdc498ed1680c4fd1448319a8c04f

# lm_user_current.txt  (the two 8-byte LM halves, one per line)
Administrator:1122334455667788
Administrator:aabbccddeeff0011

Crack with hashcat --username, which ignores the username: prefix:

hashcat -m 1000 --username ntlm_user_current.txt wordlist.txt
hashcat -m 3000 --username lm_user_current.txt wordlist.txt

pwdump

secretsdump-compatible "newer pwdump" output — byte-for-byte the files impacket-secretsdump -outputfile writes:

File Contents
hashes.ntds username:rid:lm:nt:::, with inline username_historyN:... lines for password history.
hashes.ntds.kerberos username:<etype>:<key> Kerberos keys, labelled exactly as secretsdump (e.g. aes256-cts-hmac-sha1-96, des-cbc-md5; older Server 2008 databases also carry dec-cbc-crc and rc4_hmac).
hashes.ntds.cleartext username:CLEARTEXT:<password> for reversibly-encrypted passwords.

This is the modern pwdump secretsdump emits: the classic username:rid:lm:nt::: line plus the Kerberos-key and cleartext sidecar files. Accounts that carry a userPrincipalName are prefixed with their UPN domain (TEST.corp\test2), exactly as secretsdump does.

Password-history padding entries

For exact secretsdump parity, history lines (username_historyN) include the trailing PKCS7 padding block that secretsdump decrypts and emits as a history hash. That entry is not a real previous password — it is derived from encryption padding, not a stored credential. NTDSWolf keeps it so hashes.ntds matches secretsdump -history byte-for-byte, and prints a WARNING to stderr naming each account whose history decrypts to more hashes than its SecretLength declares, so the fabricated entries are easy to spot.

ntdswolf ntds.dit --system SYSTEM --format pwdump
# hashes.ntds
Administrator:500:aad3b435b51404eeaad3b435b51404ee:7facdc498ed1680c4fd1448319a8c04f:::

# hashes.ntds.kerberos
Administrator:aes256-cts-hmac-sha1-96:6c2d8...e1
Administrator:aes128-cts-hmac-sha1-96:9af3b...02

Selecting object classes

--extract / -e limits output to specific object classes. It accepts singular or plural names (user or users) and all for everything (the default). The filter applies to every format, including the hash formats — --extract users keeps machine accounts out of ntlm_user_current.txt, and --extract computers keeps user accounts out.

# Only user accounts, as hashcat-ready NT hashes
ntdswolf ntds.dit --system SYSTEM --format hashcat --extract users

# Users and groups only, as NDJSON
ntdswolf ntds.dit --system SYSTEM --extract users --extract groups