Я пытаюсь изменить адрес возврата в стеке в обработчике ошибок сегмента, чтобы он пропускал инструкцию по сбою. Тем не менее, я получаю ошибку сегмента, когда я пытаюсь изменить обратный адрес, если я не вызываю обработчик сигнала напрямую.Различия в стеке между обработчиком сигнала, вызываемым напрямую, и raise()?
gdb не подходит для отладки, когда программа выполняет segfault, но когда я делаю info frame
Я вижу, что после segfault есть «уровень кадра 2», а не «уровень кадра 0»? Я не знаю, где GDB получает эту информацию, потому что, когда я пытаюсь x/12xw $ebp
или как бы много слов, я не вижу обратный адрес main()
...
Скомпилировано с -m32 -z execstack -fno-stack- протектор на CentOS Linux
#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, потому что команда phail в main()
составляет 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 <[email protected]>
мне нужно увеличить смещение немного ли? Является ли мой метод доступа к стеку (который, как мне кажется, соответствует EBP + 4), необходимо изменить при работе с ситуацией сбоя сегмента?
Вам необходимо изменить сохраненный ПК в структуре 'ucontext_t', переданный обработчику, * не * непосредственный обратный адрес функции обработки сигналов. (И * не * вызывайте его напрямую.) Пример программы на странице https://stackoverflow.com/questions/5119288/getting-fault-address-that-generated-a-unix-signal/5120984 показывает, как получить доступ к 'ucontext_t'. – zwol