• No results found

Detecting Buffer Overflows using Python

N/A
N/A
Protected

Academic year: 2022

Share "Detecting Buffer Overflows using Python"

Copied!
80
0
0

Laster.... (Se fulltekst nå)

Fulltekst

(1)

Detecting Buffer

Overflows using Python

Automating Buffer Overflow Detection and Exploitation using Python framework pwntools Ingeborg Ytrehus

Master’s Thesis, Spring 2020

(2)

This master’s thesis is submitted under the master’s programme Programming and System Architecture, with programme optionInformation Security, at the Department of Informatics, University of Oslo. The scope of the thesis is 30 credits.

(3)

Abstract

This thesis will give an overview of buffer overflow vulnerabilities and will briefly outline some of the existing tools for detecting such vulnerabilities. Possible improvements and future development that could be done on these tools will also be described. A new tool, called Bufferfly, has been developed to to provide improvements for a previous project on automating buffer overflow detection.

Bufferfly is a black box tester and is found suitable for finding and exploiting simple buffer overflow vulnerabilities. It currently supports limited architectures for its target binary and is not able to solve complex buffer overflows, like the ones that are likely to occur in modern software. The tool is therefore not likely to find new, undocumented vulnerabilities, but could be developed into a more full-coverage fuzzer. Improvements for this projcet should be directed towards adding more complex mechanisms for discovering and exploiting different types of buffer overflow vulnerabilities. This could for instance be vulnerabilities in binaries where security protections, such as RELRO, NX and stack canaries, are enabled or where specific interaction with the target binary is required. The tool is written with the intent to facilitate further development and addition of more functionalities. In addition, a separate tool, vuln_create has been created, in order to easily create vulnerable binaries for Bufferfly. Both Bufferfly and vuln_create will be described in detail in this thesis, added as appendices and available on Github [iyt15].

(4)
(5)

Contents

Abstract i

Contents iii

List of Figures v

1 Introduction 1

1.1 Background and Motivation . . . 1

1.2 Scope and Limitations . . . 2

1.3 Outline . . . 3

2 Technical Background 5 2.1 Types of Buffer Overflows and Techniques . . . 5

2.2 Mitigations for buffer overflows . . . 10

2.3 Consequences . . . 13

2.4 Notes on Architecture . . . 13

2.5 CVEs Related to Buffer Overflows . . . 14

3 A Short Timeline of Published Literature Relating to Buffer Overflows 17 3.1 CVE and Other Similar Databases . . . 17

3.2 Documentation of Buffer Overflow Mechanisms and Mitigations 18 3.3 Tools Used for Detecting Buffer Overflows . . . 19

4 Introduction to AutoBOF and Joern 23 4.1 AutoBof - a programmatic approach . . . 23

4.2 Joern - a graph based approach . . . 25

4.3 Difference in Approach for Joern and autoBOF . . . 27

4.4 Further Work for this Project . . . 27

5 Possibe Further Work and Improvements for autoBOF 29 5.1 Effective Use of Existing Tools . . . 29

5.2 Python Version . . . 29

5.3 Code Readability . . . 30

5.4 Configuration and Command Line Arguments . . . 30

5.5 Documentation . . . 30

5.6 Application Execution Time . . . 31

(6)

Contents

5.7 Interacting with GDB and Metasploit . . . 31

6 Bufferfly - Method, Documentation and Usage 33 6.1 Approach for Bufferfly . . . 34

6.2 Testing and Creating Binaries for Testing . . . 35

6.3 Requirements, Configuration and Usage . . . 38

6.4 Potential Usage of Bufferfly . . . 40

6.5 Differences Between Bufferfly and autoBOF . . . 41

6.6 Shortcomings and Further Work . . . 43

7 Conclusion 47 7.1 Summary of Findings . . . 47

7.2 Conclusion . . . 49

Appendices 51

A Source Code for Bufferfly 53

B Source Code for vuln_create 65

Bibliography 69

iv

(7)

List of Figures

2.1 Simple Buffer Overwrite . . . 7

2.2 Stack buffer overflow . . . 8

2.3 Rop Chaining . . . 9

2.4 Return2libc . . . 10

2.5 Turning off NX protection . . . 12

4.1 Code Property Graph used by Joern . . . 26

6.1 Cyclic Pattern Injected in Stack Buffer . . . 34

6.2 Screenshot of vuln_create . . . 37

6.3 Screenshot of Bufferfly’s resultfile/program . . . 40

(8)
(9)

CHAPTER 1

Introduction

1.1 Background and Motivation Goals for this Thesis

The goal for this thesis is to provide a brief overview of buffer overflow vulnerabilities and their history. Part of this thesis is focused on furthering the work that has been done with the tool autoBOF; for this a new tool, Bufferfly, has been created.

Buffer Overflow Vulnerabilities

Buffer overflow vulnerabilities are well-known and widespread and they have an array of negative consequences. They exist in many different forms and there have been many different security protections created for mittigating their impact. Even if these security protections are present, attackers can circumvent them, leading to vulnerable software. Buffer overflow vulnerabilities can lead to arbitrary code execution, program crashes, information leaks and memory corruption and while they are considered to be a thing of the past, they are still present both in legacy software and in newly produced software. This may be due to the fact that they can occur from many different types of mistakes and circumstances. Some buffer overflow vulnerabilities are less obvious, harder to exploit and may require elaborate circumventing of security protections.

Implementing the security protections are only helpful if they are implemen- ted correctly and securely. They also cannot always protect against attacks when code quality is poor. This means that security protections alone are not enough to prevent releasing vulnerable software and security researchers may need security auditing tools to aid detecting vulnerabilities. Because of the increase in complexity, amount of projects and size of these projects, it is fair to assume that both the complexity and work load of examining code has also increased.

Tools for Detecting Buffer Overflows

Buffer overflow vulnerabilities can be detected and prevented by security researchers. In order to facilitiate this, they can be equipped with well suited tools to aid them in this task. Many tools have been created for this and are

(10)

1. Introduction

discussed in this thesis. Joern and Autobof are two already existing tools that can be used for finding buffer overflow vulnerabilities. Autobof is an automation based approach written in Python and its target binary is hardcoded to be the Crossfire application/game. Joern is based on code property graphs and can be used with any language, whether compiled or interpreted. Joern is intended to be a fuzzing tool for analysts examining code and can aid in finding a vast array of different vulnerabilities. In contrast, Autobof is a tool that attempts to give a concrete answer as to whether or not the targeted program is vulnerable to buffer overflows. In many ways, autoBOF simulates the way a code analyst would traditionally look for buffer overflows. AutoBOF will initially attempt to crash the target binary by sending large amounts of data. Once a crash is found, the consequences of the bug is be investigated. Joern, however, will give the security researchers an different set of properties to be used to analyze the program, taking a graph based approach.

