Automated Exploitation of Fully Randomized Executables by Austin James Gadient B.S. Computer Engineering United States Air Force Academy (2018) Submitted to the Department of Electrical Engineering and Computer Science in partial fulfillment of the requirements for the degree of Master of Science in Computer Science and Engineering at the MASSACHUSETTS INSTITUTE OF TECHNOLOGY February 2020 ○c Austin Gadient, 2019. All rights reserved.

The author hereby grants to MIT permission to reproduce and to distribute publicly paper and electronic copies of this thesis document in whole or in part in any medium now known or hereafter created.

Author...... Department of Electrical Engineering and Computer Science December 18, 2019 Certified by...... Martin C. Rinard Professor of Computer Science and Electrical Engineering Thesis Supervisor Accepted by ...... Leslie A. Kolodziejski Professor of Computer Science and Electrical Engineering Chair, Department Committee on Graduate Students 2 Automated Exploitation of Fully Randomized Executables by Austin James Gadient

Submitted to the Department of Electrical Engineering and Computer Science on December 18, 2019, in partial fulfillment of the requirements for the degree of Master of Science in Computer Science and Engineering

Abstract Despite significant research into their remediation, memory corruption vulnerabil- ities remain a significant issue today. Attacks created to exploit these vulnerabilities are remarkably brittle due to their dependence on the presence of specific security settings, use of certain compiler toolchains, and the target’s environment. I present Marten, a new end-to-end system for automatically discovering, exploiting, and com- bining information leakage and vulnerabilities to generate exploits that are robust against defenses, compilation decisions, and environment differences. Marten has generated four control flow hijacking exploits and three information leak- age exploits. One of the information leakage exploits is generated against a previously undiscovered zero-day vulnerability in Serveez-0.2.2. CVE-2019-16200 has been as- signed to this vulnerability. These results highlight Marten’s ability to generate robust exploits that bypass modern defenses to download and execute injected code selected by an attacker.

Thesis Supervisor: Martin C. Rinard Title: Professor of Computer Science and Electrical Engineering

3 4 Acknowledgments

Thank you to my advisor, Martin Rinard, for his expert guidance, mentorship, and leadership throughout the entirety of my research. His insight and recommendations helped me improve both the presentation and substance of this work immeasurably.

I would also like to thank Jeff Perkins, Ricardo Barato, Eli Davis, and Baltazar Ortiz for their expert knowledge and work upon which my research is built. Isaac Newton once said, "If I have seen further, it is by standing upon the shoulders of gi- ants." These men are the giants and their efforts are the shoulders upon which I stand.

Additionally, I thank my teachers, from pre-kindergarten to now, who simultane- ously drove and satiated my hunger for knowledge. Without their efforts, I would never have developed the discipline and skillset that has allowed me to succeed aca- demically at MIT. In particular, I would like to thank my mother for reading to me every night when I was young and homeschooling me for three years. I never had a teacher who cared more than her and I doubt I ever will.

Finally, I give great thanks the my father Anthony, my sisters Katharyn and Megan, and my girlfriend Dominique for their support through every difficult stage in my life. I would not be where I am today without their unconditional love.

5 6 Contents

1 Introduction 15 1.1 Background ...... 15 1.1.1 Memory Corruption Arms Race ...... 15 1.2 Marten ...... 17 1.3 Scope ...... 17 1.4 Contributions ...... 18 1.5 Structure ...... 20

2 Overview 21 2.1 Defenses ...... 21 2.1.1 ASLR ...... 21 2.1.2 NX ...... 22 2.1.3 Full RELRO ...... 22 2.1.4 Fortify Source ...... 23 2.2 Threat Model ...... 23 2.3 Marten ...... 24 2.4 Instrumentation ...... 24 2.5 Vulnerability Discovery ...... 24 2.6 Information Leakage Exploit ...... 25 2.7 Exploit Generation ...... 25

3 Example 27 3.1 Dnsmasq ...... 27

7 3.1.1 Trace Generation and Analysis ...... 27 3.1.2 Vulnerability Discovery ...... 28 3.1.3 Information Leakage ...... 29 3.1.4 Vulnerability Discovery ...... 30 3.1.5 ROP Chain Generation ...... 30 3.2 Final Exploit ...... 32

4 Program Instrumentation 33 4.0.1 Logging Execution Traces ...... 33 4.0.2 Trace Analyzer ...... 34

5 Vulnerability Discovery 37 5.1 Vulnerability Discovery Algorithm ...... 37 5.2 Success Functions ...... 39 5.2.1 Overflow ...... 39 5.2.2 Information Leak ...... 39 5.3 Path Explosion and Symbolic Execution ...... 40

6 Information Leakage 43 6.1 Information Discovery Algorithm ...... 43 6.2 Information Leakage Verification ...... 45 6.3 Information Identification ...... 45 6.4 GDB Scripting ...... 46

7 Exploit Generation 49 7.1 ROP Chain Generation ...... 50 7.2 Stack Offset Calculation ...... 52 7.3 Exploit Finalization ...... 52 7.4 Chain Size ...... 53 7.5 Exploit Reliability ...... 54

8 8 Results 55 8.1 Dnsmasq-2.77 ...... 56 8.2 Nginx-1.4.0 and OpenSSL-1.0.1 ...... 56 8.3 Asterisk-11.1.2 and OpenSSL-1.0.1 ...... 59 8.4 Serveez-0.0.20 ...... 61

9 Related work 65

10 Conclusion 71

9 10 List of Figures

2-1 The overall workflow of Marten. The diagram is split between program instrumentation and trace generation (pink), analysis that generates different portions of the final exploit (blue), and the final exploit’s direct interaction with the remote process (green). Section numbers for each component are given in parenthesis...... 22

3-3 Statistics of ROP chains generated for each target system’s 64-bit libc library ...... 31

6-1 Disassembly when setting breakpoint in outpacket.c at line 84 for Dnsmasq-2.77 ...... 46

8-2 CVE-2013-2028: Stack Buffer Overflow in Nginx ...... 58 8-3 CVE-2013-2685 Asterisk Buffer Overflow Vulnerability . . . . . 60 8-4 CVE-2019-16200 Serveez Information Leak Vulnerability ...... 61 8-5 Bugtraq ID 42560: Serveez Buffer Overflow Vulnerability . . . . 62

11 12 List of Tables

8.1 Results for benchmark applications. Marten generates working exploits for seven vulnerabilities and chains them together to create exploits that bypass full randomization and other defenses...... 55

13 14 Chapter 1

Introduction

Memory corruption vulnerabilities have been a common target of control-flow hijacking attacks for decades [20, 31, 39, 21]. Attackers inject code into a running process, or reuse code that already exists, to subvert the system. Address Space Layout Randomization (ASLR) has proven to be an effective defense against these attacks [36]. While it is possible to apply ASLR to only some parts of the process, modern systems such as Ubuntu 18.04 apply full ASLR to all code and data in a process. This thesis addresses full ASLR.

1.1 Background

This section provides brief summaries that describe the history of memory cor- ruption vulnerabilities. It gives useful context for the design decisions made in this thesis.

1.1.1 Memory Corruption Arms Race

Memory corruption exploits have existed for decades. One notable paper on these attacks was introduced in 1996 with Aleph One’s influential work on stack buffer overflows [20]. This technical description made the art of program exploitation main- stream and provided a base from which offensive and defense techniques grew. The

15 paper by Aleph One focused on stack buffer overflows and their exploitation inthe absence of defenses. The goal of these attacks is to write past the end of a stack buffer and corrupt a return pointer which can be set to arbitrarily execute codewith the same permissions as the process in which the code runs. This type of attack was effective in targeting server programs and allowed attackers to inject code and subvert critical systems.

The popularity of stack buffer overflow attacks motivated the development ofone important defense, non-executable memory (NX) [7]. NX takes advantage of the fact that some values in a process’s address space represent code, while some represent data. The code that needs to execute is typically mapped into its own location such as the .text section in executable and linkable format (ELF) binaries [16]. NX made it so that the code inside of a process could be executed but not written, and the data could be written but not executed. Thus, a simple xor operation was applied to executable memory and writable memory. This defense prevented attackers from simply injecting their own code, often referred to as because of its tendency to spawn a shell, into a process.

In response to this defense, attackers developed the return-to-libc attack [40]. This attack worked by using code that was already present in the process to launch attacker selected commands. This method was realized by calling library functions such as execve with specially selected parameters. Another similar attack, return oriented programming (ROP), was also developed [32]. This attack used small sequences of instructions, often referred to as gadgets, that occurred before return instructions. It was shown that given a sufficiently large body of x86 code, a Turing complete setof operations could be performed using the gadgets [32].

To defend against code reuse attacks like return-to-libc and ROP, ASLR was de- veloped [36]. ASLR works by randomizing the location of code within a process’s address space. The central idea is that if an attacker cannot find the code they want to reuse, then their exploits will fail. The combination of ASLR and NX is extremely effective in preventing exploits, but they are not insurmountable. If an attacker can trigger an information leak to gain knowledge about the layout of a target process’s

16 address space. With information leaks, code reuse attacks are once again viable [31].

1.2 Marten

I present Marten, a novel end-to-end automated exploitation system which gen- erates robust control-flow hijacking exploits that bypass full ASLR. A key capability of Marten is its ability to automatically find and exploit information leakage vul- nerabilities to exfiltrate information about the layout of the address space ofthe target process. This information enables Marten to then generate payloads that suc- cessfully exploit buffer overflow vulnerabilities by overwriting code pointers (such as return pointers) to point to selected code sequences in the randomized process. My current Marten implementation generates robust ROP chains that enable arbitrary command/code execution even in the presence of full ASLR. These exploits work against fully stripped binaries compiled in different environments and running on different varieties of Linux. To the best of my knowledge, Marten is 1) the first system to automatically find and exploit buffer overread vulnerabilities to derandomize reusable code (i.e., find the addresses of the code in the randomized address space) and 2) the first system to automatically generate control-flow hijacking exploits that download and execute code of the attacker’s choice into processes protected with full ASLR.

1.3 Scope

Marten targets open-source software for which source and benign inputs are avail- able. Starting with the benign inputs, Marten automatically deploys a vulnerability discovery algorithm that works with an instrumented version of the application to identify target sites and craft inputs that expose buffer overread and buffer overflow vulnerabilities. Marten is designed to exploit processes running on remote servers, accessing these processes via their network interfaces. I emphasize that even though Marten works

17 with an instrumented version of the application to discover the vulnerabilities, it generates exploits that work on stripped binary versions of the source code compiled by others and running on remote servers. Upon discovering a buffer overread vulnerability, Marten crafts an input that causes the target process to send regions of its address space back without crashing the target process. Marten then examines the returned data to derandomize addresses (such as the location of standard libraries like libc) within the target process. Marten leverages this address space layout information to synthesize short ROP chains that achieve the desired goal of the attacker. My current implementation, for example, synthesizes ROP chains that download and run a program of the attacker’s choice from a remote server. These ROP chains are designed to be short enough to fit into a single TCP packet and contain padding that makes them robust against environment differences. To execute the ROP chain, Marten automatically discovers a buffer overflow vul- nerability and generates payloads that use this vulnerability to inject the ROP chain into the running process and exploit it. Once given the source code and benign inputs, Marten is fully automatic — it generates the exploit with no human interven- tion. I emphasize that the exploits it generates are effective against stripped binaries compiled on different systems than my testing environment. The exploits generated by Marten bypass more defenses than just full ASLR. In fact, the use of information leakage gives me enough ROP gadgets that I can bypass three other widely deployed defenses: NX, Full RELRO, and Fortify Source. I discuss these defenses in greater detail in Section 2.

