2010-08-10 4 views
5

Я нашел эти несколько строк сборки в 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 

Может кто пошагово и скажите мне, что здесь происходит?

+0

@ x0n - откуда домашняя бирка? –

+0

Это не домашнее задание, я просто плохо разбираюсь в сборке. – Iron

+0

удален домашняя бирка. – x0n

ответ

6

Это вызов указателя функции, хранящегося в структуре.

Эта первая строка получает указатель, хранящийся по адресу DS:xxxxxxxx. Квадратные скобки обозначают разыменованием адреса, как * в C. Значение из памяти предназначено для использования в качестве указателя; он помещается в регистр ecx.

MOV ECX,DWORD PTR DS:[xxxxxxxx] ; xxxxxxxx is an address 

Вторая строка разделяет указатель, полученный выше. Это значение от ecx теперь используется как адрес, который разыменовывается. Значение, найденное в памяти, является другим указателем. Этот второй указатель помещается в регистр edx.

MOV EDX,DWORD PTR DS:[ECX] 

Третья строка снова разыменовывает память; на этот раз доступ происходит по адресу offset из указателя, полученного выше, на 0x116 байт. Это не равномерно делится на четыре, поэтому этот указатель функции не появляется из C++ vtable. Значение, полученное из памяти, на этот раз хранится в регистре eax.

MOV EAX,DWORD PTR DS:[EDX+116] 

Наконец, функция указывает eax выполняется. Это просто вызывает функцию через указатель функции. Функция, как представляется, принимает нулевые аргументы, но у меня есть вопрос о пересмотре моего ответа: есть ли инструкция PUSH, предшествующая этому фрагменту? Это будут аргументы функции. Вопросительные знаки указывают, что эта функция может вернуть значение, мы не можем сказать из нашего преимущества.

CALL EAX 

В целом, фрагмент кода выглядит как вызов функции расширения из плагина в библиотеке в OllyDbg. ABI OllyDbg определяет различные struct s, которые содержат некоторые указатели на функции. Существуют также массивы указателей на функции, но двойная обратная связь, чтобы добраться до указателя edx (также смещение с невыравниванием по четному краю), заставляет меня думать, что это struct, а не массив указателей функций или класс vtable класса C++.

Иными словами, xxxxxxxx является указателем на указатель на struct, содержащий указатель на функцию.

В исходном файле OllyDbg PlugIn.h - некоторые кандидаты 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.

+0

+1 для лучшего описания, чем мое. :-) – Pretzel

+0

«Это, наверное,« призыв ... »будет более точным, нет? Вы не представляете, что это на самом деле. – x0n

+0

@ x0n. Нет, я думаю, у меня есть очень хорошая идея, что это. У меня есть опыт работы с OllyDbg. Например, я бы никогда ничего не написал по строкам «OllyDbg, возможно, был написан на неопределенном языке более высокого уровня». Он был скомпилирован с MSVC 2005, и я обладаю знаниями, специфичными для домена. Разумеется, фрагмент может быть встроенной сборкой, но написав плагин OllyDbg или три и фальшивый тестовый жгут проводов OllyDbg ... Я думаю, что знаю, что это такое. XOFF. –

0

Это было некоторое время, так как я сделал ASM (1997), и даже тогда я только делал i386 ASM так что простите меня, если мой ответ не все, что полезно ...

К сожалению, эти 4 строки кода дону Не говори мне много. Это просто загрузка файлов в регистры процессора и вызов функции.

В частности, это похоже на данные или, возможно, указатель загружается с этого адреса в ваш регистр CX. Затем это значение копируется из CX в DX. Таким образом, вы указали значение указателя CX, расположенного в DX. Затем это значение в DX плюс смещение 116 копируется в регистр AX (ваш аккумулятор?).

Затем выполняется любая функция, расположенная на этом адресе, скопированном в AX.

+0

Изменяет ли он его в любом случае DWORD PTR то, что уже было DWORD PTR'd? – Iron

+0

Я не вижу никаких изменений, но CALL'ing EAX может называть что-то, что делает некоторые изменения. Я не могу сказать, не зная, что там находится ... – Pretzel

+0

Я уверен, что загружает значение *, указываемое * DS: [ECX] в EDX, а не просто копирование ECX в EDX, например x0n. – zwol

2

Возьмите 32-разрядное число с адреса xxxxxxx и поместите его в регистр ECX, затем используйте это значение в качестве адреса и прочитайте значение и поместите его в регистр EDX, наконец добавьте 116 к этому номеру и прочитайте значение этого адрес в EAX. Затем он начинает выполнять код по адресу, который теперь находится в EAX. Когда этот код встречает код операции возврата, выполнение будет продолжено после команды вызова.

Это довольно простая сборка. Это заставляет меня задуматься о том, что вы делаете с отладчиком и когда назначается ваше задание ;-)

+0

Я изучаю сборку через отладочные материалы, поэтому неудивительно, что это базовая. Я понял, что он сделал, но я не видел смысла в «MOV ECX, DWORD PTR [адрес]», затем «MOV EDX, DWORD PTR [ECX]», поэтому я подумал, что это может сделать что-то не очевидное , Так или иначе, означает ли это, что xxxxxxxx является указателем на функцию или указателем на указатель на функцию? – Iron

+0

Это не значит ничего, кроме того, что это значит. Вы не можете сделать вывод, что там есть «функция» или даже если функции существуют как концепция в любом более высоком языке, который был скомпилирован (или даже если речь шла о языке более высокого уровня, tbh). Чтобы перепроектировать этот код, вы «Мне нужно интимное знание компилятора, который его создал. – x0n

+0

Я знаю, что это был MSVC++, вероятно, 2005 год. – Iron

0

Я на 99% уверен, что это вызов виртуального метода, учитывая комментарии о компиляторе, являющемся MSVC.

MOV ECX,DWORD PTR DS:[xxxxxxxx] 

Указатель экземпляра класса загружается в ECX из глобальной переменной. (NB: по умолчанию __thiscall call convention использует ECX для передачи указателя экземпляра, так же как этот указатель).

MOV EDX,DWORD PTR DS:[ECX] 

Указатель vftable (virtual function table) обычно является первым элементом в макете класса. Здесь указатель загружается в EDX.

MOV EAX,DWORD PTR DS:[EDX+116] 

Указатель метода в смещении 116 (0x74) в таблице загружается в EAX. Поскольку каждый указатель имеет 4 байта, это 30-й виртуальный метод класса (116/4 + 1).

CALL EAX 

Метод называется.

В оригинальной C++ это будет выглядеть примерно так:

g_pObject1->method30(); 

Чтобы узнать больше о реализации MSVC о классах C++, включая виртуальные методы, смотрите мою статью о here.

Смежные вопросы