# NTLM

[NT Lan Manager](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/c50a85f0-5940-42d8-9e82-ed206902e919) (NTLM/[MS-NLMP](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/b38c36ed-2804-4868-a9ff-8dd3182128e4)) is the name of a family of security protocols consisting of

* LM
* NTLMv1
* NTLMv2

NTLM is a connection-oriented protocol, its connection-less variant is called [MS-NLMP](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/c50a85f0-5940-42d8-9e82-ed206902e919). It's worth noting that both domain-joined and workgroup computers can utilize NTLM for authentication.

The protocol is used on various Windows-based networks to authenticate remote users and optionally provide session security when requested by the application. The NTLM security protocols are all embedded protocols, meaning that although NTLM has messages and a state machine like other protocols, it does not have a network protocol stack layer allowing any protocol with a defined layer in the network stack such as SMB, HTTP / HTTPS, and LDAP / LDAPS to utilize it.

NTLM is a challenge-response protocol that uses nonces, pseudo-random numbers generated for one-time use, as a defensive mechanism against replaying attacks.

Unlike normal protocol implementations, NTLM's nature means that the protocol is best implemented as a function library that can be called by application protocols rather than as a layer in a network protocol stack. This happens through [Security Support Provider Interface](https://learn.microsoft.com/en-us/windows/win32/rpc/sspi-architectural-overview) (SSPI), an API that allows connected applications to call one of several security providers to establish authenticated connections and to exchange data securely over those connections.

