docs/metasploit-framework.wiki/Debugging-Dead-Meterpreter-Sessions.md
Dead shells. Nobody likes them. Yet, despite the advances made in the Metasploit stagers and Meterperter itself, we still see them regularly.
There are many reasons why shells refuse to connect or die after they're established. The goal of this post is to help people understand why. Hopefully, by the end, the most common causes will be understood, and users can fix things themselves.
Prior to diving into the possible breakages and their causes, it's important to have some background knowledge of stagers, and how Meterpreter works. Please be sure to read the following articles prior to reading the rest of this post:
Each exploit and handler is made up of multiple things, and they're all independent:
In some cases, there might be multiple stages (as is the case with POSIX Meterpreter). This is called an intermediate stage. Usually, these stages are slightly bigger than the stager and can do more work to help establish communications.
The most important thing to remember is that both the stager and the stage have their own configurations that are independent. THE MOST COMMON cause of dead shells is the result of the stage not having the correct configuration; in other words, it's different to that specified in the stager.
Any user of Metasploit will tell you that they know what LHOST and LPORT mean, yet it's incredibly common to find out that their understanding isn't 100% correct. To prevent dead sessions that are related to a misconfiguration of these values, we need to make sure we understand what they mean.
LHOST is short for Local Host. This value represents the IP address or hostname that stagers and stages should attempt to connect to. It is where the handler can be reached. This doesn't mean that this is where the handler actually exists.
LHOST is a value that is meaning from the perspective of the target machine. This value is passed along as part of the configuration for stagers and stages and tells the target machine where to go to reach the handler, and so this has to map to a value that is reachable by the target.
A handler obviously needs to listen on a host/IP for the incoming connection. In cases where the LHOST value, for example the address that the target is able to reach, is the same as that which the host can listen on, no extra work has to be done. The LHOST value is used by the handler.
However, if some kind of NAT or port forward is enabled, or if the handler is behind a firewall, then setting LHOST isn't enough. In order to listen on the appropriate interface, another setting must be used called ReverseListenerBindAddress. This value tells the handler to listen on a different interface/IP, but it doesn't change the fact that the LHOST value is given to the target when the stage is uploaded.
In short, LHOST must always remain the IP/host that is routable from the target, and if this value is not the same as what the listener needs to bind to, then change the ReverseListenerBindAddress value. If you're attacking something across the Internet and you specify an internal IP in LHOST, you're doing it wrong.
The principles of LHOST and ReverseListenerBindAddress can be applied to LPORT and ReverseListenerBindPort as well. If you have port forwarding in place, and your listener needs to bind to a different port, then you need to make use of the ReverseListenerBindPort setting.
The classic example of this case is where an attacker wants to make use of port 443, but rightfully doesn't want to run Metasploit as root just so they can directly bind to ports lower than 1024. Instead, the set up a port forward (on their router, or using iptables) so that 443 forwards to 8443, with a goal of accepting connections on that port instead.
To accommodate this scenario, the LHOST value must still contain 443, as this is the port that the target machine needs to establish communications on; 443 is the value that needs to go out with the stager and the stage configurations. Metasploit needs to bind locally to port 8443, and so the handler is configured so that ReverseListenerBindPort has this value instead.
When the handler launches, it binds to 8443 and handles any connections it receives. When a stage is generated, it uses 443 from LHOST value to populate the configuration.
If the attacker makes the mistake of either setting LPORT to 8443, or leaving LPORT as 443 and not using ReverseListenerBindPort, then the result is either a dead shell after the first stage, or no connect back at all.
There are a few things to check for when debugging a dead shell.
LHOST is set to a routable address from the target, and not a local listen address.LPORT is set to the port number that the target needs to connect to.ReverseListenerBindPort is set if port forwarding is enabled and the traffic is being routed to a different port.metsrv, is being caught while being uploaded. reverse_tcp and reverse_http stagers download metsrv without any encryption, and so the content of the DLL is visible to anything watching on the wire. reverse_https can still get caught in cases where AV is doing MITM content inspection. In this case, consider encoding your payloads, or if possible using stageless Meterpreter instead.