After a long hiatus, we shall Yet again emerge via the shadowy depths of the internet to build an exploit. This specific time, we’ll be looking at how to defeat a non-executable stack by using the ret2libc technique — a lean, mean, in addition to brilliant way of exploiting a stack overflow vulnerability.
Since This specific has been so long since we last built an exploit together, This specific might be a not bad idea to review a few key topics to developing exploits, such as what a stack overflow vulnerability is usually in addition to what is usually the instruction pointer. So make sure to go over of which stuff below before jumping to Step 1 of This specific exploit development tutorial.
A stack overflow vulnerability occurs when a program improperly allocates memory for a variable on the stack. For instance, let’s say we set aside 16 bytes of memory for a variable called “movieName.” We spend hours devising an intuitive system where users can enter inside name of a movie to store This specific in This specific variable, in addition to This specific looks beautiful. We have created the most gorgeous input box known to man.
This specific input we created becomes useless, however, because we completely forget to check if the user is usually inputting a movie name of which is usually longer than 16 bytes (or 16 characters). One user inputs an obnoxiously long title such as “The Emperor’s fresh Groove,” in addition to our whole program breaks! This specific happens because the user input exceeds the 16 bytes of memory we allocated for This specific in addition to overflows into memory meant to contain some other variables or data. Gross.
As a hacker, however, these sorts of vulnerabilities can be super useful. If we can keep track of what data we’re overwriting, in addition to what fresh data we are replacing This specific with, we could gain a lot of control. Enter the instruction pointer.
What is usually the Instruction Pointer?
The instruction pointer, also known as EIP, contains the memory address of the next instruction to execute. If we were able to overwrite EIP with our own memory address, we could redirect code execution of the entire program. of which sounds like fun. Of course, we can’t review everything we’ve learned so far here, so check out the article linked below to re-learn the fundamental ideas of which you’ll need to finish This specific tutorial.
What’s the Catch?
Of course, most programmers don’t just say “oh well” in addition to let us ruin their programs. Different strategies for protecting against stack overflow vulnerabilities have been devised. One particular strategy is usually to make sure the program knows not to execute any instructions of which are located somewhere on the stack. This specific is usually a problem for us.
Thankfully, our dear friend Protostar, the virtual machine, has an exploit development challenge of which will help us learn how to get around This specific. Let’s take a look at the stack6 level on Protostar in addition to see what we can learn!
Step 1: Taking a Look at the Source Code
As always, the first thing we should do is usually take a look at the source code on Exploit Exercises to see what we’re up against:
Let’s break This specific code down line by line:
- In lines 8 in addition to 9, we see two variables defined. The first one is usually an array of characters named “buffer” which is usually given a size of 64 bytes. This specific means This specific can hold at most 64 characters. This specific is usually not bad to know. Next, we see an integer named “ret” defined. We haven’t seen a variable like This specific in previous exercises before, so This specific’ll be interesting to see what This specific is usually used for.
- In line 11, the program prompts the user for input, in addition to on line 13 This specific input is usually passed to the buffer variable. Notice how the program doesn’t check to see if the user input will fit inside the 64 bytes given to buffer. of which’s pretty dumb although actually not bad for us so we won’t tell the programmer. Shh.
- today, in line 15, the variable ret pops up again. This specific is usually actually an assignment statement. The __builtin_return_address(0) refers to EIP. This specific turns out This specific line is usually storing the value of EIP into the ret variable. Why on earth would likely the programmer be doing of which? …
- Well, in line 17, we find out, in addition to as attackers, the answer isn’t not bad. Line 17 holds what seems to be a cryptic “if” statement. This specific if statement is usually using what is usually called a bitwise operator to check if the address written to the instruction pointer starts with the byte “0xbf.” If the address does start with This specific byte, the program stops the execution.
Well, of which’s not not bad. Maybe the programmer isn’t so dumb after all. Essentially, This specific means of which we can’t overwrite EIP with any address of which starts with “0xbf.” This specific is usually a problem because, in This specific challenge, any shellcode we could write will always be located in a memory address of which starts with “0xbf.” How inside heck are we going to exploit This specific program then? We’ll worry about what we’re going to overwrite EIP with later. For today, let’s just start with actually overwriting EIP with anything at all.
Step 2: Building the Framework of Our Exploit
Let’s SSH into the Protostar VM in addition to get cracking. If you don’t already have Protostar installed, check out our guide on how to install Protostar as a virtual machine.
Once Protostar is usually all set up, use your favorite SSH client to log in. The username to log in is usually user in addition to the password is usually also user. Once we’re logged in, let’s spruce up our terminal prompt a little bit. By default, Protostar serves us a /bin/sh shell for us, although This specific can be sort of limiting. We want a fully featured, glorious /bin/bash prompt instead. To get one, type:
Simple as of which. today let’s open up a fresh file by typing the following command:
After of which, we’ll build the framework for our exploit by typing the code inside screenshot below.
- As always, the first line is usually optional. All This specific does is usually tell the OS of which when This specific program is usually executed, This specific should be executed as a Python script. While This specific line enables us to execute the script directly, This specific is usually not needed to run the script via the python command.
- The next two lines import the struct in addition to os packages for use in our program. We’ll use struct later, although we’ll need the os package right away.
- Next, we define our main function. Here we start by defining an integer called padding. This specific variable will determine how long we make our buffer overflow. As we can see on the next line, we store our payload variable first with the letter “A” multiplied by our padding variable. This specific means if padding is usually 4, we end up with 4 A’s in our exploit.
- The next three lines are fresh to This specific series. Instead of using the echo command to pass our payload to a text file, we are going to use Python’s file I/O to get the job done. The reason we’re doing This specific is usually because certain memory addresses create problems when they are passed directly to the shell.
Once we open, write to, in addition to close our payload.txt file, we are ready to pass the payload to the vulnerable program. This specific can be done right inside shell, so we use the os.system command to do This specific. We first use the cat command to read the contents of payload.txt to standard output, then we use the pipe (“|”) command to redirect standard output to the standard input of the vulnerable stack6 program.
Let’s save This specific, run the program in addition to see what happens:
Well, we didn’t see any terribly exciting output, although This specific is usually a nice confirmation. The framework of our exploit works. today This specific’s time to jump back into the fray in addition to indulge inside delicious world of the GNU debugger (GDB).
The quickest way for us to determine how large our exploit needs to be is usually by looking at the memory of the program. Let’s hop into GDB in addition to take a peak. To do This specific, we type:
Doing so should result in output of which looks similar to the screenshot below.
Once GDB has started off up, we need to set a breakpoint. This specific breakpoint will stop execution at a certain point to ensure we can identify the values of variables in addition to registers at of which instant. Looking back at the source code, line 22 seems like a not bad candidate. This specific is usually because at This specific point the program has already received in addition to processed the input via the user, although hasn’t printed the user input yet. We don’t actually want to see the user input because once we start inserting memory addresses into our payload, the whole thing will look actually messy. For the sake of organization, This specific makes sense to break before This specific happens.
To set a breakpoint at line 22, we type:
Pretty simple. today This specific’s time to run the program. In order to run the program in addition to pass This specific our current payload via inside GDB, we’ll have to type:
run < payload.txt
At This specific point, our screen should look something like This specific:
As you can see, we’ve hit our breakpoint in addition to can begin looking at memory. Specifically, we are going to want to look at the current stack frame. This specific is usually where our payload will be, as well as the instruction pointer. In order to do This specific, we’ll type:
The first x is usually short for “examine.” This specific command allows us to examine memory, so the name is usually fitting. The /32 specifies of which we want to examine the next 32 four-byte segments. The final x at the very end tells GDB of which we want to view This specific section of memory in hexadecimal format. The last term, $esp, tells the command to start looking at the memory at the very beginning of the current stack frame.
Let’s see what output we get via This specific command:
Well, would likely you look at of which. … We’ve found our A’s! They were right where we left them inside stack frame. We can see here of which our four A’s start at the memory location 0xbffff77c in addition to fill through 0xbffff77f. This specific is usually actually useful. today of which we know where our payload starts, all we need to do is usually figure out where the instruction pointer is usually. Then we will be able to determine how long our payload should be.
This specific is usually very trivial for us. In order to locate the instruction pointer, all we have to do is usually type:
In addition to giving us information about the instruction pointer, we’ll also see some other information about the current stack frame with This specific command. For our purposes, however, This specific information is usually extraneous in addition to not needed. Let’s take a look at the output we get via This specific command:
Lo in addition to behold, we have precisely just what we need. By running the info frame command, we can today see of which the instruction pointer is usually located at the memory address 0xbffff7cc (highlighted in red) in addition to contains the address 0x08048505 (highlighted in green). This specific isn’t too far via the start of our payload. In fact, we can figure out just how far apart those two addresses are by typing the following command.
p 0xbffff7cc – 0xbffff77c
Typing This specific gives us a result of 80. This specific means we need a total of 80 A’s as padding to overflow memory right up to EIP. While 80 A’s won’t actually overwrite EIP, This specific will be one byte away via doing so. Let’s test of which theory.
We can exit GDB by typing the command quit. Once we’ve done of which, let’s hop back into our exploit by typing nano exploit.py. Let’s change the value of our padding variable via 4 to 80 in addition to see what the memory looks like in GDB.
Once the padding variable has been modified, save in addition to close exploit.py. Let’s run the exploit in addition to see what happens:
Well, of which is usually absolutely bizarre. Not only does the program output appear twice, although we have some weird stuff happening to our PuTTY prompt. If you are using a program some other than PuTTY, your output might look different, although This specific’s probably still very weird. Most notably, we seem to have caused a segmentation fault inside program. Usually, This specific indicates of which we actually overwrote the instruction pointer. of which wouldn’t make sense, though, since we just did the math. Let’s look at another GDB memory dump in addition to see what we find:
Repeating the same steps as earlier, we’re able to see a memory dump of the stack frame with our fresh payload. Sure enough, we have filled the memory with just enough A’s to bring us next to EIP without messing with This specific. of which segmentation fault we saw earlier must be caused by a different breakdown inside program’s logic by our exploit. This specific shouldn’t impact our exploit itself though.
If you’ve been following This specific tutorial series, much of This specific is usually most likely review for you. You’ve interacted with GDB, looked over source code, in addition to pushed more A’s around than you’d care to admit. You’re ready for the fresh stuff, in addition to fresh stuff you shall get. Let’s finally walk through what the ret2libc technique actually is usually.
Essentially, the problem we’re faced with is usually This specific: In order to get a shell inside past, we have written shellcode inside a variable in addition to overwritten the instruction pointer with an address of which would likely eventually point to This specific shellcode. In This specific challenge, we can’t point EIP anywhere near where we can put shellcode. With This specific in mind, where on earth do we redirect EIP to? The answer is usually simple: We redirect EIP to system.
Believe This specific or not, you’ve already created a system call. If we look at our current exploit, at the very end we use a function called os.system which passes an argument as a system command. We can do the very same thing inside of our vulnerable program. If we were to give EIP the address of the system function, we could tell the system to execute /bin/sh in addition to bless us which has a shell.
In order to successfully execute the system function, we have to follow a certain template in our exploit of which looks something like This specific:
The reason This specific order is usually required has to do with the function prologue of the system function. Essentially, This specific is usually the part of the function of which sets up the stack frame the function will use. This specific includes producing sure of which arguments are passed to the function correctly.
The first argument for the system function occurs four bytes after the initial call to the function. How all of This specific works features a lot to do with the actual assembly instructions, which we won’t get into. For today, just know of which we need an extra four dummy bytes after the address of system in order for the function to correctly read the address of our string.
We can’t actually just pass “/bin/sh” in our exploit. The system function takes a pointer to a string, not a string itself. This specific means of which we store the string “/bin/sh” somewhere else in memory in addition to pass the memory address to the system function. This specific can be a bit annoying, although we’ll shove of which into the corner in addition to pretend This specific’s not there — for today. Let’s focus on the next step: Obtaining the address of system.
Finding the address of system is usually actually a pretty straightforward process in GDB. Let’s jump back into GDB in addition to reset our breakpoint again. Once of which’s done, we’ll type run to start the program. We don’t need to pass our payload This specific time because we aren’t concerned with looking at memory. Instead, feel free to just type whatever you want into the program’s prompt, in addition to hit enter. Doing so will trigger the breakpoint.
Once we’ve hit the breakpoint, we need to type the following command.
This specific will print out information about the system function, including its address. inside above image, the address of system is usually highlighted in red. Write of which address down somewhere — we’re going to need This specific soon.
Step 7: Implementing a Call to System in Our Exploit
Let’s exit out of GDB in addition to open our exploit, which will today look something like This specific:
We’ve changed two things here: First, on line 7, we’ve created a fresh variable called system_addr. As you may have guessed, This specific will hold the address of system. Like we’ve done inside past, we’ll use the handy-dandy struct.pack function to package the address of system inside correct format. We then append This specific address to the end of the payload string, followed by the four dummy bytes we saw in our diagram earlier.
If we saved in addition to ran the exploit at This specific point, we wouldn’t actually see anything exciting. In fact, the exploit would likely behave exactly the same as This specific had before we made these fresh modifications. The reason just for This specific is usually because we haven’t passed any real arguments to system yet. The Python equivalent of our current exploit would likely be This specific:
of which sucks. of which’s boring. of which’s going to change. Our next mission is usually to find a string somewhere inside program of which contains “/bin/sh.” This specific will be a grind.
At first glance, looking for the string “/bin/sh” inside a program seems to be a bit of a wild goose chase. Why would likely of which string exist inside stack6 program? of which’s a great question because the string won’t actually be incoming via the program. We’ll find our target string inside environmental variables of our current shell session.
Don’t believe me? Let’s type the following command in addition to see.
BOOM. There This specific is usually. This specific variable, along with every some other environmental variable, is usually loaded into every program of which is usually run via This specific shell. If we can find where in memory This specific string is usually, we can use This specific as the argument to our system call. Finding This specific won’t be easy though.
We might as well get started off, so let’s open GDB back up in addition to start searching. Yet again, we’ll set a breakpoint at line 22 in addition to run the program. Passing payload.txt as input is usually not necessary This specific time.
Once we hit our breakpoint, we’re going to type something a little different. Take a look at the following command:
This specific looks intimidating, although we’ll break This specific down.
The first part should look familiar. The x at the very beginning tells us of which we are using the examine command of which we know in addition to love. Instead of passing /x, however, we pass /s as the first argument. This specific means of which instead of examining the data in hexadecimal format, we want to examine the data as a string. We do This specific because This specific would likely be actually hard to identify the string “SHELL=/bin/sh” in hexadecimal format.
The last portion of the command is usually the most arcane looking. Let’s actually start by defining what the term environ means. Here, environ is usually a pointer to a pointer for the environmental variables of a program. As obnoxiously abstract as of which sounds, essentially what of which means is usually of which environ contains a memory address which points to another memory address. In This specific second memory address, the starting address of the environmental variables is usually stored.
We don’t want the pointer address, though, we want the address of the environmental variables. To get This specific, we have to dereference the pointer. When we dereference a pointer, we grab the value via the memory address of which is usually stored inside pointer. This specific is usually a common idea inside C programming language, although This specific can be tricky to understand at first. Take a look at the diagram below for an explanation of what’s going on.
Essentially, the environ variable contains a memory address. This specific is usually similar to the system_addr variable in our exploit. The value stored at of which memory address is usually another memory address. This specific value is usually the address of the environmental variables. While This specific seems convoluted, This specific allows us to quickly iterate through the environmental variables inside program until we find the one we want, like so:
This specific will show us the second environmental variable in memory, regardless of how long the first one is usually. This specific makes digging through the memory much easier. All we have to do is usually keep incrementing our addition to environ until we find the SHELL variable like so:
Bingo. The address of /bin/sh. Well, sort of. inside above screenshot, the address 0xbfffff88 points to the string “SHELL=/bin/sh.” We only want “/bin/sh.” This specific is usually a simple fix though. All we have to do is usually add 6 to the address when we pack This specific in our exploit. No problem. Let’s add This specific address to our exploit in addition to see what happens!
today of which we have This specific address, our exploit should look something like This specific:
As you can see we’ve added a variable called shell_addr. We slap This specific on the back of our payload string to finish implementing the exploit template we looked at earlier. Let’s save our exploit in addition to see what happens!
After all of our hard work, This specific appears we’re done. This specific’s time to bask in our glorious fresh exploit in addition to pop a root shell on stack6. Let’s see This specific!
What? What happened? We did everything right. We found the address of system, the address of /bin/sh, in addition to put them all together correctly. Why did This specific exploit not work?
Well, there’s a couple reasons. Let’s start with the first one: We didn’t actually find the correct address of /bin/sh. We found the address when the program is usually running inside GDB. The address of /bin/sh modifications outside the debugger. So how do we find the real address of /bin/sh?
The first thing we could try to do is usually guess the address of /bin/sh, although of which might take awhile. While the address we have via GDB is usually somewhat close, This specific will still take a lot of guessing to find what we want.
Determining exactly where the string /bin/sh might be in memory is usually possible, although complicated. We could write another tutorial for just of which. However, we can still get closer than we actually are. If we can print the address of SHELL via a similar executable we create ourselves, we could get closer to finding the real slim SHELL. Let’s open up a fresh file in nano by typing:
In case you’re wondering, yes, we will be writing a simple C program. This specific’s the only way to do This specific. I promise This specific won’t be of which bad though. Let’s take a look:
See? This specific’s not so bad! Just a couple lines. The first line defines a pointer which stores the address of the SHELL variable. The second line prints This specific. Simple. To compile This specific program, type:
Once the program is usually compiled, This specific will be saved as an executable called a.out. To run a.out, type:
You should see the following:
Alright, today we’re getting closer. Our program is usually telling us of which inside a.out program, SHELL is usually located at 0xbfffff9de. We can be pretty confident This specific is usually an underestimate because our program is usually far simpler than stack6.c. The address will still be close though.
Let’s make some edits to our exploit:
We make two modifications here: First, we modify the address of shell to our closer estimate. The second change, however, comes inside system call on the last line of main. As you can see, cat payload.txt has become (cat payload.txt; cat).
As some of you might recall in our last stack overflow tutorial, running /bin/sh via an exploit can be tricky. This specific is usually because the standard output can close as soon as This specific opens. To make sure we’re not missing the correct address, we’ve kept the standard input in addition to output open which has a call to the cat command.
Alright! via here, This specific actually is usually just Guess City. Luckily for you, I’ve already done the guessing for you. Our estimate was still 1,465 bytes early via the actual address of SHELL. of which means the final exploit will look something like This specific:
Run of which bad boy, in addition to you should end up which has a shell like This specific:
While This specific exploit is usually not bad, This specific isn’t perfect. As you play around with your nice fresh shell, you’ll notice of which when you type the exit command, you end up which has a segmentation fault. of which isn’t very clean. The reason is usually This specific: After the system call we pass finishes execution, the instruction pointer goes to the next address. Remember what we set of which to? of which’s right, AAAA. of which will always cause a crash. This specific sure would likely be nice if there was a way to exit a little more nicely, although I’ll leave of which as an exercise for you to do on your own.
Thank you for reading! Congratulations on producing This specific through the slow grind. Comment below with any questions or contact me via Twitter @xAllegiance if you need help.