2012-08-12 2 views
4

Я работаю над программой обратного проектирования. Я использую IDA Pro и Decompiler Hex-Rays. Я сталкиваюсь с кусками кода, где я знаю, что есть объект, и есть вызов метода на объекте, но он показан так, как я не могу понять. Например:Извлечение макета памяти объектов без отладки запущенной программы?

if ((*(*interfacePtr + 24))(interfacePtr, &v23) >= 0) 

Я знаю здесь, что interfacePtr указывает на объект ICLRRuntimeHost. (C++, .NET CLR). Однако ... я понятия не имею, что есть на * (* interfacePtr + 24). Я могу сказать, что это метод, но как мне понять, что сидит на +24?

+0

Вам не кажется, что это лучше ответили на одном из форумов обратного проектирования? Или, возможно, форум IDA/hex-ray, к которому у вас должен быть доступ после оплаты дорогостоящего pricetag для этого программного обеспечения? – snemarch

+1

IDA может анализировать файлы заголовков C для деклараций структуры. 'ICLRRuntimeHost' определен в файле SDK' mscoree.h' Windows, с некоторыми работами вы можете либо передать этот файл в IDA, либо, по крайней мере, извлечь объявления класса и vtable в другой файл и проанализировать это.После того, как у IDA есть определение этого класса, вы можете просто сказать Hex-Rays, что 'interfacePtr' имеет тип' ICLRRuntimeHost' (нажмите Y или щелкните правой кнопкой мыши имя переменной), и он обновит отображение, чтобы включить имя функции. – DCoder

+0

@snemarch Я думаю, что этот вопрос совершенно верен, учитывая, что SO - это все о программировании, которое в конце дня ... это то, о чем мой вопрос действительно. Я бы использовал доски объявлений для продукта, если у меня возникла проблема с продуктом. Тем не менее, это просто у меня недостаточно знаний о лежащей в основе механике собственного исполняемого файла Windows ... не у меня проблема с IDA или декомпилятором Hex-Rays. –

ответ

2

vtable класса - это просто список указателей на функции. Он содержит один указатель для каждой виртуальной функции, в порядке: очень, очень верхний базовый класс, следующий базовый класс, подкласс этого. , , самый производный класс.

Пример:

struct A { 
    virtual ~A() {} 
    virtual void foo() = 0; 
} 
struct B : public A { 
    virtual void foo() { // do something } 
    virtual void bar() { // do something else } 
} 

виртуальные таблицы для B будет содержать, в следующем порядке:

  • ~ A
  • Foo
  • бар

(те, для A должны быть первыми, так что одна и та же vtable может быть u sed по частям кода, которые имеют указатель типа A к этому объекту; этот код не знает, что базовый объект действительно B.)

Если вы ищете 32-разрядный источник, указатели составляют 4 байта, поэтому 24 = 4 * 6, вы смотрите на 7-й виртуальный функция (индекс начинается с 0). Если вы на 64-битном, указатели составляют 8 байтов, поэтому 24 = 8 * 3, и вы ищете 4-й. Фактически, я не использовал функциональность IDA «конвертировать в C++», поэтому, возможно, 24 фактически является 24-й записью в таблице.

Простой способ подтверждения: написать свою собственную программу. Объявите переменную типа ICLRRuntimeHost. Вызовите функцию, которую вы подозреваете (основываясь на просмотре файла заголовка и подсчете до 7 или 4, в зависимости от битности или 24, если я неправильно понял ваш пример). Посмотрите на сгенерированный код сборки и убедитесь, что ваш индекс прав. (Я всегда выключен один на такого рода вещи, так что это обеспечит проверку.)

+0

Действительно ли я предполагаю, что вы хотели объявить B расширением A? –

+0

Помимо моего вышеприведенного комментария, глядя на mscoree.h при чтении этого psuedocode, хорошо сочетается с всей схемой упорядочения vtable. Похоже, это было для меня недостающее звено. : D –

+0

Да, B должен расширять A. Исправлено. – Michael

0

Посмотрите определения ICLRRuntimeHostVtbl и ICLRRuntimeHostVtbl в mscoree.h

примерно переводится на что-то hexrays бы понять, они выглядят следующим образом:

struct ICLRRuntimeHost { 
    ICLRRuntimeHostVtbl *vtbl; 
}; 
struct ICLRRuntimeHostVtbl { 
    _DWORD (*QueryInterface)(ICLRRuntimeHost*, _DWORD*, void**); 
    _DWORD (*AddRef)(ICLRRuntimeHost*); 
    _DWORD (*Release)(ICLRRuntimeHost*); 
    _DWORD (*Start)(ICLRRuntimeHost*); 
    _DWORD (*Stop)(ICLRRuntimeHost*); 
    _DWORD (*SetHostControl)(ICLRRuntimeHost*, void*); 
    _DWORD (*GetCLRControl)(ICLRRuntimeHost*, void**); 
}; 

Ваша переменная interfacePtr должна иметь тип: ICLRRuntimeHost, то ваш код должен декомпилировать так:

interfacePtr->GetCLRControl(&v23);