CAPTURING 0DAY EXPLOITSWITH PERFECTLY PLACED
HARDWARE TRAPS
Cody Pierce . Matt Spisak . Kenneth FitchINTRODUCTIONINTRODUCTIONBLACKHAT 2016

EXPLOIT DETECTION IS A MOVING TARGET▸ Exploitation is increasingly more sophisticated▸ Creativity in exploitation is hard to plan for in the Security Development
Lifecycle (SDL)▸ A well financed attacker armed with 0days has the advantage

BLACKHAT 2016

INTRODUCTIONEARLY PREVENTION TO MAINTAIN THE ADVANTAGE

SoftwareIdentification

Memory Organization

Return Oriented
Programming

Version Identification

Vulnerability
Preparation

Payload Execution

OS Identification

Vulnerability Trigger

COE

Code Execution

PersistenceBLACKHAT 2016

INTRODUCTIONEARLY PREVENTION TO MAINTAIN THE ADVANTAGE

SoftwareIdentification

Memory Organization

Return Oriented
Programming

Version Identification

Vulnerability
Preparation

Payload Execution

OS Identification

Vulnerability Trigger

COE

Code Execution

PersistenceINTRODUCING
HARDWARE ASSISTANCEBLACKHAT 2016

INTRODUCING - HARDWARE ASSISTANCECPU COREPERFORMANCEMONITORING UNIT

BRANCHPREDICTION UNITINTRODUCING - PERFORMANCE MONITORING UNIT

CPU COREPERFORMANCEMONITORING UNIT

BLACKHAT 2016

BRANCHPREDICTION UNITINTRODUCING - PERFORMANCE MONITORING UNIT

BLACKHAT 2016

PERFORMANCE MONITORING UNIT
▸ A special unit in microprocessor architectures to enable hardware level
performance and system information. Often used to optimize hardware andsoftware▸ The PMU can be programed to record dozens of different hardware “events”▸ Traditionally reserved for developers and system architects

INTRODUCING - PERFORMANCE MONITORING UNIT

0x03 LD_BLOCKS
0x0D INT_MISC

CPU CORE

0x3C CPU_CLK_UNHALTED
0x48 L1D_PEND_MISS
0x85 ITLB_MISSES
0x89 BR_MISP_EXEC
0xA2 RESOURCE_STALLS
0xAE ITLB.ITLB_FLUSH
0xC0 INST_RETIREDPERFORMANCEMONITORING UNIT

BLACKHAT 2016

INTRODUCING - PERFORMANCE MONITORING UNIT

BLACKHAT 2016

PERFORMANCE MONITORING UNIT FOR SECURITY▸ “Security Breaches as PMU Deviation: Detecting and Identifying Security
Attacks Using Performance Counters”, Yuan et al., 2011
▸ “CFIMon: Detecting Violation of Control Flow Integrity using Performance
Counters”, Xia et al., 2012
▸ “kBouncer: Efficient and Transparent ROP Mitigation”, Pappas, 2012
▸ “Transparent ROP Detection using CPU Performance Counters”, Li & Crouse,
2014

BLACKHAT 2016

INTRODUCING - BRANCH PREDICTION UNIT

CPU COREPERFORMANCEMONITORING UNIT

BRANCHPREDICTION UNITINTRODUCING - BRANCH PREDICTION UNIT

BLACKHAT 2016

BRANCH PREDICTION UNIT
▸ A unit in microprocessor architectures dedicated to improving the prediction of
branch destinations to increase instruction pipeline efficiency▸ Better branch prediction can have a large effect on processor performance▸ Misprediction penalties can be many clock cycles due to flushing and filling thecorrect branch into the instruction pipeline▸ Indirect branches can be common in C++ applications and predicting them iscrucial to performance

HOLD FOR VIDEOBLACKHAT 2016

INTRODUCING - HARDWARE ASSISTANCECPU CORE

INTERRUPT 0XFEPERFORMANCEMONITORING UNIT

BRANCHPREDICTION UNITINTRODUCINGCONTROL FLOW INTEGRITYINTRODUCING - CONTROL FLOW INTEGRITYBLACKHAT 2016

CONTROL FLOW INTEGRITY▸ Enforcement of legitimate control flow in a program▸ Traditionally done with compiler generated instrumentation▸ Many different implementation of policy enforcement exist but the basic idea is
to validate each indirect control flow transfer against a static list of trusted
functions

BLACKHAT 2016

