Skip to content

Commit 3e8b28a

Browse files
mariasfiraialateodutu
authored andcommitted
taming-the-stack: Add session content
Add content related to the stack only. The session focuses on function calls, the stack frame and stack pointer. Signed-off-by: Maria Sfiraiala <maria.sfiraiala@gmail.com>
1 parent bfacda9 commit 3e8b28a

15 files changed

+396
-41
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Function Calls
2+
3+
Use `objdump` to investigate the prologue of the `read_array()` and `print_array()` functions.
4+
5+
```console
6+
root@kali:~$ objdump -d -M intel main
7+
```
8+
9+
Notice how in the prologue, `ebp` saves the `esp` value before the local variables are stored on stack:
10+
11+
```asm
12+
080491a6 <read_array>:
13+
80491a6: 55 push ebp
14+
80491a7: 89 e5 mov ebp,esp
15+
80491a9: 83 ec 18 sub esp,0x18
16+
80491ac: 83 ec 08 sub esp,0x8
17+
```
18+
19+
What's more, take a closer look at how the parameters are handled:
20+
21+
```asm
22+
80491af: ff 75 0c push DWORD PTR [ebp+0xc] ; the second argument of read_array()
23+
80491b2: 68 08 a0 04 08 push 0x804a008
24+
80491b7: e8 c4 fe ff ff call 8049080 <__isoc99_scanf@plt>
25+
26+
8049213: 8b 45 08 mov eax,DWORD PTR [ebp+0x8] ; the first argument of print_array()
27+
```
28+
29+
Now, inside `gdb`, let's take a look at where the return address is saved:
30+
31+
```console
32+
pwndbg> info frame
33+
Stack level 0, frame at 0xffffcd30:
34+
eip = 0x80491ac in read_array (main.c:5); saved eip = 0x8049273
35+
Saved registers:
36+
ebp at 0xffffcd28, eip at 0xffffcd2c
37+
38+
pwndbg> x 0xffffcd2c
39+
0xffffcd2c: 0x08049273
40+
```
41+
42+
Let's do the math:
43+
44+
- `ebp` points at `0xffffcd28`
45+
- `ebp + 4` will then point at `0xffffcd2c`
46+
- the value stored at `0xffffcd2c` is `0x08049273`, the same as the one from the saved `eip`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
CFLAGS = -m32 -Wall -fno-PIC -g -O0
2+
LDFLAGS = -m32 -no-pie
3+
4+
.PHONY: all clean
5+
6+
all: main
7+
8+
main: main.o
9+
10+
main.o: main.c
11+
12+
clean:
13+
-rm -f main.o
14+
-rm -f main
15+
-rm -f *~
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// SPDX-License-Identifier: BSD-3-Clause
2+
/*
3+
* Copyright 2023 University POLITEHNICA of Bucharest
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
*
8+
* 1. Redistributions of source code must retain the above copyright notice, this
9+
* list of conditions and the following disclaimer.
10+
*
11+
* 2. Redistributions in binary form must reproduce the above copyright notice,
12+
* this list of conditions and the following disclaimer in the documentation
13+
* and/or other materials provided with the distribution.
14+
*
15+
* 3. Neither the name of the copyright holder nor the names of its contributors
16+
* may be used to endorse or promote products derived from this software
17+
* without specific prior written permission.
18+
*
19+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29+
*/
30+
31+
#include <stdio.h>
32+
33+
void read_array(int *v, int *n)
34+
{
35+
scanf("%d", n);
36+
37+
for (int i = 0; i < *n; ++i)
38+
scanf("%d", &v[i]);
39+
}
40+
41+
void print_array(int *v, int n)
42+
{
43+
for (int i = 0; i < n; ++i)
44+
printf("%d ", v[i]);
45+
46+
printf("\n");
47+
}
48+
49+
int main(void)
50+
{
51+
int v[16], n;
52+
53+
read_array(v, &n);
54+
print_array(v, n);
55+
56+
return 0;
57+
}
Loading

chapters/binary-introduction/taming-the-stack/media/stack-array.svg

+4
Loading
Loading

chapters/binary-introduction/taming-the-stack/reading/README.md

