Location
Room 220, New Computer Science
Event Description

Title: Memory corruption mitigation via software hardening and bug-finding

Abstract:
Despite decades of research, memory corruption vulnerabilities continue to be at
the forefront of today's security threats. There are two main avenues for
automating defenses against these vulnerabilities: (a) develop automated
analysis/testing techniques to find these bugs, or (b) develop software
transformations that block their exploitation, or at least make them more
difficult (hardening). This dissertation explores both of these avenues.

The thesis begins with a general model of memory corruption attacks and a
systematic analysis of previous hardening techniques. We identified two
subcategories of exploit prevention approaches where significant advances were
possible, and developed new and practical solutions in each category. The first
among these was a hardening technique for Windows binaries to enforce
control-flow integrity (CFI) with excellent performance. We then turned our
attention from hardening to prevention: we developed a novel solution called
Code Pointer Integrity (CPI) that guarantees the protection of all code pointers
in a program, thereby making control-flow hijacks impossible. Some elements of
this solution have already been adopted into the popular LLVM compiler.

The second part of the dissertation focuses on automated techniques for finding
memory corruption bugs. Fuzzing and symbolic execution are the two main
approaches currently being used for bug finding. Both approaches are aimed at
generating inputs that can crash a program. Fuzzing is the approach of choice
for practitioners, since it is simple to use, and scales to large programs. Its
main drawback is its lack of direction, which makes it very hard to reach "deep"
bugs that require passing many conditional branches. It is in this regard that
symbolic execution excels: by employing SAT and SMT constraint solvers, these
techniques can generate inputs that can reach program points guarded by many
conditionals. Unfortunately, symbolic execution is slow, and moreover, is
difficult to apply because it requires faithful modeling of a program's
environment, such as the operating system. We introduce a new technique that
combines the benefits of these approaches, while avoiding their main weaknesses.
In particular, we make fuzzing much more directional. Our directional
technique achieves much more coverage than competing fuzzers and symbolic
execution tools, and is able to find more bugs in a shorter period of time.

Event Title
PhD Defense: Laszlo Szekeres