INTRODUCING - CONTROL FLOW INTEGRITYCONTROL TRANSFERDESTINATIONDESTINATIONDESTINATIONBLACKHAT 2016

INTRODUCING - CONTROL FLOW INTEGRITYCONTROL BRANCHCFI POLICY ENFORCEMENTDESTINATIONTERMINATEINTRODUCING - CONTROL FLOW INTEGRITYBLACKHAT 2016

ALTERNATIVE CFI IMPLEMENTATIONS▸ Control Flow Guard (CFG), Microsoft, 2014
▸ Control-flow Enforcement Technology (CET) , Intel, TBD?
▸ Return Address Protection/Indirect Control Transfer Protection (RAP/ICTP), PaX
Team, 2015

INTRODUCING - CONTROL FLOW INTEGRITYBLACKHAT 2016

ALTERNATIVE CFI IMPLEMENTATIONS▸ Control Flow Guard (CFG), Microsoft, 2014
▸ Control-flow Enforcement Technology (CET) , Intel, TBD?
▸ Return Address Protection/Indirect Control Transfer Protection (RAP/ICTP), PaX
Team, 2015
▸ While these are very strong implementations they require recompilation,
updated software/kernel/OS, or aren’t cross platform

INTRODUCING - PERFECTLY PLACED TRAPSBLACKHAT 2016SCOPING OUR RESEARCH TO FILL THE GAP▸ No source code access▸ Cross-Platform OS support▸ 32 and 64 bit support▸ No pre-processing of binaries or CFG reconstruction▸ Not specific to a single bug-class or exploit technique such as Use-After-Free(UAF) or Return-oriented Programming (ROP)▸ Overhead must be acceptable in benchmarks and subjective user experienceINTRODUCING - PERFECTLY PLACED TRAPSBLACKHAT 2016

REAL-WORLD VERIFICATION▸ Approach must be verified using “real” exploits and “real” software▸ Cyber Grand Challenge samples▸ Research community PoCs
▸ Metasploit modules▸ Exploit Kit samples including previous 0days▸ Internally developed exploits

CFI APPROACH

CFI APPROACH

BLACKHAT 2016

HARDWARE-ASSISTED CONTROL FLOW INTEGRITY (HA-CFI)▸ Hijacked indirect branches almost always mispredicted by BPU▸ HA-CFI Approach:▸ Use Intel PMU to trap all mispredicted indirect branches▸ Requires setting counter to -1▸ Use ISR for CFI policy: validate indirect branch destinations in real-time▸ Initial prototype in LinuxBLACKHAT 2016

CFI APPROACHOUR INITIAL APPROACH
CORE 1

CORE 2…

CORE NPERFORMANCE MONITORING UNITKERNEL

IA32_PMC0= -1
IA32_PERFEVTSEL0 = MISP INDIRECT CALLPMU
INTERRUPTSERVICE ROUTINE

IA32_PMC0= -1
IA32_PERFEVTSEL0 = MISP INDIRECT CALL…

IA32_PMC0= -1
IA32_PERFEVTSEL0 = MISP INDIRECT CALL

USER MODEDATA COLLECTION
CLIENTPMU
INTERRUPTSERVICE ROUTINE…

PMUINTERRUPTSERVICE ROUTINEPYTHON POSTPROCESSINGCFI APPROACH

BUT WONT ALL THOSE INTERRUPTS BE EXPENSIVE?

BLACKHAT 2016

BLACKHAT 2016

CFI APPROACH

INDIRECT BRANCH CFI COMPARISON
Source CodeRequired

Binary Rewriting
Compiler Transformation
PMU-Assisted

NO

YES

NO

Patching
Required
YES

NO

NO

Overhead

CFI Logic Frequency

LOW

100% FORPROTECTED CALLS

LOW

100% FORPROTECTED CALLSMEDIUM

ONLY WHENMISPREDICTED
1%-20%

BLACKHAT 2016

CFI APPROACH

PROGRAMMING THE PMU
CORE 1

CORE 2…

CORE NPERFORMANCE MONITORING UNITKERNEL

IA32_PMC0= -1
IA32_PERFEVTSEL0 = MISP INDIRECT CALLPMU
INTERRUPTSERVICE ROUTINE

IA32_PMC0= -1
IA32_PERFEVTSEL0 = MISP INDIRECT CALL…

IA32_PMC0= -1
IA32_PERFEVTSEL0 = MISP INDIRECT CALL

USER MODEDATA COLLECTION
CLIENTPMU
INTERRUPTSERVICE ROUTINE…

