C++内存越界访问

在C++中可以直接用地址来访问内存,并且不会确保这些位置对被引用的内存缓冲区有效。这可能导致在与其他变量、数据结构或者内部程序的数据相关的内存位置上执行读写操作。因此攻击者能够执行任意代码、预期的控制流、读取敏感消息或者导致系统崩溃。

内存越界的种类:

1.可索引资源的错误访问,范围错误。

2.不检查输入大小的缓冲区复制。

3.越界读取。

4.返回超出预期范围的指针值。

5.在缓冲区之前就开始访问内存。

6.越界写入。

7.缓冲区结束偶访问内存位置。

8.长度不正确的缓冲区访问。

9.不受信任的指针取消引用。

10.使用超出范围的指针偏移。

11.未初始化的指针的访问。

12.过期指针取消引用。

13.输入验证不当。

14.数组索引验证不正确。

15.缓冲区大小计算错误。

16.整数溢出或者环绕。

17.有符号到无符号转换错误。

18.没有检查最小检查的数值范围比较。

19.使用不兼容的类型访问,类型混淆。

20.实数的精度或者准确性不足。

常见的内存错误访问例子

例1.代码如下:

void host_lookup(char *user_supplied_addr){
    struct hostent *hp;
    in_addr_t *addr;
    char hostname[64];
    in_addr_t inet_addr(const char *cp);

    /*routine that ensures user_supplied_addr is in the right format for conversion */

    validate_addr_form(user_supplied_addr);
    addr = inet_addr(user_supplied_addr);
    hp = gethostbyaddr( addr, sizeof(struct in_addr), AF_INET);
    strcpy(hostname, hp->h_name);
}
View Code

例1中的函数分配一个64字节的缓冲区来存储,但是不能保证主机名不会大于64字节,如果指定的地址是很大很长,则该函数可能会覆盖敏感数据暂时放弃控制流。这个示例还包含一个未经检查的返回值,它可能导致NULL指针。

例2.代码如下:

int main (int argc, char **argv) {
    char *items[] = {"boat", "car", "truck", "train"};
    int index = GetUntrustedOffset();
    printf("You selected %s\n", items[index-1]);
}

如果程序员允许用户指定要选择列表中那个元素,但是攻击者可以提供越界偏移,从而导致缓冲区过度读取。

int getValueFromArray(int *array, int len, int index) {
    int value;
    // check that the array index is less than the maximum
    // length of the array
    if (index < len) {
    // get the value at the specified index of the array
    value = array[index];
    }
    // if array index is invalid then output error message

    // and return value indicating error
    else {
        printf("Value is: %d\n", array[index]);
        value = -1;
    }

    return value;
}
View Code

这个例子中仅仅是检查了给定数组索引是否小于数组的最大长度,但是不检查最小值,这将允许接受负值作为数组索引,这也会导致越界读取。并可能访问到敏感内存。有检查输入数组索引以验证其是否在数组所需最大和最小范围内。

posted @ 2022-05-27 15:27  VarForrest  阅读(665)  评论(0编辑  收藏  举报