х86 способ отличить инструкцию от данных - PullRequest
4 голосов
/ 19 ноября 2010

Существует ли более или менее надежный способ определить, являются ли данные в каком-либо месте в памяти началом инструкции процессора или какими-то другими данными?

Например, E8 3F BD 6A 00 может быть call инструкцией (E8) с относительным смещением 0x6ABD3F, или это может быть три байта данных, принадлежащих какой-либо другой инструкции, за которыми следует push 0 (* 1008) *).

Я знаю, что вопрос звучит глупо, и, вероятно, не существует простого способа, но, возможно, набор инструкций был разработан с учетом этой проблемы, и, возможно, некоторый простой код, исследующий + -100 байт вокруг местоположения, может дать ответ, который, скорее всего, правильный .

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

Ответы [ 5 ]

5 голосов
/ 19 ноября 2010

Если это ваш код (или другой, содержащий информацию о связях и отладке), лучше всего сканировать таблицы символов / перемещений в объектном файле. В противном случае не существует надежного способа определить, является ли какой-либо байт вторжением или данными.

Возможно, наиболее эффективный метод проверки данных - это рекурсивная разборка. И. е. дизассемблирование кода из точки входа и из всех найденных пунктов перехода. Но это не совсем надежно, потому что оно не пересекает таблицы переходов (вы можете попытаться использовать некоторую эвристику для этого, но это также не совсем надежно).

Решением вашей проблемы было бы заменить саму функцию исправления: перезаписать ее начало переходом к вашей функции.

2 голосов
/ 19 ноября 2010

К сожалению, нет 100% надежного способа отличить код от данных. С точки зрения процессора, код является кодом только тогда, когда какой-то код операции перехода заставляет процессор пытаться выполнить байты, как если бы они были кодом. Можно попытаться выполнить анализ потока управления, начав с точки входа в программу и следуя всем возможным путям выполнения, но это может не сработать при наличии указателей на функцию.

Для вашей конкретной проблемы: я понимаю, что вы хотите заменить существующую функцию заменой вашей собственной. Я предлагаю вам исправить саму замененную функцию. Т.е. вместо того, чтобы найти все вызовы функции foo() и заменить их вызовом bar(), просто замените первые байты foo() переходом на bar() (jmp, а не * 1008). *: вы не хотите связываться со стеком). Это менее удовлетворительно из-за двойного прыжка, но это надежно.

1 голос
/ 19 ноября 2010

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

1 голос
/ 19 ноября 2010

Невозможно отличить данные от инструкции в целом, и это из-за архитектуры фон Неймана . Анализ кода вокруг полезен, и инструменты разборки делают это. ( Это может быть полезным. Если вы не можете использовать IDA Pro / она коммерческая /, используйте другой инструмент для разборки.)

0 голосов
/ 20 ноября 2010

Томас предлагает правильную идею. Для правильной реализации вам необходимо разобрать первые несколько инструкций (часть, которую вы перезаписали бы JMP) и сгенерировать простую функцию батута, которая выполняет их, а затем переходит к остальной части исходной функции.

Есть библиотеки, которые делают это для вас. Хорошо известным является Detours , но он имеет несколько неловкие условия лицензирования. Хорошая реализация той же идеи с более разрешительной лицензией: Mhook .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...