Vulnerable Code in “C” Language
Introduction
Welcome to module 4 of this workshop. In this module, we will experience some debugging with the vulnerable code based on Linux platform and we will be using “C” as our programming language.
Prerequisites
To get the most out of this module, it is recommended that you should have:
• Complete previous three modules
• Background in programming at least at a beginner level
• Understands TCP/IP
• Beginner level knowledge in information security
• Passion to learn ethical hacking
• Understand Debugging and Know GDB
This module will not be as theoretical as we had in previous modules; however, what we will cover in our lab is the debugging on Linux and how to make good use of it for exploit development. The key of exploit development is controlling EIP, and in this module we will go to the level of overwriting EIP register with the help of GDB in debugging.
Debugging on Linux with GDB
We have already spoken about GDB and its use in our previous modules to some extent, here we will be giving examples how you can simply run the compiled code in Linux within the debugging environment, which is an essential part of exploiting.
Example 1
Simple code in “C” language, which we will be using in this example, is given below. What you need to do is simply use this code with an appropriate name.
#include <stdio.h>
void main(void)
{
printf(“\nHello Linux, I am first program\n\n”)
}
}
Now save this as firstprogram.c and ensure that you have “gcc” and “gdb” installed in your Linux OS.
Lab1
Now in this lab we would only show how you could use GDB to disassemble any function.
Now in this lab we would only show how you could use GDB to disassemble any function.
Open terminal (bash shell) and compile the firstprogram as shown in the figure below. This way it will generate a binary file with the name given. It will appear in green color.
Now, you can execute this file with [./firstprogram] as shown below. This way it will execute and will do the required tasks coded in the program. In our case, it will simply print a line as we coded.
So far we only tested how to compile and run the code, now lets run this in debug mode with GDB. Since we have not compiled the code with debugging options here we will again do it with [-g] switch as shown below.
Now, we will run the firstprogram.g file that is the compiled version of our program in GDB as shown below. For this simply run GDB with filename as parameter.
Now, we only have one function in our code which was [main]. Let’s disassemble this and see the outcome. For this use command [disassemble main] as shown in below figure.
You can see the assembler code for function main is displayed.
Example2
In this lab we will learn how you can display registers while working with GDB. Let’s code another
program as shown below.
#include <string.h>
void go(char *data)
{
char name[64];
strcpy(name, data);
}
int main(int argc, char **argv)
{
go(argv[1]);
}
We will compile this code with the following commands as shown below.
Now, let’s run GDB and perform some second level of info and see register’s information.
When we disassembled the main function we see a call to another function as shown in below figure, you can also see the function name (go).
You can also see register level information by typing [info register command] as shown below where 41 [i r] is the short form.
Since this is 64-bit machine, you will see some differences in the register names. “r” represents the 64-bit size.
For your ease of use, we will also display 32-bit register information via the same process as shown below.
Overwriting EIP register
Example3
This is one of the key steps you need to perform in exploit development, to control EIP you need to overwrite EIP register. To show you this, we will go back to 32-bit register size to make it easy to understand (32-bit Ubuntu Desktop).
Save this following code and compile this with the following switches as shown later.
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv)
{
char buffer[500];
strcpy(buffer, argv[1]);
return 0;
}
In the above program, we are simply passing a parameter at run time, which can only be at the size of 500 characters. To compile this program, follow the instructions as shown in below snapshot.
Now, we will run the compiled code in our debugger and pass the run time parameter, which would be more than the size it can accept as value.
Run the GDB debugger as shown in below figure and pass the value at run time by passing it through python code.
Now run the program as shown below with value given as $(python –c ‘print “\x41” * 600’).
This way, we will be passing 600 “A” as a value to our program at run time and since we have passed a value that is more than the size of buffer in the memory, it should overwrite the EIP. Let’s run and see, the result is shown in below figure.
You can see that segmentation fault occurred and now we will see what is there in EIP register by typing command [info register eip] as shown below in figure.
We have successfully overwritten the EIP value. Let’s see what else is written with “A”. To find this, we will type command [info registers] as shown below in figure.
This confirms that EIP and EBP are overwritten. To complete code exploit, you need to calculate space and a shellcode.