[ << ALL_FEED ]

Реверсим Delphi без IDR

Ещё в группе «Общее»

🛠 Реверсим Delphi без IDR

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

🕵️ Первый шаг при анализе Delphi — не забыть переключить параметр компилятора в Options → Compiler Options → Compiler, тогда IDA будет лучше обрабатывать вызовы функций.

Классы в Delphi создаются через функцию ClassCreate, которая получает на вход указатель на структуру класса и вызывает в нем функцию Tobject_NewInstance путем вычитания оффсета из указателя на VMT.

👀 Сама структура класса в Delphi выглядит следующим образом (пример на скриншоте 1):


struct DelphiClassInternal
{
  DWORD* vmt;
  DWORD* InterfaceTable; используется только для интерфейсов
  DWORD* PAutoTable; 
  DWORD* PInitTable;  
  DWORD* TypeInfo;
  DWORD* FieldTable;
  DWORD* MethodTable;
  DWORD* DynamicMethodTable;
}
Code language: plaintext (plaintext)


💼 Рассмотрим содержимое полей TypeInfo, MethodTable и FieldTable подробнее, поскольку в них больше всего полезной для анализа информации.

➡️ TypeInfo

В Delphi каждый тип объекта имеет свой идентификатор. Как видно на скриншоте 2, для нашего объекта выставлен идентификатор 7 — тип Class. В зависимости от этого типа, для объекта указывается соответствующий контекст. Для классов это информация о Property и указатель на родительский тип. Зная имя Property, нетрудно понять и разметить Get/Set-функции. Восстановление этих имен позволяет сильно упростить восприятие некоторых блоков кода. Пример на скриншоте 3.

➡️ MethodTable

Внимательный читатель заметит, что на скриншоте 1 присутствуют имена некоторых методов. Достать их можно, заглянув в таблицу опубликованных (Published) методов (текущего и родительского классов). Delphi не хранит информацию о других типах методов: приватных, защищенных и публичных. Помимо имени, там приводятся: возвращаемый тип, количество аргументов, их типы и имена.

Псевдоструктуру метода можно представить так (пример на скриншоте 4):


struct CMArg
{
  DWORD* TypeInfo;
  WORD   UNK;
  BYTE   NameLen;
  char   Name[];
  BYTE   UNK2[3];
}
struct ClassPubMethod
{
   WORD   EntrySize;
   DWORD* MethodPtr;
   BYTE   NameLen;
   char   Name[];
   WORD   W_UNK1;
   DWORD* ReturnType;
   WORD   W_UNK2;
   BYTE   ArgCount;
   CMArg  Args[];
}
Code language: plaintext (plaintext)


Из-за механизма наследования методов в Delphi восстановление даже части имен методов имеет большую пользу, если сделать это глобально, для всех классов. Затем это можно использовать среди прочего и для генерации структуры VMT класса с осмысленными именами. Пример — на скриншоте 5.

➡️ FieldTable

Заглянув в Class → FieldTable, можно найти большое количество информации о переменных (пример на скриншоте 6). Представлена она может быть в двух вариантах:

1. В виде имени, оффсета и номера типа переменной (из таблицы типов). Первые два байта в FieldTable — количество элементов в этой таблице, следующие четыре — указатель на таблицу типов.

2. В виде имени, оффсета и указателя на тип переменной (таблица начинается сразу после таблицы из п. 1).

Структура переменных имеет следующий вид:


struct VarTypeTable
{
  WORD   Count;
  DWORD* Entries[];
}
struct ClassVar
{
  DWORD* TypeInfo;
  WORD   VarOffset;
  WORD   UNK;
  BYTE   NameLen;
  char   Name[];
}
struct TableClassVar
{
  WORD VarOffet;
  WORD UNK;
  WORD TableTypeNum;
  BYTE NameLen;
  char Name[];
}
Code language: plaintext (plaintext)


Исходя из полученной информации о переменных можно составить структуру класса (нужно не забыть, что переменные также наследуются из родительских классов). Пример — на скриншоте 7.

🤔 Резюме: в Delphi присутствует большое количество RTTI-информации, за счет которой можно относительно просто разметить большое количество функций или восстановить структуру классов для упрощения статического анализа.


#TI #Delphi #Reverse
@ptescalator

Ещё от ti_author

Ещё от ti_author

Ещё в группе «Общее»