无法访问x86-32上的返回地址
我想我的运气与缓冲区溢出,但是,我卡住了一点。我覆盖返回地址,以便EIP
将指向我的shellcode的底座nop
的地址。但是,运行ret
时,出现错误:Cannot access memory at address 0x90909094
。任何人都可以看到什么是错的?无法访问x86-32上的返回地址
从内存转储:
(gdb) x/8wx $esp
0xbffff18c: 0xbffff470 0xbffff400 0x00000000 0x08048559
0xbffff19c: 0xb7fc6ff4 0x08048550 0x00000000 0x00000000
(gdb) x/8wx 0xbffff470
0xbffff470: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff480: 0x90909090 0x90909090 0x90909090 0x90909090
(gdb) nexti
Cannot access memory at address 0x90909094
(gdb) i r eip
eip 0xbffff470 0xbffff470
正如你所看到的,寄信人地址是0xbffff470并在那个位置,我的nop
雪橇放置。但是,只要我运行下一条指令(即ret
),就会出现错误。这里有什么问题? 编辑:我使用的x86-32
编辑:我发现在另一篇文章中回答:GDB ret "cannot access memory at address" 基本上,问题是对之前的地址ESP设置为EBP相等,在我的情况时,将是0x90909090 ..因此,一个快速解决方案是不使用'A'作为填充,而是使用每个单词中的地址。
OP回答了自己的问题(或多或少):
Edit: I found the answer in another post: GDB ret "cannot access memory at address" Basically, the problem is right before the address esp is set to equals ebp, when in my case will be 0x90909090.. Thus, a quick solve is to not use 'A's as padding, but rather just the address in every word.
换句话说,问题是,他改写当前函数的栈帧的一些,但没有覆盖的实际指向存储返回地址的堆栈。
// let's say his function ended with a "return 0"...
xorl %eax, %eax
// now here is where he did the "x/8wx" debugger command...
// but then the function epilogue goes and does the usual thing:
movl %esp, %ebp
popl %ebp
// and so here, at the actual return, %esp no longer points
// to the same bytes he saw with "x/8wx"
ret
The linked answer表明,他的调试器可能有某种故障与leave
指令(即相当于上述movl
/popl
),使得调试器是告诉,他停在OP指令ret
,但实际上处理器尚未执行leave
。
等价地,调试器可能在函数序言或结尾中间有一个反感,以致于如果你试图在结语中间设置一个断点,它会被秘密地调整到结尾的开头。
这是x86-32吗?我不知道还有人用过! :)标记您的问题[x86-32]或[x86-64],以便人们知道您正在使用哪一个。如果你使用的是x86-64,一个bug是显而易见的:你应该看看'%rip'和'%rsp',而不仅仅是'%eip'和'%esp'。这是全部吗? – Quuxplusone
假设你没有犯任何错误,是否有机会启用cpu的数据执行保护并防止指令在非代码段运行? – rcgldr
@rcgldr我觉得不是?如果我用-z execstack和-fno-stack-protector编译,它应该都很好? – user1090614