Training - Exploit Development
Author: [email protected]
This training will cover the following topics from a technical and practical perspective, and starting from running and exploiting your first targets to gaining persistence and owning a whole network. This course builds deep background knowledge and expert-level skills and the ideal attendants will be penetration testers, security enthusiasts and network administrators.
- Concepts and basics
- Attacker Decision Making
- Getting started with Exploit Pack and Setup
- Internals of Exploit Pack
- Enumeration of Targets
- Exploiting the LAN
- Exploiting Windows Hosts
- Exploiting Linux Hosts
- Exploiting Web Servers
- Basic Exploit Writing
- Advanced technics and real world examples
- Post Exploitation
About the instructor:
Juan Sacco is the author and main devv of Exploit Pack, he currently works as an Exploit Writer and Reverse Engineer, in the pat he has worked at companies like ING Bank, Core Security, NOD32, Homeland Security (ARG) and other financial and security related organizations.
Concepts and basics
A “bit” of history about Exploits. Let’s start by saying that memory errors exploitations have been around since 1980’s and they still rank among other software errors like the most dangerous, from an integrity or availability perspective, the impact of a memory error exploit will for sure have a disruptive impact in any organization.
During this training we show you the history, the do, don’t and how’s of memory errors, exploitation technics, attacks, defenses and countermeasures. And all this will be covered not from a SysAdmin or Developer view, we will learn the practical way of a Black Hat hacker.
Introduction
Memory errors, overflows and exceptions are one of the oldest software vulnerabilities. These kind of vulnerabilities exists by design, and an attacker could take advantage of an overflow in order to takedown or remotely control a machine.
But let’s go back in time, and for this we need to talk a bit about history, and the origins of this flaws.
Join me to a time-machine read, let’s set our Flux condenser to take us back..
Precisely to November 2nd, 1988.
“If my calculations are correct, when this baby hits 88 miles per hours, your’re gonna see some serious events.”
Dr. Emmet brown ( A time traveler )
Ok, so here we are at 1988. Robert T. Morris abruptly brought down the Internet. Could you just imagine, having the power of taking down the whole Internet? Yes. Just wow, right?
Ok, wait. We know when. 1988, November 2nd. But Why.. and most important for us.. is how!
Robert Morris Jr. at this time is a graduate student in Computer Science at Cornell University, he just wrote a self-replicating, self-propagating program that created the name of “Cyber Worm”. He just deployed this program from the MIT itself, and to avoid trace backs he executed this piece of software from non-traced government computers.
But soon enough, or not so soon, he realized that his worm was too fast being replicated, but of course just have in mind the speeds of that time..
The worm made his way by exploiting more than just one vulnerability.
Basically the worm exploited: Sendmail, FingerD and rsh/rexec.
These exploits were successful and the worm gained remote access and allowed arbitrary code execution, but there was an unintended feature on this worm.
The worm could not check whenever a machine was infected or not, and because of this the same machine could potentially get infected multiple times, and every time it was creating an additional process on that target, that in fact it will slowly take the machine down by memory consumption.
Eventually on certain point the computer will turn out to be non-responsive and it will be on a Denial Of Service state, making the system connected to it, unusable.
The targets and host machines were: BSD Systems and Sun-3 Systems.
The following code is a part of the Morris worm that shows the attacks and the previously mentioned exploits, take a deep look into it, and try to understand the exploits and how they were crafted.
Note: While you are into that, try to think how you would create a feature that could detect whenever a machine was infected or not.
Back to the basics
Now that we understand how an exploit is created, and how a worm works. And also, what an attacker can do with it. Let’s go a bit further in time. Did you ever read the famous Phrack e-zine?
Specifically there is an old article that we want to point you in, and it’s called.. “ Smashing the stack, for fun and profit”.
Reference to this article: http://phrack.org/issues/60/6.html
Actually, this article was a step-stone in the history of exploit development, basically this paper showed us how to create and debug exploits for x86 platform from scratch, by abusing of buffer overflows vulnerabilities and also how to execute our shellcodes/payloads by doing ROP ( Return Oriented Programming ) technics against the LIBC.
Following to this article, we will also cover the basics. But Smashing the stack is a recommended read that you should do before continue this course. And it’s also complimentary to this training.
Now, that you have done that. Let’s begin, we would like to start with a simple overflow:
Now it’s the moment, open Exploit Pack!
For this example you will need a Linux box, it could be a Virtual Machine of course, and you can use any distro but it will be easier for you if you manage to get an old version of Ubuntu like, 6.06. Because that one has already these protections turned off.
In order to continue, open Exploit Pack and navigate to the Linux modules and select “Exploit-Tutorial” after you clicked on it, the code of this exercise will appear on the Code side, ( right side ) of the screen.
This is a Python script and you can edit it and save it directly from the built-in Exploit Pack interface.
On the commented section you can see the code that we will use for this Buffer Overflow, in fact you need to uncomment it or just copy and paste the code we have on this document:
#include
<stdio.h>
#include
<string.h>
int main(int argc, char** argv) { char buffer[100]; strcpy(buffer, argv[1]); // Vulnerable function! return 0; }
As the exploit says, before compiling this code using GCC you have to disable some protections:
First, in order to disable ASLR ( Address Space Layout Randomization ) type the following:
sudo bash -c ‘echo 0 > /proc/sys/kernel/randomize_va_space’
But, you may ask. What is ASLR?.. Well here is the concept of it:
Address space layout randomization (ASLR) is a computer security technique involved in protection from buffer overflow attacks. In order to prevent an attacker from reliably jumping to, for example, a particular exploited function in memory, ASLR randomly arranges the address space positions of key data areas of a process, including the base of the executable and the positions of the stack, heap and libraries.
Basically, we are going to use fixed memory addresses in order to control the EIP, if we have ASLR turned on, if we try to jump to our stack using a fixed address, it will fail because the stack has changed.
Then, what we have to do is to disable Stack Protector, so we can not only Jump to a fixed stack position but also execute the code of our Payload when we are there.
How!? When you compile your C code, do it like this:
$ gcc overflow.c -o overflow -fno-stack-protector -z execstack
Where -fno-stack-protector disable canaries checks Pro Police and -z execstack allows to execute from the Stack.
Canaries or canary words are known values that are placed between a buffer and control data on the stack to monitor buffer overflows. When the buffer overflows, the first data to be corrupted will usually be the canary, and a failed verification of the canary data is therefore an alert of an overflow, which can then be handled, for example, by invalidating the corrupted data. The terminology is a reference to the historic practice of using canaries in coal mines, since they would be affected by toxic gases earlier than the miners, thus providing a biological warning system. Canaries are alternately known as cookies, which is meant to evoke the image of a "broken cookie" when the value is corrupted. There are three types of canaries in use: terminator, random, and random XOR. Current versions of StackGuard support all three, while ProPolice supports terminator and random canaries.
This is great, now we understand the basic about Stack Protectors, and how to disable those protections to run our custom program in oder to overflow it and jump to the stack.
You should now have a solid understanding of what happens when a function is called ( On our exampe, strcpy ) and how it interacts with the stack. Now we arre going to see what happens when we stuff too much data into a buffer. Once you have developed an understanding of what happens when a buffer is overflowed, we can move into more exciting material, namely exploiting a buffer and taking control of execution. So compile the code and run the program, then enter some user input to be fed into the buffer. For the first run, simply enter 240 A’s.
The program returns as expected and everything works fine. Now let’s put in 280 characters, which will overflow the buffer and start to write over things stored on the stack.
Note: Use python to get the amount of characters you want:
$ python -c ‘print “A”*280’ and press Enter. So after this run we got a segmentation fault as expected, but why? Let’s take an indeep look using GDB
First, we start GDB like this: gdb ./overflow ← Where overflow is the name of the compiler C program. (gdb) disas main()
Here we can see the call instructions for strcpy(). Add a breakpoint to see what happens: (gdb) break *0x80000000 ← Where you have to replace it for the memory address that correspond to where is StrCpy() on your stack.
Now run the program, using “run” command and it will go up to our first breakpoint.
If we take a look at the stack now, after we go trough Strcpy(), with this command: x/20x $esp we can see that our string 0x41414141 is all over the place. ( 41 is the equivalent of “A” in hexadecimal ).
And if we continue forward, using the command next we can see that the return pointer goes to 0x41414141 in ?? () This is because, we are executing code at an address that was specified in our string. After overflowing the array the result is overwriting other items on the stack.
We filled up the array with A’s and then kept on going. We wrote the stored address of EBP, which is now a dword containing hexadecimal representation of AAAA. More important, we wrote over RET with another dword of AAAA.
When the function exited, it read the value stored in RET, which is now 0x41414141, the hexadecimal equivalent of AAAA, and attempted to jump to this address. This address is not a valid address, or is in protected address space, and the program terminated with a segmentation fault.
Controlling the Instruction Pointer
We have now successfully overflowed a buffer, overwritten EBP and RET, and therefore caused our overflowed value to be loaded into EIP. All this actions ended crashing the program. While this overflow can be useful in creating a denial of service, the program that you’re going to crash should be important enough that someone would care if it were not available. In our case, it’s not, for obvious reasons.
We have to move on into controlling the path of execution or basically, controlling what gets loaded into EIP, the instruction pointer.
Next update: October 1 2016.