(Предполагается, что решение Адама Розенфилда неприменимо. Возможно, это лучший способ его решения или аналогичный подход).
Вы не указали, как эмулировать% gs.зарегистрируйтесь, но, вероятно, будет непросто пропатчить каждое использование в целом, если у вас нет специальных знаний о программе, потому что в противном случае у вас есть только 2 байта (в худшем, обычном случае), которые вы можете изменить с помощьюваш патч.Конечно, если вы используете что-то вроде% es =% gs, это должно быть относительно просто.
Если предположить, что это как-то может работать в вашем случае, стратегия состоит в том, чтобы сканировать исполняемые секции ELF-файл и исправление любой инструкции, которая использует или изменяет регистр GS.Это как минимум следующих инструкций:
- Любая инструкция с префиксом переопределения сегмента GS (
65
ожидается для инструкций ветвления, в этом случае префикс указывает на что-то еще) push gs
(0F A8
) pop gs
(0F A9
) mov r/m16, gs
(8C /r
) mov gs, r/m16
(8E /r
) mov gs, r/m64
(REX.W 8E /r
) (если вы поддерживаете 64-битный режим)
И любые другие инструкции, которые разрешают регистры сегментов (я не думаю,это гораздо больше, но я не уверен на 100%).
Это все из Руководство разработчика программного обеспечения для архитектуры Intel® 64 и IA-32, Объединенные тома 2A и 2B: Справочник по наборам инструкций, AZ .Имейте в виду, что инструкции иногда имеют префикс других префиксов, иногда нет, поэтому вам, вероятно, следует использовать библиотеку для декодирования команд, а не вслепую искать последовательности байтов.
Некоторые изПриведенные выше инструкции должны быть относительно простыми, чтобы их можно было преобразовать в call my_patch
или аналогичные, но у вас, вероятно, возникнут проблемы с поиском чего-то, что умещается в два байта и работает в целом.int XX
(CD XX
) может быть хорошим кандидатом, если вы можете установить вектор прерывания, но я не уверен, что он будет быстрее, чем метод, который вы используете в настоящее время.Вам, конечно, нужно будет записать, какая инструкция была исправлена, и обработчик прерываний (или что-то еще) реагирует по-разному в зависимости от адреса возврата (который получает ваш обработчик).
Возможно, вы сможете установить батут, еслиВы можете найти место в пределах -128,127 байт и использовать JMP rel8
(EB cb
), чтобы прыгнуть на батут (обычно другой JMP
, но на этот раз с большим количеством места для целевого адреса), который затем обрабатывает инструкциюэмуляции и переходит обратно к инструкции, следуя исправленному использованию% gs.
Наконец, я бы порекомендовал оставить код trap-and-emulate запущенным, чтобы перехватывать любые случаи, о которых вы, возможно, не подумали (самоизменение иливведенный код например).Таким образом, вы также можете регистрировать любые необработанные случаи и добавлять их в свое решение.