docs/metasploit-framework.wiki/Meterpreter-Configuration.md
Meterpreter has always needed to be configured on the fly so that it knows how to talk to Metasploit. For many years, this configuration management was achieved by hot-patching a copy of the metsrv DLL/binary using a simple "string replace" approach. This worked well enough to support a number of situations but restricted the flexibility of Meterpreter and its support for handling multiple transports.
It wasn't just transports that were locked down, but the ability to provide payloads that contained way more than the core Meterpreter (metsrv) itself. It was also not easy to pass other forms of information on the fly to the Meterpreter instance because the stagers were only able to pass in a copy of the active socket handle.
Recent modifications to Meterpreter have done away with this old method and have replaced with a dynamic configuration block that can be used to alleviate these problems and provide the flexibility for other more interesting things down the track.
This document contains information on the structure and layout of the new configuration block, along with how it is used by Meterpreter.
In the past, Meterpreter has required that the stager (or stage0 as some like to call it) pass in a handle to the active socket so that it can take over communications without creating a new socket (at least in the case of TCP connections). While this feature is still required, it doesn't happen in the way that it used to. Instead, Meterpreter now requires that the stager pass in a pointer to the start of the configuration block. The configuration block can be anywhere in memory, so long as the memory region is marked as RWX.
Stage 1 of loading Windows Meterpreter now utilises a new loader, called meterpreter_loader (Win x86, Win x64), which does the following:
metsrv DLL from disk.metsrv and calculates the location that points to the end of metsrv in memory. It also takes any existing socket value (found in edi or rdi depending on the architecture) and writes that directly to the configuration (more on this later).metsrv binary.The result is that the payload has the following structure once it has been prepared:
+--------------+
| Patched DOS |
| header |
+--------------+
| |
. .
. metsrv dll .
. .
| |
+--------------+
| config block |
+--------------+
All of the configuration for the POSIX Meterpreter is able to be passed through command-line arguments to the payload. When generating a payload with a specific configuration, a simulated command line is patched into a static variable in the main startup code. Generate a payload and see ./mettle -h for a full description of available arguments.
In order to pass information to Meterpreter and not have it break, a known format of configuration is required. This format needs to be consistent on each invocation, much like you would expect with any configuration. In the case of binary Meterpreter (POSIX and Windows), this configuration block contains the following:
Each of these blocks is described in detail in the sections below.
The notion of a session configuration block is used to wrap up the following values:
metsrv executes. This socket handle is written to the configuration block on the fly by the loader. It is stored in the Session configuration block so that it has a known location. This value is always a 32-bit DWORD, even on 64-bit platforms.The layout of this block in memory looks like this:
+--------------+
|Socket Handle |
+--------------+
| Exit func |
+--------------+
|Session Expiry|
+--------------+
| |
| UUID |
| |
| |
+--------------+
| <- 4 bytes ->|
With this structure in place, Meterpreter knows that the session configuration block is exactly 28 bytes in size.
The Session configuration block description can be found in the Meterpreter source.
The Transport configuration block is a term used to refer to the group of transport configurations that are present in the payload. Meterpreter now supports multiple transports, and so the configuration should support multiple transports too.
There are two main issues when dealing with transport configurations:
Meterpreter's current transport implementations provide two main "classes" of transport, those being HTTP(S) and TCP. Each of these transport classes requires different configuration values, as well as common values, in order to function.
The values that are common to both HTTP(S) and TCP transports are:
512 characters (Windows Meterpreter uses wchar_t, while POSIX Meterpreter uses char). Transport types are specified by the scheme element in the URL, and the body of the URL specifies key information such as host and port information. Meterpreter inspects this to determine what type of transport block is in use, and hence from there is able to determine the size of the block. Valid values look like the following:
tcp://<host>:<port> - indicates that this payload is a reverse IPv4 TCP connection.tcp6://<host>:<port>?<scope> - indicates that this payload is a reverse IPv6 TCP connection.tcp://:<port> - indicates that this payload is a bind payload listening on the specified port (note that no host is specified).http://<host>:<port>/<uri> - indicates that this payload is an HTTP connection (can only be reverse).https://<host>:<port>/<uri> - indicates that this payload is an HTTPS connection (can only be reverse).The layout of this block in memory looks like the following:
+--------------+
| |
| URL |
. .
. . 512 characters worth
. . (POSIX -> ASCII -> char)
. . (Windows -> wide char -> wchar_t)
. .
| |
+--------------+
| Comms T/O |
+--------------+
| Retry Total |
+--------------+
| Retry Wait |
+--------------+
| <- 4 bytes ->|
The common transport configuration block description can be found in the Meterpreter source.
At this time, there are no TCP-specific configuration values, as the common configuration block caters for all of the needs of TCP transports. This may change down the track.
HTTP and HTTPS connections have a number of extra configuration values that are required in order to make it function correctly in various environments. Those values are:
128 characters in size (wchar_t only, given that we don't yet have HTTP/S transport in POSIX), and can be in one of the following formats:
http://<proxy ip>:<proxy port> in the case of HTTP proxies.socks=<socks ip>:<sock port> in the case of socks proxies.64 characters in size (wchar_t).64 characters in size (wchar_t).HTTP/S requests are made to Metasploit. This field is 256 characters in size (wchar_t).HTTPS. This value contains the 20-byte SHA1 hash of the expected certificate. For more information, please read the SSL certificate validation documentation (link coming soon).All values that are shown above need to be specified in the configuration, including SSL certificate validation for plain HTTP connections. Values that are not used should be zeroed out.
The structure of the HTTP/S configuration is as follows.
+--------------+
| |
| Proxy host |
. . 128 characters worth (wchar_t)
| |
+--------------+
| |
| Proxy user |
. . 64 characters worth (wchar_t)
| |
+--------------+
| |
| Proxy pass |
. . 64 characters worth (wchar_t)
| |
+--------------+
| |
| User agent |
. . 256 characters worth (wchar_t)
| |
+--------------+
| |
| SSL cert |
| SHA1 hash |
| |
| |
+--------------+
| <- 4 bytes ->|
The HTTP/S transport configuration block description can be found in the Meterpreter source.
As already mentioned, more than one of these transport configuration blocks can be specified. In order to facilitate this, Meterpreter needs to know when the "list" of transports has ended. Using the URL, Meterpreter can determine the size of the block and can move to the next block, depending on the type that is discovered. As soon as Meterpreter detects a transport configuration URL value that has a string length of zero, for example, a single NULL ASCII char in POSIX and a single NULL multi-byte char in Windows, it assumes that the transport list has been terminated. The byte immediately following this is deemed to be the start of the Extension configuration, which is documented in the next section.
The extension configuration block is designed to allow Meterpreter payloads to contain any extra extensions that the user wants to bundle in. The goal is to provide the ability to have [[Stageless payloads|./Meterpreter-Stageless-Mode.md]], and to provide the means for sharing of extensions during migration (though this hasn't been implemented yet). Each of the extensions must have been compiled with Reflective DLL Injection support, as this is the mechanism that is used to load the extensions when Meterpreter starts. For more information on this facility, please see the [[Stageless payloads|./Meterpreter-Stageless-Mode.md]] documentation.
The extension configuration block also functions as a "list" to allow for an arbitrary number of extensions to be included. Each extension entry needs to contain:
When loading the extensions from the configuration, Meterpreter will continue to parse entries until it finds a size value of 0. At this point, Meterpreter assumes it has reached the end of the extension list and will stop parsing.
The structure is simply laid out like the following:
+--------------+
| Ext. Size |
+--------------+
| Ext. content |
+--------------+
| NULL term. |
| (4 bytes) |
+--------------+
To summarise, the following shows the layout of a full configuration:
+--------------+
|Socket Handle |
+--------------+
| Exit func |
+--------------+
|Session Expiry|
+--------------+
| |
| UUID |
| |
| |
+--------------+
| Transport 1 |
| tcp://... |
. .
| |
+--------------+
| Comms T/O |
+--------------+
| Retry Total |
+--------------+
| Retry Wait |
+--------------+
| Transport 2 |
| http://... |
. .
| |
+--------------+
| Comms T/O |
+--------------+
| Retry Total |
+--------------+
| Retry Wait |
+--------------+
| |
| Proxy host |
| |
+--------------+
| |
| Proxy user |
| |
+--------------+
| |
| Proxy pass |
| |
+--------------+
| |
| User agent |
| |
+--------------+
| |
| SSL cert |
| SHA1 hash |
| |
+--------------+
| NULL term. |
|(1 or 2 bytes)|
+--------------+
| Ext 1. Size |
+--------------+
|Ext 1. content|
+--------------+
| Ext 2. Size |
+--------------+
|Ext 2. content|
+--------------+
| NULL term. |
+--------------+