Bufferfly

A tool has been created for this thesis, named Bufferfly. This has been loosely based on the same approach as autoBOF. The properties, shortcomings and suggestions for further work of this tool will be discussed in this paper.

1.2 Scope and Limitations

Architecture and Source Code Language

The scope of this thesis will as a rule be limited to C/C++ programs compiled for 32 bit x86 architecture on Unix systems. This includes all chapters of this paper. If other architectures or systems are discussed this is specifically noted during its discussion. This is chosen for simplicity. For the developed tool, Bufferfly, support for other architectures may be expanded upon at a later point in time.

Language of Literature Discussed

The literature chapter is limited to published works, articles and internet resources written in English. Non-English literature on the subject is likely to exist and likely to be valuable for a more comprehensive understanding of the background of this paper. However, the amount of literature found in written in English has, however, been considered to be enough for this paper.

Other Reverse Engineering Tools

There are many other tools used for reverse engineering that can be used to identify buffer overflow vulnerabilities, other than the ones discussed in this thesis. These are tools like Radare2, Ghidra, Angr and many more. These tools work by disassembling the compiled code to assembly code and often presenting the result as control flow graphs. Many of these tools are capable of performing both static and dynamic analysis. This paper will not focus on these tools, but will focus on autoBOF, Joern and the newly developed tool, Bufferfly.

2

(11)

1.3. Outline

1.3 Outline

The rest of this paper is organised as follows:

Chapter 2 contains a brief technical explanation of buffer overflow vulnerabil- ities, how they occur and how they can be prevented. This is considered technical background for the following chapters. If the reader feels that they are familiar with the subject matter, they may skip reading this chapter.

Chapter 3 will describe the history of discoveries related to buffer overflows and the tools that can be used to discover them. Like Chapter 2, this chapter is included in order to add background to the need for effective tools for buffer overflow vulnerability detection.

Chapter 4 covers the background of autoBOF and Joern tools. These are two tools that can be used to find buffer overflow vulnerabilities. This chapter includes a short history of each tool, description of usage and applications. In addition the two different approaches of autoBOF and Joern are compared.

Chapter 5 describes possible improvements for autoBOF and how the tool can be further devloped. These areas are the basis of Chapter 6.

Chapter 6 covers the tool created for this paper, Bufferfly. The tool is based on the vulnerability detection techniques used by autoBOF. The documentation, usage and possible further development for Bufferfly will be discussed and evaluated in this chapters.

Chapter 7 contains the conclusion and the summary of the findings from this project.

Appendix A contains the source code for Bufferfly, the tool created for this paper. As mentioned earlier, this tool will be discovered in Chapter 6.

Appendix B contains the source code of the python script for creating vulnerable binaries. The binaries created with this tool was used for testing the functionality of Bufferfly.

(12)
(13)

CHAPTER 2

Technical Background

A short technical background on buffer overflows, their mitigations and consequences are presented in this chapter. This information is required for understanding how to protect against and detect buffer overflow vulnerabilities and it is therefore recommended to read this chapter if the reader lacks background knowledge of the subject. If the reader is familiar with the subject, however, this chapter should not be the focus of the paper.

2.1 Types of Buffer Overflows and Techniques

Buffer overflows occur when more data is written into a buffer than the amount of memory that has been allocated to that buffer. Buffer overflows are also known as buffer overruns, but they are called buffer overflows throughout this thesis. Buffer overflows are often caused by improper handling of user input.

This could for instance be by using unsafe functions such as gets or strcpy [17][19a].

Buffer overflows are vulnerabilities because they allow attackers to overwrite the data placed after the vulnerable buffer, which could be return address values on the stack and memory data on the heap. This could cause memory corruption, privilege escalation, denial of service or arbitrary code execution.

Buffer overflow vulnerabilities exist in different forms, which require different mitigations and have different consequences if they are successfully exploited.

The buffer overflows mainly occur either in the stack memory or the heap memory. The memory segment in which they occur may affect the mitigations and consequences of an attack. [Dec05][One96]

It should be noted that while the types of attack explained in this section can occur, modern software are usually compiled with mitigations that will hinder or eliminate the possibility of successfully performing these attacks. This does mean that special circumstances must be in place if these types of buffer overflow exploits are to be successful in modern software. These mitigations are explained in the subsection "2.2 Mitigations for Buffer Overflows".

(14)

2. Technical Background

Stack based Buffer Overflow

Stack based buffer overflows occur when excessive data is written to buffers placed directly on the stack. This can occur when user input is not handled correctly. There are several examples of this, for instance using unsafe functions such as the "gets" function, which only terminates input reading when a newline character is encountered [17]. This means that for instance 50 bytes of data can be written into a 20 byte array, as long as none of those 50 bytes are newline characters. The same vulnerability will occur if using the read function and taking in more input than the size of the buffer that is being read into.

Example of vulnerable code is shown below in Listing 1.

Listing 1: Simple Example of Vulnerable C Program. Note that this program must disable stack canary and NX-protection before compilation to be exploited in the manner which is described in Figure 2.1 and Figure 2.2.

#include <stdio.h>

#include <unistd.h>

int main(void) {

int inty = 32;

char buf[8];

printf("Getting input...");

read(STDIN_FILENO, buf, 64);

return 0;

}

When the running this program the stack will be built with the integer "inty"

placed after the buffer "buf". After this, there are stack values that are used to define the address that will be returned to once the current function returns, as well as as arguments to the current and past functions. [One96][Dec05] If more bytes are written than what is allocated to the buffer "buf", they will be written past the bounds of the buffer and onto the integer "inty" and the rest of the stack values. This could therefore be used to manipulate the return value. Figure 2.1 shows how the values of "buf", "inty" and the return value would look like if a user gave the string "AAAAAAAABBBBCCCC". The last bytes, containing four "C"s, will overwrite the return value. These bytes could be arbitrarily chosen by an attacker. This example is illustrated in Figure 2.1 and a similar example is illustrated in Figure 2.2.

Typical ways of exploiting this vulnerability includes overwriting the return address to some other address the attacker may prefer. This could for instance be the address of a function in the libc library; an example of this is shown in Figure 2.4. Because the attacker will have access to the stack memory, shellcode could also be injected onto the stack buffer and the return address could be overwritten with the address of that stack buffer. If this attack is done successfully, the shellcode placed on the stack will be executed when the program tries to return from the current function. A limitation that might occur is that there could be a small amount of bytes between the return address 6

(15)

2.1. Types of Buffer Overflows and Techniques

Figure 2.1: Illustration of the buffer overflow that could occur with the code example shown in Listing 1. Changing the amount of bytes read in the function

"read" to 8 bytes, would make the program safe from overflows and result in the value of inty and the return address remaining unchanged.

