Ожидаются ли изменения, внесенные в GOT, во время обратной отладки? - PullRequest
2 голосов
/ 14 января 2020

Ожидается ли, что изменения, внесенные в адресное пространство программы, не будут отменены во время обратной отладки?

Я выполнял отладку программы, которая вызывает ошибки, когда указатель на strlen в GOT повреждается во время ход исполнения. Благодаря совету, основанному на комментариях к этому вопросу , я получил ПОЛУЧЕНИЕ этой программы только для чтения, связавшись с опцией -z relro; однако это не предотвращает перезапись указанного указателя. А именно, я могу start программу в gdb, перейти к первому появлению strlen, проверить, что указатель действителен (например, x/g 0x5555555d10a8 ==> 0x5555555d10a8 <strlen@got.plt>: 0x00007ffff7e8d1e0), continue запущен, и ждать, пока указатель станет недействительным (указывая на бессмысленный адрес за пределами адресного пространства программы; например: x/g 0x5555555d10a8 ==> 0x5555555d10a8 <strlen@got.plt>: 0x0000000000002156), запрашивая segv.

Однако, если я record full всего выполнения (от первой строки до программа с ошибками), а затем awatch адрес с указателем на strlen во время reverse-continue, точка наблюдения никогда не срабатывает. И когда программа, наконец, вернулась к инструкции # 0, указатель все еще указывает на неверный адрес, который у нее был при сбое.

Это приводит к двум вопросам. Во-первых, почему GOT изменчив, несмотря на параметр компоновщика -z relro? Во-вторых, ожидается ли, что место в памяти (указатель на strlen), измененное во время выполнения программы, не будет восстановлено до исходного значения во время обратного выполнения?

Ответы [ 2 ]

1 голос
/ 14 января 2020

Во-первых, почему GOT изменчив, несмотря на опцию -z relro linker?

То, что вы применяете с -Wl,-z,relro, является только частичной защитой RELRO. Эта опция имеет основную цель перемещения GOT перед BSS, чтобы избежать искажения записей из-за переполнения из буферов в BSS, а также делает небольшую часть GOT доступной только для чтения. Вам нужно full RELRO, которое получается с -Wl,-z,relro,-z,now. Флаг компоновщика -z now заставляет загрузчик разрешать все символы при запуске, а затем переназначать сегмент, содержащий GOT, только для чтения, перед запуском программы.

Во-вторых, ожидается ли это для местоположения в памяти (указатель на strlen), который изменяется во время выполнения программы и не восстанавливается до исходного значения во время обратного выполнения?

Возможно, вы забыли установить target record-full перед началом отладки, но Я не уверен, что это даст какой-либо эффект, так как вы уже используете record full. Обратное выполнение нелегко, отладчик может решить , а не отменить изменения памяти GOT (или других разделов) по соображениям производительности (так как обычно их не следует трогать). Функция записи GDB также имеет некоторые другие ограничения, например, не поддерживает инструкции AVX. Я не знаю намного больше, чтобы дать лучший ответ. Вы можете попытать счастья с rr.

1 голос
/ 14 января 2020

Опция -z relro делает только частичное только чтение (В частичном RELRO не-PLT часть секции GOT ( .got из вывода readelf) только для чтения, но .got.plt все еще доступен для записи. Принимая во внимание, что в полном RELRO весь GOT ( .got и .got.plt оба) помечен как доступный только для чтения.

Если вы хотите иметь полное чтение, используйте также -z, now.

Закаливание двоичных файлов ELF с помощью Relocation

...