Reverse engineering Delphi without IDR

More in General
- Operation Chewbacca
At the end of June, the PT ESC team, during incident investigations, discovered a new group…
- Ding, ding — who's there?
Ding, ding — who's there? 🔔 The cyber intelligence group of Positive Technologies' expert security center…
- Enterprise-grade validation system with schema support
Enterprise-grade validation system with schema support (c) The author of a dozen trojans who forgot to…
- One less feathered thief — plus one hundred rating points!
One less feathered thief — plus one hundred rating points! 😵 The Threat Intelligence team at…
- DragonDoll: a matryoshka in the world of Android spies
DragonDoll: a matryoshka in the world of Android spies 🪆 At the beginning of this spring,…
When you’re actively involved in reverse engineering, sooner or later you encounter an executable file written in Delphi. Analyzing objects in Delphi requires a special approach, and doing it manually is difficult. However, such analysis can be significantly accelerated with automation, if you know exactly how the object structure is organized.
🕵️ The first step when analyzing Delphi — don’t forget to toggle the compiler parameter in
Options → Compiler Options → Compiler, then IDA will handle function calls better.Classes in Delphi are created through the
ClassCreate function, which receives a pointer to the class structure as input and calls the Tobject_NewInstance function within it by subtracting an offset from the VMT pointer. 👀 The class structure in Delphi itself looks as follows (example in screenshot 1):
struct DelphiClassInternal
{
DWORD* vmt;
DWORD* InterfaceTable; used only for interfaces
DWORD* PAutoTable;
DWORD* PInitTable;
DWORD* TypeInfo;
DWORD* FieldTable;
DWORD* MethodTable;
DWORD* DynamicMethodTable;
}
Code language: plaintext (plaintext)💼 Let’s examine the contents of the
TypeInfo, MethodTable, and FieldTable fields in more detail, since they contain the most information useful for analysis.➡️ TypeInfo
In Delphi, every object type has its own identifier. As seen in screenshot 2, our object has identifier 7 — type
Class. Depending on this type, the corresponding context is specified for the object. For classes, this is information about Property and a pointer to the parent type. Knowing the Property name, it’s easy to understand and annotate the Get/Set functions. Recovering these names greatly simplifies the perception of certain code blocks. Example in screenshot 3.➡️ MethodTable
The attentive reader will notice that in screenshot 1 some method names are present. They can be extracted by looking into the table of published methods (of the current and parent classes). Delphi does not store information about other method types: private, protected, and public. Besides the name, it also provides: the return type, the number of arguments, their types and names.
The pseudo-structure of a method can be represented as follows (example in screenshot 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)Due to the method inheritance mechanism in Delphi, recovering even a portion of method names is highly beneficial if done globally, for all classes. This can then be used, among other things, to generate the class VMT structure with meaningful names. Example — in screenshot 5.
➡️ FieldTable
By looking into
Class → FieldTable, you can find a large amount of information about variables (example in screenshot 6). It can be presented in two variants: 1. As a name, offset, and variable type number (from the type table). The first two bytes in
FieldTable — the number of entries in this table, the next four — a pointer to the type table.2. As a name, offset, and pointer to the variable type (the table begins immediately after the table from item 1).
The variable structure has the following form:
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)Based on the obtained information about variables, a class structure can be composed (don’t forget that variables are also inherited from parent classes). Example — in screenshot 7.
🤔 Summary: Delphi contains a large amount of RTTI information, thanks to which it is relatively easy to annotate a large number of functions or recover class structures to simplify static analysis.






#TI #Delphi #Reverse
@ptescalator
More in General
- Operation Chewbacca
At the end of June, the PT ESC team, during incident investigations, discovered a new group…
- Ding, ding — who's there?
Ding, ding — who's there? 🔔 The cyber intelligence group of Positive Technologies' expert security center…
- Enterprise-grade validation system with schema support
Enterprise-grade validation system with schema support (c) The author of a dozen trojans who forgot to…
- One less feathered thief — plus one hundred rating points!
One less feathered thief — plus one hundred rating points! 😵 The Threat Intelligence team at…
- DragonDoll: a matryoshka in the world of Android spies
DragonDoll: a matryoshka in the world of Android spies 🪆 At the beginning of this spring,…



