重谈堆栈方向和栈溢出的利用(栈溢出攻击原理)

因为不同的程序所用栈和所用堆的比重不同,将两者的公用空间联用是一个高效的做法

一般情况下,栈是从高地址向低地址增长,堆是从低地址向高地址增长

程序员习惯从低向高去读写内存

(所谓“指针指向下一个位置”,会默认“下一个位置默认”为高地址)

所以在设计的时候就将堆布局为就是从低向高增长,而栈对此并不敏感,所以会出现现代程序的堆栈布局

当向栈中写入了超过了限定长度的数据,溢出的数据会覆盖到指定区域,如果把想要执行的地址覆盖到到原来函数的返回地址,那么返回时候,就会执行被覆盖的地址的函数

这也是“黑客程序栈溢出攻击”的通用做法

下面举个最简单的例子:

#include<stdio.h>
 
int fun1()
{
	int a;
	gets((char *)&a);
	return 0;
}
 
int fun2()
{
	printf("Stack overflow, function jump!\n");
	return 0;
}
 
int main(int argc, char *argv[])
{
	fun1();
 
	return 0;
}

注意这里利用了一个C语言里面非常危险的函数gets(),这个函数没有边界检查,只能检测4字节的大小(32位,即为4个字符),当输入字符大于数量这个的时候就会发生越界

以上程序,当输入4个A的时候,查看堆栈情况,可以看到没有异常

当输入7个A的时候,意味着超过了3个存储空间(A在16进制中是41)

注意到BP区域被侵占了,BP为栈的基地址

(之前的R代表是64位,同理E代表32位,不加代表16位)

字符超了就直接超越了栈的基地址空间 ,将别的空间入侵了

那么直接填写12个A,就直接超越了基地址空间!

再多的字符就到了下一个空间,就是IP,是函数返回时要跳转的地址

如果把这个地址改为fun2的地址就可以实现跳转到我们需要它执行的位置了

下面是原理图:

IP为指令指针寄存器 指向将要执行的下一条指令的地址,是我们要入侵的地方

BP为栈底基地址

去寻找func2的函数入口:

 可以找到0x000000000040157f是func2的入口地址

在gets处输入AAAAAAAAAAAA+0x000000000040157f直接穿透栈底,把fun2的地址注入到下一步要执行的地址空间

(注意大小端和地址格式的转换)

执行!!!然后就翻车了,不过程序在这里卡住了,说明它去找那个地址了,但是我们提供的地址不对,估计是地址输入格式不对什么的,这里学艺不精,没复现出效果,原谅一下哈,但是思路是没问题的😂

 那就换一个编译器,发现不能使用了

 哈哈,看来微软的编译器是非常安全的,都直接禁用了这个函数

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值