Shellcode Injection Buffer Overflow: Beyond ret2win

September 2, 2025

Shellcode Injection Buffer Overflow: Beyond ret2win

Challenge 2: Simple Shellcode Buffer Overflow (2_simple.c)

Source Code:

#include <stdio.h>

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

// Now we have to create shellcode
// Compiled: gcc -Wall -Wextra -Iinclude -g -fno-stack-protector -z execstack -no-pie -Wl,-z,norelro -o bin/2_simple src/2_simple.c

What it does:

This is a buffer overflow challenge that requires shellcode injection since there's no win() function.

Vulnerability:

  • Allocates a 64-byte buffer for name
  • Uses read(0, name, 150) which reads 150 bytes into a 64-byte buffer
  • This allows 86 bytes of overflow past the buffer boundary
  • Unlike challenge 1, there's no convenient win() function to return to

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

Why shellcode injection works here:

  • All these functions can be exploited in the same way when combined with:
    • Executable stack (-z execstack)
    • Disabled stack protector (-fno-stack-protector)
    • No ASLR/PIE (-no-pie)

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:

  • Since there's no win() function, we need to inject our own shellcode
  • The executable stack (-z execstack) allows code execution from the stack
  • Payload structure: shellcode + padding + return address pointing to shellcode

Compilation:

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

Security mitigations disabled:

  • Same as challenge 1, with the key difference being -z execstack which is crucial for shellcode execution

Key Differences:

  1. Challenge 1: ret2win technique - redirect execution to existing win() function
  2. Challenge 2: Shellcode injection - inject and execute custom assembly code

Both challenges use identical compilation flags that disable modern security protections, making them ideal for learning basic buffer overflow exploitation techniques.


Binary Exploitation Learning Path

Previous: Basic ret2win Buffer Overflow - Learn the fundamentals of return address hijacking

Next Steps:

-- 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.