Obtaining a Fully Interactive Shell

I came across this while trying to solve similar issues, might help others. There are few additional commands to what is listed in first post.

• On the remote machine, run python -c ‘import pty; pty.spawn(“bash”)’ and press CTRL-z to put the SSH session to the background.
• Then run stty -a to print out information about your shell. Note the rows and columns (say they are 40 and 160 respectively).
• Now run stty raw -echo to put your shell into raw mode, then fg to get back into the SSH session, and finally reset to reset the shell. It you get asked for the type of the terminal, use xterm-256color.
• After that, run stty rows 40 columns 160 to specify the correct size. You should now have a fully working shell, in particular vi should work.

That’s a great thing to share, so here are my two cents:

  • Spawning bash with python:
$ python -c 'import pty; pty.spawn("/bin/bash")'
  • Background’ing the remote shell with CTRL-Z:
user@remote:~$ ^Z
  • Getting ROWS and COLS within current terminal window:
user@local:~$ stty -a | head -n1 | cut -d ';' -f 2-3 | cut -b2- | sed 's/; /\n/'
  • Ignoring hotkeys in the local shell and getting back to the remote:
user@local:~$ stty raw -echo; fg
  • Setting correct size for the remote shell (where ROWS and COLS are the values from the 3rd bullet):
user@remote:~$ stty rows ROWS cols COLS
  • Adding some colors:
user@remote:~$ export TERM=xterm-256color
  • Reloading bash to apply the TERM variable:
user@remote:~$ exec /bin/bash

:triumph:

2 Likes

Great thread. Sexytime

You can also write a c program that spawns a child which is controlled by a pty. In this article you find information on how to do that:
http://rachid.koucha.free.fr/tech_corner/pty_pdip.html

If you want to read about what tty/pty are, take a look at this article:
http://www.linusakesson.net/programming/tty/

something handy for me is setting this up in the custom commands plugin for terminator.
i have 3 commands, one to pty.spawn bash, one to print and set stty info locally, and one to set stty on the actual rev shell. they are quick and dirty one liners but it works pretty well here are my commands:

Terminator Custom Commands

name: Upgrade TTY Python
Command: python -c “import pty;pty.spawn(‘/bin/bash’)”

