Branch Regulation: Low-Overhead Protection from Code Reuse Attacks Mehmet Kayaalp, Meltem Ozsoy, Nael Abu-Ghazaleh and Dmitry Ponomarev Department of Computer Science State University of New York at Binghamton Presented at the 39 th International Symposium on Computer Architecture (ISCA), June 11 th 2012
Attack Classification from NIST Database *2009 – 2010 CVE Records (Vulnerability level 8 – 10) ISCA %
Buffer Overflow and Code Injection Attack: Example main (int argc, char **argv) {... vulnerable(argv[1]);... } vulnerable(char *str1) { char str2[100]; strcpy(str2,str1); return; } 0x0000 0xFFFF Stack growth Stack frame for main() Stack frame for vulnerable() return address str2 malicious input (str2) xor ecx, ecx mul ecx lea ebx, [esp+8] mov al, 11 int 0x80 malicious return ISCA 20123
Existing Protection from Code Injection Attacks: No Execute Bit (NX) 0x0000 0xFFFF WRITABLE NOT EXECUTABLE xor ecx, ecx mul ecx lea ebx, [esp+8] mov al, 11 int 0x80 malicious return Mark memory pages as –Either WRITABLE –Or EXECUTABLE –But not both Standard technique in current processors and operating systems –Intel XD bit –AMD XN bit –Windows DEP –Linux PaX ISCA Stack growth
Next Frontier: Code Reuse Attacks (CRAs) Key Idea: Reuse existing library code instead of code injection CRA timeline –Return-into-libc attack (1997) –Return Oriented Programming (2007) –Jump Oriented Programming (2010) All bypass NX ISCA 20125
Return Oriented Programming (ROP) 0x0000 0xFFFF Stack growth Stack frame for main() Stack frame for vulnerable() xor ecx, ecx mul ecx lea ebx, [esp+8] mov al, 11 int 0x80 malicious return xor ecx, ecx ret lea ebx, [esp+8] ret mov al, 11 int 0x80 mul ecx ret ISCA Page marked as EXECUTABLE
Protecting Against ROP: Secure Call Stack Semantics of return instruction – ret expects an address pushed by a call Keep a copy of return addresses in a separate memory space –Secured by OS/Hardware On each return: –Compare two copies of the return addresses –Generate exception if they mismatch Citations to these works are in the paper ISCA 20127
Example of a Secure Call Stack main (int argc, char **argv) {... vulnerable(argv[1]);... } vulnerable(char *str1) { char str2[100]; strcpy(str2,str1); return; } 0x0000 0xFFFF Stack growth Stack frame for main() Stack frame for vulnerable() return address str2 malicious input return addressmalicious return ≠ ISCA 20128
Defeating Secure Call Stacks Initiating an attack –Overwrite a function pointer, –Overwrite a longjmp buffer, –Exploit a format string vulnerability Performing an attack –Use indirect jumps instead of returns Jump Oriented Programming Need a special gadget to orchestrate control ISCA 20129
Jump Oriented Programming 0x0000 0xFFFF Stack growth Stack frame for main() Stack frame for vulnerable() xor ecx, ecx mul ecx lea ebx, [esp+8] mov al, 11 int 0x80 malicious return pop edi jmp edi lea ebx, [esp+8] jmp esi mov al, 11 int 0x80 mul ecx jmp esi xor ecx, ecx jmp esi popa jmp esi ISCA Page marked as EXECUTABLE Dispatcher Gadget
Defending Against JOP Attacks Use solutions preventing buffer overflows –Bounds Checking –Information Flow Tracking Can ensure the legitimacy of jump targets at runtime –Difficult to do Need to construct a Control Flow Graph –Control Flow Integrity (CFI) Abadi et al, USENIX Security 2005 ISCA
Control Flow Integrity Generate Control Flow Graph –Unique labels for edges Instrument the code with checks –Each indirect branch checks target for a label... cmp [ecx], h jne error_label lea ecx, [ecx+4] jmp ecx... mov eax, [esp+4]... jmp ecx... mov eax, [esp+4]... SourceDestination CFI instrumentation ISCA Added instructions
CFI Limitations Need to construct Control Flow Graph –No publicly available tools for constructing CFG from binaries Need access to source code Runtime performance overhead due to extra instructions –About 20% for SPEC 2K6 Benchmarks Problems with dynamic linking Does not handle unintended instructions ISCA
Where Do Jump Targets Go? Typical use of indirect jump instruction –To efficiently implement switch-case statements Target is in the same function –To support dynamic linking Target is a function entry point Key Observation: Legitimate jump targets ARE NOT in the middle of another function ISCA
Our Proposal: Branch Regulation Enforce the following rules: –Returns go to the correct addresses –Jumps target same functions or function entry points –Calls target function entry points Use hardware checks for enforcement –Low performance overhead (around 2%) –Unintended instructions are handled –No CFG needed –Requires minimal binary annotations Security shown for common libraries ISCA
How Does BR Mitigate JOP Attacks? 0x0000 0xFFFF Stack growth Stack frame for main() Stack frame for vulnerable() xor ecx, ecx mul ecx lea ebx, [esp+8] mov al, 11 int 0x80 malicious return pop edi jmp edi lea ebx, [esp+8] jmp esi mov al, 11 int 0x80 mul ecx jmp esi xor ecx, ecx jmp esi popa jmp esi function1() function2() NOT ALLOWED ISCA
Implementing Branch Regulation Use a Secure Call Stack Annotate function entry points with function size info Compare jump targets with function bounds and allow if checks pass Store bounds in secure call stack Cache a few secure stack entries for performance ISCA
Inserting Code Annotations ISCA e4 : 80483e4: push ebp 80483e5: mov ebp, esp f9: mov eax, fe: leave 80483ff: ret g F.text 005a __libc_csu_init e4 g F.text 001c main b8 g F.init 0000 _init d2 : 80483d2: 80483e4: push ebp 80483e5: mov ebp, esp f9: mov eax, fe: leave 80483ff: ret Original Code Annotated Code Symbol Table
Executing Call Instruction calleax : call eax bc: 0x be: push esp 80482C0: … : jmp ecx : ret. FetchDecodeExecute Commit Instruction Cache call eax … | … | … Base | Bound | Return … | … | … BR Check Function Bounds Stack bc 0098 (function size) 80482bc | | ISCA
Executing Jump Instruction jmpecx. 0x : call eax. 0x80482BC: 0x98 0x80482BE: push esp 0x80482C0: …. 0x : jmp ecx. 0x : ret. FetchDecodeExecute Commit Instruction Cache jmp ecx … | … | … Base | Bound | Return … | … | … BR Check Function Bounds Stack 0x80483AA 0x80482BC | 0x | 0x x80482BC > 0x > ISCA
Executing Return Instruction ret. 0x : call eax. 0x80482BC: 0x98 0x80482BE: push esp 0x80482C0: …. 0x : jmp ecx. 0x : ret. FetchDecodeExecute Commit Instruction Cache ret … | … | … Base | Bound | Return … | … | … BR Check Function Bounds Stack 0x x80482BC | 0x | 0x x = Return Address from Stack ISCA
Security of Branch Regulation Effectively reduces the exploitable code base to the current function An attacker needs to find in same function: –A vulnerability to exploit –Sufficient functional gadgets –Dispatcher gadget –A system call instruction ISCA
Number of Vulnerable Functions Library libc libm libcrypto libgcrypt libssl ISCA Functions with Dispatcher Gadget and System Call Functions with Dispatcher Gadget Total Number of Functions
Additional Security Analysis in the Paper Analysis of available gadgets Dispatcher gadget discovery algorithms Gadget trie example Analysis of gadget side effects –Gadget length –Impact of unintended gadgets ISCA
Increase of Executable Size ISCA
Impact of Secure Stack Cache Size ISCA
BR Performance with 4-Entry Cache ISCA
Conclusions ISCA Emerging Code Reuse Attacks bypass existing defenses against code injection New low overhead solutions are needed We proposed Branch Regulation –Uses hardware checks to enforce a limited set of rules –Incurs 2% performance overhead and 1% increase in code size –Handles unintended instructions –Does not rely on Control Flow Graph of the program –Can protect legacy binaries with minimal effort We demonstrated security of Branch Regulation for a variety of common libraries
Thank you! Questions? ISCA
Backup Slides ISCA
Unintended Instructions : E8 33 FE FF FF : 8D BB 18 FF FF FF F: 8D FF FF FF : 29 C : FF 8D BB 18 FF FF E: FF 8D FF FF : FF 29 Code Snippet from __libc_csu_init function : E8 33 FE FF FF : 8D BB 18 FF FF FF F: 8D FF FF FF : 29 C7 Unintended Code Snippet from __libc_csu_init function call lea edi, [ebx-e8h] lea eax, [ebx-e8h] sub, edi, eax dec [ebp-e745h] dec [ebp-e77dh] jmp [ecx] FF 8D BB 18 FF FF FF 8D FF FF FF 29 ISCA
Dispatcher Gadgets Replacement of return for JOP attacks Advance a register/memory to represent program counter Dispatcher Gadget Potential (DGP) –If able to write to the target of indirect jump –If not, not Turing-complete Dispatcher Gadget Confirmed (DGC) –If found a potential dispatcher gadget –Still a system call is needed for harmful attack (DGC-SYS) ISCA
Identifying Dispatcher Gadgets If memory indirect branch –Find an iterator If register indirect branch –Find a loader and an iterator mov / pop etc. loads add / sub / lea / pop etc. iterates ISCA
Dispatcher Gadget Examples Instruction Type loader and iterator register indirect jump iterator memory indirect jump iterator loader register indirect jump iterator conveyor memory indirect jump Dispatcher Gadget pop r1 jmp r1 add r1, r2 jmp [r1] lea r1, [r1 + r2] mov r3, [r1] jmp r3 sub r1, 4 mov r2, [r1] mov r3, r2 jmp [r3] ISCA
Unintended Instructions Mostly garbage instructions Usually more side effects than intentional ISCA
Gadget Length Long gadget means more intermediate instructions ISCA