Presentation is loading. Please wait.

Presentation is loading. Please wait.

Continuous, Low Overhead, Run-Time Validation of Program Executions

Similar presentations


Presentation on theme: "Continuous, Low Overhead, Run-Time Validation of Program Executions"— Presentation transcript:

1 Continuous, Low Overhead, Run-Time Validation of Program Executions
Paper by Erdem Aktas, Furat Afram, Kanad Ghose of State University of New York Presentation by Alec Lofquist Security is important, right When I say security, I mean making sure only programs you want to run can run, and that bugs in the program can’t be exploited to take control of the system

2 Outline Common vulnerabilities Existing work What is REV
Experimental Assessment of REV Limitations of REV

3 Code Injection Attacks
An attacker somehow gets their own program into memory and moves control flow to it Direct code injection Binary is overwritten by another process Indirect code injection Binary overwritten or “added to” using a vulnerability in the program The classic example is a buffer overflow exploit Code injection attacks can be protected from pretty well with features like the NX bit Allows programmers/the OS to specify memory as not-executable (typically done with the stack) Most programs don’t need memory that is both executable and writeable JITs are the notable exception

4 Code-reuse Attacks Return-oriented programming (ROP)
Find existing functions in the binary (that end with a return) that do something useful just before returning (this is called a “gadget”) If we could compose the right gadgets, we could “write” any program… We can do this without execute permissions by manipulating the call stack Overwrite the return address of many stack frames with a chain of gadget addresses Control will jump to the first gadget in the list, perform the function, then return, then jump to the second gadget on the stack, and so on Also jump-oriented programming, return-to-libc, overwriting vtables Jump-oriented programming - Like ROP, but with indirect jumps instead of ret instructions Return-to-libc - Sort of like ROP, but using libc functions instead of gadgets Overwriting vtables

5 How can we protect against these exploits?
Static program certification before execution Useless for protecting against zero-day vulnerabilities Run-time validation Validating the executed instructions (code injection attacks) Validating program control flow (ROP/JOP/vtable/return-to-libc attacks) Zero-day vulnerability – vulnerability unknown to the vendor in a program that has already been shipped Static certification is common because it’s easy to implement (even in software) NX bit is also used to protect from code injection attacks

6 Problems with Existing Designs
Too slow to be practical Do not play well with OoO CPU designs Program size limitations Require modifications to binaries Require source code access Not continuous - only validate at checkpoints The paper discusses nearly a dozen related works, listing reasons why the authors find them unsatisfying A lot of these target embedded systems (first 3) Modifications to binaries – use modified ISA Require source code access – could be to recompile for new ISA, could be to generate signatures Validating at checkpoints can be defeated if the attacker cleans up after themselves

7 REV Design Goals Be general enough to detect any kind of compromise to code and control flow. Be scalable for arbitrarily large programs. Have a low performance overhead. Be transparent to executables Changes must be validated before being committed. Support speculative execution. General – detect both code injection and code reuse attacks Scalable – many existing implementations keep reference signatures in CPU internal tables, which might work for small embedded programs but doesn’t scale for large binary sizes Also support cross-module calls 3. Existing implementations are often too slow to be useable, have very high penalties for context switches 4. Existing implementations require modifying the binary in some way with some sort of ISA change, and these changes often require source code level access. 5. We don’t want to allow changes to the permanent state of the system without first validating the change. This is a stumbling block for some HW and pretty much all software CFI implementations which only validate at certain checkpoints. 6. Allow aborting/rolling back

8 How REV Works Pipelined Crypto Hash Generator (CHG) calculates hashes of basic blocks on the fly as instructions are fetched Compare calculated hashes to reference hashes before commit If they don’t match, raise an exception When committing control-flow modifying instructions (branch/call/jump/ret), validate that the control that flowed into the BB along an expected path Compare computed target address with stored target addresses CHG has from instruction fetch to commit to calculate the hash

9 Reference Signatures Stored encrypted in main memory in a hash table (Signature Table) Contains crypto hash for BB, successor/predecessor addresses The CPU is informed of tables by special limit register/base address reg pairs Generated with static analysis or profiling Accessed through a Signature Cache (SC) to improve performance The limit registers are how multiple modules are supported There is a hardware limit on the number of limit/base reg pairs

10 REV Diagram CHG – pipelined, responsible for hashing basic block by commit SC – cache for recent signatures, goes through the normal processor memory stages on miss (L1/L2 caches) SAG – generates main memory address of signature table entry based on base address registers, retrieves it Match -> return entry No match -> iterate through “Next entry” linked list pointers, then generate exception SAG also holds limit registers/base pointers for signature tables!

11 Signature Cache Entry

12 Signature Table (RAM) Encrypted in RAM, decrypted on the fly in the CPU Extra tags are used to distinguish between blocks with matching crypto hash values (extremely unlikely, ended up unique in experiments) Size ranges from 15-52% of binary size with an average of around 37%

13 Overhead Dynamic power overhead at 3GHz is estimated at 7.2% the power consumption of the base core design “With a shared L3 cache and the I/O pad power added in, the overall power overhead added by the REV logic to a multicore chip is reduced from 7.2% to less than 5.5%.” Area overhead is about 8% of base Performance overhead is 1.87% on average across all SPEC CPU benchmarks. Evaluated through simulation using the cycle-accurate MARSS Models a modern x86-64 OoO CPU with L1/L2 caches An additional L1 data cache port was assumed for use by the SC Area/power could be even lower if crypto logic is shared with the CPU Control flow locality has a strong impact on program performance (SC misses)

14 IPC for SPEC CPU 2006

15 IPC Overhead for SPEC CPU 2006
Gobmk – AI for the game Go

16 REV Limitations Self-modifying code (e.g. JIT-compiled code)
Only use last 4 bytes of hashes Limited number of simultaneous modules Control flow validation during exceptions? Is generating control flow signatures difficult? Self modifying code 1. Generate references on the slow (“significant overhead”) 2. Disable REV for JITed code (give up) It may be possible to alter a BB such that the last 4 bytes still match

17 Thank You Questions?


Download ppt "Continuous, Low Overhead, Run-Time Validation of Program Executions"

Similar presentations


Ads by Google