Saturday, September 30, 2017

SSHPry v2 - Spy & Control SSH Connected client's TTY

- What if we'll have a tool that can show us a terminal of active SSH connection?
and... maybe... control it? Record it? Investigate?

I always curious about what can be done after you somehow got root and already talked about some techniques of post exploitation with highly privileged accounts:
1. SSH Snooping
2. RDP Session Hijacking

Today I want to talk about linux terminals - TTYs.

Hurry? Scroll down to Demo.

- Observation -

Every *nix user should already know about GNU Screen, especially of it's '-x' multi display mode feature, that allows to observe an attached screen session.
That's cool, but what if we don't have screen on the target machine?

I don't know nothing about terminal emulators, so i can make mistakes, but...
As mentioned in SSH Snooping attack, we can utilize 'strace' to get all process' syscalls read/write including root's password.

As you may already know, I've implemented this technique to get ALL read() strings of connected ssh client in script that mirrors a terminal of connected SSH client.

BTW, main python trick was 'string'.decode('string_escape') and voila we've got identical terminal session!

So far so good, but not enough, we need full control.

- Taking Control -

Firstly, I wondered how can I send some data or keystrokes to another TTY. Because if you make something like this:
echo 123 > /dev/pts/19
It will appear on that TTY but only as standard output, meaning, if you press Enter - nothing happens.

I've found utility in C that actually sends data to another TTY, but the downside that it needs to be compiled. Luckily google come up with python library that can do that!

import termios, fcntl
import sys

command = sys.argv[1]
tty = sys.argv[2]

with open(tty) as f:
   for c in command.decode('string_escape'):

Secondly, thanks to enrico.bacis answer on StackOverflow, I've learned how to catch my keyboard input.

By combining all these techniques and spawning two separate threads one for echoing 'strace' strings to our terminal and second for transferring our standard input to target TTY we get a tool that replicates GNU screen '-x' feature without screen itself with couple more #redteam and #blueteam related cool features.

Once we get full control over the session, and we get all strings - we can make some phishing :)

- Console-Level Phishing -

As we already know 'echo 123 > /dev/pts/TTY'  does not affect terminal except standard output, we can create custom phishing messages to target user/tty.
Furthermore, we can utilize terminal escape sequences, which described here and here, then craft a realistic phishing message:

We see login keyring message, but instead we have executed some evil script:

import termios, fcntl
import sys
from time import sleep

tty = sys.argv[1]

command = 'python -c \'exec("aW1wb3J0IGdldHBhc3MNdHJ5Og0gZ2V0cGFzcy5nZXRwYXNzKCkNZXhjZXB0Og0gcGFzcw0=".decode("base64"))\'\n'
message = '\033[2A\033[2K\r'+' '*(len(command)+20)
message += '\nEnter password to unlock your login keyring:'

with open(tty) as f:
   for c in command.decode('string_escape'):
with open(tty,'w') as f:

While listening to all strings with 'strace', we can get clear-text password of any logged in user, especially root.

- Record & Replay -

While the initial idea was offensive, once I've developed the tool came out that it can be useful to all kind of defenders: Blue-Teams, Incident Response and Forensics.

I've developed a feature that allows to record an SSH session of connected client, and then replay it to investigate what happened.

- Demo -

- Get It -

Developed under GNU General Public License v 3.0


  1. Hi, little help, when run ./ --auto as root on alma linux 9.2 with Python ver 3.9.16 got: (, TypeError("a bytes-like object is required, not 'str'"), ). any ideas