being overwritten and the vulnerable buffer. This would limit the size of the shellcode that can be placed on the stack. [One96][Kim03]

Heap based Buffer Overflow

Heap based buffer overflows occur when excessive data is written to buffers placed on the heap. This gives different opportunities to attackers than those acquired from stack based overflow vulnerabilities, partly because the memory on the heap is allocated and de-allocated dynamically during program execution [ano01]. If larger memory areas need to be allocated, they may be more likely to be allocated on the heap rather than the stack. This may partly be due to the fact that the memory area of the heap area is in most systems larger than that of the stack area. In addition, buffers that need to be passed through different stack frames will be placed on the heap. This also means that, in some cases, buffer overflows that occur on the heap can be more complicated than those that occur on the stack. The buffer on the heap may have many different methods that are performed on them than those on the stack, including more writing and reading from it, which may also increase the likelihood that one of these methods includes a vulnerability. [cwe][swi09]

Because the stack contains values such as the next return value, overflowing a stack buffer is more likely to cause program flow redirection than overflowing a buffer on the heap. There are still methods exploiting heap buffers that will lead to code execution, memory corruption and program crashes.[ano01][cwe][swi09]

ROP (Return Oriented Programming)

Return oriented programming (ROP) is a technique where each payload in the buffer overflow exploit is built from instruction sequences found in the programs’s memory. These instructions are commonly referred to as "gadgets"

(16)

2. Technical Background

Figure 2.2: The stack before and after a stack buffer overflow exploit. Here the return address is overwritten with a rop gadget containing the instruction "jmp

% esp", which will cause the EIP to jump to the instruction at the the curren esp. The esp will at this point contain the shellcode inserted to the vulnerable buffer.

and are instruction sequences that end with a return instruction. Gadgets are found as part of a function written or included in the binary, and by extent any included libraries. Because of the return statement, these gadgets can be chained together as each gadget will in turn be the next return address. An example of ROP is shown in figure 2.3. This type of attack evades many of the mitigations put in place against buffer overflows and can be used to run arbitrary code. These mitigations are described in Section 2.2 "Mitigations for buffer overflows" of this chapter. Because the gadgets need to be in memory, a larger binary with bigger code bases makes it more likely too find useful gadgets. With a sufficiently large code base, gadgets can be used to create Turing-complete functionality. This is because large code bases would allow for gadgets of enough different assembly instructions, to provide any wanted functionality.[CW14][LEs17][Sha07]

Return to libc (ret2libc)

Return to libc (ret2libc) has similarities to ROP and is a method where the return address is overwritten with the address of a function in libc. This is also possible to do with other included libraries, but libc has many useful 8

(17)

2.1. Types of Buffer Overflows and Techniques

Figure 2.3: Example of the stack during a buffer overflow attack using return oriented programming. The purple areas of the stack contain gadgets, the yellow areas contain values being used for register values and the green area contains a syscall (system call). Note that the actual values for in the purple areas on the stack are the addresses of the gadget instruction written in the example. They are not the values of the instructions themselves. [LEs17]

functions and is commonly included in projcets. Ret2libc can be used for calling known functions after setting up the function arguments. This will break the protection given by a non-executable stack, that is put into place to mitigate against running shellcode on the stack, because the attacker does not attempt to run injected shellcode on the stack. Mitigating buffer overflows by using non-executable stack is described in a later section of this chapter. [Des]

Heap Spraying

Heap spraying is a technique that may facilitate buffer overflows. In order to

"spray the heap", an attacker adds the payload they wish to execute to the heap multiple times so that there will be many instances of this payload on the heap. The attacker then attempts to redirect the program to anywhere on the heap, in hopes of landing in one of the injected payloads. This can lead to an attacker achieving arbitrary code execution. In order for this approach to be effective, the payload often contains a nop-sled. A nop-sled is a list of

(18)

2. Technical Background

Figure 2.4: Example of a buffer overflow attack using the return2libc technique.

The return address is being overwritten with the known address for the system() function and the address of the string "/bin/sh"

instructions or gadgets containing a nop-instruction, instructing the computer to do a no-operation instruction and jump to the next instruction. This technique can be used to increase the success rates of many different types of vulnerability exploits, but is still a noteworthy technique that is important for heap buffer overflows.[cor31]

2.2 Mitigations for buffer overflows

Because of the severe possible consequences of exploited buffer overflow vulner- abilities, there has been developed several mitigations for them. The mitigations can be used to harden different aspects of the binary. These aspects can be roughly divided into the following 3 categories. [Sid28][MR13][Cow+12][Kim03]

Sanity checksin the heap manager or in the stack, such as stack canaries.

∗ Separating code and data, so that certain areas of memory are not executable. This is described as modifying RWX permissions(Read, Write, Execute permissions) in the remainder of this chapter.

Randomization of memory areas and offsets so that functions or strings are not found at a predictable offset. This can be achieved with features such as ASLR (Address Space Layout Randomization)

10

(19)

2.2. Mitigations for buffer overflows

These mitigations are explained in short in this section and, while they have an effect on many different vulnerabilities, this section is focused on the effect these mitigations have on specifically buffer overflow exploit attempts.

Sanity Checks - Stack Canaries

A stack canary is a value placed between the allocated buffer and the subsequent memory. These canaries are analogous to the canaries used for checking the air quality in coal mines. Any changes to the value of the canary indicate that the integrity of the data after the buffer (registry values for stack based buffer overflows), much like a dead canary would indicate that the mine workers might be in danger. If the integrity of the stack canary is broken, the program will terminate so that an attacker cannot abuse the stack. [MR13][Cow+12]

Sanity Checks - Memory Heap Managers

Sanity checks can be placed on both stack and heap buffers, although for heap buffers this requires more of an overhead during allocation of heap memory.

Canary values or similar schemes will need to be added by the memory managers such as malloc.[ano01]

RWX Permissions - Non-Executable Stack (NX) or Heap

Another mitigation is separating the memory into areas containing either code or data, so that areas containing program data are non-executable. This includes making the memory area of the stack (NX-protection) or the heap non-executable, so that if shellcode is written into the buffer, it cannot be executed. This ensures that any memory area that can be manipulated by the user, will not be executed. There are still known ways to circumvent this mitigation, for example by re-enabling stack execution during run-time execution. For instance, if an attacker uses a ret2libc-technique they can return to the C function mprotect (found in mman.h) to give executable rights to the areas of the stack. This means that by invoking mprotect, the stack will be executable after the shellcode has already been written to the stack. Once the mprotect function exits, the attacker can add the next return address to the shellcode on the stack, successfully running the attacker’s shellcode. An example of the stack during this attack is illustrated in 2.5. Any memory on the heap that is writeable by the user could also be made non-executable to achieve the same protection for heap overflows as NX would achieve for stack overflows.[Kim03]

