Помочь расшифровать несколько строк сборки
Вопрос
Я нашел эти несколько строк сборки в Ollydbg:
MOV ECX,DWORD PTR DS:[xxxxxxxx] ; xxxxxxxx is an address
MOV EDX,DWORD PTR DS:[ECX]
MOV EAX,DWORD PTR DS:[EDX+116]
CALL EAX
Может кто-нибудь выступить и скажи мне, что здесь происходит?
Решение
Это вызов указателя функции, хранящегося в структуре.
Эта первая строка получает указатель, хранящийся по адресу DS:xxxxxxxx
. Отказ Квадратные скобки указывают Дереференция адреса, как *
в C. Значение из памяти собирается использоваться в качестве указателя; это помещено в ecx
регистр.
MOV ECX,DWORD PTR DS:[xxxxxxxx] ; xxxxxxxx is an address
Вторая линия разыгрывает указатель, полученный выше. Это значение из ecx
в настоящее время используется в качестве адреса, который превенствует. Значение, найденное в памяти, является еще одним указателем. Этот второй указатель помещен в edx
регистр.
MOV EDX,DWORD PTR DS:[ECX]
Третья строка снова разрабатывает память; На этот раз доступ встречается с адресом компенсировать От указателя, полученного выше 0x116 байта. Это не равномерно делится на четыре, поэтому этот указатель функции не появляется от VTable C ++. Значение, полученное из памяти, это время, сохраненное в регистре eax
.
MOV EAX,DWORD PTR DS:[EDX+116]
Наконец, функция, указанная на eax
выполняется. Это просто вызывает функцию через указатель функции. Появляется функция, чтобы взять нулевые аргументы, но у меня есть вопрос о пересмотре моего ответа: там есть PUSH
Инструкция, предшествующая этому фрагменту? Это были бы функциональные аргументы. Знаки вопросов указывают, что эта функция может вернуть значение, мы не можем сказать с нашего Vantage.
CALL EAX
В целом, фрагмент кода выглядит как вызов функции расширения из библиотеки плагинов в Ollydbg. Ollydbg Abi определяет различные struct
S, который содержит некоторые функциональные указатели. Существуют также массивы указателей функций, но двойное косвествие, чтобы добраться до edx
-Хельдный указатель (также не совсем выровненный-даже-многократный смещение) заставляет меня думать, что это struct
и не массив указателей функций или VTable класса C ++.
Другими словами, xxxxxxxx
является указателем на указатель на struct
содержащий указатель функции.
В плагине исходного файла Ollydbg. Есть какой-то кандидат struct
Определения. Вот пример:
typedef struct t_sorted { // Descriptor of sorted table
char name[MAX_PATH]; // Name of table, as appears in error
int n; // Actual number of entries
int nmax; // Maximal number of entries
int selected; // Index of selected entry or -1
ulong seladdr; // Base address of selected entry
int itemsize; // Size of single entry
ulong version; // Unique version of table
void *data; // Entries, sorted by address
SORTFUNC *sortfunc; // Function which sorts data or NULL
DESTFUNC *destfunc; // Destructor function or NULL
int sort; // Sorting criterium (column)
int sorted; // Whether indexes are sorted
int *index; // Indexes, sorted by criterium
int suppresserr; // Suppress multiple overflow errors
} t_sorted;
Эти примеры разрешено быть NULL
, и ваш фрагмент ASM не проверяет NULL
Указатель в указателе функции. Поэтому это должно быть DRAWFUNC
от t_table
или SPECFUNC
из t_dump
.
Вы можете создать небольшой проект, который включает в себя файл заголовка и использует printf()
и offsetof()
Чтобы определить, является ли либо из них на смещении 0x116.
В противном случае я представляю, что в этом же стиле написаны внутренности ollydbg. Так что, вероятно, будут частными struct
Определения (не опубликованные в файле Plugin.h), используемые для различных целей в Ollydbg.
Я хотел бы добавить, я думаю, что это позор, что источники Ollydbg недоступны. У меня было впечатление, что по статиционально связанному девочке он содержит, было под какой-то? Лицензия GPL, но мне не повезло получать источники в Ollydbg.
Другие советы
Возьмите 32-битный номер с адреса XXXXXXX и поместите его в регистр ECX, затем используйте это значение в качестве адреса и прочитайте значение и поместите его в REDX Register, наконец добавьте 116 на этот номер и прочитайте значение этого адреса в EAX. Затем он начинает выполнять код по адресу, который теперь проводится в EAX. Когда этот код сталкивается с возвратом OPCode, выполнение будет продолжено после инструкции вызова.
Это довольно базовая сборка. Это заставляет меня удивляться WTF, вы делаете с отладчиком, и когда ваше задание должно быть ;-)
Это было некоторое время, так как я сделал ASM (1997) и даже тогда я только делал только I386 ASM, поэтому простите меня, если мой ответ не все это полезно ...
К сожалению, эти 4 строки кода не говорят мне много. Он в основном просто загружает вещи в регистры CPU и вызывают функцию.
В частности, похоже, что данные или, возможно, указатель загружается из этого адреса в ваш регистр CX. Тогда это значение копируется от CX в DX. Таким образом, у вас есть значение указателя CX, расположенного в DX. Тогда это значение в DX плюс смещение 116 копируется в регистр AX (ваш аккумулятор?)
Тогда какая-либо функция, расположенная на этом адресе, скопированной в топор.
Я на 99% уверен, что это вызов виртуального метода, учитывая комментарии о компиляторе MSVC.
MOV ECX,DWORD PTR DS:[xxxxxxxx]
Указатель на экземпляр класса загружен в ECX из глобальной переменной. (NB: по умолчанию __thishall Convenge Convenge использует ECX для передачи указателя экземпляра, ака это указатель).
MOV EDX,DWORD PTR DS:[ECX]
Указатель VFTable (таблица виртуальной функции) обычно является первым элементом в классе класса. Здесь указатель загружен в edx.
MOV EAX,DWORD PTR DS:[EDX+116]
Указатель метода при смещении 116 (0x74) в таблице загружается в EAX. Поскольку каждый указатель составляет 4 байта, это 30-й виртуальный метод класса (116/4 + 1).
CALL EAX
Способ называется.
В оригинальном C ++ будет выглядеть что-то подобное:
g_pObject1->method30();
Чтобы узнать больше о реализации MSVC классов C ++, включая виртуальные методы, см. Мою статью здесь.