Reverse Engineering Made Easy: Operand Offset Structs in IDA

2024-04-05

1. Motivations

Struct, short for structure, is an important concept in many programming languages. A struct can contain different variables, each of which can be a different data type. Struct allows programmers to group many fields into a structured group for easier processing, storage, and access. Therefore, structs are used in almost all applications.

Below is an example of a struct defined in C:

struct Student {
    char *name;
    int age;
    float height;
};

Unfortunately, compilers will discard the struct definitions, and you will only see the offsets being used (added to a base address) instead of field names when disassembling a compiled program. The example below is a compiled snippet that assigns values to the fields name, age, and height of struct Student. Pay close attention to the register eax, which is used as a base address, and the offsets values added to eax:

example_struct_student_compiled

The readability of the disassembled code above is low since you have to make sense of the offsets each time you read it.

Luckily, we can transform the code to something similar to the code below using operand offset structs in IDA:

readability_improved_struct_student

To make it even more interesting, I will analyze the shellcode presented in my previous blog (A Simple Windows Shellcode) to showcase the power of operand offset structs. Let’s go!

2. Actions

What is our goal? - We want to turn the assembly code below into something easy to read and understand. (This is a portion of the shellcode from A Simple Windows Shellcode, loaded to IDA)

before_operand_offset_struct

This section presents the steps to label the offsets in the shellcode.

The first step to label the offsets is obtaining the information about the structs being used. You can create structs by referencing documents from Windows. However, IDA comes with some useful type libraries, which are a great time saver.

To add a type information library in IDA, follow: View --> Open subviews --> Type libraries (Shift + F11), and then press the key INS on your keyboard to load type libraries. Choose the type library you need from the Available Type Libraries window. mssdk_win10 is the type library you need to analyze the shellcode:

load_type_libraries

2.2 Adding Structures

A type library contains many structure definitions, but IDA will not automatically import all the structures after you add a type library. You will need to add the specific structures you want to use manually.

To add a standard struct: View --> Open subviews --> Structure (Shift + F9). Then press the key INS on your keyboard, and choose Add standard structure

add_standard_structure

A window will pop up and allow you to choose the structs you want to add:

choose_standard_structure_to_add

You will need to add the following structs to label the offsets in the shellcode:

  • PEB
  • PEB_LDR_DATA
  • IMAGE_DOS_HEADERS
  • IMAGE_NT_HEADERS32

2.3 Applying Operand Offset Structs

This is the most exciting part. Once you added the struct definition into IDA, you can use them to label the offset structs.

Click or move the text cursor to the offset you want to label, and: Edit --> Operand type --> Offset --> Offset (struct)... T

A small window will pop up and allow you to Choose a structure offset:

applying_the_first_operand_type_offset_struct

In the example above, the offset 0x0C corresponds to different fields in a couple of structs (There could be more if you added more structs). It is important to have knowledge about which struct to use. If you read the blog about the shellcode, you will understand why I chose PEB.Ldr. If you still have questions, It’s a good idea to revisit the blog for clarification (Here).

Take a look at how nice the label is: result_the_first_operand_type_offset_struct

You can now repeat the steps above to label all the other offsets in the shellcode. The result will look something like the picture below: after_operand_offset_struct

Congratulations! The shellcode is now much easier to read and understand thanks to the labelled fields. This improvement will also save your brainpower, allowing you to focus on the bigger picture when reverse engineering.

3. Homework

I know homework sucks, and you are not even my student. But look at the Student struct I mentioned at the beginning of this blog. I don’t just name it Student for nothing!

All jokes aside, you can compile a small C/C++ program that uses the struct Student and add the struct’s definition into IDA to label the offset structs to get a result similar to what I showed in the first section of this blog.

I hope you enjoyed reading this blog as much as I enjoyed writing it!