PMUINTERRUPTSERVICE ROUTINEPYTHON POSTPROCESSINGCFI APPROACH

BLACKHAT 2016

PROGRAMMING THE PMU▸ Controlled by several Model Specific Registers (MSRs)▸ IA32_PERF_GLOBAL_CTRL : global enable/disable of counters▸ IA32_PERFEVTSELx : event to count, mode inclusion bits, interrupt bit▸ IA32_PMCx : counter value▸ IA32_PERF_GLOBAL_STATUS / IA32_PERF_GLOBAL_OVF_CTRL▸ counter overflow status and clear registers▸ Additional references: Threads 2014 [Li et al], BH USA 2015 [Herath, Fogh]

BLACKHAT 2016

CFI APPROACH

INDIRECT BRANCH - INTEL PMU EVENTSEVENT NAME

UMASK

CODE

DESCRIPTION

BR_MISP_RETIRED.NEAR_CALL

0x02

0xC5

Direct and indirect mispredicted near call instructions retired

BR_MISP_EXEC.TAKEN_INDIRECT_NEAR_CALL

0xA0

0x89

Taken speculative and retired mispredicted indirect calls▸ BR_MISP_RETIRED (PEBS) counts retired only, includes direct and indirect▸ BR_MISP_EXEC includes speculative events == branches falsely labeled as
mispredicted▸ Opted to use BR_MISP_RETIRED.NEAR_CALL since more precise and fewer Interrupts

BLACKHAT 2016

CFI APPROACH

THE INTERRUPT SERVICE ROUTINE
CORE 1

CORE 2…

CORE NPERFORMANCE MONITORING UNITKERNEL

IA32_PMC0= -1
IA32_PERFEVTSEL0 = MISP INDIRECT CALLPMU
INTERRUPTSERVICE ROUTINE

IA32_PMC0= -1
IA32_PERFEVTSEL0 = MISP INDIRECT CALL…

IA32_PMC0= -1
IA32_PERFEVTSEL0 = MISP INDIRECT CALL

USER MODEDATA COLLECTION
CLIENTPMU
INTERRUPTSERVICE ROUTINE…

PMUINTERRUPTSERVICE ROUTINEPYTHON POSTPROCESSINGBLACKHAT 2016

CFI APPROACH

PMU TRAPS “ON PAPER”
IA32_PMC0: 0xFFFFFFFF (-1)

Event: 0x5102C5

RIP: 0xB890
-1
-1
-1

foo:
0

0x1000: MOV
0x1003: MOV
0x1007: CALL

0xB890: MOV
0xB893: MOV

rax, [rsi]rdi, [rax+0x78]
rdi

rax, rsp[rax+0x20], r9d

PMU ISR

PMI#ifdef WINDOWS
ip = KTRAP_FRAME.RIP;#else
ip = pt_regs.rip;//Apply CFI policy to RIP
do_cfi(ip);BLACKHAT 2016

CFI APPROACH

PMU TRAPS IN THE REAL WORLD
IA32_PMC0: 0xFFFFFFFF (-1)

Event: 0x5102C5

RIP: 0xB893
-1
-1
-1

0x1000: MOV
0x1003: MOV
0x1007: CALL

rax, [rsi]rdi, [rax+0x78]
rdi

PMU ISRfoo:
0
00xB890: MOV
0xB893: MOV

rax, rsp[rax+0x20], r9d

Skid = 1 Instruction
PMI?

CFI APPROACH

BLACKHAT 2016

PMU TRAPS IN THE REAL WORLD▸ Due to instruction skid after overflow, no guarantee saved IP is address ofbranch destination▸ AMD docs state skid could be up to 72 instructions▸ We found 1 instruction skid (or none) to be most common on Intel▸ Need a more precise way to get branch target address on PMU overflow

CFI APPROACH

BLACKHAT 2016

LBR TO THE RESCUE▸ Intel Last Branch Record (LBR) can provide us precise branch addresses▸ Configured and accessed via MSRs:▸ IA32_DEBUGCTL : Enable/Disable bit, Freeze on PMI bit▸ LBR_SELECT : filter types of branches▸ LASTBRANCH_x_FROM_IP / LASTBRANCH_x_TO_IP : LBR stack entries▸ LBR_TOS : Offset that points to current top of LBR stackCFI APPROACH

LBR TO THE RESCUELBR_SELECT = 0x1ED ( Indirect Calls in ring > 0 )easy first check in ISRBLACKHAT 2016