RWX Permissions - Relocation Read-Only (RELRO)

RELRO (Relocation Read-Only) is a technique where GOT (Global Offset Table) is marked as read-only. RELRO can be implemented in two modes, either partial or full. Full RELRO causes the entire GOT to be read-only. This removes attacks where the GOT address of a specific function is overwritten with a different function address or ROP gadget. Full RELRO is therefore the most effective in ELF (Extensible Linking Format) hardening, but may increase the time taken to start the program. This is because the linker will create all

(20)

2. Technical Background

Figure 2.5: Stack execution rights being re-enabled by invoking the mprotect function found in mmap.h. This specific example will result in first enabling stack execution, then executing shellcode on the stack. For this to work, the attacker needs to know or guess the address of the stack and the function mprotect.

the GOT entries before entering the main function. With either full or partial relro, an attempt to overwrite any GOT entry will cause a segmentation fault [Sid28]. Partial RELRO ensures that the GOT is placed before the BSS segment, removing the possibility of overflowing variables in the GOT entries during runtime. Partial RELRO is normally the default setting in linux distrobutions [Sid28].

Memory Randomization - Address space layout randomization (ASLR)

The memory layout can be randomized so that the heap, stack and libraries do not start at a fixed address. This makes it more challenging for attackers to find the address of functions, gadgets and the buffer being overflowed. [swi09]

Memory Randomization - Position Independent Executable (PIE)

Enabling PIE for a binary will cause the binary and its dependencies to be loaded into randomized locations within virtual memory when the application is executed. The memory addresses will therefore be different each time 12

(21)

2.3. Consequences

the program is run. When enabling both PIE and ASLR, the programs memory organization will be more diverse, making attacks against the program harder.[Red28][Mil12]

Other - Compartmentalization

Compartmentalization is a different type of mitigation than those described above and will in this context mean letting each running service/program run in a separate virtual environment. With this approach the program will not have access to other processes or resources than those that are required to run the program. This will minimize the consequences of arbitrary code execution, because if an attacker gains access to a shell on the server via buffer overflow exploits, they will not be able to access the rest of the system.

Compartmentalization will not by itself protect against denial of service attacks.

Compartmentalization can for instance be achieved by using Docker or similar tools [20b]. It should also be noted that a misconfigured Docker instance still can be broken out of, but if correctly configured, Docker can still be added as an extra layer of security [Avr21] [19b].

2.3 Consequences

The consequences of an exploited buffer overflow vulnerability depend on whether the overflow occurs in heap memory or in stack memory. In either case the two main categories of consequences are program crashes and arbitrary code execution. Program crashes will mainly affect the program’s availability and possibly render some of its functionality non-functioning, depending on where in the program the overflow is located. These program crashes can be caused by input either with non-malicious or malicious intent. In the case of a non-malicious user crashing the program, the user is also unlikely to receive a useful error message, which is not especially user friendly.

Through arbitrary code execution, any security aspect can be attacked.

Arbitrary code execution could also lead to lack of availability, through intentional, malicious shellcode or flow redirecting to cause a program malfunction. [One96][cwe][Kim03]

2.4 Notes on Architecture

Attacks and analysis of buffer overflows will depend on the architecture that the binary has been compiled for. This means that certain techniques and tools are limited to a subset of architectures. In addition, security protective measures such as ASLR and DEP, may be implemented differently in the different architectures. Security mechanisms that are enabled by default also varies between architectures [swi09][Red28][Mil12].

Another possible consideration is the assembly language used for writing shellcode (if shellcode is included in the attack). This needs to be written in the same language as that of the vulnerable binary. This is because the instruction set and the calling conventions is different for different architectures. Specifically

(22)

2. Technical Background

for x86 architectures, the differences in calling convention for 32 bit and 64 bit processors, means that they require different approaches while setting up buffer overflow exploits. For 64 bit binaries, the arguments for functions are placed in registers and not as part of the call stack. This means that successfully calling known functions as part of the payload for buffer overflows is more complicated and requires more manipulation for 64 bit binaries than for 32 bit binaries.

[Fog30]

2.5 CVEs Related to Buffer Overflows

Table 2.1 shows a list of CVEs relating to buffer overflows. The list is incomplete and has been assembled to show real world examples of the variety of consequences caused by buffer overflow vulnerabilities. They are placed in chronological order, and not in order of criticality or relevance. As can be seen from the CVE codes, there are vulnerabilities relating to buffer overflows that are still being discovered in present time. All CVEs can be found on https://cve.mitre.org.

14

(23)

2.5. CVEs Related to Buffer Overflows

CVE-2010-3396 A buffer overflow was found in Kingsoft An- tivirus for certain versions that allows local users to execute arbitrary code via a specific- ally crafted argument.

CVE-2014-9761 Stack buffer overflows in the GNU C Library were found for certain versions allow context- dependent attackers to either cause an applic- ation crash or possibly achieve arbitrary code execution.

CVE-2016-9066 A buffer overflow resulting in a potentially ex- ploitable crash due to memory allocation issues when handling large amounts of incoming data.

This vulnerability affects some versions of Fire- fox and Thunderbird

CVE-2018-3898 A specifically crafted QR code can cause a buffer overflow in the scanning functionality fo the Yi Home Camera. This can result in code execution.

CVE-2018-5674 A specifically crafted, malicious page or file could cause an overflow of a heap-based buffer, when opened with some versions of Phantom- PDF or Foxit Reader. Opening the file requires user interaction andthe overflow could be used to execute code as the current process.

CVE-2019-10164 Certain versions of PostgreSQL let authentic- ated users overflow a stack-based buffer while changing their user’s password. This could lead to arbitrary code execution on the PostgreSQL operating system account.

CVE-2020-3172 A vulnerability caused by insufficently valid- ated Cisco Discovery Protocol packet headers exist in a feature of various Cisco software.

This could lead to arbitrary code execution as root user or denial of service on affected Cisco devices. A specific packet header must be sent to an adjacent device (both attacker and the affected device must be on the same broadcast domain) in order to exploit this vulnerability.

CVE-2020-0504 Certain versions of Intel(R) Graphics Drivers have a buffer overflow vulnerability that could allow an authenticated user to enable escala- tion of privilege and denial of service.

Table 2.1: Table of CVEs Relating to Buffer Overflows

(24)
(25)

CHAPTER 3

A Short Timeline of Published Literature Relating to Buffer

Overflows

This chapter contains a short literature summary on the subject of buffer overflows. It will also briefly cover some tools and methods used to discover these vulnerabilities. Something that can be learned from looking at the history of reports written about these vulnerabilities is that some of them were so-called 0-days, meaning that the vulnerability was not known publicly before the attack. Not all malware exploits new, groundbreaking vulnerabilties; in some exploits publicly disclosed and patched vulnerabilities are exploited. For these exploits, the main mitigation could be considered to be better patching policy.