1.4 Contributions

This thesis makes the following contributions:

∙ Marten: It presents Marten, a novel end-to-end system that automatically targets information leakage and buffer overflow exploits to generate exploits that bypass full ASLR, NX, full RELRO, and Fortify Source. Marten generates these

18 exploits automatically with no human intervention to exploit remote, stripped binaries compiled and run in different environments.

∙ Information Leakage: It presents a new algorithm and approach to automate the exploitation of information leakage vulnerabilities, with the information used to derandomize attacker reusable code in remote processes. This approach is built on a mature program instrumentation system that combines taint anal- ysis and targeted symbolic execution to enable Marten to generate inputs that exfiltrate derandomization information without crashing the target process.

∙ Chain Generation: It presents an end-to-end ROP chain generation approach that leverages the availability of derandomized libraries to produce short, effec- tive ROP chains that fit into a single TCP packet and contain enough padding to make the chains effective across different environments.

∙ Example: It presents an example using Marten to exploit vulnerabilities in Dnsmasq-2.77. The example highlights the overall workflow of Marten asa system when generating an exploit.

∙ Results: It presents results for the exploits generated against four processes spanning five code bases. These codebases are Dnsmasq-2.77, Asterisk-11.1.2, Nginx-1.4.0, Openssl-1.0.1, and Serveez-0.2.2. I apply Marten to exploit seven unique vulnerabilities. One of the information leak vulnerabilities is a previ- ously undiscovered zero-day in Serveez-0.2.2. For all four processes, Marten automatically generates exploits that bypass full ASLR, NX, full RELRO, and Fortify Source. My exploits are initially generated and tested on Ubuntu. I also test exploits that target stripped binaries compiled on Debian and Red Hat to verify their robustness across different environments. The results highlight Marten’s ability to combine buffer overreads and buffer overflows to generate payloads that successfully exploit processes protected with full ASLR (as well as a range of other modern defenses) and its generalizability across different server applications.

19 1.5 Structure

The remainder of the thesis is structured as follows. In Section 2, I provide an overview of Marten, discuss the defenses it circumvents, and provide a threat model. In Section 3, I provide an example of how my system works when exploiting vulnerabil- ities in Dnsmasq-2.77. Section 4 presents a technical analysis of the instrumentation I place on target programs. Section 5 presents my approach to vulnerability discov- ery in detail. In Section 6 I present my novel approach to automatically generating information leakage exploits. In Section 7, I present Marten’s final exploit generation component and ROP chain generation algorithms. Section 8 presents the overall re- sults of Marten’s exploits across five different code bases. Section 9 discusses related work. Section 10 concludes the thesis.

20 Chapter 2

Overview

I discuss challenges incumbent with automatically generating robust exploits that bypass full ASLR, NX and other defenses present on modern systems. I present an overview of Marten and how it bypasses these defenses as well as a threat model discussing the assumptions and requirements of my system.

2.1 Defenses

Marten is able to automatically generate exploits that bypass a number of modern defenses. Each of these defenses is described in detail.

2.1.1 ASLR

Address Space Layout Randomization (ASLR) [36] randomizes the virtual addresses of a process’s memory pages with the goal of eliminating the attacker’s ability to locate code in the address space for code reuse attacks like ROP [32]. Originally, ASLR did not apply to the text section of an executable [33]. Today, systems randomize the location of all code and data, including information located in the text section of the executable. Programs with full randomization are said to be Position Independent Executables (PIE) [26] on Linux systems. Marten uses information leakage exploits to bypasses this defense.

21 Trace Generation Analysis Exploitation

Final Exploit Remote Server Malicious Input Vulnerability Discovery (5) Information Leak Exploit Remote Process Leaked Data Sinks Vulnerability Triggering Input Leaked Data Program Source (Input) Information Leakage (6) Information Extractor Trace Instrumented App (4) Trace Analyzer (4.2) Process-Specific Data

Process-Specific ROP Chain Benign Inputs Sinks Exploit Generation (7) General ROP Chain (Input) Vulnerability Triggering Input Buffer Overflow Exploit Vulnerability Discovery (5)

Figure 2-1: The overall workflow of Marten. The diagram is split between program instrumentation and trace generation (pink), analysis that generates different portions of the final exploit (blue), and the final exploit’s direct interaction with the remote process (green). Section numbers for each component are given in parenthesis.

2.1.2 NX

The non-executable bit (NX) [7] makes it impossible for memory that is initially mapped into a process (such as the stack and heap) to be both executable and writable. Thus, it requires an attacker to reuse code already present in the process to develop an exploit, rather than injecting their own code. Marten handles this defense by using ROP [32]. Note that NX does not prevent an application from mapping in a writable and executable page at runtime. Thus, Marten can use ROP to map in a page as writable and executable and read shellcode into this page. This mechanism allows for code execution without being constrained to the gadgets present in a binary or library.

2.1.3 Full RELRO

Relocation Read-Only (RELRO) [25] protects an executable by rearranging where certain data sections are located to prevent overflows into function pointers. Fur- thermore, full RELRO makes the Global Offset Table (GOT), a location that is full

22 of function pointers to library functions, read only. Thus, an attacker cannot hijack the function pointers located here to take control of code execution. Additionally, an attacker cannot partially overwrite these function pointers to access code located nearby. This technique is commonly used to obtain missing gadgets or bypass par- tial ASLR. None of Marten’s generated ROP payloads attempt to overwrite GOT addresses, allowing it to bypass this protection.

2.1.4 Fortify Source

Fortify Source [27] places extra checks in certain dangerous libraries to ensure they do not result in an overflow. For example, Fortify Source will check at compile time that calls to memcpy of a fixed size do not overflow the destination buffer. Itisoften difficult for the compiler to reason about whether a function is being used unsafelyat compile time. This challenge is made especially difficult when the size of a memory transfer is decided by data received at runtime in another function. The exploits generated by Marten in Section 3 all work against binaries compiled with this defense in place.

2.2 Threat Model

I assume that full ASLR, Full RELRO, Fortify Source, and NX are all enabled in the target application. The attacker must have access to the source code of the target application. Also, the attacker must be able to generate seed inputs that Marten can use as a starting point for exploring paths in the target program. While Marten can generate exploits for a single buffer overread or buffer overflow vulnerability individ- ually, both must be present in the target application to synthesize an exploit that bypasses the assumed defenses. Finally, Marten leaks the address of at least one code section in the target process (i.e., a linked library). Marten must have access to the binary or library whose address is leaked to properly construct ROP chains derived from the code in that file.

23 2.3 Marten

Figure 2-1 presents the overall workflow of Marten. First, Marten runs initial anal- ysis and vulnerability discovery to find an overread error. It then generates a finely tuned input file which provides Marten with an information leakage exploit. Marten then generates a ROP payload for the target application based on data gained from the information leakage exploit. Marten reruns the vulnerability discovery algorithm to find a stack buffer overflow. Once this overflow is found, my ROP payloadisfit into my vulnerability triggering input using the Z3 SMT solver [6]. This final exploit payload is sent to the target application and used to verify that the exploit works.

2.4 Instrumentation

During vulnerability discovery and exploit generation, Marten works with an in- strumented version of the application compiled locally. This instrumentation can provide Marten with full symbolic expressions, in terms of program constants and input bytes, for all values computed by the program. To make the collection of these expressions tractable, Marten only computes these expressions for bytes used in sinks, i.e., potential target locations within the program. Examples of these target locations include calls to memcpy and recv where the length or pointer parameters are tainted, i.e., influenced by the input. The instrumentation is implemented as an augmented version of LLVM’s Dataflow Sanitizer (DFSAN) [15]. The instrumentation supports logging information about operations performed on tainted data as it flows through the program. This log provides a trace of the program’s execution after it has received my input. I implement a trace analyzer which operates on these logs to derive the symbolic expressions.

2.5 Vulnerability Discovery

Marten uses a goal directed branch enforcement algorithm to find vulnerabilities [34]. Marten iterates through the sinks identified in the initial analysis and tries to

24 expose a vulnerability for each one. To find a vulnerability, Marten adds constraints one at a time until it triggers the bug or the solver fails to generate an input file based on the constraints. The main goal of vulnerability discovery is to generate an operation that either writes outside of the destination buffer (an overflow), or reads outside of the source buffer (an overread). Additionally, vulnerability discovery ensures data leaked in an overread reaches an output function that is accessible by the attacker, like a socket send. This objective is also achieved using a goal directed branch enforcement algorithm which ensures constraints are satisfied between the execution of the overread and the output function [34]. When looking for a sink to exploit, Marten iterates through the sinks identified in the initial analysis to tryto generate a vulnerability for each one.

2.6 Information Leakage Exploit

The information leakage exploit spills process RAM and reveals the randomized location of code pages. Marten parses the output of the program and identifies the target information it is trying to leak, in my current implementation the base address of libc. To avoid rerandomization associated with restarting the process, Marten generates information leakage exploits that avoid memory corruption, specifically by ensuring that the destination buffer is large enough to hold the leaked data.

2.7 Exploit Generation

The final payload exploits a buffer overflow. To create this payload, Marten automatically finds the vulnerability and generates a ROP payload that meets the constraints of the target application so that the vulnerable target site can be reached. Marten supports the generation of multiple types of chains, each designed to bypass modern defenses. The first type of chain I implement, the execve chain, executes an execve syscall on a command or bash script supplied by the attacker. This script allows the attacker to execute arbitrary commands on the target system. The next

25 chain type, the shellcode chain, uses the mmap syscall to map in a page that is both writable and executable. Then, it reads in code specified by the attacker to this page and executes it. One challenge is ensuring the ROP payload is small enough to fit within a single TCP packet and can successfully navigate through the control flow of the program to reach the target. Marten therefore formulates a set of SMT constraints that capture the properties that the input must satisfy, then uses an SMT solver to solve the constraints and deliver the final attack input.

26 Chapter 3

Example

I present an example to highlight the process Marten goes through to automati- cally generate exploits.

3.1 Dnsmasq

CVE-2017-14494: CVE-2017-14494 is an information leak vulnerability caused by a buffer overread. It is triggered when a malformed DHCPv6 forwarding packet is sent to the target which causes private information to be copied into a buffer. This information is then sent back to the attacker, leaking data to the attacker.

3.1.1 Trace Generation and Analysis

