Here are the links to the previous 2 posts related to this topic:
Prepare, Bait, Hook, Execute and Control - Exploit Kits
Prepare, Bait, Hook, Execute and Control - Phishing
Lab
In the previous post, you read about exploit kits and how they work. As described by Palo Alto, after a device hits a landing page that is infected, the device is then evaluated against a series of exploits to see which would work, the exploit is triggered and then the payload is delivered. The exploit that was triggered was an Adobe Flash heap based buffer overflow (I think).
In the post below I would like to explore how an exploit would be discovered using fuzzing. Then overwriting of a buffer to gain control of what is called an extended instruction pointer or EIP. With being able to control the EIP change the next instruction to be executed to a command that I would like to execute. This is different than the Adobe Flash heap based buffer overflow, however this is where you may need to begin to build a foundation of understanding.
1. The buffer overflow example I am going to demonstrate is a simple stack based buffer overflow. This is a real simple example, but remember when you learned to ride a bike, you probably started with training wheels.
2. First we need to use a VM that is 32 bit. I am going to use the Billu_b0x VM that we used previously. The first step is you need to briefly change the network interface to be NATed and install gdb.
Command: apt-get update; apt-get install gdb
* Change the network interface back to host only when you are done. Remember to not trust what you do not build and secure and even then be careful.
3. GDB is short for the GNU Debugger. We will use it for looking at the registers and memory as we conduct the exercises below. Now let's build a vulnerable C program that we can utilize. On the Billu_b0x, after I connected with SSH from my host, I created a directory called prog.
Command: mkdir prog
Command: cd prog
4. Below is the vulnerable C program that I created and will be using. I called the program c_prog.c.
#include
int main(int argc, char *argv[])
{
char buff[180];
if (argc == 2) {
strcpy(buff, argv[1]);
if (strcmp(buff, "aS3cr3tP@ssword")) {
printf("You shall not pass!\n");
}
else {
printf("You may enter at your own risk...\n");
}
}
else {
printf("To login the syntax is: %s \n", argv[0]);
exit (0);
}
return 0;
}
To step through the program. I setup a character buffer of 180 characters. Then I read in the first argument being the filename that I execute then the second argument being the password. If I do not put a password in-place then it reminds me of the syntax that I need to use. If the password does not match what I have, then it does not log me in. If it does match then display a message in the console to enter at your own risk.
5. After creating the simple program I compiled it using gcc.
Command: gcc c_prog.c
*The warnings that are displayed we will ignore for now. If there are any errors please correct them by verifying your code.
6. If not specified, when you compile a program using gcc and you do not specify the output filename it will give the compiled program the name of "a.out". Let's test "a.out" to verify it is working.
7. Now I am going to fuzz the password field to see how long the buffer is. To fuzz the password, we are not trying to guess it or brute force it. We are trying to send various characters at different lengths to see if we can get it to crash.
8. If you followed the commands that I executed above, first I sent 50 letter A's into the program as my password, then 100, 150 and 200. When I reached sending in 200 it came back stating "stack smashing detected" and then displayed segmentation fault. We can conclude that the buffer is between 150 and 200 characters long. Let's try another round of fuzzing to see if we can be more precise on how long the buffer is.
9. From the above screenshot we can see that the buffer is now between 180 and 184 characters in length because it crashes on 185 characters. After a little more research you can tell that the acceptable buffer length is 180 characters.
10. Before we continue, we need to make a couple of adjustments to allow us to be able to complete the lab. The first adjustment is, the Billu_b0x and modern day operating systems, have stack protection built-in. This protection will randomize the placement of the stack in memory so that it is less predictable to overwrite and other protections exist also. You can study more about that in your spare time. As root execute the following command to disable the stack protector.
Command: sysctl kernel.randomize_va_space=0
11. The gcc compiler also has protection built-in to protect the stack. The following command will recompile the c_prog.c without the stack protector and will include the debuging information we need for future exercises.
Command: gcc -ggdb -fno-stack-protector c_prog.c
12. After you complete steps 10 and 11 repeat step 7 to cause the "stack smashing detected". You should see different results as shown below.
13. Let's use gdb to demonstrate what we are trying to accomplish with smashing the stack.
Command: gdb -q a.out
(gdb) list
(gdb) <enter>
(gdb) <enter>
14. As you can see above we can list the code. With compiling the c_prog.c with -ggdb we can see the source code in the debugger. On line 10 we are copying our input into the buffer. The buffer is built for 180 characters and we are going to push 500 characters into it. This overflows the buffer. To be able to see this in the debugger we are going to place a breakpoint on line 11. A breakpoint will stop the execution of the program on that line.
(gdb) break 11 OR (gdb) b 11
* The breakpoint is not necessary, however it is a concept you need to know about gdb.
15. Now to run the program we type run and then after put in the password that the program is looking for, exactly as if we were running it in the terminal.
(gdb) run testPassword
16. Notice that the argv=0xbffff7f4 is set. Then you can type step to then step through the rest of the program. Eventually the program will terminate, but you should see, minus the code, what would be displayed in the terminal.
17. Now let's run the program again inside of the debugger. If you had to leave gdb and then rerun it to get back into gdb you will need to resetup the breakpoint on line 11. This time we are going to overflow the stack using python to write 500 A's or 0x41 into the buffer.
(gdb) run `python -c 'print "A"*500'`
18. Notice that the argv=0x41414141 or if you convert the hex to ASCII you notice that we have overwritten the argument with AAAA. That means that I can control the program cause I can overwrite what is in memory because no bounds are placed to disallow me to put more information into the buffer than is specified.
19. Let's rerun the program in the debugger with inserting exactly 180 A's into the buffer. We are going to examine the ESP register. The esp is the extended stack pointer. It points to the top of the stack. So we are going to step through the program and then before it finishes we are going to examine 200 hexadecimal values starting at the ESP register.
(gdb) x/200x $esp
20. In the above image you can see that we inserted into the stack the 180 A's. To demonstrate smashing the stack or the goal of overwriting the EIP register, we are going to use the letter B. This is so we can see it in the debugger.
(gdb) run python -c 'print "A"*180 + "B"*4'`
(gdb) step (3 times)
(gdb) x/200x $esp
21. In the above image we are placing 184 characters into the buffer which overflows the designated size of the buffer. In the above image your can see 0x42424242 to demonstrate where we overflowed the buffer. Compare it to the image in step 19. Notice in the image we had 3 0x00000000 now we only have 2. If you step 2 more times in the code it will exit normally.
22. Let's change from adding 4 B's to 8 B's.
(gdb) run python -c 'print "A"*180 + "B"*8'`
(gdb) step (3 times)
(gdb) x/200x $esp
23. In the above steps we have talked about the esp register and the eip register. If we can control the EIP register then we can modify the next instruction or code that is executed. First let's learn how to display the registers in gdb.
(gdb) info registers OR (gdb) i r
24. Repeat steps 20 through 23 until you can overwrite the EIP register as displayed below in the image. Try and do it by adding 4 B's at a time.
25. After you overwrite the EIP register examine from the ESP register as we did above. We are looking for a memory address that may be consistent. To speed up this process I am not going to set a breakpoint.
26. Notice we need to take away 2 things. The first is a memory address of where the A's are being placed consistently. I am going to pick the following.
Memory Address: 0xbffff890 (Note: yours may be different)
Now go back and run the program in the debugger and verify that this address consistently has 0x41414141 next to it.
27. The next thing I need to calculate is how many A's into the 180 character buffer is the memory address. We do not need to be exact as long as what we do equals 180.
Number of A's: 30
28. So let's imagine that the code I want to execute is 50 hex characters long. I would run the program in gdb with the following command, which would include my code indicated by the letter C.
(gdb) run `python -c 'print "A"*30 + "C"*50 + "A"*100 + "B"*16'`
29. Now that we can see that we have introduced the code, we want the EIP register to call the memory address 0xbffff890 and then the code would be executed. To do this we need to modify the last 4 B's. Without going into much detail the registers work in Little Endian format. We need to write the memory address in little endian formal as shown below.
(gdb) run `python -c 'print "A"*30 + "C"*50 + "A"*100 + "B"*12 + "\x90\xf8\xff\xbf'`
30. Notice that we have controlled the EIP register and pointed to where we could place our code. This is where I am going to end this. However, if you would like to go further on generating a payload and learning more about exploit development study the following links.
Binary Payloads - Metasploit Unleashed
Corelan Exploit Writing Part 1
Also study about:
More and More and More about Smashing the Stack on Windows and Linux
Heap Spraying
Use-after-Free
....
Check out the pwn2own and other similar competitions. Exploit development may be difficult to learn but it pays very well if you are great at it.
No comments:
Post a Comment