Documentation Index
Fetch the complete documentation index at: https://mintlify.com/fortra/impacket/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The Structure class provides a powerful framework for parsing and packing binary data structures in network protocols. It’s used extensively throughout Impacket for defining packet formats, protocol structures, and binary data layouts.
Basic Usage
from impacket.structure import Structure
class MyPacket(Structure):
structure = (
('Version', '<L=0'), # Little-endian unsigned long, default 0
('Length', '<H=0'), # Little-endian unsigned short
('Data', ':'), # Variable-length data
)
# Parse binary data
packet = MyPacket(data=binary_data)
print(f"Version: {packet['Version']}")
print(f"Length: {packet['Length']}")
# Create and pack
packet = MyPacket()
packet['Version'] = 1
packet['Length'] = 100
packet['Data'] = b'Hello World'
binary_output = packet.getData()
Based on Python’s struct module:
'<L' # Little-endian unsigned long (4 bytes)
'<H' # Little-endian unsigned short (2 bytes)
'<Q' # Little-endian unsigned long long (8 bytes)
'<l' # Little-endian signed long
'<h' # Little-endian signed short
'B' # Unsigned byte
'b' # Signed byte
'16s' # 16-byte string
Byte Order
< - Little-endian
> - Big-endian
! - Network byte order (big-endian)
= - Native byte order
@ - Native byte order with native alignment
Variable Length Data
':' # Copy bytes as-is (for Structure objects or raw bytes)
'z' # Null-terminated string (asciiz)
'u' # UTF-16LE string with double-null terminator
Length Specifiers
# Field length based on another field
('DataLen', '<L=0'),
('_Data', '_-Data', 'self["DataLen"]'), # Virtual field for length
('Data', ':'),
Arrays
# Fixed size array
('Items', '10*<L'), # Array of 10 unsigned longs
# Variable size array (count in another field)
('Count', '<L=0'),
('Items', '<L*<H'), # First <L is count field, <H is item format
Conditional Fields
# Address field - field only exists if address field is non-zero
('HasData', '<L=0'),
('Data', '?&HasData', 'self["HasData"]'), # Only parsed if HasData != 0
Literals
('Magic', '"\\xef\\xcd\\xab\\x89'), # Literal bytes that must match
Structure Definition
Basic Structure
class NetworkPacket(Structure):
structure = (
('Magic', '<L=0x12345678'),
('Version', '<H=1'),
('Type', '<H=0'),
('Length', '<L=0'),
('_Payload', '_-Payload', 'self["Length"]'),
('Payload', ':'),
)
Nested Structures
class Header(Structure):
structure = (
('Version', '<L=0'),
('Flags', '<L=0'),
)
class Packet(Structure):
structure = (
('Header', ':', Header), # Nested structure
('DataLen', '<L=0'),
('_Data', '_-Data', 'self["DataLen"]'),
('Data', ':'),
)
# Usage
packet = Packet(binary_data)
print(f"Version: {packet['Header']['Version']}")
Dynamic Structures
class DynamicPacket(Structure):
def __init__(self, data=None, packet_type=0):
if packet_type == 1:
self.structure = (
('Type', '<H=1'),
('Value', '<L=0'),
)
else:
self.structure = (
('Type', '<H=0'),
('Value', '<Q=0'),
)
Structure.__init__(self, data)
Methods
fromString(data)
Parse binary data into the structure.
packet = MyPacket()
packet.fromString(binary_data)
# Or use constructor
packet = MyPacket(data=binary_data)
getData()
Serialize the structure to binary data.
packet = MyPacket()
packet['Field1'] = 100
packet['Field2'] = b'data'
binary_data = packet.getData()
dump()
Print structure contents for debugging.
packet.dump()
# Output:
# MyPacket
# Field1: 100
# Field2: b'data'
Field Access
# Dictionary-style access
packet['FieldName'] = value
value = packet['FieldName']
# Check if field exists
if 'FieldName' in packet.fields:
print(packet['FieldName'])
# Delete field
del packet['FieldName']
Alignment
class AlignedPacket(Structure):
def __init__(self, data=None):
Structure.__init__(self, data, alignment=4) # 4-byte alignment
# Fields will be padded to 4-byte boundaries
Advanced Examples
class SMBHeader(Structure):
structure = (
('Protocol', '"\\xffSMB'), # Literal magic bytes
('Command', 'B=0'),
('ErrorClass', 'B=0'),
('Reserved', 'B=0'),
('ErrorCode', '<H=0'),
('Flags', 'B=0'),
('Flags2', '<H=0'),
('PIDHigh', '<H=0'),
('SecurityFeatures', '8s=""'),
('Reserved2', '<H=0'),
('TID', '<H=0xffff'),
('PID', '<H=0'),
('UID', '<H=0'),
('MID', '<H=0'),
)
Variable Length Array
class ArrayPacket(Structure):
structure = (
('Count', '<L=0'),
('Items', '<L*<H'), # Array of <H, count in Count field
)
# Create
packet = ArrayPacket()
packet['Count'] = 3
packet['Items'] = [100, 200, 300]
data = packet.getData()
# Parse
packet = ArrayPacket(data=data)
print(packet['Items']) # [100, 200, 300]
Conditional Fields
class ConditionalPacket(Structure):
structure = (
('Flags', '<L=0'),
('_OptionalData', '_-OptionalData', '20 if self["Flags"] & 0x01 else 0'),
('OptionalData', ':'),
)
String Handling
class StringPacket(Structure):
structure = (
('NameLen', '<H=0'),
('_Name', '_-Name', 'self["NameLen"]'),
('Name', ':'), # Raw bytes
('NullTermStr', 'z'), # Null-terminated
('UnicodeStr', 'u'), # UTF-16LE with double-null
)
packet = StringPacket()
packet['NameLen'] = 5
packet['Name'] = b'Hello'
packet['NullTermStr'] = b'World'
packet['UnicodeStr'] = 'Test'.encode('utf-16le')
Encoding Configuration
class MyStructure(Structure):
ENCODING = 'utf-8' # Default is 'latin-1'
structure = (
('Data', ':'),
)
Utility Functions
hexdump()
Display binary data in hexadecimal format.
from impacket.structure import hexdump
hexdump(packet.getData())
# Output:
# 0000 12 34 56 78 01 00 02 00 48 65 6C 6C 6F .4Vx....Hello
Common Patterns
TLV (Type-Length-Value)
class TLVRecord(Structure):
structure = (
('Type', '<H=0'),
('Length', '<H=0'),
('_Value', '_-Value', 'self["Length"]'),
('Value', ':'),
)
Size Prefix
class SizedData(Structure):
structure = (
('Size', '<L=0'),
('_Data', '_-Data', 'self["Size"]'),
('Data', ':'),
)
Magic Number Validation
class ValidatedPacket(Structure):
structure = (
('Magic', '"PACK'), # Must be exactly b'PACK'
('Version', '<L=0'),
)
try:
packet = ValidatedPacket(data=binary_data)
except Exception as e:
print("Invalid packet magic")
Best Practices
- Use virtual fields (
_-FieldName) for length calculations
- Set defaults for fields that have common values
- Use alignment for structures that require padding
- Document structures with comments
- Validate critical fields in
__init__
- Use nested structures for complex protocols
- Test both directions (packing and unpacking)
See Also
- Python struct module - Base format specifiers
- SMB, LDAP, and other Impacket protocol implementations for real-world examples