Помогите расшифровать несколько строк сборки - PullRequest
5 голосов
/ 11 августа 2010

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

Может ли кто-нибудь пройти и рассказать мне, что здесь происходит?

Ответы [ 4 ]

6 голосов
/ 11 августа 2010

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

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

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

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

MOV EDX,DWORD PTR DS:[ECX]

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

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

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

CALL EAX

В целом, фрагмент кода выглядит как вызов функции расширения из библиотеки подключаемых модулей к OllyDbg. ABI OllyDbg определяет различные struct, которые содержат некоторые указатели на функции. Существуют также массивы указателей на функции, но двойное косвенное обращение к указателю 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.

2 голосов
/ 11 августа 2010

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

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

0 голосов
/ 26 августа 2010

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

MOV ECX,DWORD PTR DS:[xxxxxxxx]

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

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 ++, включая виртуальные методы, см. Мою статью здесь .

0 голосов
/ 11 августа 2010

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

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

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

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

...