Overflow in Motion

Demonstrate how a simple buffer overflow vulnerability in a C program can be used to manipulate the value of an adjacent variable in memory without directly modifying it in code

In this blog, we’ll walk through a basic buffer overflow in C where we'll change the value of a variable . This won't involve shellcode or advanced exploitation, it' s just a clear, beginner-friendly demonstration of how overflowing memory affects adjacent data.

Here’s the vulnerable code:

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

int main() {
    char buffer[8];
    int flag = 0;

    printf("Enter some input: ");
    gets(buffer);  

    if (flag == 1) {
        printf("Buffer overflow successful! 🎉\n");
    } else {
        printf("Try again. Flag is still %d.\n", flag);
    }

    return 0;
}

Understanding the Code

This simple program isn’t meant to be dangerous. In fact, on the surface, it looks like a basic input-checking example. Let’s walk through what it's trying to do:

  • It declares a small character buffer (char buffer[8]) to store user input.

  • It sets a flag variable (int flag = 0) used to determine if some specific condition is met.

  • It then takes input using gets(buffer), and checks:

    • If flag == 1, it prints a success message.

    • Otherwise, it says “Try again.

Now, if you're comfortable with programming, you'll notice something odd:

Nowhere in the code do we ever assign flag = 1.

So under normal conditions, this if block should never execute. The message Buffer overflow successful! 🎉 should never appear.

But here’s the problem:

⚠️ Why gets() Is Unsafe (and Useful Here)

The function gets() doesn’t check how much input you provide it just keeps copying characters into memory, even if the buffer overflows. That’s what makes it dangerous in real programs, but perfect for our demo.

Think of it like a bucket under a tap with no overflow protection. Once the bucket (buffer) fills up, water (input) keeps spilling out soaking nearby things like our flag variable in memory.

That’s how we’re able to change its value without directly touching it in code.

Now that we understand how gets() can overflow the buffer, let’s see how we can take advantage of this behavior to manipulate memory and change the flag without ever touching it in code.

Compiling and Running the Code

To test this buffer overflow, we’ll need to compile the C program in a way that disables certain security features that would normally stop this kind of behavior.

gcc -fno-stack-protector -z execstack -o bof_demo bof_demo.c

What This Does:

  • -fno-stack-protector: Disables stack protection (normally used to detect overflows).

  • -z execstack: Allows execution on the stack (not needed for this example, but used in advanced exploits).

Now Let's run the binary

You may have noticed that the program accepts 18 characters of input Can i get the flag without crashing. That’s expected we're not breaking anything (yet), just overflowing memory very deliberately.And it is very as it was intended to be because flag value can never be 1 so it is giving out put try again

🧨 Now Let’s Exploit the Vulnerability

Here’s the input we used to exploit the vulnerability:

python3 -c "print('A'*8 + '\x01\x00\x00\x00')" | ./bof_demo

What this does:

  • 'A'*8 fills up the 8-byte buffer completely.

  • '\x01\x00\x00\x00' is a 4-byte integer (in little-endian format) that overwrites the flag variable, setting it to 1.

🧠 What Just Happened?

Without changing the source code or directly assigning a new value to flag, we’ve manipulated the program’s logic just by overflowing memory. The condition in the code:

if (flag == 1)

which normally evaluates to false, now passes and we get:

Buffer overflow successful! 🎉

This demonstrates the core idea behind buffer overflows: when a program trusts user input without enforcing boundaries, it gives attackers a way to inject values, change behaviour, and even take control of execution flow.

🧠 Curious about what’s really happening under the hood? Read the next page.

Last updated