这个实验主要是熟悉栈,和了解数据缓存区溢出的问题。
数据缓存区溢出:程序每次调用函数时,会把当前的eip指针保存在栈里面,作为被调用函数返回时的程序指针。在被调用程序里面,栈是向下增长的。所有局部变量都存储在栈里面(静态局部变量除外)。假设有一个字符串变量str,在str读取数据时,如果缓存区没有进行一定的保护,会造成缓存区的溢出。由于栈是向下增长的,但是对于一个变量,如str,他的数据存储顺序是向上增长的。所以当缓存区溢出时,可能对eip的返回指产生影响,可以通过输入,来改变eip指针的值,从而控制程序返回的地址。
Level 0: Candle
程序是一个字符串的输入程序,如果输入超过40个,就会说输入错误。
试验一就是要通过查看程序的栈帧,进行缓存区溢出攻击,通过输入,改变程序的返回地址。
void test()
{
unsigned long long val;
volatile unsigned long long local = 0xdeadbeef;
char* variable_length;
entry_check(3); /* Make sure entered this function properly */
val = getbuf();
if (val <= 40) {
variable_length = alloca(val);
}
entry_check(3);
/* Check for corrupted stack */
if (local != 0xdeadbeef) {
printf("Sabotaged!: the stack has been corrupted\n");
}
else if (val == cookie) {
printf("Boom!: getbuf returned 0x%llx\n", val);
if (local != 0xdeadbeef) {
printf("Sabotaged!: the stack has been corrupted\n");
}
validate(3);
}
else {
printf("Dud: getbuf returned 0x%llx\n", val);
}
}
unsigned long long getbuf()
{
char buf[36];
volatile char* variable_length;
int i;
unsigned long long val = (unsigned long long)Gets(buf);
variable_length = alloca((val % 40) < 36 ? 36 : val % 40);
for(i = 0; i < 36; i++)
{
variable_length[i] = buf[i];
}
return val % 40;
}
实验要求,输入一个字符串,然后是getbuf()完成后,跳转到smoke()函数,而不是test函数。
首先,进入getbuf函数,查看getbuf的栈帧。
可以看到,程序的返回地址存储在rip中,地址是:
也就是要通过输入,改变0x7fffffffb1a8地址中的值。
根据程序:
char buf[36];
volatile char* variable_length;
int i;
unsigned long long val = (unsigned l