Marten compiles Dnsmasq-2.77 with my custom instrumentation. It sends a be- nign DHCPv6 forwarding packet (a provided benign seed input) to the instrumented version of Dnsmasq, which creates a trace file that contains information about opera- tions performed on tainted data. Marten analyzes the trace file to discover vulnerable points in the program’s execution. Examples of vulnerable points include calls to memory transfer functions (memcpy, memmove, recv) where the size of the transfer is influenced by the attacker. In this example Marten finds one potentially vulnerable point. Marten uses the information in the trace file to derive symbolic expressions

27 for relevant function parameters such as the length passed to the memory transfer function. Each symbolic expression captures the complete computation that gener- ated the corresponding value as a function of the input bytes and program constants. Marten also generates any constraints placed on each of the input bytes by branches that occur in Dnsmasq.

3.1.2 Vulnerability Discovery

Marten iterates over all of the target locations determined by the trace analyzer. Figure 3-1 presents the symbolic expressions for the values of parameters to the call to memcpy on line 6 of Figure 3-1 (I present the expressions in Z3 syntax [6]). The symbolic expressions show why the memcpy is vulnerable. The src_expr is the size of the buffer Marten is attacking when it was allocated. The src_addr is the concrete value of the source buffer’s base address. The index_expr is the pointer into the buffer used as the source for the memcpy call. Finally, the size_expr is the symbolic expression which dictates the number of bytes copied in the memcpy. The size_expr shows that the value of the size is determined by the 0x24th and 0x25th bytes in the input. There are no constraints set on these bytes by the program. There are 38 bytes between the start of the allocated buffer and the beginning of the source buffer used in the memcpy. This value is determined by the difference between the index_expr and the src_addr. With these parameters, Marten generates a symbolic equation of the following form to generate an overread:

푠푖푧푒_푒푥푝푟 > 푠푟푐_푒푥푝푟 − (푖푛푑푒푥_푒푥푝푟 − 푠푟푐_푎푑푑푟)

Marten uses Z3 [6] to solve the resulting symbolic equation to generate an overflow by setting the size_expr to a value exceeding 510. Address Sanitizer (ASAN) [30] then reports an error. Marten ensures that the data which is read out of bounds reaches an output source such as a socket send call. Marten makes this check so that it knows the data will be sent back. This method turns a buffer overread error into an information leakage vulnerability.

28 1 void *put_opt6 ( void *data, size_t len) 2 { 3 void *p ; 4 5 i f ((p = expand(len)) && data) 6 ◁ memcpy(p, data, len); 7 8 return p ; 9 } CVE-2017-14494

"src_expr": (BitVec 64) bv548 "src_addr": 94435196822144 "index_expr": (BitVec 64) bv94435196822182 "size_expr": (BitVec 16)((byte_0x24<<8)+byte_0x25) CVE-2017-14494 Symbolic Expressions

Figure 3-1: Vulnerable code and generated symbolic expressions for CVE-2017-14494

3.1.3 Information Leakage

Marten now tailors the input to leak desired information. Marten runs an unin- strumented version of the application under GDB, using an automated interface to stop execution at the memcpy shown in line 7. It then inspects the memory near the source buffer, trying to find the largest code page it can leak that is reachable bythe memcpy. It determines that there is a pointer into libc which can be leaked, giving access to a huge number of potential ROP gadgets. Marten adjusts the length of the overread such that the size is greater than the distance between the start of the memcpy and the desired information. To ensure that the resulting exploit leaves Dns- masq in an uncorrupted state, Marten also uses the symbolic expression for the length of the destination buffer to ensure that the leaked information fits in the destination buffer. In this example, Marten computes the length of the overread as0xFFFF— the length is stored in an unsigned short, with the maximum value of 0xFFFF less than the length of the destination buffer. At this point, Marten runs the application with this specially crafted input. It verifies that the desired target data is inthe output and Dnsmasq continues to execute properly. Marten now has a successful information leakage exploit.

29 1 i f ( ( opt = opt6_find ( opts , end , OPTION6_CLIENT_MAC, 3) ) ) 2 { 3 state −>mac_type = opt6_uint(opt, 0, 2); 4 state −>mac_len = opt6_len(opt) − 2 ; 5 ◁ memcpy(& state −>mac[0], opt6_ptr(opt, 2), state −>mac_len ) ; 6 } CVE-2017-14493

"dest_expr": (BitVec 64) bv16 "dest_addr": 140735078453168 "index_expr": (BitVec 64) bv140735078453168 "size_expr": (BitVec 16)((byte_0x24<<8)+byte_0x25)−2 CVE-2017-14493 Symbolic Expressions

Figure 3-2: Vulnerable code and generated symbolic expressions for CVE-2017-14493.

CVE-2017-14493 Marten next finds a buffer overflow vulnerability that enables remote code execution. Marten’s vulnerability discovery algorithm discovers CVE- 2017-14493, which is triggered when a malformed DHCPv6 packet is sent to the target that causes data to be written outside of a statically sized stack buffer.

3.1.4 Vulnerability Discovery

Line 5 of Figure 3-2 presents the vulnerable call to memcpy. The data in the source buffer and the number of bytes to copy is controlled by the attacker. Todetect this vulnerability, Marten solves a symbolic equation over the variables in Figure 3- 2. This equation takes the same form as the equation of CVE-2017-14494. Marten also ensures that it appends the proper amount of data to the malformed DHCPv6 packet such that there is enough to overflow the target buffer. These extra bytes are placeholder values that Marten replaces with a ROP chain in the next step. When the vulnerability is uncovered by a crash in Address Sanitizer (ASAN), the ROP chain generation begins [30].

3.1.5 ROP Chain Generation

The ROP chain generation takes as an input the target library whose pointer is leaked in the information leakage step. In this case, it is the version of libc used

30 Libc In Chain Type Gadget count Instruction Count Gadget Type[Number] Length (bytes) Padding (bytes) write[19], load[42] Red Hat 8.0 execve 62 138 1496 48 syscall[1] write[5], load[15] Red Hat 8.0 shellcode 22 42 544 80 syscall[1], call[1] write[19], load[42] Debian 9.9 execve 62 62 920 80 syscall[1] write[5], load[15] Debian 9.9 shellcode 22 22 422 80 syscall[1], call[1] write[19], load[42] Ubuntu 18.04 execve 62 138 1496 48 syscall[1] write[5], load[15] Ubuntu 18.04 shellcode 22 42 544 80 syscall[1], call[1]

Figure 3-3: Statistics of ROP chains generated for each target system’s 64-bit libc library

by the target application. From here, the payload generation has access to a huge number of gadgets and can quickly synthesize both shellcode and execve ROP chains. Marten minimizes the length of the ROP chain by searching for gadgets that perform the desired computation with few (three or less) extraneous instructions. In practice, targeting libc gives Marten access to a wide enough range of gadgets that Marten is able to find exact matches for each desired gadget so that the finalROP chains have few extraneous instructions. The chain generation algorithm also takes special care to pad the generated payloads with offsets into the library which point to ret instructions. This padding is the ROP equivalent of a NOP sled, which is a technique to improve the robustness of an exploit against changes to the environment [20]. Then, the payload generation appends the attack code, which is also a set of offsets pointing to short code sequences in the leaked library. Marten generates a separate ROP payload file for each version of libc (one for each version of Linux) — the offsets of the gadgets are different for each version.

Figure 3-3 presents statistics for the generated ROP chains for the target 64- bit libraries. The ROP chains contain either 62 (execve1 exploit) or 22 (shellcode exploit) gadgets. The generated chains contain four kinds of gadgets: write, load, syscall, and call depending on the action the gadget performs. The length of the ROP chains varies between 1496 and 422 bytes, with the amount of padding included in the

31 ROP chain being either 48 or 80 bytes. The padding consists of the address of a ret instruction in libc. To ensure that the chains fit within a single TCP packet, Marten generates ROP chains that are less than 1500 bytes on 64-bit systems. Figure 3-3 also includes statistics on the number and type of gadgets identified for each of the system’s libraries. The generated ROP payload is placed within the placeholder bytes appended to the malformed DHCPv6 packet in the vulnerability discovery step. From here, Marten solves any unsatisfied constraints created by replacing placeholder bytes with the ROP payload.

3.2 Final Exploit

The final exploit is a Python script that receives a target IPv6 address, apayload file for the information leak, and a payload file for the stack buffer overflow complete with relative offsets for the ROP gadgets. Marten will generate a Python script using a template that sends the information leak payload to the server and receives the leaked data. The script will search for the target pointer using the offset it saved in the information leak payload generation step and determine the base address of libc. Once the script has found this base address, it will add it to all of the relative offsets in the ROP payload to generate absolute addresses. Then, this final payload file is sent to the target process. The result is an exploit which can perform arbitrary commands on the victim system that bypass full ASLR and other modern defenses such as NX. I verified that the exploits work against Dnsmsaq-2.77 compiled on Ubuntu 18.04, Debian 9.9, and Red Hat Enterprise 8.0.

32 Chapter 4

Program Instrumentation

Marten takes the source code of an application and compiles it using an aug- mented version of Dataflow Sanitizer (DFSAN) [15]. This program is then runwith a given input and Marten traces its execution while tracking taint as the input flows through the target application. Finally, I implement a trace analyzer for the logged information which tracks input bytes and their symbolic expressions.

4.0.1 Logging Execution Traces

Our instrumentation creates log files that track information about how the pro- gram computes and uses tainted values. To support the logging capability, I create wrappers for functions of interest using Dataflow Sanitizer [15]. Each of these wrap- pers calls the function of interest and ensures it returns without an error code. If the function does complete its execution successfully, a message may be logged detailing the concrete values for the parameters of a function as well as their taint status. For example, calls to memcpy may log the following information

1. dest: destination buffer address

2. src: source buffer address

3. count: number of bytes copied

4. dest_label taint label of destination address

33 5. src_label taint label of source address

6. count taint label of count address

Marten determines whether to log information based on the function called and the taint labels of its various parameters. For example, a call to memcpy would be logged if any one of the parameters is tainted. This logging is done because any of these parameters could be adjusted to cause an overflow or overread depending on the constraints placed on them by the program. If the src or count parameters are tainted, the function call may be adjusted to cause a buffer overread. Similarly, if the dest or count parameters are tainted, it is possible that the function call could create a buffer overflow. The ability to cause an overflow or overread depends onthe constraints placed on these parameters by the program. Marten uses the logged information and bytecode files generated by LLVM to derive symbolic expressions for the tainted values and for the constraints placed on tainted values by conditional statements. Systems like Valgrind [18] do not log data and instead track data at runtime in memory. Our approach reduces the memory overhead of storing this data while running an instrumented application.

4.0.2 Trace Analyzer

The trace analyzer reads the log files to generate sinks in the program which Marten will later analyze to expose vulnerabilities. A sink is a message containing details about a function where data is used in a way that may cause an overflow, an overread, or perform transformations on the input bytes. Marten generates four different kinds of sinks:

∙ Memtransfer: A function corresponding to a memory transfer function, such as memcpy, that Marten is trying to attack. These are generated while Marten is looking for buffer overflows when the destination or size of a memory transfer is tainted.

