Stack Overflow
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
A stack overflow is a vulnerability that occurs when a program writes more data to the stack than it is allocated to hold. This excess data will overwrite adjacent memory space, leading to the corruption of valid data, control flow disruption, and potentially the execution of malicious code. This issue often arises due to the use of unsafe functions that do not perform bounds checking on input.
The main problem of this overwrite is that the saved instruction pointer (EIP/RIP) and the saved base pointer (EBP/RBP) to return to the previous function are stored on the stack. Therefore, an attacker will be able to overwrite those and control the execution flow of the program.
The vulnerability usually arises because a function copies inside the stack more bytes than the amount allocated for it, therefore being able to overwrite other parts of the stack.
Some common functions vulnerable to this are: strcpy
, strcat
, sprintf
, gets
... Also, functions like fgets
, read
& memcpy
that take a length argument, might be used in a vulnerable way if the specified length is greater than the allocated one.
For example, the following functions could be vulnerable:
The most common way to find stack overflows is to give a very big input of A
s (e.g. python3 -c 'print("A"*1000)'
) and expect a Segmentation Fault
indicating that the address 0x41414141
was tried to be accessed.
Moreover, once you found that there is Stack Overflow vulnerability you will need to find the offset until it's possible to overwrite the return address, for this it's usually used a De Bruijn sequence. Which for a given alphabet of size k and subsequences of length n is a cyclic sequence in which every possible subsequence of length _n_** appears exactly once** as a contiguous subsequence.
This way, instead of needing to figure out which offset is needed to control the EIP by hand, it's possible to use as padding one of these sequences and then find the offset of the bytes that ended overwriting it.
It's possible to use pwntools for this:
or GEF:
During an overflow (supposing the overflow size if big enough) you will be able to overwrite values of local variables inside the stack until reaching the saved EBP/RBP and EIP/RIP (or even more). The most common way to abuse this type of vulnerability is by modifying the return address so when the function ends the control flow will be redirected wherever the user specified in this pointer.
However, in other scenarios maybe just overwriting some variables values in the stack might be enough for the exploitation (like in easy CTF challenges).
In this type of CTF challenges, there is a function inside the binary that is never called and that you need to call in order to win. For these challenges you just need to find the offset to overwrite the return address and find the address of the function to call (usually ASLR would be disabled) so when the vulnerable function returns, the hidden function will be called:
In this scenario the attacker could place a shellcode in the stack and abuse the controlled EIP/RIP to jump to the shellcode and execute arbitrary code:
This technique is the fundamental framework to bypass the main protection to the previous technique: No executable stack (NX). And it allows to perform several other techniques (ret2lib, ret2syscall...) that will end executing arbitrary commands by abusing existing instructions in the binary:
An overflow is not always going to be in the stack, it could also be in the heap for example:
There are several protections trying to prevent the exploitation of vulnerabilities, check them in:
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)