数组越界访问

1 数组越界

先区分一下数组越界漏洞溢出漏洞

  • 数组越界访问包含读写类型
  • 溢出属于数据写入
  • 部分溢出漏洞本质确实就是数组越界漏洞。

数组越界就像是倒水的时候倒错了杯子,溢出就像是水从杯子里溢出来。

1.1 原理

堆中的数组越界: 因为堆是我们自己分配的,如果越界会把堆中其他空间的数据写掉或着读取其他空间的数据。如果是变量则会引起数值改变,如果是指针则可能会引起crash。

栈中的数组越界:因为栈是向下增长的,进入函数前,会把参数和下一条指令地址压栈,如果覆盖了当前函数的ebp(栈底),那么栈还原时esp(栈顶)就不正确指向,从而发送未知错误(大部分是程序崩溃退出),ebp后面的返回地址也被覆盖那么程序执行流程则可被控制。

下面代码为例分析数组越界访问漏洞:

1
2
3
4
5
6
7
8
9
10
11
#include<stdio.h>
int main(){
int index;
int array[3] = {111,222,333};

printf("输入数组索引下标:");
scanf("%d",&index);
printf("输出数组元素:array[%d] = %d\n", index, array[index]);
//array[index] = 1;
return 0;
}

执行生成的程序,然后分别输入2 和 4 作为数组下标,输出结果如下,当输入的数组下标为 0、1、2 的时候,会得到正常数值,但是从索引3开始就超出了原来的数组 array 的范围,比如输入4,将会数组越界访问栈中的值,导致读取不在程序控制范围内的数值。

image-20220904162857184

使用gdb调试发现array[4] 就是从 array 开始的第六个数据0x4012A9,已经读取到了array之外的数据,如果越界访问距离过大,就会访问到不可访问的内存空间,导致程序崩溃。

我们可以利用这种方式来取得栈上的 canary,进而绕过canary。

image-20220904162631275

image-20220904162118330

canary = 0x3dd8e70f8 =103762510310

image-20220904162735865

这里我们已经取得了栈中 canary 的值,接下来只要通过栈溢出,进行覆盖,并把 canary 放入 [rbp-0x8] 就能控制程序去执行 shellcode 了。

0x9d5720fbb2e21300

参数:

整数溢出+数组越界

​ 漏洞战争