It is fair to assume that for the cases were 0-days are exploited, giving security researchers better tools might increase the rate at which these vulnerabilities are being discovered and patched, before software is released to production and public use. If security researchers are employed with effective tools and are in the picture during the process of software development, they may be in a better position for discovering software security flaws before a potentially malicious actor is able to discover them.[Mee25]

Because the vulnerabilities listed here are often discovered as part of an attack on vulnerable software, most of the literature on buffer overflows are papers or online resources related to attacks on specific software or malware exploiting commonly used software or libraries. These resources have historically not been included in academic research. This may be caused by the fact that online sources and mailing lists posts are transient by nature and therefore not ideal sources for academic works.[Mee25]

3.1 CVE and Other Similar Databases

CVE was publicly launched in September 1999 and is a database for publicly disclosed cybersecurity vulnerabilities. The concept of this database is based on a white paper released in January 1999, named "Towards a Common Enumeration of Vulnerabilities". As a consequence of implementing this CVE, a much more comprehensive and united vulnerability database than previously seen, has been created. A shortcoming of this system as a historic database

(26)

3. A Short Timeline of Published Literature Relating to Buffer Overflows

for vulnerabilities is that the level of abstraction is fairly high. Many CVEs are described as only having a "buffer overflow" or "SQL injection", but does not necessarily provide any more details than this. This means that in order to find more detailed descriptions, one has to look for documentation in other sources. So while there have been many buffer overflow vulnerabilities assigned a CVE-number within the timeline described below, this section is focused on cases where buffer overflows as a concept have been further documented. [Dav99]

The Open Source Vulnerability Database (OSVDB) was an inde- pendent, open-source database containing descriptions of vulnerabilities, similar to those of CVE. OSVDB was created in March 2004 and shut down in April 2016. A major difference between CVE and OSVDB was that OSVDB accepted a much larger amount of vulnerabilities. The database was more comprehensive and in some cases more detailed, including solutions and detailed descriptions for some of the vulnerability entries. Because the database is no longer alive, much of this information is lost. Some of the entries and data related to them can still be found in other sources.[Gol07]

3.2 Documentation of Buffer Overflow Mechanisms and Mitigations

1972 - First Documented Case of a Buffer Overflow Vulnerability

The earliest documented description of a buffer overflow attack was in 1972, in a publication named "Computer Security Technology Planning Study".

The following was written to describe a functionality that allowed moving information between system and user space: "The code performing this function does not check the source and destination addresses properly, permitting portions of the monitor to be overlaid by the user. This can be used to inject code into the monitor that will permit the user to seize control of the machine." The paper then goes on to explain an attack that could be made on this system, using the vulnerable function handling the input. [And72]

1988 - Morris Worm and Related Vulnerabilities in finger

The next big thing happening in the realm of buffer overflows was in 1988 with the famous Morris Worm. This was the first documented case of a computer worm. It exploited a buffer overflow in the Unix service finger, a simple network protocol for exchanging user information. finger was using an insecure protocol, gets, for getting user input. Because this function does not limit the amount of bytes read from the program input source, but rather stops at inputted newlines, it allows for overwriting the intended buffer. [See]

1995 - Vulnerabilities in NCSA HTTPD 1.3

A stack buffer overflow occuring in NCSA HTTPD 1. was warned about in the Bugtraq mailing list by Thomas Lopatic. This overflow occurred in strcopy, a function used for copying the contents of a buffer into another buffer. The problem with this function as that it does not specify the size of the buffer that 18

(27)

3.3. Tools Used for Detecting Buffer Overflows

will be copied, and cannot guarantee that the buffer it is being copied into is large enough to not be overrun. [Lop95]

1996 - Smashing The Stack For Fun And Profit

A famous article written in 1996 by Aleph One is the documented stack buffer overflows. This was structured as a detailed guide to create an exploit for such flaws. [One96]

2001 - Code Red

The Code Red worm was a server jamming worm released in July 2001 and exploited unchecked buffers in Microsofts Index Server ISAPI Extension. A patch for this had been posted earlier as MS01-033, but not all systems where patched at the time of attack [Mic01]. This is different from, for instance, the Morris worm, where the vulnerabilities exploited existed in the most recent version of the software and the vulnerability was not archived or assigned a vulnerability number or code.

2003 - SQL Slammer

SQL Slammer was a computer worm discovered in 2003 that exploited a buffer overflow in Microsofts SQL Server and Desktop Engine. Like Code Red Worm, a patch notice for this buffer vulnerability was already available when the attack occurred. The patch was released by Microsoft as MS02-061 in July 2002, around 6 months earlier, after security expert David Litchfield reported the issue to Microsoft. The SQL slammer still caused major disruption, as many systems were not patched. [Mic02]

Later Examples

At later points in time, buffer overflow vulnerabilities have been discovered in new and old software and these have later been exploited with malicious intent. Refer to Table 2.1 in the previous chapter for a short, incomplete list of examples of CVEs relating to buffer overflows. The complete list of buffer overflow can be found on CVEs website: cve.mitre.org.

3.3 Tools Used for Detecting Buffer Overflows

Several tools and methods exist for detecting vulnerabilities by analyzing source code and binaries. The main categories of tools used for detecting buffer overflow vulnerabilities are described below and two select tools, autoBOF and Joern, are discussed further in Chapter 4.

Below is a list of different categories of security code audit tools, taken from a text book of buffer overflow attacks from 2005 [Dec05]. In truth, many modern tools used today will fit in more than one category, so the list below should be considered a very rough categorization of tools.

Static code analyzersThese tools can range from scanning the source code for known vulnerable functions, such as gets or strcopy to more

(28)

3. A Short Timeline of Published Literature Relating to Buffer Overflows

complex, semantic checkers that look for context as well as the functions used. These semantic code checkers can discover cases where so-called safe functions are used unsafely. A problem with some of these tools is that they can produce a large amount of false positives which, if the software being analyzed is large, can make it difficult for the security auditor to prioritize high risk areas of the source code. A simple example of this approach is grepping after a specific function name. A similar approach can also be done on assembly level and an early example of this is Bugscan. Static analysis has been in use for vulnerability detection since the early 2000s. [LE01]

Dynamic code analyzersThis category includes tracers, such as ltrace and strace. These tools are used as a wrapper around the target binary, and the behaviour of the target binary can be studied. This includes monitoring system calls (strace), library functions (ltrace) or heap memory usage (Valgrind). These tools can be time consuming, but will yield useful information about the target binary.

