Available via license: CC BY-NC-ND 4.0
Content may be subject to copyright.
ScienceDirect
Available online at www.sciencedirect.com
Procedia Computer Science 160 (2019) 9–14
1877-0509 © 2019 The Authors. Published by Elsevier B.V.
This is an open access article under the CC BY-NC-ND license (http://creativecommons.org/licenses/by-nc-nd/4.0/)
Peer-review under responsibility of the Conference Program Chairs.
10.1016/j.procs.2019.09.437
10.1016/j.procs.2019.09.437 1877-0509
© 2019 The Authors. Published by Elsevier B.V.
This is an open access article under the CC BY-NC-ND license (http://creativecommons.org/licenses/by-nc-nd/4.0/)
Peer-review under responsibility of the Conference Program Chairs.
Available online at www.sciencedirect.com
ScienceDirect
Procedia Computer Science 00 (2019) 000–000
www.elsevier.com/locate/procedia
* Corresponding author. Tel.: +4-021-319-1901.
E-mail address: snicula@protonmail.com
1877-0509 © 2019 The Authors. Published by Elsevier B.V.
This is an open access article under the CC BY-NC-ND license (http://creativecommons.org/licenses/by-nc-nd/4.0/)
Peer-review under responsibility of the Conference Program Chairs.
The 10th International Conference on Emerging Ubiquitous Systems and Pervasive Networks
(EUSPN 2019)
November 4-7, 2019, Coimbra, Portugal
Exploiting stack-based buffer overflow using modern day
techniques
Ștefan Niculaa*, Răzvan Daniel Zotaa
aThe Bucharest University of Economic Studies, 15-17 Dorobanti, Bucharest 010552, ROMANIA
Abstract
One of the most commonly known vulnerabilities that can affect a binary executable is the stack-based buffer overflow. The
buffer overflow occurs when a program, while writing data to a buffer, overruns the buffer's boundary and overwrites adjacent
memory locations. Nowadays, due to multiple protection mechanisms enforced by the operating system and on the executable
level, the buffer overflow has become harder to exploit. Multiple bypassing techniques are often required to be used in order to
successfully exploit the vulnerability and control the execution flow of the studied executable. One of the security features
designed as protection mechanisms is Data Execution Prevention (DEP) which helps prevent code execution from the stack, heap
or memory pool pages by marking all memory locations in a process as non-executable unless the location explicitly contains
executable code. Another protection mechanism targeted is the Address Space Layout Randomization (ASLR), which is often
used in conjunction with DEP. This security feature randomizes the location where the system executables are loaded into
memory. By default, modern day operating systems have these security features implemented. However, on the executable level,
they have to be explicitly enabled. Most of the protection mechanisms, like the ones mentioned above, require certain techniques
in order to bypass them and many of these techniques are using some form of address memory leakage in order to leverage an
exploit. By successfully exploiting a buffer overflow, the adversary can potentially obtain code execution on the affected
operating system which runs the vulnerable executable. The level of privilege granted to the adversary is highly depended on the
level of privilege that the binary is executed with. As such, an adversary may gain elevated privileges inside the system. Most of
the times, this type of vulnerability is used for privilege escalation attacks or for gaining remote code execution on the system.
© 2019 The Authors. Published by Elsevier B.V.
This is an open access article under the CC BY-NC-ND license (http://creativecommons.org/licenses/by-nc-nd/4.0/)
Peer-review under responsibility of the Conference Program Chairs.
Keywords: stack buffer overflow, return oriented programming, libc attack, exploiting buffer overflow, stack protection mechanisms, address
memory leak;
Available online at www.sciencedirect.com
ScienceDirect
Procedia Computer Science 00 (2019) 000–000
www.elsevier.com/locate/procedia
* Corresponding author. Tel.: +4-021-319-1901.
E-mail address: snicula@protonmail.com
1877-0509 © 2019 The Authors. Published by Elsevier B.V.
This is an open access article under the CC BY-NC-ND license (http://creativecommons.org/licenses/by-nc-nd/4.0/)
Peer-review under responsibility of the Conference Program Chairs.
The 10th International Conference on Emerging Ubiquitous Systems and Pervasive Networks
(EUSPN 2019)
November 4-7, 2019, Coimbra, Portugal
Exploiting stack-based buffer overflow using modern day
techniques
Ștefan Niculaa*, Răzvan Daniel Zotaa
aThe Bucharest University of Economic Studies, 15-17 Dorobanti, Bucharest 010552, ROMANIA
Abstract
One of the most commonly known vulnerabilities that can affect a binary executable is the stack-based buffer overflow. The
buffer overflow occurs when a program, while writing data to a buffer, overruns the buffer's boundary and overwrites adjacent
memory locations. Nowadays, due to multiple protection mechanisms enforced by the operating system and on the executable
level, the buffer overflow has become harder to exploit. Multiple bypassing techniques are often required to be used in order to
successfully exploit the vulnerability and control the execution flow of the studied executable. One of the security features
designed as protection mechanisms is Data Execution Prevention (DEP) which helps prevent code execution from the stack, heap
or memory pool pages by marking all memory locations in a process as non-executable unless the location explicitly contains
executable code. Another protection mechanism targeted is the Address Space Layout Randomization (ASLR), which is often
used in conjunction with DEP. This security feature randomizes the location where the system executables are loaded into
memory. By default, modern day operating systems have these security features implemented. However, on the executable level,
they have to be explicitly enabled. Most of the protection mechanisms, like the ones mentioned above, require certain techniques
in order to bypass them and many of these techniques are using some form of address memory leakage in order to leverage an
exploit. By successfully exploiting a buffer overflow, the adversary can potentially obtain code execution on the affected
operating system which runs the vulnerable executable. The level of privilege granted to the adversary is highly depended on the
level of privilege that the binary is executed with. As such, an adversary may gain elevated privileges inside the system. Most of
the times, this type of vulnerability is used for privilege escalation attacks or for gaining remote code execution on the system.
© 2019 The Authors. Published by Elsevier B.V.
This is an open access article under the CC BY-NC-ND license (http://creativecommons.org/licenses/by-nc-nd/4.0/)
Peer-review under responsibility of the Conference Program Chairs.
Keywords: stack buffer overflow, return oriented programming, libc attack, exploiting buffer overflow, stack protection mechanisms, address
memory leak;
10 Ștefan Nicula et al. / Procedia Computer Science 160 (2019) 9–14
2 Author name / Procedia Computer Science 00 (2018) 000–000
1. Introduction
The stack-based buffer overflow is one of the most commonly known vulnerabilities and it still one of the most
exploited vulnerabilities that are affecting software and operating systems [1]. A successful exploitation of this
vulnerability can sometimes be difficult to achieve, and modern operating system nowadays have protection
mechanisms in-place in order to prevent such issues to be exploited. These protections can also be implemented at
the binary level in order to increase its security level. However, certain techniques can be used in order to bypass
these prevention mechanisms, but all the techniques described do need auxiliary information in order to be
implemented. The study presented will be focused on Intel architecture x86-x64, being more targeted around the
Linux operating system internals and having as the main scope achieving code execution on the underlying operating
system.
2. Exploitation prevention mechanisms
Buffer overflow has been an active research topic through the history of Computer Science and multiple aspects
have been addressed in order to prevent different exploitations. We can encounter multiple protection mechanisms
that prevent overflow from occurring or react once the overflow happens [2].
Data Execution Prevention (DEP) is implemented at the binary level and dictates the execution privilege on a
memory location. This protection prevents malicious code from being executed directly from the buffer value by
allowing only specific memory location to have execution privileges. Only certain memory blocks have execution
privileges if they explicitly request so [3].
Address space layout randomization (ASLR) is implemented by the binary or by the operating system. This
protection mechanism randomizes the memory address of the binary and external libraries each time it gets executed.
As such, every attack which is based on static known values will fail [4].
Stack canaries/cookies assures that the stack data is not corrupted or overwritten from untrusted user supplied data.
This method works by placing a small randomly chosen value inside the program stack, in memory, just before the
stack return pointer. Because the buffer overflow is writing stack memory from lower to higher address, the return
pointer will be overwritten and thus the stack canary will also be modified [5].
Partial or full RELRO removes all the dynamic linked functions and ensures that the Global Offset Table (GOT) is
read-only. By making GOT entries read-only, an adversary can no longer overwrite external function call addresses
to controlled stack memory address [6].
Position Independent Executable (PIE) is an optional feature that can be used at compile time which makes the
executable behaviour as a dynamic external library at linking and loading time. This feature adds more
randomization in the linking and loading process. A note here is that ASLR predates PIE and ASLR does not require
PIE to be enabled [7].
These protection mechanisms can prevent the exploitation of a buffer overflow and can further limit an adversary's
possibilities. For most of these mechanisms, an auxiliary vulnerability that can obtain a memory leak address is
mandatory in order to bypass them.
3. Exploitation techniques and protection bypasses
3.1 Bypassing DEP and ASLR
Some of the most common identified protection mechanisms are the DEP and ASLR. The Data Execution
Prevention mechanism is implemented at the binary level. This protection mechanism allows only specific stack
frames to have execution privileges. This translates in the fact that data written in arbitrary chosen stack-frames
Ștefan Nicula et al. / Procedia Computer Science 160 (2019) 9–14 11
Author name / Procedia Computer Science 00 (2018) 000–000 3
cannot be referenced by the instruction pointer to be executed. A good example would be a buffer overflow
vulnerability that can be exploited in order to point the instruction pointer to a specific address inside the stack which
is controlled by our buffer input. In this scenario, even though we have control on the Instruction Pointer, we cannot
execute data that is being held in the stack frame which we overwrite. In order to bypass this protection, a technique
called Return Oriented Programming (or ROP chain) can be used. By using this technique, which can also be
reference as Return to libc attack [8], we can bypass the DEP protection [9] by re-using code already present in the
exploited binary. Sometimes, the studied binary does not have all the needed instructions inside its base-code in
order to fully exploit an existing buffer overflow. As such, the libc attack can be used. Inside the libc library, we can
re-use a variety of instructions to fulfil the scope of exploiting the vulnerability. To use the libc code-base, we need
to further leak an address inside the targeted binary. This can be achieved, for example, by chaining a format string
vulnerability affecting the vulnerable binary.
In regard to the format string vulnerability, this particular one is sometimes crucial in exploiting a vulnerable binary
that has ASLR protection on. This is mainly due to the fact that ASLR protection is implemented by the binary or by
the operating system [10]. In modern operating systems, the ASLR protection is implemented by default. As such,
all the external libraries linked on the targeted binary are having randomized address values. However, the binary
itself can opt to have the ASLR protection in-place. By doing this, the binary will randomize its instruction addresses
and memory maps each time the binary is executed. In order to defeat this protection mechanism, an information
leak vulnerability such as a format string can be used in order to leak a base address that can be further used by the
developed exploit. Other method of defeating this popular protection mechanism is to use a potential buffer overflow
together with calling a function that uses stdout in order to print results. This can be further used by leaking GOT
and PLT addresses in order to reveal libc base addresses [11]. Using the obtained libc base address from the function
memory address leak, we can pin-point the exact version of the library used by the executable. In this way, all the
other function references can be calculated based on the initial libc version.
3.2 Return Oriented Programming and Return to libc attack
We can particularly note the concept of gadgets in a ROP chain. Gadgets are a set of instructions that serve our
purpose of manipulating the executable in order to achieve our scope. Gadgets are pieces of code from the
executable, commonly found in the loaded external libraries but can be found in the local binary code as well [12].
By using them, an adversary can do a variety of actions such as invoking syscalls while keeping the execution flow
by always returning inside a stack controlled memory address. The need of RET opcode is mandatory for gadgets in
order for us to keep the execution flow. Certain gadgets require different parameters which should be placed on the
stack accordingly in the payload, before the function call. We know that functions are receiving parameters from the
stack and because we control the stack using our buffer overflow, we can pass arguments to the called functions. In
this way, we can create a chain of multiple gadgets that will provide the capabilities of executing code on the
underlying operating system through the usage of the binary affected by a buffer overflow.
3.3 Magic gadget C
One gadget that can be used to exploit a buffer overflow using ROP chain is the C/C++ Magic gadget. Almost all of
the libc libraries contain a version of the magic gadget. Basically, this gadget is used for ROP chaining and is
consisted of some code residing in the libc which, when executed, opens a shell. The magic gadget code has to either
call execve or issue the corresponding syscall directly. In our case, /bin/sh is set as a first argument. [13]
3.4 GOT overwrite
Another exploitation technique is defined by using the Global Offsets Table to overwrite function entries in order to
execute malicious code [14]. This attack method can be avoided by implementing RELRO which basically removes
all the dynamic linked functions and ensures that the GOT is read-only [15]. An example of a successful GOT
rewrite would be overwriting a libc address with a local stack-frame address that contains malicious code. This can
be prevented by making the GOT read-only at the initial launch of the binary file.
12 Ștefan Nicula et al. / Procedia Computer Science 160 (2019) 9–14
4 Author name / Procedia Computer Science 00 (2018) 000–000
4. Memory leak using stdout functions
Given the constraints that can be applied to a specific executable, a successful exploitation of a stack-based buffer
overflow requires a certain memory address leak. This can be achieved in multiple ways. One of the most common
technique is finding and exploiting a format string vulnerability which basically allows us to leak values from the
stack. Format string vulnerability is a type of vulnerability which allows an adversary to control the format of the
printed output. [16]
Another technique which I will discuss in the next chapter is related to using certain C/C++ functions that
manipulate stdout in order to leak entries from the Global Offset Table (GOT). The GOT contains the direct address
of the function inside the external libraries. At compile time, that address is unknown, the dynamic linker will
populate the entry when the binary is executed, and the loading and linkage routines are executed. Inside the studied
binary, the Procedure Linkage Table (PLT) is holding the trampoline address value to the GOT. By invoking a
stdout from using the PLT address to the GOT address reference, we can obtain the actual address of a function from
the loaded external library. [17]
5. Case study example
The previous chapters enumerated a series of exploitation techniques that can be implemented in order to bypass
specific protection and prevention mechanisms. Let's look at the following code snippet example which is vulnerable
to stack-based buffer overflow:
int main(){
char local_var [60];
puts("Enter some input:");
fflush(stdout);
fgets(local_var,700,stdin);
return 0;
}
Inside the main function we can note the initialization of the "local_var" variable which is of type char vector of size
60. We can note the usage of "puts" function which we will later abuse in order to obtain an address memory leak.
The "fgets" function call is receiving a stream input of max size 700 from the standard input and stores the input
inside our previously declared local variable. Since there is no boundary check on the "local_var", the user can
provide a size larger than the allocated size 60 of the buffer, thus resulting in a buffer overflow scenario.
For this particular exploit, we will use gdb peda and pwntools as an example of automating certain tasks and for the
ease of use that these tools are bringing to the table [18]. The binary will the dynamically compiled targeting i386-
x86-x64 architecture for the Linux platform so the compiled analysed binary will be an ELF file designed for x64
architecture.
By checking the security feature of the binary after the compilation, we can observe the following:
ASLR: OFF
CANARY: disabled
FORTIFY: disabled
NX: ENABLED
PIE: disabled
RELRO: partial
By investigating the checksec output from gdb peda, we can observe that this is a classic buffer overflow example
which can be exploited using ROP chain gadgets. We can note that the binary does not have local ASLR enabled and
we also note the lack of stack canaries. Even if the ASLR is disabled for the binary, the external libraries used are
subject to randomization due to the ASLR enforced by the operating system [19]. We can also note that the NX (not
Ștefan Nicula et al. / Procedia Computer Science 160 (2019) 9–14 13
Author name / Procedia Computer Science 00 (2018) 000–000 5
executable) feature is enabled. By studying this particular case, we can note that the buffer overflow can be exploited
but it will require a ROP chain in order to achieve code execution. That's because the NX privilege is enabled which
does not allow us to redirect the execution flow in our controlled buffer but the missing stack canaries protection
means that next execution instruction can be overwritten with our chosen address [20].
Considering that the binary is compiled with dynamic libraries, we will require a memory leak to obtain a base
address from the libc library. Since we have no ASLR enabled on the binary level, we can search for the address of
the puts function which is a stdout function. By invoking the puts using the PLT address of the puts function from
the GOT, we can obtain the puts address inside the actual libc library. We want puts to call itsel f on the Global
Offset Table which will give us the address of the puts in the binary that changes every single time [21]. We can
obtain the binary PLT address of the puts by using objdump on the compiled binary.
An example of calls would be the following:
puts@plt 0x400476 -> puts@got 0x601018 -> puts@libc linked address
This action is achieved by using gadgets and arranging the stack in such a way because the calls of the functions will
take arguments from the stack itself and these arguments will be the ones controlled by us. After obtaining the puts
address from the libc, we can calculate the base address of the libc itself. We need this information in order to create
ROP gadgets based on libc. The library address is modifying every time the binary is executed so we need to
calculate its base address in order to correctly reference other code snippets from inside the libc.
From the libc base address, we can use any specific gadget from the libc library which will provide us a reverse
shell. One particular gadget described earlier is the Magic Gadget which uses a series of code snippets to execute
syscall as execve into /bin/sh.[22]
6. Conclusion
A stack-based buffer overflow can be exploited in multiple ways depending on several variables. First, the allocated
buffer size can play a huge role in choosing the right way to exploit the issue. In the previous case study shown, the
buffer size was generous and allowed us enough space to inject various addresses and use multiple techniques
without worrying too much about the memory space. If the buffer size was restricted to a small limited number of
characters, additional steps would be required to successfully exploit the vulnerability. For example, an additional
input buffer may have been required to redirect the execution flow into it however, that hypothetical input needed to
be, again, controlled by the adversary. Some techniques used to get around the limited buffer size promote the usage
of environmental variables that are loaded by the binary when executed. A memory leak address is needed in order
to obtain such details. The second problem raised is related to the protection mechanisms that are preventing a
straight forward exploitation technique. We cannot redirect the execution flow directly into our defined buffer due to
DEP. Also, the address to libc functions is randomized each time we execute the binary given the ASLR protection
enabled. We also have a disabled RELRO which should allow us some opportunities to overwrite the GOT-PLT
entries inside the memory blocks. In order to bypass the aforementioned protections, a memory address leak is
mandatory in order to obtain an address so we can further calculate our needed function addresses. A stack -buffer
overflow cannot be exploited stand-alone, it can be situational and certain memory leak vulnerabilities are required
given the protection mechanisms encountered in the process. A very important role is how to understand the
internals of a program as well as properly identifying and using external libraries loaded by the executable in order
to achieve code execution.
Buffer overflows are still an emerging, active and real threat. Yearly, this specific vulnerability can be encountered
in multiple CVEs reported on popular known software [23]. In order to successfully exploit them, certain techniques
are required in order to bypass common protection mechanisms. Nevertheless, these vulnerabilities are still found in
solutions that have a high level of maturity in terms of security best practices and implementations. We should not
overlook nor undermine their potential risk, even though modern-day systems are implementing multiple protection
mechanisms in order to try and prevent such attacks.
14 Ștefan Nicula et al. / Procedia Computer Science 160 (2019) 9–14
6 Author name / Procedia Computer Science 00 (2018) 000–000
References
[1] National Institute of Standards and Technology. ICAT Metabase.http://icat.nist.gov/
[2] Erick Leon, Stefan D. Bruda, Counter-measures against stack buffer overflows in GNU/Linux operating systems., The International
Workshop on Parallel Tasks on High Performance Computing, Procedia Computer Science 83, 2016, Volume 83, pages 1301 – 1306
[3] A detailed description of the Data Execution Prevention (DEP) feature in Windows XP Service Pack 2, Windows XP Tablet PC Edition 2005,
and Windows Server 2003, (Jul.2017) https://support.microsoft.com/en-us/help/875352/a-detailed-description-of-the-data-execution-prevention-
dep-feature-in, retrieved Dec.2018
[4] Address Space Layout Randomization, (Mar.2003), https://pax.grsecurity.net/docs/aslr.txt, retrieved Feb. 2015.
[5] Buffer overflow protection, (Jun.2018), https://en.wikipedia.org/wiki/Buffer_overflow_protection#Canari es, retrieved Jan.2019
[6] Hardening ELF binaries using Relocation Read -Only (RELRO), (Jan.2019), https://www.redhat.com/en/blog/hardening-elf-binaries-using-
relocation-read-only-relro, retrieved Jan.2019
[7] Position Independent Executables (PIE), (Nov.2012), https://access.redhat.com/blogs/766093/posts/1975793, retrieved Jan.2019
[8] Return-to-libc Exploit, (Feb.11), https://medium.com/@nikhilh20/return-to-libc-exploit-aa3fe6fb0d69, retrieved Mar.2019
[9] Bypassing DEP with ROP (32-bit), (Dec.2017), https://bytesoverbombs.io/bypassing-dep-with-rop-32-bit-39884e8a2c4a, retrieved Mar.2019
[10] Bypassing ASLR - Part I, (May 2015), https://sploitfun.wordpress.com/2015/05/08/bypassing-aslr-part-i/, retrieved Dec.2018
[11] Yan Fen, Yuan Fuchao, Shen Xiaobing, Yin Xinchun, Mao Bing, A New Data Randomization Method to Defend Buffer Overflow Attacks,
International Conference on Applied Physics and Industrial Engineering, Physics Procedia 24, Volume 24, Part C, 2012, pages 1757-1764
[12] Bruce Dang , Practical Reverse Engineering: x86, x64, ARM, Windows Kernel, Reversing Tools, and Obfuscation, Wiley Publishing, 2014
[13] The magic gadget, (Sep.2016), )https://github.com/m1ghtym0/magic_gadget_finder, retrieved Apr.2019
[14] How to hijack the Global Offset Table with pointers for root shells, (Apr.2006), https://www.exploit-db.com/papers/13203, retrieved
Apr.2019
[15] Ryan "elfmaster" O'Neill, Learning Linux Binary Analysis, Packt, 2016
[16] Format String Exploitation-Tutorial, https://www.exploit-db.com/docs/english/28476-linux-format-string-exploitation.pdf, retrieved
Apr.2019
[17] P. Silberman and R. Johnson, A Comparison of Buffer Overflow Prevention Implementations and Weaknesses, presentation at Black Hat
USA, Caesar's Palace, Las Vegas, NV, USA (Jul. 2004).
[18] Eldad Eilam, Reversing: Secrets of Reverse Engineering, Wiley Publishing, 2005
[19] Sahel Alouneh, Mazen Kharbutli, Rana AlQurem, Stack Memory Buffer Overflow Protection Based on Duplication and Randomization, The
4th International Conference on Emerging Ubiquitous Systems and Pervasive Networks, Procedia Computer Science 21, 2013, pages 250 – 256
[20] G. Duarte. Epilogues, Canaries, and Buffer Overflows, (Mar. 19 2014), http://duartes.org/gustavo/blog/post/epiloguescanaries -
bufferoverflows/ , retrieved Feb. 2015.
[21] Ryan "elfmaster" O'Neill, Learning Linux Binary Analysis, Packt, 2016
[22] Smashing the Stack, (Apr.2014), http://phrack.org/issues/49/14.html, retrieved Oct.2018
[23] Mitre CVE Buffer Overflow search result, https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=Buffer+Overflow, retrieved May.2019