Buffer Overflow Attack Lab - Updated
Buffer Overflow Attack Lab - Updated
Lab 2
Buffer Overflow Attack Lab
Lab environment
Download pre-built virtual machine image of ubuntu 32 bit:
https://drive.google.com/file/d/12l8OO3PXHjUsf9vfjkAf7-I6bsixvMUa/view?usp=sharing
Unzip SEEDUbuntu-16.04-32bit.zip and you should be able to see a folder that contains the VM
files.
* use following link to run and configure the VM on VirtualBox.
https://seedsecuritylabs.org/Labs_16.04/Documents/SEEDVM_VirtualBoxManual.pdf
* You will be logged into an account called seed, and its password is dees
Screenshot 1: take the screen shot of the installation of ubuntu/linux
Overview
Buffer overflow is defined as the condition in which a program attempts to write data beyond
the boundary of a buffer. This vulnerability can be used by a malicious user to alter the flow
control of the program, leading to the execution of malicious code.
Objective
The objective of this lab is for students to gain practical insights into this type of vulnerability,
and learn how to exploit the vulnerability in attacks.
Environment Setup
Turning Off Countermeasures
Modern operating systems have implemented several security mechanisms to make the buffer-
overflow attack difficult. To simplify our attacks, we need to disable them first.
Address Space Randomization. Ubuntu and several other Linux-based systems uses
address space randomization to randomize the starting address of heap and stack. This makes
guessing the exact addresses difficult; guessing addresses is one of the critical steps of buffer-
overflow attacks. This feature can be disabled using the following command:
Open the terminal and write the following commands
Configuring /bin/sh. The following command can be used to link /bin/sh to zsh:
Screenshot 2: take one screen shot of the terminal where you write the above two commands
Unfortunately, we cannot just compile this code and use the binary code as our shellcode. The
best way to write a shellcode is to use assembly code. In this lab, we only provide the binary
version of a shellcode, without explaining how it works (it is non-trivial)
Invoking the Shellcode
The binary code is generated, and put the code in a C program called call shellcode.c. In this
task, we will test the shellcode.
Run call_shellcode.c and describe your observations. It should be noted that the compilation uses
the execstack option, which allows code to be executed from the stack; without this option, the
program will fail.
$ gcc -m32 -z execstack call_shellcode.c
After successful compilation you can execute the code with the following command
$ ./a.out
where a.out is the name of executable file that will be created after successful compilation of
call_shellcode.c program. After successful execution you will be able to get the terminal (shell).
Screenshot 3: take the screen shot of the compilation and running of above program.
Compilation. To compile the above vulnerable program, do not forget to turn off the
StackGuard and the non-executable stack protections using the -fno-stack-protector and "-z
execstack" options.
After the compilation, we need to make the program a root-owned Set-UID program. We can
achieve this by first change the ownership of the program to root (Line ➀), and then change the
permission to 4755 to enable the Set-UID bit (Line ➁). It should be noted that changing
ownership must be done before turning on the Set-UID bit, because ownership change will cause
the Set-UID bit to be turned off.
Vi
Note 1. When gdb stops inside the bof() function, it stops before the ebp register is set to point
to the current stack frame, so if we print out the value of ebp here, we will get the caller’s ebp
value. We need to use next to execute a few instructions and stop after the ebp register is
modified to point to the stack frame of the bof() function.
Note 2. It should be noted that the frame pointer value obtained from gdb is different from that
during the actual execution (without using gdb). This is because gdb has pushed some
environment data into the stack before running the debugged program. When the program runs
directly without using gdb, the stack does not have those data, so the actual frame pointer value
will be larger. You should keep this in mind when constructing your payload.
ret (return address) it is the value of ebp + a number greater than hundred.
Offset : it will be ebp – buffer + 4
Note that the ebp and buffer address will be different from the above. It will be different for each
computer.
After you finish the above program, run it. This will generate the contents for badfile. Then run
the vulnerable program stack. If your exploit is implemented correctly, you should be able to get
a root shell: