IDA Pro structs for networking protocols: IP, TCP, UDP, ARP

I’ve recently analyzed a malware sample that parsed and modified raw network packet data. That means I had to deal with many register relative offsets in IDA Pro. The most practical way for this is to define and apply structs.

Defined and applied struct for TCP data packet
Defined and applied struct for TCP data packet

While IDA’s type libraries contain some of the packet structures (i.e., ETHERNET_FRAME, IP, TCP, and UDP_HEADER), other protocols (i.e., ARP) are missing. Additionally, I did not find structures encompassing multiple communication layers – for example ETHERNET_FRAME, IP, and TCP grouped in one structure.

Inspired by https://hiddencodes.wordpress.com/2011/10/03/ida-pro-idc-scripts-for-reversing-network-software-binary/ I’ve created an IDAPython script snippit to create structs for packets of the following networking protocols:

  • Internet Protocol (IP)
  • Transmission Control Protocol (TCP)
  • User Datagram Protocol (UDP)
  • Address Resolution Protocol (ARP)

Where available, the definitions rely on already existing structures from IDA’s type library information.

"""
IDAPython script to create structs in IDA Pro for networking protocols: IP, TCP, UDP, ARP.
"""
import idc


# load type library information
sid_ethernet_frame = idc.Til2Idb(-1, "ETHERNET_FRAME")
sid_ip = idc.Til2Idb(-1, "IP")
sid_tcp = idc.Til2Idb(-1, "TCP")
sid_udp = idc.Til2Idb(-1, "UDP_HEADER")

# IP
sid_ip_packet = idc.AddStrucEx(-1, "IP_PACKET", 0)
idc.AddStrucMember(sid_ip_packet, "EthernetFrame", -1, idc.FF_STRU, sid_ethernet_frame, idc.GetStrucSize(sid_ethernet_frame), -1, 0, idc.REF_OFF32)
idc.AddStrucMember(sid_ip_packet, "IP_", -1, idc.FF_STRU, sid_ip, idc.GetStrucSize(sid_ip))

# TCP
sid_tcp_packet = idc.AddStrucEx(-1, "TCP_PACKET", 0)
idc.AddStrucMember(sid_tcp_packet, "EthernetFrame", -1, idc.FF_STRU, sid_ethernet_frame, idc.GetStrucSize(sid_ethernet_frame))
idc.AddStrucMember(sid_tcp_packet, "IP_", -1, idc.FF_STRU, sid_ip, idc.GetStrucSize(sid_ip))
idc.AddStrucMember(sid_tcp_packet, "TCP", -1, idc.FF_STRU, sid_tcp, idc.GetStrucSize(sid_tcp))

# UDP
sid_udp_packet = idc.AddStrucEx(-1, "UDP_PACKET", 0)
idc.AddStrucMember(sid_udp_packet, "EthernetFrame", -1, idc.FF_STRU, sid_ethernet_frame, idc.GetStrucSize(sid_ethernet_frame))
idc.AddStrucMember(sid_udp_packet, "IP_", -1, idc.FF_STRU, sid_ip, idc.GetStrucSize(sid_ip))
idc.AddStrucMember(sid_udp_packet, "UDP_HEADER", -1, idc.FF_STRU, sid_udp, idc.GetStrucSize(sid_udp))

# ARP
sid_arp_packet = idc.AddStrucEx(-1, "ARP_PACKET", 0)
idc.AddStrucMember(sid_arp_packet, "EthernetFrame", -1, idc.FF_STRU, sid_ethernet_frame, idc.GetStrucSize(sid_ethernet_frame))
idc.AddStrucMember(sid_arp_packet, "HardwareType", -1, idc.FF_WORD, -1, 2)
idc.AddStrucMember(sid_arp_packet, "ProtocolType", -1, idc.FF_WORD, -1, 2)
idc.AddStrucMember(sid_arp_packet, "HardwareAddrLen", -1, idc.FF_BYTE, -1, 1)
idc.AddStrucMember(sid_arp_packet, "ProtocolAddrLen", -1, idc.FF_BYTE, -1, 1)
idc.AddStrucMember(sid_arp_packet, "Operation", -1, idc.FF_WORD, -1, 2)
idc.AddStrucMember(sid_arp_packet, "SenderHwAddress", -1, idc.FF_BYTE, -1, 6)
idc.AddStrucMember(sid_arp_packet, "SenderProtocolAddress", -1, idc.FF_BYTE, -1, 4)
idc.AddStrucMember(sid_arp_packet, "TargetHwAddress", -1, idc.FF_BYTE, -1, 6)
idc.AddStrucMember(sid_arp_packet, "TargetProtocolAddress", -1, idc.FF_BYTE, -1, 4)

The IDAPython script does not contain any error handling, so make sure to check IDA Pro’s output window for potential warning messages.

Leave a Reply

Your email address will not be published.