Skip to main content

Correct, spec-compliant Active Directory password change, reset, and policy read over SAMR, Netlogon, LSA, Kerberos, and LDAP — including the AES paths impacket lacks.

Project description

PassWolf

Correct, spec-compliant Active Directory password change, reset, and policy read over SAMR, Netlogon, LSA, Kerberos, and LDAP - including the AES paths impacket lacks.

CI PyPI Python 3.11+ License: Apache 2.0 Docs

Getting startedChoosing a methodMethod matrix

One console command, passwolf, with three subcommands - passwolf change, passwolf reset, and passwolf policy - that implement every documented and undocumented Windows method for changing or resetting an account password or hash over SAMR, Netlogon, LSA, Kerberos kpasswd, and LDAP, and for reading the effective password policy. A Windows Server 2025 domain controller hardens off the legacy RC4 SAMR change opcodes and accepts only the AES SAMR change (SamrUnicodeChangePasswordUser4, opnum 73) in their place; passwolf speaks that AES change, and a good deal more.

Why separate tools

A change and a reset are different operations with different security models, and conflating them is the root of several sharp edges in the bundled tooling. passwolf keeps them apart on purpose:

  • passwolf change proves the account's current secret (password or NT hash) and needs no privilege on the target. It is subject to the full domain password policy.
  • passwolf reset is a privileged overwrite that proves nothing about the old secret. It bypasses minimum password age and history and requires a caller with reset rights.
  • passwolf policy reads the effective password and lockout policy (the domain policy, any applicable PSO, and the configured SYSVOL GPO intent) so you can see the constraints a change has to satisfy before you attempt one.

What it covers

Every method below is mapped to its Microsoft Open Specification section and validated against live domain controllers (Server 2022 build 20348 and Server 2025 build 26100).

Change methods (passwolf change)

Method Protocol / opnum Notes
samr-aes SAMR 73, SamrUnicodeChangePasswordUser4 AES; the only SAMR change Server 2025 accepts
samr-rc4 SAMR 55, SamrUnicodeChangePasswordUser2 legacy RC4; pass-the-hash capable
samr-oem SAMR 54, SamrOemChangePasswordUser2 OEM/LM RC4; needs a stored LM hash and a password ≤14 chars
samr-des SAMR 38, SamrChangePasswordUser DES OWF cross-encryption; needs a user handle; can set the new password by NT hash with --target-new-hash
samr-diag SAMR 63, SamrUnicodeChangePasswordUser3 undocumented; returns the structured policy rejection reason
kpasswd Kerberos 464, version 0x0001 RFC 3244 change protocol
ldap LDAP unicodePwd delete + add defaults to sealed 389, no certificate needed
netlogon-aes Netlogon 30, NetrServerPasswordSet2 machine/trust, AES NL_TRUST_PASSWORD over a sealed channel
netlogon-des Netlogon 6, NetrServerPasswordSet machine/trust, DES OWF; still accepted on Server 2025
rap RAP opcode 115, NetUserPasswordSet2 over SMB1 obsolete cleartext LM-only path; not NTLM-usable on modern hosts
rap-oem RAP opcode 214, SamOEMChangePasswordUser2 over SMB1 legacy OEM/LM RC4; works on SMB1 hosts that store an LM hash

Reset methods (passwolf reset)

Method Protocol / opnum Notes
samr-aes SAMR 58 + UserInternal7 AES cleartext reset (the UserInternal7 info level)
samr-rc4 SAMR 58 + UserInternal4InformationNew legacy RC4 + MD5-salt cleartext reset
samr-hash SAMR 37 + UserInternal1 set the NT OWF directly (full policy bypass)
kpasswd Kerberos 464, version 0xFF80 RFC 3244 set protocol, with target name and realm
ldap LDAP unicodePwd replace defaults to sealed 389
dsrm (--dsrm) SAMR 66, SamrSetDSRMPassword the DC-local recovery (RID 500) password; selected with the dedicated --dsrm flag

auto is the default for both operations. For passwolf change it prefers the strongest SAMR change the DC accepts (AES) and falls back to RC4 only when AES is genuinely unavailable, never merely for compatibility. For passwolf reset it walks a cross-method ladder - kpasswd, LDAPS, LDAP, then the SAMR resets (AES, RC4, RC4-unsalted, set-hash) - and takes the first that succeeds.

On Windows Server 2025, the Kerberos set (kpasswd), the LDAP unicodePwd replace (ldap), and the AES SAMR RPC reset (samr-aes, SamrSetInformationUser2 opnum 58 + UserInternal7) all work - confirmed live against a Server 2025 domain controller. The 2025 RC4 hardening (CVE-2021-33757 / KB5004605) blocks the legacy SAMR changes, not resets, so no passwolf reset method is blocked there.

When the target's password is expired or flagged must-change-at-next-logon, passwolf change retries the SAMR bind over a null session and completes the change. This covers the buffer-based methods (samr-aes, samr-rc4, samr-oem, samr-diag, and auto); the handle-based samr-des cannot use the null-session path.

Authentication

All three subcommands bind with NTLM by default, or with Kerberos via -k / --kerberos. Under -k the tool uses the ticket cache named by KRB5CCNAME if it holds a usable TGT, otherwise it fetches one from --dc with the supplied password or NT hash; either way the interactive bind-password prompt is skipped.

Installation

passwolf is managed with uv.

uv tool install git+https://github.com/StrongWind1/PassWolf

Or run it from a checkout without installing:

uv run passwolf change --help
uv run passwolf reset --help
uv run passwolf policy --help

Examples

# Self-change on a Server 2025 DC (auto selects the AES opnum 73).
passwolf change --target-domain SNOW --target-user jdoe --dc dc.snow.lab --target-old-password 'OldPass1!' --target-new-password 'NewPass1!'

