我正在做有关 bufferOverflow 的家庭作业。测试程序用于fread()
从文件中读取 4096 个字节。
当我将 kernel.randomize_va_space 设置为 0,并在 gdb 中运行程序时,我可以看到 fread() 命令没有返回任何内容。
如果我将 kernel.randomize_va_space 设置为 1 或 2,并使用 gdb 重新运行程序,我可以在 fread 存储文件的缓冲区中看到预期的数据。
为什么 ASLR 会导致 fread 停止正常工作?
仅供参考:这是 ubuntu 12.0.4 64 位,该程序是使用 gcc 的 -c99 和 -m32 标志编译的。
我为此作业给出的测试程序如下:
#include <stdio.h>
#define READSIZE 0x1000
void countLines(FILE* f){
char buf[0x400];//should be big enough for anybody
int lines=0;
fread(buf,READSIZE,1,f);
for(int i=0;i<0x400;i++)
if(buf[i] == '\n')
lines++;
printf("The number of lines in the file is %d\n",lines);
return;
}
int main(int argc,char** argv){
if(argc<2){
printf("Proper usage is %s <filename>\n",argv[0]);
exit(0);
}
FILE* myfile=fopen(argv[1],"r");
countLines(myfile);
return 0;
}
当我在 gdb 中运行它时,我将断点放在该行上:
for(int i=0;i<0x400;i++)
然后在 gdb 中执行以下操作:
(gdb) x $esp
0xbffff280 0xbffff298
如果我做:
(gdb) x /12wx $esp
我可以看到前 4 个字节是 buf 的地址,接下来的 4 个字节是传递给 fread 的 0x1000,接下来的 4 个字节是也传递给 fread 的 0x01。
这在我看来就像 fread 函数的堆栈框架而不是countLines()
.
为什么 $esp 不指向当前堆栈帧而不是刚刚退出的堆栈帧?
更新
我修改了代码如下:
#include <stdio.h>
#define READSIZE 0x1000
void countLines(FILE* f){
char buf[0x400];//should be big enough for anybody
int lines=0;
int ferr=0;
fread(buf,READSIZE,1,f);
ferr=ferror(f);
if (ferr)
printf("I/O error when reading (%d)\n",ferr);
else if (feof(f))
printf("End of file reached successfully\n");
for(int i=0;i<0x400;i++)
if(buf[i] == '\n')
lines++;
printf("The number of lines in the file is %d\n",lines);
return;
}
int main(int argc,char** argv){
if(argc<2){
printf("Proper usage is %s <filename>\n",argv[0]);
exit(0);
}
FILE* myfile=fopen(argv[1],"r");
countLines(myfile);
return 0;
}
当我在禁用 ASLR 的情况下运行它时,我得到:I/O errorwhen readin (1)
如果我在启用 ASLR(值 = 1)的情况下运行它,则达到 EOF。