【发布时间】:2017-01-27 23:18:04
【问题描述】:
我正在尝试在段错误处理程序中修改堆栈上的返回地址,以便它跳过错误指令。但是,如果我不直接调用信号处理程序,则每当我尝试修改返回地址时都会出现段错误。
当程序发生段错误时,gdb 不适合调试,但是当我执行info frame 时,我看到,在段错误之后,有“帧级别 2”而不是“帧级别 0”?我不知道 GDB 从哪里得到这些信息,因为当我尝试x/12xw $ebp 或任何字数时,我看不到main() 的返回地址...
在 CentOS linux 上使用 -m32 -z execstack -fno-stack-protector 编译
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
void segment_fault_handler(int signum)
{
char* ret = (char*)(&signum)-4;
*(ret) += 8;
}
int main()
{
int phail = 0;
signal(SIGSEGV, segment_fault_handler);
segment_fault_handler(7); //Only by using this can I skip the next instruction
phail = *( (int *) 0);
printf("Win!\n");
return 0;
}
我加8的原因是因为main()中的phail指令是8个字节:
0x080484e2 <+37>: movl $0x7,(%esp)
0x080484e9 <+44>: call 0x8048480 <segment_fault_handler>
0x080484ee <+49>: mov $0x0,%eax
0x080484f3 <+54>: mov (%eax),%eax
0x080484f5 <+56>: mov %eax,0x1c(%esp)
0x080484f9 <+60>: movl $0x80485b4,(%esp)
0x08048500 <+67>: call 0x8048350 <puts@plt>
我需要稍微增加偏移量吗?在处理段错误情况时,我访问堆栈的方法(我认为对应于 EBP+4)是否需要更改?
【问题讨论】:
-
您需要修改传递给处理程序的
ucontext_t结构中保存的PC,不是信号处理函数的立即返回地址。 (并且不要直接调用它。)stackoverflow.com/questions/5119288/… 的示例程序展示了如何访问ucontext_t结构。
标签: c gcc segmentation-fault stack-overflow disassembly