Reverse engineering tools and debuggers These tools work by disassembling binaries to assembly code so that it can be read and better understood. Some tools also attempt to represent the code in more readable code or with program flow graphs. This is done in order to learn more about the programs control flow and could in turn lead to discoveries about vulnerabilities in the software. Examples include gdb, Ghidra, Radare/Cutter or IDA [08].

Machine learning for static source code or binary analysisTools that apply machine learning to properties of the source code or binary.

This is a relatively more novel method than the other methods mentioned here, but shows some promise as a supplemental approach. [CV18]

Black box testing/fuzzingThese tools have an approach that involves sending invalid data, either as large amount of data or invalid characters, in order to attempt to crash the target binary. This is also a method that is sometimes used as part of a test driven development approach, as a method of specifying how the target binary should treat invalid user input.

For software projects developed with insufficient testing, this approach can yield some relatively simple, easy-to-fix vulnerabilities.

Tools Specifically Geared Towards Buffer Overflow Vulnerabilities

The tools described above are not necessarily, specifically geared towards finding buffer overflow vulnerabilities, but can be used for discovering all types of bugs and vulnerabilities. Below, two tools that where created for this purpose will be introduced. These are also the two tools that are discussed in further detail in the next chapter.

autoBOF

autoBOF was developed in 2019 as part of a master thesis. It falls into the category of black box testing tools and has a more programmatic approach than Joern. It is described as an automation of buffer overflow exploitation. As 20

(29)

3.3. Tools Used for Detecting Buffer Overflows

a tool, it is a lot more specifically geared to buffer overflow vulnerabilities than Joern. [Rai19]

Joern

Joern is a tool written for a PhD thesis in 2012. It makes use of machine learning and code property graphs, where several different types of property graphs describing the program are combined and analyzed to give further insight into the inner workings of the analyzed program. This deeper understanding of the program is acquired in order to better discover bugs and vulnerabilities.

The tool has since been developed to work for different types of vulnerabilities, but was originally geared towards recognizing buffer overflows. [Yam15]

(30)
(31)

CHAPTER 4

Introduction to AutoBOF and Joern

Two select tools, autoBOF and Joern, are described in this chapter. They have differing approaches for vulnerability detection and use cases, which are discussed.

4.1 AutoBof - a programmatic approach

AutoBOF is a tool written as part of a master thesis in 2019, which covers automation of buffer overflow exploitation [Rai19]. The project is written in Python and makes use of some other well known tools, such as gdb and the Metasploit framework. It was originally intended to support cross-platform operations and to exploit target binaries remotely. Every piece of information written in this chapter on how the tool has been developed and designed has been found on a blog post by the author of the tool and the github page for the tool. [Rai19][Dis19]

autoBOFs Approach

autoBOF automates an approach similar to one that could done manually by security researchers when looking for buffer overflows. The approach that the program is built upon is summarized as the following steps:

1. The target is fuzzed, in an attempt to cause a program crash.

2. If crash is successful, the exact amount of bytes required to cause a crash is found. If crash does not occur, the program exits.

3. The program tries to figure out which characters are "bad" characters.

These are characters that are processed differently than expected, or differently than other, legitimate characters. This might include newlines or null-bytes or many other characters.

4. A rop-gadget containing "jmp esp" is looked for. This is used to redirect the program flow to the shellcode that is placed on the stack.

5. The payload is assembled from shellcode and rop-gadget with instruction

"jmp esp".

(32)

4. Introduction to AutoBOF and Joern

Step number 2 is done because knowing the exact amount of bytes required to cause an overflow is a requirement for knowing which values are being overwritten on which number input byte. It is also required for knowing how much space there is between the start of the buffer being overflowed and the return value. For an exploit where shellcode is placed on the stack, this amount of bytes is the size of the shellcode that can be written and executed. Limiting the size of the shellcode might limit the functionality that the shellcode could achieve, and therefore that the attacker can achieve.

Bad characters are found by giving all possible bytes (from 0x00 to 0xff) to the program and seeing how the target binary reacts. If a character is processed differently than expected, it is added to a list of "bad" characters. This list is later used to ensure that the payload does not contain any of the "bad"

characters. This is added as a measure to ensure that the payload is read by the program in its entirety.

The program relies on external tools, like gdb and the Metasploit framework.

The values that the program finds with Metasploit, like addresses of rop-gadgets and size of buffer, are saved temporarily in text files. These files are deleted before the program exits. Once the program has fully assembled a payload, the finished payload will also be written to a text file. [Rai19][Dis19]

Configuration

The configurations/command line arguments that can be set are the following:

start- initial data sequence including spaces. This sequence is added at the start of the generated payload.

end- any post-payload data sequence including spaces. The sequence is added at the end of the generated payload.

lengthMin- minimum length of the buffer

lengthMax- maximum length of the buffer

increment - amount of bytes to increment the test buffer with each attempt.

targetIP- remote IP that will be connected to when payload is generated.

targetPort - remote port that will be connected to if the payload is successfully is generated.

localIP- local IP for connecting to while testing if the generated payload is effective.

shellPort - local port for connecting to while testing if the generated payload is effective.

payloadAttempts- maximum attempts at generating payload for the target binary. If this number of attempts is exceeded, the program will exit.

24

(33)

4.2. Joern - a graph based approach

exploitName- path to the file where the generated payload is saved to.

silent - level of verbosity. Can be set to on or off and will affect the amount of information sent to stdout.

Possible Use Cases

The program could be used to find simple buffer oveflow bugs, like the one described in figure 2.2. Exploiting these types of overflow vulnerabilities require that stack execution is either not enabled or can be turned off. Because these types of vulnerabilties occur infrequently in the wild, the tool may not be considered very useful in bug hunting. The author of the program states that it could be used for solving tasks given in educational or certification programs.

He also argues that this might be considered cheating, as using the tool does not prove that the user understands the problem they are trying to solve.[Rai19]

AutoBOFs Authors Evaluation and Conclusion

The author concludes that autoBOF may not be useful in all cases and that the largest outcome might be the learning outcome for the author. The type of overflow that autoBOF detects is a fairly simple one, which is not necessarily likely to be found in the wild. The program is not currently cross-platform, which was the original intention of the author. [Rai19]

Similar Projects

As a side note, there are numerous projects online that are similar to autoBOF.

These are usually tools that uses more or less the same approach and many of these state that their purpose is for solving CTF (Capture the Flag) tasks more easily.[20d]This goal is similar to the goal that security analysts may have while, manually looking for buffer overflow vulnerabilities in code that is in active use. The main difference between these two goals is that many of the CTF tasks that contain buffer overflows contain vulnerabilities that are written to be found and are well-known. The vulnerabilities being used for CTFs are likely to be more obvious than those occurring in code used in production software.

An example of a similar tool is found at https://github.com/0xfml/autobof.

