我有一个练习要求我制作一个seg.fault。 根据我的理解,我可以通过溢出缓冲区来做到这一点。 所以我需要做的就是提供一个大于特定大小的输入(Name)(覆盖返回地址)。 因此,如果buf,i和c保持52字节和ebp 4,则返回地址应该在56字节之后。因此,如果我给出大于56的输入,它应该产生一个seg.fault。我的想法是否正确?我试过这些数字,但它仍然运行并正确退出。(UNIX-32bit)
#include <stdio.h>
#include <sys/mman.h>
#include <string.h>
#include <stdlib.h>
#define BUFSIZE 44
char grade = '3';
char Name[BUFSIZE];
void readString(char *s) {
char buf[BUFSIZE];
int i = 0;
int c;
while (1) {
c = fgetc(stdin);
if ((c == EOF) || (c == '\n'))
break;
buf[i++] = c;
}
buf[i] = 0;
for (i = 0; i < BUFSIZE; i++)
s[i] = buf[i];
return;
}
int main(void) {
mprotect((void*)((unsigned int)Name & 0xfffff000), 1,
PROT_READ | PROT_WRITE | PROT_EXEC);
printf("What is your name?\n");
readString(Name);
exit(0)
}
答案 0 :(得分:1)
这段代码可以保护您免受段错误的侵害。
for (i = 0; i < BUFSIZE; i++)
s[i] = buf[i];
你可能会跑掉buf数组的末尾但是在堆栈上。
为什么不呢?
*(int*)(0x00000000) = 0;
答案 1 :(得分:0)
在我看来,堆栈是单词对齐的,如果你的buf [BUFSIZE],它将与本地i和c变量有一个洞。这样的反汇编代码:
4005d4: 55 push %rbp
4005d5: 48 89 e5 mov %rsp,%rbp
4005d8: 48 83 ec 50 sub $0x50,%rsp
4005dc: 48 89 7d b8 mov %rdi,-0x48(%rbp)
4005e0: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%rbp)
它的堆栈创建了90个字节,所以你想改变rbp必须输入很多。 所以如果你想改变像rbp这样的其他值,你必须输入超过64。 不幸的是,它可能没有用,因为当你经过i位置时,你的输入值会改变i值,所以buff [i ++]可能不是你想要的位置。所以改变rpb的最好方法是只是跳过在第一个中加入的堆栈。