Skip to content

Instantly share code, notes, and snippets.

@shinaisan
Created December 17, 2012 14:58
Show Gist options
  • Save shinaisan/4318875 to your computer and use it in GitHub Desktop.
Save shinaisan/4318875 to your computer and use it in GitHub Desktop.
A PE header reading sample using BinData Ruby gem.
require 'bindata'
require 'pp'
class ImageDosHeader < BinData::Record
endian :little
uint16 :e_magic, :check_value => 0x5A4D # MZ
uint16 :e_cblp
uint16 :e_cp
uint16 :e_crlc
uint16 :e_cparhdr
uint16 :e_minalloc
uint16 :e_maxalloc
uint16 :e_ss
uint16 :e_sp
uint16 :e_csum
uint16 :e_ip
uint16 :e_cs
uint16 :e_lfarlc
uint16 :e_ovno
array :_res, :type => :uint16, :initial_length => 4
uint16 :e_oemid
uint16 :e_oeminfo
array :e_res2, :type => :uint16, :initial_length => 10
uint32 :e_lfanew
end
class ImageFileHeader < BinData::Record
endian :little
uint16 :machine
uint16 :numberOfSections
uint32 :timeDateStamp
uint32 :pointerToSymbolTable
uint32 :numberOfSymbols
uint16 :sizeOfOptionalHeader
uint16 :characteristics
end
class ImageDataDirectory < BinData::Record
endian :little
uint32 :virtualAddress
uint32 :tableSize
end
class ImageOptionalHeader < BinData::Record
IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16
endian :little
uint16 :magic
uint8 :majorLinkerVersion
uint8 :minorLinkerVersion
uint32 :sizeOfCode
uint32 :sizeOfInitializedData
uint32 :sizeOfUninitializedData
uint32 :addressOfEntryPoint
uint32 :baseOfCode
uint32 :baseOfData
uint32 :imageBase
uint32 :sectionAlignment
uint32 :fileAlignment
uint16 :majorOperatingSystemVersion
uint16 :minorOperatingSystemVersion
uint16 :majorImageVersion
uint16 :minorImageVersion
uint16 :majorSubsystemVersion
uint16 :minorSubsystemVersion
uint32 :win32VersionValue
uint32 :sizeOfImage
uint32 :sizeOfHeaders
uint32 :checkSum
uint16 :subsystem
uint16 :dllCharacteristics
uint32 :sizeOfStackReserve
uint32 :sizeOfStackCommit
uint32 :sizeOfHeapReserve
uint32 :sizeOfHeapCommit
uint32 :loaderFlags
uint32 :numberOfRvaAndSizes
array :dataDirectory, :type => :image_data_directory, :initial_length => IMAGE_NUMBEROF_DIRECTORY_ENTRIES
end
class ImageNtHeaders < BinData::Record
endian :little
uint32 :signature, :check_value => 0x00004550 # PE
image_file_header :fileHeader
image_optional_header :optionalHeader
end
class ImageSectionHeader < BinData::Record
endian :little
IMAGE_SIZEOF_SHORT_NAME = 8
array :shortName, :type => :uint8, :initial_length => IMAGE_SIZEOF_SHORT_NAME
uint32 :virtualSize
uint32 :virtualAddress
uint32 :sizeOfRawData
uint32 :pointerToRawData
uint32 :pointerToRelocations
uint32 :pointerToLinenumbers
uint16 :numberOfRelocations
uint16 :numberOfLinenumbers
uint32 :characteristics
end
class PeFile < BinData::Record
endian :little
image_dos_header :dosHeader
array :dosStub, :type => :uint8, :initial_length => lambda{dosHeader.e_lfanew - dosStub.offset}
image_nt_headers :ntHeaders
array :sectionHeaders, :type => :image_section_header, :initial_length => lambda{ntHeaders.fileHeader.numberOfSections}
end
io = File.open("test.exe")
header = PeFile.read(io)
pp header
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment