IDA: Structures Tutorial

You can use IDA to interactively define and manipulate structures in the disassembly.

Sample program

Consider this simple sample C program:

#include <stdio.h>

struct client {
  char code;
  long id;
  char name[32];
  client *next;
};

void print_clients(client *ptr) {
  while ( ptr != NULL ) {
    printf("ID: %4ld Name: %-32s\n",ptr->id,ptr->name);
    ptr = ptr->next;
  }
}
          

Standard disassembly

Here is the disassembly with no structures defined, as IDA automatically generates it:

@print_clients$qp6client proc near

ptr		= word ptr  4

		push	bp
		mov	bp, sp
		push	si
		mov	si, [bp+ptr]
		jmp	short loc_1_32

loc_1_19:				; CODE XREF: print_clients(client *)+24j
		mov	ax, si
		add	ax, 5
		push	ax
		push	word ptr [si+3]
		push	word ptr [si+1]
		mov	ax, offset aId4ldName32s
		push	ax
		call	_printf
		add	sp, 8
		mov	si, [si+25h]

loc_1_32:				; CODE XREF: print_clients(client *)+7j
		or	si, si
		jnz	loc_1_19
		pop	si
		pop	bp
		retn	
@print_clients$qp6client endp
        

Defining structures

In order to use meaningful names instead of numbers, we open the structure window and press insert to define a new strcture type. Structure members are added with the D key for data and the A key for ASCII strings. As we add new structure members, IDA automatically names them. You can change any member's name by pressing N.

client_t	struc
code		db ?
id		dd ?
name		db 32 dup(?)
next		dw ?
client_t	ends
        

Improved disassembly

Finally, the defined structure type can be used to specify the type of an instruction operand. (menu Edit|Operand types|Struct offset).

@print_clients$qp6client proc near

ptr		= word ptr  4

		push	bp
		mov	bp, sp
		push	si
		mov	si, [bp+ptr]
		jmp	short loc_1_32

loc_1_19:				; CODE XREF: print_clients(client *)+24j
		mov	ax, si
		add	ax, client_t.name
		push	ax
		push	word ptr [si+client_t.id+2]
		push	word ptr [si+client_t.id]
		mov	ax, offset aId4ldName32s
		push	ax
		call	_printf
		add	sp, 8
		mov	si, [si+client_t.next]

loc_1_32:				; CODE XREF: print_clients(client *)+7j
		or	si, si
		jnz	loc_1_19
		pop	si
		pop	bp
		retn	
@print_clients$qp6client endp