# Understanding Buffer Overflows: A Beginner's Guide - Part 2

This article is a 2nd part of [https://blogs.copsiitbhu.co.in/understanding-buffer-overflows-a-beginners-guide-part-1](https://blogs.copsiitbhu.co.in/understanding-buffer-overflows-a-beginners-guide-part-1#heading-registers) make sure you have read that for understanding it

In this article, we will dive into the binary and see what’s going on; for that, we need a debugger. What is a debugger? Well, a debugger is a tool that allows developers to test, inspect, and troubleshoot their code by executing it step-by-step, setting breakpoints, and examining variables and program flow. We are going to use gdb as our debugger in this article.

# Installation

### For Linux

run (for debian and derivatives) `sudo apt install gdb`

### For macOS

run `brew install gdb`

### For windows

Don’t install it on windows just use linux. Just kidding for windows use this steps

1. Download the MinGW installer from [https://sourceforge.net/projects/mingw/](https://sourceforge.net/projects/mingw/)
    
2. Run the installer and select "GDB" during the installation process.
    
3. After installation, add the MinGW `bin` directory to your system's PATH.
    

Use terminal based on your OS and run this command to check your gdb installation

`gdb --version`

## Buffer Overflow

To use `gdb`, we first need a binary to run. Let's try the following example:

```c
// gcc -m32 -fno-stack-protector -z execstack -fsyntax-only -o vuln vuln.c

#include <stdio.h>
#include <string.h> 

const char MYPASS[] = "REDATED";

void win() {
    puts("This code is super secure, isn't it? :)");
}

void vuln() {
    char buffer[32];
    int password = 0;
    fgets(buffer, 0x32, stdin);
    if (strcmp(buffer, MYPASS) == 0) {
        password = 1;
    }

    if (password) {
        win();
    } else {
        puts("Incorrect password!");
    }
}

int main() {
    puts("Hello to our new bank!");

    vuln();

    return 0;
}
```

Save this file as `vuln.c`, then compile it using the following command in the same directory as `vuln.c`:

`gcc -m32 -fno-stack-protector -z execstack -fsyntax-only -o vuln vuln.c`

Now you have a binary named `vuln`. The password is unknown, but we can try to reach the `win()` function through buffer overflow manipulation. Let’s experiment and see what happens when we run the binary.

```bash
> ./vuln
Hello to our new bank!
tellmethepassword
Incorrect password!
```

In this code, the developer made a mistake in the `fgets` call by reading 50 bytes (`0x32`) instead of limiting it to 32 bytes. can we abuse this ??

Let’s try to adding input bigger that 32 and see what’s happening

```bash
> ./vuln
Hello to our new bank!
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
This code is super secure, isn't it? :)
Segmentation fault (core dumped)
```

😯 we just got in the win functions but there is Segmentation fault ?? Let’s dive into gdb and see what’s going on.

### gdb

First, run this binary using GDB by executing:

```bash
gdb ./vuln
```

GDB comes with many powerful features. We can set breakpoints using GDB, and we can even see the assembly code of the binary. Let’s try to see the code of the `main` function in GDB. Run the following command:

```abap
gdb➤ disass main
```

You will see the output for the `main` function, where you can observe the `esp`, `ebp`, `ebx`, and `ecx` registers explained in the previous article. Here, we can see the call instructions for `puts` and `vuln`:

```perl
   0x0804924f <+37>:	call   0x8049060 <puts@plt>
   0x08049254 <+42>:	add    esp,0x10
   0x08049257 <+45>:	call   0x80491b1 <vuln>
```

Now let’s take a look at the `vuln` function inside GDB by running:

```abap
gdb➤ disass vuln
```

You may get output like this,

```perl
   0x080491b1 <+0>:	push   ebp
   0x080491b2 <+1>:	mov    ebp,esp
   0x080491b4 <+3>:	push   ebx
   0x080491b5 <+4>:	sub    esp,0x34
   0x080491b8 <+7>:	call   0x80490c0 <__x86.get_pc_thunk.bx>
   0x080491bd <+12>:	add    ebx,0x2e37
   0x080491c3 <+18>:	mov    DWORD PTR [ebp-0xc],0x0
   0x080491ca <+25>:	mov    eax,DWORD PTR [ebx-0x8]
   0x080491d0 <+31>:	mov    eax,DWORD PTR [eax]
   0x080491d2 <+33>:	sub    esp,0x4
   0x080491d5 <+36>:	push   eax
   0x080491d6 <+37>:	push   0x32
   0x080491d8 <+39>:	lea    eax,[ebp-0x2c]
   0x080491db <+42>:	push   eax
   0x080491dc <+43>:	call   0x8049050 <fgets@plt>
   0x080491e1 <+48>:	add    esp,0x10
   0x080491e4 <+51>:	sub    esp,0x8
   0x080491e7 <+54>:	lea    eax,[ebx-0x1fd4]
   0x080491ed <+60>:	push   eax
   0x080491ee <+61>:	lea    eax,[ebp-0x2c]
   0x080491f1 <+64>:	push   eax
   0x080491f2 <+65>:	call   0x8049030 <strcmp@plt>
   0x080491f7 <+70>:	add    esp,0x10
   0x080491fa <+73>:	test   eax,eax
   0x080491fc <+75>:	jne    0x8049205 <vuln+84>
   0x080491fe <+77>:	mov    DWORD PTR [ebp-0xc],0x1
   0x08049205 <+84>:	cmp    DWORD PTR [ebp-0xc],0x0
   0x08049209 <+88>:	je     0x8049212 <vuln+97>
   0x0804920b <+90>:	call   0x8049186 <win>
   0x08049210 <+95>:	jmp    0x8049224 <vuln+115>
   0x08049212 <+97>:	sub    esp,0xc
   0x08049215 <+100>:	lea    eax,[ebx-0x1f88]
   0x0804921b <+106>:	push   eax
   0x0804921c <+107>:	call   0x8049060 <puts@plt>
   0x08049221 <+112>:	add    esp,0x10
   0x08049224 <+115>:	nop
   0x08049225 <+116>:	mov    ebx,DWORD PTR [ebp-0x4]
   0x08049228 <+119>:	leave
   0x08049229 <+120>:	ret
```

Here we can see the calls to `fgets`, `strcmp`, `win`, and `puts`. By analyzing the source code, we know that before jumping to the `win` function, it will check the password in the `if` condition. Similarly, in this assembly code, we can see the `cmp` instruction, which compares `DWORD PTR [ebp-0xc]` with `0x0`. Let’s set a breakpoint there and see what’s going on. In GDB, we can set a breakpoint using `b` or `break` followed by the address where we want to stop.

```abap
gdb➤ b *0x08049205
```

Alternatively, we can use a relative address, like so:

```abap
gdb➤ b *(vuln+84)
```

Both methods work the same way; you can use either. Now let’s run this binary using the command:

```abap
gdb➤ run
```

The program will wait for input. Let’s try `IAmMrRobot` as the password. After entering the password, the program will hit the breakpoint. We can now check where we are by using the command:

```perl
gdb➤ disass $eip
```

In 32-bit architecture, `$eip` always points to the instruction that is about to be executed, and the `$` signifies that we are referencing the value of `eip`.

The output of `disass $eip` will look like this:

```perl
   0x080491b1 <+0>:	push   ebp
   0x080491b2 <+1>:	mov    ebp,esp
   0x080491b4 <+3>:	push   ebx
   0x080491b5 <+4>:	sub    esp,0x34
   0x080491b8 <+7>:	call   0x80490c0 <__x86.get_pc_thunk.bx>
   0x080491bd <+12>:	add    ebx,0x2e37
   0x080491c3 <+18>:	mov    DWORD PTR [ebp-0xc],0x0
   0x080491ca <+25>:	mov    eax,DWORD PTR [ebx-0x8]
   0x080491d0 <+31>:	mov    eax,DWORD PTR [eax]
   0x080491d2 <+33>:	sub    esp,0x4
   0x080491d5 <+36>:	push   eax
   0x080491d6 <+37>:	push   0x32
   0x080491d8 <+39>:	lea    eax,[ebp-0x2c]
   0x080491db <+42>:	push   eax
   0x080491dc <+43>:	call   0x8049050 <fgets@plt>
   0x080491e1 <+48>:	add    esp,0x10
   0x080491e4 <+51>:	sub    esp,0x8
   0x080491e7 <+54>:	lea    eax,[ebx-0x1fd4]
   0x080491ed <+60>:	push   eax
   0x080491ee <+61>:	lea    eax,[ebp-0x2c]
   0x080491f1 <+64>:	push   eax
   0x080491f2 <+65>:	call   0x8049030 <strcmp@plt>
   0x080491f7 <+70>:	add    esp,0x10
   0x080491fa <+73>:	test   eax,eax
   0x080491fc <+75>:	jne    0x8049205 <vuln+84>
   0x080491fe <+77>:	mov    DWORD PTR [ebp-0xc],0x1
=> 0x08049205 <+84>:	cmp    DWORD PTR [ebp-0xc],0x0
   0x08049209 <+88>:	je     0x8049212 <vuln+97>
   0x0804920b <+90>:	call   0x8049186 <win>
   0x08049210 <+95>:	jmp    0x8049224 <vuln+115>
   0x08049212 <+97>:	sub    esp,0xc
   0x08049215 <+100>:	lea    eax,[ebx-0x1f88]
   0x0804921b <+106>:	push   eax
   0x0804921c <+107>:	call   0x8049060 <puts@plt>
   0x08049221 <+112>:	add    esp,0x10
   0x08049224 <+115>:	nop
   0x08049225 <+116>:	mov    ebx,DWORD PTR [ebp-0x4]
   0x08049228 <+119>:	leave
   0x08049229 <+120>:	ret
```

It points to the location where we want to stop. Now, let’s see what the value of `ebp-0xc` is using this command:

```perl
gdb➤ x/x $ebp-0xc
0xffffd6fc:	0x0804a08000000000
```

Here, the first `x` is the command in GDB used to examine memory at a given address. The `/x` specifies the format, telling GDB to output in hexadecimal format. The value of `DWORD PTR [ebp-0xc]` will only look at the lower 32 bits, resulting in `0x00000000`, which is the value of the `password` variable

Now, let’s rerun the binary with the `r` command, but this time with a larger input of `AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA`, and see the value of `ebp-0xc`:

```perl
gdb➤  x/x $ebp-0xc
0xffffd6fc:	0x4141414141414141
```

🤯 We have overwritten the value of `password` with `0x4141414141414141`, which is the hexadecimal value of `AAAAAAAA`. This is due to the buffer overflow in the `buffer`. The `buffer` variable is set to be 32 bytes, but we tried to write 50 bytes using `fgets`, so we overwrite the extra bytes on the stack where other variables are stored. Hence, this leads to a stack buffer overflow.

So you remember the segmentation fault , you can try to find out what causes the segmentation fault. if you get that you can also understand the payload given in previous article.
