1 / 22

Securing Programs by Continuous Address Space Randomization

Securing Programs by Continuous Address Space Randomization. Tugrul Ince tugrul@cs.umd.edu PD Week ’13. Code Layout. Software and hardware have evolved to run programs fast Optimizing compilers Complex code transformations Inlining Packed code layout

sammy
Download Presentation

Securing Programs by Continuous Address Space Randomization

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Securing Programs by Continuous Address Space Randomization TugrulInce tugrul@cs.umd.edu PD Week ’13

  2. Code Layout • Software and hardware have evolved to run programs fast • Optimizing compilers • Complex code transformations • Inlining • Packed code layout • Execution environments are very strict • Every piece of code occupies a predetermined location • Each module has a fixed address at runtime • Hard to modify executables

  3. Problems with Code Layout • Intrusion attacks benefit from strict program layouts • Attackers guess locations of critical functions • Function locations are constant for non-PIE executables • Relative distances between functions are constant even in shared libraries • Current randomization techniques only change the base address • Very sensitive to information leakage

  4. A Typical Function Call … void currentFunc() { … foo(arg1, …, argN); … } void foo(int arg1, …, int argN) { char buffer[64]; scanf(“%s”, buffer); … return; } int system(char* cmd) { // run cmd } Current Func. arg1 … argN Saved RIP Saved RBP buffer foo

  5. Return-Programming Attack … void currentFunc() { … foo(arg1, …, argN); … } void foo(int arg1, …, int argN) { char buffer[64]; scanf(“%s”, buffer); … return; } int system(char* cmd) { // run cmd } Current Func. arg1 … … &buffer argN … Saved RIP &system() Saved RBP … buffer Malicious command foo

  6. Return-Programming Attack … void currentFunc() { … foo(arg1, …, argN); … } void foo(int arg1, …, int argN) { char buffer[64]; scanf(“%s”, buffer); … return; } int system(char* cmd) { // run cmd } Current Func. arg1 … I need to guess the location of system() and where return address is stored … &buffer argN … Saved RIP &system() Saved RBP … buffer Malicious command foo

  7. Preventing Attacks • Address Space Layout Randomization (ASLR) • Conventional approach • Rebase executable files (including shared libraries) • ASLR has many limitations • One randomization constant for the whole executable • If attacker learns one address in the executable, s/he knows the full map • Randomization constant fixed during execution • Allows multiple tries (brute-force) • No randomization for child processes • Attackers might have unlimited identical processes to attack

  8. Entropy with ASLR • ASLR promises high entropy • 40-bits of entropy on patched kernels • Actual entropy is much less • All executables are loaded at addresses that start with 0x00007f---------- • Executables are loaded very close to each other • Least-significant 12-bit-offset of a function address is constant 12-16 bits 0 0 0 0 7 F B C 3 A X 1 2 12-16 bits of entropy … … Executable A 0x00007fxxxy------ 0x00007fxxxy---123 64-bit Address Space 0x00007f---------- 0x00007f---------- Executable B 0x00007fxxxz------ 0x00007fxxxz---456 … … similar offset

  9. NINJA System Overview • NINJA: No Intrusion by Jumping Around • Rewrite executableswith completely relocatable functions • Link with a first-party runtime relocator Executable Relocatable Executable execution foo foo' Binary Rewriter Relocator

  10. Completely Relocatable Functions • Position independent code (PIC) • Dependent on location after initial relocation of executable • Relative addressing • Remove dependencies to location • Instruction-pointer based addressing • Calls with • absolute addresses • relative addressing • Table-based branches

  11. Editing the Executable • Instruction-pointer based addressing • Updating offsets is impractical • Why not use a constant instead of the instruction-pointer? • No need to update the offset Target Offset mov 0x0, 0x100(%rip) ??? Instruction Instruction

  12. Editing the Executable • Our constant: initial location of the function • Store this value on stack • All IP-based addresses are updated to use this new value and a modified offset • (IP + Offset) = (<Initial Function Location> + Offset’) • mov 0x0, 0x100(%rip) mov 0x0, 0x80(%r15) • Shared Libraries • This constant initially depends on the instruction-pointer • During first relocation, it is replaced with a real constant • No modification of code for relocation after the first one

  13. Editing the Executable • Function Table • Calls go through this table • Updated at runtime • Table-based branches • Table contains only offsets • Add instruction-pointer to offsets to determine target Initial Location Current Location Execution Count Active Call Count Size jmp *rax Block 1 Block 2 Block 3 Block 4

  14. Editing the Executable • Accessing parameters on stack • Need to update offsets to rsp / rbp … PrevFunc. Frame Parameter Return Addr. Stack Ptr. Prev. Frame Ptr. Initial Func. Loc. • Add call to Relocator at function exit

  15. Runtime Relocation Strategy • Relocate individual functions • Randomly after a given time interval (R) • After they execute N times • How to pick a reasonable N? • N = 1 : relocate after every function execution • High overhead • N = 10,000 : infrequent relocation • Adaptive Strategy: Pick Nwith respect to execution frequency • Profiling data • High N for functions that execute often • Low N for functions that execute rarely

  16. Experimental Evaluation • Linux (Ubuntu 11.04) • Maximum 28-bits of entropy • Measurements • Overhead using benchmarks from SPEC CPU 2006 • Time for successful attack using a modified version of Apache HTTP Server

  17. Runtime Performance

  18. Attacks on NINJA • ASLR with PIE: Attacks take an average of 4.9 hours • Range: 16 seconds to more than 14 hours • NINJA: low probability of successful attack • Probability of a successful attack in itries is given by:

  19. Probability of Successful Attack 20 25 210 215 220 225 230 235 240

  20. Successful Attack Probability in 24 hrs Probability of Successful Attack (log scale) 1 8 16 24 Elapsed Time (hours)

  21. Runtime Overhead with Relocation

  22. Conclusion • Strict layout of code makes programs vulnerable • Process functions to be completely relocatable • Relocate functions at runtime • After Nth execution • Periodically at timed intervals • Attackers cannot identify function locations on time to attack

More Related