Обход и использование _thiscall в качестве ловушки (соглашение о вызовах GCC)
Недавно я работал над функциями обхода (только в Linux) и до сих пор добился большого успеха. Я разрабатывал свой собственный обходной класс, пока не нашел это. Я немного модернизировал код и преобразовал его в C++ (как класс, конечно). Этот код, как и любая другая обходная реализация, заменяет исходный адрес функции JMP на мою собственную указанную функцию ловушки. Это также создает "батут" для оригинальной функции.
Все работает безупречно, но я бы хотел сделать одну простую настройку. Я программирую на чистом C++, я не использую глобальные функции, и все заключено в классы (как Java/C#). Проблема в том, что этот метод обхода нарушает мою схему. Функция "hook" должна быть статической / не классовой функцией.
То, что я хочу сделать, - это реализовать поддержку ловушек _thiscall (что должно быть довольно просто с соглашением GCC _thiscall). Мне не удалось изменить этот код для работы с ловушками _thiscall. То, что я хочу в качестве конечного результата, является чем-то таким же простым, как это; PatchAddress(void * target, void * hook, void * class);
, Я не прошу никого делать это для меня, но я хотел бы знать, как решить / подойти к моей проблеме?
Из того, что я знаю, мне нужно только увеличить размер "патча" (то есть теперь это 5 байтов, и мне нужно дополнительно 5 байтов?), А затем, прежде чем я использую вызов JMP (для моей функции ловушки), я вставьте мой указатель this в стек (который должен быть таким, как если бы я вызывал его как функцию-член). Проиллюстрировать:
push 'my class pointer'
jmp <my hook function>
Вместо того, чтобы просто / просто вызывать 'jmp'. Это правильный подход или есть что-то еще, что следует принять во внимание (примечание: меня не волнует поддержка VC++ _thiscall)?
ПРИМЕЧАНИЕ: вот моя реализация вышеупомянутого кода: header: source, использует libudis86
1 ответ
Я попробовал несколько различных методов, и среди них была JIT-компиляция (с использованием libjit), которая оказалась успешной, но метод не обеспечил достаточную производительность, чтобы его можно было использовать. Вместо этого я обратился к libffi, который используется для динамического вызова функций во время выполнения. Библиотека libffi имеет закрывающий API (ffi_prep_closure_loc
), который позволял мне указывать мой указатель this для каждого сгенерированного замыкания. Поэтому я использовал статическую функцию обратного вызова и преобразовал void
указатель на мой тип объекта, и оттуда я могу вызвать любую нестатическую функцию, какую захочу!