(Это предполагает, что решение Адама Rosenfields не применит его, или подобный подход, вероятно, лучшим способ. решите его.)
Вы не указали, как вы эмулируете регистр% 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 and IA-32 Architectures Software Developer's Manual Combined Volumes 2A and 2B: Instruction Set Reference, A-Z. Имейте в виду, что инструкции иногда префиксны с другими префиксами, иногда нет, поэтому вы, вероятно, должны использовать library, чтобы выполнять декодирование команд, а не слепо искать последовательности байтов.
Некоторые из приведенных выше инструкций должны быть относительно простыми, чтобы превратиться в call my_patch
или аналогичные, но у вас, вероятно, возникнут проблемы с поиском того, что подходит в двух байтах и работает в целом. int XX
(CD XX
) может быть хорошим кандидатом, если вы можете настроить вектор прерывания, но я не уверен, что он будет быстрее, чем метод, который вы сейчас используете.Разумеется, вам нужно будет записать, какая инструкция была исправлена, и обработчик прерывания (или что-то другое) реагирует по-разному в зависимости от обратного адреса (который получает ваш обработчик).
Вы можете быть в состоянии установить батут, если вы можете найти номер в пределах -128..127 байтов и использовать JMP rel8
(EB cb
), чтобы перейти к батут (обычно другой JMP
, но на этот раз с более места для целевого адреса), который затем обрабатывает эмуляцию команды и возвращается к инструкции после исправленного использования% gs.
Наконец-то я рекомендую держать код ловушки и эмуляции запущенным, чтобы поймать любые случаи, которые вы, возможно, не подумали (например, самомодифицируемый или введенный код). Таким образом, вы также можете регистрировать любые необработанные случаи и добавлять их в свое решение.
Теперь мы перехватываем ошибки страниц, вызванные доступом к несуществующему регистру% gs, двухбайтовый метод прерывания быстрее, чем перехват ошибки страницы? –
@Phillip: Поскольку я не знаю вашу среду исполнения, я не знаю, можно ли даже установить обработчик прерываний, и, как я писал, это, вероятно, не будет намного быстрее (вам нужно будет самому это время) , Я упомянул только об использовании прерываний, потому что это двухбайтная инструкция и позволяет «прыгать вперёд». Я бы предложил использовать 'int3' (' CC'), который вызывает 'SIGTRAP', но это будет мешать отладке. – user786653