32-bit

file-archive
3KB

1. Analysis

We will start by inspecting the binary in Ghidra. Ghidra is a decompiler which translates low-level machine code into pseudo-C code to trace the somewhat original code

Original code:

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


void flag(int check, int check2) {
    if(check == 0xFACEB00C && check2 == 0x8BADF00D) {
        puts("How are you here??");
    } else {
    	puts("So close, yet so far...");
    }
}

void vuln() {
    char buffer[40];

    printf("There's nothing to see here right?\n> ");
    gets(buffer);
}

int main() {
    vuln();
    return 0;
}

Check the file type

Decompiled code (vuln function):

vuln()

You can also look at other decompiled functions in the Symbol Tree. Now, in this function we can clearly see the buffer is being read by gets which is a vulnerable function that reads more than the allocated bytes of the buffer

Let's take a look at flag()

flag()

Convert the values first into the original unsigned integers by right clicking and swap to the char

That looks more like the original code. The function tries to take in two arguments to validate and will output the win message if the value of the arguments are correct.


2. Plan

Seems easy enough, we just do a ret2win style attack but we will supply the correct parameters, the first one being 0xfaceb00c and the second one 0x8badf00d .

Find the offset first

Grab the address of flag() using gdb


3. pwntools

To ease our exploits we will be utilizng pwntools from now on

pwntoolschevron-right

pwntools comes with a lot of handy features such as p32() which is a function that automatically converts the address from Big-endian to Little-endian on a 32-bit binary. There is also p64() for 64-bit but we'll get to that later.


4. Exploit

One thing that should make you wonder is the 0x0. Unlike the previous example which we only return to the function to execute, we didn't care if the program crashed or not. As long as it printed our flag.

circle-info

In this case, we are required to provide parameters. When the EIP is filled with the flag() address. The EIP is going to look for the next instruction and this is where 0x0 (null return address) comes in, it acts as a placeholder so the stack won't misalign causing the process to crash .

And just like that, we called flag() with the correct params. If you notice in the debug section in this part, the 00 00 00 00 is the null return address we inputted followed by 0xfaceb00c and 0x8badf00d

Last updated