name: Fix TTY 1
command: printf "\n\n(Rows,Cols)\n ";printf ‘\e[1;91m%-6s\e[m’ $(stty size);printf “\n\nTerm= \e[91m$TERM\e[0m\n\n”;stty raw -echo;fg;

name: Fix TTY 2
command: export SHELL=bash;export TERM=xterm-256color;stty rows 20 columns 100;\echo ;echo ;read -p “Enter Rows:” ROWS;read -p “Enter Cols:” COLS;stty rows $ROWS columns $COLS && clear

once you get a reverse shell

  1. right click > custom commands > Upgrade TTY Python
  2. Press Ctrl+z to background
  3. right click > custom commands > Fix TTY 1
  4. right click > custom commands > Fix TTY 2
  5. enter the row and col values when prompted (should still be on screen from step 2, so long as no reset is used).

For the people (@hkh4cks) who’s gettin the ^M and ^? instead of ENTER and BACKSPACE after running the fg command here’s the problem explanation and solution.

Probably you’re using zsh as your terminal and/or MacOS. The main problem here is that zsh doesn’t handle the stty command the same way bash or sh does. So if you read stty manual and check what the command stty raw -echo was intended to do, you’ll see that after running it, your output wasn’t supposed to be echoed back to your screen anymore. So if you run stty -echo and still are able to see what you’re typing next, your terminal are not respecting the -echo. Reading this zsh mailing list thread (Re: stty not working) we can see that zsh, specifically, only respect the -echo until the next prompt. That means that you need to type your next command all in one line, just line like @snovvcrash showed in his comment:

user@local:~$ stty raw -echo; fg

If you try to execute this as two separated commands, as soon as the prompt appear for you to execute the fg command, your -echo command already lost its effect. This is not a zsh limitation however, au contraire, this is an intended behavior for your own safety. Zsh behave like this to prevent you from getting stuck blinded at a terminal. For you to understand what it mean, just run bash and then stty -echo. Now you have no ideia what you’re typing anymore. You’re blind Jost hoping you correctly type reset to get your echo back.

Hope this help. Cheers!

Type your comment> @salamander said:

For the people (@hkh4cks) who’s gettin the ^M and ^? instead of ENTER and BACKSPACE after running the fg command here’s the problem explanation and solution.

Probably you’re using zsh as your terminal and/or MacOS. The main problem here is that zsh doesn’t handle the stty command the same way bash or sh does. So if you read stty manual and check what the command stty raw -echo was intended to do, you’ll see that after running it, your output wasn’t supposed to be echoed back to your screen anymore. So if you run stty -echo and still are able to see what you’re typing next, your terminal are not respecting the -echo. Reading this zsh mailing list thread (Re: stty not working) we can see that zsh, specifically, only respect the -echo until the next prompt. That means that you need to type your next command all in one line, just line like @snovvcrash showed in his comment:

user@local:~$ stty raw -echo; fg

If you try to execute this as two separated commands, as soon as the prompt appear for you to execute the fg command, your -echo command already lost its effect. This is not a zsh limitation however, au contraire, this is an intended behavior for your own safety. Zsh behave like this to prevent you from getting stuck blinded at a terminal. For you to understand what it mean, just run bash and then stty -echo. Now you have no ideia what you’re typing anymore. You’re blind Jost hoping you correctly type reset to get your echo back.

Hope this help. Cheers!

Big man coming in clutch with this. Props.

After fg, ctrl+z cannot background the shell ?

Type your comment> @BaiduFu said:

After fg, ctrl+z cannot background the shell ?

You did it backwards. fg stands for “foreground”, meaning you’ll be foregrounding the job you just “backgrounded” with CTRL+Z.

After getting a terminal:

python -c ‘import pty; pty.spawn(“/bin/bash”)’
CTRL-z
bg
stty raw -echo
fg
reset
(In case of unknown terminal type try: linux)

Optional:
export SHELL=/bin/bash
export TERM=xterm-color
export HOME=

Then fix up the rows and columns. Open another terminal
stty -a

Get the rows and columns.

Back on your reverse shell:
stty rows <> columns <>

Rarely does the python part not work… when it doesn’t I simply find a work around or just deal with what I have.

For the sake of variety; instead of doing the python -c ... thing, thus relying on python being available on the box, you could also do:

script /dev/null, this will give you a pty (as tty will tell you), so su and passwd should work. I usually do a bash -i first. Do note that the environment will still need some fixing up (CTRL+z ... etc and export TERM=linux, export HOME=/tmp or something similar).

HTH!

Type your comment> @KeyboardCaper said:

After getting a terminal:

python -c ‘import pty; pty.spawn(“/bin/bash”)’
CTRL-z
bg
stty raw -echo
fg
reset
(In case of unknown terminal type try: linux)

Optional:
export SHELL=/bin/bash
export TERM=xterm-color
export HOME=

Then fix up the rows and columns. Open another terminal
stty -a

Get the rows and columns.

Back on your reverse shell:
stty rows <> columns <>

Rarely does the python part not work… when it doesn’t I simply find a work around or just deal with what I have.

Probably good to note for this that python -c 'import pty;pty.spawn("/bin/bash")' won’t work with any versions of Python3, so specifying python3 -c ... is necessary. Otherwise solid description, you nailed it to a “T”.

I have a curious problem with this kind of shell. I’m working with the Kali KDE distribution with the standard Konsole terminal and /bin/bash/.

I start a reverse shell from another machine.

On my attacking machine I have netcat listening:
nc -l -v -p 80

I get the connection on my host:
listening on [any] 80 …
connect to [10.10.14.2] from craft.htb [10.10.10.110] 40575
/bin/sh: can’t access tty; job control turned off
/opt/app #

I do my routine to elevate the shell:
python -c ‘import pty; pty.spawn(“/bin/bash”)’
CTRL-z
stty raw -echo
fg
reset

I have a fully functional shell BUT I can’t close it. I’ll always have to kill the process. I use exit to leave the shell and end up in a window where I can’t enter any commands. At first I thought that it is a problem with zsh (stty raw -echo; fg kind of) but it is the same in /bin/bash and in Xterm instead of Konsole.

Any Ideas what could go wrong here?

On a side note, what if I don’t have an /bin/bash on the remote machine? Is it possible to get an fully interactive shell?

@timebeyond said:
I have a fully functional shell BUT I can’t close it. I’ll always have to kill the process. I use exit to leave the shell and end up in a window where I can’t enter any commands. At first I thought that it is a problem with zsh (stty raw -echo; fg kind of) but it is the same in /bin/bash and in Xterm instead of Konsole.

I actually had this exact same issue when I was working on networked. I had to kill the process, but I am not sure what went wrong.

On a side note, what if I don’t have an /bin/bash on the remote machine? Is it possible to get an fully interactive shell?

You can use /bin/sh, which is most of the time just a symbolic link to the real active shell.

Thanks for the reassurance that my standard setup has no flaws. Just wanted to be sure that the problem isn’t between the keyboard and the chair.

If you are looking for a way to get fully interactive shell on Windows i just released a c#/powershell reverse shell that implements the pty console. Here the link → GitHub - antonioCoco/ConPtyShell: ConPtyShell - Fully Interactive Reverse Shell for Windows

@splintercode said:
If you are looking for a way to get fully interactive shell on Windows i just released a c#/powershell reverse shell that implements the pty console. Here the link → GitHub - antonioCoco/ConPtyShell: ConPtyShell - Fully Interactive Reverse Shell for Windows

This is absolutely glorious! Just tried it, and suddenly my smb-recon-using-linux-tools-PTSD is cured by the healing light of PS in a PTY :slight_smile:

@splintercode it appears to have some issues deciding which process that listens to the input pipe though. I run the shell from a small PS-stager that IEXs the Invoke-Con*-definition along with an invocation in the same command, and often I get atleast two powershell.exe’s spinning up a process each for every one I try to start :slight_smile:

@scud78 i don’t understand the bugged scenario. If you can open an issue on github (Issues · antonioCoco/ConPtyShell · GitHub) i could troubleshoot the scenario and work for a fix.

@splintercode said:
@scud78 i don’t understand the bugged scenario. If you can open an issue on github (Issues · antonioCoco/ConPtyShell · GitHub) i could troubleshoot the scenario and work for a fix.

Turns out it was the combination of three (or possibly four) nested powershell processes (including yours) with DUPd stdhandles. Not much you can do about that, really :wink: