无法访问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'作为填充,而是使用每个单词中的地址。

+0

这是x86-32吗?我不知道还有人用过! :)标记您的问题[x86-32]或[x86-64],以便人们知道您正在使用哪一个。如果你使用的是x86-64,一个bug是显而易见的:你应该看看'%rip'和'%rsp',而不仅仅是'%eip'和'%esp'。这是全部吗? – Quuxplusone

+2

假设你没有犯任何错误,是否有机会启用cpu的数据执行保护并防止指令在非代码段运行? – rcgldr

+0

@rcgldr我觉得不是?如果我用-z execstack和-fno-stack-protector编译,它应该都很好? – user1090614

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

等价地,调试器可能在函数序言或结尾中间有一个反感,以致于如果你试图在结语中间设置一个断点,它会被秘密地调整到结尾的开头。