A [security support provider](https://learn.microsoft.com/en-us/windows/win32/rpc/security-support-providers-ssps-) (SSP) is a DLL responsible for implementing the SSPI by exposing one or more security packages to applications with each security package providing mappings between an application's SSPI function calls and an actual security model's functions.

The [NTLM SSP](https://learn.microsoft.com/en-us/windows-server/security/windows-authentication/security-support-provider-interface-architecture#BKMK_NTLMSSP) (located at `%windir%\system32\msv1_0.dll`) is a binary messaging protocol utilized by SSPI to facilitate NTLM challenge-response authentication and to negotiate options for integrity and confidentiality. The SSP encompasses both the NTLM and NTLMv2.

From a security standpoint, NTLM allows the plaintext credentials or cryptographic keys not to be sent over the wire (just like Kerberos) as the keys are either shared with the DC before-hand (in AD environments). Moreover, the NTLM version used in the authentication process isn't dynamically chosen during authentication, instead it's pre-configured through security policies and registry settings (`Security Settings > Local Policies > Security Options > Network security: LAN Manager authentication level`).

#### Password Hashing

| **Hash/Protocol** | **Cryptographic technique** | **Mutual Authentication** | **Message Type**        | **Trusted Third Party** |
| ----------------- | --------------------------- | ------------------------- | ----------------------- | ----------------------- |
| NTLM              | Symmetric key cryptography  | No                        | Random number           | Domain Controller       |
| NTLMv1            | Symmetric key cryptography  | No                        | MD4 hash, random number | Domain Controller       |
| NTLMv2            | Symmetric key cryptography  | No                        | MD4 hash, random number | Domain Controller       |

**LM hashes**

`LAN Manager` (LM or LANMAN) hashes are the oldest password storage mechanism used by the Windows operating system. LM debuted in 1987 on the OS/2 operating system. If in use, they are stored in the SAM database on a Windows host and the NTDS.DIT database on a Domain Controller. Due to significant security weaknesses in the hashing algorithm used for LM hashes, it has been turned off by default since Windows Vista/Server 2008. However, it is still common to encounter, especially in large environments where older systems are still used. Passwords using LM are limited to a maximum of `14` characters. Passwords are not case sensitive and are converted to uppercase before generating the hashed value, limiting the keyspace to a total of 69 characters making it relatively easy to crack these hashes using a tool such as Hashcat.

Before hashing, a 14 character password is first split into two seven-character chunks. If the password is less than fourteen characters, it will be padded with NULL characters to reach the correct value. Two DES keys are created from each chunk. These chunks are then encrypted using the string `KGS!@#$%`, creating two 8-byte ciphertext values. These two values are then concatenated together, resulting in an LM hash. This hashing algorithm means that an attacker only needs to brute force seven characters twice instead of the entire fourteen characters, making it fast to crack LM hashes on a system with one or more GPUs. If a password is seven characters or less, the second half of the LM hash will always be the same value and could even be determined visually without even needed tools such as Hashcat. The use of LM hashes can be disallowed using [Group Policy](https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/network-security-do-not-store-lan-manager-hash-value-on-next-password-change). An LM hash takes the form of `299bd128c1101fd6`.

{% hint style="info" %}
Windows operating systems prior to Windows Vista and Windows Server 2008 (Windows NT4, Windows 2000, Windows 2003, Windows XP) stored both the LM hash and the NTLM hash of a user's password by default.
{% endhint %}

The following are the instructions used to hash a password using the LM algorithm

1. Convert all lower case to upper case
2. Pad password to 14 characters with NULL characters
3. Split the password to two 7 character chunks
4. Create two DES keys from each 7 character chunk
5. DES encrypt the string "KGS!@#$%" with these two chunks
6. Concatenate the two DES encrypted strings. This is the LM hash.

**NTHash (NTLM) hashes**

`NT LAN Manager` (NTLM) hashes are used on modern Windows systems. It is a challenge-response authentication protocol and uses three messages to authenticate: a client first sends a `NEGOTIATE_MESSAGE` to the server, whose response is a `CHALLENGE_MESSAGE` to verify the client's identity. Lastly, the client responds with an `AUTHENTICATE_MESSAGE`. These hashes are stored locally in the SAM database or the NTDS.DIT database file on a Domain Controller. The protocol has two hashed password values to choose from to perform authentication: the LM hash (as discussed above) and the NT hash, which is the MD4 hash of the little-endian UTF-16 value of the password. The algorithm can be visualized as: `MD4(UTF-16-LE(password))`.

![](https://i.imgur.com/1v5yT2u.png)

Even though they are considerably stronger than LM hashes (supporting the entire Unicode character set of 65,536 characters), they can still be brute-forced offline relatively quickly using a tool such as Hashcat. GPU attacks have shown that the entire NTLM 8 character keyspace can be brute-forced in under `3 hours`. Longer NTLM hashes can be more challenging to crack depending on the password chosen, and even long passwords (15+ characters) can be cracked using an offline dictionary attack combined with rules. NTLM is also vulnerable to the pass-the-hash attack, which means an attacker can use just the NTLM hash (after obtaining via another successful attack) to authenticate to target systems where the user is a local admin without needing to know the cleartext value of the password.

An NT hash takes the form of `b4b9b02e6f09a9bd760f388b67351e2b`, which is the second half of the full NTLM hash. An NTLM hash looks like this:

```
Rachel:500:aad3c435b514a4eeaad3b935b51304fe:e46b9e548fa0d122de7f59fb6d48eaa2:::
```

Looking at the hash above, we can break the NTLM hash down into its individual parts:

* `Rachel` is the username
* `500` is the Relative Identifier (RID). 500 is the known RID for the `administrator` account
* `aad3c435b514a4eeaad3b935b51304fe` is the LM hash and, if LM hashes are disabled on the system, can not be used for anything
* `e46b9e548fa0d122de7f59fb6d48eaa2` is the NT hash. This hash can either be cracked offline to reveal the cleartext value (depending on the length/strength of the password) or used for a pass-the-hash attack.

During NTLM authentication, a client can prove to a server its identity by encrypting with its password some piece of information provided by the server. So the only thing the attacker has to do is to let the client do its work, and passing the messages from the client to the server, and the replies from the server to the client.

All the client has to send to the server, the attacker will receive it, and he will send the messages back to the real server, and all the messages that the server sends to the client, the attacker will also receive them, and he will forward them to the client, as is.

![](https://i.imgur.com/igqar9c.png)

So attacks like Pass-The-Hash work following this protocol and using the same secret as the legitimate user, but instead of hashing the password, the attacker can just use the raw NTLM hash

![](https://i.imgur.com/QXEzpnv.png)

**NTLMv1 (Net-NTLMv1) hashes**

The NTLM protocol performs a challenge/response between a server and client using the NT hash. NTLMv1 uses both the NT and the LM hash, which can make it easier to "crack" offline after capturing a hash using a tool such as [Responder](https://github.com/lgandx/Responder) or via an [NTLM relay attack](https://byt3bl33d3r.github.io/practical-guide-to-ntlm-relaying-in-2017-aka-getting-a-foothold-in-under-5-minutes.html) (both of which are out of scope for this module and will be covered in later modules on Lateral Movement). The protocol is used for network authentication, and the Net-NTLMv1 hash itself is created from a challenge/response algorithm. The server sends the client an 8-byte random number (challenge), and the client returns a 24-byte response. These hashes can NOT be used for pass-the-hash attacks. The algorithm looks as follows:

```
C = 8-byte server challenge, random
K1 | K2 | K3 = LM/NT-hash | 5-bytes-0
response = DES(K1,C) | DES(K2,C) | DES(K3,C)
```

An example of a full NTLMv1 hash looks like:

```
u4-netntlm::kNS:338d08f8e26de93300000000000000000000000000000000:9526fb8c23a90751cdd619b6cea564742e1e4bf33006ba41:cb8086049ec4736c
```

NTLMv1 was the building block for modern NTLM authentication. Like any protocol, it has flaws and is susceptible to cracking and other attacks. Now let us move on and take a look at NTLMv2 and see how it improves on the foundation that version one set.

**NTLMv2 (Net-NTLMv2) hashes**

The NTLMv2 protocol was first introduced in Windows NT 4.0 SP4 and was created as a stronger alternative to NTLMv1. It has been the default in Windows since Server 2000. It is hardened against certain spoofing attacks that NTLMv1 is susceptible to. NTLMv2 sends two responses to the 8-byte challenge received by the server. These responses contain a 16-byte HMAC-MD5 hash of the challenge, a randomly generated challenge from the client, and an HMAC-MD5 hash of the user's credentials. A second response is sent, using a variable-length client challenge including the current time, an 8-byte random value, and the domain name. The algorithm is as follows:

```
SC = 8-byte server challenge, random
CC = 8-byte client challenge, random
CC* = (X, time, CC2, domain name)
v2-Hash = HMAC-MD5(NT-Hash, user name, domain name)
LMv2 = HMAC-MD5(v2-Hash, SC, CC)
NTv2 = HMAC-MD5(v2-Hash, SC, CC*)
response = LMv2 | CC | NTv2 | CC*
```

An example of an NTLMv2 hash is:

```
admin::N46iSNekpT:08ca45b7d7ea58ee:88dcbe4446168966a153a0064958dac6:5c7830315c7830310000000000000b45c67103d07d7b95acd12ffa11230e0000000052920b85f78d013c31cdb3b92f5d765c783030
```

We can see that developers improved upon V1 by making NTLMv2 harder to crack and giving it a more robust algorithm made up of multiple stages. We have one more authentication mechanism to discuss before moving on. This method is of note to us because it does not require a persistent network connection to work.

More on how the responses are sent and calculated below.

#### Authentication Workflow

The NTLM authentication workflow for domain-joined computers starts with the client exchanging implementation-specific application protocol messages with the server (where the desired service is), indicating that it wants to authenticate. Subsequently, the client and server exchange three NTLM-specific messages during authentication (embedded in application protocol messages):

1. [NEGOTIATE\_MESSAGE](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/b34032e5-3aae-4bc6-84c3-c6d80eadf7f2) (also known as `Type 1` message)
2. [CHALLENGE\_MESSAGE](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/801a4681-8809-4be9-ab0d-61dcfe762786) (also known as `Type 2` message)
3. [AUTHENTICATE\_MESSAGE](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/033d32cc-88f9-4483-9bf2-b273055038ce) (also known as `Type 3` message)

Once it receives the `AUTHENTICATE_MESSAGE`, and because it does not possess the client's secret key, the server delegates the verification of the user's identity to a DC (a procedure known as [Pass-through authentication](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nrpc/70697480-f285-4836-9ca7-7bb52f18c6af)) by invoking [NetrLogonSamLogonWithFlags](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nrpc/d17f1077-de4b-4fcd-8867-39068cb789f5), which contains [NETLOGON\_NETWORK\_INFO](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nrpc/e17b03b8-c1d2-43a1-98db-cf8d05b9c6a8), a data structure populated with the various fields that the DC requires to verify the user. If authentication is successful, the DC returns a [NETLOGON\_VALIDATION\_SAM\_INFO4](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nrpc/bccfdba9-0c38-485e-b751-d4de1935781d) data structure to the server, and the server establishes an authenticated session with the client; otherwise, the DC returns an error, and the server might return an error message to the client, or, it can simply terminate the connection.

The diagram below is [NTLM's pass-through authentication](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-apds/5bfd942e-7da5-494d-a640-f269a0e3cc5d):

![](https://i.imgur.com/zMox83P.png)

The only difference for workgroup authentication is that the server verifies the user's identity instead of delegating it to the DC:

![](https://i.imgur.com/T1NzBdC.png)

#### NTLM Messages

Each NTLM message is variable-length, containing a fixed-length header and a variable-sized message payload. The header always starts with the `Signature` and `MessageType` fields, and depending on the latter, messages can have additional message-dependent fixed-length fields. A variable-length message payload follows these fields.

![NTLM\_Message\_Fields.png](https://academy.hackthebox.com/storage/modules/232/NTLM_Message_Fields.png)

| Field                    | Meaning                                                                                                                                                                                                                                                                                                                                    |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `Signature`              | An 8-byte NULL-terminated ASCII string always set to \[`N`, `T`, `L`, `M`, `S`, `S`, `P`, `\0`].                                                                                                                                                                                                                                           |
| `MessageType`            | A 4-byte unsigned integer always set to either `0x00000001` (`NtLmNegotiate`) to indicate that the NTLM message is a `NEGOTIATE_MESSAGE` or `0x00000002` (`NtLmChallenge`) to indicate that the NTLM message is a `CHALLENGE_MESSAGE` or `0x00000003` (`NtLmAuthenticate`) to indicate that the NTLM message is an `AUTHENTICATE_MESSAGE`. |
| `MessageDependentFields` | A variable-length field that contains the NTLM message contents.                                                                                                                                                                                                                                                                           |
| `payload`                | A variable-length field that contains a message-dependent number of individual payload messages, referenced by byte offsets in `MessageDependentFields`.                                                                                                                                                                                   |

**NEGOTIATE\_MESSAGE**

The [NEGOTIATE\_MESSAGE](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/b34032e5-3aae-4bc6-84c3-c6d80eadf7f2) is the first NTLM-specific message, sent by the client indicating that it wants to authenticate to the server and specifying its supported/requested NTLM options. It contains four message-dependent fixed-length fields. One important field to know about is `NegotiateFlags`; this 4-bytes field, present in all three NTLM messages and not exclusive to `NEGOTIATE_MESSAGE`, is a [NEGOTIATE](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/99d90ff4-957f-4c8a-80e4-5bfe5a9a9832) structure consisting of 32 1-bit flags that allow indicating which NTLM capabilities are supported/requested by the sender.

**CHALLENGE\_MESSAGE**

The [CHALLENGE\_MESSAGE](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/801a4681-8809-4be9-ab0d-61dcfe762786) is the second NTLM-specific message, sent by the server to the client to state the NTLM options it can support and challenge the client to prove its identity. It contains six message-dependent fixed-length fields, two important to know about, `NegotiateFlags` and `ServerChallenge`. `NegotiateFlags` holds the flags the server has chosen from the options offered/requested by the client in `NegotiateFlags` of the `NEGOTIATE_MESSAGE`. At the same time, `ServerChallenge` is a 64-bit nonce that holds the NTLM challenge generated by the server.

Some tools, such as [NTLM Challenger](https://github.com/nopfor/ntlm_challenger), [ntlm-info](https://gitlab.com/Zer1t0/ntlm-info), [NTLMRecon](https://github.com/praetorian-inc/NTLMRecon), and [DumpNTLMInfo.py](https://github.com/fortra/impacket/blob/impacket_0_11_0/examples/DumpNTLMInfo.py) perform reconnaissance against endpoints/hosts that accept NTLM authentication by parsing the information returned within the `CHALLENGE_MESSAGE` (review its other fields to know why this is possible):

```
python3 examples/DumpNTLMInfo.py 172.16.117.3

Impacket v0.12.0.dev1+20230803.144057.e2092339 - Copyright 2023 Fortra

[+] SMBv1 Enabled   : False
[+] Prefered Dialect: SMB 3.0
[+] Server Security : SIGNING_ENABLED | SIGNING_REQUIRED
[+] Max Read Size   : 8.0 MB (8388608 bytes)
[+] Max Write Size  : 8.0 MB (8388608 bytes)
[+] Current Time    : 2023-08-14 17:39:26.822236+00:00
[+] Name            : DC01
[+] Domain          : DOMAIN
[+] DNS Tree Name   : DOMAIN.COM
[+] DNS Domain Name : DOMAIN.COM
[+] DNS Host Name   : DC01.DOMAIN.COM
[+] OS              : Windows NT 10.0 Build 17763
[+] Null Session    : True
```

**AUTHENTICATE\_MESSAGE**

The [AUTHENTICATE\_MESSAGE](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/033d32cc-88f9-4483-9bf2-b273055038ce) is the third and last NTLM-specific message, sent by the client to the server to prove its possession of the shared secret key. It contains nine message-dependent fixed-length fields, two important to know about, `LmChallengeResponseFields` and `NtChallengeResponseFields`. For the pseudocode provided by MS-NLMP, we will also refer to the relevant implementation of [impacket's NTLM](https://github.com/fortra/impacket/blob/master/impacket/ntlm.py).

**NTLMv1 Response Calculation**

If `NTLMSSP_NEGOTIATE_LM_KEY` (the `G` bit in [NEGOTIATE](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/99d90ff4-957f-4c8a-80e4-5bfe5a9a9832)) was agreed upon by the server and client in `NegotiateFlags`, then, if NTLMv1 is used, `LmChallengeResponseFields` contains a [LM\_RESPONSE](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/e3fee6d1-0d93-4020-84ab-ca4dc5405fc9) structure, otherwise, if NTLMv2 is used, `LmChallengeResponseFields` will contain a [LMv2\_RESPONSE](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/8659238f-f5a9-44ad-8ee7-f37d3a172e56) structure. `LM_RESPONSE` contains one field, which is `Response`, a 24-byte array of [unsigned char](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/050baef1-f978-4851-a3c7-ad701a90e54a) that contains the client's `LmChallengeResponse`. While for `LMv2_RESPONSE`, it contains two fields, `Response` and `ChallengeFromClient`; `Response` is a 16-byte array of unsigned char that contains the clients `LM` `challenge-response`, while `ChallengeFromClient` is an 8-byte array of unsigned char that contains a challenge generated by the client. To compute the `Response` field of `LM_RESPONSE` or `LMv2_RESPONSE`, MS-NLMP provides [pseudocode](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/1b72429a-d8b8-4a04-bc82-1eedc980b87a).

For [NTLMv1 authentication](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/464551a8-9fc4-428e-b3d3-bc5bfb2e73a5), [NTOWFv1](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/780943e9-42e6-4dbe-aa87-1dce828ba82a#gt_7a2805fa-1dcd-4b4e-a8e4-2a2bcc8651e9) (used only by NTLMv1 and implemented in the [compute\_nthash](https://github.com/fortra/impacket/blob/9a8d27034eab20d23802730d0c69bf99356d8af1/impacket/ntlm.py#L759-L769) function), is an `NT LAN Manager` (`NT`) one-way function that creates a hash based on the user's password to generate a principal's security key: instead of using the user's plaintext password, the resultant hash of this function gets used in computing the response. [LMOWFv1](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/780943e9-42e6-4dbe-aa87-1dce828ba82a#gt_fd74ef50-cb97-4acd-b537-4941bdd9e064) (implemented in the [compute\_lmhash](https://github.com/fortra/impacket/blob/9a8d27034eab20d23802730d0c69bf99356d8af1/impacket/ntlm.py#L742C1-L747) function), used only by `LM` and NTLMv1, is an `NT LAN Manager` (`LM`) one-way function that also creates a hash based on the user's password to generate a principal's security key. The client uses these two functions to calculate the response it returns to the server; the [pseudocode](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/464551a8-9fc4-428e-b3d3-bc5bfb2e73a5) for the response calculation is implemented in the function [computeResponseNTLMv1](https://github.com/fortra/impacket/blob/9a8d27034eab20d23802730d0c69bf99356d8af1/impacket/ntlm.py#L717-L740).

For `NtChallengeResponseFields`, if NTLMv1 is used, `NtChallengeResponse` will contain an [NTLM\_RESPONSE](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/b88739c6-1266-49f7-9d22-b13923bd8d66) structure, otherwise, if NTLMv2 is used, then `NtChallengeResponse` will contain a [NTLMv2\_RESPONSE](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/d43e2224-6fc3-449d-9f37-b90b55a29c80) structure; `NTLM_RESPONSE` contains one field, which is `Response`, a 24-byte array of unsigned char that contains the client's `NtChallengeResponse`. For `NTLMv2_RESPONSE`, it contains two fields, `Response` and a [NTLMv2\_CLIENT\_CHALLENGE](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/aee311d6-21a7-4470-92a5-c4ecb022a87b) structure; `Response` is a 16-byte array of unsigned char that contains the client's `NtChallengeResponse`, while `NTLMv2_CLIENT_CHALLENGE` is a variable-length byte array that contains eight fixed-length variables, including `ChallengeFromClient`. If we were to capture an NTLMv1 hash using `Responder`, it will display it using the format `User::HostName:LmChallengeResponse:NtChallengeResponse:ServerChallenge`:

```shell-session
[SMB] NTLMv1 Client   : 172.19.117.36
[SMB] NTLMv1 Username : Support1
[SMB] NTLMv1 Hash     : Support1::WIN-OLMHXGAP0V2:e2dL3196O8f55fB6:Q49S19A2937J6XC3CKA418EI4958OHB9:xF2K324O5L6Q7V8C
```

**NTLMv2 Response Calculation**

For the response calculation of [NTLMv2 authentication](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/5e550938-91d4-459f-b67d-75d70009e3f3), [NTOWFv2](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/780943e9-42e6-4dbe-aa87-1dce828ba82a#gt_ba118c39-b391-4232-aafa-a876ee1e9265) and [LMOWFv2](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/780943e9-42e6-4dbe-aa87-1dce828ba82a#gt_a043ea96-e876-4259-be4b-aa8d2335fdfe) (both are version-dependent and only used by NTLMv2, they are implemented in the functions [LMOWFv2](https://github.com/fortra/impacket/blob/9a8d27034eab20d23802730d0c69bf99356d8af1/impacket/ntlm.py#L896C1-L897) and [NTOWFv2](https://github.com/fortra/impacket/blob/9a8d27034eab20d23802730d0c69bf99356d8af1/impacket/ntlm.py#L889C1-L894), respectively) are the one-way functions used to create a hash based on the user's password to generate a principal's security key. With these two functions, the client calculates the response it returns to the server as described in [pseudocode](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/5e550938-91d4-459f-b67d-75d70009e3f3) (implemented in the function [computeResponseNTLMv2](https://github.com/fortra/impacket/blob/9a8d27034eab20d23802730d0c69bf99356d8af1/impacket/ntlm.py#L900-L937)). If we were to capture an NTLMv2 hash using `Responder`, it will display it using the format `User::Domain:ServerChallenge:Response:NTLMv2_CLIENT_CHALLENGE`:

```shell-session
[SMB] NTLMv2-SSP Client   : 172.19.117.55
[SMB] NTLMv2-SSP Username : DOMAIN\Support2
[SMB] NTLMv2-SSP Hash     : Support2::DOMAIN:e2d2339638fc5fd6:D4979A923DD76BC3CFA418E94958E2B0:010100000000000000E0550D97CCD901509F9CE743AB58760000000002000800350034005800360001001E00570049004E002D00390038004B005100480054005300390048004200550004003400570049004E002D00390038004B00510048005400530039004800420055002E0035003400580036002E004C004F00430041004C000300140035003400580036002E004C004F00430041004C000500140035003400580036002E004C004F00430041004C000700080000E0550D97CCD901060004000200000008003000300000000000000000000000004000002DB95E9E27F0AD66CAA477372F555B500CFEA9C5A231FC68F0DA4FABFF76607E0A001000000000000000000000000000000000000900240063006900660073002F003100370032002E00310036002E003100310037002E00330030000000000000000000
```

#### NTLM Session Security

If the client and server negotiate it, [session security](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/d1c86e81-eb66-47fd-8a6f-970050121347) provides [message integrity](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/131b0062-7958-460e-bca5-c7a9f9086652) (`signing`) and [message confidentiality](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/115f9c7d-bc30-4262-ae96-254555c14ea6) (`sealing`). The NTLM protocol itself does not provide session security; instead, [SSPI](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/0776e9c8-1d92-488f-9219-10765d11c6b7) provides it. NTLMv1, supplanted by NTLMv2, does not support `sealing` but only `signing`; therefore, [Microsoft](https://support.microsoft.com/en-au/topic/security-guidance-for-ntlmv1-and-lm-network-authentication-da2168b6-4a31-0088-fb03-f081acde6e73) strongly recommends against its usage (and the deprecated `LM` authentication protocol also).

**Message Signing and Sealing**

`Message signing` provides message integrity and helps against relay attacks; it is a critical security feature designed to enhance the security of messages sent between the client and server during NTLM communications. When `session signing` is negotiated, the client and server negotiate a `session key` to sign all messages exchanged. The `session key` is generated using a combination of the client's and server's challenge messages and the user's password hash. Once the session key is established, all messages between the client and server are signed using a `MAC`. The `MAC` is generated by applying a cryptographic algorithm to the message and the session key. The server can verify the `MAC` by using the same algorithm as the message and the session key and comparing the result to the `MAC` provided by the client. Although an adversary might be eavesdropping, they don't possess the user's password hash since it is never transmitted over the wire, and therefore cannot sign messages. Based on the blog post [The Basics of SMB Signing (covering both SMB1 and SMB2)](https://learn.microsoft.com/en-us/archive/blogs/josebda/the-basics-of-smb-signing-covering-both-smb1-and-smb2), we can know the default `SMB signing` settings for hosts in the network depending on the SMB version they are running. Except for `SMB1`, which has three possible settings, `Required`, `Enabled`, or `Disabled`, `SMB2` and `SMB3` only have `Required` or `Not Required`:

| **Host**              | **Default Signing Setting** |
| --------------------- | --------------------------- |
| `SMB1 Client`         | `Enabled`                   |
| `SMB1 Server`         | `Disabled`                  |
| `SMB2 & SMB3 Clients` | `Not Required`              |
| `SMB2 & SMB3 Servers` | `Not Required`              |
| `Domain Controllers`  | `Required`                  |

Due to the ever-lasting abuse of the default SMB signing settings by adversaries, [Microsoft](https://blogs.windows.com/windows-insider/2023/06/02/announcing-windows-11-insider-preview-build-25381/) released an update to enforce SMB `signing` on Windows 11 Insider editions (and later on for major releases). Microsoft decided, for a better security stature, to finally let go of the legacy behavior where Windows 10 and 11 required SMB `signing` by default only when connecting to shares named `SYSVOL` and `NETLOGON` and where DCs required SMB `signing` when any client connected to them. Ned Pyle, a Principal Program Manager at Microsoft, wrote the following regretful statement in the post [SMB signing required by default in Windows Insider](https://techcommunity.microsoft.com/t5/storage-at-microsoft/smb-signing-required-by-default-in-windows-insider/ba-p/3831704):

"SMB encryption is far more secure than signing, but environments still run legacy systems that don't support SMB 3.0 and later. If I could time travel to the 1990s, SMB signing would've always been on and we'd have introduced SMB encryption much sooner; sadly, I was both in high school and not in charge. We'll continue to push out more secure SMB defaults and many new SMB security options in the coming years; I know they can be painful for application compatibility and Windows has a legacy of ensuring ease of use, but security cannot be left to chance."

`Message sealing` provides message confidentiality by implementing a symmetric-key encryption mechanism; it ensures that the content of the messages exchanged between the client and server remains secure and that adversaries cannot read or tamper with them. In the context of NTLM, `sealing` also implies `signing` because every `sealed` message is also `signed`.

#### Extended Protection for Authentication (EPA)

`Extended Protection for Authentication` (`EPA`), based on [RFC 5056](https://datatracker.ietf.org/doc/html/rfc5056), is a feature introduced in Windows Server 2008 and later versions that enhance the security of NTLM authentication. When `EPA` is enabled, the client and server establish a secure channel using a `channel binding token` (`CBT`). The `CBT` binds the authentication to the specific channel characteristics, such as the IP address and port, preventing the authentication from replaying on a different channel. `EPA` is designed to work with SMB and HTTP protocols, providing additional security for applications and services that rely on NTLM authentication; however, it requires the client and server to support it to establish a secure channel.

#### Domain Cached Credentials (MSCache2)

In an AD environment, the authentication methods mentioned in this section and the previous require the host we are trying to access to communicate with the "brains" of the network, the Domain Controller. Microsoft developed the [MS Cache v1 and v2](https://webstersprodigy.net/2014/02/03/mscash-hash-primer-for-pentesters/) algorithm (also known as `Domain Cached Credentials` (DCC) to solve the potential issue of a domain-joined host being unable to communicate with a domain controller (i.e., due to a network outage or other technical issue) and, hence, NTLM/Kerberos authentication not working to access the host in question. Hosts save the last `ten` hashes for any domain users that successfully log into the machine in the `HKEY_LOCAL_MACHINE\SECURITY\Cache` registry key. These hashes cannot be used in pass-the-hash attacks. Furthermore, the hash is very slow to crack with a tool such as Hashcat, even when using an extremely powerful GPU cracking rig, so attempts to crack these hashes typically need to be extremely targeted or rely on a very weak password in use. These hashes can be obtained by an attacker or pentester after gaining local admin access to a host and have the following format: `$DCC2$10240#bjones#e4e938d12fe5974dc42a90120bd9c90f`. It is vital as penetration testers that we understand the varying types of hashes that we may encounter while assessing an AD environment, their strengths, weaknesses, how they can be abused (cracking to cleartext, pass-the-hash, or relayed), and when an attack may be futile (i.e., spending days attempting to crack a set of Domain Cached Credentials).