-40
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Data, Data Everywhere
2+
3+
Up until now, we've learnt that our application (or program) is made out of data and code.
4+
While the code is the engine of the process, as it obviously tells the processor the work that it should do, data is the most interesting (and dangerous) part when it comes to changing the execution of an app.
5+
Why, you might ask?
6+
Well, because it's modifiable;
7+
the majority of the data contained by your program lays around in the `.stack`, `.heap` or `.data` sections of the executable, which makes it **writable**.
8+
And therefore, even more appealing to the attackers.
9+
10+
Attacks on `.rodata` variables are rarely possible due to the protections enforced by the permissions, or lack thereof.
11+
Even though less protected, the `.text` section also gets fewer attacks, as the `W ^ X` security feature becomes the norm.
12+
13+
The gate remains open for malicious endeavours on the `.stack`, `.heap` and `.data` sections, and, today, we'll discuss the most prolific one: the stack.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Functions and the Stack
2+
3+
Every function has two classes of values, usually stored on stack, extremely important for its well-being:
4+
5+
1. the return address
6+
7+
1. the parameters / arguments
8+
9+
Meddling with these might get you to a big fat **SEGFAULT** or to great power.
10+
11+
## `ebp`, the Stack Frame
12+
13+
But before discussing that, we have to bring light to another obscure register, `ebp`.
14+
We kind of used it before, in our journey, as it has a great advantage.
15+
It stores the stack pointer value right before the stack begins to hold local variables and preserved register values.
16+
In other words, it keeps a pointer to the stack at the beginning of the function, enabling us to actually move freely through the stack.
17+
We will, now, refer to values stored on it, even though they are not the last ones.
18+
19+
```asm
20+
push ebp
21+
mov ebp, esp
22+
23+
push dword 3
24+
push dword 4
25+
push dword 5
26+
27+
; at this point esp decreased its value with 3 * 4 = 12 bytes
28+
; traditionally we can access the last value only,
29+
; however the stack is like an array, so we will use the pointers
30+
; it offers us
31+
32+
mov eax, [esp + 8] ; eax = 3
33+
mov eax, [ebp - 4] ; eax = 3
34+
```
35+
36+
## The Return Address
37+
38+
The return address of a function is one of the **most targeted** piece of information in an attack.
39+
There is even a special class of attacks that takes its name from it, [ROP](https://security-summer-school.github.io/binary/return-oriented-programming/) (Return Oriented Programming).
40+
Moreover, the return address can also be defined as a **code pointer**, a pointer that stores the address of an instruction.
41+
Remember how the instructions were stored in the code or text section, hence the **code pointer** label.
42+
43+
The reason for this kind of popularity is obvious: it represents one of the rare instances when the program **performs a jump to a code pointer saved on stack**, which, combined with the stupidity or the laziness of the programmer, can result in a nasty backdoor to the system.
44+
45+
The address at which the return address is usually stored on x86 systems is `[ebp + 4]`.
46+
47+
## The Parameters
48+
49+
The parameters follow a similar story to that of the return address, with a slight modification, though.
50+
On 64-bit x86 they are placed in special registers, if possible.
51+
If the number of parameters is high, they would get transmitted using the stack, just as it happens, on 32-bit x86.
52+
53+
The address at which the first parameter gets stored on 32-bit x86 systems is `ebp + 8`.
54+
55+
The address at which the second parameter gets stored on 32-bit x86 systems is `ebp + 12`.
56+
57+
The address at which the third parameter gets stored on 32-bit x86 systems is `ebp + 16`.
58+
59+
And so on.
60+
61+
![parameters and ebp](../media/function-stack.jpg)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Further Reading
2+
3+
[Stack Immersion](https://github.com/systems-cs-pub-ro/iocla/blob/master/laborator/content/stiva/README.md)
4+
5+
[Function Calls Immersion](https://github.com/systems-cs-pub-ro/iocla/blob/master/laborator/content/apel-functii/README.md)
6+
7+
[ROP attacks](https://resources.infosecinstitute.com/topics/hacking/return-oriented-programming-rop-attacks/)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Introduction
2+
3+
While the last three sessions introduced concepts regarding processes, executables and the means to investigate them, this session will, **finally**, focus on how to manipulate apps to do strange and (sometimes) undesired behaviour.
4+
5+
## Reminders and Prerequisites
6+
7+
- hexadecimal representation
8+
- process address space
9+
- x86 Assembly knowledge: memory addressing and basic commands
10+
- `Ghidra`, `objdump`, `nm`, `gdb`

0 commit comments

Comments
 (0)