This has the same name as the tool described in this chapter, but is written by a different author. The approach has some similarities.

4.2 Joern - a graph based approach

Joern is an application that has been developed since 2013 as part of the PhD thesis on pattern-based vulnerability discovery via code property graphs for Fabian Yamaguchi.[Yam15] The author has since worked on Ocular with shiftleft.io, which shares the same underlying technology with Joern. He has also been working on a partial open-sourcing of this underlying technology [Shi20a]. The open-source project is called Joern-Reborn [Shi20b].

These tools are tools that gives guidance to the security researchers looking for vulnerabilities of different types. The focus of this tool is to gain a better

(34)

4. Introduction to AutoBOF and Joern

understanding of the code of the given program.[Shi20b]

Code Property Graphs

Joern combines many different types of graph representations of the code base, including data represented in program dependency graphs, dominator trees and class diagrams. This provides a representation that considers the syntax, the control flow and the data flow of the application being analyzed. These code property graphs give a unique perspective of the program being analyzed.

These are stored and queried using graph database technology. [Yam15]

Figure 4.1: Visualization of a code property graph. This example is taken from the PhD thesis by Fabian Yamaguchi, which describes the technology behind Joern. [Yam15]

Cross Platform Compatibility

Joern and the underlying technologies can be configured to different environ- ments, architectures and languages. A similar approach to that of Joern has also been used to detect malware in android application. This approach shows promising results and speaks to how versatile the approach used is.[Gas+13]

Tuning

Joern can be tuned to the environment that it is used in, as to reduce the amount of false positives. This is very useful for tools of this kind, so that more effort can be placed on matches that are more likely to be real security issues and less effort is placed on false positives. If the false positive rate is kept to a minimum, all matches can be examined thoroughly and real security risks are more likely to be discovered.

Joern also has a library of vulnerability patterns for the most common frameworks. This means that it can be "pre-tuned" to the environment before starting examination and will work as a more efficient fuzzer for the specific environment[Shi20b].

26

(35)

4.3. Difference in Approach for Joern and autoBOF

4.3 Difference in Approach for Joern and autoBOF

Based on the information gathered about Joern and autoBOF, Joern seems to be better suited for larger, more complicated binaries where bugs are more complicated. It also seems like it has a wider range of use cases and application areas. In contrast, autoBOF seeks to provide a concrete res- ults that will show whether or not the target binary is vulnerable. It also has a much more specific approach, testing only against one type of buffer overflow vulnerability. This naturally limits the type of target binaries. As discussed above, Joern can be configured to recognize many different types of vulnerabilities. This means that, in terms of buffer overflows, autoBOF is likely to have a higher tendency for false negatives. In contrast, Joern, if not configured correctly, may have a large number of false positives, leading to noise.

4.4 Further Work for this Project

While it seems that Joern is the most promising of these two tools and has the widest area of usage, autoBOF seems to have the most potential for improvement within the scope of this thesis. It has therefore been decided that areas of autoBOF which can be improved upon (see Chapter 5) is described and later implemented (see Chapter 6).

(36)
(37)

CHAPTER 5

Possibe Further Work and Improvements for autoBOF

While autoBOF does solve the problem it was designed for, it has several aspects that are problematic or sub-optimal. These aspects are identified and discussed in this chapter. All of the information on how the design of autoBOF is retrieved from the author’s github page for autoBOF and from a blog entry about the same tool [Rai19][Dis19]. A new tool has been created for this thesis, in an attempt to improve upon some of these aspects. This tool will be described in Chapter 6.

5.1 Effective Use of Existing Tools

Autobof is a buffer overlfow detection automation tool written in Python. It makes use of the Metasploit framework and gdb (GNU debugger), which are respectively used for pentesting and debugging. Because of their use cases, these tools seem likely to provide a valuable addition to bug hunting [Met20][08].

In addition to these tools, there are several well-known and well-developed python libraries for analyzing and interacting with binary files. These libraries are therefore likely candidates for building useful screening tools for buffer overflows. An example of this type of tool is pwntools. Pwntools is a CTF and exploit development library. The Pwntools library contains modules for creating shellcode for various architectures. It also has a module for return oriented programming, including finding gadgets in the binary [20d]. A possible improvement for the Autobof project is making use of more of these type of tools and python packages.

5.2 Python Version

Autobof is written in Python 2.7, which reached end of life (EOL) on January 1st, 2020 [Pet03]. This will also extend to any python packages that are used in the program. According to the author, this was not an intentional decision [Rai19]. There seems to be no good reason for keeping autoBOF in Python 2.7 and considering the size of the current project, porting the project to a newer version should be a fairly manageable task. The project also will not be able to make use of modules for Python 3 if it is not ported to Python 3. Porting the project over to Python 3 is therefore a necessary step for further development.

(38)

5. Possibe Further Work and Improvements for autoBOF

5.3 Code Readability

The project consists of two python files containing respectfully 415 and 28 lines of code. This is one main script and one partner script, the latter is required to communicate with the GDB instance autoBOF requires. Many of these lines are repeated pieces of code that could easily be written into methods to increase modularity and readability. Following the DRY-principle, so that every discrete piece of code exists in one singular place, modifying and adding to the code base is less likely to cause bugs. For much the same reasoning, testing of the code should be added. This is both to ensure that the current program is functioning as intended and to attempt to discover if new bugs are introduced when modifying or adding new code. Other measures that could improve maintainability is refactoring parts of the code and removing unnecessary hardcoded values. The hardcoded values and file paths needs to be changed in the source code of autoBOF if the program is to run on a different system.

These issues need to be resolved if the program is to be extended to support further functionalities and to allow easier maintenance.

5.4 Configuration and Command Line Arguments

autoBOF has several configuration options. These are specified in a configura- tion file. There is added functionality in the code to add these via command line arguments as well, but this has not been tested sufficiently. The parsing of both command line arguments and the config file has been done with only built-in Python functions. There are modules written for Python that will make this parsing easier and the code more fluent. Two examples of these is argparse and configparse [pyt20a][pyt20b]. When using such modules the general handling of the arguments, such as casting to different data types and such, will be taken care of by the module. This reduces the risk of coding errors in the project code.

In addition, it would be more user friendly if the program also had a configuration option for specifying the target binary. In the current version, the user would have to change the source code in order to use autoBOF on a different target. Adding this configuration option would therefore increase the user friendliness of autoBOF. As noted above, adding new command line arguments to the program will be more fluent when a Python module is used for argument parsing. It will then be possible to add new arguments and specify how to handle this argument, including expected type and default values, with a single line of code.

5.5 Documentation

The tool has a -help option, but otherwise lacks proper documentation and usage guidance. The -help option displays a short description of all configuration options, as well as a reminder that the partner, hosting GDB, script needs to run. A more in-depth usage description and documentation could be added 30