34 ∙ Input: A function which reads tainted data. These are generated any time data is read into the program from the attack input.

∙ Overread: A function corresponding to a memory transfer in which the source pointer or size is tainted. These are only generated when Marten is looking for buffer overreads.

∙ Data: A sink generated to represent tainted data that later flows into the other types of sinks. These are generated to support transformations of the data that flows into other sinks for both ROP chain generation and information leakage.

The trace analyzer will generate sinks depending on whether the parameters are tainted and if the sink type is of interest based on the type of attack Marten is imple- menting. When Marten attacks stack buffer overflows, it is interested in Memtransfer and Input sinks. In this kind of attack, Marten is targeting a vulnerable memcpy or recv in the program. When Marten generates information leak exploits, it is targeting overread sinks and data sinks. Sinks include important information such as the constraints on the input bytes which allow Marten to reach a certain function of interest, the symbolic equations for the input, and concrete values for function parameters. Furthermore, Marten logs the taint labels of specific bytes so that it can determine where data that is manipulated in an overread is used again in an output function like a socket send. Symbolic Expressions and Constraints: The trace analyzer keeps track of the symbolic expressions of individual bytes in the input. Marten tracks expressions for each of the bytes in the input that reach a sink. This optimization allows Marten to avoid tracking symbolic information for every input byte, which would quickly become intractable. The symbolic expressions are generated by walking through the LLVM bytecode generated at compile time to determine the operations computed on the bytes before they become the parameters of a sink. Once an input function, such as read or recv, is activated on a communication channel that is controlled by Marten, the trace analyzer will mark the input bytes as

35 tainted and create symbolic variables for the bytes read if they reach a sink. Consider a symbolic variable called byte which is created when some input is read in. Any calculation performed on information associated with byte will propagate symbolic expressions to the relevant destinations. These calculations are checked by examining the LLVM bytecode generated at compile time. For example, say the LLVM register i8 has the symbolic expression byte. If an LLVM instruction of the following form takes place :

%i9 = add i32 %i8, 10

Marten now knows that the register i9 will have the symbolic expression byte + 10. If i9 is later used to determine the size of a memcpy and Marten knows the size of the destination buffer, it will be able to determine if a concrete value existsfor byte that will overflow the buffer. Marten also keeps track of the constraints placed on the input bytes based on the branches that occur within the program. These constraints are represented with sym- bolic expressions that include a result of True or False. Marten uses the constraints extensively in vulnerability discovery.

36 Chapter 5

Vulnerability Discovery

At this stage, Marten determines whether it is possible to leak information or overflow a buffer. To trigger vulnerabilities, Marten follows a goal directed condi- tional branch enforcement algorithm described by Sidiroglou et al. [34]. I generalize this technique to find any type of vulnerability, not just integer overflows. Thisgen- eralization is achieved by developing specific success functions for each vulnerability. I present functions for buffer overflow and information leakage vulnerabilities. To detect a bug using these functions, Marten recompiles the target application with Address Sanitizer (ASAN) [30] which will report out of bounds reads and writes.

5.1 Vulnerability Discovery Algorithm

I implement an algorithm based on goal directed conditional branch enforcement to transform a benign input that traverses a target site into an input which triggers a vulnerability. Algorithm 1 shows my approach to this problem.

37 Algorithm 1: Vulnerability Discovery Algorithm

1 input: 퐶: source code of the program 퐿: LLVM instrumented program 푆: the target sinks generated from initial analysis, 퐼: program input, 퐹 : success function

2 output: 휌: an input that triggers the vulnerability or ⊥

3 퐴 ← 퐴푆퐴푁_푐표푚푝푖푙푒(퐶)

4 for 푠 in 푆 do

5 푐푢푟_푐표푛푠 ← ∅

6 while 푐푢푟_푐표푛푠 ̸= 푎푙푙_푐표푛푠 do

7 if not 휌 ← 푠표푙푣푒푟_푔푒푛푒푟푎푡푒_푖푛푝푢푡(퐼, 푐푢푟_푐표푛푠) then

8 break

9 end

10 if 퐹 (휌, 퐴, 퐿) then

11 return 휌

12 end

13 푚표푑_푐표푛푠 ← 푔푒푡_푐표푛푠푡푟푎푖푛푡푠(퐿(휌)) ;

14 if 푔표푡_푛푒푤_푐표푛푠푡푟푎푖푛푡(푐푢푟_푐표푛푠, 푚표푑_푐표푛푠) then

15 푎푑푑_푛푒푤_푐표푛푠푡푟푎푖푛푡(푐푢푟_푐표푛푠, 푚표푑_푐표푛푠)

16 else if 푐표푛푠푡푟푎푖푛푡_푛표푡_푓푙푖푝푝푒푑(푐푢푟_푐표푛푠, 푚표푑_푐표푛푠) then

17 푓푙푖푝_푛푒푤푒푠푡_푐표푛푠푡푟푎푖푛푡(푐푢푟_푐표푛푠)

18 else

19 break;

20 end

21 end

22 return ⊥ ;

s Given the source code of a program 퐶, a version of 퐶 compiled with my 퐿퐿푉 푀 instrumentation 퐿, the sinks generated from initial analysis 푆, the benign seed input 퐼, and a success function 퐹 , the algorithm will first compile an ASAN version of the source code. Then, it will iterate through the sinks in 푆, trying to attack each of them.

38 Each sink has constraints associated with it. Marten starts by mutating 퐼 such that the new input triggers a vulnerability without adding any constraints. If the solver is unable to generate an input that meets the current constraints, Marten breaks out of the current loop iteration and continues on to the next sink. If this input fails to trigger a bug, Marten will obtain the branches from the mutated input and add one new constraint associated with the target sink. If no new constraints have been generated, Marten will flip the newest constraint and continue executing. If no new constraints are generated and Marten has already tried flipping the newest constraint, Marten determines that it is not possible to generate an input which exercises a vulnerability for this sink. Thus, Marten moves on to the next sink and tries to attack it. Marten stops once it has found a bug or if it has tried all of the sinks in 푆 and was unable to trigger a vulnerability. The success function 퐹 is used to determine whether the input triggers the desired type of vulnerabilities. In my current implementation, I supply two different types of success functions.

5.2 Success Functions

I present two success functions, one for buffer overflows and one for buffer over- reads. Additional success functions can be written to provide a general error checking algorithm for different types of vulnerabilities.

5.2.1 Overflow

This function simply checks that the input causes ASAN to report a buffer overflow error. If it does, then it returns True. If not, it returns False.

5.2.2 Information Leak

Similarly to the overflow function, this success function will check that ASAN has reported an error when run on the given input. Additionally, it will rerun the

39 input with my instrumented version of the program. The function will check that the additional data read into the buffer at the overread reaches an output function such as a socket send. If it does, then I have a successful information leak. If not, then the program will solve constraints between the overread and the output function. This solving is done to ensure that the input which causes ASAN to report an error also leaks the data from the overread. Preventing Memory Corruption: Marten takes special care to ensure that it does not crash the target program after triggering the buffer overread. This goal is achieved by ensuring that the destination buffer is large enough to hold the data being read into it. Marten logs the size of the destination buffer in my sinks when it traces the process’s execution and verifies the buffer is large enough to hold thedata by checking its allocated size against the length of the overread.

5.3 Path Explosion and Symbolic Execution

One significant issue with symbolic execution is path explosion. Each new branch in a program increases the number of paths to be explored exponentially. It is im- portant to realize that Marten is only using symbolic execution in a limited way to explore the program. Marten will only explore the path followed by a given sample input. The only new paths it will explore are those traversed while trying to flip all branches along this path. If a new path does not reach the target location, it is discarded. Thus, Marten’s use of a goal directed conditional branch enforcement algorithm significantly reduces the space that it searches for vulnerabilities. This method allows for a targeted exploration of the program that includes:

1. The path originally executed by operating on the provided seed input.

2. Any new paths generated by flipping branches along the original path.

The reason this methodology is successful in finding vulnerabilities is largely de- tailed in [34]. To summarize, programs often perform incomplete sanity checks on inputs before they allow those inputs to reach potentially dangerous functions (such

40 as memcpy). These checks often have small mistakes that are difficult to discover through manual source code analysis alone. Placing these sanity checks in an SMT solver along with the desired parameters to a target function, such as a count pa- rameter of a memcpy call that is overly large, can be an effective method of finding vulnerabilities.

41 42 Chapter 6

Information Leakage

In the information leakage phase, I determine whether I can leak useful information (such as randomized pointers) from the process. Marten leaks the addresses of code sections to bypass full ASLR. Marten implements a novel algorithm to discover target information by inspecting points of interest in the program and ensuring the desired data is leaked back to Marten. A scripted version of GDB is invoked by Marten to inspect the processes at runtime [35].

6.1 Information Discovery Algorithm

Algorithm 2 sets a breakpoint at a location of interest determined by the vulnera- bility discovery component of Marten. Next, it runs the program until it reaches the desired breakpoint. If this location is the point at which the overread occurs, Marten inspects the program’s state to determine the ranges for its executable memory pages. Otherwise, Marten will continue executing. When Marten reaches the overread, it attempts to find a pointer into the largest code segment located within reach ofthe overread and take note of its value. To find this pointer, Marten obtains the exe- cutable memory maps for the process from the respective /proc/pid/maps where pid matches that of the target process. This method allows Marten to verify that the pointer is within an executable code segment. At this point, Marten mutates the input file to generate an overread which leaks the greatest amount of information it

43 Algorithm 2: Information Leakage Algorithm 1 input: 퐶: source code of the program, 푆: the point in the program Marten is targeting, 푉 : vulnerability triggering input 2 output: 휖: leaking input or ⊥ 3 푃 ← 퐷퐸퐵푈퐺_푐표푚푝푖푙푒(퐶) 4 set_break(푆, 푃 ) 5 푃푖 ← run 푃 (푉 ) 6 while 푏푟푒푎푘_푟푒푎푐ℎ푒푑(푃푖) do 7 if correct_point(푃푖, 푆) then 8 푋 ← 푒푥푒푐푢푡푎푏푙푒_푠푒푔푚푒푛푡푠(푃푖) 9 퐵 ← 푔푒푡_푏푖푡푠_표푓_푋_푎푡_푝표푖푛푡(푃푖, 푋) 10 break 11 else 12 continue 13 end 14 end 15 휖 ← 푚푢푡푎푡푒_푖푛푝푢푡(푉 ) ; 16 if 푣푒푟푖푓푦_표푢푡푝푢푡(휖, 푃, 퐵) then 17 return 휖 18 else 19 return ⊥ ; 20 end

44 can obtain without overflowing the destination buffer.

6.2 Information Leakage Verification

Marten verifies that the information leakage exploit is successful by first running the target application and stopping execution on the first instruction after libc has been loaded. At this point, Marten inspects the memory map of the process and gathers the memory range for the library it intends to leak. Marten then lets the program run to completion. Marten sends the exploiting input to the program and verifies that there is a pointer in the response which resides somewhere in thetarget memory map. If there is such a pointer, Marten knows that it has generated an input which successfully leaks critical information for the next stage of exploitation. Marten can now use all of the code in the leaked library to break full ASLR.

6.3 Information Identification

At a high level, buffer overreads are exploited by sending the vulnerable process data and then receiving data from that process. There is useful information for control-flow hijacking exploits in the received data (i.e. the randomized addresses of libraries used by the program). Marten uses a novel method for finding library addresses that can later be used in control-flow hijack attacks. To find library address in received data, Marten first generates the largest infor- mation leak it can without corrupting the target, causing the highest probability of the target data being leaked. It then takes advantage of the bits of entropy used to realize ASLR. On 64 bit Linux systems, libraries have 28 bits of entropy [17]. A library address takes on the following form for 64 bit systems:

0x00007fXXXXXXXYYY

In the above example, the bits represented with an X are randomized by ASLR and the bits represented with a Y are not. Marten determines the value of YYY

45 1 ◁ 0x442067 mov rdx, qword ptr [rbp−0x20 ] 2 0x44206b mov rcx, qword ptr [rbp−0x18 ] 3 0x44206f mov rax, qword ptr [rbp −8] 4 0x442073 mov rsi , rcx 5 0x442076 mov rdi , rax 6 0x442079 call memcpy@plt <0x402a10>

Figure 6-1: Disassembly when setting breakpoint in outpacket.c at line 84 for Dnsmasq-2.77

when it selects a target to leak from automated analysis with GDB. From this point, finding the information is a matter of applying a bitmask to each 8 byte valueinthe output until Marten finds a value that matches the form of 0x00007fXXXXXXXYYY. Marten subtracts the offset gathered from GDB analysis and can now determine the base address of the target library. Marten relies on the fact that standard libraries such as libc, unlike applications, are typically compiled once for each Linux release and are then distributed along with the release. The code offsets within libc are therefore typically the same across all machines running the same Linux distribution so that the ROP chain generated for that version of libc will usually work across all of those machines.

6.4 GDB Scripting

I created a python class, GDBWrapper, which invokes GDB as a subprocess and provides various member functions that perform the useful functionality of differ- ent commands. One of the challenges with automating GDB is ensuring that the commands sent generalize to more than one program. I use information from initial analysis to handle this issue. From the LLVM bytecode, I are able to determine the source file and line of a specific function of interest. Once I have identified theover- read sink I wish to attack, ensuring that I can analyze the interesting point of this program is as simple as setting a breakpoint at the proper location. Breaking at a line number is a higher level of abstraction than breaking on a specific machine code instruction. As can be seen in Figure 6-1, when a breakpoint

46 is set at the target location in the source code, GDB ends up stopping execution a number of instructions before the memcpy call. Thus, I ensure that I step for a few instructions until I are on the call memcpy opcode. This method ensures the registers are properly set up to analyze the state of the program. Note that I may hit the breakpoint multiple times during the execution of the program. I therefore check the transfer size and stop only when the size matches. Once I reach the location of interest, I have to inspect the program state to find the useful information. To do this, I rely on the fact that the x86_64 calling convention places the arguments in the registers RDI, RSI, and RDX, respectively. Thus, I know the address of the source buffer in the memcpy of Figure 6-1 is in RSI. I can inspect memory located after this pointer to find the information I wish to leak and generate an input file that causes this memory transfer to reach the target information.

47 48 Chapter 7

Exploit Generation

Once an information leak has been performed, the results are used to generate an exploit that bypasses full ASLR and other modern defenses. This process works in three steps consisting of ROP chain generation, stack offset calculation, and exploit finalization. The final result is a Python script that takes an IP address forthetarget and automatically performs an information leakage attack and a buffer overflow attack that gives the attacker arbitrary computation and bypasses full ASLR.

Algorithm 3: execve chain generation 1 input: 퐿: library for the target program, debug info not needed, 푂: Offset from base address of library, 푋: Command for the chain to execute 2 output: 퐶: ROP chain that executes 푋 3 퐺 = find_gadgets(퐿) 4 offset_gadgets(퐺,푂) 5 퐷 = get_data_segment_offset(퐶) 6 argv_addr = 퐷 7 cmd_addr = 퐷 + length(푋) + 0x8 8 null_address = cmd_address + length(푋) 9 퐶 += create_command(푋, cmd_addr, arvg_addr) 10 퐶 += write_memory(0x0, null_address) 11 퐶 += create_dep_chain(%rax, %rdi, %rsi, %rdx) 12 퐶 += syscall_gadget 13 퐶 = add_padding(C) 14 return 퐶

49 7.1 ROP Chain Generation

My system uses a modified version of Ropper [28] to generate ROP [32] payloads, which are capable of bypassing NX and RELRO protections. I built upon the auto- matic ROP chain creation portion of Ropper, giving it the ability to generate exploits that are capable of much more flexible attacks than simply opening a local shell. My current approach generates two different chains, the execve and shellcode chains.

execve: The execve ROPchain writes a command string to memory and then makes an execve() system call using that command string. The string may be an arbitrarily complex shell script. The only constraint is that the chain must be small enough to fit within the process’s memory. The execve chain determines a place to write the string based on determining which locations in the library are both writable and readable. These are data sections used by the process to store information that is needed at runtime.

The create_command() function used during execve chain generation splits the provided string into architecture-appropriate sized pieces that are written by sequen- tial write gadgets starting at cmd_addr, allowing for arbitrary length commands to be passed by users of Marten. Once the string literals have been written, an array of pointers to the strings are written to argv_addr.

The create_dep_chain() function takes in a set of register to value mappings and figures out an ordering of gadgets such that at the end of their execution, allofthe desired registers will be set to the specified values without any of the registers being accidentally clobbered by previous gadgets. Algorithm 3 implements this technique. shellcode: The shellcode ROPchain makes a mprotect() system call to make a portion of the data section executable, writes a small shellcode loader to the now executable memory, then jumps to the loader. The loader copies another shellcode to the addresses beneath it, then runs it.

As seen in the Algorithm 4, Marten first generates the chain 푀, which executes the mprotect system call on a desired memory range. Then, it generates a simple chain 퐶 which writes the loader to memory. Finally, the 푀 chain is appended to 퐶

50 and returned. The 퐶 chain is generated second even though it executes first, as it requires the loader to be finished, which requires 푀 to be finished so that Marten can check whether an additional pop is needed in the loader or not.

Algorithm 4: shellcode chain generation 1 input: 퐿: library for the target program, debug info not needed, 푂: Offset from base address of library, 푋: Command for the chain to execute 2 output: C: ROP chain that executes 퐶, 푆퐶 : shellcode to be included in buffer overflow that will be written to an executable location 3 퐺 = find_gadgets(퐿) 4 offset_gadgets(퐺,푂) 5 푆퐶 = choose_shellcode(푋) 6 퐷 = get_data_segment_offset(퐶) 7 target_addr = 퐷 8 target_addr_aligned = align(target_addr, 0x1000) 9 load_dst = target_addr + 0x100 10 푆푍 = 0x2000 11 푃 = 0x7 (RWX permission) 12 푀 = create_dep_chain(%rax, %rdi, %rsi, %rdx) 13 푀 += syscall_gadget 14 jump_addr = target_addr + library_base_address 15 푀 += jump(jump_addr) 16 loader = build_loader(loader_dst, len(shellcode)) 17 퐶 = memwrite_chain(target_addr, loader) 18 퐶 += 푀 19 퐶 = add_padding(C) return 퐶, 푆퐶

Information Leakage Integration: Marten specifies a base address from which gadget addresses are calculated. By feeding in the base address for the library tar- geted by information leakage, Marten is able to generate a ROP chain that uses the randomized offset that was leaked. Marten generates this ROP chain by usingthe gadgets located at specific offsets from the base address, stitching them into achain, and applying the randomized base address once it is determined by my information leakage exploit.

51 7.2 Stack Offset Calculation

Once one or more ROP chains have been generated, Marten fits this chain into the vulnerability triggering input found in previous stages of the pipeline. To fit the chain, Marten requests a second input that contains a long De Bruijn sequence [1] that will overflow the buffer and overwrite the saved instruction pointer.

If Marten is able to generate the input that hijacks the return pointer of the program, the instruction pointer will be a portion of the De Bruijn sequence. The De Brujin sequence is used to quickly calculate the offset from the beginning of overflow to the saved instruction pointer.

If Marten was not able to generate such an input, but is able to find a smaller, non crashing input with specifiable fingerprint value, it will use my GDB wrapper tofind the fingerprint value in memory. Once the fingerprint is found, Marten can calculate the difference between the location of the fingerprint and the saved instruction pointer.

7.3 Exploit Finalization

After one of the two stack offset calculation processes is run, Marten knows how many bytes need to be written to the buffer to cause a control flow hijack. Foreach generated ROP chain Marten can now ask the solver to assemble a final input that consists of whatever information is needed to get to the desired memory transfer, place arbitrary content to overflow the buffer, and then the values of the chain. Ifan input is able to be generated, Marten now has an attack file that can be sent to the target program that will bypass full ASLR and other modern defenses.

The final exploit is a Python script which takes the IP address of the target server and performs an information leakage exploit against it. The library base address that is leaked is applied to the relative offsets present in the attack file. The final attack file is then sent to the target, exploits it, and bypasses full ASLR.

52 7.4 Chain Size

The ROP chains I generate are short enough to fit within a single TCP packet. This quality prevents the chains from being split up across multiple packets which is useful for remote exploits. If Marten is sending exploits to a remote server across a slow network, large chains may not reach the target server at the same time. If the server is using non-blocking receives, which is quite common, then this situation would cause only part of my chain to be loaded into memory. Because only part of the chain gets executed, my exploit would just crash the target, an undesirable outcome for an attacker. Because Marten’s chains fit into a TCP packet, they arrive at the server as a unit and are loaded into memory all at once, enabling the exploits to complete their execution. My chains are short for two primary reasons. First, information leakage gives Marten access to a huge number of gadgets because it can use all of the code in large libraries like libc. This information allows Marten to create chains using gadgets with few (three or less) extraneous instructions. For example, if Marten needs to set the the RDI register, a gadget such as:

pop RDI; ret; is typically readily available. The second reason Marten is able to generate short chains is that it takes a heuristic approach to gadget searching. In Algorithm 3 and Algorithm 4, Marten searches for gadgets that meet very specific criteria. For example, when Marten wants to load a register it searches for gadgets that only have a single pop or mov instruction. This technique prevents Marten from searching for gadgets that have extraneous instructions which perform undesirable computation that is corrected with adding yet more gadgets to the chain. My approach ensures Marten is building chains with gadgets that are compact. Marten generates chains that fit within a single TCP packet which beneficial for generating reliable remote exploits.

53 7.5 Exploit Reliability

