Это для 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
Почему не получается, когда я только что подтвердил, что могу писать там?