Linux 溢出

概述

Linux下的溢出学习。

目标代码

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
#include <stdio.h>
#include <stdlib.h>
const char pass[] = "IloveIS2013@ZJGSU"; /* Password */
void authorized()
{
printf( "You have been authorized!\n" );
}
void getInput()
{
char buffer[20];
gets( buffer );
if ( strcmp( pass, buffer ) == 0 )
{
authorized();
}
else
printf("Your password is wrong!\n");
}
int main()
{
getInput();
return(0);
}

代码很简单,用户输入一个密码,然后程序把它加密起来,并且和程序中存储的密码对比,如果成功了,就调用authorized()函数,就当这个authorized()函数是用来让用户在登录后干一些敏感操作的好了。

1
gcc -ggdb -fno-stack-protector -z execstack overflow.c -lcrypt -o overflow

步骤

linux-overflow-1.png

程序分配20字节的缓冲区,然后把用户输入存储到这个缓冲区里面,然后调用函数把它加密,再和程序里的密码对比。

我们编译的时候会被编译器提示gets()不安全,事实上也是,因为它并没有做任何边界检查,所以我们就用它来调用漏洞了。

我们用objdump来dump一下生成的机器码,看看这儿它做了什么
objdump -d -M intel overflow

linux-overflow-2.png

linux-overflow-3.png

linux-overflow-4.png

linux-overflow-5.png

linux-overflow-6.png

linux-overflow-7.png

现在我们所有要做的就是把getInput的返回地址覆盖为0x0000000000400636,而且我们可以做到。我们可 以在shell里用printf把数据传给程序,你可以用\x来转意16进制数据,因为地址是倒着来的(注:小端),所以我们也倒着给它就好了。还有,我 们需要用0x00来终止我们的缓存,这样strcmp就不会在我们函数返回之前引起一个段错误。printf的结果如下:

linux-overflow-8.png

我们可以知道authorized()函数事实上已经执行成功了。