My exploits are effective against stripped binaries that are compiled in different environments for three main reasons. First, my chains are short for the reasons listed in Section 7.4. Marten also adds padding by augmenting its exploits with ret gadgets. This method is the ROP equivalent of a NOP sled [20], a technique used to improve the reliability of exploits against unpredictable stack layouts. These extra gadgets at the beginning of my chains provide a buffer space to account for shifted stack configu- rations which may be due to different compilation settings of the target, different environment variables, etc. Marten also gathers chains from libraries, not the program’s code. Programs may have different instruction sequences and offsets when compiled with different flag settings and optimization levels. From my own experience, compiling Nginx-1.4.0 in a different directory caused the gadgets in the binary to change. Libraries, especially libc, are typically compiled once, then distributed with the operating system release. Marten’s exploits therefore target code in libc rather than code in the application.

54 Chapter 8

Results

Marten generates working exploits for seven vulnerabilities across five code bases. One of the vulnerabilities is a previously undiscovered zero-day. These exploits have been verified to work against fully randomized, stripped binaries compiled inthree different environments. Specifically, these environments are Ubuntu 18.04, Debian 9.9, and Red Hat Enterprise 8.0. All binaries are compiled with the defenses detailed in Section 2.1. Overall results for this work are detailed in Figure 8.1

All of the final payloads were generated on a machine with one Intel(R) Core(TM) i9-8950HK CPU @ 2.90GHz processor and 8 GB of RAM running Ubuntu 18.04. All exploits generate in under six minutes on this machine. In general, the offsets of ROP gadgets within libc may be different for different versions of Linux. Marten

Program Vulnerability Type Advisory ID. FULL ASLR NX RELRO FORITIFY Chains Generated Verified On execve Ubuntu 18.04 Nginx-1.4.0 Buffer Overflow CVE-2013-2028 ✓ ✓ ✓ ✓ shellcode Debian 9.9 OpenSSL-1.0.1 Buffer Overread CVE-2014-0160 ✓ ✓ ✓ ✓ Red Hat Enterprise 8.0 execve Ubuntu 18.04 Dnsmasq-2.77 Buffer Overflow CVE-2017-14493 ✓ ✓ ✓ ✓ shellcode Debian 9.9 Dnsmasq-2.77 Buffer Overread CVE-2017-14494 ✓ ✓ ✓ ✓ Red Hat Enterprise 8.0 Ubuntu 18.04 Asterisk-11.1.2 Buffer Overflow CVE-2013-2685 ✓ ✓ ✓ ✓ execve Debian 9.9 OpenSSL-1.0.1 Buffer Overread CVE-2014-0160 ✓ ✓ ✓ ✓ Red Hat Enterprise 8.0 Ubuntu 18.04 Serveez-0.0.20 Buffer Overflow Bugtraq ID: 42560 ✓ ✓ ✓ ✓ execve Debian 9.9 Serveez-0.0.20 Buffer Overread Zero Day ✓ ✓ ✓ ✓ Red Hat Enterprise 8.0

Table 8.1: Results for benchmark applications. Marten generates working exploits for seven vulnerabilities and chains them together to create exploits that bypass full randomization and other defenses.

55

1 therefore works with the appropriate version of libc when generating the ROP chain for processes running on the corresponding version of Linux.

8.1 Dnsmasq-2.77

The exploitation process against Dnsmasq-2.77 is detailed in Section 3. To summa- rize, Marten discovers a buffer overread and buffer overflow in the DHCPv6 handling code of Dnsmasq-2.77. These vulnerabilities allow Marten to generate combined in- formation leak and control-flow hijacking exploits against Dnsmasq using both the execve and shellcode ROP chains.

8.2 Nginx-1.4.0 and OpenSSL-1.0.1

I compiled Nginx-1.4.0 with OpenSSL-1.0.1 which is vulnerable to CVE-2014-0160, the infamous Heartbleed vulnerability [9]. The code for CVE-2014-0160 is presented in Figure 8-1. The input packet is represented by p. On line 11, the n2s function is used to obtain the value of payload from p. Once the program verifies that the input type is indeed a heartbeat packet on line 19, a buffer is allocated with a size slightly greater than payload on line 28. The call to memcpy on line 34 is vulnerable to a buffer overread because the size of the payload parameter is not checked to ensure that it stays within the source buffer, pl. The payload parameter is determined by an input from the network. Thus, this code can cause an excessive amount of data to be read into the buffer from the heap which is then sent back to the attacker. This data reveals critical information about the randomization of the process’s address space. Marten is given a benign heartbeat packet as a seed file to send to the target process. Marten runs an instrumented version of Nginx and correctly identifies the vulnerable call to memcpy that causes a buffer overread. Marten attacks this sink by mutating the length field of the heartbeat packet such that a buffer overread occurs. The length field is used to determine the amount of data sent back to the attacker.

