栈溢出漏洞利用原理
2013-12-26 21:21 3686
下面的代码引自《shellcoder's handbook》英文版,中文版中没有这一节,可能是漏译,也可能是有意为之。下面的过程是经过本人调试并测试通过的,请不要套用,因为不同的平台,其结果可能也是不同的,至少我调试得到的字节数跟书中作者调试得到的字节数是有出入的,但是思路是相同的。
用例代码
overflow.c
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
38
39
40
41
42
43
44
45
46
47
48
|
int valid_serial(char *psz)
{
size_t len=strlen(psz);
unsigned int total=0;
size_t i;
if (len<10)
return 0;
for (i=0;i<len;i++)
{
if ((psz[i]< '0' )||(psz[i]> 'z' ))
return 0;
total+=psz[i];
}
if (total%853==83)
return 1;
return 0;
}
int validate_serial()
{
char serial[24];
fscanf(stdin, "%s" ,serial);
if (valid_serial(serial))
return 1;
else
return 0;
}
int do_invalid_stuff()
{
printf ( "Invalid serial number!\nExiting\n" );
exit (1);
}
int do_valid_stuff()
{
printf ( "The serial number is valid!\n" );
exit (0);
}
int main(int argc,char *argv[])
{
if (validate_serial())
do_valid_stuff();
else
do_invalid_stuff();
return 0;
}
|
编译:gcc -g overflow.c -o overflow
首先使用GDB调试overflow,在主函数处设置断点,如图1

图1
运行程序至断点处,反汇编EIP所指地址处的代码,如图2

图2
从上图,可以看到,do_valid_stuff的函数调用地址为0x08048629,记下这个地址,稍后我们会用到这个地址,改变程序的执行流程。同时,记下call指令的下一条指令的地址,也就是0x08048625,这个值将会在后面遇到。此时,查看一下eax,ebx,ecx,edx,ebp,esp寄存器的内容,如图3

图3
从上图中我们可以看到此时寄存器esp的值是0xbffff3d0,因此在调用validate_serial函数之前,我们看看栈中的内容,如图4

图4
从图中可以看到在调用函数之前,寄存器esp所指的值为0x08048650.
现在来看看validate_serial函数的反汇编结果,如图5

图5
当我们进入函数时,反汇编一下,看看我们的程序运行到何处,如图6

图6
从上图中我们可以看出,目前已经进入到validate_serial函数内,但是该函数的第一条指令还没有执行。此时,我们来看看栈中的情况,如图7

图7
注意看0xbffff3cc地址处的值,其值是0x08048625,这个值是不是有点儿眼熟,看看我们的图1,它是不是call指令的下一个指令的地址,我们要覆盖的值就是它。在图中我们还看到了地址为0xbffff3d0的值是0x08048650,这个值是不是也很眼熟。从这条信息中,我们可以得到一个信息,在进行函数调用时,call指令会将该指令的下一条指令的地址放入到栈中,之后给函数分配栈大小。
当我们多执行几条指令时,如图8

图8
此时,从代码中我们可以看到,系统给该函数分配了0x38个字节,分析一下代码你会发现 -0x20(%ebp)的地址其实就是我们的fscanf将获取到的字符串存储到栈中的地址,我们要覆盖的就是从该处到返回地址之间(包括返回地址)的字节数,也就是0x20+0x4+0x4,第一个4是push %ebp指令占用的4字节,第二个4就是我们要改写的地址字节数,其值我们改写为do_validate_stuff的地址,也就是0x08048629.因此,因此我们构造的字符串如下:
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDD\x29\x86\x04\x08
当我们执行如下命令时,它就会跳到我们指定的调用地址处,这样我们就可以如愿以偿地改变了程序的执行流程.
printf “AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDD\x29\x86\x04\x08”|./overflow
如图所示:

图9
当我们输入13个H时,其结果也是如此,如图所示:

图10
有不对之处,还请不吝赐教!
《0day安全 软件漏洞分析技术(第二版)》第三次再版印刷预售开始!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」