[SOUND]. For many reasons, programmers will continue to write and run memory unsafe C programs. In such a world, we need to defend against attacks that exploit vulnerabilities in these programs. There are two basic defenses. First, we can try to make vulnerabilities harder to exploit. The vulnerabilities are still in the programs, but the adversary will have a harder time using them to, say, perform remote code injection. This defense focuses on making one or more of the steps involved in an exploitation harder or, or even impossible. The second approach is to avoid vulnerabilities in the first place. This defense involves employing coding practices that are less likely to introduce bugs. It might also involve the use of advanced code review and testing techniques to reveal bugs prior to deployment. These two approaches, mitigating exploitations and preventing bugs are complementary. And in fact, both are used in modern software development processes. Alright, so let's consider how to avoid exploitation. Recall the steps of a stack smashing attack. We need to make it so that one of these steps is hard or is impossible to carry out. The first was finding a way to put attacker code into memory. And recall that we worried about zeroes and other control characters in the code, which would thwart strcpy or scanf during the insertion phase. Then we needed a way to get EIP, the program counter, to point to and run the attacker code. And the way we did that, was to overwrite the return address. We needed to know its relative location on the stack so we could get it to point instead, to the buffer that we inserted when smashing the stack. So the question is, how can we make each step more difficult to carry out. In the best case we can complicate exploitation by changing the libraries, the compiler, the operating system. That way, we can leave the application code alone, which is hard to change correctly. And the fix instead is in the architectural design, which we can do once and apply to all programs. The first technique we`ll look at, is Detecting overflows using stack canaries. And the analogy here is from 19th century coal mine integrity. Back in the 19th century, coal miners were concerned that mines might contain noxious gas. In order to tell that, that might be the case, they would bring along with them a canary. If at some point, the canary keeled over and died, the coal miners would be very concerned that there was gas around them and they would abort and leave the mine. So, we can do the same thing to check whether or not the stack has been smashed. The way that we can do it, is that instead of putting all the local variables next to the safe frame pointer, the same, the saved program counter that is the return address and so on. We can make space for what's called a stack canary, which is some number that we store there. Then, if the attacker overruns a buffer, the attacker will also overrun the canary. Now the code will have been changed. Automatically by say the compiler or the linker, to check upon returning whether or not the stack canary is as it was expected to be. In this case because we overrode it, it's different, and so we'll abort. Now the question is, what value should the canary have? Obviously we want to choose one that it's hard for the attacker to guess or to use. So there's a couple of choices. One is called a Terminator canary. This attempts to stop attacks that are based on library routines like scanf or strcopy. And it uses things like carriage return, line feed, null and so on, which those routines can't deal with and so therefore wouldn't be able to deposit there. An alternative and the most common approach is to use a Random canary. And the idea here is that when a process starts up it will choose a random value, store it somewhere in memory and write protect it so that the program won't subsequently change it. And then, it will use that value to write it as the canary. And it will then use the stored value somewhere in memory to check that the canary is unchanged. A modification a, a variation of this approach is to XOR canaries against some control information that's particular to say, a stack frame. So for example you could use a return address as the XOR mask against which to XOR the canary. Okay, so this defense will make it so that we can't smash the stack and overrun it with with new attacker code. Another thing we could try to stop is getting EIP to point to and run the code. And in fact, one way we can do that directly, whether we use stack canaries or not, is to make it so that the stack and heap are non-executable. That is, if the program runs normally, then the text segment, the code, is immutable, and every other portion of memory in the program is non-executable. So if you loaded code in there into a malloc buffer or onto the stack, the architecture would prevent you from running it because, it was not designated as a code region and therefore not allowed to be run. Unfortunately, this approach can be bypassed too using an attack called return-to-libc. So, here's the set up of the stack with our normal stack smashing attack when we have the nop sled and the guess of the location and the malicious code. So we don't have to insert malicious code, or the nop sled, or the guess. Instead what we do, is we overwrite the return address to point to some location already in memory, that has the code that we want. In addition, we overwrite the next thing to be the argument to that memory. For example here, we pointed the return pointer to exec to create a new process, and we pointed the next thing on the stack to /bin/sh the constant string. And this way when we return from the overrun function, we'll turn our current process into a shell. One nice thing about this approach is we don't need to know the absolute return address location, we simply need to know that we've overrun it with pointers to exec and bin/sh. So, the way that we can defeat this attack is we can use something called Address-space Layout Randomization. And the idea is to randomly place the standard libraries and other elements of memory of the system like the stack in random locations, and therefore making them harder to guess. So the attacker can't build a one size fits all exploit that knows exactly where exec is for every program that's run. And a similar sort of thing makes it hard to find the return pointer. That is, the stack has been randomized and so it's location is not the same every time. So, if we return to the example, here we are again, now we don't know where exec and bin/sh are because the location of the standard libraries has been randomized. ASLR is available today on most modern operating systems. It was first introduced for Linux in 2004 and adoption came slowly thereafter for other systems. For example, OpenBSD supported it in 2006, Windows in 2007. MAC OS introduced it in the same year for system libraries, and for normal programs in 2011. Handheld device operating systems also use ASLR. Android had full support as of 2012. And IOS for iPhones had it in 2011. Now, while ASLR makes exploitation more difficult, it is not perfect. First, keep in mind that it only randomizes the offset of memory areas, it does not randomize their contents. Second, ASLR implementations apply only to standard libraries, not program code. This is because program code must be compiled to be position independent if it is to be located in the address space. Some programs are not compiled this way and so their application code is not subject to ASLR relocation. Shared libraries are normally compiled this way, application code, not always. Third, ASLR needs sufficient randomness to avoid brute force attacks. A research paper by Hovav Shacham demonstrated that Linux ASLR support on 32 bit operating systems was susceptible to brute force attacks. In particular, he crafted an attack that attempted to guess the ASLR offset while attacking a running Apache HTTPD instance. He was able to perform this attack successfully and taking only 216 seconds on average. Fortunately, modern 64 bit operating systems do provide a lot more entropy, and would make Shacham's brute force attack infeasible.