Wednesday, June 25, 2008

BitStruct is great

If you code in Ruby and do any binary parsing then you need to be using BitStruct. It makes C style structs in Ruby very easy. Sometimes you have to sniff a custom binary protocol the quick and dirty way, these are times I turn to Ruby instead of C. The Bitstruct release has some good examples of parsing network protocols but using raw sockets in Ruby is ugly. I prefer to use the LibPcap wrappers instead for the awesomeness of pcap filters.
require 'pcaplet'
require 'bit-struct'

# Fake protocol I made up for this example
class CustomProtocol < BitStruct
char :header, 64, :endian => :native
unsigned :length, 8, :endian => :native
unsigned :next_hdr, 16, :endian => :little
unsigned :next_tag, 16, :endian => :network
unsigned :type, 32, :endian => :native
rest :data

# Capture up to 1533 bytes
sniff ='-s 1533')

# Specific pcap filter so we only grab the protocol we are dissecting
pcap_filter ='tcp && port 34504 && src', sniff.capture)


for pkt in sniff
if pcap_filter =~ pkt
puts pkt
struct =
puts sprintf("ASCII Header: %s\tLength: %x\tNext Hdr: %x\tNext Tag: %x\tType: %x\tData: %s",
struct.header, struct.length, struct.next_hdr, struct.next_tag, struct.type,


Jon Oberheide said...

Neat! Looks similar in construct to its Python equivalent, dpkt:

Example of ARP module:

Eric Monti said...

I used a lot of bit-struct early. But I kept bumping my head against variable length fields.

I ended up moving to BinData for lots of things. It's much further along in this regard.

Anonymous said... is usefull too