libdestruct Skills
Parse binary data like C structs, instantly in Python
❌ Manually parsing and mapping binary data to typed structures is error-prone and tedious.
✅ Convert raw bytes into strongly-typed Python objects with automatic serialization and memory tracking.
- ✓Maps raw bytes to C-like types automatically
- ✓Read and write support with freeze/diff/reset snapshots
- ✓Handles structs, arrays, pointers, enums, bitfields
- ✓Memory offset tracking and hex dump inspection
👁 3 views · 📦 0 installs
Free to install — no account needed
Copy the command below and paste into your agent.
Instant access • No coding needed • No account needed
What you get in 5 minutes
- Full skill code ready to install
- Works with 4 AI agents
- Lifetime updates included
Run this helper
Answer a few questions and let this helper do the work.
▸Advanced: use with your AI agent
Description
# libdestruct Skills libdestruct is a Python library for destructuring binary data into typed objects. It maps raw bytes to C-like types (integers, floats, strings, structs, pointers, arrays, enums, bitfields) with read/write support. ## Installation ```bash pip install git+https://github.com/mrindeciso/libdestruct.git ``` ## Core Concepts All types inherit from `obj`. Every `obj` has: - `.value` property to read/write the underlying data - `.address` property for the memory offset - `.to_bytes()` to serialize back to bytes - `.freeze()` / `.diff()` / `.reset()` for snapshotting - `.hexdump()` for a hex dump of the object's bytes - `.from_bytes(data)` class method to create a read-only instance from raw bytes Memory is accessed through an `inflater`, which wraps a `bytes`, `bytearray`, or `mmap.mmap` buffer. Use `bytearray` or writable mmap for read/write access. For file-backed memory, use `inflater_from_file()`. ## Quick Reference ### Imports ```python from typing import Annotated from libdestruct import ( inflater, # memory wrapper (bytearray / mmap) inflater_from_file, # file-backed inflater (convenience) FileInflater, # file-backed inflater class struct, # struct base class c_int, c_uint, # 32-bit integers (signed/unsigned) c_long, c_ulong, # 64-bit integers (signed/unsigned) c_short, c_ushort, # 16-bit integers (signed/unsigned) c_char, c_uchar, # 8-bit integers (signed/unsigned) c_float, c_double, # IEEE 754 floats (32/64-bit) c_str, # null-terminated C string ptr, # 8-byte pointer ptr_to, # typed pointer field descriptor (legacy) ptr_to_self, # self-referential pointer field descriptor (legacy) array, array_of, # array type + field descriptor vla_of, # variable-length array field descriptor enum, enum_of, # enum type + field descriptor flags, flags_of, # bit flags type + field descriptor bitfield_of, # bitfield descriptor union, # union annotation type union_of, # plain union field descriptor tagged_union, # tagged union field descriptor offset, # explicit field offset size_of, # get size in bytes of any type/instance/field alignment_of, # get natural alignment of any type/instance ) ``` ### Type Sizes | Type | Size (bytes) | |---|---| | `c_int` / `c_uint` | 4 | | `c_long` / `c_ulong` | 8 | | `c_float` | 4 | | `c_double` | 8 | | `ptr` | 8 | | `c_str` | variable (reads until null) | ### Reading Primitives from a Buffer ```python memory = bytearray(b"\x2a\x00\x00\x00\x00\x00\x00\x00") lib = inflater(memory) x = lib.inflate(c_int, 0) # inflate c_int at offset 0 print(x.value) # 42 y = lib.inflate(c_long, 0) # inflate c_long at offset 0 print(y.value) ``` ### Reading Primitives from Raw Bytes ```python x = c_int.from_bytes(b"\x2a\x00\x00\x00") print(x.value) # 42 # Note: from_bytes returns a frozen (read-only) object ``` ### Writing Primitives ```python memory = bytearray(4) lib = inflater(memory) x = lib.inflate(c_int, 0) x.value = -1 print(memory) # bytearray(b'\xff\xff\xff\xff') ``` ### Defining Structs ```python class player_t(struct): health: c_int score: c_uint position_x: c_float position_y: c_float ``` Struct fields are laid out sequentially. Access members as attributes; each returns a typed `obj` (use `.value` to get the Python value). ### Inflating Structs ```python import struct as pystruct memory = bytearray(16) memory[0:4] = pystruct.pack("<i", 100) memory[4:8] = pystruct.pack("<I", 5000) memory[8:12] = pystruct.pack("<f", 1.5) memory[12:16] = pystruct.pack("<f", -3.0) lib = inflater(memory) player = lib.inflate(player_t, 0) print(player.health.value) # 100 print(player.score.value) # 5000 print(player.position_x.value) # 1.5 ``` Or from raw bytes (read-only): ```python player = player_t.from_bytes(memory) ``` ### Pointers ```python class node_t(struct): value: c_int next: ptr["node_t"] # pointer to own type (forward ref) # Typed pointer to another type: class container_t(struct): data: c_int ref: ptr[c_long] # subscript syntax (preferred) ``` Legacy syntax with `ptr_to()` and `ptr_to_self()` is still supported: ```python class node_t(struct): value: c_int next: ptr = ptr_to_self() class container_t(struct): data: c_int ref: ptr = ptr_to(c_long) ``` Dereference with `.unwrap()` or safe `.try_unwrap()` (returns `None` if invalid): ```python node = lib.inflate(node_t, 0) print(node.value.value) next_node = node.next.unwrap() # follow pointer maybe_node = node.next.try_unwrap() # None if invalid ``` Pointer arithmetic (C-style, scaled by element size): ```python p = lib.inflate(ptr, 0) p.wrapper = c_int print(p[0].value) # element at index 0 print(p[1].value) # element at index 1 print((p + 2).unwrap().value) # element at index 2 ``` Pointer results are cached; call `.invalidate()` after memory changes. ### Forward References For mutually referential structs, use `ptr["TypeName"]`: ```python class tree_t(struct): value: c_int left: ptr["tree_t"] right: ptr["tree_t"] ``` ### Arrays ```python class packet_t(struct): length: c_int data: array[c_int, 8] # subscript syntax (preferred) ``` Legacy syntax with `array_of()` is still supported: ```python class packet_t(struct): length: c_int data: array = array_of(c_int, 8) ``` Access array elements: ```python pkt = lib.inflate(packet_t, 0) print(pkt.data[0].value) # first element print(pkt.data.count()) # 8 for element in pkt.data: print(element.value) ``` ### Variable-Length Arrays VLAs model C flexible array members: the count is read from a sibling field at inflation time. ```python class packet_t(struct): length: c_int data: array[c_int, "length"] # subscript syntax (string = VLA) ``` Or with the descriptor: ```python class packet_t(struct): length: c_int data: array = vla_of(c_int, "length") ``` ```python pkt = lib.inflate(packet_t, 0) print(len(pkt.data)) # reads from pkt.length.value print(pkt.data[0].value) # first element ``` Size semantics: `size_of(packet_t)` returns the fixed part only (excludes VLA). `size_of(instance)` includes VLA data. VLA must be the last field in the struct. VLA elements can be structs. ### Enums ```python from enum import IntEnum class Color(IntEnum): RED = 0 GREEN = 1 BLUE = 2 class pixel_t(struct): color: enum[Color] # subscript syntax (preferred, defaults to c_int backing) alpha: c_int # With a custom backing type: class pixel_t(struct): color: enum[Color, c_short] # 2-byte backing type alpha: c_int ``` Legacy syntax with `enum_of()` is still supported: ```python class pixel_t(struct): color: enum = enum_of(Color) alpha: c_int ``` ```python pixel = lib.inflate(pixel_t, 0) print(pixel.color.value) # Color.RED ``` ### Bit Flags Use Python's `IntFlag` for bitmask fields: ```python from enum import IntFlag class Perms(IntFlag): READ = 1 WRITE = 2 EXEC = 4 class file_t(struct): mode: flags[Perms] # subscript syntax (defaults to c_int backing) size: c_int # With a custom backing type: class file_t(struct): mode: flags[Perms, c_short] # 2-byte backing size: c_int ``` Legacy syntax with `flags_of()`: ```python class file_t(struct): mode: flags = flags_of(Perms) size: c_int ``` ```python f = lib.inflate(file_t, 0) print(f.mode.value) # Perms.READ|Perms.WRITE print(Perms.READ in f.mode.value) # True ``` By default flags are lenient (unknown bits produce raw int). Use `flags_of(Perms, lenient=False)` for strict mode that raises `ValueError` on unknown bits. ### Bitfields ```python class flags_t(struct): read: c_int = bitfield_of(c_int, 1) write: c_int = bitfield_of(c_int, 1) execute: c_int = bitfield_of(c_int, 1) reserved: c_int = bitfield_of(c_int, 29) ``` Consecutive bitfields with the same backing type are packed together. The struct above is 4 bytes total, not 16. ### Unions ```python from libdestruct.common.union import union, union_of, tagged_union # Plain union — all variants overlaid at the same offset class packet_t(struct): data: union = union_of({"i": c_int, "f": c_float, "l": c_long}) pkt = lib.inflate(packet_t, 0) pkt.data.i.value # interpret as int pkt.data.f.value # interpret as float (same bytes) # Tagged union — discriminator selects the active variant class message_t(struct): type: c_int payload: union = tagged_union("type", { 0: c_int, 1: c_float, 2: point_t, # struct variants work too }) ``` The discriminator field must appear before the union. The union size is the max of all variant sizes. Struct variant fields are accessible directly: `msg.payload.x.value`. Use `.variant` to get the raw variant object. Unknown discriminator values raise `ValueError`. ### Struct Alignment ```python # Default: packed (no padding) class packed_t(struct): a: c_char b: c_int # size: 5 # Aligned: natural C alignment with padding class aligned_t(struct): _aligned_ = True a: c_char b: c_int # size: 8 (1 + 3 padding + 4) alignment_of(c_int) # 4 alignment_of(aligned_t) # 4 (max member alignment) # Custom alignment width class wide_t(struct): _aligned_ = 16 a: c_int # size: 16, alignment: 16 ``` ### Explicit Field Offsets ```python from typing import Annotated class sparse_t(struct): a: c_int b: Annotated[c_int, offset(0x10)] # Annotated syntax (preferred) ``` This works with any type, including subscript types: ```python class example_t(struct): a: c_int data: Annotated[array[c_int, 4], offset(0x10)] ref: Annotated[ptr[c_int], offset(0x20)] ``` Legacy syntax with default values is still supported: ```python class sparse_t(struct): a: c_int b: c_int = offset(0x10) ``` ### Nested Structs ```python class vec2(struct): x: c_float y: c_float class entity_t(struct): id: c_int pos: vec2 ``` ```python e = lib.inflate(entity_t, 0) print(e.pos.x.value) ``` ### Struct Inheritance Structs support Python class inheritance. Derived structs include all parent fields first, then their own. ```python class base_t(struct): a: c_int class derived_t(base_t): b: c_int ``` ```python d = derived_t.from_bytes(pystruct.pack("<ii", 10, 20)) print(d.a.value) # 10 print(d.b.value) # 20 size_of(derived_t) # 8 ``` Multi-level inheritance (A -> B -> C) and alignment inheritance both work. Parent fields always appear first in layout and `to_dict()`. ### size_of ```python size_of(c_int) # 4 size_of(c_long) # 8 size_of(player_t) # computed from fields size_of(array_of(c_int, 10)) # 40 size_of(some_instance) # works on instances too ``` ### Hex Dump ```python player = lib.inflate(player_t, 0) print(player.hexdump()) # 00000000 64 00 00 00 88 13 00 00 00 00 c0 3f 00 00 40 c0 |d..........?..@.| health, score, position_x, position_y ``` Struct hexdumps annotate lines with field names. Primitive hexdumps show raw bytes. ### Dict / JSON Export ```python point = point_t.from_bytes(memory) point.to_dict() # {"x": 10, "y": 20} import json json.dumps(entity.to_dict()) # nested structs produce nested dicts ``` `to_dict()` works on all types: primitives return their value, structs return `{name: value}` dicts, arrays return lists, unions return variant values, enums return their int value. ### Freeze / Diff / Reset ```python x = lib.inflate(c_int, 0) x.freeze() # snapshot current value x.value = 99 # raises ValueError (frozen) # For non-frozen objects: x.freeze() # save state # ... memory changes externally ... print(x.diff()) # (old_value, new_value) x.reset() # restore to frozen value x.update() # update frozen value to current ``` ### C Struct Parser Parse C struct definitions directly (requires `pycparser`): ```python from libdestruct.c.struct_parser import definition_to_type player_t = definition_to_type(""" struct player_t { int health; unsigned int score; float x; double y; }; """) player = player_t.from_bytes(data) ``` Supports: nested structs, pointers (including self-referential), arrays, bitfields, typedefs, `#include` directives (requires a C preprocessor), and `__attribute__` stripping. ## Common Patterns ### Parsing a binary format ```python class header_t(struct): magic: c_uint version: c_int num_entries: c_int entries_ptr: ptr[entry_t] with open("file.bin", "rb") as f: data = bytearray(f.read()) lib = inflater(data) header = lib.inflate(header_t, 0) for i in range(header.num_entries.value): entry = header.entries_ptr[i] # process entry... ``` ### Modifying binary data in-place ```python data = bytearray(open("save.bin", "rb").read()) lib = inflater(data) player = lib.inflate(player_t, 0x100) player.health.value = 999 open("save.bin", "wb").write(data) ``` ### File-backed inflater Read (and optionally write) binary files directly via mmap, without loading the entire file into memory: ```python # Read-only with inflater_from_file("firmware.bin") as lib: header = lib.inflate(header_t, 0) print(header.magic.value) # Writable — changes are persisted to the file with inflater_from_file("save.bin", writable=True) as lib: player = lib.inflate(player_t, 0x100) player.health.value = 999 ``` You can also pass an `mmap.mmap` object directly to `inflater()`. ### Working with libdebug libdestruct integrates with [libdebug](https://github.com/libdebug/libdebug) for live process memory inspection. The debugger's memory view can be passed directly to `inflater`.
Security Status
Verified
Manually verified by security team
Related AI Tools
More Career Boost tools you might like
ru-text — Russian Text Quality
FreeApplies professional Russian typography, grammar, and style rules to improve text quality across content types
/forge:工作流总入口
Free'Forge 工作流总入口。检查项目状态,推荐下一步该用哪个 skill。任何时候不知道下一步该干什么,就用 /forge。触发方式:用户说"forge"、"下一步"、"接下来做什么"、"继续"(在没有明确上下文时)。'
TypeScript React & Next.js Production Patterns
FreeProduction-grade TypeScript reference for React & Next.js covering type safety, component patterns, API validation, state management, and debugging
Charles Proxy Session Extractor
FreeExtracts HTTP/HTTPS request and response data from Charles Proxy session files (.chlsj format), including URLs, methods, status codes, headers, request bodies, and response bodies. Use when analyzing captured network traffic from Charles Proxy debug
Java Backend Interview Simulator
FreeSimulates realistic Java backend technical interviews with customizable interviewer styles and candidate levels for Chinese tech companies
AI News & Trends Intelligence
FreeFetches latest AI/ML news, trending open-source projects, and social media discussions from 75+ curated sources for comprehensive AI briefings