Это, скорее всего, C++, а не обычный C. То есть именно то, что Visual C++ - генерироваться вызовы виртуального метода выглядеть. Я бы сказал, что:
dword_10087418
является указателем на объект. Это либо глобальная, либо статическая переменная, а не локальная.
- Этот объект имеет таблицу виртуальных методов, а код вызывает вторую функцию в этой таблице.
- Предполагая, что Hex-Rays правильно определили аргументы функции, вызываемая функция принимает один 32-битный аргумент. Тип возврата не ясен.
- Вызов C++ был, скорее всего, очень простым, похожим на
SomeClass::Instance->func(arg)
.
Если вы не знакомы с планировкой объекта в C++, вы должны прочитать C++ Under the Hood, Reversing: Secrets of Reverse Engineering или Inside the C++ Object Model. Книга IDA Pro также содержит краткий раздел по этой теме.
Если вы хотите получить краткое резюме, читайте дальше. Имейте в виду, что все это деталь реализации MSVC, другие компиляторы делают это по-другому, и они могут свободно изменять ее по своему усмотрению. (Кроме того, я упрощаю вещи, не говоря уже о виртуальном/множественном наследовании). Когда класс использует виртуальные функции, компилятор строит таблицу всех таких функций в этом классе и помещает указатель на эту таблицу в качестве первого скрытого члена каждого объекта этого класса.Затем, вызывая виртуальную функцию из таблицы так же просто, как:
mov ecx, esi ; pretend that esi contains a pointer
; to the object whose method is being called
; also known as "this"
; __thiscall functions expect to find this pointer in ecx
; and all later arguments on the stack
mov edx, [ecx] ; get the vtable address
push edi ; set up some integer-sized argument
call [edx + 4] ; call the second function in the vtable
И это в основном то, что строка кода делает:
(*(int (__thiscall **)(int, int))(*(_DWORD *)dword_10087418 + 4))(dword_10087418, v11)
^-----------------------^
dereference pointer to get the address of the vtable
(it's the first piece of data in the object)
^-----------------------------^
add 4 bytes to get address of the second function
^------------------------------------------------------------------------------------^
cast that pointer to a particular function pointer and call it
(cast is invisible in assembler code, so it's just a call)
Обратите внимание, что поскольку функция член нуждается в доступе к this
, компилятор должен передать его также. Это деталь, которая не видна в C++, но this
рассматривается как дополнительный аргумент для функции - следовательно, вы видите два аргумента, но функция принимает только один (в соглашении MSVC thiscall
указывается, что указатель передан в ecx
). IDA не беспокоится о том, чтобы скрывать этот указатель, потому что это запуталось бы.
Дополнительные советы: Получить ms_rtti
скрипт для IDA и запустить его, чтобы найти таблицы виртуальных методов в DLL, а затем искать другие ссылки на dword_10087418
, чтобы увидеть, какие значения записываются в ней - вы должны быть в состоянии определить, какая vtable связана с этим объектом, а затем выяснить, какая функция вызывается.
Вы можете сделать шестнадцатеричные лучи более удобным для отображения кода, если вы определяете типы структуры stub для класса и рассматриваемого vtable, а затем сообщите IDA, что указатель использует этот тип структуры.
Ух ты .. Я думаю, что это одна из причин, почему я так сильно избегаю C-Style. – Brandon