56 1 tls1_process_heartbeat(SSL * s ) 2 { 3 4 unsigned char *p = &s−>s3−>rrec.data[0] , * pl ; 5 unsigned short hbtype ; 6 unsigned int payload ; 7 unsigned int padding = 16; /* Use minimum padding */ 8 9 /* Read type and payload length first */ 10 hbtype = *p++; 11 n2s (p , payload ) ; 12 pl = p ; 13 14 i f ( s−>msg_callback) 15 s−>msg_callback(0, s−>version , TLS1_RT_HEARTBEAT, 16 &s−>s3−>rrec.data[0], s−>s3−>rrec.length , 17 s , s−>msg_callback_arg) ; 18 19 i f ( hbtype == TLS1_HB_REQUEST) 20 { 21 unsigned char * b u f f e r , *bp ; 22 int r ; 23 24 /* Allocate memory for the response, size is 1 bytes 25 * message type, plus 2 bytes payload length, plus 26 * payload, plus padding 27 */ 28 buffer = OPENSSL_malloc(1 + 2 + payload + padding); 29 bp = b u f f e r ; 30 31 /* Enter response type, length and copy payload */ 32 *bp++ = TLS1_HB_RESPONSE; 33 s2n ( payload , bp ) ; 34 memcpy(bp, pl, payload);

Figure 8-1: CVE-2014-0160: the Heartbleed Vulnerability.

57 1 i f ( r−>headers_in.content_length_n == 0) { 2 r−>read_event_handler = ngx_http_block_reading; 3 return NGX_OK; 4 } 5 6 i f ( ! r−>connection −>read−>ready ) { 7 return NGX_AGAIN; 8 } 9 10 size = (size_t) ngx_min(r−>headers_in .content_length_n , 11 NGX_HTTP_DISCARD_BUFFER_SIZE) ; 12 13 n = r−>connection −>recv ( r−>connection, buffer , size);

Figure 8-2: CVE-2013-2028: Stack Buffer Overflow in Nginx

An overly long heartbeat response is sent, spilling process memory that results in an information leak exploit.

Figure 8-2(a) presents the vulnerable code for CVE-2013-2028, a stack buffer over- flow in Nginx-1.4.0. The value of size on line 10 is determined by comparing network input to a value that has been defined in the program, NGX_HTTP_DISCARD_BUFFER_SIZE. Both values are signed and the input from the network is not checked to insure it is non-negative. Thus, Nginx-1.4.0 is vulnerable to an improper use of a signed/unsigned comparison. The size value located on line 10 of Figure 8-2 is used to determine the length of data read by a recv() function call on line 13. The size value is checked on line 10 to ensure it is not too large using the ngx_min function. However, the value checked is signed while the parameter to the recv() call is unsigned. By creating a negative signed input for the size value, Marten is able to bypass the check and call recv() with an overly large unsigned value. This call to recv triggers a stack buffer overflow when the attacker sends a large amount ofdata.

Marten runs the same instrumented version of the application used to generate the information leakage exploit. The difference is that this time, Marten is given aseed file that executes the code vulnerable to a buffer overflow. Marten then mutatesthis input into one that triggers the stack buffer overflow and causes an ASAN instance of Nginx to crash.

Using the input that triggers a stack buffer overflow, Marten fits a ROP chain into

58 a malicious HTTP packet. The chain sets up the parameters to a system call that allows the attacker to download and run a program from a remote server. The ROP chain generated by Marten is filled with relative addresses. At exploitation time, these addresses are modified using the absolute base address of libc calculated bythe information leakage exploit. The final exploit performs an information leak attack and using the information obtained from this stage, generates a robust ROP exploit that is used to execute code in the context of the Nginx server.

8.3 Asterisk-11.1.2 and OpenSSL-1.0.1

Similarly to Nginx-1.4.0, I compiled Asterisk-11.1.2 to use OpenSSL-1.0.1. Marten generates an exploit targeting CVE-2014-0160 for Asterisk in the same way that it does for Nginx. The result is an exploit that will leak information from the target process. Asterisk-11.1.2 is vulnerable to CVE-2013-2685. The code for this vulnerability is displayed in Figure 8-3. This code parses a specific line of a given sip packet. The line in question determines the Session Description Protcol (SDP) parameters. Non-malicious parameters will take on the form "a=fmtp:96 sprop-parameter-sets=J0LgDZWWFglk,KM4Ecg==". An SDP parame- ter set is a pair of base64 encoded strings. Asterisk attempts to parse these strings on line 19 by placing them into two stack buffers, sps and pps. Marten logs the call to sscanf and the format string used to parse the input. Once it is determined that the string being parsed is tainted (i.e. determined by attacker input), Marten attempts to generate an overly long string that respects the specified format. This generated string causes a buffer overflow that allows Marten to corrupt the instruction pointer. The parsing code contains a stack buffer overflow vulnerability caused by a call to the function sscanf using the %s format specifier. The %s specifier allows for a string of unbounded length to be read into the buffer supplied to sscanf. Asterisk limits the length of this string to 256 bytes, while the length of the pps and sps buffers are

59 1 s t at i c int h264_format_attr_sdp_parse( struct ast_format_attr * format_attr , const char * attributes) 2 { 3 char * attribs = ast_strdupa(attributes), * a t t r i b ; 4 5 format_attr−>format_attr [H264_ATTR_KEY_REDUNDANT_PIC_CAP] = H264_ATTR_KEY_UNSET; 6 format_attr−>format_attr [H264_ATTR_KEY_PARAMETER_ADD] = H264_ATTR_KEY_UNSET; 7 format_attr−>format_attr [H264_ATTR_KEY_PACKETIZATION_MODE] = H264_ATTR_KEY_UNSET; 8 format_attr−>format_attr [H264_ATTR_KEY_LEVEL_ASYMMETRY_ALLOWED] = H264_ATTR_KEY_UNSET; 9 10 while ((attrib = strsep(&attribs , ";"))) { 11 unsigned int v a l ; 12 unsigned long int val2 ; 13 char sps [H264_MAX_SPS_PPS_SIZE] , pps [H264_MAX_SPS_PPS_SIZE ] ; 14 15 i f (sscanf(attrib , "profile −l e v e l −id=%lx", &val2) == 1) { 16 format_attr−>format_attr [H264_ATTR_KEY_PROFILE_IDC] = ( ( val2 >> 16) & 0xFF) ; 17 format_attr−>format_attr [H264_ATTR_KEY_PROFILE_IOP] = ( ( val2 >> 8) & 0xFF) ; 18 format_attr−>format_attr [H264_ATTR_KEY_LEVEL] = ( val2 & 0xFF) ; 19 } else i f (sscanf(attrib , "sprop−parameter−sets=%[^’,’],%s", sps, pps) == 2)

Figure 8-3: CVE-2013-2685 Asterisk Buffer Overflow Vulnerability

only 16 bytes. Thus, a small (240 byte) buffer overflow occurs.

The fact that the exploit is string based presents a challenge for Marten. Marten must generate a ROP payload that does not contain NULL bytes. Given this con- straint, it is not possible to generate a ROP payload for most 64-bit systems because the code addresses contain NULL bytes. Thus, Marten only generates exploits for this vulnerability against 32-bit systems. Marten is able to avoid sending any NULL bytes in the ROP chain by identifying locations in the leaked library’s data sections that contain NULL bytes. Any strings that need to be used for the the execve sys- tem call are then written to these locations. Thus, no NULL bytes are needed in the actual ROP chain as they already exist in the running process.

Another obstacle for this exploit is the size of the overflow. This constraint pre- vents a long ROP chain from being executed. As a result, only the execve ROP chain was successfully generated. The command executed by this chain was 8 bytes (including the NULL byte at the end of the string), "/bin/sh".

60 1 int http_cgi_write (socket_t sock) 2 { 3 int do_write ; 4 int num_written ; 5 http_socket_t * http = sock−>data ; 6 /* 7 * Write as many bytes as possible , remember how many 8 * were actually sent. Do not write more than the content 9 * length of the post data. 10 */ 11 do_write = sock−>recv_buffer_fill ; 12 i f (do_write > http−>contentlength) 13 { 14 do_write = http−>contentlength ; 15 i f ((num_written = write (sock−>pipe_desc [WRITE] , 16 sock−>recv_buffer , do_write)) == −1) 17 { 18 l o g _ p r i n t f (LOG_ERROR, " c g i : write : %s \n" , SYS_ERROR) ; 19 }

Figure 8-4: CVE-2019-16200 Serveez Information Leak Vulnerability

8.4 Serveez-0.0.20

The information leak in Serveez-0.0.20 is a previously undiscovered zero-day that has now been assigned CVE-2019-16200 [11]. The vulnerable code is presented in Figure 8-4. On line 12, there is a length comparison between two signed values. Specifically, the value of the contentlength variable can be set by the attacker through the input that they provide. If the attacker provides a negative number, then contentlength will be less than the do_write variable. Once this check is passed, the contentlength parameter will be passed as the length to a write() system call. write expects an unsigned value for the length, but contentlength is a signed negative number. Thus, it will evaluate to a huge unsigned value which causes a buffer overread that leaks a large amount of data to the attacker.

Marten runs an instrumented version of the application with a benign HTTP packet as a seed file. Marten adjusts the seed file so that the contentlength field is set to a negative (very large unsigned) number. Marten uses its automated GDB interface to interact with an uninstrumented version of Serveez and identifies pointer values that can be leaked from the input. At this point, Marten has a successful

61 1 switch ( date [ 3 ] ) 2 { 3 /* ASCTIME−Date */ 4 case ’’: 5 sscanf (date, "%3s %3s %2d %02d:%02d:%02d %04d", 6 _wkday, _month, &parse_time.tm_mday, &parse_time.tm_hour, 7 &parse_time.tm_min, &parse_time.tm_sec, &parse_time.tm_year); 8 9 break ; 10 /* RFC1123−Date */ 11 case ’,’: 12 sscanf (date, "%3s, %02d %3s %04d %02d:%02d:%02d GMT", 13 _wkday, &parse_time.tm_mday, _month, &parse_time.tm_year, 14 &parse_time.tm_hour, &parse_time.tm_min, &parse_time.tm_sec); 15 16 break ; 17 /* RFC850−Date */ 18 default : 19 sscanf (date, "%s, %02d−%3s−%02d %02d:%02d:%02d GMT" , 20 _wkday, &parse_time.tm_mday, _month, &parse_time.tm_year, 21 &parse_time.tm_hour, &parse_time.tm_min, &parse_time.tm_sec); 22 23 parse_time.tm_mon += parse_time.tm_mon >= 70 ? 1900 : 2000;

Figure 8-5: Bugtraq ID 42560: Serveez Buffer Overflow Vulnerability

information leakage exploit for the zero-day vulnerability. Serveez-0.0.20 is vulnerable to a buffer overflow as detailed in Bugtraq ID 42560. The vulnerable code is displayed in Figure 8-5. The program will decide how to parse a date and time provided via a socket input in the case statement. If the format does not match the first few options, then the program will opt for a default date format. In this default format, a critical mistake is made. Similarly to Asterisk, an overflow is caused by a call to sscanf with a %s format specifier as shown on line 22 of Figure 8-5. In this case, the overflow is not bounded to a small number of bytes by the program. Thus, it is much easier for Marten to generate an exploit for this vulnerability allowing both the execve and shellcode chains to be generated. Marten runs an instrumented version of Serveez and is given a benign input packet that includes a valid Request for Comments (RFC) 850-Date field [12]. The instru- mented program logs the vulnerable call to sscanf which Marten identifies. Marten then generates an input that causes an ASAN instance of the application to crash due to an overly long _wkday field in the input. Marten then inserts a ROP chain into

62 this field and is able to execute arbitrary code in the context of the Serveez process. Marten combines the zero-day information leak and stack buffer overflow to gen- erate an exploit that bypasses modern defenses such as full randomization. This achievement is made by replacing relative addresses in the ROP chain with absolute addresses. Because the buffer overflow in string-based, Marten must generate a chain under the constraint that it include no NULL characters. This challenge requires Marten to search for addresses which satisfy the constraint. In addition, locations that already contain NULL bytes are used to write parameters for the execve chain, much like the exploit for Asterisk.

63 64 Chapter 9

Related work

Automatic Exploit Generation: Brumley et al. showed, given source code access, that it is possible to automatically convert a patch into an input that violates the safety checks created by the patch, not one that hijacks the control flow of the target program [4]. The generated inputs target standard undefended (nonrandomized with executable stack and heap) binaries. Marten, in contrast, does not require patches (only source code access and a benign input that exercises potential attack targets) and generates fully functional exploits that bypass full ASLR (as well as other defenses such as NX) to inject and execute attacker code within remote processes accessible only via a network connection. AEG and Mayhem use symbolic execution to automatically find stack buffer over- flows and format string vulnerabilities while generating exploits that target these bugs [2, 5]. Mayhem does this without access to source code while AEG requires source code. The exploits generated by these systems only work with nonrandomized binaries where all defenses such as ASLR and NX are disabled. Furthermore, they rely on binaries having the specific compiler and operating system combinations of their compiled target program. Marten, in contrast, 1) uses goal-directed conditional branch enforcement to find heap and stack overread and overwrite vulnerabilities deep within the program, 2) leverages information leakage vulnerabilities to bypass full ASLR defenses, 3) gener- ates compact ROP exploits that bypass NX layouts, 4) and generates final exploits

65 that work against stripped binaries compiled using different compilers and operating systems with different stack and heap layouts. Automatic Data Oriented Exploits: FLOWSTITCH is a system that makes exploits through manipulating the data and not the control flow of a program [13]. Their system automatically performs data corruption attacks. These attacks result in privilege escalation attacks, sometimes allow for command execution on the target system, and never allow for code execution. Their exploits only work in the presence of a weak form of ASLR where only the libraries, stack, and heap are randomized but not the text and bss segments. FLOWSTITCH can perform information leakage attacks, but relies on data and code sections which are not protected by randomization and requires the attacker to specify the data that they want to leak. Unlike data oriented exploits, Marten generates remote control flow hijacking ex- ploits against fully randomized binaries. The exploits automatically allow the attacker to gain arbitrary code or command execution on the target server. This capability gives the attacker more flexibility over their attack’s consequences and allows them to hijack the execution of processes that are only accessible through remote vectors. Marten’s exploits also work in the presence of full ASLR and do not require small portions of the process’s code or data segments to be nonrandomized. Marten can leak addresses from a victim process with full randomization enabled and identifies the target data to leak automatically without requiring any attacker interaction. BOPC is another dataflow exploitation system [14]. It requires that the attacker can arbitrarily read memory and can arbitrarily write memory. BOPC is not end- to-end because it does not discover these vulnerabilities. Additionally, BOPC has a much weaker notion of an exploit than Marten. All but three inputs generated by BOPC simply allow the user to control some registers, cause an infinite loop, or cause a program crash. Only three inputs cause the program to call the execve system call and they do not provide the user with an ability to execute arbitrary commands Marten is end-to-end. It both discovers vulnerabilities and exploits them au- tomatically. Marten does not require that the attacker can arbitrarily read or write memory. Marten has a strong notion of an exploit. The exploits generated by Marten

66 allow the user to execute arbitrary commands and code in the context of the victim process. From POC to Exploitable: Revery is a system which takes crashing Proof of Concept (POC) inputs and determines whether they could lead to exploitable con- ditions or not when attacking nonrandomized binaries [38]. This system was only tested on nonrandomized CTF binaries which are extremely simplified, small pro- grams designed for hacking competitions. This system stopped when it could write to an arbitrary address or gained control of the instruction pointer. Revery cannot perform information leakage attacks. Marten is an end to end system which finishes the job of developing a fully func- tional exploit that is effective against stripped, fully randomized binaries protected by modern defenses. These binaries may be generated on other systems and do not need to be compiled by Marten. Additionally, Marten is able to take a benign input and convert it into a POC input that exposes a vulnerability using a goal directed conditional branch enforcement algorithm. Marten is tested against and succeeds in exploiting real applications, not simple toy programs. Marten performs information leakage exploits successfully. Automatic Exploit Hardening: Q is a system that automatically hardens POC exploits against modern defenses by replacing shellcode with ROP chains [29]. Their system’s exploits target the nonrandomized sections of a program protected by a weak form of ASLR that does not randomize the location of the text and bss sections in a binary. The exploits generated by their system either call a library function without control of the arguments, or writes to an arbitrary address and then stops. Q can only use the gadgets available in the binary to generate its chains because it cannot perform information leakage exploits. Marten does not require an existing POC exploit to develop its own exploits. In- stead, Marten takes a benign input to the target program and creates a POC input that exercises a vulnerability automatically. Marten can exploit programs protected by full ASLR using information leakage exploits. Additionally, Marten develops ro- bust, reliable exploits that can achieve arbitrary code or command execution. Marten

67 generates chains using libraries, so it has access to many more gadgets and can build shorter ROP chains. Marten it able to use these libraries because of its ability to perform information leakage exploits. Automatic Buffer Overread Discovery: BORG automatically finds and triggers buffer overreads using symbolic execution and static analysis [19]. BORG generates inputs that cause buffer overreads which do not leak data. Instead, they cause the target applications to crash. Borg does not generate control flow hijacking exploits. BORG does not try to generate inputs for programs with defenses such as full ASLR enabled. Marten is able to automatically find and trigger buffer overreads that do not crash the program. Marten extends this capability to ensure that the data in the overread is sent back to the attacker. From this information, Marten can generate control flow hijacking exploits that bypass full ASLR and other defenses. Goal Directed Conditional Branch Enforcement: DIODE implements a goal- directed conditional branch enforcement algorithm [34]. DIODE uses the algorithm to find integer overflow vulnerabilities in programs [8]. DIODE does not generate exploits of any kind after finding these vulnerabilities. Marten extends the goal-directed conditional branch enforcement algorithm to automatically find and trigger buffer overflow and buffer overread vulnerabilities as well as integer overflows. I generalize the algorithm proposed in [34] so that itcan find any type of vulnerability. Marten uses this capability to generate information leakage and control flow hijacking exploits that bypass full ASLR and other modern defenses. Automatic ROP Chain Generation: A number of other systems have explored the automatic ROP chain generation problem [10, 23, 37, 28, 24, 22]. All of these systems are meant to be interactive and to help a user generate ROP chains. These systems do not generate complete ROP chains. Instead, they assist the attacker by helping them find useful gadgets in the target binary. These systems do nothave the capability to integrate with information leakage exploits. These systems do not attempt to build chains that are robust against changes to the environment.

68 Marten is totally automatic and does not require user interaction after it begins running. Marten’s ROP chains are able to load registers for function arguments and finish the job by calling target functions. Marten’s ROP chains are integrated with its ability to generate information leakage exploits to generate chains that bypass full ASLR and other modern defenses. Marten is capable of generating two types of chains. One that injects and executes arbitrary shellcode and one that calls the execve system call to execute arbitrary commands. Blind ROP: Bittau et al. proposed a system for automatically generating ROP chains for stack buffer overflows against remote targets without access to the source or binary code of the target [3]. Their technique is known as blind ROP (BROP). BROP relies on a server that calls fork without using execve to re-randomize the address space of the child process. Their attack approach relies on brute forcing values on the stack byte by byte. This method causes the target program to crash many times. Their system is incapable of analyzing a program to find vulnerabilities on its own. BROP does not perform information leakage exploits using buffer overreads. Marten is end-to-end. Marten starts with seed inputs and is able to 1) mutate the input to expose a vulnerability, 2) generate an exploit for said vulnerability, and 3) automatically combine information leak and stack overflow exploits to bypass full randomization and other defenses. Marten does not rely on the process calling fork without execve. Marten’s exploits use information leakage to determine address values and do not crash the program by brute forcing them. Just-In-Time Code Reuse: Monrose et al. developed a system that takes arbitrary memory read and arbi- trary memory write vulnerabilities and generates exploits that bypass fine grained ASLR [14]. Their system is not end-to-end. It does not discover the vulnerabilities. Also, the threat model for their system is different. Their system works in the context of attacks on web browsers or document readers that allow considerable control over attacks through scripting languages like JavaScript. Thus, the attacks generated by their system are not remote. Marten is end-to-end and automates the nontrivial task of finding information

