enforcing un unique code target property for control flow
play

Enforcing Un Unique Code Target Property for Control-Flow Integrity - PowerPoint PPT Presentation

Enforcing Un Unique Code Target Property for Control-Flow Integrity Ho Hong Hu Hu, Chenxiong Qian, Carter Yagmann, Simon Pak Ho Chung, William R. Harris , Taesoo Kim, Wenke Lee * 1 Control-flow attack Control-flow: the order of


  1. Enforcing Un Unique Code Target Property for Control-Flow Integrity Ho Hong Hu Hu, Chenxiong Qian, Carter Yagmann, Simon Pak Ho Chung, William R. Harris ∗ , Taesoo Kim, Wenke Lee * 1

  2. Control-flow attack • Control-flow: the order of instruction execution • Attackers use bugs to divert control flow • indirect control-flow transfer (ICT): • call *%rax, jmp *%rax, ret • func_ptr/ret_addr ==> &shellcode/&ROP_gadgets • the most common exploit method 2

  3. Control-flow attack is getting harder • Control-flow integrity (CFI) Defenses De • Statically build control-flow graph (CFG) CCFIR • Dynamically check with CFG · · · binCFI · · · MCFI check · · · piCFI · · · TypeArmor · · · PittyPat · · · static CFG run-time 3

  4. Control-flow attack is still possible Defenses De Atta ttacks • Advanced attacks bypassing CFI • Out-of-control (oakland’14), CCFIR • COOP (oakland’15), · · · Out-of-control binCFI · · · • Control-flow bending (usenix’15), · · · Stitch-gadgets • Code jujutsu (ccs’15) MCFI · · · • |allowed flow| ≫ |real valid flow| · · · COOP piCFI · · · • The end of the story? · · · CF bending TypeArmor · · · • |allowed flow| = 1 · · · Control Jujutsu <=> ∀ ICT, |allowed target| = 1 PittyPat · · · · · · ? 4

  5. Our solution – uCFI • Enforce unique code target property • only one valid target is allowed at runtime • Efficient enforcement • 8% on SPEC CPU 2006 • 4% on nginx • 1% on vsftpd 5

  6. Example: control-flow attack 5,6, 7,8 1 typedef void (*FP)(); 2 void A(); void B(); void C(); void D(); void E(); 3 10 9 4 void handleRequest(int id, char * input) { 5 FP arr[3] = {&A, &B, &C}; 11 6 FP unused = &D; 7 FP fun = NULL; 12 14 8 char buf[20]; 9 if (id < 0 || id > 2) 15 10 return; system 11 if (id == 0) strcpy 12 fun = arr[0]; mprotect 13 else 16 exec 14 fun = arr[id]; 15 strcpy(buf, input); fun fun setuid 16 (*fun)(); unknown before run 17 } 17 6

  7. Example: control-flow integrity • Identify valid target set S S for each ICT • For a run-time target t : : t ∊ S S ? continue: abort • Larger | S | => more attack Method S (id = 1) | S | no CFI * ∞ 5 FP arr[3] = {&A, &B, &C}; 6 FP unused = &D; Type-based CFI A, B, C, D, E 5 7 FP fun = NULL; Static CFI A, B, C 3 9 if (id < 0 || id > 2) 10 return; piCFI A, B, C, D 4 11 if (id == 0) 12 fun = arr[0]; PittyPat B, C 2 13 else 14 fun = arr[id]; uCFI B 1 16 (*fun)(); 7

  8. Unique code target property • UCT property: 5 FP arr[3] = {&A, &B, &C}; • for each invocation of an ICT, 7 FP fun = NULL; 8 char buf[20]; • on one and on only on one allowed target 9 if (id < 0 || id > 2) 10 return; 11 if (id == 0) • Enforcement: 12 fun = arr[0]; 13 else • collect necessary runtime info to 14 fun = arr[id]; 15 strcpy(buf, input); infer the unique target 16 (*fun)(); • PittyPat [1] uses the same methodology, • but fa fails to enforce UCT property 8

  9. Challenges with Intel PT • Intel PT only delivers control-data 5 FP arr[3] = {&A, &B, &C}; • TNT: branch taken / non-taken 7 FP fun = NULL; • TIP: ICT target 8 char buf[20]; 9 if (id < 0 || id > 2) • C1: unique target 10 return; 11 if (id == 0) • line 14: id = 1 or 2 ? | S | = 2 12 fun = arr[0]; 13 else • | S | = 479 for gobmk 14 fun = arr[id]; 15 strcpy(buf, input); • C2: efficient analysis 16 (*fun)(); • path reconstruction from PT trace is slow! • 30x slow down for sjeng (based on our simple implementation) • 9

  10. uCFI – enforce unique target • Encode non-control data in some ICT fun = arr[id]; strcpy(buf, input); (*fun)(); 10

  11. uCFI – enforce unique target • Encode non-control data in some ICT fun = arr[id]; ret FP new_ptr = BASE_PTR + id; ret TIP assert(inBound(new_ptr)); ret (*new_ptr)(); ret strcpy(buf, input); … (*fun)(); 11

  12. uCFI – enforce unique target • Encode non-control data in some ICT fun = arr[id]; int read_data() { ret FP new_ptr = BASE_PTR + id; int packet = getPTPacket(); ret TIP assert(inBound(new_ptr)); int id = packet – BASE_PTR; ret (*new_ptr)(); return id; ret strcpy(buf, input); } … (*fun)(); • Restore non-control data in monitor process 12

  13. uCFI – enforce unique target • Encode non-control data in some ICT fun = arr[id]; int read_data() { ret FP new_ptr = BASE_PTR + id; int packet = getPTPacket(); ret TIP write_data(id); assert(inBound(new_ptr)); int id = packet – BASE_PTR; ret (*new_ptr)(); return id; ret strcpy(buf, input); } … (*fun)(); • Restore non-control data in monitor process • write_data(x): • log arbitrary non-control-data into PT trace • enable analysis for unique target • current setting: 4M ret instrs ==> [-1024, 4M-1024] 13

  14. Which data is necessary? Constraining data: non-control-data affecting control-flow 1. Control-data : (similar to CPI [5] ) • a code pointer / a pointer of a known control-data • recursive data-flow analysis 2. Control-instruction : • Instructions operating on control-data 3. Constraining-data : • non-control data used in control-instructions • like, array index, condition in cmov 14

  15. uCFI – perform efficient analysis path reconstruction from PT trace is slow! • Avoid (most) path reconstruction write_data(ID1); FP arr[3] = {&A, &B, &C}; write_data(ID2); FP fun = NULL; char buf[20]; if (id < 0 || id > 2) return; if (id == 0) { write_data(ID3); fun = arr[0]; } else { write_data(ID4); fun = arr[id]; } strcpy(buf, input); write_data(ID5); (*fun)(); 15

  16. uCFI – perform efficient analysis path reconstruction from PT trace is slow! • Avoid (most) path reconstruction write_data(ID1); FP arr[3] = {&A, &B, &C}; • assign an ID to each control-instruction write_data(ID2); • write_data(ID) into PT trace FP fun = NULL; char buf[20]; if (id < 0 || id > 2) return; if (id == 0) { write_data(ID3); fun = arr[0]; } else { write_data(ID4); fun = arr[id]; } strcpy(buf, input); write_data(ID5); (*fun)(); 16

  17. uCFI – perform efficient analysis path reconstruction from PT trace is slow! • Avoid (most) path reconstruction write_data(ID1); FP arr[3] = {&A, &B, &C}; • assign an ID to each control-instruction write_data(ID2); • write_data(ID) into PT trace FP fun = NULL; char buf[20]; • Ignore all TNT packets if (id < 0 || id > 2) return; • Analysis if (id == 0) { write_data(ID3); while(ID = decode_data()) fun = arr[0]; switch(ID) } else { case ID1: pts[arr+0] = A; pts[arr+1] = B; write_data(ID4); pts[arr+2] = C; break; case ID2: pts[fun] = NULL; break; fun = arr[id]; case ID3: pts[fun] = pts[arr+0]; break; } case ID4: id = decode_data(); strcpy(buf, input); pts[fun] = pts[arr+id]; break; write_data(ID5); case ID5: if(pts[fun] != PT_packet) (*fun)(); abort(); 17

  18. uCFI – perform efficient analysis path reconstruction from PT trace is slow! • Avoid (most) path reconstruction write_data(ID1); FP arr[3] = {&A, &B, &C}; • assign an ID to each control-instruction write_data(ID2); basic block w/ some control-instrs • write_data(ID) into PT trace FP fun = NULL; char buf[20]; • Ignore all TNT packets if (id < 0 || id > 2) return; efficien ef ently • Analysis if (id == 0) { write_data(ID3); while(ID = decode_data()) fun = arr[0]; switch(ID) } else { case ID1: pts[arr+0] = A; pts[arr+1] = B; write_data(ID4); pts[arr+2] = C; break; case ID2: pts[fun] = NULL; break; fun = arr[id]; case ID3: pts[fun] = pts[arr+0]; break; } case ID4: id = decode_data(); strcpy(buf, input); pts[fun] = pts[arr+id]; break; write_data(ID5); case ID5: if(pts[fun] != PT_packet) (*fun)(); abort(); 18

  19. uCFI overview • uCFI compiler uCFI compiler • identify constraining data constraining constraining basic block data detector data encoder ID encoder source • encode constraining data code • encode basic block ID exeutable LLVM IR ID2BB uCFI monitor points-to update analyzor query execution points-to BBID table process trace decoder user space kernel PT driver space PT CPU Intel PT trace 19

  20. uCFI overview • uCFI monitor uCFI compiler • decode basic block ID constraining constraining basic block data detector data encoder ID encoder source • decode constraining data code • perform points-to analysis exeutable LLVM IR ID2BB • perform CFI check uCFI monitor • sy sync with execution on critical system calls points-to update analyzor query execution points-to BBID table process trace decoder user space kernel PT driver space PT CPU Intel PT trace 20

  21. Implementation • x86_64 system • uCFI compiler (1,652 SLOC) – based on LLVM 3.6 • uCFI monitor (4,310 SLOC) • PT driver – based on Griffin [2] code • IP filtering • 1 return instruction • 1 indirect call instruction 21

  22. Evaluation – set up • Benchmark • SPEC CPU 2006 (-O2) • nginx & vsftpd (default compilation script) • Environment: • 8-core Intel i7-7740X CPU (4.30GHz), 32GB RAM • 64-bit Ubuntu 16.04 system 22

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend