示例解析缓冲区溢出攻击的原理

本文通过一个实例详细解析了C语言中由于数组赋值导致的缓冲区溢出问题,解释了如何利用strcpy函数造成栈溢出,进而改变返回地址,实现对程序执行流程的控制。主要涉及栈帧结构、函数调用过程以及汇编代码分析,揭示了栈溢出攻击的基本机制。
摘要由CSDN通过智能技术生成

在为C语言的数组等赋值时,可能赋值大小超出了数组的长度限制,这时超出的部分就会覆盖掉栈中其他部分的内容,从而发生缓冲区溢出。

下面用一个危险的例子进行说明:在这个程序中,我们利用strcpy()函数进行赋值操作。

C代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void StringCopy(char *str){
    char p[10];
    strcpy(p,str);
}
void hacked(){
    while(1){
        printf("you are hacked!!!");
    }
}
int main()
{
    char str[] = "0123456789012345678901234567891111";
    unsigned long long *p = (unsigned long long*)&str[18];
    (*p) = (unsigned long long)hacked;
    //用hack函数的地址覆盖字符串str中的部分内容
    //这里的18是在ubuntu64位下测试得到,其他系统可能会出现问题,不能正常运行
    StringCopy(str);
    return 0;
}

运行结果:

程序疯狂显示you are hacked;但这不是hack()函数的功能吗?我们并没有调用hack函数啊。
在这里插入图片描述
为了理解这个问题的本质,首先我们要知道,main函数在调用子函数时,首先会进行地址(下条命令的地址)压栈,然后将栈基址指针%ebp压栈;

然后会分配内存空间,如%esp-0x20(即分配32个空间,这个值具体看程序和OS),在这部分空间中进行函数内部操作;

函数执行完毕后,会清理掉这部分内存空间,弹出%ebp,并开始执行返回地址所指向的命令!

那么我们只需要覆盖这个返回地址,让它变成我们hack()程序的地址,那么程序就会执行hack程序了!

所以我们只需要计算返回地址的位置即可,StringCopy函数对应的汇编代码如下:

;4  :	void StringCopy(char *str){
0x555555555169	endbr64
0x55555555516d	push   %rbp
0x55555555516e	mov    %rsp,%rbp
0x555555555171	sub    $0x20,%rsp
0x555555555175	mov    %rdi,-0x18(%rbp)
;5  :	    char p[10];
;6  :	    strcpy(p,str);
0x555555555179	mov    -0x18(%rbp),%rdx
0x55555555517d	lea    -0xa(%rbp),%rax
#%ebp-0xa即为p的地址,p占十个字节;再加上%ebp占8个字节
0x555555555181	mov    %rdx,%rsi
0x555555555184	mov    %rax,%rdi
0x555555555187	callq  0x555555555060 <strcpy@plt>
;7  :	}
0x55555555518c	nop
0x55555555518d	leaveq
0x55555555518e	retq

从上述程序我们可以看出,从变量p到栈底%ebp,一共占18个字节,而18个字节之后,便是返回地址所在的位置。

执行strcpy之前:
在这里插入图片描述
执行strcpy之后:
在这里插入图片描述
可以看到,函数的返回地址已经发生了改变。
在这里插入图片描述
继续执行,可以看到%rip的值也发生了改变,并且程序跳转到了hack()函数中,这里就完成了缓冲区溢出的攻击。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值