BLACKHAT 2016

CFI APPROACH

PMU TRAPS WITH LBR PRECISION
IA32_PMC0: 0xFFFFFFFF (-1)

-1
-1
-1

foo:
0
0

0x1000: MOV
0x1003: MOV
0x1007: CALL

RIP: 0xB893

Event: 0x5102C5

rax, [rsi]rdi, [rax+0x78]
rdi

TOS

LBR FROMLBR TO

0x59BC5CE5

0x75DFC3FB

0x12340x10000x8000000000001007

0xB8900x59BC61C3

0x75DFC452

PMU ISR
0xB890: MOV
0xB893: MOV

rax, rsp[rax+0x20], r9d
PMI//Get LBR TO
tos = rdmsr(LBR_TOS);
lbr_to = rdmsr(LBR_TO + tos)//Apply CFI policy to LBR to
do_cfi(lbr_to);BLACKHAT 2016

CFI APPROACH

COLLECTING ALL THE DATACORE 1

CORE 2…

CORE NPERFORMANCE MONITORING UNITKERNEL

IA32_PMC0= -1
IA32_PERFEVTSEL0 = MISP INDIRECT CALLPMU
INTERRUPTSERVICE ROUTINE

IA32_PMC0= -1
IA32_PERFEVTSEL0 = MISP INDIRECT CALL…

IA32_PMC0= -1
IA32_PERFEVTSEL0 = MISP INDIRECT CALL

USER MODEDATA COLLECTION
CLIENTPMU
INTERRUPTSERVICE ROUTINE…

PMUINTERRUPTSERVICE ROUTINELAST BRANCH RECORDPYTHON POSTPROCESSINGBLACKHAT 2016

CFI APPROACH

VALIDATING APPROACH W/ CYBER GRAND CHALLENGE SAMPLES
vrp@ubuntu:~$ miniperf -p 8491 -i 1 -e 0x51a089
Monitoring process: CROMU_00044 (8491)
80007F51FCF6DDBD 7F51FCF9D5F080007F51FCF9F62B 7F51FCF9E570
80007F51FCF9E734 7F51FCF9E7C080007F51FCF9E4D9 7F51FCF9CFC080007F51FCF9E69D 7F51FCF9D5D080007F51FCF6DDBD 7F51FCF9D5F080007F51FCF9F62B 7F51FCF9E570
80007F51FCF9E734 7F51FCF9E7C0…
80007F51FCF9D69E 7F51FCF9E7C080007F51FCF9E4D9 7F51FCF9CFC080000000004032B2 41414141

403294:403299:40329d:4032a1:
4032a4:4032a8:4032ab:4032af:4032b2:

callq
mov
mov
mov
add
mov
mov
mov
callq

<_ZN10CUserEntry20GetLastUnreadMessageEv>%rax,-0x30(%rbp)-0x30(%rbp),%rax(%rax),%rax$0x10,%rax(%rax),%rax-0x30(%rbp),%rdx%rdx,%rdi*%rax// Display last unread message
pCur = pUser->GetLastUnreadMessage();printf( "From: @s\n", pCur->GetFrom().c_str() );BLACKHAT 2016

CFI APPROACH

INDIRECT BRANCH ANALYSIS - CVE-2014-0556
ACTIONSCRIPT TRIGGER▸▸▸

Ubuntu 14.04.3 LTS x64
Pepper Flash 14.0.0.177

HIJACKED CALL SITE

ByteArray.readBytes()

0x33D438:

jmp rax

ByteArray.readBytes()

0x33D3BC:

call qword ptr [rax]ByteArray.readMultiByte()

0x33D1D6:

call qword ptr [rax]ByteArray.readMultiByte()

0x33D343:

call qword ptr [rax+0x10]

ByteArray.readMultiByte()

0x33D1A7:

call qword ptr [rax+0x10]

ByteArray.readMultiByte()

0x405358:

call qword ptr [rax+0x8]

Tweaked ActionScript
POC from Chris Evans togenerate additional data:

ByteArray.writeBytes()

0x33D4A8:

jmp rax

ByteArray.writeBytes()

0x33D0E7:

call qword ptr [rax+0x10]

ByteArray.writeMultiByte()

0x33CFFB:

call qword ptr [rax+0x10]

ByteArray.writeMultiByte()

0x40805A:

call qword ptr [rcx]16 unique hijack
points

ByteArray.writeUTF()

0x33CE48:

call qword ptr [rax]ByteArray.writeUTFBytes()

0x33D0B8:

call qword ptr [rax]ByteArray.writeObject()

0x33D05E:

call qword ptr [rax+0x10]

ByteArray.writeObject()

0x40477A:

jmp rax

ByteArray.readObject()

0x33CDCE:

call qword ptr [rax+0x10]

ByteArray.readObject()

0x40482B:

jmp rax

Moved to real-world
Linux x64 POC, but
missed hijack due to JMP▸▸

Call / JMP Analysis

BLACKHAT 2016

CFI APPROACH

INDIRECT BRANCH - CALL VS JMP
CALL

27%

x64

73%
jscript9.dll

2%

JMP

13%
87%

98%
Flash.ocx

x64

libpepflashplayer.so▸ Hijackable indirect JMP slightly more common in Linux binaries▸ Indirect JMPs often used for switch statements▸ For this talk we will focus exclusively on indirect CALLs

12%88%libxul.so

BLACKHAT 2016

CFI APPROACH

WHAT IS A VALID INDIRECT BRANCH?

2%
5% 8%
Firefox20%

167,755,264
Branches collected
Dromaeo JavaScript Benchmark
dromaeo.com

66%
Non MISPJIT code page

Exports
Callbacks

Relocations

BLACKHAT 2016

CFI APPROACH

OUR FINAL DESIGNPERFORMANCE MONITORING UNIT

CORE 1

CORE 2…

CORE N

IA32_PMC0= -1
IA32_PERFEVTSEL0 = MISP INDIRECT CALL

IA32_PMC0= -1
IA32_PERFEVTSEL0 = MISP INDIRECT CALL…

IA32_PMC0= -1
IA32_PERFEVTSEL0 = MISP INDIRECT CALLKERNELPMU
INTERRUPTSERVICE ROUTINEPMUINTERRUPTSERVICE ROUTINE

WHITELISTOF VALID BRANCHTARGETS…

PMU
INTERRUPTSERVICE ROUTINE
hacfi.sys / hacfi.ko

CFI APPROACH

BLACKHAT 2016

WHITELIST GENERATION▸ Only after we were able to validate all 160M branches from ELF did we even
explore real-time whitelist query▸ Generate list on each image load in protected processes▸ Overall approach is same on ELF and PE:▸ Find all code pointer addresses present in loaded image▸ Code pointer considered if relative or absolute address points to .text▸ Primarily focus on Exports, Relocations, and “Callbacks”

IMPLEMENTATIONCHALLENGESIMPLEMENTATION CHALLENGESKEY CHALLENGES▸ Receiving PMU Interrupts▸ Clearing PMU Interrupts▸ Thread Tracking

BLACKHAT 2016

IMPLEMENTATION CHALLENGESBLACKHAT 2016

RECEIVING PMU INTERRUPTS ON WINDOWS▸ Modifying the Interrupt Descriptor Table (IDT) for the PMU interrupt will notwork for x64 due to PatchGuard▸ While investigating how Windows handles PMI, we discovered a non-exported
kernel routine in hal.dll▸ HalpSetSystemInformation()▸ InformationClass of HalProfileSourceInterruptHandler▸ Reachable through HalDispatchTable export

IMPLEMENTATION CHALLENGESBLACKHAT 2016