(39)

5.6. Application Execution Time

for for better usability. In addition it would also make it easier for others to understand and contribute to the project. Something that could be added to autoBOF is simple docstrings, explaining the functionalities of different methods, or some other form for documentation in the source code. There is a page on 0x00sec.org explaining how the tool works, as well as a github page [Rai19][Dis19]. This does, however, not provide a precise documentation on how to use the tool or configure it to other binaries.

5.6 Application Execution Time

The time used to execute the program is not consistent, even when testing with the same file. The causes of this appear to be unknown and, according to the author, it is possible that it is due to the environment and not the program itself. [Rai19]

5.7 Interacting with GDB and Metasploit

AutoBOF uses Pythons interface for communicating with the operating system in order to start GDB and Metasploit. Because the autoBOF communicates with GDB and Metasploit in only one direction, it cannot receive information from them. Therefore, text files are created and parts of the output of the GDB and Metasploit processes will be written to the files. These text files will later be used for reading these values back so that they can be added to the payload. The generated text files are removed when the exploit file has been run.

A drawback of this approach is that sleep statements need to be added, to ensure that the process has finished so that the file has actually been created.

Depending on the system and how long the sleep statement is, this will either slow down the system or cause the file containing the output values to be attempted read before it is written to. Therefore it could be useful to change this approach to an approach which allows for controlling stdin and stdout of the GDB and Metasploit processes. Pwntools has a function for doing just this, which could be a useful addition to this program [20d].

(40)
(41)

CHAPTER 6

Bufferfly - Method, Documentation and Usage

Attempt to Refactor autoBOF

An attempt was initially made to refactor the tool autoBOF, in a way that would facilitate adding new methods or easily configuring the tool to test other binaries. This was quickly found to not be the best option, as a fairly large amount of changes would be required in order to refactor the code. This would have included changing the python version, the configuration method and removing many hardcoded values.

Bufferfly - Starting from Scratch

Because refactoring was not a viable option, a new tool has been created for this thesis. This tool is named Bufferfly. The source code for this tool is added as Appendix A of this paper and is also available on Github[iyt15]. The general approach for this tool is still similar to that of autoBOF. The developed tool acts more as a fuzzer than Joern does and is, as of now, intended to find relatively simple flaws. Bufferfly, like autoBOF, therefore falls into the category of a blackbox testing tool [Dec05].

Bufferfly also attempts to find ways to exploit the flaws that are found. This is partly to prove that the flaws are in fact flaws and not false positives, but also to exemplify the consequences of such flaws. The tool is developed in Python 3.7.6, using pwntools 4.0.1.

Testing Tool

In addition to Bufferfly a tool has been created to more easily create binaries that are vulnerable to buffer overflows and can be used for testing. The tools creates binaries with different buffer sizes, goal functions and types of security protections based on the arguments given. This has been useful during testing the functionality of Bufferfly. The source code of this creation tool is also added as appendix B and its usage is explained briefly in this chapter. It is also available on github [iyt15]. This tool was written in Python version 3.7.6.

(42)

6. Bufferfly - Method, Documentation and Usage

6.1 Approach for Bufferfly

The approach of bufferfly it similar to that of autoBOF. It will first attempt to crash the target binary, then attempt to build a payload that will exploit the binary if this is found to be possible. Each step and decision taken are described in this section, as well as the differences between autoBOF and Joern..

Finding the Amount of Bytes Required for Overflowing a Buffer

The program will fuzz the given binary for overflows. This is done by giving the program a cyclic pattern string larger than the suspected vulnerable buffer.

The string is created in a pattern starting from "aaaa", "baaa" and so on. This means that no 4 characters of the pattern is the same. Therefore this string can be inputted to the vulnerable program and the stack memory area the crashed program can be examined. If the EIP-register of the stack is overwritten, the value can be read and its exact position in the cyclic pattern can be found.

This position represents the amount of padding characters required to overwrite the value of the return address. This works similarly to the pattern-offset and pattern-create tool in the Metasploit framework.[Sec20]

Figure 6.1: Cyclic pattern string injected to stack buffer. The old return address is overwritten with the characters "EAAA", which can be found starting at offset 16 from the start of the cyclic pattern string. This means that 16 bytes of padding is required to overwrite the values of the return address.

In order to read the value of the EIP-register at the time of the crash, the program is launched with gdb (Gnu Debugger). This is one of several methods to read this value, for instance the cyclic pattern could be given as input to an instance of strace running with the examined binary. Gdb was chosen for this task, because gdb can be used for many other tasks as well. This will reduce the total amount of required tools and dependencies, reducing the complexity of the project. After the program is launched with gdb, the resulting process is then supervised by Bufferfly, so that input and output is controlled. Gdb will 34

(43)

6.2. Testing and Creating Binaries for Testing

print the EIP-value, which will then be used to calculate the required amount of padding for an overflow.

Different attack options

Bufferfly supports a few different, fairly simple types of attack. The program will by default check for all attack versions available for the program. If it is known or suspected which type of attack the target binary is vulnerable to, this attack can be specified in the config file or as an argument. Because the different attack versions are dependent on which security properties and mitigations are implemented, not all attacks are possible to achieve.

1. Overwrite Return Value

The approach for this attack is fairly straight forward. The suspected input functionality is fuzzed and if found vulnerable, the amount of padding required is calculated. Then, a goal function is identified and the address of the function is found. The payload is then assembled from padding and the address of the goal function, and will be passed on to the result file.

2. Ret2libc

This attack is approached similarly to the previous attack. The padding required is found and amount of bytes required to overflow the return value will be identified. Then, the address of system@plt is found. In addition, an address of a memory area containing the string "/bin/sh/"

is found. The payload is assembled from padding, address of system, 4 bytes (in place of the return address that is sent to the system function) and lastly the address containing the "/bin/sh" string. The payload is written to the result file.

3. ROP-builder

There is an interactive functionality for chaining ropgadgets found in the target binary into rop-chains. This is an interactive process and therefore requires the user to be knowledgeable in the art of creating shellcode from ropgadgets. The generated shellcode is saved in the resultfile and can be attempted run against the target machine like any of the other attacks.

Resultfile

Once Bufferfly has attempted to find vulnerabilities and possible attack payloads it will write the results to a file. This file is a python program and can be used for giving the found payloads to the target binary. The usage of this program is shown in Section 6.3.

6.2 Testing and Creating Binaries for Testing Vuln_create - A Tool for Creating Vulnerable Binaries

- Benefits of this Tool

A tool has been written for creating vulnerable binaries that can be exploited and used for testing for Bufferfly. The source code for this tool is included as an appendix for this paper. This tool can be configured to specify:

Referanser

RELATERTE DOKUMENTER