Почему я получаю ошибку сегментации при попытке выполнить запись инструкции в память, когда отладчик может вручную записать в ту же память? - PullRequest
0 голосов
/ 23 января 2019

Это для x86-64, часть эксплойта по переполнению стека.

Вывод GDB:

=> 0x000055555555e996:  48 89 18    mov    QWORD PTR [rax],rbx

Переместить rbx в адрес памяти, хранящейся в rax, просто. Поскольку в этой инструкции есть ошибки, давайте посмотрим на нее.

Что такое в rax?

(gdb) i r rax
rax            0x7ffff79f4c80      140737347800192

Действительна ли эта память?

(gdb) x/16b $rax
0x7ffff79f4c80 <_itoa_upper_digits>:    0x30    0x31    0x32    0x33    0x34    0x35    0x36    0x37
0x7ffff79f4c88 <_itoa_upper_digits+8>:  0x38    0x39    0x41    0x42    0x43    0x44    0x45    0x46

Ну, по крайней мере, я могу читать. Можно мне написать?

(gdb) set $rbx = 0x4141414141414141
(gdb) set {unsigned long} $rax = $rbx
(gdb) x/16b $rax
0x7ffff79f4c80 <_itoa_upper_digits>:    0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0x7ffff79f4c88 <_itoa_upper_digits+8>:  0x38    0x39    0x41    0x42    0x43    0x44    0x45    0x46

Кажется, что работает нормально, и эта операция набора действительно, кажется, действительно записывает в память, попытка того же к известному неправильному адресу приведет к ошибке. Так что, похоже, я могу и писать, и читать в эту память.

Давайте попробуем выполнить эту инструкцию. Все тот же:

(gdb) x/i $pc
=> 0x55555555e996:  mov    QWORD PTR [rax],rbx
(gdb) si

Program received signal SIGSEGV, Segmentation fault.
(a=<error reading variable: Cannot access memory at address 0x376141366141355d>)
    at test.c:371
371     asm volatile("mov %rbx,(%rax);"
=> 0x000055555555e996:  48 89 18    mov    QWORD PTR [rax],rbx
   0x000055555555e999:  c3  ret    

Почему не получается, когда я только что подтвердил, что могу писать там?

1 Ответ

0 голосов
/ 23 января 2019

Почему не получается, когда я только что подтвердил, что могу написать туда?

Программа не может писать туда, может только GDB.

Адрес, по которому вы пытаетесь написать, находится в разделе .text, который обычно mmap ed с PROT_READ|PROT_EXEC и без PROT_WRITE.

Однако GDB (или любому процессу, * ptrace использующему этот процесс) разрешено записывать в такие отображения. Это необходимо для того, чтобы GDB мог вставлять точки останова (что часто требует переписывания инструкций программы).

...