# Pass-the-hash change.
passwolf change --target-domain SNOW --target-user jdoe --dc dc.snow.lab --target-old-hash 47c4cc3a368a4a0fa79a7bf059b7adba --target-new-password 'NewPass1!'

# Set the new password by NT hash on a change (DES change, proves the old secret, no privilege).
passwolf change --target-domain SNOW --target-user jdoe --dc dc.snow.lab --target-old-password 'OldPass1!' --target-new-hash 47c4cc3a368a4a0fa79a7bf059b7adba

# Change an expired or must-change-at-next-logon password (retries over a null session).
passwolf change --target-domain SNOW --target-user jdoe --dc dc.snow.lab --target-old-password 'Expired1!' --target-new-password 'NewPass1!'

# Privileged reset, AES cleartext path, as an admin.
passwolf reset --target-domain SNOW --target-user jdoe --dc dc.snow.lab --auth-as-user Administrator --auth-as-password 'Admin1!' --target-new-password 'NewPass1!'

# Set the NT hash directly (no Kerberos keys regenerated).
passwolf reset --target-domain SNOW --target-user jdoe --dc dc.snow.lab --auth-as-user Administrator --auth-as-password 'Admin1!' --target-new-hash 47c4cc3a368a4a0fa79a7bf059b7adba

# Rotate a computer account password over the Netlogon secure channel.
passwolf change --target-domain SNOW --target-user 'WS01$' --dc dc.snow.lab --account machine --target-old-password 'curr3nt' --target-new-password 'n3wer' --netbios SNOW

# LDAP change over sealed 389 (works without an LDAPS certificate).
passwolf change --target-domain SNOW --target-user jdoe --dc dc.snow.lab --method ldap --target-old-password 'OldPass1!' --target-new-password 'NewPass1!'

# Kerberos bind using the ticket in KRB5CCNAME (no bind password needed).
passwolf change --target-domain SNOW --target-user jdoe --dc dc.snow.lab -k --target-old-password 'OldPass1!' --target-new-password 'NewPass1!'

Output formats

--format text (default) prints one greppable status line, --format json prints a single JSON object, and --format pretty renders a rich panel. The result always decodes the NTSTATUS precisely so a wrong old password, a policy rejection, and a disabled method are distinguishable.

What sets it apart

  • The AES change (opnum 73) and the AES reset info levels (UserInternal7) are what a Server 2025 DC requires, and both are implemented here.
  • The LDAP path defaults to plain 389 with a SASL sign-and-seal bind, so it works without an LDAPS certificate instead of requiring ldaps://.
  • The undocumented SAMR opnum 63 returns the structured reason a change was rejected.
  • Precise NTSTATUS decoding and a strict change-versus-reset separation.

Limitations and notes

  • The reset cleartext info levels use the SMB session key as their content-encryption key, so they require the SMB named-pipe transport, not direct TCP.
  • The OEM change and the LDAP change need the cleartext old password (the LM hash and the unicodePwd delete value cannot be formed from an NT hash).
  • Netlogon and the DSRM reset address machine/trust and the RID-500 recovery account respectively, not arbitrary users.

Development

make install-dev   # uv sync
make check         # ruff check + ruff format --check + ty + pytest + docs
make format        # ruff format + ruff check --fix

Credits

Built on Impacket and PyCryptodome. The AES SAMR change (opnum 73) and the AES cleartext reset info levels (UserInternal7) that impacket does not implement are traced directly to the Microsoft Open Specifications ([MS-SAMR], [MS-NRPC], [MS-LSAD], [MS-ADTS]).

Related tools

Other projects in this collection:

  • AD-SecretGen - derive AD password hashes and Kerberos keys from a password
  • NTDSWolf - offline NTDS.dit parser and credential extractor
  • CredWolf - Active Directory credential validation
  • KerbWolf - Kerberos roasting and hash extraction toolkit
  • Kerberos - Kerberos in Active Directory: protocol, security, and attacks

Disclaimer

PassWolf is intended for authorized penetration testing, red team engagements, and security audits only. You must have explicit written permission from the system owner before changing or resetting any account secret in an Active Directory environment. Unauthorized access to computer systems is illegal. The authors are not responsible for any misuse or damage caused by this tool.

License

Apache License 2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

passwolf-0.3.0.tar.gz (158.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

passwolf-0.3.0-py3-none-any.whl (91.8 kB view details)

Uploaded Python 3

File details

Details for the file passwolf-0.3.0.tar.gz.

File metadata

  • Download URL: passwolf-0.3.0.tar.gz
  • Upload date:
  • Size: 158.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for passwolf-0.3.0.tar.gz
Algorithm Hash digest
SHA256 60a105e48511391716189a95d03e4457db66609feb047dff7becc317215aa3d9
MD5 67aa23c7e2972082ced7b9c5592376b9
BLAKE2b-256 dbd83f55905dd0dcc8391f41b943d09c5a8411f3931cdf7d705b51f08191be38

See more details on using hashes here.

Provenance

The following attestation bundles were made for passwolf-0.3.0.tar.gz:

Publisher: publish.yml on StrongWind1/PassWolf

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file passwolf-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: passwolf-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 91.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for passwolf-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 17fe20f95c074e59bc50286143997dcf72cbb19d75d4989661b543d6caa9dc76
MD5 981532077e93f0a951d9cf8593825aac
BLAKE2b-256 5857b0d5cffc081f84ae3b9dda2c97a3cd6760bbd367ccb1e04f7c68abf1a130

See more details on using hashes here.

Provenance

The following attestation bundles were made for passwolf-0.3.0-py3-none-any.whl:

Publisher: publish.yml on StrongWind1/PassWolf

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page