69 leak and buffer overflow vulnerabilities. Additionally, Marten does not require access to a scripting interface in the victim process. The exploits generated by Marten do not require that the user open a malicious file or webpage. Instead, Marten works simply by sending and receiving data through sockets. Thus, the exploits generated by Marten work against remote server-based targets.

70 Chapter 10

Conclusion

Address space layout randomization poses a significant obstacle to the successful exploitation of memory corruption vulnerabilities. By automatically discovering and exploiting information leakage vulnerabilities, Marten can successfully derandomize remote randomized target processes. The resulting information about the locations of remote code enables Marten to generate successful ROP chains tailored to the specific randomized addresses of the remote process. Coupled with Marten’s ability to au- tomatically discover buffer overflow vulnerabilities, these ROP chains enable Marten to deliver a fully automatic end to end system that combines multiple vulnerabilities to exploit remote randomized processes. Exploits generated by Marten highlight the success of this approach.

71 72 Bibliography

[1] Sharon Anderson, Alan T Bankier, Bart G Barrell, Maarten HL de Bruijn, Alan R Coulson, Jacques Drouin, Ian C Eperon, Donald P Nierlich, Bruce A Roe, Frederick Sanger, et al. Sequence and organization of the human mitochon- drial genome. Nature, 290(5806):457, 1981. [2] Thanassis Avgerinos, Sang Kil Cha, Brent Lim Tze Hao, and David Brumley. Aeg: Automatic exploit generation. 2011. [3] Andrea Bittau, Adam Belay, Ali Mashtizadeh, David Mazières, and Dan Boneh. Hacking blind. In 2014 IEEE Symposium on Security and Privacy, pages 227– 242. IEEE, 2014. [4] David Brumley, Pongsin Poosankam, Dawn Song, and Jiang Zheng. Automatic patch-based exploit generation is possible: Techniques and implications. In 2008 IEEE Symposium on Security and Privacy (sp 2008), pages 143–157. IEEE, 2008. [5] Sang Kil Cha, Thanassis Avgerinos, Alexandre Rebert, and David Brumley. Un- leashing mayhem on binary code. In 2012 IEEE Symposium on Security and Privacy, pages 380–394. IEEE, 2012. [6] Leonardo De Moura and Nikolaj Bjørner. Z3: An efficient smt solver. In Inter- national conference on Tools and Algorithms for the Construction and Analysis of Systems, pages 337–340. Springer, 2008. [7] Solar Designer. Non-executable user stack. 1997. [8] Will Dietz, Peng Li, John Regehr, and Vikram Adve. Understanding integer overflow in c/c++. ACM Transactions on Software Engineering and Methodology (TOSEM), 25(1):2, 2015. [9] Zakir Durumeric, Frank Li, James Kasten, Johanna Amann, Jethro Beekman, Mathias Payer, Nicolas Weaver, David Adrian, Vern Paxson, Michael Bailey, et al. The matter of heartbleed. In Proceedings of the 2014 conference on internet measurement conference, pages 475–488. ACM, 2014. [10] Andreas Follner, Alexandre Bartel, Hui Peng, Yu-Chen Chang, Kyriakos Is- poglou, Mathias Payer, and Eric Bodden. Pshape: automatically combining gadgets for arbitrary method execution. In International Workshop on Security and Trust Management, pages 212–228. Springer, 2016.

73 [11] Austin Gadient. Cve-2019-16200. https://nvd.nist.gov/vuln/detail/ CVE-2019-16200, 2019.

[12] Mark R. Horton. Standard for interchange of usenet messages. https://tools. ietf.org/html/rfc850, 2019.

[13] Hong Hu, Zheng Leong Chua, Sendroiu Adrian, Prateek Saxena, and Zhenkai Liang. Automatic generation of data-oriented exploits. In 24th {USENIX} Se- curity Symposium ({USENIX} Security 15), pages 177–192, 2015.

[14] Kyriakos K Ispoglou, Bader AlBassam, Trent Jaeger, and Mathias Payer. Block oriented programming: Automating data-only attacks. In Proceedings of the 2018 ACM SIGSAC Conference on Computer and Communications Security, pages 1868–1882. ACM, 2018.

[15] Chris Lattner and Vikram Adve. Llvm: A compilation framework for lifelong pro- gram analysis & transformation. In Proceedings of the international symposium on Code generation and optimization: feedback-directed and runtime optimiza- tion, page 75. IEEE Computer Society, 2004.

[16] Hongjiu Lu. Elf: From the programmer’s perspective, 1995.

[17] Hector Marco-Gisbert and Ismael Ripoll-Ripoll. Exploiting linux and aslr’s weaknesses on 32-and 64-bit systems. BlackHat Asia, 2016.

[18] Nicholas Nethercote and Julian Seward. Valgrind: a framework for heavyweight dynamic binary instrumentation. In ACM Sigplan notices, volume 42, pages 89–100. ACM, 2007.

[19] Matthias Neugschwandtner, Paolo Milani Comparetti, Istvan Haller, and Herbert Bos. The borg: Nanoprobing binaries for buffer overreads. In Proceedings of the 5th ACM Conference on Data and Application Security and Privacy, pages 87– 97. ACM, 2015.

[20] Aleph One. Smashing the stack for fun and profit. Phrack magazine, 7(49):14–16, 1996.

[21] Hilarie Orman. The morris worm: A fifteen-year perspective. IEEE Security & Privacy, 99(5):35–43, 2003.

[22] PAKT. ropc, 2019.

[23] Nguyen Anh Quynh. Optirop: the art of hunting rop gadgets, 2013.

[24] Rapid7. Msfrop, 2019.

[25] Redhat. Hardening elf binaries using relocation read-only (relro). 2012.

[26] Redhat. Position independent executables (pie). 2012.

74 [27] Redhat. Enhance application security with fortify_source. 2014.

[28] Sascha Schirra. Ropper. 2019.

[29] Edward J Schwartz, Thanassis Avgerinos, and David Brumley. Q: Exploit hard- ening made easy. In USENIX Security Symposium, pages 25–41, 2011.

[30] Konstantin Serebryany, Derek Bruening, Alexander Potapenko, and Dmitriy Vyukov. Addresssanitizer: A fast address sanity checker. In Presented as part of the 2012 {USENIX} Annual Technical Conference ({USENIX}{ATC} 12), pages 309–318, 2012.

[31] Fermin J Serna. The info leak era on software exploitation. Black Hat USA, 2012.

[32] Hovav Shacham et al. The geometry of innocent flesh on the bone: return-into- libc without function calls (on the x86). In ACM conference on Computer and communications security, pages 552–561. New York„ 2007.

[33] Hovav Shacham, Matthew Page, Ben Pfaff, Eu-Jin Goh, Nagendra Modadugu, and Dan Boneh. On the effectiveness of address-space randomization. In Pro- ceedings of the 11th ACM conference on Computer and communications security, pages 298–307. ACM, 2004.

[34] Stelios Sidiroglou-Douskos, Eric Lahtinen, Nathan Rittenhouse, Paolo Piselli, Fan Long, Deokhwan Kim, and Martin Rinard. Targeted automatic integer overflow discovery using goal-directed conditional branch enforcement. In ACM Sigplan Notices, volume 50, pages 473–486. ACM, 2015.

[35] Richard Stallman, Roland Pesch, Stan Shebs, et al. Debugging with gdb. Free Software Foundation, 51:02110–1301, 2002.

[36] PaX Team. Pax address space layout randomization (aslr). 2001.

[37] A Wally. nrop, 2019.

[38] Yan Wang, Chao Zhang, Xiaobo Xiang, Zixuan Zhao, Wenjie Li, Xiaorui Gong, Bingchang Liu, Kaixiang Chen, and Wei Zou. Revery: From proof-of-concept to exploitable. In Proceedings of the 2018 ACM SIGSAC Conference on Computer and Communications Security, pages 1914–1927. ACM, 2018.

[39] Matthew Warren and William Hutchinson. Cyber attacks against supply chain management systems: a short note. International Journal of Physical Distribu- tion & Logistics Management, 30(7/8):710–716, 2000.

[40] Rafal Wojtczuk. The advanced return-into-lib (c) exploits: Pax case study. Phrack Magazine, Volume 0x0b, Issue 0x3a, Phile# 0x04 of 0x0e, 2001.

75