Basic ret2win Buffer Overflow: Your First Stack Smashing

August 31, 2025

Basic ret2win Buffer Overflow: Your First Stack Smashing

Challenge 1: Simple ret2win Buffer Overflow (1_simple.c)

Source Code:

#include <stdio.h>

int main() {
    char name[64] = {0};
    read(0, name, 120); // reading too much input so we can return to win()
    printf("Your name is %s", name);
    return 0;
}

int win() {
    system("/bin/sh");
    return 0;
}

// This is a basic ret2win Bof example
// Compiles gcc -Wall -Wextra -Iinclude -g -fno-stack-protector -z execstack -no-pie -Wl,-z,norelro -o bin/1_simple src/1_simple.c

What it does:

This is a basic ret2win buffer overflow challenge that demonstrates a classic stack overflow vulnerability.

Vulnerability:

  • Allocates a 64-byte buffer for name
  • Uses read(0, name, 120) which reads 120 bytes into a 64-byte buffer
  • This allows 56 bytes of overflow past the buffer boundary
  • The overflow can overwrite the return address on the stack

Other Functions That Can Cause Similar Buffer Overflows:

Input Functions:

  • gets() - reads until newline with no bounds checking
  • scanf("%s", buffer) - no bounds checking on string input
  • strcpy(dest, src) - no bounds checking when copying strings
  • strcat(dest, src) - concatenates without checking destination size
  • sprintf(buffer, format, ...) - can overflow if format string is too long

Example vulnerable code patterns:

char buffer[64];
gets(buffer);                    // Dangerous - no bounds check
scanf("%s", buffer);             // Dangerous - no bounds check
strcpy(buffer, long_string);     // Dangerous - no bounds check
sprintf(buffer, "%s", long_str); // Dangerous - no bounds check

Safer alternatives:

  • fgets(buffer, sizeof(buffer), stdin) instead of gets()
  • scanf("%63s", buffer) to limit input size
  • strncpy() and strncat() with proper size limits
  • snprintf() with buffer size specified

Exploitation:

  • The program contains a win() function that spawns a shell (system("/bin/sh"))
  • By overflowing the buffer, we can overwrite the return address to point to win()
  • Payload structure: 64 bytes of padding + 8 bytes (return address) = 72 bytes total

Compilation:

gcc -Wall -Wextra -Iinclude -g -fno-stack-protector -z execstack -no-pie -Wl,-z,norelro -o bin/1_simple src/1_simple.c

Security mitigations disabled:

  • -fno-stack-protector: No stack canaries
  • -z execstack: Executable stack
  • -no-pie: No position independent executable
  • -Wl,-z,norelro: No RELRO (relocation read-only)

Try it yourself with my Github Repo - Exploit Development Step-by-Step There you are able to check the whole code and also the full exploit script.