我一直在学习缓冲区溢出,并注意到一些奇怪的事情。
void vuln()
{
char buf[180];
gets(buf);
puts(buf);
return;
}
int main()
{
__gid_t egid;
setvbuf(stdout, 0x0, 2, 0);
egid = getegid();
setresgid(effective_gid, effective_gid, effective_gid);
puts("You know who are 0xDiablos: ");
vuln();
return 0;
}
我将代码编译为64位和32位。
gcc test.c -fno-stack-protector -o 64bit.o
gcc test.c -fno-stack-protector -o 32bit.o -m32
我在strace下的32位应用程序上通过了180多个A作为输入。
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x41414141} ---
+++ killed by SIGSEGV (core dumped) +++
然后,我在strace下对64位应用程序进行了相同的测试。
--- SIGSEGV {si_signo=SIGSEGV, si_code=SI_KERNEL, si_addr=NULL} ---
+++ killed by SIGSEGV (core dumped) +++
为什么64位显示无效内存引用为NULL,而不是像32位SIGSEGV那样为0x41414141?
不确定这是否重要,但我的内核是5.5.8。
为什么64位显示无效内存引用为NULL,而不是0x41414141
它显示NULL,因为处理器实际上并没有执行CALL
,因为目标地址不是规范形式的。
最简单的演示程序:
int main()
{
int (*fn)(void) = (int(*)()) 0x4141414141414141;
return fn();
}