computer science, daily notes

Main menu

Post navigation

Exploit stack-based buffer overflow using NOP-sled technique

Stack-based buffer overflow is a common programming error that I get when I started to learn programming but I did not know that it would be really dangerous. In this post, I will try to note down what I have learned after trying to exploit this vulnerability using the well-know NOP-sled technique.

The stack
First, we need to have some idea about the memory stack. Yeah, I know the memory has a lot of things, but now, just focus on the stack. The stack is a part of the memory that store the static memory. It has the pointer that points the current using memory. When a function is called, the stack will allocate the memory that is used for the function and save the address that will it return to after the function is done.

Why are we talking about the stack? Well, the value of address of memory to point to after function execution is placed right after the allocated memory for the function. Why is that dangerous? If we do not manage the memory the right way, the attacker might somehow overwrite the value of the return address to somewhere he wants (which I did!).

In order to do so, the attacker needs to do 3 things:

First, he must know how to overwrite the return address.

Second, he must know the address where he wants to jump to.

Lastly, he must inject the code that he wants to execute to the address that he has just jumped to.

String buffer overflow and return address overwriting
As I mentioned, this is a problem that I made very often when I learned programming. Since in C/C++, the string is just a array of char that ends with a char NULL. If the attacker input a string that is longer than the allocated memory of the string and the programmer doesn’t check for the input length before accepting the string, the string will overflow the memory of the array and “might” overwrite the return address.
For example, consider this piece of code:

If the attacker enters a string that is longer than 200 chars, this string will overwrite the memory after the string that is allocated, and will also overwrite the return address. That is why you get the Segmentation fault because the program cannot jump to the memory address which was overwritten to some incorrect values. Now, the problem of the attacker is to choose a string that has a length enough fill the memory and at the last bytes, he put the return address that he wants to jumps to, for example, a string to the previous example will be “AAAAA….AAAA\xea\xf3\xff\xbf” which will overwrite the return address to the address 0xbffff3ea (\xea\xf3\xff\xbf is just the little endian convention for the address). Now, after the function finishes, instead of jumping to the address that was saved, it will jump to new address! Problem 1 solved.Find the address to jump to and inject the code
Ok, now we can make the program jumps to any place that we want, how can we inject the code that we want to execute?
In order to make the program execute the code, we need to convert the code to shellcode. I do not know much about shellcode, I just used the shellcode that was given, but let’s assume we have the shellcode (which is similar to \xff\xbf\x89\….). To get the address to jump to, we have to guess (unluckily!). We can try to debug the program and display the address of some string that we can inject the code (the str variable in the previous example for example) and with the ‘p &str’ command in gdb, we can see the address of str. But the problem now is the address changes overtime, how can we jump into in the next time after exiting the gbd?
The answer is, well, the address changes, but it will changes around the address that we investigated. We then can apply NOP-sled technique to jump to a approximate address and tell the application to pass the pointer to next byte.The NOP instruction
You can read about the NOP instruction here: http://en.wikipedia.org/wiki/NOP_slideBasically, it is a instruction which has the values “\x90” that tell the program to pass to next instruction. To take advantage of this, we will organize the str as:
str
1. x90
2. x90
3. x90
…
99. x90
100. our_shellcode_injected here
…
129. A
130. A
…
200. A
201. A
202. A
203. \xea
204. \xf3
205. \xff
206. \xbf

Now, use the gdb to get the address of the elements around 40-60 of the string, 50 for example, and set it to the end of the string. Now, when the function called finishes, the program will jump to the address of element 50, which is a x90 instruction and will then pass the instruction to next one and until it hits the wanted shellcode and Bump! Game over!

Hey Aldy,
For the last paragraph, let’s say after all you have done, generating the string:
\x90\x90\…\shellcode\AAAA\your_address, you input it to the program given above, the string will be stored in variable str. If you use gdb, you can say `p &str[50]` and it will show the address of the 50th element of str. Take that address and replace it at the end of your string then run again. Be patience and good luck!

Hey..I was going through your explanation. It’s really nice. However I have a doubt. Why are you talking about &p[50]? What happens if I choose any extreme address like p[1]? Is it because randomization will definitely change extreme addresses..However, in between addresses are safe to replace with NOP? It would be very helpful if you explain.

Hello,
The p[50] with the assumption that the return address is is somewhere between 40-60. If you use gdb to print the string, you will see “‘your string”return address'”. Choose the index number larger than the length of the string and less than the size of the array.