160 likes | 281 Views
Encoded PC: Self Protection from Buffer Overflow Attacks. Akhilesh Tyagi Depts: Elec. & Computer Engg; Computer Science Iowa State University. ATIAS Program (FRT#1). Prof. Gyung-Ho Lee Prof. Akhilesh Tyagi 2 Graduate students. Project Goals. Protection of Program Pointers:
E N D
Encoded PC: Self Protection from Buffer Overflow Attacks Akhilesh Tyagi Depts: Elec. & Computer Engg; Computer Science Iowa State University
ATIAS Program (FRT#1) Prof. Gyung-Ho Lee Prof. Akhilesh Tyagi 2 Graduate students
Project Goals • Protection of Program Pointers: (1) return address on AR (2) function pointers • Explore the role of microarchitecture and compiler. • The closest related project is StackGuard and PointGuard.
The Main Idea • Memory is a public area – open to attacks. • Any Program Counter (PC) bound value v encoded through an encoding function e(v). • Decoded d(e(v)) = v before being placed in PC.
Return Address: A valid PC bound value goes through both encoding, e, and decoding, d, functions in a PC-Memory-PC roundtrip. A compromised value only goes through the decoding function d redirecting the attack to d(A) instead of the intended address A.
Microarchitectural Version The set of actions taken on linking jumps/branches includes: MEM[$sp] e($PC); Encoding Function: e($PC) = $PC $fp;
Decoding: Instructions to pop the return address into PC can decode: jr $ra or rts $PC $ra $fp
Encoding/Decoding Key Selection • Direct protection: In order to protect an object at address A, it is not sufficient to protect the surrounding addresses: A+i and A-i for i=1,2, …, k. • Dynamically variable keys: A new value for each protected object instance.
Key characteristics continued: • Non-reproducibility: Attacker has access to identical software and hardware environment. Key = $fp random # • Register-resident keys: Most paranoid model is to assume that all memory-resident values are susceptible.
Return Address Stack • Most ILP microarchitectures include 8-16 deep stack of most recent return addresses for return address prediction. • Covers over 90% of nesting depths in practice. • It can also be used to supplement the encoding/decoding schemes.
Compiler-assisted Version • The microarchitecture actions can also be implemented in the compiler. • jal/jsr actions can go into the prologue for the procedure. • jr / rts actions go into the epilogue.
Current Project Status • Project started Nov 1, 2000. • Gcc modified to incorporate the encoding/decoding. • Linux and libraries recompiled with the PC encoding gcc. • Conceptual development for function pointer protection.
Function Pointer Protection • Similar encoding/decoding: *fp = address replaced by *fp = e(address) = address key. • Dereferencing leads to decoding: foo = *fp replaced by foo = d(*fp) = *fp key or (*fp)() replaced by ((*fp) key)(). • Microarchitecture alone does not suffice: assignment to a function pointer results in a store – compiler needs to distinguish the function pointer assignments.
Func. Pointer Protection Contd. • Key selection: many choices to satisfy the stated properties. Some combination of PID, FP address, compiler generated call path signature will work. • Where/when to encode and decode? • Compiler can attribute declarations such as (void) (*fp)() to type a subset of pointers as function pointers.
Func. Pointer Protection Contd. • Decoding instructions can be inserted at the dereferencing points for the tagged function pointers or inside the prologue of the function. • Encoding at the linking/loading time or through PC-bound static analysis for limited cases.
Conclusions • Microarchitecture offers efficiency, transparency, and a truly private encoding key. • The approach may be extensible to larger objects than the program pointer objects.