RECEIVING PMU INTERRUPTS ON WINDOWSNT_STATUS _HalpSetSystemInformation(HAL_SET_INFORMATION_CLASS InformationClass, ULONG BufferSize,PVOID *Buffer) {// ...
if(InformationClass == HalProfileSourceInterruptHandler) {if(BufferSize != 4)
return STATUS_INFO_LENGTH_MISMATCH;
if(HalpFeatureBits & 1 == 0)
return STATUS_INVALID_DEVICE_REQUEST;
if(ProfilingProcessId == 0) {_HalpPerfInterruptHandler = Buffer[0];if(Buffer[0] != NULL)
ProfilingProcessId = PsGetCurrentProcessId();} else {if(PsGetCurrentProcessId() != ProfilingProcessId)
return STATUS_INVALID_DEVICE_REQUEST;_HalpPerfInterruptHandler = Buffer[0];ProfilingProcessId = (Buffer[0] ? ProfilingProcessId : 0);}}

return STATUS_SUCCESS;// ...

IMPLEMENTATION CHALLENGESBLACKHAT 2016

RECEIVING PMU INTERRUPTS ON WINDOWS▸ Pass in the interrupt handler function and it will be called when a PMI occurs
NTSTATUS status;
PVOID buffer[1];buffer[0] = profileSourceInterruptHandler;
status = HalpSetSystemInformation(HalProfileSourceInterruptHandler,
sizeof(PVOID),
buffer);▸ Calling (from the same process) with a NULL pointer deregisters the handler
NTSTATUS status;
PVOID buffer[1];buffer[0] = NULL;
status = HalpSetSystemInformation(HalProfileSourceInterruptHandler,
sizeof(PVOID),
buffer);IMPLEMENTATION CHALLENGESBLACKHAT 2016

CLEARING PMU INTERRUPTS ON WINDOWS▸ Another issue encountered involved unmasking PMU interrupts from thehandler▸ PMU interrupts are delivered by the APIC
▸ In order to acknowledge an interrupt has been handled and to receive futureinterrupts, a register in the APIC needs to be written▸ How this is accomplished depends on the APIC interface used, which differs
between Windows versions

BLACKHAT 2016

IMPLEMENTATION CHALLENGES

CLEARING PMU INTERRUPTS ON WINDOWS
xAPIC

x2APIC▸ Existed since Pentium 4▸ Introduced in Nehalem microarch▸ Windows 7▸ Windows 8/8.1▸ APIC Registers are accessed throughmapped physical memory▸ APIC Registers are accessed via MSRs

▸ Register access accomplished using
physical memory mapped into kernel
virtual memory via MmMapIoSpace▸ Interface can be accessed with asingle __writemsr intrinsic__writemsr(LVT_x2APIC_PMI, 0xFE)

IMPLEMENTATION CHALLENGES

RECEIVING PMU INTERRUPTS ON LINUX▸ Setting this up on Linux is even simpler▸ Register for a Non-Maskable Interrupt (NMI) handler
register_nmi_handler(NMI_LOCAL,
our_nmi_handler,
NMI_FLAG_FIRST,“hacfi_pmi");unregister_nmi_handler(NMI_LOCAL, "hacfi_pmi");BLACKHAT 2016

IMPLEMENTATION CHALLENGESBLACKHAT 2016

THREAD TRACKING▸ We don’t want to monitor the entire system▸ Monitoring can be restricted to a few “high threat” executables▸ The PMU doesn’t know anything about thread or process context

IMPLEMENTATION CHALLENGESBLACKHAT 2016

THREAD TRACKING ON WINDOWS▸ Not so straightforward▸ Windows has no (explicit) mechanism for executing arbitrary code at thread
context switches▸ Without some sort of callback when a thread quantum starts execution, we
don’t know when to turn on the PMU counters▸ This is a problem

IMPLEMENTATION CHALLENGESBLACKHAT 2016

ASYNCHRONOUS PROCEDURE CALLS TO THE RESCUE▸ “When an APC is queued to a thread, the system issues a software interrupt.
The next time the thread is scheduled, it will run the APC function.” - Microsoft▸ Perfect! We could just use APCs to get callbacks, and re-queue a new onwhenever we finish the previous▸ Not quite that simple, since we don’t track all threads and don’w know when amonitored quantum has ended▸ Also, scheduling an APC for the current thread, from an APC handler, leads toan endless APC loop due to the software interrupt

IMPLEMENTATION CHALLENGESBLACKHAT 2016

OUR APC SOLUTION
1. Schedule a kernel APC for every thread we want to track
2. Configure PMU to trap all mispredicted branches
3. When we see an interrupt for the wrong thread, schedule a new APC for theprevious thread on the processor (or all tracked threads that don’t have one
currently queued)
4. Repeat

BLACKHAT 2016

IMPLEMENTATION CHALLENGESOUR APC SOLUTION
APC'

APC'

APC'

Context'Switch'
Detected'

Interrupts'

CALC.EXE'IEXPLORE.EXE'

CALC.EXE' IEXPLORE.EXE'

CALC.EXE'

FIREFOX.EXE'

Time'
Disable'PMU'

Enable'PMU'

Disable'PMU' Enable'PMU' Disable'PMU'

Enable'PMU'

IMPLEMENTATION CHALLENGESBLACKHAT 2016

THREAD TRACKING ON LINUX▸ Very straightforward▸ preempt_notifier_init gives us a simple callback registration for when a thread ispreempted
static struct preempt_notifier notifier;static struct preempt_ops hacfi_preempt_ops = {.sched_in = hacfi_notifier_sched_in,.sched_out = hacfi_notifier_sched_out};
static void hacfi_notifier_sched_in(struct preempt_notifier *notifier, int cpu);
static void hacfi_notifier_sched_out(struct preempt_notifier *notifier,struct task_struct *next);
preempt_notifier_init(&notifier, &hacfi_preempt_ops);

RESULTS

RESULTSANALYSIS OF RESULTS▸ Performance Overhead▸ Exploit Detection efficacy testing

BLACKHAT 2016

RESULTSBLACKHAT 2016

PERFORMANCE▸ We expect there to be a lot of mispredicted branches leading to excessiveinterrupts▸ There is also a minor fixed overhead for each quantum from the APC▸ We need to test and see if this is feasible…

BLACKHAT 2016

RESULTS

HOW MANY PMU INTERRUPTS ARE WE TALKING ABOUT?
MISPREDICTED INDIRECT CALLS DURING OCTANE

13,557,147

14,678,764
8,058,444

SANDY BRIDGEIVY BRIDGE

HASWELLBLACKHAT 2016

RESULTSPERFORMANCE OVERHEAD
Benchmark

PassMark PerformanceTest

Dromaeo JavaScript
w/ Internet Explorer

Baseline

HA-CFI

EMET

score: 940

9%score: 855

3%score: 910

325 runs/s

22%
253 runs/s

32%
220 runs/s*TESTING PERFORMED ON AN INTEL HASWELL CPU

RESULTSBLACKHAT 2016

EXPLOIT DETECTION TESTING▸ We needed exploits to test….
▸ We wanted exploits of recent CVEs for Adobe Flash, Internet Explorer, andMicrosoft Office▸ To Metasploit!

BLACKHAT 2016

RESULTSEXPLOIT DETECTION TESTING - METASPLOIT
VULNERABILITYTARGET

DETECTION RATE

CVE-2014-0497

Flash Player 11.7.700.202

100%

CVE-2014-0515

Flash Player 11.7.700.275

100%

CVE-2014-0556

Flash Player 14.0.0.145

100%

CVE-2014-0569

Flash Player 15.0.0.167

100%

CVE-2014-8440

Flash Player 15.0.0.189

100%

CVE-2015-0311

Flash Player 16.0.0.235

100%

CVE-2015-0313

Flash Player 16.0.0.296

100%

CVE-2015-0359

Flash Player 17.0.0.134

100%

CVE-2015-3090

Flash Player 17.0.0.169

90%

CVE-2015-3105

Flash Player 17.0.0.188

100%

CVE-2015-3113

Flash Player 18.0.0.160

100%

CVE-2015-5119

Flash Player 15.0.0.189

100%

CVE-2015-5122

Flash Player 18.0.0.194

100%

CVE-2014-1761

Microsoft Word 2010100%

RESULTSBLACKHAT 2016

EXPLOIT DETECTION TESTING▸ Metasploit results were great, but what about the bad guys?
▸ The techniques used in an exploit matter as much or more than the actual
vulnerability itself▸ We don’t think Metasploit is a great testbed for HA-CFI, due to lack of diversity
in exploitation approach▸ So we turned to VirusTotal and Exploit Kit samples collected in the wild

BLACKHAT 2016

RESULTSEXPLOIT DETECTION TESTING - VIRUSTOTAL▸ VirusTotal enabled us to test on real-world malware including previously 0day exploits▸ Decided that samples from some of the more popular exploit kits would be a goodbasis for testing▸ Using actual exploits from ‘the wild’ should provide a good sample of exploitation
techniques▸ We chose 48 unique samples for our testbed

7

Exploit Kits

48

Samples20

Unique CVEs

RESULTSBLACKHAT 2016

EXPLOIT DETECTION TESTING - VIRUSTOTAL▸ We analyzed each sample and bucketed them into three separate categories
according to exploitation technique▸ ROP Technique - Uses standard Return Oriented Programming techniques▸ ROPless Technique A - Flash exploitation technique invoking a wrapper routineof VirtualProtect to make shellcode executable▸ ROPless Technique B - Similar to A, but via hijacking Method.apply() inActionScript to find and invoke VirtualProtect directly (Vitaly Toropov)

BLACKHAT 2016

RESULTSEXPLOIT KIT DETECTION - HA-CFI VS EMETCODE EXECUTIONTECHNIQUE# SAMPLES

HA-CFI
DETECTION RATEEMET
DETECTION RATE

ROP

37

95%

100%

ROPless
Technique A

1

100%

0%

ROPless
Technique B

10

100%

0%

BLACKHAT 2016

RESULTSEXPLOIT KIT DETECTION - BY BUG CLASSBUG CLASS# CVE’S# SAMPLES

HA-CFI
DETECTION RATE

Out-of-bounds Write

3

6

83.3%

Buffer Overflow

3

6

83.3%

Integer Overflow

2

6

100%

Use-After-Free

4

14

100%

Double Free

2

4

100%

Type Confusion

3

6

100%

Race Condition

1

4

100%

Uninitialized Memory

1

1

100%

CASE STUDIESBLACKHAT 2016

CASE STUDIES

CLASSIC ROP TECHNIQUE▸ CVE-2015-2419 : Double-free in jscript9 (MS15-065)▸ Magnitude EK Sample

HA-CFI blocks the initial hijack.
RIP in ISR = jscript9 + 3BE32

jscript9 + A7541 ; JavascriptOperators::OP_SetElementIcall edi
jscript9 + 3BE32
xchg eax,esp ; stack pivot gadget
retn
jscript9 + 4B0B5
mov [ecx+0xC],ax
retn; CoE help

jscript9 + 3BE33
retnkernel32 + 42C15
VirtualProtectStub
StackPivot detected on VirtualProtect; mark shellcode +X

HA-CFICASE STUDIESBLACKHAT 2016

ROPLESS TECHNIQUE #1▸ CVE-2014-0515 : Heap overflow in Adobe Flash (patch in 13.0.0.206)▸ Found in many Exploit kits and watering hole attacks▸ ROPless technique re-uses VirtualProtect wrapper function in Flash image▸ 2 control flow hijacks: one to VP wrapper, second one to shellcode▸ Bypasses anti-ROP checks since VP invoked somewhat legitimately

BLACKHAT 2016

CASE STUDIESROPLESS TECHNIQUE #1▸ CVE-2014-0515 : Heap overflow in Adobe Flash (patch in 13.0.0.206)
FileReference.cancel()Flash32_12_0_0_77 + 25783D
call dword ptr [eax+0x14]

HA-CFI detects and blocks the initial hijack.
IP at time of interrupt = Flash32_12_0_0_77 + 3BD636
Flash32_12_0_0_77 + 3BD636
push 1
push dword ptr [eax-8]
push dword ptr [eax-4]
call virtual_protect_wrapper
add esp,0xC
retn

This branch is also mispredicted
FileReference.cancel()
Shellcode

HA-CFIFUTURE WORKBLACKHAT 2016

FUTURE WORK
▸ Hypervisor support to enable hardware features in virtual machines▸ Last Branch Record (LBR) is not fully supported in popular hypervisors▸ Performance Monitoring Interrupts (PMI) on overflow is supported in many
hypervisors▸ We wrote a patch for Xen to enable HA-CFI but it crashes randomly, anyone
want to help?
▸ Just-In-Time code pages are hard to validate with our current whitelist approach

CONCLUSION

CONCLUSIONBLACKHAT 2016

EXPLOIT DEFENSE▸ Exploit defense needs to detect and prevent exploitation at the earliest phase▸ Compile-time solutions are powerful, but there is room for run-time defense
too▸ Defenses focused exclusively on techniques such as Return-oriented
Programming can be easily circumvented as new methods get adopted▸ Exploits will continue to “look normal” to bypass prevention checks

CONCLUSIONBLACKHAT 2016

HARDWARE ASSISTED CONTROL FLOW INTEGRITY▸ CFI is a powerful first step in ensuring only trusted code paths can be executed▸ Many vulnerabilities must hijack control-flow to achieve code execution▸ Hardware can be leveraged for strong CFI policy enforcement of applications
at run-time▸ Many new hardware features are emerging that can be used for exploit
defenseCONCLUSIONBLACKHAT 2016

CFI ENFORCEMENT▸ CFI policies can be more complex▸ Powerful features of the PMU interrupt on branches for prevention are the high
IRQL and complete access to context information▸ We have more ideas in the works to detect additional events and apply policies
to detect abnormal read, writes, and cases where attackers stay within ourwhitelist

CONCLUSIONSPECIAL THANKS▸ Aaron Lamb, Endgame▸ Gabriel Landau, Endgame▸ Andrea Limbago, Endgame▸ Kafeine, malware.dontneedcoffee.com▸ Fellow researchers and vendors working on exploit defense

BLACKHAT 2016

QUESTIONS?