This Proof of Concept (PoC) demonstrates a classic stack-based buffer overflow vulnerability in a C program. It walks through the complete process of identifying the vulnerability, crashing the application, analyzing the stack memory, and finally constructing a payload to achieve arbitrary code execution by redirecting the instruction pointer.
Video Walkthrough: YouTube Link (Visual demonstration of the debugging and exploitation process).
For educational and research purposes only. Do not use these techniques on unauthorized systems.
overflow.c: The vulnerable source code containing thememcpyflaw and a hidden function.payload_good.txt: A benign 16-byte input file that allows the program to execute normally.payload_overflow.txt: An oversized input file to corrupt the stack and trigger a segmentation fault.payload_secret_func.txt: Crafted payload containing the padded buffer and the reversed (Little Endian) memory address to hijack execution.exploit.py: Python script to dynamically generate the Return-Oriented payload.
The vulnerability exists in the use of the memcpy function without proper bounds checking. The program attempts to copy a dynamically sized file input into a smaller, fixed-size 16-byte stack buffer.
When the input exceeds 16 bytes, it overflows the allocated buffer and overwrites adjacent memory on the stack, including the saved Base Pointer (EBP/RBP) and the crucial Return Address (EIP/RIP).
- Crash the program: Prove the vulnerability exists by overwriting the return address with junk data.
- Control the execution flow: Overwrite the return address with the specific memory address of a hidden
secret_function()that is never called during normal execution.
Modern compiler protections must be disabled to demonstrate this vulnerability.
- IDE: Visual Studio Code
- Compiler: GCC
- Debugger: x64dbg (Windows) / GDB (Linux)
gcc -fno-stack-protector -z execstack -o overflow overflow.c-fno-stack-protector: Disables the stack canary, allowing the overflow to reach the return address.-z execstack: Marks the stack as executable.
Providing the pre-made normal input file (payload_good.txt).
C:\> overflow.exe payload_good.txt
Input: AAAAAAAAAAAAAAAA
Buffer: AAAAAAAAAAAAAAAA size 16
[!] Program completed without crashing.Providing the oversized input file (payload_overflow.txt) to corrupt the stack.
C:\> overflow.exe payload_overflow.txt
Input: AAAAAAAAAAAAAAAAAAAAAAAAAA
Buffer: AAAAAAAAAAAAAAAAAAAAAAAAAA size 16
Segmentation fault (core dumped) / Program CrashesUsing x64dbg, we attach to the process to analyze the crash. We determine that a 24-byte offset (16 bytes for the buffer + 8 bytes for the base pointer) is required to reach the return address on the stack. We then locate the memory address of secret_function().
Because the architecture uses Little Endian format, the memory address of our target function must be written backwards (bytes reversed) into our payload file.
Method A: Manual Hex Editing (Shown in Video)
Using a hex editor, we create a new file and input 24 bytes of padding (e.g., Hex 41 for 'A'). Immediately following the padding, we append the reversed bytes of the target memory address.
Example: If secret_function() is located at 0x00007FF7D1B91710, we manually write it into the hex editor as:
10 17 B9 D1 F7 7F 00 00
Method B: Automated Generation (Included Script)
Use the provided script to pack the address dynamically. Update the target_address variable in exploit.py if the compiler maps the function to a different location.
python exploit.pyRunning the program with the crafted payload overwrites the return address exactly, hijacking the execution flow.
C:\> overflow.exe payload_secret_func.txt
Input: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...
Buffer: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA... size 16
[!] Success! You have hijacked the execution flow.
[!] Secret function executed.