summaryrefslogtreecommitdiff
path: root/python/examples
diff options
context:
space:
mode:
authorAndrew Lamoureux <andrew@vector35.com>2019-03-16 01:16:06 -0400
committerRusty Wagner <rusty@vector35.com>2019-03-20 13:00:17 -0400
commit36650362e2723036605ae336a40b4064ffd1b0fb (patch)
tree7a050902e1f8abcd1987081ed303891934f156db /python/examples
parent8ab595cfbf92b80d4ef81913d0c82621db114702 (diff)
kaitai UI plugin + elf,macho,pe
Diffstat (limited to 'python/examples')
-rw-r--r--python/examples/kaitai/__init__.py1
-rw-r--r--python/examples/kaitai/elf.py1685
-rw-r--r--python/examples/kaitai/kaitaistruct.py379
-rwxr-xr-xpython/examples/kaitai/kshelpers.py450
-rw-r--r--python/examples/kaitai/mach_o.py2739
-rw-r--r--python/examples/kaitai/microsoft_pe.py758
-rw-r--r--python/examples/kaitai/view.py220
7 files changed, 6232 insertions, 0 deletions
diff --git a/python/examples/kaitai/__init__.py b/python/examples/kaitai/__init__.py
new file mode 100644
index 00000000..90cdbd77
--- /dev/null
+++ b/python/examples/kaitai/__init__.py
@@ -0,0 +1 @@
+from . import view
diff --git a/python/examples/kaitai/elf.py b/python/examples/kaitai/elf.py
new file mode 100644
index 00000000..b06956c4
--- /dev/null
+++ b/python/examples/kaitai/elf.py
@@ -0,0 +1,1685 @@
+# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
+
+from pkg_resources import parse_version
+from kaitaistruct import __version__ as ks_version, KaitaiStruct, KaitaiStream, BytesIO
+from enum import Enum
+import collections
+
+
+if parse_version(ks_version) < parse_version('0.7'):
+ raise Exception("Incompatible Kaitai Struct Python API: 0.7 or later is required, but you have %s" % (ks_version))
+
+class Elf(KaitaiStruct):
+ """
+ .. seealso::
+ Source - https://sourceware.org/git/?p=glibc.git;a=blob;f=elf/elf.h;hb=HEAD
+ """
+
+ class Endian(Enum):
+ le = 1
+ be = 2
+
+ class ShType(Enum):
+ null_type = 0
+ progbits = 1
+ symtab = 2
+ strtab = 3
+ rela = 4
+ hash = 5
+ dynamic = 6
+ note = 7
+ nobits = 8
+ rel = 9
+ shlib = 10
+ dynsym = 11
+ init_array = 14
+ fini_array = 15
+ preinit_array = 16
+ group = 17
+ symtab_shndx = 18
+ sunw_capchain = 1879048175
+ sunw_capinfo = 1879048176
+ sunw_symsort = 1879048177
+ sunw_tlssort = 1879048178
+ sunw_ldynsym = 1879048179
+ sunw_dof = 1879048180
+ sunw_cap = 1879048181
+ sunw_signature = 1879048182
+ sunw_annotate = 1879048183
+ sunw_debugstr = 1879048184
+ sunw_debug = 1879048185
+ sunw_move = 1879048186
+ sunw_comdat = 1879048187
+ sunw_syminfo = 1879048188
+ sunw_verdef = 1879048189
+ sunw_verneed = 1879048190
+ sunw_versym = 1879048191
+ sparc_gotdata = 1879048192
+ arm_exidx = 1879048193
+ arm_preemptmap = 1879048194
+ arm_attributes = 1879048195
+
+ class OsAbi(Enum):
+ system_v = 0
+ hp_ux = 1
+ netbsd = 2
+ gnu = 3
+ solaris = 6
+ aix = 7
+ irix = 8
+ freebsd = 9
+ tru64 = 10
+ modesto = 11
+ openbsd = 12
+ openvms = 13
+ nsk = 14
+ aros = 15
+ fenixos = 16
+ cloudabi = 17
+ openvos = 18
+
+ class Machine(Enum):
+ not_set = 0
+ sparc = 2
+ x86 = 3
+ mips = 8
+ powerpc = 20
+ arm = 40
+ superh = 42
+ ia_64 = 50
+ x86_64 = 62
+ aarch64 = 183
+ riscv = 243
+ bpf = 247
+
+ class DynamicArrayTags(Enum):
+ null = 0
+ needed = 1
+ pltrelsz = 2
+ pltgot = 3
+ hash = 4
+ strtab = 5
+ symtab = 6
+ rela = 7
+ relasz = 8
+ relaent = 9
+ strsz = 10
+ syment = 11
+ init = 12
+ fini = 13
+ soname = 14
+ rpath = 15
+ symbolic = 16
+ rel = 17
+ relsz = 18
+ relent = 19
+ pltrel = 20
+ debug = 21
+ textrel = 22
+ jmprel = 23
+ bind_now = 24
+ init_array = 25
+ fini_array = 26
+ init_arraysz = 27
+ fini_arraysz = 28
+ runpath = 29
+ flags = 30
+ preinit_array = 32
+ preinit_arraysz = 33
+ maxpostags = 34
+ sunw_auxiliary = 1610612749
+ sunw_filter = 1610612750
+ sunw_cap = 1610612752
+ sunw_symtab = 1610612753
+ sunw_symsz = 1610612754
+ sunw_sortent = 1610612755
+ sunw_symsort = 1610612756
+ sunw_symsortsz = 1610612757
+ sunw_tlssort = 1610612758
+ sunw_tlssortsz = 1610612759
+ sunw_capinfo = 1610612760
+ sunw_strpad = 1610612761
+ sunw_capchain = 1610612762
+ sunw_ldmach = 1610612763
+ sunw_capchainent = 1610612765
+ sunw_capchainsz = 1610612767
+ hios = 1879044096
+ valrnglo = 1879047424
+ gnu_prelinked = 1879047669
+ gnu_conflictsz = 1879047670
+ gnu_liblistsz = 1879047671
+ checksum = 1879047672
+ pltpadsz = 1879047673
+ moveent = 1879047674
+ movesz = 1879047675
+ feature_1 = 1879047676
+ posflag_1 = 1879047677
+ syminsz = 1879047678
+ valrnghi = 1879047679
+ addrrnglo = 1879047680
+ gnu_hash = 1879047925
+ tlsdesc_plt = 1879047926
+ tlsdesc_got = 1879047927
+ gnu_conflict = 1879047928
+ gnu_liblist = 1879047929
+ config = 1879047930
+ depaudit = 1879047931
+ audit = 1879047932
+ pltpad = 1879047933
+ movetab = 1879047934
+ addrrnghi = 1879047935
+ versym = 1879048176
+ relacount = 1879048185
+ relcount = 1879048186
+ flags_1 = 1879048187
+ verdef = 1879048188
+ verdefnum = 1879048189
+ verneed = 1879048190
+ verneednum = 1879048191
+ loproc = 1879048192
+ sparc_register = 1879048193
+ auxiliary = 2147483645
+ used = 2147483646
+ hiproc = 2147483647
+
+ class Bits(Enum):
+ b32 = 1
+ b64 = 2
+
+ class PhType(Enum):
+ null_type = 0
+ load = 1
+ dynamic = 2
+ interp = 3
+ note = 4
+ shlib = 5
+ phdr = 6
+ tls = 7
+ gnu_eh_frame = 1685382480
+ gnu_stack = 1685382481
+ gnu_relro = 1685382482
+ pax_flags = 1694766464
+ hios = 1879048191
+ arm_exidx = 1879048193
+
+ class ObjType(Enum):
+ relocatable = 1
+ executable = 2
+ shared = 3
+ core = 4
+ SEQ_FIELDS = ["magic", "bits", "endian", "ei_version", "abi", "abi_version", "pad", "header"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['magic']['start'] = self._io.pos()
+ self.magic = self._io.ensure_fixed_contents(b"\x7F\x45\x4C\x46")
+ self._debug['magic']['end'] = self._io.pos()
+ self._debug['bits']['start'] = self._io.pos()
+ self.bits = KaitaiStream.resolve_enum(self._root.Bits, self._io.read_u1())
+ self._debug['bits']['end'] = self._io.pos()
+ self._debug['endian']['start'] = self._io.pos()
+ self.endian = KaitaiStream.resolve_enum(self._root.Endian, self._io.read_u1())
+ self._debug['endian']['end'] = self._io.pos()
+ self._debug['ei_version']['start'] = self._io.pos()
+ self.ei_version = self._io.read_u1()
+ self._debug['ei_version']['end'] = self._io.pos()
+ self._debug['abi']['start'] = self._io.pos()
+ self.abi = KaitaiStream.resolve_enum(self._root.OsAbi, self._io.read_u1())
+ self._debug['abi']['end'] = self._io.pos()
+ self._debug['abi_version']['start'] = self._io.pos()
+ self.abi_version = self._io.read_u1()
+ self._debug['abi_version']['end'] = self._io.pos()
+ self._debug['pad']['start'] = self._io.pos()
+ self.pad = self._io.read_bytes(7)
+ self._debug['pad']['end'] = self._io.pos()
+ self._debug['header']['start'] = self._io.pos()
+ self.header = self._root.EndianElf(self._io, self, self._root)
+ self.header._read()
+ self._debug['header']['end'] = self._io.pos()
+
+ class PhdrTypeFlags(KaitaiStruct):
+ SEQ_FIELDS = []
+ def __init__(self, value, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self.value = value
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ pass
+
+ @property
+ def read(self):
+ if hasattr(self, '_m_read'):
+ return self._m_read if hasattr(self, '_m_read') else None
+
+ self._m_read = (self.value & 4) != 0
+ return self._m_read if hasattr(self, '_m_read') else None
+
+ @property
+ def write(self):
+ if hasattr(self, '_m_write'):
+ return self._m_write if hasattr(self, '_m_write') else None
+
+ self._m_write = (self.value & 2) != 0
+ return self._m_write if hasattr(self, '_m_write') else None
+
+ @property
+ def execute(self):
+ if hasattr(self, '_m_execute'):
+ return self._m_execute if hasattr(self, '_m_execute') else None
+
+ self._m_execute = (self.value & 1) != 0
+ return self._m_execute if hasattr(self, '_m_execute') else None
+
+ @property
+ def mask_proc(self):
+ if hasattr(self, '_m_mask_proc'):
+ return self._m_mask_proc if hasattr(self, '_m_mask_proc') else None
+
+ self._m_mask_proc = (self.value & 4026531840) != 0
+ return self._m_mask_proc if hasattr(self, '_m_mask_proc') else None
+
+
+ class SectionHeaderFlags(KaitaiStruct):
+ SEQ_FIELDS = []
+ def __init__(self, value, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self.value = value
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ pass
+
+ @property
+ def merge(self):
+ """might be merged."""
+ if hasattr(self, '_m_merge'):
+ return self._m_merge if hasattr(self, '_m_merge') else None
+
+ self._m_merge = (self.value & 16) != 0
+ return self._m_merge if hasattr(self, '_m_merge') else None
+
+ @property
+ def mask_os(self):
+ """OS-specific."""
+ if hasattr(self, '_m_mask_os'):
+ return self._m_mask_os if hasattr(self, '_m_mask_os') else None
+
+ self._m_mask_os = (self.value & 267386880) != 0
+ return self._m_mask_os if hasattr(self, '_m_mask_os') else None
+
+ @property
+ def exclude(self):
+ """section is excluded unless referenced or allocated (Solaris)."""
+ if hasattr(self, '_m_exclude'):
+ return self._m_exclude if hasattr(self, '_m_exclude') else None
+
+ self._m_exclude = (self.value & 134217728) != 0
+ return self._m_exclude if hasattr(self, '_m_exclude') else None
+
+ @property
+ def mask_proc(self):
+ """Processor-specific."""
+ if hasattr(self, '_m_mask_proc'):
+ return self._m_mask_proc if hasattr(self, '_m_mask_proc') else None
+
+ self._m_mask_proc = (self.value & 4026531840) != 0
+ return self._m_mask_proc if hasattr(self, '_m_mask_proc') else None
+
+ @property
+ def strings(self):
+ """contains nul-terminated strings."""
+ if hasattr(self, '_m_strings'):
+ return self._m_strings if hasattr(self, '_m_strings') else None
+
+ self._m_strings = (self.value & 32) != 0
+ return self._m_strings if hasattr(self, '_m_strings') else None
+
+ @property
+ def os_non_conforming(self):
+ """non-standard OS specific handling required."""
+ if hasattr(self, '_m_os_non_conforming'):
+ return self._m_os_non_conforming if hasattr(self, '_m_os_non_conforming') else None
+
+ self._m_os_non_conforming = (self.value & 256) != 0
+ return self._m_os_non_conforming if hasattr(self, '_m_os_non_conforming') else None
+
+ @property
+ def alloc(self):
+ """occupies memory during execution."""
+ if hasattr(self, '_m_alloc'):
+ return self._m_alloc if hasattr(self, '_m_alloc') else None
+
+ self._m_alloc = (self.value & 2) != 0
+ return self._m_alloc if hasattr(self, '_m_alloc') else None
+
+ @property
+ def exec_instr(self):
+ """executable."""
+ if hasattr(self, '_m_exec_instr'):
+ return self._m_exec_instr if hasattr(self, '_m_exec_instr') else None
+
+ self._m_exec_instr = (self.value & 4) != 0
+ return self._m_exec_instr if hasattr(self, '_m_exec_instr') else None
+
+ @property
+ def info_link(self):
+ """'sh_info' contains SHT index."""
+ if hasattr(self, '_m_info_link'):
+ return self._m_info_link if hasattr(self, '_m_info_link') else None
+
+ self._m_info_link = (self.value & 64) != 0
+ return self._m_info_link if hasattr(self, '_m_info_link') else None
+
+ @property
+ def write(self):
+ """writable."""
+ if hasattr(self, '_m_write'):
+ return self._m_write if hasattr(self, '_m_write') else None
+
+ self._m_write = (self.value & 1) != 0
+ return self._m_write if hasattr(self, '_m_write') else None
+
+ @property
+ def link_order(self):
+ """preserve order after combining."""
+ if hasattr(self, '_m_link_order'):
+ return self._m_link_order if hasattr(self, '_m_link_order') else None
+
+ self._m_link_order = (self.value & 128) != 0
+ return self._m_link_order if hasattr(self, '_m_link_order') else None
+
+ @property
+ def ordered(self):
+ """special ordering requirement (Solaris)."""
+ if hasattr(self, '_m_ordered'):
+ return self._m_ordered if hasattr(self, '_m_ordered') else None
+
+ self._m_ordered = (self.value & 67108864) != 0
+ return self._m_ordered if hasattr(self, '_m_ordered') else None
+
+ @property
+ def tls(self):
+ """section hold thread-local data."""
+ if hasattr(self, '_m_tls'):
+ return self._m_tls if hasattr(self, '_m_tls') else None
+
+ self._m_tls = (self.value & 1024) != 0
+ return self._m_tls if hasattr(self, '_m_tls') else None
+
+ @property
+ def group(self):
+ """section is member of a group."""
+ if hasattr(self, '_m_group'):
+ return self._m_group if hasattr(self, '_m_group') else None
+
+ self._m_group = (self.value & 512) != 0
+ return self._m_group if hasattr(self, '_m_group') else None
+
+
+ class DtFlag1Values(KaitaiStruct):
+ SEQ_FIELDS = []
+ def __init__(self, value, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self.value = value
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ pass
+
+ @property
+ def singleton(self):
+ """Singleton symbols are used."""
+ if hasattr(self, '_m_singleton'):
+ return self._m_singleton if hasattr(self, '_m_singleton') else None
+
+ self._m_singleton = (self.value & 33554432) != 0
+ return self._m_singleton if hasattr(self, '_m_singleton') else None
+
+ @property
+ def ignmuldef(self):
+ if hasattr(self, '_m_ignmuldef'):
+ return self._m_ignmuldef if hasattr(self, '_m_ignmuldef') else None
+
+ self._m_ignmuldef = (self.value & 262144) != 0
+ return self._m_ignmuldef if hasattr(self, '_m_ignmuldef') else None
+
+ @property
+ def loadfltr(self):
+ """Trigger filtee loading at runtime."""
+ if hasattr(self, '_m_loadfltr'):
+ return self._m_loadfltr if hasattr(self, '_m_loadfltr') else None
+
+ self._m_loadfltr = (self.value & 16) != 0
+ return self._m_loadfltr if hasattr(self, '_m_loadfltr') else None
+
+ @property
+ def initfirst(self):
+ """Set RTLD_INITFIRST for this object."""
+ if hasattr(self, '_m_initfirst'):
+ return self._m_initfirst if hasattr(self, '_m_initfirst') else None
+
+ self._m_initfirst = (self.value & 32) != 0
+ return self._m_initfirst if hasattr(self, '_m_initfirst') else None
+
+ @property
+ def symintpose(self):
+ """Object has individual interposers."""
+ if hasattr(self, '_m_symintpose'):
+ return self._m_symintpose if hasattr(self, '_m_symintpose') else None
+
+ self._m_symintpose = (self.value & 8388608) != 0
+ return self._m_symintpose if hasattr(self, '_m_symintpose') else None
+
+ @property
+ def noreloc(self):
+ if hasattr(self, '_m_noreloc'):
+ return self._m_noreloc if hasattr(self, '_m_noreloc') else None
+
+ self._m_noreloc = (self.value & 4194304) != 0
+ return self._m_noreloc if hasattr(self, '_m_noreloc') else None
+
+ @property
+ def confalt(self):
+ """Configuration alternative created."""
+ if hasattr(self, '_m_confalt'):
+ return self._m_confalt if hasattr(self, '_m_confalt') else None
+
+ self._m_confalt = (self.value & 8192) != 0
+ return self._m_confalt if hasattr(self, '_m_confalt') else None
+
+ @property
+ def dispreldne(self):
+ """Disp reloc applied at build time."""
+ if hasattr(self, '_m_dispreldne'):
+ return self._m_dispreldne if hasattr(self, '_m_dispreldne') else None
+
+ self._m_dispreldne = (self.value & 32768) != 0
+ return self._m_dispreldne if hasattr(self, '_m_dispreldne') else None
+
+ @property
+ def rtld_global(self):
+ """Set RTLD_GLOBAL for this object."""
+ if hasattr(self, '_m_rtld_global'):
+ return self._m_rtld_global if hasattr(self, '_m_rtld_global') else None
+
+ self._m_rtld_global = (self.value & 2) != 0
+ return self._m_rtld_global if hasattr(self, '_m_rtld_global') else None
+
+ @property
+ def nodelete(self):
+ """Set RTLD_NODELETE for this object."""
+ if hasattr(self, '_m_nodelete'):
+ return self._m_nodelete if hasattr(self, '_m_nodelete') else None
+
+ self._m_nodelete = (self.value & 8) != 0
+ return self._m_nodelete if hasattr(self, '_m_nodelete') else None
+
+ @property
+ def trans(self):
+ if hasattr(self, '_m_trans'):
+ return self._m_trans if hasattr(self, '_m_trans') else None
+
+ self._m_trans = (self.value & 512) != 0
+ return self._m_trans if hasattr(self, '_m_trans') else None
+
+ @property
+ def origin(self):
+ """$ORIGIN must be handled."""
+ if hasattr(self, '_m_origin'):
+ return self._m_origin if hasattr(self, '_m_origin') else None
+
+ self._m_origin = (self.value & 128) != 0
+ return self._m_origin if hasattr(self, '_m_origin') else None
+
+ @property
+ def now(self):
+ """Set RTLD_NOW for this object."""
+ if hasattr(self, '_m_now'):
+ return self._m_now if hasattr(self, '_m_now') else None
+
+ self._m_now = (self.value & 1) != 0
+ return self._m_now if hasattr(self, '_m_now') else None
+
+ @property
+ def nohdr(self):
+ if hasattr(self, '_m_nohdr'):
+ return self._m_nohdr if hasattr(self, '_m_nohdr') else None
+
+ self._m_nohdr = (self.value & 1048576) != 0
+ return self._m_nohdr if hasattr(self, '_m_nohdr') else None
+
+ @property
+ def endfiltee(self):
+ """Filtee terminates filters search."""
+ if hasattr(self, '_m_endfiltee'):
+ return self._m_endfiltee if hasattr(self, '_m_endfiltee') else None
+
+ self._m_endfiltee = (self.value & 16384) != 0
+ return self._m_endfiltee if hasattr(self, '_m_endfiltee') else None
+
+ @property
+ def nodirect(self):
+ """Object has no-direct binding."""
+ if hasattr(self, '_m_nodirect'):
+ return self._m_nodirect if hasattr(self, '_m_nodirect') else None
+
+ self._m_nodirect = (self.value & 131072) != 0
+ return self._m_nodirect if hasattr(self, '_m_nodirect') else None
+
+ @property
+ def globaudit(self):
+ """Global auditing required."""
+ if hasattr(self, '_m_globaudit'):
+ return self._m_globaudit if hasattr(self, '_m_globaudit') else None
+
+ self._m_globaudit = (self.value & 16777216) != 0
+ return self._m_globaudit if hasattr(self, '_m_globaudit') else None
+
+ @property
+ def noksyms(self):
+ if hasattr(self, '_m_noksyms'):
+ return self._m_noksyms if hasattr(self, '_m_noksyms') else None
+
+ self._m_noksyms = (self.value & 524288) != 0
+ return self._m_noksyms if hasattr(self, '_m_noksyms') else None
+
+ @property
+ def interpose(self):
+ """Object is used to interpose."""
+ if hasattr(self, '_m_interpose'):
+ return self._m_interpose if hasattr(self, '_m_interpose') else None
+
+ self._m_interpose = (self.value & 1024) != 0
+ return self._m_interpose if hasattr(self, '_m_interpose') else None
+
+ @property
+ def nodump(self):
+ """Object can't be dldump'ed."""
+ if hasattr(self, '_m_nodump'):
+ return self._m_nodump if hasattr(self, '_m_nodump') else None
+
+ self._m_nodump = (self.value & 4096) != 0
+ return self._m_nodump if hasattr(self, '_m_nodump') else None
+
+ @property
+ def disprelpnd(self):
+ """Disp reloc applied at run-time."""
+ if hasattr(self, '_m_disprelpnd'):
+ return self._m_disprelpnd if hasattr(self, '_m_disprelpnd') else None
+
+ self._m_disprelpnd = (self.value & 65536) != 0
+ return self._m_disprelpnd if hasattr(self, '_m_disprelpnd') else None
+
+ @property
+ def noopen(self):
+ """Set RTLD_NOOPEN for this object."""
+ if hasattr(self, '_m_noopen'):
+ return self._m_noopen if hasattr(self, '_m_noopen') else None
+
+ self._m_noopen = (self.value & 64) != 0
+ return self._m_noopen if hasattr(self, '_m_noopen') else None
+
+ @property
+ def stub(self):
+ if hasattr(self, '_m_stub'):
+ return self._m_stub if hasattr(self, '_m_stub') else None
+
+ self._m_stub = (self.value & 67108864) != 0
+ return self._m_stub if hasattr(self, '_m_stub') else None
+
+ @property
+ def direct(self):
+ """Direct binding enabled."""
+ if hasattr(self, '_m_direct'):
+ return self._m_direct if hasattr(self, '_m_direct') else None
+
+ self._m_direct = (self.value & 256) != 0
+ return self._m_direct if hasattr(self, '_m_direct') else None
+
+ @property
+ def edited(self):
+ """Object is modified after built."""
+ if hasattr(self, '_m_edited'):
+ return self._m_edited if hasattr(self, '_m_edited') else None
+
+ self._m_edited = (self.value & 2097152) != 0
+ return self._m_edited if hasattr(self, '_m_edited') else None
+
+ @property
+ def group(self):
+ """Set RTLD_GROUP for this object."""
+ if hasattr(self, '_m_group'):
+ return self._m_group if hasattr(self, '_m_group') else None
+
+ self._m_group = (self.value & 4) != 0
+ return self._m_group if hasattr(self, '_m_group') else None
+
+ @property
+ def pie(self):
+ if hasattr(self, '_m_pie'):
+ return self._m_pie if hasattr(self, '_m_pie') else None
+
+ self._m_pie = (self.value & 134217728) != 0
+ return self._m_pie if hasattr(self, '_m_pie') else None
+
+ @property
+ def nodeflib(self):
+ """Ignore default lib search path."""
+ if hasattr(self, '_m_nodeflib'):
+ return self._m_nodeflib if hasattr(self, '_m_nodeflib') else None
+
+ self._m_nodeflib = (self.value & 2048) != 0
+ return self._m_nodeflib if hasattr(self, '_m_nodeflib') else None
+
+
+ class EndianElf(KaitaiStruct):
+ SEQ_FIELDS = ["e_type", "machine", "e_version", "entry_point", "program_header_offset", "section_header_offset", "flags", "e_ehsize", "program_header_entry_size", "qty_program_header", "section_header_entry_size", "qty_section_header", "section_names_idx"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ _on = self._root.endian
+ if _on == self._root.Endian.le:
+ self._is_le = True
+ elif _on == self._root.Endian.be:
+ self._is_le = False
+
+ if self._is_le == True:
+ self._read_le()
+ elif self._is_le == False:
+ self._read_be()
+ else:
+ raise Exception("Unable to decide endianness")
+
+ def _read_le(self):
+ self._debug['e_type']['start'] = self._io.pos()
+ self.e_type = KaitaiStream.resolve_enum(self._root.ObjType, self._io.read_u2le())
+ self._debug['e_type']['end'] = self._io.pos()
+ self._debug['machine']['start'] = self._io.pos()
+ self.machine = KaitaiStream.resolve_enum(self._root.Machine, self._io.read_u2le())
+ self._debug['machine']['end'] = self._io.pos()
+ self._debug['e_version']['start'] = self._io.pos()
+ self.e_version = self._io.read_u4le()
+ self._debug['e_version']['end'] = self._io.pos()
+ self._debug['entry_point']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.entry_point = self._io.read_u4le()
+ elif _on == self._root.Bits.b64:
+ self.entry_point = self._io.read_u8le()
+ self._debug['entry_point']['end'] = self._io.pos()
+ self._debug['program_header_offset']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.program_header_offset = self._io.read_u4le()
+ elif _on == self._root.Bits.b64:
+ self.program_header_offset = self._io.read_u8le()
+ self._debug['program_header_offset']['end'] = self._io.pos()
+ self._debug['section_header_offset']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.section_header_offset = self._io.read_u4le()
+ elif _on == self._root.Bits.b64:
+ self.section_header_offset = self._io.read_u8le()
+ self._debug['section_header_offset']['end'] = self._io.pos()
+ self._debug['flags']['start'] = self._io.pos()
+ self.flags = self._io.read_bytes(4)
+ self._debug['flags']['end'] = self._io.pos()
+ self._debug['e_ehsize']['start'] = self._io.pos()
+ self.e_ehsize = self._io.read_u2le()
+ self._debug['e_ehsize']['end'] = self._io.pos()
+ self._debug['program_header_entry_size']['start'] = self._io.pos()
+ self.program_header_entry_size = self._io.read_u2le()
+ self._debug['program_header_entry_size']['end'] = self._io.pos()
+ self._debug['qty_program_header']['start'] = self._io.pos()
+ self.qty_program_header = self._io.read_u2le()
+ self._debug['qty_program_header']['end'] = self._io.pos()
+ self._debug['section_header_entry_size']['start'] = self._io.pos()
+ self.section_header_entry_size = self._io.read_u2le()
+ self._debug['section_header_entry_size']['end'] = self._io.pos()
+ self._debug['qty_section_header']['start'] = self._io.pos()
+ self.qty_section_header = self._io.read_u2le()
+ self._debug['qty_section_header']['end'] = self._io.pos()
+ self._debug['section_names_idx']['start'] = self._io.pos()
+ self.section_names_idx = self._io.read_u2le()
+ self._debug['section_names_idx']['end'] = self._io.pos()
+
+ def _read_be(self):
+ self._debug['e_type']['start'] = self._io.pos()
+ self.e_type = KaitaiStream.resolve_enum(self._root.ObjType, self._io.read_u2be())
+ self._debug['e_type']['end'] = self._io.pos()
+ self._debug['machine']['start'] = self._io.pos()
+ self.machine = KaitaiStream.resolve_enum(self._root.Machine, self._io.read_u2be())
+ self._debug['machine']['end'] = self._io.pos()
+ self._debug['e_version']['start'] = self._io.pos()
+ self.e_version = self._io.read_u4be()
+ self._debug['e_version']['end'] = self._io.pos()
+ self._debug['entry_point']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.entry_point = self._io.read_u4be()
+ elif _on == self._root.Bits.b64:
+ self.entry_point = self._io.read_u8be()
+ self._debug['entry_point']['end'] = self._io.pos()
+ self._debug['program_header_offset']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.program_header_offset = self._io.read_u4be()
+ elif _on == self._root.Bits.b64:
+ self.program_header_offset = self._io.read_u8be()
+ self._debug['program_header_offset']['end'] = self._io.pos()
+ self._debug['section_header_offset']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.section_header_offset = self._io.read_u4be()
+ elif _on == self._root.Bits.b64:
+ self.section_header_offset = self._io.read_u8be()
+ self._debug['section_header_offset']['end'] = self._io.pos()
+ self._debug['flags']['start'] = self._io.pos()
+ self.flags = self._io.read_bytes(4)
+ self._debug['flags']['end'] = self._io.pos()
+ self._debug['e_ehsize']['start'] = self._io.pos()
+ self.e_ehsize = self._io.read_u2be()
+ self._debug['e_ehsize']['end'] = self._io.pos()
+ self._debug['program_header_entry_size']['start'] = self._io.pos()
+ self.program_header_entry_size = self._io.read_u2be()
+ self._debug['program_header_entry_size']['end'] = self._io.pos()
+ self._debug['qty_program_header']['start'] = self._io.pos()
+ self.qty_program_header = self._io.read_u2be()
+ self._debug['qty_program_header']['end'] = self._io.pos()
+ self._debug['section_header_entry_size']['start'] = self._io.pos()
+ self.section_header_entry_size = self._io.read_u2be()
+ self._debug['section_header_entry_size']['end'] = self._io.pos()
+ self._debug['qty_section_header']['start'] = self._io.pos()
+ self.qty_section_header = self._io.read_u2be()
+ self._debug['qty_section_header']['end'] = self._io.pos()
+ self._debug['section_names_idx']['start'] = self._io.pos()
+ self.section_names_idx = self._io.read_u2be()
+ self._debug['section_names_idx']['end'] = self._io.pos()
+
+ class DynsymSectionEntry64(KaitaiStruct):
+ SEQ_FIELDS = ["name_offset", "info", "other", "shndx", "value", "size"]
+ def __init__(self, _io, _parent=None, _root=None, _is_le=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._is_le = _is_le
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+
+ if self._is_le == True:
+ self._read_le()
+ elif self._is_le == False:
+ self._read_be()
+ else:
+ raise Exception("Unable to decide endianness")
+
+ def _read_le(self):
+ self._debug['name_offset']['start'] = self._io.pos()
+ self.name_offset = self._io.read_u4le()
+ self._debug['name_offset']['end'] = self._io.pos()
+ self._debug['info']['start'] = self._io.pos()
+ self.info = self._io.read_u1()
+ self._debug['info']['end'] = self._io.pos()
+ self._debug['other']['start'] = self._io.pos()
+ self.other = self._io.read_u1()
+ self._debug['other']['end'] = self._io.pos()
+ self._debug['shndx']['start'] = self._io.pos()
+ self.shndx = self._io.read_u2le()
+ self._debug['shndx']['end'] = self._io.pos()
+ self._debug['value']['start'] = self._io.pos()
+ self.value = self._io.read_u8le()
+ self._debug['value']['end'] = self._io.pos()
+ self._debug['size']['start'] = self._io.pos()
+ self.size = self._io.read_u8le()
+ self._debug['size']['end'] = self._io.pos()
+
+ def _read_be(self):
+ self._debug['name_offset']['start'] = self._io.pos()
+ self.name_offset = self._io.read_u4be()
+ self._debug['name_offset']['end'] = self._io.pos()
+ self._debug['info']['start'] = self._io.pos()
+ self.info = self._io.read_u1()
+ self._debug['info']['end'] = self._io.pos()
+ self._debug['other']['start'] = self._io.pos()
+ self.other = self._io.read_u1()
+ self._debug['other']['end'] = self._io.pos()
+ self._debug['shndx']['start'] = self._io.pos()
+ self.shndx = self._io.read_u2be()
+ self._debug['shndx']['end'] = self._io.pos()
+ self._debug['value']['start'] = self._io.pos()
+ self.value = self._io.read_u8be()
+ self._debug['value']['end'] = self._io.pos()
+ self._debug['size']['start'] = self._io.pos()
+ self.size = self._io.read_u8be()
+ self._debug['size']['end'] = self._io.pos()
+
+
+ class ProgramHeader(KaitaiStruct):
+ SEQ_FIELDS = ["type", "flags64", "offset", "vaddr", "paddr", "filesz", "memsz", "flags32", "align"]
+ def __init__(self, _io, _parent=None, _root=None, _is_le=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._is_le = _is_le
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+
+ if self._is_le == True:
+ self._read_le()
+ elif self._is_le == False:
+ self._read_be()
+ else:
+ raise Exception("Unable to decide endianness")
+
+ def _read_le(self):
+ self._debug['type']['start'] = self._io.pos()
+ self.type = KaitaiStream.resolve_enum(self._root.PhType, self._io.read_u4le())
+ self._debug['type']['end'] = self._io.pos()
+ if self._root.bits == self._root.Bits.b64:
+ self._debug['flags64']['start'] = self._io.pos()
+ self.flags64 = self._io.read_u4le()
+ self._debug['flags64']['end'] = self._io.pos()
+
+ self._debug['offset']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.offset = self._io.read_u4le()
+ elif _on == self._root.Bits.b64:
+ self.offset = self._io.read_u8le()
+ self._debug['offset']['end'] = self._io.pos()
+ self._debug['vaddr']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.vaddr = self._io.read_u4le()
+ elif _on == self._root.Bits.b64:
+ self.vaddr = self._io.read_u8le()
+ self._debug['vaddr']['end'] = self._io.pos()
+ self._debug['paddr']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.paddr = self._io.read_u4le()
+ elif _on == self._root.Bits.b64:
+ self.paddr = self._io.read_u8le()
+ self._debug['paddr']['end'] = self._io.pos()
+ self._debug['filesz']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.filesz = self._io.read_u4le()
+ elif _on == self._root.Bits.b64:
+ self.filesz = self._io.read_u8le()
+ self._debug['filesz']['end'] = self._io.pos()
+ self._debug['memsz']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.memsz = self._io.read_u4le()
+ elif _on == self._root.Bits.b64:
+ self.memsz = self._io.read_u8le()
+ self._debug['memsz']['end'] = self._io.pos()
+ if self._root.bits == self._root.Bits.b32:
+ self._debug['flags32']['start'] = self._io.pos()
+ self.flags32 = self._io.read_u4le()
+ self._debug['flags32']['end'] = self._io.pos()
+
+ self._debug['align']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.align = self._io.read_u4le()
+ elif _on == self._root.Bits.b64:
+ self.align = self._io.read_u8le()
+ self._debug['align']['end'] = self._io.pos()
+
+ def _read_be(self):
+ self._debug['type']['start'] = self._io.pos()
+ self.type = KaitaiStream.resolve_enum(self._root.PhType, self._io.read_u4be())
+ self._debug['type']['end'] = self._io.pos()
+ if self._root.bits == self._root.Bits.b64:
+ self._debug['flags64']['start'] = self._io.pos()
+ self.flags64 = self._io.read_u4be()
+ self._debug['flags64']['end'] = self._io.pos()
+
+ self._debug['offset']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.offset = self._io.read_u4be()
+ elif _on == self._root.Bits.b64:
+ self.offset = self._io.read_u8be()
+ self._debug['offset']['end'] = self._io.pos()
+ self._debug['vaddr']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.vaddr = self._io.read_u4be()
+ elif _on == self._root.Bits.b64:
+ self.vaddr = self._io.read_u8be()
+ self._debug['vaddr']['end'] = self._io.pos()
+ self._debug['paddr']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.paddr = self._io.read_u4be()
+ elif _on == self._root.Bits.b64:
+ self.paddr = self._io.read_u8be()
+ self._debug['paddr']['end'] = self._io.pos()
+ self._debug['filesz']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.filesz = self._io.read_u4be()
+ elif _on == self._root.Bits.b64:
+ self.filesz = self._io.read_u8be()
+ self._debug['filesz']['end'] = self._io.pos()
+ self._debug['memsz']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.memsz = self._io.read_u4be()
+ elif _on == self._root.Bits.b64:
+ self.memsz = self._io.read_u8be()
+ self._debug['memsz']['end'] = self._io.pos()
+ if self._root.bits == self._root.Bits.b32:
+ self._debug['flags32']['start'] = self._io.pos()
+ self.flags32 = self._io.read_u4be()
+ self._debug['flags32']['end'] = self._io.pos()
+
+ self._debug['align']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.align = self._io.read_u4be()
+ elif _on == self._root.Bits.b64:
+ self.align = self._io.read_u8be()
+ self._debug['align']['end'] = self._io.pos()
+
+ @property
+ def dynamic(self):
+ if hasattr(self, '_m_dynamic'):
+ return self._m_dynamic if hasattr(self, '_m_dynamic') else None
+
+ if self.type == self._root.PhType.dynamic:
+ io = self._root._io
+ _pos = io.pos()
+ io.seek(self.offset)
+ self._debug['_m_dynamic']['start'] = io.pos()
+ if self._is_le:
+ self._raw__m_dynamic = io.read_bytes(self.filesz)
+ io = KaitaiStream(BytesIO(self._raw__m_dynamic))
+ self._m_dynamic = self._root.EndianElf.DynamicSection(io, self, self._root, self._is_le)
+ self._m_dynamic._read()
+ else:
+ self._raw__m_dynamic = io.read_bytes(self.filesz)
+ io = KaitaiStream(BytesIO(self._raw__m_dynamic))
+ self._m_dynamic = self._root.EndianElf.DynamicSection(io, self, self._root, self._is_le)
+ self._m_dynamic._read()
+ self._debug['_m_dynamic']['end'] = io.pos()
+ io.seek(_pos)
+
+ return self._m_dynamic if hasattr(self, '_m_dynamic') else None
+
+ @property
+ def flags_obj(self):
+ if hasattr(self, '_m_flags_obj'):
+ return self._m_flags_obj if hasattr(self, '_m_flags_obj') else None
+
+ self._debug['_m_flags_obj']['start'] = self._io.pos()
+ if self._is_le:
+ self._m_flags_obj = self._root.PhdrTypeFlags((self.flags64 | self.flags32), self._io, self, self._root)
+ self._m_flags_obj._read()
+ else:
+ self._m_flags_obj = self._root.PhdrTypeFlags((self.flags64 | self.flags32), self._io, self, self._root)
+ self._m_flags_obj._read()
+ self._debug['_m_flags_obj']['end'] = self._io.pos()
+ return self._m_flags_obj if hasattr(self, '_m_flags_obj') else None
+
+
+ class DynamicSectionEntry(KaitaiStruct):
+ SEQ_FIELDS = ["tag", "value_or_ptr"]
+ def __init__(self, _io, _parent=None, _root=None, _is_le=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._is_le = _is_le
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+
+ if self._is_le == True:
+ self._read_le()
+ elif self._is_le == False:
+ self._read_be()
+ else:
+ raise Exception("Unable to decide endianness")
+
+ def _read_le(self):
+ self._debug['tag']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.tag = self._io.read_u4le()
+ elif _on == self._root.Bits.b64:
+ self.tag = self._io.read_u8le()
+ self._debug['tag']['end'] = self._io.pos()
+ self._debug['value_or_ptr']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.value_or_ptr = self._io.read_u4le()
+ elif _on == self._root.Bits.b64:
+ self.value_or_ptr = self._io.read_u8le()
+ self._debug['value_or_ptr']['end'] = self._io.pos()
+
+ def _read_be(self):
+ self._debug['tag']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.tag = self._io.read_u4be()
+ elif _on == self._root.Bits.b64:
+ self.tag = self._io.read_u8be()
+ self._debug['tag']['end'] = self._io.pos()
+ self._debug['value_or_ptr']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.value_or_ptr = self._io.read_u4be()
+ elif _on == self._root.Bits.b64:
+ self.value_or_ptr = self._io.read_u8be()
+ self._debug['value_or_ptr']['end'] = self._io.pos()
+
+ @property
+ def tag_enum(self):
+ if hasattr(self, '_m_tag_enum'):
+ return self._m_tag_enum if hasattr(self, '_m_tag_enum') else None
+
+ self._m_tag_enum = KaitaiStream.resolve_enum(self._root.DynamicArrayTags, self.tag)
+ return self._m_tag_enum if hasattr(self, '_m_tag_enum') else None
+
+ @property
+ def flag_1_values(self):
+ if hasattr(self, '_m_flag_1_values'):
+ return self._m_flag_1_values if hasattr(self, '_m_flag_1_values') else None
+
+ if self.tag_enum == self._root.DynamicArrayTags.flags_1:
+ self._debug['_m_flag_1_values']['start'] = self._io.pos()
+ if self._is_le:
+ self._m_flag_1_values = self._root.DtFlag1Values(self.value_or_ptr, self._io, self, self._root)
+ self._m_flag_1_values._read()
+ else:
+ self._m_flag_1_values = self._root.DtFlag1Values(self.value_or_ptr, self._io, self, self._root)
+ self._m_flag_1_values._read()
+ self._debug['_m_flag_1_values']['end'] = self._io.pos()
+
+ return self._m_flag_1_values if hasattr(self, '_m_flag_1_values') else None
+
+
+ class SectionHeader(KaitaiStruct):
+ SEQ_FIELDS = ["ofs_name", "type", "flags", "addr", "ofs_body", "len_body", "linked_section_idx", "info", "align", "entry_size"]
+ def __init__(self, _io, _parent=None, _root=None, _is_le=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._is_le = _is_le
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+
+ if self._is_le == True:
+ self._read_le()
+ elif self._is_le == False:
+ self._read_be()
+ else:
+ raise Exception("Unable to decide endianness")
+
+ def _read_le(self):
+ self._debug['ofs_name']['start'] = self._io.pos()
+ self.ofs_name = self._io.read_u4le()
+ self._debug['ofs_name']['end'] = self._io.pos()
+ self._debug['type']['start'] = self._io.pos()
+ self.type = KaitaiStream.resolve_enum(self._root.ShType, self._io.read_u4le())
+ self._debug['type']['end'] = self._io.pos()
+ self._debug['flags']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.flags = self._io.read_u4le()
+ elif _on == self._root.Bits.b64:
+ self.flags = self._io.read_u8le()
+ self._debug['flags']['end'] = self._io.pos()
+ self._debug['addr']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.addr = self._io.read_u4le()
+ elif _on == self._root.Bits.b64:
+ self.addr = self._io.read_u8le()
+ self._debug['addr']['end'] = self._io.pos()
+ self._debug['ofs_body']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.ofs_body = self._io.read_u4le()
+ elif _on == self._root.Bits.b64:
+ self.ofs_body = self._io.read_u8le()
+ self._debug['ofs_body']['end'] = self._io.pos()
+ self._debug['len_body']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.len_body = self._io.read_u4le()
+ elif _on == self._root.Bits.b64:
+ self.len_body = self._io.read_u8le()
+ self._debug['len_body']['end'] = self._io.pos()
+ self._debug['linked_section_idx']['start'] = self._io.pos()
+ self.linked_section_idx = self._io.read_u4le()
+ self._debug['linked_section_idx']['end'] = self._io.pos()
+ self._debug['info']['start'] = self._io.pos()
+ self.info = self._io.read_bytes(4)
+ self._debug['info']['end'] = self._io.pos()
+ self._debug['align']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.align = self._io.read_u4le()
+ elif _on == self._root.Bits.b64:
+ self.align = self._io.read_u8le()
+ self._debug['align']['end'] = self._io.pos()
+ self._debug['entry_size']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.entry_size = self._io.read_u4le()
+ elif _on == self._root.Bits.b64:
+ self.entry_size = self._io.read_u8le()
+ self._debug['entry_size']['end'] = self._io.pos()
+
+ def _read_be(self):
+ self._debug['ofs_name']['start'] = self._io.pos()
+ self.ofs_name = self._io.read_u4be()
+ self._debug['ofs_name']['end'] = self._io.pos()
+ self._debug['type']['start'] = self._io.pos()
+ self.type = KaitaiStream.resolve_enum(self._root.ShType, self._io.read_u4be())
+ self._debug['type']['end'] = self._io.pos()
+ self._debug['flags']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.flags = self._io.read_u4be()
+ elif _on == self._root.Bits.b64:
+ self.flags = self._io.read_u8be()
+ self._debug['flags']['end'] = self._io.pos()
+ self._debug['addr']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.addr = self._io.read_u4be()
+ elif _on == self._root.Bits.b64:
+ self.addr = self._io.read_u8be()
+ self._debug['addr']['end'] = self._io.pos()
+ self._debug['ofs_body']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.ofs_body = self._io.read_u4be()
+ elif _on == self._root.Bits.b64:
+ self.ofs_body = self._io.read_u8be()
+ self._debug['ofs_body']['end'] = self._io.pos()
+ self._debug['len_body']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.len_body = self._io.read_u4be()
+ elif _on == self._root.Bits.b64:
+ self.len_body = self._io.read_u8be()
+ self._debug['len_body']['end'] = self._io.pos()
+ self._debug['linked_section_idx']['start'] = self._io.pos()
+ self.linked_section_idx = self._io.read_u4be()
+ self._debug['linked_section_idx']['end'] = self._io.pos()
+ self._debug['info']['start'] = self._io.pos()
+ self.info = self._io.read_bytes(4)
+ self._debug['info']['end'] = self._io.pos()
+ self._debug['align']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.align = self._io.read_u4be()
+ elif _on == self._root.Bits.b64:
+ self.align = self._io.read_u8be()
+ self._debug['align']['end'] = self._io.pos()
+ self._debug['entry_size']['start'] = self._io.pos()
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ self.entry_size = self._io.read_u4be()
+ elif _on == self._root.Bits.b64:
+ self.entry_size = self._io.read_u8be()
+ self._debug['entry_size']['end'] = self._io.pos()
+
+ @property
+ def body(self):
+ if hasattr(self, '_m_body'):
+ return self._m_body if hasattr(self, '_m_body') else None
+
+ io = self._root._io
+ _pos = io.pos()
+ io.seek(self.ofs_body)
+ self._debug['_m_body']['start'] = io.pos()
+ if self._is_le:
+ _on = self.type
+ if _on == self._root.ShType.strtab:
+ self._raw__m_body = io.read_bytes(self.len_body)
+ io = KaitaiStream(BytesIO(self._raw__m_body))
+ self._m_body = self._root.EndianElf.StringsStruct(io, self, self._root, self._is_le)
+ self._m_body._read()
+ elif _on == self._root.ShType.dynamic:
+ self._raw__m_body = io.read_bytes(self.len_body)
+ io = KaitaiStream(BytesIO(self._raw__m_body))
+ self._m_body = self._root.EndianElf.DynamicSection(io, self, self._root, self._is_le)
+ self._m_body._read()
+ elif _on == self._root.ShType.dynsym:
+ self._raw__m_body = io.read_bytes(self.len_body)
+ io = KaitaiStream(BytesIO(self._raw__m_body))
+ self._m_body = self._root.EndianElf.DynsymSection(io, self, self._root, self._is_le)
+ self._m_body._read()
+ elif _on == self._root.ShType.dynstr:
+ self._raw__m_body = io.read_bytes(self.len_body)
+ io = KaitaiStream(BytesIO(self._raw__m_body))
+ self._m_body = self._root.EndianElf.StringsStruct(io, self, self._root, self._is_le)
+ self._m_body._read()
+ else:
+ self._m_body = io.read_bytes(self.len_body)
+ else:
+ _on = self.type
+ if _on == self._root.ShType.strtab:
+ self._raw__m_body = io.read_bytes(self.len_body)
+ io = KaitaiStream(BytesIO(self._raw__m_body))
+ self._m_body = self._root.EndianElf.StringsStruct(io, self, self._root, self._is_le)
+ self._m_body._read()
+ elif _on == self._root.ShType.dynamic:
+ self._raw__m_body = io.read_bytes(self.len_body)
+ io = KaitaiStream(BytesIO(self._raw__m_body))
+ self._m_body = self._root.EndianElf.DynamicSection(io, self, self._root, self._is_le)
+ self._m_body._read()
+ elif _on == self._root.ShType.dynsym:
+ self._raw__m_body = io.read_bytes(self.len_body)
+ io = KaitaiStream(BytesIO(self._raw__m_body))
+ self._m_body = self._root.EndianElf.DynsymSection(io, self, self._root, self._is_le)
+ self._m_body._read()
+ elif _on == self._root.ShType.dynstr:
+ self._raw__m_body = io.read_bytes(self.len_body)
+ io = KaitaiStream(BytesIO(self._raw__m_body))
+ self._m_body = self._root.EndianElf.StringsStruct(io, self, self._root, self._is_le)
+ self._m_body._read()
+ else:
+ self._m_body = io.read_bytes(self.len_body)
+ self._debug['_m_body']['end'] = io.pos()
+ io.seek(_pos)
+ return self._m_body if hasattr(self, '_m_body') else None
+
+ @property
+ def name(self):
+ if hasattr(self, '_m_name'):
+ return self._m_name if hasattr(self, '_m_name') else None
+
+ io = self._root.header.strings._io
+ _pos = io.pos()
+ io.seek(self.ofs_name)
+ self._debug['_m_name']['start'] = io.pos()
+ if self._is_le:
+ self._m_name = (io.read_bytes_term(0, False, True, True)).decode(u"ASCII")
+ else:
+ self._m_name = (io.read_bytes_term(0, False, True, True)).decode(u"ASCII")
+ self._debug['_m_name']['end'] = io.pos()
+ io.seek(_pos)
+ return self._m_name if hasattr(self, '_m_name') else None
+
+ @property
+ def flags_obj(self):
+ if hasattr(self, '_m_flags_obj'):
+ return self._m_flags_obj if hasattr(self, '_m_flags_obj') else None
+
+ self._debug['_m_flags_obj']['start'] = self._io.pos()
+ if self._is_le:
+ self._m_flags_obj = self._root.SectionHeaderFlags(self.flags, self._io, self, self._root)
+ self._m_flags_obj._read()
+ else:
+ self._m_flags_obj = self._root.SectionHeaderFlags(self.flags, self._io, self, self._root)
+ self._m_flags_obj._read()
+ self._debug['_m_flags_obj']['end'] = self._io.pos()
+ return self._m_flags_obj if hasattr(self, '_m_flags_obj') else None
+
+
+ class DynamicSection(KaitaiStruct):
+ SEQ_FIELDS = ["entries"]
+ def __init__(self, _io, _parent=None, _root=None, _is_le=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._is_le = _is_le
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+
+ if self._is_le == True:
+ self._read_le()
+ elif self._is_le == False:
+ self._read_be()
+ else:
+ raise Exception("Unable to decide endianness")
+
+ def _read_le(self):
+ self._debug['entries']['start'] = self._io.pos()
+ self.entries = []
+ i = 0
+ while not self._io.is_eof():
+ if not 'arr' in self._debug['entries']:
+ self._debug['entries']['arr'] = []
+ self._debug['entries']['arr'].append({'start': self._io.pos()})
+ _t_entries = self._root.EndianElf.DynamicSectionEntry(self._io, self, self._root, self._is_le)
+ _t_entries._read()
+ self.entries.append(_t_entries)
+ self._debug['entries']['arr'][len(self.entries) - 1]['end'] = self._io.pos()
+ i += 1
+
+ self._debug['entries']['end'] = self._io.pos()
+
+ def _read_be(self):
+ self._debug['entries']['start'] = self._io.pos()
+ self.entries = []
+ i = 0
+ while not self._io.is_eof():
+ if not 'arr' in self._debug['entries']:
+ self._debug['entries']['arr'] = []
+ self._debug['entries']['arr'].append({'start': self._io.pos()})
+ _t_entries = self._root.EndianElf.DynamicSectionEntry(self._io, self, self._root, self._is_le)
+ _t_entries._read()
+ self.entries.append(_t_entries)
+ self._debug['entries']['arr'][len(self.entries) - 1]['end'] = self._io.pos()
+ i += 1
+
+ self._debug['entries']['end'] = self._io.pos()
+
+
+ class DynsymSection(KaitaiStruct):
+ SEQ_FIELDS = ["entries"]
+ def __init__(self, _io, _parent=None, _root=None, _is_le=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._is_le = _is_le
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+
+ if self._is_le == True:
+ self._read_le()
+ elif self._is_le == False:
+ self._read_be()
+ else:
+ raise Exception("Unable to decide endianness")
+
+ def _read_le(self):
+ self._debug['entries']['start'] = self._io.pos()
+ self.entries = []
+ i = 0
+ while not self._io.is_eof():
+ if not 'arr' in self._debug['entries']:
+ self._debug['entries']['arr'] = []
+ self._debug['entries']['arr'].append({'start': self._io.pos()})
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ if not 'arr' in self._debug['entries']:
+ self._debug['entries']['arr'] = []
+ self._debug['entries']['arr'].append({'start': self._io.pos()})
+ _t_entries = self._root.EndianElf.DynsymSectionEntry32(self._io, self, self._root, self._is_le)
+ _t_entries._read()
+ self.entries.append(_t_entries)
+ self._debug['entries']['arr'][len(self.entries) - 1]['end'] = self._io.pos()
+ elif _on == self._root.Bits.b64:
+ if not 'arr' in self._debug['entries']:
+ self._debug['entries']['arr'] = []
+ self._debug['entries']['arr'].append({'start': self._io.pos()})
+ _t_entries = self._root.EndianElf.DynsymSectionEntry64(self._io, self, self._root, self._is_le)
+ _t_entries._read()
+ self.entries.append(_t_entries)
+ self._debug['entries']['arr'][len(self.entries) - 1]['end'] = self._io.pos()
+ self._debug['entries']['arr'][len(self.entries) - 1]['end'] = self._io.pos()
+ i += 1
+
+ self._debug['entries']['end'] = self._io.pos()
+
+ def _read_be(self):
+ self._debug['entries']['start'] = self._io.pos()
+ self.entries = []
+ i = 0
+ while not self._io.is_eof():
+ if not 'arr' in self._debug['entries']:
+ self._debug['entries']['arr'] = []
+ self._debug['entries']['arr'].append({'start': self._io.pos()})
+ _on = self._root.bits
+ if _on == self._root.Bits.b32:
+ if not 'arr' in self._debug['entries']:
+ self._debug['entries']['arr'] = []
+ self._debug['entries']['arr'].append({'start': self._io.pos()})
+ _t_entries = self._root.EndianElf.DynsymSectionEntry32(self._io, self, self._root, self._is_le)
+ _t_entries._read()
+ self.entries.append(_t_entries)
+ self._debug['entries']['arr'][len(self.entries) - 1]['end'] = self._io.pos()
+ elif _on == self._root.Bits.b64:
+ if not 'arr' in self._debug['entries']:
+ self._debug['entries']['arr'] = []
+ self._debug['entries']['arr'].append({'start': self._io.pos()})
+ _t_entries = self._root.EndianElf.DynsymSectionEntry64(self._io, self, self._root, self._is_le)
+ _t_entries._read()
+ self.entries.append(_t_entries)
+ self._debug['entries']['arr'][len(self.entries) - 1]['end'] = self._io.pos()
+ self._debug['entries']['arr'][len(self.entries) - 1]['end'] = self._io.pos()
+ i += 1
+
+ self._debug['entries']['end'] = self._io.pos()
+
+
+ class DynsymSectionEntry32(KaitaiStruct):
+ SEQ_FIELDS = ["name_offset", "value", "size", "info", "other", "shndx"]
+ def __init__(self, _io, _parent=None, _root=None, _is_le=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._is_le = _is_le
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+
+ if self._is_le == True:
+ self._read_le()
+ elif self._is_le == False:
+ self._read_be()
+ else:
+ raise Exception("Unable to decide endianness")
+
+ def _read_le(self):
+ self._debug['name_offset']['start'] = self._io.pos()
+ self.name_offset = self._io.read_u4le()
+ self._debug['name_offset']['end'] = self._io.pos()
+ self._debug['value']['start'] = self._io.pos()
+ self.value = self._io.read_u4le()
+ self._debug['value']['end'] = self._io.pos()
+ self._debug['size']['start'] = self._io.pos()
+ self.size = self._io.read_u4le()
+ self._debug['size']['end'] = self._io.pos()
+ self._debug['info']['start'] = self._io.pos()
+ self.info = self._io.read_u1()
+ self._debug['info']['end'] = self._io.pos()
+ self._debug['other']['start'] = self._io.pos()
+ self.other = self._io.read_u1()
+ self._debug['other']['end'] = self._io.pos()
+ self._debug['shndx']['start'] = self._io.pos()
+ self.shndx = self._io.read_u2le()
+ self._debug['shndx']['end'] = self._io.pos()
+
+ def _read_be(self):
+ self._debug['name_offset']['start'] = self._io.pos()
+ self.name_offset = self._io.read_u4be()
+ self._debug['name_offset']['end'] = self._io.pos()
+ self._debug['value']['start'] = self._io.pos()
+ self.value = self._io.read_u4be()
+ self._debug['value']['end'] = self._io.pos()
+ self._debug['size']['start'] = self._io.pos()
+ self.size = self._io.read_u4be()
+ self._debug['size']['end'] = self._io.pos()
+ self._debug['info']['start'] = self._io.pos()
+ self.info = self._io.read_u1()
+ self._debug['info']['end'] = self._io.pos()
+ self._debug['other']['start'] = self._io.pos()
+ self.other = self._io.read_u1()
+ self._debug['other']['end'] = self._io.pos()
+ self._debug['shndx']['start'] = self._io.pos()
+ self.shndx = self._io.read_u2be()
+ self._debug['shndx']['end'] = self._io.pos()
+
+
+ class StringsStruct(KaitaiStruct):
+ SEQ_FIELDS = ["entries"]
+ def __init__(self, _io, _parent=None, _root=None, _is_le=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._is_le = _is_le
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+
+ if self._is_le == True:
+ self._read_le()
+ elif self._is_le == False:
+ self._read_be()
+ else:
+ raise Exception("Unable to decide endianness")
+
+ def _read_le(self):
+ self._debug['entries']['start'] = self._io.pos()
+ self.entries = []
+ i = 0
+ while not self._io.is_eof():
+ if not 'arr' in self._debug['entries']:
+ self._debug['entries']['arr'] = []
+ self._debug['entries']['arr'].append({'start': self._io.pos()})
+ self.entries.append((self._io.read_bytes_term(0, False, True, True)).decode(u"ASCII"))
+ self._debug['entries']['arr'][len(self.entries) - 1]['end'] = self._io.pos()
+ i += 1
+
+ self._debug['entries']['end'] = self._io.pos()
+
+ def _read_be(self):
+ self._debug['entries']['start'] = self._io.pos()
+ self.entries = []
+ i = 0
+ while not self._io.is_eof():
+ if not 'arr' in self._debug['entries']:
+ self._debug['entries']['arr'] = []
+ self._debug['entries']['arr'].append({'start': self._io.pos()})
+ self.entries.append((self._io.read_bytes_term(0, False, True, True)).decode(u"ASCII"))
+ self._debug['entries']['arr'][len(self.entries) - 1]['end'] = self._io.pos()
+ i += 1
+
+ self._debug['entries']['end'] = self._io.pos()
+
+
+ @property
+ def program_headers(self):
+ if hasattr(self, '_m_program_headers'):
+ return self._m_program_headers if hasattr(self, '_m_program_headers') else None
+
+ _pos = self._io.pos()
+ self._io.seek(self.program_header_offset)
+ self._debug['_m_program_headers']['start'] = self._io.pos()
+ if self._is_le:
+ self._raw__m_program_headers = [None] * (self.qty_program_header)
+ self._m_program_headers = [None] * (self.qty_program_header)
+ for i in range(self.qty_program_header):
+ if not 'arr' in self._debug['_m_program_headers']:
+ self._debug['_m_program_headers']['arr'] = []
+ self._debug['_m_program_headers']['arr'].append({'start': self._io.pos()})
+ self._raw__m_program_headers[i] = self._io.read_bytes(self.program_header_entry_size)
+ io = KaitaiStream(BytesIO(self._raw__m_program_headers[i]))
+ _t__m_program_headers = self._root.EndianElf.ProgramHeader(io, self, self._root, self._is_le)
+ _t__m_program_headers._read()
+ self._m_program_headers[i] = _t__m_program_headers
+ self._debug['_m_program_headers']['arr'][i]['end'] = self._io.pos()
+
+ else:
+ self._raw__m_program_headers = [None] * (self.qty_program_header)
+ self._m_program_headers = [None] * (self.qty_program_header)
+ for i in range(self.qty_program_header):
+ if not 'arr' in self._debug['_m_program_headers']:
+ self._debug['_m_program_headers']['arr'] = []
+ self._debug['_m_program_headers']['arr'].append({'start': self._io.pos()})
+ self._raw__m_program_headers[i] = self._io.read_bytes(self.program_header_entry_size)
+ io = KaitaiStream(BytesIO(self._raw__m_program_headers[i]))
+ _t__m_program_headers = self._root.EndianElf.ProgramHeader(io, self, self._root, self._is_le)
+ _t__m_program_headers._read()
+ self._m_program_headers[i] = _t__m_program_headers
+ self._debug['_m_program_headers']['arr'][i]['end'] = self._io.pos()
+
+ self._debug['_m_program_headers']['end'] = self._io.pos()
+ self._io.seek(_pos)
+ return self._m_program_headers if hasattr(self, '_m_program_headers') else None
+
+ @property
+ def section_headers(self):
+ if hasattr(self, '_m_section_headers'):
+ return self._m_section_headers if hasattr(self, '_m_section_headers') else None
+
+ _pos = self._io.pos()
+ self._io.seek(self.section_header_offset)
+ self._debug['_m_section_headers']['start'] = self._io.pos()
+ if self._is_le:
+ self._raw__m_section_headers = [None] * (self.qty_section_header)
+ self._m_section_headers = [None] * (self.qty_section_header)
+ for i in range(self.qty_section_header):
+ if not 'arr' in self._debug['_m_section_headers']:
+ self._debug['_m_section_headers']['arr'] = []
+ self._debug['_m_section_headers']['arr'].append({'start': self._io.pos()})
+ self._raw__m_section_headers[i] = self._io.read_bytes(self.section_header_entry_size)
+ io = KaitaiStream(BytesIO(self._raw__m_section_headers[i]))
+ _t__m_section_headers = self._root.EndianElf.SectionHeader(io, self, self._root, self._is_le)
+ _t__m_section_headers._read()
+ self._m_section_headers[i] = _t__m_section_headers
+ self._debug['_m_section_headers']['arr'][i]['end'] = self._io.pos()
+
+ else:
+ self._raw__m_section_headers = [None] * (self.qty_section_header)
+ self._m_section_headers = [None] * (self.qty_section_header)
+ for i in range(self.qty_section_header):
+ if not 'arr' in self._debug['_m_section_headers']:
+ self._debug['_m_section_headers']['arr'] = []
+ self._debug['_m_section_headers']['arr'].append({'start': self._io.pos()})
+ self._raw__m_section_headers[i] = self._io.read_bytes(self.section_header_entry_size)
+ io = KaitaiStream(BytesIO(self._raw__m_section_headers[i]))
+ _t__m_section_headers = self._root.EndianElf.SectionHeader(io, self, self._root, self._is_le)
+ _t__m_section_headers._read()
+ self._m_section_headers[i] = _t__m_section_headers
+ self._debug['_m_section_headers']['arr'][i]['end'] = self._io.pos()
+
+ self._debug['_m_section_headers']['end'] = self._io.pos()
+ self._io.seek(_pos)
+ return self._m_section_headers if hasattr(self, '_m_section_headers') else None
+
+ @property
+ def strings(self):
+ if hasattr(self, '_m_strings'):
+ return self._m_strings if hasattr(self, '_m_strings') else None
+
+ _pos = self._io.pos()
+ self._io.seek(self.section_headers[self.section_names_idx].ofs_body)
+ self._debug['_m_strings']['start'] = self._io.pos()
+ if self._is_le:
+ self._raw__m_strings = self._io.read_bytes(self.section_headers[self.section_names_idx].len_body)
+ io = KaitaiStream(BytesIO(self._raw__m_strings))
+ self._m_strings = self._root.EndianElf.StringsStruct(io, self, self._root, self._is_le)
+ self._m_strings._read()
+ else:
+ self._raw__m_strings = self._io.read_bytes(self.section_headers[self.section_names_idx].len_body)
+ io = KaitaiStream(BytesIO(self._raw__m_strings))
+ self._m_strings = self._root.EndianElf.StringsStruct(io, self, self._root, self._is_le)
+ self._m_strings._read()
+ self._debug['_m_strings']['end'] = self._io.pos()
+ self._io.seek(_pos)
+ return self._m_strings if hasattr(self, '_m_strings') else None
+
+
+
diff --git a/python/examples/kaitai/kaitaistruct.py b/python/examples/kaitai/kaitaistruct.py
new file mode 100644
index 00000000..4d588b9f
--- /dev/null
+++ b/python/examples/kaitai/kaitaistruct.py
@@ -0,0 +1,379 @@
+import itertools
+import sys
+import struct
+from io import BytesIO, SEEK_CUR, SEEK_END # noqa
+
+PY2 = sys.version_info[0] == 2
+
+# Kaitai Struct runtime streaming API version, defined as per PEP-0396
+# standard. Used for two purposes:
+#
+# * .py files generated by ksc from .ksy check that they import proper
+# KS runtime library by this version number;
+# * distribution utils (setup.py) use this when packaging for PyPI
+#
+__version__ = '0.8'
+
+
+class KaitaiStruct(object):
+ def __init__(self, stream):
+ self._io = stream
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *args, **kwargs):
+ self.close()
+
+ def close(self):
+ self._io.close()
+
+ @classmethod
+ def from_file(cls, filename):
+ f = open(filename, 'rb')
+ try:
+ return cls(KaitaiStream(f))
+ except Exception:
+ # close file descriptor, then reraise the exception
+ f.close()
+ raise
+
+ @classmethod
+ def from_bytes(cls, buf):
+ return cls(KaitaiStream(BytesIO(buf)))
+
+ @classmethod
+ def from_io(cls, io):
+ return cls(KaitaiStream(io))
+
+
+class KaitaiStream(object):
+ def __init__(self, io):
+ self._io = io
+ self.align_to_byte()
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *args, **kwargs):
+ self.close()
+
+ def close(self):
+ self._io.close()
+
+ # ========================================================================
+ # Stream positioning
+ # ========================================================================
+
+ def is_eof(self):
+ io = self._io
+ t = io.read(1)
+ if t == b'':
+ return True
+ else:
+ io.seek(-1, SEEK_CUR)
+ return False
+
+ def seek(self, n):
+ self._io.seek(n)
+
+ def pos(self):
+ return self._io.tell()
+
+ def size(self):
+ # Python has no internal File object API function to get
+ # current file / StringIO size, thus we use the following
+ # trick.
+ io = self._io
+ # Remember our current position
+ cur_pos = io.tell()
+ # Seek to the end of the File object
+ io.seek(0, SEEK_END)
+ # Remember position, which is equal to the full length
+ full_size = io.tell()
+ # Seek back to the current position
+ io.seek(cur_pos)
+ return full_size
+
+ # ========================================================================
+ # Integer numbers
+ # ========================================================================
+
+ packer_s1 = struct.Struct('b')
+ packer_s2be = struct.Struct('>h')
+ packer_s4be = struct.Struct('>i')
+ packer_s8be = struct.Struct('>q')
+ packer_s2le = struct.Struct('<h')
+ packer_s4le = struct.Struct('<i')
+ packer_s8le = struct.Struct('<q')
+
+ packer_u1 = struct.Struct('B')
+ packer_u2be = struct.Struct('>H')
+ packer_u4be = struct.Struct('>I')
+ packer_u8be = struct.Struct('>Q')
+ packer_u2le = struct.Struct('<H')
+ packer_u4le = struct.Struct('<I')
+ packer_u8le = struct.Struct('<Q')
+
+ # ------------------------------------------------------------------------
+ # Signed
+ # ------------------------------------------------------------------------
+
+ def read_s1(self):
+ return KaitaiStream.packer_s1.unpack(self.read_bytes(1))[0]
+
+ # ........................................................................
+ # Big-endian
+ # ........................................................................
+
+ def read_s2be(self):
+ return KaitaiStream.packer_s2be.unpack(self.read_bytes(2))[0]
+
+ def read_s4be(self):
+ return KaitaiStream.packer_s4be.unpack(self.read_bytes(4))[0]
+
+ def read_s8be(self):
+ return KaitaiStream.packer_s8be.unpack(self.read_bytes(8))[0]
+
+ # ........................................................................
+ # Little-endian
+ # ........................................................................
+
+ def read_s2le(self):
+ return KaitaiStream.packer_s2le.unpack(self.read_bytes(2))[0]
+
+ def read_s4le(self):
+ return KaitaiStream.packer_s4le.unpack(self.read_bytes(4))[0]
+
+ def read_s8le(self):
+ return KaitaiStream.packer_s8le.unpack(self.read_bytes(8))[0]
+
+ # ------------------------------------------------------------------------
+ # Unsigned
+ # ------------------------------------------------------------------------
+
+ def read_u1(self):
+ return KaitaiStream.packer_u1.unpack(self.read_bytes(1))[0]
+
+ # ........................................................................
+ # Big-endian
+ # ........................................................................
+
+ def read_u2be(self):
+ return KaitaiStream.packer_u2be.unpack(self.read_bytes(2))[0]
+
+ def read_u4be(self):
+ return KaitaiStream.packer_u4be.unpack(self.read_bytes(4))[0]
+
+ def read_u8be(self):
+ return KaitaiStream.packer_u8be.unpack(self.read_bytes(8))[0]
+
+ # ........................................................................
+ # Little-endian
+ # ........................................................................
+
+ def read_u2le(self):
+ return KaitaiStream.packer_u2le.unpack(self.read_bytes(2))[0]
+
+ def read_u4le(self):
+ return KaitaiStream.packer_u4le.unpack(self.read_bytes(4))[0]
+
+ def read_u8le(self):
+ return KaitaiStream.packer_u8le.unpack(self.read_bytes(8))[0]
+
+ # ========================================================================
+ # Floating point numbers
+ # ========================================================================
+
+ packer_f4be = struct.Struct('>f')
+ packer_f8be = struct.Struct('>d')
+ packer_f4le = struct.Struct('<f')
+ packer_f8le = struct.Struct('<d')
+
+ # ........................................................................
+ # Big-endian
+ # ........................................................................
+
+ def read_f4be(self):
+ return KaitaiStream.packer_f4be.unpack(self.read_bytes(4))[0]
+
+ def read_f8be(self):
+ return KaitaiStream.packer_f8be.unpack(self.read_bytes(8))[0]
+
+ # ........................................................................
+ # Little-endian
+ # ........................................................................
+
+ def read_f4le(self):
+ return KaitaiStream.packer_f4le.unpack(self.read_bytes(4))[0]
+
+ def read_f8le(self):
+ return KaitaiStream.packer_f8le.unpack(self.read_bytes(8))[0]
+
+ # ========================================================================
+ # Unaligned bit values
+ # ========================================================================
+
+ def align_to_byte(self):
+ self.bits = 0
+ self.bits_left = 0
+
+ def read_bits_int(self, n):
+ bits_needed = n - self.bits_left
+ if bits_needed > 0:
+ # 1 bit => 1 byte
+ # 8 bits => 1 byte
+ # 9 bits => 2 bytes
+ bytes_needed = ((bits_needed - 1) // 8) + 1
+ buf = self.read_bytes(bytes_needed)
+ for byte in buf:
+ # Python 2 will get "byte" as one-character str, thus
+ # we need to convert it to integer manually; Python 3
+ # is fine as is.
+ if isinstance(byte, str):
+ byte = ord(byte)
+ self.bits <<= 8
+ self.bits |= byte
+ self.bits_left += 8
+
+ # raw mask with required number of 1s, starting from lowest bit
+ mask = (1 << n) - 1
+ # shift mask to align with highest bits available in self.bits
+ shift_bits = self.bits_left - n
+ mask <<= shift_bits
+ # derive reading result
+ res = (self.bits & mask) >> shift_bits
+ # clear top bits that we've just read => AND with 1s
+ self.bits_left -= n
+ mask = (1 << self.bits_left) - 1
+ self.bits &= mask
+
+ return res
+
+ # ========================================================================
+ # Byte arrays
+ # ========================================================================
+
+ def read_bytes(self, n):
+ if n < 0:
+ raise ValueError(
+ "requested invalid %d amount of bytes" %
+ (n,)
+ )
+ r = self._io.read(n)
+ if len(r) < n:
+ raise EOFError(
+ "requested %d bytes, but got only %d bytes" %
+ (n, len(r))
+ )
+ return r
+
+ def read_bytes_full(self):
+ return self._io.read()
+
+ def read_bytes_term(self, term, include_term, consume_term, eos_error):
+ r = b''
+ while True:
+ c = self._io.read(1)
+ if c == b'':
+ if eos_error:
+ raise Exception(
+ "end of stream reached, but no terminator %d found" %
+ (term,)
+ )
+ else:
+ return r
+ elif ord(c) == term:
+ if include_term:
+ r += c
+ if not consume_term:
+ self._io.seek(-1, SEEK_CUR)
+ return r
+ else:
+ r += c
+
+ def ensure_fixed_contents(self, expected):
+ actual = self._io.read(len(expected))
+ if actual != expected:
+ raise Exception(
+ "unexpected fixed contents: got %r, was waiting for %r" %
+ (actual, expected)
+ )
+ return actual
+
+ @staticmethod
+ def bytes_strip_right(data, pad_byte):
+ new_len = len(data)
+ if PY2:
+ # data[...] must yield an integer, to compare with integer pad_byte
+ data = bytearray(data)
+
+ while new_len > 0 and data[new_len - 1] == pad_byte:
+ new_len -= 1
+
+ return data[:new_len]
+
+ @staticmethod
+ def bytes_terminate(data, term, include_term):
+ new_len = 0
+ max_len = len(data)
+ if PY2:
+ # data[...] must yield an integer, to compare with integer term
+ data = bytearray(data)
+
+ while new_len < max_len and data[new_len] != term:
+ new_len += 1
+
+ if include_term and new_len < max_len:
+ new_len += 1
+
+ return data[:new_len]
+
+ # ========================================================================
+ # Byte array processing
+ # ========================================================================
+
+ @staticmethod
+ def process_xor_one(data, key):
+ if PY2:
+ return bytes(bytearray(v ^ key for v in bytearray(data)))
+ else:
+ return bytes(v ^ key for v in data)
+
+ @staticmethod
+ def process_xor_many(data, key):
+ if PY2:
+ return bytes(bytearray(a ^ b for a, b in zip(bytearray(data), itertools.cycle(bytearray(key)))))
+ else:
+ return bytes(a ^ b for a, b in zip(data, itertools.cycle(key)))
+
+ @staticmethod
+ def process_rotate_left(data, amount, group_size):
+ if group_size != 1:
+ raise Exception(
+ "unable to rotate group of %d bytes yet" %
+ (group_size,)
+ )
+
+ mask = group_size * 8 - 1
+ anti_amount = -amount & mask
+
+ r = bytearray(data)
+ for i in range(len(r)):
+ r[i] = (r[i] << amount) & 0xff | (r[i] >> anti_amount)
+ return bytes(r)
+
+ # ========================================================================
+ # Misc
+ # ========================================================================
+
+ @staticmethod
+ def resolve_enum(enum_obj, value):
+ """Resolves value using enum: if the value is not found in the map,
+ we'll just use literal value per se. Works around problem with Python
+ enums throwing an exception when encountering unknown value.
+ """
+ try:
+ return enum_obj(value)
+ except ValueError:
+ return value
diff --git a/python/examples/kaitai/kshelpers.py b/python/examples/kaitai/kshelpers.py
new file mode 100755
index 00000000..374a1e77
--- /dev/null
+++ b/python/examples/kaitai/kshelpers.py
@@ -0,0 +1,450 @@
+#!/usr/bin/env python
+
+import io
+import sys
+import types
+
+import binaryninja
+
+from PySide2.QtCore import Qt
+from PySide2.QtWidgets import QTreeWidgetItem
+
+from kaitaistruct import KaitaiStruct
+
+#------------------------------------------------------------------------------
+# id and parse
+#------------------------------------------------------------------------------
+
+def id_data(data):
+ if len(data) < 4:
+ return None
+
+ if data[0:4] == "\x7fELF":
+ return 'elf'
+ elif data[0:4] in ['\xfe\xed\xfa\xce', '\xce\xfa\xed\xfe', '\xfe\xed\xfa\xcf', '\xcf\xfa\xed\xfe']:
+ return 'macho'
+ elif data[0:2] == 'MZ':
+ return 'pe'
+
+ return None
+
+def id_file(fpath):
+ data = None
+ with open(fpath, 'rb') as fp:
+ data = fp.read(16)
+ return id_data(data)
+
+def getKaitaiModuleFromFileType(ftype):
+ if ftype == 'elf':
+ from elf import Elf
+ return Elf
+ elif ftype == 'macho':
+ from mach_o import MachO
+ return MachO
+ elif ftype == 'pe':
+ from microsoft_pe import MicrosoftPe
+ return MicrosoftPe
+
+ return None
+
+def parse_fpath(fpath):
+ kaitaiModule = getKaitaiModuleFromFileType(id_file(fpath))
+ if not kaitaiModule: return None
+ parsed = kaitaiModule.from_file(fpath)
+ parsed._read()
+ return parsed
+
+def parse_data(data):
+ kaitaiModule = getKaitaiModuleFromFileType(id_data(data))
+ if not kaitaiModule: return None
+ parsed = kaitaiModule.from_bytes(data)
+ parsed._read()
+ return parsed
+
+def parse_io(ioObj):
+ ioObj.seek(0, io.SEEK_SET)
+ kaitaiModule = getKaitaiModuleFromFileType(id_data(ioObj.read(16)))
+ ioObj.seek(0, io.SEEK_SET)
+ if not kaitaiModule:
+ print 'ERROR: finding suitable kaitai module'
+ return None
+ parsed = kaitaiModule.from_io(ioObj)
+ parsed._read()
+ return parsed
+
+#------------------------------------------------------------------------------
+# Kaitai IO Wrapper
+#------------------------------------------------------------------------------
+
+# wraps a BinaryView into an "IO" that KaitaiStream can use
+#
+# now Kaitai can parse directly from the BinaryView and we can avoid making a
+# potentially giant copy of the file contents just for kaitai parsing
+#
+class KaitaiBinaryViewIO:
+ def __init__(self, binaryView):
+ self.binaryView = binaryView
+ self.position = 0
+
+ def seek(self, offs, whence=io.SEEK_SET):
+ #print 'seek(0x%X, %d)' % (offs, whence)
+ if whence == io.SEEK_SET:
+ self.position = offs
+ elif whence == io.SEEK_CUR:
+ self.position += offs
+ elif whence == io.SEEK_END:
+ self.position = len(self.binaryView)
+ else:
+ raise Exception('unknown whence in seek(): %d' % whence)
+
+ def tell(self):
+ #print 'tell() returning 0x%X' % (self.position)
+ return self.position
+
+ def read(self, length):
+ #print 'read(%d) (starting at position: 0x%X)' % (length, self.position)
+ data = self.binaryView.read(self.position, length)
+ self.position += length
+ return data
+
+ def close(self):
+ pass
+
+#------------------------------------------------------------------------------
+# text dump/debug testing stuff
+#------------------------------------------------------------------------------
+
+def dump(obj, depth=0):
+ dump_exceptions = ['_root', '_parent', '_io']
+
+ indent = ' '*depth
+
+ if isinstance(obj, KaitaiStruct):
+ for fieldName in dir(obj):
+ if hasattr(obj, fieldName):
+ getattr(obj, fieldName)
+
+ for fieldName in dir(obj):
+ #print 'considering field: %s (hasattr returns: %d)' % (fieldName, hasattr(obj, fieldName))
+ if (fieldName != '_debug' and fieldName.startswith('_')) or fieldName in dump_exceptions or not hasattr(obj, fieldName):
+ continue
+
+ #print 'A: %s' % fieldName
+
+ subObj = getattr(obj, fieldName)
+
+ if type(subObj) == types.MethodType:
+ pass
+ elif type(subObj) == types.TypeType:
+ pass
+ elif type(subObj) == types.ListType:
+ if len(subObj)>0 and isinstance(subObj[0], KaitaiStruct):
+ for i in range(len(subObj)):
+ print '%s.%s[%d]:' % (indent, fieldName, i)
+ dump(subObj[i], depth+1)
+ else:
+ print '%s.%s: %s' % (indent, fieldName, str(subObj))
+ elif type(subObj) == types.DictionaryType:
+ print '%s.%s: %s' % (indent, fieldName, subObj)
+
+ elif type(subObj) == types.StringType:
+ print '%s.%s: %s' % (indent, fieldName, repr(subObj))
+
+ elif type(subObj) == int:
+ print '%s.%s: 0x%X (%d)' % (indent, fieldName, subObj, subObj)
+
+ elif str(type(subObj)).startswith('<enum '):
+ print '%s.%s: %s' % (indent, fieldName, repr(subObj))
+
+ elif isinstance(subObj, KaitaiStruct):
+ print '%s.%s:' % (indent, fieldName)
+ dump(subObj, depth+1)
+
+ elif fieldName == '_debug':
+ print '%s._debug: %s' % (indent, repr(subObj))
+ else:
+ print '%s.%s: %s' % (indent, fieldName, type(subObj))
+ else:
+ print indent + repr(obj)
+ #else:
+ # print '%s%s: %s' % (indent, fieldName, repr(subObj))
+
+#------------------------------------------------------------------------------
+# Qt/Kaitai OOP
+#------------------------------------------------------------------------------
+
+# why subclass?
+# - override "<" to get sorting to work right
+# - setLabel(), setValue(), etc. conveniences
+# - centralized location to modify field names and labels (eg: remove '_m_')
+
+class KaitaiTreeWidgetItem(QTreeWidgetItem):
+ def __init__(self, parent=None, data=[None,None,None,None]):
+ QTreeWidgetItem.__init__(self, parent, data)
+
+ self.label = None # string
+ self.value = None # string
+ self.start = None # int
+ self.end = None # int
+ self.ksobj = None # KaitaiStruct
+
+ def __lt__(self, otherItem):
+ column = self.treeWidget().sortColumn()
+
+ lhsText = self.text(column)
+ rhsText = otherItem.text(column)
+
+ if not lhsText:
+ return False
+ if not rhsText:
+ return True
+
+ try:
+ return int(lhsText,16) < int(rhsText, 16)
+ except:
+ return lhsText.__lt__(rhsText)
+
+ def setLabel(self, label):
+ self.label = label
+ if label.startswith('_m_'):
+ label = label[3:]
+ self.setData(0, Qt.DisplayRole, label)
+
+ def setValue(self, value):
+ self.value = value
+ if type(value) == types.IntType:
+ value = '%X'%value
+ self.setData(1, Qt.DisplayRole, value)
+
+ def setStart(self, start):
+ if start == None:
+ self.start = None
+ elif type(start) in [types.IntType, types.LongType]:
+ self.start = start
+ start = '%X'%start
+ else:
+ self.start = int(start,16)
+
+ self.setData(2, Qt.DisplayRole, start)
+
+ def setEnd(self, end):
+ if end == None:
+ self.end = None
+ elif type(end) in [types.IntType, types.LongType]:
+ self.end = end
+ end = '%X'%end
+ else:
+ self.end = int(end,16)
+ self.setData(3, Qt.DisplayRole, end)
+
+ def setKaitaiObject(self, ksobj):
+ self.ksobj = ksobj
+ self.setData(0, Qt.UserRole, ksobj)
+
+ def __str__(self):
+ result = 'label=%s: value=%s range=[%s,%s)' % \
+ (self.label, self.value, self.start, self.end)
+
+ result += ' ksobj=%s' % self.ksobj
+
+ if self.ksobj:
+ result += ' io=%s' % self.ksobj._io
+
+ #if self.parent:
+ # result += ' parent=%s' % self.ksobj.parent
+
+ return result
+
+ def __str_short__(self):
+ return '[%s,%s) %s' % (repr(self.start), repr(self.end), repr(self.label))
+
+#------------------------------------------------------------------------------
+# build QTree and helpers
+#------------------------------------------------------------------------------
+
+# ARGS:
+# obj: KaitaiStruct
+# RETURNS:
+# KaitaiTreeWidgetItem (QTreeWidgetItem)
+#
+def build_qtree(ksobj):
+ if not isinstance(ksobj, KaitaiStruct):
+ return None
+
+ exceptions = ['_root', '_parent', '_io', 'SEQ_FIELDS', '_debug']
+
+ qwi = KaitaiTreeWidgetItem()
+ qwi.setKaitaiObject(ksobj)
+
+ for fieldName in dir(ksobj):
+ if hasattr(ksobj, fieldName):
+ getattr(ksobj, fieldName)
+
+ fields = dir(ksobj)
+ for fieldName in fields:
+ if fieldName.startswith('_') and (not fieldName.startswith('_m_')):
+ continue
+ if fieldName in exceptions:
+ continue
+ if not hasattr(ksobj, fieldName):
+ continue
+ if ('_m_'+fieldName) in fields:
+ # favor the '_m_' version which seems to get the debug info
+ continue
+
+ subObj = getattr(ksobj, fieldName)
+ subObjType = type(subObj)
+
+ child = None
+ if isinstance(subObj, KaitaiStruct):
+ fieldLabel = fieldName
+ child = build_qtree(subObj)
+ if child:
+ populate_child(ksobj, fieldName, fieldName, None, child)
+ qwi.addChild(child)
+
+ elif subObjType == types.ListType and len(subObj)>0:
+ # CASE: is list of KaitaiObjects -> recurse!
+ if isinstance(subObj[0], KaitaiStruct):
+ child = KaitaiTreeWidgetItem()
+ populate_child(ksobj, fieldName, fieldName, None, child)
+
+ # does _debug have an array version of start/end?
+ startsEnds = None
+ if hasattr(ksobj, '_debug'):
+ if fieldName in ksobj._debug:
+ if 'arr' in ksobj._debug[fieldName]:
+ startsEnds = ksobj._debug[fieldName]['arr']
+
+ for i in range(len(subObj)):
+ grandchild = build_qtree(subObj[i])
+ fieldLabel = '%s[%d]' % (fieldName, i)
+ grandchild.setLabel(fieldLabel)
+
+ if startsEnds:
+ grandchild.setStart(startsEnds[i]['start'])
+ grandchild.setEnd(startsEnds[i]['end'])
+
+ child.addChild(grandchild)
+
+ qwi.addChild(child)
+
+ # CASE: is list of primitive objects -> create leaves
+ else:
+ child = KaitaiTreeWidgetItem()
+ populate_child(ksobj, fieldName, fieldName, None, child)
+
+ # TODO: explain this hack
+ kstmp = KaitaiStruct(ksobj._io)
+ kstmp._parent = ksobj
+ child.setKaitaiObject(kstmp)
+
+ # does _debug have an array version of start/end?
+ startsEnds = None
+ if hasattr(ksobj, '_debug'):
+ if fieldName in ksobj._debug:
+ if 'arr' in ksobj._debug[fieldName]:
+ startsEnds = ksobj._debug[fieldName]['arr']
+
+ for i in range(len(subObj)):
+ grandchild = createLeaf('%s[%d]'%(fieldName,i), subObj[i])
+ if not grandchild:
+ continue
+
+ if startsEnds:
+ grandchild.setStart(startsEnds[i]['start'])
+ grandchild.setEnd(startsEnds[i]['end'])
+
+ child.addChild(grandchild)
+
+ qwi.addChild(child)
+ else:
+ child = createLeaf(fieldName, subObj)
+ if child:
+ # don't override createLeaf()'s work on label, value
+ populate_child(ksobj, fieldName, None, None, child)
+ qwi.addChild(child)
+
+ return qwi
+
+def createLeaf(fieldName, obj):
+ objtype = type(obj)
+
+ if objtype == types.MethodType:
+ return None
+ elif objtype == types.TypeType:
+ return None
+
+ fieldValue = None
+
+ if objtype in [types.StringType, types.UnicodeType]:
+ #if filter(lambda c: c<32 or c>127, obj):
+ fieldValue = repr(obj)
+ elif objtype == types.IntType:
+ fieldValue = '0x%X (%d)' % (obj, obj)
+ elif objtype == types.BooleanType:
+ fieldValue = '%s' % (obj)
+ elif str(objtype).startswith('<enum '):
+ fieldValue = '%s' % (obj)
+ else:
+ #print 'field %s has type: -%s-' % (fieldName,str(objtype))
+ pass
+
+ if fieldValue:
+ widget = KaitaiTreeWidgetItem()
+ widget.setLabel(fieldName)
+ widget.setValue(fieldValue)
+ return widget
+ else:
+ return None
+
+# ARG TYPE NOTES
+# ksobj: KaitaiStruct the current one we're on
+# fieldName: string actual field name inside the kaitai struct
+# fieldLabel: string label used in the tree view
+# fieldValue: string value used in the tree view
+# widget: KaitaiTreeWidgetItem the item to which we want to imprint start/end
+def populate_child(ksobj, fieldName, fieldLabel, fieldValue, widget):
+ if fieldLabel:
+ widget.setLabel(fieldLabel)
+ #print 'setting Label: %s' % fieldLabel
+ if fieldValue:
+ widget.setValue(fieldValue)
+
+ if (not ksobj) or (not hasattr(ksobj, '_debug')):
+ return
+
+ start = None
+ if 'start' in ksobj._debug[fieldName]:
+ start = ksobj._debug[fieldName]['start']
+
+ end = None
+ if 'end' in ksobj._debug[fieldName]:
+ end = ksobj._debug[fieldName]['end']
+
+ if start != None:
+ widget.setStart(start)
+ if end != None:
+ widget.setEnd(end)
+
+#------------------------------------------------------------------------------
+# main() - for dev testing
+#------------------------------------------------------------------------------
+
+if __name__ == '__main__':
+ if not sys.argv[2:]:
+ sys.exit(-1)
+
+ cmd = sys.argv[1]
+ fpath = sys.argv[2]
+
+ if cmd == 'dump':
+ parsed = parse_fpath(sys.argv[2])
+ print parsed.header.program_headers
+
+ elif cmd == 'dumpbinja':
+ binaryView = binaryninja.BinaryViewType['Raw'].open(fpath)
+ kaitaiIo = KaitaiBinaryViewIO(binaryView)
+ parsed = parse_io(kaitaiIo)
+ print parsed.header.program_headers
+
diff --git a/python/examples/kaitai/mach_o.py b/python/examples/kaitai/mach_o.py
new file mode 100644
index 00000000..ac517678
--- /dev/null
+++ b/python/examples/kaitai/mach_o.py
@@ -0,0 +1,2739 @@
+# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
+
+from pkg_resources import parse_version
+from kaitaistruct import __version__ as ks_version, KaitaiStruct, KaitaiStream, BytesIO
+from enum import Enum
+import collections
+
+
+if parse_version(ks_version) < parse_version('0.7'):
+ raise Exception("Incompatible Kaitai Struct Python API: 0.7 or later is required, but you have %s" % (ks_version))
+
+class MachO(KaitaiStruct):
+
+ class MagicType(Enum):
+ fat_le = 3199925962
+ fat_be = 3405691582
+ macho_le_x86 = 3472551422
+ macho_le_x64 = 3489328638
+ macho_be_x86 = 4277009102
+ macho_be_x64 = 4277009103
+
+ class CpuType(Enum):
+ vax = 1
+ romp = 2
+ ns32032 = 4
+ ns32332 = 5
+ i386 = 7
+ mips = 8
+ ns32532 = 9
+ hppa = 11
+ arm = 12
+ mc88000 = 13
+ sparc = 14
+ i860 = 15
+ i860_little = 16
+ rs6000 = 17
+ powerpc = 18
+ abi64 = 16777216
+ x86_64 = 16777223
+ arm64 = 16777228
+ powerpc64 = 16777234
+ any = 4294967295
+
+ class FileType(Enum):
+ object = 1
+ execute = 2
+ fvmlib = 3
+ core = 4
+ preload = 5
+ dylib = 6
+ dylinker = 7
+ bundle = 8
+ dylib_stub = 9
+ dsym = 10
+ kext_bundle = 11
+
+ class LoadCommandType(Enum):
+ segment = 1
+ symtab = 2
+ symseg = 3
+ thread = 4
+ unix_thread = 5
+ load_fvm_lib = 6
+ id_fvm_lib = 7
+ ident = 8
+ fvm_file = 9
+ prepage = 10
+ dysymtab = 11
+ load_dylib = 12
+ id_dylib = 13
+ load_dylinker = 14
+ id_dylinker = 15
+ prebound_dylib = 16
+ routines = 17
+ sub_framework = 18
+ sub_umbrella = 19
+ sub_client = 20
+ sub_library = 21
+ twolevel_hints = 22
+ prebind_cksum = 23
+ segment_64 = 25
+ routines_64 = 26
+ uuid = 27
+ code_signature = 29
+ segment_split_info = 30
+ lazy_load_dylib = 32
+ encryption_info = 33
+ dyld_info = 34
+ version_min_macosx = 36
+ version_min_iphoneos = 37
+ function_starts = 38
+ dyld_environment = 39
+ data_in_code = 41
+ source_version = 42
+ dylib_code_sign_drs = 43
+ encryption_info_64 = 44
+ linker_option = 45
+ linker_optimization_hint = 46
+ version_min_tvos = 47
+ version_min_watchos = 48
+ req_dyld = 2147483648
+ load_weak_dylib = 2147483672
+ rpath = 2147483676
+ reexport_dylib = 2147483679
+ dyld_info_only = 2147483682
+ load_upward_dylib = 2147483683
+ main = 2147483688
+ SEQ_FIELDS = ["magic", "header", "load_commands"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['magic']['start'] = self._io.pos()
+ self.magic = KaitaiStream.resolve_enum(self._root.MagicType, self._io.read_u4be())
+ self._debug['magic']['end'] = self._io.pos()
+ self._debug['header']['start'] = self._io.pos()
+ self.header = self._root.MachHeader(self._io, self, self._root)
+ self.header._read()
+ self._debug['header']['end'] = self._io.pos()
+ self._debug['load_commands']['start'] = self._io.pos()
+ self.load_commands = [None] * (self.header.ncmds)
+ for i in range(self.header.ncmds):
+ if not 'arr' in self._debug['load_commands']:
+ self._debug['load_commands']['arr'] = []
+ self._debug['load_commands']['arr'].append({'start': self._io.pos()})
+ _t_load_commands = self._root.LoadCommand(self._io, self, self._root)
+ _t_load_commands._read()
+ self.load_commands[i] = _t_load_commands
+ self._debug['load_commands']['arr'][i]['end'] = self._io.pos()
+
+ self._debug['load_commands']['end'] = self._io.pos()
+
+ class RpathCommand(KaitaiStruct):
+ SEQ_FIELDS = ["path_offset", "path"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['path_offset']['start'] = self._io.pos()
+ self.path_offset = self._io.read_u4le()
+ self._debug['path_offset']['end'] = self._io.pos()
+ self._debug['path']['start'] = self._io.pos()
+ self.path = (self._io.read_bytes_term(0, False, True, True)).decode(u"utf-8")
+ self._debug['path']['end'] = self._io.pos()
+
+
+ class Uleb128(KaitaiStruct):
+ SEQ_FIELDS = ["b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "b10"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['b1']['start'] = self._io.pos()
+ self.b1 = self._io.read_u1()
+ self._debug['b1']['end'] = self._io.pos()
+ if (self.b1 & 128) != 0:
+ self._debug['b2']['start'] = self._io.pos()
+ self.b2 = self._io.read_u1()
+ self._debug['b2']['end'] = self._io.pos()
+
+ if (self.b2 & 128) != 0:
+ self._debug['b3']['start'] = self._io.pos()
+ self.b3 = self._io.read_u1()
+ self._debug['b3']['end'] = self._io.pos()
+
+ if (self.b3 & 128) != 0:
+ self._debug['b4']['start'] = self._io.pos()
+ self.b4 = self._io.read_u1()
+ self._debug['b4']['end'] = self._io.pos()
+
+ if (self.b4 & 128) != 0:
+ self._debug['b5']['start'] = self._io.pos()
+ self.b5 = self._io.read_u1()
+ self._debug['b5']['end'] = self._io.pos()
+
+ if (self.b5 & 128) != 0:
+ self._debug['b6']['start'] = self._io.pos()
+ self.b6 = self._io.read_u1()
+ self._debug['b6']['end'] = self._io.pos()
+
+ if (self.b6 & 128) != 0:
+ self._debug['b7']['start'] = self._io.pos()
+ self.b7 = self._io.read_u1()
+ self._debug['b7']['end'] = self._io.pos()
+
+ if (self.b7 & 128) != 0:
+ self._debug['b8']['start'] = self._io.pos()
+ self.b8 = self._io.read_u1()
+ self._debug['b8']['end'] = self._io.pos()
+
+ if (self.b8 & 128) != 0:
+ self._debug['b9']['start'] = self._io.pos()
+ self.b9 = self._io.read_u1()
+ self._debug['b9']['end'] = self._io.pos()
+
+ if (self.b9 & 128) != 0:
+ self._debug['b10']['start'] = self._io.pos()
+ self.b10 = self._io.read_u1()
+ self._debug['b10']['end'] = self._io.pos()
+
+
+ @property
+ def value(self):
+ if hasattr(self, '_m_value'):
+ return self._m_value if hasattr(self, '_m_value') else None
+
+ self._m_value = (((self.b1 % 128) << 0) + (0 if (self.b1 & 128) == 0 else (((self.b2 % 128) << 7) + (0 if (self.b2 & 128) == 0 else (((self.b3 % 128) << 14) + (0 if (self.b3 & 128) == 0 else (((self.b4 % 128) << 21) + (0 if (self.b4 & 128) == 0 else (((self.b5 % 128) << 28) + (0 if (self.b5 & 128) == 0 else (((self.b6 % 128) << 35) + (0 if (self.b6 & 128) == 0 else (((self.b7 % 128) << 42) + (0 if (self.b7 & 128) == 0 else (((self.b8 % 128) << 49) + (0 if (self.b8 & 128) == 0 else (((self.b9 % 128) << 56) + (0 if (self.b8 & 128) == 0 else ((self.b10 % 128) << 63)))))))))))))))))))
+ return self._m_value if hasattr(self, '_m_value') else None
+
+
+ class SourceVersionCommand(KaitaiStruct):
+ SEQ_FIELDS = ["version"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['version']['start'] = self._io.pos()
+ self.version = self._io.read_u8le()
+ self._debug['version']['end'] = self._io.pos()
+
+
+ class CsBlob(KaitaiStruct):
+
+ class CsMagic(Enum):
+ blob_wrapper = 4208855809
+ requirement = 4208856064
+ requirements = 4208856065
+ code_directory = 4208856066
+ embedded_signature = 4208856256
+ detached_signature = 4208856257
+ entitlement = 4208882033
+ SEQ_FIELDS = ["magic", "length", "body"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['magic']['start'] = self._io.pos()
+ self.magic = KaitaiStream.resolve_enum(self._root.CsBlob.CsMagic, self._io.read_u4be())
+ self._debug['magic']['end'] = self._io.pos()
+ self._debug['length']['start'] = self._io.pos()
+ self.length = self._io.read_u4be()
+ self._debug['length']['end'] = self._io.pos()
+ self._debug['body']['start'] = self._io.pos()
+ _on = self.magic
+ if _on == self._root.CsBlob.CsMagic.requirement:
+ self._raw_body = self._io.read_bytes((self.length - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.CsBlob.Requirement(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.CsBlob.CsMagic.code_directory:
+ self._raw_body = self._io.read_bytes((self.length - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.CsBlob.CodeDirectory(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.CsBlob.CsMagic.entitlement:
+ self._raw_body = self._io.read_bytes((self.length - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.CsBlob.Entitlement(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.CsBlob.CsMagic.requirements:
+ self._raw_body = self._io.read_bytes((self.length - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.CsBlob.Requirements(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.CsBlob.CsMagic.blob_wrapper:
+ self._raw_body = self._io.read_bytes((self.length - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.CsBlob.BlobWrapper(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.CsBlob.CsMagic.embedded_signature:
+ self._raw_body = self._io.read_bytes((self.length - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.CsBlob.SuperBlob(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.CsBlob.CsMagic.detached_signature:
+ self._raw_body = self._io.read_bytes((self.length - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.CsBlob.SuperBlob(io, self, self._root)
+ self.body._read()
+ else:
+ self.body = self._io.read_bytes((self.length - 8))
+ self._debug['body']['end'] = self._io.pos()
+
+ class Entitlement(KaitaiStruct):
+ SEQ_FIELDS = ["data"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['data']['start'] = self._io.pos()
+ self.data = self._io.read_bytes_full()
+ self._debug['data']['end'] = self._io.pos()
+
+
+ class CodeDirectory(KaitaiStruct):
+ SEQ_FIELDS = ["version", "flags", "hash_offset", "ident_offset", "n_special_slots", "n_code_slots", "code_limit", "hash_size", "hash_type", "spare1", "page_size", "spare2", "scatter_offset", "team_id_offset"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['version']['start'] = self._io.pos()
+ self.version = self._io.read_u4be()
+ self._debug['version']['end'] = self._io.pos()
+ self._debug['flags']['start'] = self._io.pos()
+ self.flags = self._io.read_u4be()
+ self._debug['flags']['end'] = self._io.pos()
+ self._debug['hash_offset']['start'] = self._io.pos()
+ self.hash_offset = self._io.read_u4be()
+ self._debug['hash_offset']['end'] = self._io.pos()
+ self._debug['ident_offset']['start'] = self._io.pos()
+ self.ident_offset = self._io.read_u4be()
+ self._debug['ident_offset']['end'] = self._io.pos()
+ self._debug['n_special_slots']['start'] = self._io.pos()
+ self.n_special_slots = self._io.read_u4be()
+ self._debug['n_special_slots']['end'] = self._io.pos()
+ self._debug['n_code_slots']['start'] = self._io.pos()
+ self.n_code_slots = self._io.read_u4be()
+ self._debug['n_code_slots']['end'] = self._io.pos()
+ self._debug['code_limit']['start'] = self._io.pos()
+ self.code_limit = self._io.read_u4be()
+ self._debug['code_limit']['end'] = self._io.pos()
+ self._debug['hash_size']['start'] = self._io.pos()
+ self.hash_size = self._io.read_u1()
+ self._debug['hash_size']['end'] = self._io.pos()
+ self._debug['hash_type']['start'] = self._io.pos()
+ self.hash_type = self._io.read_u1()
+ self._debug['hash_type']['end'] = self._io.pos()
+ self._debug['spare1']['start'] = self._io.pos()
+ self.spare1 = self._io.read_u1()
+ self._debug['spare1']['end'] = self._io.pos()
+ self._debug['page_size']['start'] = self._io.pos()
+ self.page_size = self._io.read_u1()
+ self._debug['page_size']['end'] = self._io.pos()
+ self._debug['spare2']['start'] = self._io.pos()
+ self.spare2 = self._io.read_u4be()
+ self._debug['spare2']['end'] = self._io.pos()
+ if self.version >= 131328:
+ self._debug['scatter_offset']['start'] = self._io.pos()
+ self.scatter_offset = self._io.read_u4be()
+ self._debug['scatter_offset']['end'] = self._io.pos()
+
+ if self.version >= 131584:
+ self._debug['team_id_offset']['start'] = self._io.pos()
+ self.team_id_offset = self._io.read_u4be()
+ self._debug['team_id_offset']['end'] = self._io.pos()
+
+
+ @property
+ def ident(self):
+ if hasattr(self, '_m_ident'):
+ return self._m_ident if hasattr(self, '_m_ident') else None
+
+ _pos = self._io.pos()
+ self._io.seek((self.ident_offset - 8))
+ self._debug['_m_ident']['start'] = self._io.pos()
+ self._m_ident = (self._io.read_bytes_term(0, False, True, True)).decode(u"utf-8")
+ self._debug['_m_ident']['end'] = self._io.pos()
+ self._io.seek(_pos)
+ return self._m_ident if hasattr(self, '_m_ident') else None
+
+ @property
+ def team_id(self):
+ if hasattr(self, '_m_team_id'):
+ return self._m_team_id if hasattr(self, '_m_team_id') else None
+
+ _pos = self._io.pos()
+ self._io.seek((self.team_id_offset - 8))
+ self._debug['_m_team_id']['start'] = self._io.pos()
+ self._m_team_id = (self._io.read_bytes_term(0, False, True, True)).decode(u"utf-8")
+ self._debug['_m_team_id']['end'] = self._io.pos()
+ self._io.seek(_pos)
+ return self._m_team_id if hasattr(self, '_m_team_id') else None
+
+ @property
+ def hashes(self):
+ if hasattr(self, '_m_hashes'):
+ return self._m_hashes if hasattr(self, '_m_hashes') else None
+
+ _pos = self._io.pos()
+ self._io.seek(((self.hash_offset - 8) - (self.hash_size * self.n_special_slots)))
+ self._debug['_m_hashes']['start'] = self._io.pos()
+ self._m_hashes = [None] * ((self.n_special_slots + self.n_code_slots))
+ for i in range((self.n_special_slots + self.n_code_slots)):
+ if not 'arr' in self._debug['_m_hashes']:
+ self._debug['_m_hashes']['arr'] = []
+ self._debug['_m_hashes']['arr'].append({'start': self._io.pos()})
+ self._m_hashes[i] = self._io.read_bytes(self.hash_size)
+ self._debug['_m_hashes']['arr'][i]['end'] = self._io.pos()
+
+ self._debug['_m_hashes']['end'] = self._io.pos()
+ self._io.seek(_pos)
+ return self._m_hashes if hasattr(self, '_m_hashes') else None
+
+
+ class Data(KaitaiStruct):
+ SEQ_FIELDS = ["length", "value", "padding"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['length']['start'] = self._io.pos()
+ self.length = self._io.read_u4be()
+ self._debug['length']['end'] = self._io.pos()
+ self._debug['value']['start'] = self._io.pos()
+ self.value = self._io.read_bytes(self.length)
+ self._debug['value']['end'] = self._io.pos()
+ self._debug['padding']['start'] = self._io.pos()
+ self.padding = self._io.read_bytes((4 - (self.length & 3)))
+ self._debug['padding']['end'] = self._io.pos()
+
+
+ class SuperBlob(KaitaiStruct):
+ SEQ_FIELDS = ["count", "blobs"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['count']['start'] = self._io.pos()
+ self.count = self._io.read_u4be()
+ self._debug['count']['end'] = self._io.pos()
+ self._debug['blobs']['start'] = self._io.pos()
+ self.blobs = [None] * (self.count)
+ for i in range(self.count):
+ if not 'arr' in self._debug['blobs']:
+ self._debug['blobs']['arr'] = []
+ self._debug['blobs']['arr'].append({'start': self._io.pos()})
+ _t_blobs = self._root.CsBlob.BlobIndex(self._io, self, self._root)
+ _t_blobs._read()
+ self.blobs[i] = _t_blobs
+ self._debug['blobs']['arr'][i]['end'] = self._io.pos()
+
+ self._debug['blobs']['end'] = self._io.pos()
+
+
+ class Expr(KaitaiStruct):
+
+ class OpEnum(Enum):
+ false = 0
+ true = 1
+ ident = 2
+ apple_anchor = 3
+ anchor_hash = 4
+ info_key_value = 5
+ and_op = 6
+ or_op = 7
+ cd_hash = 8
+ not_op = 9
+ info_key_field = 10
+ cert_field = 11
+ trusted_cert = 12
+ trusted_certs = 13
+ cert_generic = 14
+ apple_generic_anchor = 15
+ entitlement_field = 16
+
+ class CertSlot(Enum):
+ left_cert = 0
+ anchor_cert = 4294967295
+ SEQ_FIELDS = ["op", "data"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['op']['start'] = self._io.pos()
+ self.op = KaitaiStream.resolve_enum(self._root.CsBlob.Expr.OpEnum, self._io.read_u4be())
+ self._debug['op']['end'] = self._io.pos()
+ self._debug['data']['start'] = self._io.pos()
+ _on = self.op
+ if _on == self._root.CsBlob.Expr.OpEnum.ident:
+ self.data = self._root.CsBlob.Expr.IdentExpr(self._io, self, self._root)
+ self.data._read()
+ elif _on == self._root.CsBlob.Expr.OpEnum.or_op:
+ self.data = self._root.CsBlob.Expr.OrExpr(self._io, self, self._root)
+ self.data._read()
+ elif _on == self._root.CsBlob.Expr.OpEnum.info_key_value:
+ self.data = self._root.CsBlob.Data(self._io, self, self._root)
+ self.data._read()
+ elif _on == self._root.CsBlob.Expr.OpEnum.anchor_hash:
+ self.data = self._root.CsBlob.Expr.AnchorHashExpr(self._io, self, self._root)
+ self.data._read()
+ elif _on == self._root.CsBlob.Expr.OpEnum.info_key_field:
+ self.data = self._root.CsBlob.Expr.InfoKeyFieldExpr(self._io, self, self._root)
+ self.data._read()
+ elif _on == self._root.CsBlob.Expr.OpEnum.not_op:
+ self.data = self._root.CsBlob.Expr(self._io, self, self._root)
+ self.data._read()
+ elif _on == self._root.CsBlob.Expr.OpEnum.entitlement_field:
+ self.data = self._root.CsBlob.Expr.EntitlementFieldExpr(self._io, self, self._root)
+ self.data._read()
+ elif _on == self._root.CsBlob.Expr.OpEnum.trusted_cert:
+ self.data = self._root.CsBlob.Expr.CertSlotExpr(self._io, self, self._root)
+ self.data._read()
+ elif _on == self._root.CsBlob.Expr.OpEnum.and_op:
+ self.data = self._root.CsBlob.Expr.AndExpr(self._io, self, self._root)
+ self.data._read()
+ elif _on == self._root.CsBlob.Expr.OpEnum.cert_generic:
+ self.data = self._root.CsBlob.Expr.CertGenericExpr(self._io, self, self._root)
+ self.data._read()
+ elif _on == self._root.CsBlob.Expr.OpEnum.cert_field:
+ self.data = self._root.CsBlob.Expr.CertFieldExpr(self._io, self, self._root)
+ self.data._read()
+ elif _on == self._root.CsBlob.Expr.OpEnum.cd_hash:
+ self.data = self._root.CsBlob.Data(self._io, self, self._root)
+ self.data._read()
+ elif _on == self._root.CsBlob.Expr.OpEnum.apple_generic_anchor:
+ self.data = self._root.CsBlob.Expr.AppleGenericAnchorExpr(self._io, self, self._root)
+ self.data._read()
+ self._debug['data']['end'] = self._io.pos()
+
+ class InfoKeyFieldExpr(KaitaiStruct):
+ SEQ_FIELDS = ["data", "match"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['data']['start'] = self._io.pos()
+ self.data = self._root.CsBlob.Data(self._io, self, self._root)
+ self.data._read()
+ self._debug['data']['end'] = self._io.pos()
+ self._debug['match']['start'] = self._io.pos()
+ self.match = self._root.CsBlob.Match(self._io, self, self._root)
+ self.match._read()
+ self._debug['match']['end'] = self._io.pos()
+
+
+ class CertSlotExpr(KaitaiStruct):
+ SEQ_FIELDS = ["value"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['value']['start'] = self._io.pos()
+ self.value = KaitaiStream.resolve_enum(self._root.CsBlob.Expr.CertSlot, self._io.read_u4be())
+ self._debug['value']['end'] = self._io.pos()
+
+
+ class CertGenericExpr(KaitaiStruct):
+ SEQ_FIELDS = ["cert_slot", "data", "match"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['cert_slot']['start'] = self._io.pos()
+ self.cert_slot = KaitaiStream.resolve_enum(self._root.CsBlob.Expr.CertSlot, self._io.read_u4be())
+ self._debug['cert_slot']['end'] = self._io.pos()
+ self._debug['data']['start'] = self._io.pos()
+ self.data = self._root.CsBlob.Data(self._io, self, self._root)
+ self.data._read()
+ self._debug['data']['end'] = self._io.pos()
+ self._debug['match']['start'] = self._io.pos()
+ self.match = self._root.CsBlob.Match(self._io, self, self._root)
+ self.match._read()
+ self._debug['match']['end'] = self._io.pos()
+
+
+ class IdentExpr(KaitaiStruct):
+ SEQ_FIELDS = ["identifier"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['identifier']['start'] = self._io.pos()
+ self.identifier = self._root.CsBlob.Data(self._io, self, self._root)
+ self.identifier._read()
+ self._debug['identifier']['end'] = self._io.pos()
+
+
+ class CertFieldExpr(KaitaiStruct):
+ SEQ_FIELDS = ["cert_slot", "data", "match"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['cert_slot']['start'] = self._io.pos()
+ self.cert_slot = KaitaiStream.resolve_enum(self._root.CsBlob.Expr.CertSlot, self._io.read_u4be())
+ self._debug['cert_slot']['end'] = self._io.pos()
+ self._debug['data']['start'] = self._io.pos()
+ self.data = self._root.CsBlob.Data(self._io, self, self._root)
+ self.data._read()
+ self._debug['data']['end'] = self._io.pos()
+ self._debug['match']['start'] = self._io.pos()
+ self.match = self._root.CsBlob.Match(self._io, self, self._root)
+ self.match._read()
+ self._debug['match']['end'] = self._io.pos()
+
+
+ class AnchorHashExpr(KaitaiStruct):
+ SEQ_FIELDS = ["cert_slot", "data"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['cert_slot']['start'] = self._io.pos()
+ self.cert_slot = KaitaiStream.resolve_enum(self._root.CsBlob.Expr.CertSlot, self._io.read_u4be())
+ self._debug['cert_slot']['end'] = self._io.pos()
+ self._debug['data']['start'] = self._io.pos()
+ self.data = self._root.CsBlob.Data(self._io, self, self._root)
+ self.data._read()
+ self._debug['data']['end'] = self._io.pos()
+
+
+ class AppleGenericAnchorExpr(KaitaiStruct):
+ SEQ_FIELDS = []
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ pass
+
+ @property
+ def value(self):
+ if hasattr(self, '_m_value'):
+ return self._m_value if hasattr(self, '_m_value') else None
+
+ self._m_value = u"anchor apple generic"
+ return self._m_value if hasattr(self, '_m_value') else None
+
+
+ class EntitlementFieldExpr(KaitaiStruct):
+ SEQ_FIELDS = ["data", "match"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['data']['start'] = self._io.pos()
+ self.data = self._root.CsBlob.Data(self._io, self, self._root)
+ self.data._read()
+ self._debug['data']['end'] = self._io.pos()
+ self._debug['match']['start'] = self._io.pos()
+ self.match = self._root.CsBlob.Match(self._io, self, self._root)
+ self.match._read()
+ self._debug['match']['end'] = self._io.pos()
+
+
+ class AndExpr(KaitaiStruct):
+ SEQ_FIELDS = ["left", "right"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['left']['start'] = self._io.pos()
+ self.left = self._root.CsBlob.Expr(self._io, self, self._root)
+ self.left._read()
+ self._debug['left']['end'] = self._io.pos()
+ self._debug['right']['start'] = self._io.pos()
+ self.right = self._root.CsBlob.Expr(self._io, self, self._root)
+ self.right._read()
+ self._debug['right']['end'] = self._io.pos()
+
+
+ class OrExpr(KaitaiStruct):
+ SEQ_FIELDS = ["left", "right"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['left']['start'] = self._io.pos()
+ self.left = self._root.CsBlob.Expr(self._io, self, self._root)
+ self.left._read()
+ self._debug['left']['end'] = self._io.pos()
+ self._debug['right']['start'] = self._io.pos()
+ self.right = self._root.CsBlob.Expr(self._io, self, self._root)
+ self.right._read()
+ self._debug['right']['end'] = self._io.pos()
+
+
+
+ class BlobIndex(KaitaiStruct):
+
+ class CsslotType(Enum):
+ code_directory = 0
+ info_slot = 1
+ requirements = 2
+ resource_dir = 3
+ application = 4
+ entitlements = 5
+ alternate_code_directories = 4096
+ signature_slot = 65536
+ SEQ_FIELDS = ["type", "offset"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['type']['start'] = self._io.pos()
+ self.type = KaitaiStream.resolve_enum(self._root.CsBlob.BlobIndex.CsslotType, self._io.read_u4be())
+ self._debug['type']['end'] = self._io.pos()
+ self._debug['offset']['start'] = self._io.pos()
+ self.offset = self._io.read_u4be()
+ self._debug['offset']['end'] = self._io.pos()
+
+ @property
+ def blob(self):
+ if hasattr(self, '_m_blob'):
+ return self._m_blob if hasattr(self, '_m_blob') else None
+
+ io = self._parent._io
+ _pos = io.pos()
+ io.seek((self.offset - 8))
+ self._debug['_m_blob']['start'] = io.pos()
+ self._raw__m_blob = io.read_bytes_full()
+ io = KaitaiStream(BytesIO(self._raw__m_blob))
+ self._m_blob = self._root.CsBlob(io, self, self._root)
+ self._m_blob._read()
+ self._debug['_m_blob']['end'] = io.pos()
+ io.seek(_pos)
+ return self._m_blob if hasattr(self, '_m_blob') else None
+
+
+ class Match(KaitaiStruct):
+
+ class Op(Enum):
+ exists = 0
+ equal = 1
+ contains = 2
+ begins_with = 3
+ ends_with = 4
+ less_than = 5
+ greater_than = 6
+ less_equal = 7
+ greater_equal = 8
+ SEQ_FIELDS = ["match_op", "data"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['match_op']['start'] = self._io.pos()
+ self.match_op = KaitaiStream.resolve_enum(self._root.CsBlob.Match.Op, self._io.read_u4be())
+ self._debug['match_op']['end'] = self._io.pos()
+ if self.match_op != self._root.CsBlob.Match.Op.exists:
+ self._debug['data']['start'] = self._io.pos()
+ self.data = self._root.CsBlob.Data(self._io, self, self._root)
+ self.data._read()
+ self._debug['data']['end'] = self._io.pos()
+
+
+
+ class Requirement(KaitaiStruct):
+ SEQ_FIELDS = ["kind", "expr"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['kind']['start'] = self._io.pos()
+ self.kind = self._io.read_u4be()
+ self._debug['kind']['end'] = self._io.pos()
+ self._debug['expr']['start'] = self._io.pos()
+ self.expr = self._root.CsBlob.Expr(self._io, self, self._root)
+ self.expr._read()
+ self._debug['expr']['end'] = self._io.pos()
+
+
+ class Requirements(KaitaiStruct):
+ SEQ_FIELDS = ["count", "items"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['count']['start'] = self._io.pos()
+ self.count = self._io.read_u4be()
+ self._debug['count']['end'] = self._io.pos()
+ self._debug['items']['start'] = self._io.pos()
+ self.items = [None] * (self.count)
+ for i in range(self.count):
+ if not 'arr' in self._debug['items']:
+ self._debug['items']['arr'] = []
+ self._debug['items']['arr'].append({'start': self._io.pos()})
+ _t_items = self._root.CsBlob.RequirementsBlobIndex(self._io, self, self._root)
+ _t_items._read()
+ self.items[i] = _t_items
+ self._debug['items']['arr'][i]['end'] = self._io.pos()
+
+ self._debug['items']['end'] = self._io.pos()
+
+
+ class BlobWrapper(KaitaiStruct):
+ SEQ_FIELDS = ["data"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['data']['start'] = self._io.pos()
+ self.data = self._io.read_bytes_full()
+ self._debug['data']['end'] = self._io.pos()
+
+
+ class RequirementsBlobIndex(KaitaiStruct):
+
+ class RequirementType(Enum):
+ host = 1
+ guest = 2
+ designated = 3
+ library = 4
+ SEQ_FIELDS = ["type", "offset"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['type']['start'] = self._io.pos()
+ self.type = KaitaiStream.resolve_enum(self._root.CsBlob.RequirementsBlobIndex.RequirementType, self._io.read_u4be())
+ self._debug['type']['end'] = self._io.pos()
+ self._debug['offset']['start'] = self._io.pos()
+ self.offset = self._io.read_u4be()
+ self._debug['offset']['end'] = self._io.pos()
+
+ @property
+ def value(self):
+ if hasattr(self, '_m_value'):
+ return self._m_value if hasattr(self, '_m_value') else None
+
+ _pos = self._io.pos()
+ self._io.seek((self.offset - 8))
+ self._debug['_m_value']['start'] = self._io.pos()
+ self._m_value = self._root.CsBlob(self._io, self, self._root)
+ self._m_value._read()
+ self._debug['_m_value']['end'] = self._io.pos()
+ self._io.seek(_pos)
+ return self._m_value if hasattr(self, '_m_value') else None
+
+
+
+ class RoutinesCommand(KaitaiStruct):
+ SEQ_FIELDS = ["init_address", "init_module", "reserved"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['init_address']['start'] = self._io.pos()
+ self.init_address = self._io.read_u4le()
+ self._debug['init_address']['end'] = self._io.pos()
+ self._debug['init_module']['start'] = self._io.pos()
+ self.init_module = self._io.read_u4le()
+ self._debug['init_module']['end'] = self._io.pos()
+ self._debug['reserved']['start'] = self._io.pos()
+ self.reserved = self._io.read_bytes(24)
+ self._debug['reserved']['end'] = self._io.pos()
+
+
+ class MachoFlags(KaitaiStruct):
+ SEQ_FIELDS = []
+ def __init__(self, value, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self.value = value
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ pass
+
+ @property
+ def subsections_via_symbols(self):
+ """safe to divide up the sections into sub-sections via symbols for dead code stripping."""
+ if hasattr(self, '_m_subsections_via_symbols'):
+ return self._m_subsections_via_symbols if hasattr(self, '_m_subsections_via_symbols') else None
+
+ self._m_subsections_via_symbols = (self.value & 8192) != 0
+ return self._m_subsections_via_symbols if hasattr(self, '_m_subsections_via_symbols') else None
+
+ @property
+ def dead_strippable_dylib(self):
+ if hasattr(self, '_m_dead_strippable_dylib'):
+ return self._m_dead_strippable_dylib if hasattr(self, '_m_dead_strippable_dylib') else None
+
+ self._m_dead_strippable_dylib = (self.value & 4194304) != 0
+ return self._m_dead_strippable_dylib if hasattr(self, '_m_dead_strippable_dylib') else None
+
+ @property
+ def weak_defines(self):
+ """the final linked image contains external weak symbols."""
+ if hasattr(self, '_m_weak_defines'):
+ return self._m_weak_defines if hasattr(self, '_m_weak_defines') else None
+
+ self._m_weak_defines = (self.value & 32768) != 0
+ return self._m_weak_defines if hasattr(self, '_m_weak_defines') else None
+
+ @property
+ def prebound(self):
+ """the file has its dynamic undefined references prebound."""
+ if hasattr(self, '_m_prebound'):
+ return self._m_prebound if hasattr(self, '_m_prebound') else None
+
+ self._m_prebound = (self.value & 16) != 0
+ return self._m_prebound if hasattr(self, '_m_prebound') else None
+
+ @property
+ def all_mods_bound(self):
+ """indicates that this binary binds to all two-level namespace modules of its dependent libraries. only used when MH_PREBINDABLE and MH_TWOLEVEL are both set."""
+ if hasattr(self, '_m_all_mods_bound'):
+ return self._m_all_mods_bound if hasattr(self, '_m_all_mods_bound') else None
+
+ self._m_all_mods_bound = (self.value & 4096) != 0
+ return self._m_all_mods_bound if hasattr(self, '_m_all_mods_bound') else None
+
+ @property
+ def has_tlv_descriptors(self):
+ if hasattr(self, '_m_has_tlv_descriptors'):
+ return self._m_has_tlv_descriptors if hasattr(self, '_m_has_tlv_descriptors') else None
+
+ self._m_has_tlv_descriptors = (self.value & 8388608) != 0
+ return self._m_has_tlv_descriptors if hasattr(self, '_m_has_tlv_descriptors') else None
+
+ @property
+ def force_flat(self):
+ """the executable is forcing all images to use flat name space bindings."""
+ if hasattr(self, '_m_force_flat'):
+ return self._m_force_flat if hasattr(self, '_m_force_flat') else None
+
+ self._m_force_flat = (self.value & 256) != 0
+ return self._m_force_flat if hasattr(self, '_m_force_flat') else None
+
+ @property
+ def root_safe(self):
+ """When this bit is set, the binary declares it is safe for use in processes with uid zero."""
+ if hasattr(self, '_m_root_safe'):
+ return self._m_root_safe if hasattr(self, '_m_root_safe') else None
+
+ self._m_root_safe = (self.value & 262144) != 0
+ return self._m_root_safe if hasattr(self, '_m_root_safe') else None
+
+ @property
+ def no_undefs(self):
+ """the object file has no undefined references."""
+ if hasattr(self, '_m_no_undefs'):
+ return self._m_no_undefs if hasattr(self, '_m_no_undefs') else None
+
+ self._m_no_undefs = (self.value & 1) != 0
+ return self._m_no_undefs if hasattr(self, '_m_no_undefs') else None
+
+ @property
+ def setuid_safe(self):
+ """When this bit is set, the binary declares it is safe for use in processes when issetugid() is true."""
+ if hasattr(self, '_m_setuid_safe'):
+ return self._m_setuid_safe if hasattr(self, '_m_setuid_safe') else None
+
+ self._m_setuid_safe = (self.value & 524288) != 0
+ return self._m_setuid_safe if hasattr(self, '_m_setuid_safe') else None
+
+ @property
+ def no_heap_execution(self):
+ if hasattr(self, '_m_no_heap_execution'):
+ return self._m_no_heap_execution if hasattr(self, '_m_no_heap_execution') else None
+
+ self._m_no_heap_execution = (self.value & 16777216) != 0
+ return self._m_no_heap_execution if hasattr(self, '_m_no_heap_execution') else None
+
+ @property
+ def no_reexported_dylibs(self):
+ """When this bit is set on a dylib, the static linker does not need to examine dependent dylibs to see if any are re-exported."""
+ if hasattr(self, '_m_no_reexported_dylibs'):
+ return self._m_no_reexported_dylibs if hasattr(self, '_m_no_reexported_dylibs') else None
+
+ self._m_no_reexported_dylibs = (self.value & 1048576) != 0
+ return self._m_no_reexported_dylibs if hasattr(self, '_m_no_reexported_dylibs') else None
+
+ @property
+ def no_multi_defs(self):
+ """this umbrella guarantees no multiple defintions of symbols in its sub-images so the two-level namespace hints can always be used."""
+ if hasattr(self, '_m_no_multi_defs'):
+ return self._m_no_multi_defs if hasattr(self, '_m_no_multi_defs') else None
+
+ self._m_no_multi_defs = (self.value & 512) != 0
+ return self._m_no_multi_defs if hasattr(self, '_m_no_multi_defs') else None
+
+ @property
+ def app_extension_safe(self):
+ if hasattr(self, '_m_app_extension_safe'):
+ return self._m_app_extension_safe if hasattr(self, '_m_app_extension_safe') else None
+
+ self._m_app_extension_safe = (self.value & 33554432) != 0
+ return self._m_app_extension_safe if hasattr(self, '_m_app_extension_safe') else None
+
+ @property
+ def prebindable(self):
+ """the binary is not prebound but can have its prebinding redone. only used when MH_PREBOUND is not set."""
+ if hasattr(self, '_m_prebindable'):
+ return self._m_prebindable if hasattr(self, '_m_prebindable') else None
+
+ self._m_prebindable = (self.value & 2048) != 0
+ return self._m_prebindable if hasattr(self, '_m_prebindable') else None
+
+ @property
+ def incr_link(self):
+ """the object file is the output of an incremental link against a base file and can't be link edited again."""
+ if hasattr(self, '_m_incr_link'):
+ return self._m_incr_link if hasattr(self, '_m_incr_link') else None
+
+ self._m_incr_link = (self.value & 2) != 0
+ return self._m_incr_link if hasattr(self, '_m_incr_link') else None
+
+ @property
+ def bind_at_load(self):
+ """the object file's undefined references are bound by the dynamic linker when loaded."""
+ if hasattr(self, '_m_bind_at_load'):
+ return self._m_bind_at_load if hasattr(self, '_m_bind_at_load') else None
+
+ self._m_bind_at_load = (self.value & 8) != 0
+ return self._m_bind_at_load if hasattr(self, '_m_bind_at_load') else None
+
+ @property
+ def canonical(self):
+ """the binary has been canonicalized via the unprebind operation."""
+ if hasattr(self, '_m_canonical'):
+ return self._m_canonical if hasattr(self, '_m_canonical') else None
+
+ self._m_canonical = (self.value & 16384) != 0
+ return self._m_canonical if hasattr(self, '_m_canonical') else None
+
+ @property
+ def two_level(self):
+ """the image is using two-level name space bindings."""
+ if hasattr(self, '_m_two_level'):
+ return self._m_two_level if hasattr(self, '_m_two_level') else None
+
+ self._m_two_level = (self.value & 128) != 0
+ return self._m_two_level if hasattr(self, '_m_two_level') else None
+
+ @property
+ def split_segs(self):
+ """the file has its read-only and read-write segments split."""
+ if hasattr(self, '_m_split_segs'):
+ return self._m_split_segs if hasattr(self, '_m_split_segs') else None
+
+ self._m_split_segs = (self.value & 32) != 0
+ return self._m_split_segs if hasattr(self, '_m_split_segs') else None
+
+ @property
+ def lazy_init(self):
+ """the shared library init routine is to be run lazily via catching memory faults to its writeable segments (obsolete)."""
+ if hasattr(self, '_m_lazy_init'):
+ return self._m_lazy_init if hasattr(self, '_m_lazy_init') else None
+
+ self._m_lazy_init = (self.value & 64) != 0
+ return self._m_lazy_init if hasattr(self, '_m_lazy_init') else None
+
+ @property
+ def allow_stack_execution(self):
+ """When this bit is set, all stacks in the task will be given stack execution privilege. Only used in MH_EXECUTE filetypes."""
+ if hasattr(self, '_m_allow_stack_execution'):
+ return self._m_allow_stack_execution if hasattr(self, '_m_allow_stack_execution') else None
+
+ self._m_allow_stack_execution = (self.value & 131072) != 0
+ return self._m_allow_stack_execution if hasattr(self, '_m_allow_stack_execution') else None
+
+ @property
+ def binds_to_weak(self):
+ """the final linked image uses weak symbols."""
+ if hasattr(self, '_m_binds_to_weak'):
+ return self._m_binds_to_weak if hasattr(self, '_m_binds_to_weak') else None
+
+ self._m_binds_to_weak = (self.value & 65536) != 0
+ return self._m_binds_to_weak if hasattr(self, '_m_binds_to_weak') else None
+
+ @property
+ def no_fix_prebinding(self):
+ """do not have dyld notify the prebinding agent about this executable."""
+ if hasattr(self, '_m_no_fix_prebinding'):
+ return self._m_no_fix_prebinding if hasattr(self, '_m_no_fix_prebinding') else None
+
+ self._m_no_fix_prebinding = (self.value & 1024) != 0
+ return self._m_no_fix_prebinding if hasattr(self, '_m_no_fix_prebinding') else None
+
+ @property
+ def dyld_link(self):
+ """the object file is input for the dynamic linker and can't be staticly link edited again."""
+ if hasattr(self, '_m_dyld_link'):
+ return self._m_dyld_link if hasattr(self, '_m_dyld_link') else None
+
+ self._m_dyld_link = (self.value & 4) != 0
+ return self._m_dyld_link if hasattr(self, '_m_dyld_link') else None
+
+ @property
+ def pie(self):
+ """When this bit is set, the OS will load the main executable at a random address. Only used in MH_EXECUTE filetypes."""
+ if hasattr(self, '_m_pie'):
+ return self._m_pie if hasattr(self, '_m_pie') else None
+
+ self._m_pie = (self.value & 2097152) != 0
+ return self._m_pie if hasattr(self, '_m_pie') else None
+
+
+ class RoutinesCommand64(KaitaiStruct):
+ SEQ_FIELDS = ["init_address", "init_module", "reserved"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['init_address']['start'] = self._io.pos()
+ self.init_address = self._io.read_u8le()
+ self._debug['init_address']['end'] = self._io.pos()
+ self._debug['init_module']['start'] = self._io.pos()
+ self.init_module = self._io.read_u8le()
+ self._debug['init_module']['end'] = self._io.pos()
+ self._debug['reserved']['start'] = self._io.pos()
+ self.reserved = self._io.read_bytes(48)
+ self._debug['reserved']['end'] = self._io.pos()
+
+
+ class LinkerOptionCommand(KaitaiStruct):
+ SEQ_FIELDS = ["num_strings", "strings"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['num_strings']['start'] = self._io.pos()
+ self.num_strings = self._io.read_u4le()
+ self._debug['num_strings']['end'] = self._io.pos()
+ self._debug['strings']['start'] = self._io.pos()
+ self.strings = [None] * (self.num_strings)
+ for i in range(self.num_strings):
+ if not 'arr' in self._debug['strings']:
+ self._debug['strings']['arr'] = []
+ self._debug['strings']['arr'].append({'start': self._io.pos()})
+ self.strings[i] = (self._io.read_bytes_term(0, False, True, True)).decode(u"utf-8")
+ self._debug['strings']['arr'][i]['end'] = self._io.pos()
+
+ self._debug['strings']['end'] = self._io.pos()
+
+
+ class SegmentCommand64(KaitaiStruct):
+ SEQ_FIELDS = ["segname", "vmaddr", "vmsize", "fileoff", "filesize", "maxprot", "initprot", "nsects", "flags", "sections"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['segname']['start'] = self._io.pos()
+ self.segname = (KaitaiStream.bytes_strip_right(self._io.read_bytes(16), 0)).decode(u"ascii")
+ self._debug['segname']['end'] = self._io.pos()
+ self._debug['vmaddr']['start'] = self._io.pos()
+ self.vmaddr = self._io.read_u8le()
+ self._debug['vmaddr']['end'] = self._io.pos()
+ self._debug['vmsize']['start'] = self._io.pos()
+ self.vmsize = self._io.read_u8le()
+ self._debug['vmsize']['end'] = self._io.pos()
+ self._debug['fileoff']['start'] = self._io.pos()
+ self.fileoff = self._io.read_u8le()
+ self._debug['fileoff']['end'] = self._io.pos()
+ self._debug['filesize']['start'] = self._io.pos()
+ self.filesize = self._io.read_u8le()
+ self._debug['filesize']['end'] = self._io.pos()
+ self._debug['maxprot']['start'] = self._io.pos()
+ self.maxprot = self._root.VmProt(self._io, self, self._root)
+ self.maxprot._read()
+ self._debug['maxprot']['end'] = self._io.pos()
+ self._debug['initprot']['start'] = self._io.pos()
+ self.initprot = self._root.VmProt(self._io, self, self._root)
+ self.initprot._read()
+ self._debug['initprot']['end'] = self._io.pos()
+ self._debug['nsects']['start'] = self._io.pos()
+ self.nsects = self._io.read_u4le()
+ self._debug['nsects']['end'] = self._io.pos()
+ self._debug['flags']['start'] = self._io.pos()
+ self.flags = self._io.read_u4le()
+ self._debug['flags']['end'] = self._io.pos()
+ self._debug['sections']['start'] = self._io.pos()
+ self.sections = [None] * (self.nsects)
+ for i in range(self.nsects):
+ if not 'arr' in self._debug['sections']:
+ self._debug['sections']['arr'] = []
+ self._debug['sections']['arr'].append({'start': self._io.pos()})
+ _t_sections = self._root.SegmentCommand64.Section64(self._io, self, self._root)
+ _t_sections._read()
+ self.sections[i] = _t_sections
+ self._debug['sections']['arr'][i]['end'] = self._io.pos()
+
+ self._debug['sections']['end'] = self._io.pos()
+
+ class Section64(KaitaiStruct):
+ SEQ_FIELDS = ["sect_name", "seg_name", "addr", "size", "offset", "align", "reloff", "nreloc", "flags", "reserved1", "reserved2", "reserved3"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['sect_name']['start'] = self._io.pos()
+ self.sect_name = (KaitaiStream.bytes_strip_right(self._io.read_bytes(16), 0)).decode(u"ascii")
+ self._debug['sect_name']['end'] = self._io.pos()
+ self._debug['seg_name']['start'] = self._io.pos()
+ self.seg_name = (KaitaiStream.bytes_strip_right(self._io.read_bytes(16), 0)).decode(u"ascii")
+ self._debug['seg_name']['end'] = self._io.pos()
+ self._debug['addr']['start'] = self._io.pos()
+ self.addr = self._io.read_u8le()
+ self._debug['addr']['end'] = self._io.pos()
+ self._debug['size']['start'] = self._io.pos()
+ self.size = self._io.read_u8le()
+ self._debug['size']['end'] = self._io.pos()
+ self._debug['offset']['start'] = self._io.pos()
+ self.offset = self._io.read_u4le()
+ self._debug['offset']['end'] = self._io.pos()
+ self._debug['align']['start'] = self._io.pos()
+ self.align = self._io.read_u4le()
+ self._debug['align']['end'] = self._io.pos()
+ self._debug['reloff']['start'] = self._io.pos()
+ self.reloff = self._io.read_u4le()
+ self._debug['reloff']['end'] = self._io.pos()
+ self._debug['nreloc']['start'] = self._io.pos()
+ self.nreloc = self._io.read_u4le()
+ self._debug['nreloc']['end'] = self._io.pos()
+ self._debug['flags']['start'] = self._io.pos()
+ self.flags = self._io.read_u4le()
+ self._debug['flags']['end'] = self._io.pos()
+ self._debug['reserved1']['start'] = self._io.pos()
+ self.reserved1 = self._io.read_u4le()
+ self._debug['reserved1']['end'] = self._io.pos()
+ self._debug['reserved2']['start'] = self._io.pos()
+ self.reserved2 = self._io.read_u4le()
+ self._debug['reserved2']['end'] = self._io.pos()
+ self._debug['reserved3']['start'] = self._io.pos()
+ self.reserved3 = self._io.read_u4le()
+ self._debug['reserved3']['end'] = self._io.pos()
+
+ class CfStringList(KaitaiStruct):
+ SEQ_FIELDS = ["items"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['items']['start'] = self._io.pos()
+ self.items = []
+ i = 0
+ while not self._io.is_eof():
+ if not 'arr' in self._debug['items']:
+ self._debug['items']['arr'] = []
+ self._debug['items']['arr'].append({'start': self._io.pos()})
+ _t_items = self._root.SegmentCommand64.Section64.CfString(self._io, self, self._root)
+ _t_items._read()
+ self.items.append(_t_items)
+ self._debug['items']['arr'][len(self.items) - 1]['end'] = self._io.pos()
+ i += 1
+
+ self._debug['items']['end'] = self._io.pos()
+
+
+ class CfString(KaitaiStruct):
+ SEQ_FIELDS = ["isa", "info", "data", "length"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['isa']['start'] = self._io.pos()
+ self.isa = self._io.read_u8le()
+ self._debug['isa']['end'] = self._io.pos()
+ self._debug['info']['start'] = self._io.pos()
+ self.info = self._io.read_u8le()
+ self._debug['info']['end'] = self._io.pos()
+ self._debug['data']['start'] = self._io.pos()
+ self.data = self._io.read_u8le()
+ self._debug['data']['end'] = self._io.pos()
+ self._debug['length']['start'] = self._io.pos()
+ self.length = self._io.read_u8le()
+ self._debug['length']['end'] = self._io.pos()
+
+
+ class EhFrameItem(KaitaiStruct):
+ SEQ_FIELDS = ["length", "length64", "id", "body"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['length']['start'] = self._io.pos()
+ self.length = self._io.read_u4le()
+ self._debug['length']['end'] = self._io.pos()
+ if self.length == 4294967295:
+ self._debug['length64']['start'] = self._io.pos()
+ self.length64 = self._io.read_u8le()
+ self._debug['length64']['end'] = self._io.pos()
+
+ self._debug['id']['start'] = self._io.pos()
+ self.id = self._io.read_u4le()
+ self._debug['id']['end'] = self._io.pos()
+ if self.length > 0:
+ self._debug['body']['start'] = self._io.pos()
+ _on = self.id
+ if _on == 0:
+ self._raw_body = self._io.read_bytes((self.length - 4))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.SegmentCommand64.Section64.EhFrameItem.Cie(io, self, self._root)
+ self.body._read()
+ else:
+ self.body = self._io.read_bytes((self.length - 4))
+ self._debug['body']['end'] = self._io.pos()
+
+
+ class CharChain(KaitaiStruct):
+ SEQ_FIELDS = ["chr", "next"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['chr']['start'] = self._io.pos()
+ self.chr = self._io.read_u1()
+ self._debug['chr']['end'] = self._io.pos()
+ if self.chr != 0:
+ self._debug['next']['start'] = self._io.pos()
+ self.next = self._root.SegmentCommand64.Section64.EhFrameItem.CharChain(self._io, self, self._root)
+ self.next._read()
+ self._debug['next']['end'] = self._io.pos()
+
+
+
+ class Cie(KaitaiStruct):
+ SEQ_FIELDS = ["version", "aug_str", "code_alignment_factor", "data_alignment_factor", "return_address_register", "augmentation"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['version']['start'] = self._io.pos()
+ self.version = self._io.read_u1()
+ self._debug['version']['end'] = self._io.pos()
+ self._debug['aug_str']['start'] = self._io.pos()
+ self.aug_str = self._root.SegmentCommand64.Section64.EhFrameItem.CharChain(self._io, self, self._root)
+ self.aug_str._read()
+ self._debug['aug_str']['end'] = self._io.pos()
+ self._debug['code_alignment_factor']['start'] = self._io.pos()
+ self.code_alignment_factor = self._root.Uleb128(self._io, self, self._root)
+ self.code_alignment_factor._read()
+ self._debug['code_alignment_factor']['end'] = self._io.pos()
+ self._debug['data_alignment_factor']['start'] = self._io.pos()
+ self.data_alignment_factor = self._root.Uleb128(self._io, self, self._root)
+ self.data_alignment_factor._read()
+ self._debug['data_alignment_factor']['end'] = self._io.pos()
+ self._debug['return_address_register']['start'] = self._io.pos()
+ self.return_address_register = self._io.read_u1()
+ self._debug['return_address_register']['end'] = self._io.pos()
+ if self.aug_str.chr == 122:
+ self._debug['augmentation']['start'] = self._io.pos()
+ self.augmentation = self._root.SegmentCommand64.Section64.EhFrameItem.AugmentationEntry(self._io, self, self._root)
+ self.augmentation._read()
+ self._debug['augmentation']['end'] = self._io.pos()
+
+
+
+ class AugmentationEntry(KaitaiStruct):
+ SEQ_FIELDS = ["length", "fde_pointer_encoding"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['length']['start'] = self._io.pos()
+ self.length = self._root.Uleb128(self._io, self, self._root)
+ self.length._read()
+ self._debug['length']['end'] = self._io.pos()
+ if self._parent.aug_str.next.chr == 82:
+ self._debug['fde_pointer_encoding']['start'] = self._io.pos()
+ self.fde_pointer_encoding = self._io.read_u1()
+ self._debug['fde_pointer_encoding']['end'] = self._io.pos()
+
+
+
+
+ class EhFrame(KaitaiStruct):
+ SEQ_FIELDS = ["items"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['items']['start'] = self._io.pos()
+ self.items = []
+ i = 0
+ while not self._io.is_eof():
+ if not 'arr' in self._debug['items']:
+ self._debug['items']['arr'] = []
+ self._debug['items']['arr'].append({'start': self._io.pos()})
+ _t_items = self._root.SegmentCommand64.Section64.EhFrameItem(self._io, self, self._root)
+ _t_items._read()
+ self.items.append(_t_items)
+ self._debug['items']['arr'][len(self.items) - 1]['end'] = self._io.pos()
+ i += 1
+
+ self._debug['items']['end'] = self._io.pos()
+
+
+ class PointerList(KaitaiStruct):
+ SEQ_FIELDS = ["items"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['items']['start'] = self._io.pos()
+ self.items = []
+ i = 0
+ while not self._io.is_eof():
+ if not 'arr' in self._debug['items']:
+ self._debug['items']['arr'] = []
+ self._debug['items']['arr'].append({'start': self._io.pos()})
+ self.items.append(self._io.read_u8le())
+ self._debug['items']['arr'][len(self.items) - 1]['end'] = self._io.pos()
+ i += 1
+
+ self._debug['items']['end'] = self._io.pos()
+
+
+ class StringList(KaitaiStruct):
+ SEQ_FIELDS = ["strings"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['strings']['start'] = self._io.pos()
+ self.strings = []
+ i = 0
+ while not self._io.is_eof():
+ if not 'arr' in self._debug['strings']:
+ self._debug['strings']['arr'] = []
+ self._debug['strings']['arr'].append({'start': self._io.pos()})
+ self.strings.append((self._io.read_bytes_term(0, False, True, True)).decode(u"ascii"))
+ self._debug['strings']['arr'][len(self.strings) - 1]['end'] = self._io.pos()
+ i += 1
+
+ self._debug['strings']['end'] = self._io.pos()
+
+
+ @property
+ def data(self):
+ if hasattr(self, '_m_data'):
+ return self._m_data if hasattr(self, '_m_data') else None
+
+ io = self._root._io
+ _pos = io.pos()
+ io.seek(self.offset)
+ self._debug['_m_data']['start'] = io.pos()
+ _on = self.sect_name
+ if _on == u"__objc_nlclslist":
+ self._raw__m_data = io.read_bytes(self.size)
+ io = KaitaiStream(BytesIO(self._raw__m_data))
+ self._m_data = self._root.SegmentCommand64.Section64.PointerList(io, self, self._root)
+ self._m_data._read()
+ elif _on == u"__objc_methname":
+ self._raw__m_data = io.read_bytes(self.size)
+ io = KaitaiStream(BytesIO(self._raw__m_data))
+ self._m_data = self._root.SegmentCommand64.Section64.StringList(io, self, self._root)
+ self._m_data._read()
+ elif _on == u"__nl_symbol_ptr":
+ self._raw__m_data = io.read_bytes(self.size)
+ io = KaitaiStream(BytesIO(self._raw__m_data))
+ self._m_data = self._root.SegmentCommand64.Section64.PointerList(io, self, self._root)
+ self._m_data._read()
+ elif _on == u"__la_symbol_ptr":
+ self._raw__m_data = io.read_bytes(self.size)
+ io = KaitaiStream(BytesIO(self._raw__m_data))
+ self._m_data = self._root.SegmentCommand64.Section64.PointerList(io, self, self._root)
+ self._m_data._read()
+ elif _on == u"__objc_selrefs":
+ self._raw__m_data = io.read_bytes(self.size)
+ io = KaitaiStream(BytesIO(self._raw__m_data))
+ self._m_data = self._root.SegmentCommand64.Section64.PointerList(io, self, self._root)
+ self._m_data._read()
+ elif _on == u"__cstring":
+ self._raw__m_data = io.read_bytes(self.size)
+ io = KaitaiStream(BytesIO(self._raw__m_data))
+ self._m_data = self._root.SegmentCommand64.Section64.StringList(io, self, self._root)
+ self._m_data._read()
+ elif _on == u"__objc_classlist":
+ self._raw__m_data = io.read_bytes(self.size)
+ io = KaitaiStream(BytesIO(self._raw__m_data))
+ self._m_data = self._root.SegmentCommand64.Section64.PointerList(io, self, self._root)
+ self._m_data._read()
+ elif _on == u"__objc_protolist":
+ self._raw__m_data = io.read_bytes(self.size)
+ io = KaitaiStream(BytesIO(self._raw__m_data))
+ self._m_data = self._root.SegmentCommand64.Section64.PointerList(io, self, self._root)
+ self._m_data._read()
+ elif _on == u"__objc_imageinfo":
+ self._raw__m_data = io.read_bytes(self.size)
+ io = KaitaiStream(BytesIO(self._raw__m_data))
+ self._m_data = self._root.SegmentCommand64.Section64.PointerList(io, self, self._root)
+ self._m_data._read()
+ elif _on == u"__objc_methtype":
+ self._raw__m_data = io.read_bytes(self.size)
+ io = KaitaiStream(BytesIO(self._raw__m_data))
+ self._m_data = self._root.SegmentCommand64.Section64.StringList(io, self, self._root)
+ self._m_data._read()
+ elif _on == u"__cfstring":
+ self._raw__m_data = io.read_bytes(self.size)
+ io = KaitaiStream(BytesIO(self._raw__m_data))
+ self._m_data = self._root.SegmentCommand64.Section64.CfStringList(io, self, self._root)
+ self._m_data._read()
+ elif _on == u"__objc_classrefs":
+ self._raw__m_data = io.read_bytes(self.size)
+ io = KaitaiStream(BytesIO(self._raw__m_data))
+ self._m_data = self._root.SegmentCommand64.Section64.PointerList(io, self, self._root)
+ self._m_data._read()
+ elif _on == u"__objc_protorefs":
+ self._raw__m_data = io.read_bytes(self.size)
+ io = KaitaiStream(BytesIO(self._raw__m_data))
+ self._m_data = self._root.SegmentCommand64.Section64.PointerList(io, self, self._root)
+ self._m_data._read()
+ elif _on == u"__objc_classname":
+ self._raw__m_data = io.read_bytes(self.size)
+ io = KaitaiStream(BytesIO(self._raw__m_data))
+ self._m_data = self._root.SegmentCommand64.Section64.StringList(io, self, self._root)
+ self._m_data._read()
+ elif _on == u"__got":
+ self._raw__m_data = io.read_bytes(self.size)
+ io = KaitaiStream(BytesIO(self._raw__m_data))
+ self._m_data = self._root.SegmentCommand64.Section64.PointerList(io, self, self._root)
+ self._m_data._read()
+ elif _on == u"__eh_frame":
+ self._raw__m_data = io.read_bytes(self.size)
+ io = KaitaiStream(BytesIO(self._raw__m_data))
+ self._m_data = self._root.SegmentCommand64.Section64.EhFrame(io, self, self._root)
+ self._m_data._read()
+ elif _on == u"__objc_superrefs":
+ self._raw__m_data = io.read_bytes(self.size)
+ io = KaitaiStream(BytesIO(self._raw__m_data))
+ self._m_data = self._root.SegmentCommand64.Section64.PointerList(io, self, self._root)
+ self._m_data._read()
+ else:
+ self._m_data = io.read_bytes(self.size)
+ self._debug['_m_data']['end'] = io.pos()
+ io.seek(_pos)
+ return self._m_data if hasattr(self, '_m_data') else None
+
+
+
+ class VmProt(KaitaiStruct):
+ SEQ_FIELDS = ["strip_read", "is_mask", "reserved0", "copy", "no_change", "execute", "write", "read", "reserved1"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['strip_read']['start'] = self._io.pos()
+ self.strip_read = self._io.read_bits_int(1) != 0
+ self._debug['strip_read']['end'] = self._io.pos()
+ self._debug['is_mask']['start'] = self._io.pos()
+ self.is_mask = self._io.read_bits_int(1) != 0
+ self._debug['is_mask']['end'] = self._io.pos()
+ self._debug['reserved0']['start'] = self._io.pos()
+ self.reserved0 = self._io.read_bits_int(1) != 0
+ self._debug['reserved0']['end'] = self._io.pos()
+ self._debug['copy']['start'] = self._io.pos()
+ self.copy = self._io.read_bits_int(1) != 0
+ self._debug['copy']['end'] = self._io.pos()
+ self._debug['no_change']['start'] = self._io.pos()
+ self.no_change = self._io.read_bits_int(1) != 0
+ self._debug['no_change']['end'] = self._io.pos()
+ self._debug['execute']['start'] = self._io.pos()
+ self.execute = self._io.read_bits_int(1) != 0
+ self._debug['execute']['end'] = self._io.pos()
+ self._debug['write']['start'] = self._io.pos()
+ self.write = self._io.read_bits_int(1) != 0
+ self._debug['write']['end'] = self._io.pos()
+ self._debug['read']['start'] = self._io.pos()
+ self.read = self._io.read_bits_int(1) != 0
+ self._debug['read']['end'] = self._io.pos()
+ self._debug['reserved1']['start'] = self._io.pos()
+ self.reserved1 = self._io.read_bits_int(24)
+ self._debug['reserved1']['end'] = self._io.pos()
+
+
+ class DysymtabCommand(KaitaiStruct):
+ SEQ_FIELDS = ["i_local_sym", "n_local_sym", "i_ext_def_sym", "n_ext_def_sym", "i_undef_sym", "n_undef_sym", "toc_off", "n_toc", "mod_tab_off", "n_mod_tab", "ext_ref_sym_off", "n_ext_ref_syms", "indirect_sym_off", "n_indirect_syms", "ext_rel_off", "n_ext_rel", "loc_rel_off", "n_loc_rel"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['i_local_sym']['start'] = self._io.pos()
+ self.i_local_sym = self._io.read_u4le()
+ self._debug['i_local_sym']['end'] = self._io.pos()
+ self._debug['n_local_sym']['start'] = self._io.pos()
+ self.n_local_sym = self._io.read_u4le()
+ self._debug['n_local_sym']['end'] = self._io.pos()
+ self._debug['i_ext_def_sym']['start'] = self._io.pos()
+ self.i_ext_def_sym = self._io.read_u4le()
+ self._debug['i_ext_def_sym']['end'] = self._io.pos()
+ self._debug['n_ext_def_sym']['start'] = self._io.pos()
+ self.n_ext_def_sym = self._io.read_u4le()
+ self._debug['n_ext_def_sym']['end'] = self._io.pos()
+ self._debug['i_undef_sym']['start'] = self._io.pos()
+ self.i_undef_sym = self._io.read_u4le()
+ self._debug['i_undef_sym']['end'] = self._io.pos()
+ self._debug['n_undef_sym']['start'] = self._io.pos()
+ self.n_undef_sym = self._io.read_u4le()
+ self._debug['n_undef_sym']['end'] = self._io.pos()
+ self._debug['toc_off']['start'] = self._io.pos()
+ self.toc_off = self._io.read_u4le()
+ self._debug['toc_off']['end'] = self._io.pos()
+ self._debug['n_toc']['start'] = self._io.pos()
+ self.n_toc = self._io.read_u4le()
+ self._debug['n_toc']['end'] = self._io.pos()
+ self._debug['mod_tab_off']['start'] = self._io.pos()
+ self.mod_tab_off = self._io.read_u4le()
+ self._debug['mod_tab_off']['end'] = self._io.pos()
+ self._debug['n_mod_tab']['start'] = self._io.pos()
+ self.n_mod_tab = self._io.read_u4le()
+ self._debug['n_mod_tab']['end'] = self._io.pos()
+ self._debug['ext_ref_sym_off']['start'] = self._io.pos()
+ self.ext_ref_sym_off = self._io.read_u4le()
+ self._debug['ext_ref_sym_off']['end'] = self._io.pos()
+ self._debug['n_ext_ref_syms']['start'] = self._io.pos()
+ self.n_ext_ref_syms = self._io.read_u4le()
+ self._debug['n_ext_ref_syms']['end'] = self._io.pos()
+ self._debug['indirect_sym_off']['start'] = self._io.pos()
+ self.indirect_sym_off = self._io.read_u4le()
+ self._debug['indirect_sym_off']['end'] = self._io.pos()
+ self._debug['n_indirect_syms']['start'] = self._io.pos()
+ self.n_indirect_syms = self._io.read_u4le()
+ self._debug['n_indirect_syms']['end'] = self._io.pos()
+ self._debug['ext_rel_off']['start'] = self._io.pos()
+ self.ext_rel_off = self._io.read_u4le()
+ self._debug['ext_rel_off']['end'] = self._io.pos()
+ self._debug['n_ext_rel']['start'] = self._io.pos()
+ self.n_ext_rel = self._io.read_u4le()
+ self._debug['n_ext_rel']['end'] = self._io.pos()
+ self._debug['loc_rel_off']['start'] = self._io.pos()
+ self.loc_rel_off = self._io.read_u4le()
+ self._debug['loc_rel_off']['end'] = self._io.pos()
+ self._debug['n_loc_rel']['start'] = self._io.pos()
+ self.n_loc_rel = self._io.read_u4le()
+ self._debug['n_loc_rel']['end'] = self._io.pos()
+
+ @property
+ def indirect_symbols(self):
+ if hasattr(self, '_m_indirect_symbols'):
+ return self._m_indirect_symbols if hasattr(self, '_m_indirect_symbols') else None
+
+ io = self._root._io
+ _pos = io.pos()
+ io.seek(self.indirect_sym_off)
+ self._debug['_m_indirect_symbols']['start'] = io.pos()
+ self._m_indirect_symbols = [None] * (self.n_indirect_syms)
+ for i in range(self.n_indirect_syms):
+ if not 'arr' in self._debug['_m_indirect_symbols']:
+ self._debug['_m_indirect_symbols']['arr'] = []
+ self._debug['_m_indirect_symbols']['arr'].append({'start': io.pos()})
+ self._m_indirect_symbols[i] = io.read_u4le()
+ self._debug['_m_indirect_symbols']['arr'][i]['end'] = io.pos()
+
+ self._debug['_m_indirect_symbols']['end'] = io.pos()
+ io.seek(_pos)
+ return self._m_indirect_symbols if hasattr(self, '_m_indirect_symbols') else None
+
+
+ class MachHeader(KaitaiStruct):
+ SEQ_FIELDS = ["cputype", "cpusubtype", "filetype", "ncmds", "sizeofcmds", "flags", "reserved"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['cputype']['start'] = self._io.pos()
+ self.cputype = KaitaiStream.resolve_enum(self._root.CpuType, self._io.read_u4le())
+ self._debug['cputype']['end'] = self._io.pos()
+ self._debug['cpusubtype']['start'] = self._io.pos()
+ self.cpusubtype = self._io.read_u4le()
+ self._debug['cpusubtype']['end'] = self._io.pos()
+ self._debug['filetype']['start'] = self._io.pos()
+ self.filetype = KaitaiStream.resolve_enum(self._root.FileType, self._io.read_u4le())
+ self._debug['filetype']['end'] = self._io.pos()
+ self._debug['ncmds']['start'] = self._io.pos()
+ self.ncmds = self._io.read_u4le()
+ self._debug['ncmds']['end'] = self._io.pos()
+ self._debug['sizeofcmds']['start'] = self._io.pos()
+ self.sizeofcmds = self._io.read_u4le()
+ self._debug['sizeofcmds']['end'] = self._io.pos()
+ self._debug['flags']['start'] = self._io.pos()
+ self.flags = self._io.read_u4le()
+ self._debug['flags']['end'] = self._io.pos()
+ if ((self._root.magic == self._root.MagicType.macho_be_x64) or (self._root.magic == self._root.MagicType.macho_le_x64)) :
+ self._debug['reserved']['start'] = self._io.pos()
+ self.reserved = self._io.read_u4le()
+ self._debug['reserved']['end'] = self._io.pos()
+
+
+ @property
+ def flags_obj(self):
+ if hasattr(self, '_m_flags_obj'):
+ return self._m_flags_obj if hasattr(self, '_m_flags_obj') else None
+
+ self._debug['_m_flags_obj']['start'] = self._io.pos()
+ self._m_flags_obj = self._root.MachoFlags(self.flags, self._io, self, self._root)
+ self._m_flags_obj._read()
+ self._debug['_m_flags_obj']['end'] = self._io.pos()
+ return self._m_flags_obj if hasattr(self, '_m_flags_obj') else None
+
+
+ class LinkeditDataCommand(KaitaiStruct):
+ SEQ_FIELDS = ["data_off", "data_size"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['data_off']['start'] = self._io.pos()
+ self.data_off = self._io.read_u4le()
+ self._debug['data_off']['end'] = self._io.pos()
+ self._debug['data_size']['start'] = self._io.pos()
+ self.data_size = self._io.read_u4le()
+ self._debug['data_size']['end'] = self._io.pos()
+
+
+ class SubCommand(KaitaiStruct):
+ SEQ_FIELDS = ["name"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['name']['start'] = self._io.pos()
+ self.name = self._root.LcStr(self._io, self, self._root)
+ self.name._read()
+ self._debug['name']['end'] = self._io.pos()
+
+
+ class TwolevelHintsCommand(KaitaiStruct):
+ SEQ_FIELDS = ["offset", "num_hints"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['offset']['start'] = self._io.pos()
+ self.offset = self._io.read_u4le()
+ self._debug['offset']['end'] = self._io.pos()
+ self._debug['num_hints']['start'] = self._io.pos()
+ self.num_hints = self._io.read_u4le()
+ self._debug['num_hints']['end'] = self._io.pos()
+
+
+ class Version(KaitaiStruct):
+ SEQ_FIELDS = ["p1", "minor", "major", "release"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['p1']['start'] = self._io.pos()
+ self.p1 = self._io.read_u1()
+ self._debug['p1']['end'] = self._io.pos()
+ self._debug['minor']['start'] = self._io.pos()
+ self.minor = self._io.read_u1()
+ self._debug['minor']['end'] = self._io.pos()
+ self._debug['major']['start'] = self._io.pos()
+ self.major = self._io.read_u1()
+ self._debug['major']['end'] = self._io.pos()
+ self._debug['release']['start'] = self._io.pos()
+ self.release = self._io.read_u1()
+ self._debug['release']['end'] = self._io.pos()
+
+
+ class EncryptionInfoCommand(KaitaiStruct):
+ SEQ_FIELDS = ["cryptoff", "cryptsize", "cryptid", "pad"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['cryptoff']['start'] = self._io.pos()
+ self.cryptoff = self._io.read_u4le()
+ self._debug['cryptoff']['end'] = self._io.pos()
+ self._debug['cryptsize']['start'] = self._io.pos()
+ self.cryptsize = self._io.read_u4le()
+ self._debug['cryptsize']['end'] = self._io.pos()
+ self._debug['cryptid']['start'] = self._io.pos()
+ self.cryptid = self._io.read_u4le()
+ self._debug['cryptid']['end'] = self._io.pos()
+ if ((self._root.magic == self._root.MagicType.macho_be_x64) or (self._root.magic == self._root.MagicType.macho_le_x64)) :
+ self._debug['pad']['start'] = self._io.pos()
+ self.pad = self._io.read_u4le()
+ self._debug['pad']['end'] = self._io.pos()
+
+
+
+ class CodeSignatureCommand(KaitaiStruct):
+ SEQ_FIELDS = ["data_off", "data_size"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['data_off']['start'] = self._io.pos()
+ self.data_off = self._io.read_u4le()
+ self._debug['data_off']['end'] = self._io.pos()
+ self._debug['data_size']['start'] = self._io.pos()
+ self.data_size = self._io.read_u4le()
+ self._debug['data_size']['end'] = self._io.pos()
+
+ @property
+ def code_signature(self):
+ if hasattr(self, '_m_code_signature'):
+ return self._m_code_signature if hasattr(self, '_m_code_signature') else None
+
+ io = self._root._io
+ _pos = io.pos()
+ io.seek(self.data_off)
+ self._debug['_m_code_signature']['start'] = io.pos()
+ self._raw__m_code_signature = io.read_bytes(self.data_size)
+ io = KaitaiStream(BytesIO(self._raw__m_code_signature))
+ self._m_code_signature = self._root.CsBlob(io, self, self._root)
+ self._m_code_signature._read()
+ self._debug['_m_code_signature']['end'] = io.pos()
+ io.seek(_pos)
+ return self._m_code_signature if hasattr(self, '_m_code_signature') else None
+
+
+ class DyldInfoCommand(KaitaiStruct):
+
+ class BindOpcode(Enum):
+ done = 0
+ set_dylib_ordinal_immediate = 16
+ set_dylib_ordinal_uleb = 32
+ set_dylib_special_immediate = 48
+ set_symbol_trailing_flags_immediate = 64
+ set_type_immediate = 80
+ set_append_sleb = 96
+ set_segment_and_offset_uleb = 112
+ add_address_uleb = 128
+ do_bind = 144
+ do_bind_add_address_uleb = 160
+ do_bind_add_address_immediate_scaled = 176
+ do_bind_uleb_times_skipping_uleb = 192
+ SEQ_FIELDS = ["rebase_off", "rebase_size", "bind_off", "bind_size", "weak_bind_off", "weak_bind_size", "lazy_bind_off", "lazy_bind_size", "export_off", "export_size"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['rebase_off']['start'] = self._io.pos()
+ self.rebase_off = self._io.read_u4le()
+ self._debug['rebase_off']['end'] = self._io.pos()
+ self._debug['rebase_size']['start'] = self._io.pos()
+ self.rebase_size = self._io.read_u4le()
+ self._debug['rebase_size']['end'] = self._io.pos()
+ self._debug['bind_off']['start'] = self._io.pos()
+ self.bind_off = self._io.read_u4le()
+ self._debug['bind_off']['end'] = self._io.pos()
+ self._debug['bind_size']['start'] = self._io.pos()
+ self.bind_size = self._io.read_u4le()
+ self._debug['bind_size']['end'] = self._io.pos()
+ self._debug['weak_bind_off']['start'] = self._io.pos()
+ self.weak_bind_off = self._io.read_u4le()
+ self._debug['weak_bind_off']['end'] = self._io.pos()
+ self._debug['weak_bind_size']['start'] = self._io.pos()
+ self.weak_bind_size = self._io.read_u4le()
+ self._debug['weak_bind_size']['end'] = self._io.pos()
+ self._debug['lazy_bind_off']['start'] = self._io.pos()
+ self.lazy_bind_off = self._io.read_u4le()
+ self._debug['lazy_bind_off']['end'] = self._io.pos()
+ self._debug['lazy_bind_size']['start'] = self._io.pos()
+ self.lazy_bind_size = self._io.read_u4le()
+ self._debug['lazy_bind_size']['end'] = self._io.pos()
+ self._debug['export_off']['start'] = self._io.pos()
+ self.export_off = self._io.read_u4le()
+ self._debug['export_off']['end'] = self._io.pos()
+ self._debug['export_size']['start'] = self._io.pos()
+ self.export_size = self._io.read_u4le()
+ self._debug['export_size']['end'] = self._io.pos()
+
+ class BindItem(KaitaiStruct):
+ SEQ_FIELDS = ["opcode_and_immediate", "uleb", "skip", "symbol"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['opcode_and_immediate']['start'] = self._io.pos()
+ self.opcode_and_immediate = self._io.read_u1()
+ self._debug['opcode_and_immediate']['end'] = self._io.pos()
+ if ((self.opcode == self._root.DyldInfoCommand.BindOpcode.set_dylib_ordinal_uleb) or (self.opcode == self._root.DyldInfoCommand.BindOpcode.set_append_sleb) or (self.opcode == self._root.DyldInfoCommand.BindOpcode.set_segment_and_offset_uleb) or (self.opcode == self._root.DyldInfoCommand.BindOpcode.add_address_uleb) or (self.opcode == self._root.DyldInfoCommand.BindOpcode.do_bind_add_address_uleb) or (self.opcode == self._root.DyldInfoCommand.BindOpcode.do_bind_uleb_times_skipping_uleb)) :
+ self._debug['uleb']['start'] = self._io.pos()
+ self.uleb = self._root.Uleb128(self._io, self, self._root)
+ self.uleb._read()
+ self._debug['uleb']['end'] = self._io.pos()
+
+ if self.opcode == self._root.DyldInfoCommand.BindOpcode.do_bind_uleb_times_skipping_uleb:
+ self._debug['skip']['start'] = self._io.pos()
+ self.skip = self._root.Uleb128(self._io, self, self._root)
+ self.skip._read()
+ self._debug['skip']['end'] = self._io.pos()
+
+ if self.opcode == self._root.DyldInfoCommand.BindOpcode.set_symbol_trailing_flags_immediate:
+ self._debug['symbol']['start'] = self._io.pos()
+ self.symbol = (self._io.read_bytes_term(0, False, True, True)).decode(u"ascii")
+ self._debug['symbol']['end'] = self._io.pos()
+
+
+ @property
+ def opcode(self):
+ if hasattr(self, '_m_opcode'):
+ return self._m_opcode if hasattr(self, '_m_opcode') else None
+
+ self._m_opcode = KaitaiStream.resolve_enum(self._root.DyldInfoCommand.BindOpcode, (self.opcode_and_immediate & 240))
+ return self._m_opcode if hasattr(self, '_m_opcode') else None
+
+ @property
+ def immediate(self):
+ if hasattr(self, '_m_immediate'):
+ return self._m_immediate if hasattr(self, '_m_immediate') else None
+
+ self._m_immediate = (self.opcode_and_immediate & 15)
+ return self._m_immediate if hasattr(self, '_m_immediate') else None
+
+
+ class RebaseData(KaitaiStruct):
+
+ class Opcode(Enum):
+ done = 0
+ set_type_immediate = 16
+ set_segment_and_offset_uleb = 32
+ add_address_uleb = 48
+ add_address_immediate_scaled = 64
+ do_rebase_immediate_times = 80
+ do_rebase_uleb_times = 96
+ do_rebase_add_address_uleb = 112
+ do_rebase_uleb_times_skipping_uleb = 128
+ SEQ_FIELDS = ["items"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['items']['start'] = self._io.pos()
+ self.items = []
+ i = 0
+ while True:
+ if not 'arr' in self._debug['items']:
+ self._debug['items']['arr'] = []
+ self._debug['items']['arr'].append({'start': self._io.pos()})
+ _t_items = self._root.DyldInfoCommand.RebaseData.RebaseItem(self._io, self, self._root)
+ _t_items._read()
+ _ = _t_items
+ self.items.append(_)
+ self._debug['items']['arr'][len(self.items) - 1]['end'] = self._io.pos()
+ if _.opcode == self._root.DyldInfoCommand.RebaseData.Opcode.done:
+ break
+ i += 1
+ self._debug['items']['end'] = self._io.pos()
+
+ class RebaseItem(KaitaiStruct):
+ SEQ_FIELDS = ["opcode_and_immediate", "uleb", "skip"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['opcode_and_immediate']['start'] = self._io.pos()
+ self.opcode_and_immediate = self._io.read_u1()
+ self._debug['opcode_and_immediate']['end'] = self._io.pos()
+ if ((self.opcode == self._root.DyldInfoCommand.RebaseData.Opcode.set_segment_and_offset_uleb) or (self.opcode == self._root.DyldInfoCommand.RebaseData.Opcode.add_address_uleb) or (self.opcode == self._root.DyldInfoCommand.RebaseData.Opcode.do_rebase_uleb_times) or (self.opcode == self._root.DyldInfoCommand.RebaseData.Opcode.do_rebase_add_address_uleb) or (self.opcode == self._root.DyldInfoCommand.RebaseData.Opcode.do_rebase_uleb_times_skipping_uleb)) :
+ self._debug['uleb']['start'] = self._io.pos()
+ self.uleb = self._root.Uleb128(self._io, self, self._root)
+ self.uleb._read()
+ self._debug['uleb']['end'] = self._io.pos()
+
+ if self.opcode == self._root.DyldInfoCommand.RebaseData.Opcode.do_rebase_uleb_times_skipping_uleb:
+ self._debug['skip']['start'] = self._io.pos()
+ self.skip = self._root.Uleb128(self._io, self, self._root)
+ self.skip._read()
+ self._debug['skip']['end'] = self._io.pos()
+
+
+ @property
+ def opcode(self):
+ if hasattr(self, '_m_opcode'):
+ return self._m_opcode if hasattr(self, '_m_opcode') else None
+
+ self._m_opcode = KaitaiStream.resolve_enum(self._root.DyldInfoCommand.RebaseData.Opcode, (self.opcode_and_immediate & 240))
+ return self._m_opcode if hasattr(self, '_m_opcode') else None
+
+ @property
+ def immediate(self):
+ if hasattr(self, '_m_immediate'):
+ return self._m_immediate if hasattr(self, '_m_immediate') else None
+
+ self._m_immediate = (self.opcode_and_immediate & 15)
+ return self._m_immediate if hasattr(self, '_m_immediate') else None
+
+
+
+ class ExportNode(KaitaiStruct):
+ SEQ_FIELDS = ["terminal_size", "children_count", "children", "terminal"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['terminal_size']['start'] = self._io.pos()
+ self.terminal_size = self._root.Uleb128(self._io, self, self._root)
+ self.terminal_size._read()
+ self._debug['terminal_size']['end'] = self._io.pos()
+ self._debug['children_count']['start'] = self._io.pos()
+ self.children_count = self._io.read_u1()
+ self._debug['children_count']['end'] = self._io.pos()
+ self._debug['children']['start'] = self._io.pos()
+ self.children = [None] * (self.children_count)
+ for i in range(self.children_count):
+ if not 'arr' in self._debug['children']:
+ self._debug['children']['arr'] = []
+ self._debug['children']['arr'].append({'start': self._io.pos()})
+ _t_children = self._root.DyldInfoCommand.ExportNode.Child(self._io, self, self._root)
+ _t_children._read()
+ self.children[i] = _t_children
+ self._debug['children']['arr'][i]['end'] = self._io.pos()
+
+ self._debug['children']['end'] = self._io.pos()
+ self._debug['terminal']['start'] = self._io.pos()
+ self.terminal = self._io.read_bytes(self.terminal_size.value)
+ self._debug['terminal']['end'] = self._io.pos()
+
+ class Child(KaitaiStruct):
+ SEQ_FIELDS = ["name", "node_offset"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['name']['start'] = self._io.pos()
+ self.name = (self._io.read_bytes_term(0, False, True, True)).decode(u"ascii")
+ self._debug['name']['end'] = self._io.pos()
+ self._debug['node_offset']['start'] = self._io.pos()
+ self.node_offset = self._root.Uleb128(self._io, self, self._root)
+ self.node_offset._read()
+ self._debug['node_offset']['end'] = self._io.pos()
+
+ @property
+ def value(self):
+ if hasattr(self, '_m_value'):
+ return self._m_value if hasattr(self, '_m_value') else None
+
+ _pos = self._io.pos()
+ self._io.seek(self.node_offset.value)
+ self._debug['_m_value']['start'] = self._io.pos()
+ self._m_value = self._root.DyldInfoCommand.ExportNode(self._io, self, self._root)
+ self._m_value._read()
+ self._debug['_m_value']['end'] = self._io.pos()
+ self._io.seek(_pos)
+ return self._m_value if hasattr(self, '_m_value') else None
+
+
+
+ class BindData(KaitaiStruct):
+ SEQ_FIELDS = ["items"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['items']['start'] = self._io.pos()
+ self.items = []
+ i = 0
+ while True:
+ if not 'arr' in self._debug['items']:
+ self._debug['items']['arr'] = []
+ self._debug['items']['arr'].append({'start': self._io.pos()})
+ _t_items = self._root.DyldInfoCommand.BindItem(self._io, self, self._root)
+ _t_items._read()
+ _ = _t_items
+ self.items.append(_)
+ self._debug['items']['arr'][len(self.items) - 1]['end'] = self._io.pos()
+ if _.opcode == self._root.DyldInfoCommand.BindOpcode.done:
+ break
+ i += 1
+ self._debug['items']['end'] = self._io.pos()
+
+
+ class LazyBindData(KaitaiStruct):
+ SEQ_FIELDS = ["items"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['items']['start'] = self._io.pos()
+ self.items = []
+ i = 0
+ while not self._io.is_eof():
+ if not 'arr' in self._debug['items']:
+ self._debug['items']['arr'] = []
+ self._debug['items']['arr'].append({'start': self._io.pos()})
+ _t_items = self._root.DyldInfoCommand.BindItem(self._io, self, self._root)
+ _t_items._read()
+ self.items.append(_t_items)
+ self._debug['items']['arr'][len(self.items) - 1]['end'] = self._io.pos()
+ i += 1
+
+ self._debug['items']['end'] = self._io.pos()
+
+
+ @property
+ def rebase(self):
+ if hasattr(self, '_m_rebase'):
+ return self._m_rebase if hasattr(self, '_m_rebase') else None
+
+ io = self._root._io
+ _pos = io.pos()
+ io.seek(self.rebase_off)
+ self._debug['_m_rebase']['start'] = io.pos()
+ self._raw__m_rebase = io.read_bytes(self.rebase_size)
+ io = KaitaiStream(BytesIO(self._raw__m_rebase))
+ self._m_rebase = self._root.DyldInfoCommand.RebaseData(io, self, self._root)
+ self._m_rebase._read()
+ self._debug['_m_rebase']['end'] = io.pos()
+ io.seek(_pos)
+ return self._m_rebase if hasattr(self, '_m_rebase') else None
+
+ @property
+ def bind(self):
+ if hasattr(self, '_m_bind'):
+ return self._m_bind if hasattr(self, '_m_bind') else None
+
+ io = self._root._io
+ _pos = io.pos()
+ io.seek(self.bind_off)
+ self._debug['_m_bind']['start'] = io.pos()
+ self._raw__m_bind = io.read_bytes(self.bind_size)
+ io = KaitaiStream(BytesIO(self._raw__m_bind))
+ self._m_bind = self._root.DyldInfoCommand.BindData(io, self, self._root)
+ self._m_bind._read()
+ self._debug['_m_bind']['end'] = io.pos()
+ io.seek(_pos)
+ return self._m_bind if hasattr(self, '_m_bind') else None
+
+ @property
+ def lazy_bind(self):
+ if hasattr(self, '_m_lazy_bind'):
+ return self._m_lazy_bind if hasattr(self, '_m_lazy_bind') else None
+
+ io = self._root._io
+ _pos = io.pos()
+ io.seek(self.lazy_bind_off)
+ self._debug['_m_lazy_bind']['start'] = io.pos()
+ self._raw__m_lazy_bind = io.read_bytes(self.lazy_bind_size)
+ io = KaitaiStream(BytesIO(self._raw__m_lazy_bind))
+ self._m_lazy_bind = self._root.DyldInfoCommand.LazyBindData(io, self, self._root)
+ self._m_lazy_bind._read()
+ self._debug['_m_lazy_bind']['end'] = io.pos()
+ io.seek(_pos)
+ return self._m_lazy_bind if hasattr(self, '_m_lazy_bind') else None
+
+ @property
+ def exports(self):
+ if hasattr(self, '_m_exports'):
+ return self._m_exports if hasattr(self, '_m_exports') else None
+
+ io = self._root._io
+ _pos = io.pos()
+ io.seek(self.export_off)
+ self._debug['_m_exports']['start'] = io.pos()
+ self._raw__m_exports = io.read_bytes(self.export_size)
+ io = KaitaiStream(BytesIO(self._raw__m_exports))
+ self._m_exports = self._root.DyldInfoCommand.ExportNode(io, self, self._root)
+ self._m_exports._read()
+ self._debug['_m_exports']['end'] = io.pos()
+ io.seek(_pos)
+ return self._m_exports if hasattr(self, '_m_exports') else None
+
+
+ class DylinkerCommand(KaitaiStruct):
+ SEQ_FIELDS = ["name"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['name']['start'] = self._io.pos()
+ self.name = self._root.LcStr(self._io, self, self._root)
+ self.name._read()
+ self._debug['name']['end'] = self._io.pos()
+
+
+ class DylibCommand(KaitaiStruct):
+ SEQ_FIELDS = ["name_offset", "timestamp", "current_version", "compatibility_version", "name"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['name_offset']['start'] = self._io.pos()
+ self.name_offset = self._io.read_u4le()
+ self._debug['name_offset']['end'] = self._io.pos()
+ self._debug['timestamp']['start'] = self._io.pos()
+ self.timestamp = self._io.read_u4le()
+ self._debug['timestamp']['end'] = self._io.pos()
+ self._debug['current_version']['start'] = self._io.pos()
+ self.current_version = self._io.read_u4le()
+ self._debug['current_version']['end'] = self._io.pos()
+ self._debug['compatibility_version']['start'] = self._io.pos()
+ self.compatibility_version = self._io.read_u4le()
+ self._debug['compatibility_version']['end'] = self._io.pos()
+ self._debug['name']['start'] = self._io.pos()
+ self.name = (self._io.read_bytes_term(0, False, True, True)).decode(u"utf-8")
+ self._debug['name']['end'] = self._io.pos()
+
+
+ class LcStr(KaitaiStruct):
+ SEQ_FIELDS = ["length", "value"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['length']['start'] = self._io.pos()
+ self.length = self._io.read_u4le()
+ self._debug['length']['end'] = self._io.pos()
+ self._debug['value']['start'] = self._io.pos()
+ self.value = (self._io.read_bytes_term(0, False, True, True)).decode(u"UTF-8")
+ self._debug['value']['end'] = self._io.pos()
+
+
+ class LoadCommand(KaitaiStruct):
+ SEQ_FIELDS = ["type", "size", "body"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['type']['start'] = self._io.pos()
+ self.type = KaitaiStream.resolve_enum(self._root.LoadCommandType, self._io.read_u4le())
+ self._debug['type']['end'] = self._io.pos()
+ self._debug['size']['start'] = self._io.pos()
+ self.size = self._io.read_u4le()
+ self._debug['size']['end'] = self._io.pos()
+ self._debug['body']['start'] = self._io.pos()
+ _on = self.type
+ if _on == self._root.LoadCommandType.id_dylinker:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.DylinkerCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.reexport_dylib:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.DylibCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.source_version:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.SourceVersionCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.function_starts:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.LinkeditDataCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.rpath:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.RpathCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.sub_framework:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.SubCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.routines:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.RoutinesCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.sub_library:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.SubCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.dyld_info_only:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.DyldInfoCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.dyld_environment:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.DylinkerCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.load_dylinker:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.DylinkerCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.segment_split_info:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.LinkeditDataCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.main:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.EntryPointCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.load_dylib:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.DylibCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.encryption_info:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.EncryptionInfoCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.dysymtab:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.DysymtabCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.twolevel_hints:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.TwolevelHintsCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.encryption_info_64:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.EncryptionInfoCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.linker_option:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.LinkerOptionCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.dyld_info:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.DyldInfoCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.version_min_tvos:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.VersionMinCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.load_upward_dylib:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.DylibCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.segment_64:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.SegmentCommand64(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.sub_umbrella:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.SubCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.version_min_watchos:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.VersionMinCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.routines_64:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.RoutinesCommand64(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.id_dylib:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.DylibCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.sub_client:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.SubCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.dylib_code_sign_drs:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.LinkeditDataCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.symtab:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.SymtabCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.linker_optimization_hint:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.LinkeditDataCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.data_in_code:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.LinkeditDataCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.code_signature:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.CodeSignatureCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.version_min_iphoneos:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.VersionMinCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.load_weak_dylib:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.DylibCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.lazy_load_dylib:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.DylibCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.uuid:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.UuidCommand(io, self, self._root)
+ self.body._read()
+ elif _on == self._root.LoadCommandType.version_min_macosx:
+ self._raw_body = self._io.read_bytes((self.size - 8))
+ io = KaitaiStream(BytesIO(self._raw_body))
+ self.body = self._root.VersionMinCommand(io, self, self._root)
+ self.body._read()
+ else:
+ self.body = self._io.read_bytes((self.size - 8))
+ self._debug['body']['end'] = self._io.pos()
+
+
+ class UuidCommand(KaitaiStruct):
+ SEQ_FIELDS = ["uuid"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['uuid']['start'] = self._io.pos()
+ self.uuid = self._io.read_bytes(16)
+ self._debug['uuid']['end'] = self._io.pos()
+
+
+ class SymtabCommand(KaitaiStruct):
+ SEQ_FIELDS = ["sym_off", "n_syms", "str_off", "str_size"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['sym_off']['start'] = self._io.pos()
+ self.sym_off = self._io.read_u4le()
+ self._debug['sym_off']['end'] = self._io.pos()
+ self._debug['n_syms']['start'] = self._io.pos()
+ self.n_syms = self._io.read_u4le()
+ self._debug['n_syms']['end'] = self._io.pos()
+ self._debug['str_off']['start'] = self._io.pos()
+ self.str_off = self._io.read_u4le()
+ self._debug['str_off']['end'] = self._io.pos()
+ self._debug['str_size']['start'] = self._io.pos()
+ self.str_size = self._io.read_u4le()
+ self._debug['str_size']['end'] = self._io.pos()
+
+ class StrTable(KaitaiStruct):
+ SEQ_FIELDS = ["unknown", "items"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['unknown']['start'] = self._io.pos()
+ self.unknown = self._io.read_u4le()
+ self._debug['unknown']['end'] = self._io.pos()
+ self._debug['items']['start'] = self._io.pos()
+ self.items = []
+ i = 0
+ while True:
+ if not 'arr' in self._debug['items']:
+ self._debug['items']['arr'] = []
+ self._debug['items']['arr'].append({'start': self._io.pos()})
+ _ = (self._io.read_bytes_term(0, False, True, True)).decode(u"ascii")
+ self.items.append(_)
+ self._debug['items']['arr'][len(self.items) - 1]['end'] = self._io.pos()
+ if _ == u"":
+ break
+ i += 1
+ self._debug['items']['end'] = self._io.pos()
+
+
+ class Nlist64(KaitaiStruct):
+ SEQ_FIELDS = ["un", "type", "sect", "desc", "value"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['un']['start'] = self._io.pos()
+ self.un = self._io.read_u4le()
+ self._debug['un']['end'] = self._io.pos()
+ self._debug['type']['start'] = self._io.pos()
+ self.type = self._io.read_u1()
+ self._debug['type']['end'] = self._io.pos()
+ self._debug['sect']['start'] = self._io.pos()
+ self.sect = self._io.read_u1()
+ self._debug['sect']['end'] = self._io.pos()
+ self._debug['desc']['start'] = self._io.pos()
+ self.desc = self._io.read_u2le()
+ self._debug['desc']['end'] = self._io.pos()
+ self._debug['value']['start'] = self._io.pos()
+ self.value = self._io.read_u8le()
+ self._debug['value']['end'] = self._io.pos()
+
+
+ @property
+ def symbols(self):
+ if hasattr(self, '_m_symbols'):
+ return self._m_symbols if hasattr(self, '_m_symbols') else None
+
+ io = self._root._io
+ _pos = io.pos()
+ io.seek(self.sym_off)
+ self._debug['_m_symbols']['start'] = io.pos()
+ self._m_symbols = [None] * (self.n_syms)
+ for i in range(self.n_syms):
+ if not 'arr' in self._debug['_m_symbols']:
+ self._debug['_m_symbols']['arr'] = []
+ self._debug['_m_symbols']['arr'].append({'start': io.pos()})
+ _t__m_symbols = self._root.SymtabCommand.Nlist64(io, self, self._root)
+ _t__m_symbols._read()
+ self._m_symbols[i] = _t__m_symbols
+ self._debug['_m_symbols']['arr'][i]['end'] = io.pos()
+
+ self._debug['_m_symbols']['end'] = io.pos()
+ io.seek(_pos)
+ return self._m_symbols if hasattr(self, '_m_symbols') else None
+
+ @property
+ def strs(self):
+ if hasattr(self, '_m_strs'):
+ return self._m_strs if hasattr(self, '_m_strs') else None
+
+ io = self._root._io
+ _pos = io.pos()
+ io.seek(self.str_off)
+ self._debug['_m_strs']['start'] = io.pos()
+ self._raw__m_strs = io.read_bytes(self.str_size)
+ io = KaitaiStream(BytesIO(self._raw__m_strs))
+ self._m_strs = self._root.SymtabCommand.StrTable(io, self, self._root)
+ self._m_strs._read()
+ self._debug['_m_strs']['end'] = io.pos()
+ io.seek(_pos)
+ return self._m_strs if hasattr(self, '_m_strs') else None
+
+
+ class VersionMinCommand(KaitaiStruct):
+ SEQ_FIELDS = ["version", "sdk"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['version']['start'] = self._io.pos()
+ self.version = self._root.Version(self._io, self, self._root)
+ self.version._read()
+ self._debug['version']['end'] = self._io.pos()
+ self._debug['sdk']['start'] = self._io.pos()
+ self.sdk = self._root.Version(self._io, self, self._root)
+ self.sdk._read()
+ self._debug['sdk']['end'] = self._io.pos()
+
+
+ class EntryPointCommand(KaitaiStruct):
+ SEQ_FIELDS = ["entry_off", "stack_size"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['entry_off']['start'] = self._io.pos()
+ self.entry_off = self._io.read_u8le()
+ self._debug['entry_off']['end'] = self._io.pos()
+ self._debug['stack_size']['start'] = self._io.pos()
+ self.stack_size = self._io.read_u8le()
+ self._debug['stack_size']['end'] = self._io.pos()
+
+
+
diff --git a/python/examples/kaitai/microsoft_pe.py b/python/examples/kaitai/microsoft_pe.py
new file mode 100644
index 00000000..0c8fcc1f
--- /dev/null
+++ b/python/examples/kaitai/microsoft_pe.py
@@ -0,0 +1,758 @@
+# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
+
+from pkg_resources import parse_version
+from kaitaistruct import __version__ as ks_version, KaitaiStruct, KaitaiStream, BytesIO
+from enum import Enum
+import collections
+
+
+if parse_version(ks_version) < parse_version('0.7'):
+ raise Exception("Incompatible Kaitai Struct Python API: 0.7 or later is required, but you have %s" % (ks_version))
+
+class MicrosoftPe(KaitaiStruct):
+ """
+ .. seealso::
+ Source - http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx
+ """
+
+ class PeFormat(Enum):
+ rom_image = 263
+ pe32 = 267
+ pe32_plus = 523
+ SEQ_FIELDS = ["mz"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['mz']['start'] = self._io.pos()
+ self.mz = self._root.MzPlaceholder(self._io, self, self._root)
+ self.mz._read()
+ self._debug['mz']['end'] = self._io.pos()
+
+ class CertificateEntry(KaitaiStruct):
+ """
+ .. seealso::
+ Source - https://docs.microsoft.com/en-us/windows/desktop/debug/pe-format#the-attribute-certificate-table-image-only
+ """
+
+ class CertificateRevision(Enum):
+ revision_1_0 = 256
+ revision_2_0 = 512
+
+ class CertificateType(Enum):
+ x509 = 1
+ pkcs_signed_data = 2
+ reserved_1 = 3
+ ts_stack_signed = 4
+ SEQ_FIELDS = ["length", "revision", "certificate_type", "certificate_bytes"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['length']['start'] = self._io.pos()
+ self.length = self._io.read_u4le()
+ self._debug['length']['end'] = self._io.pos()
+ self._debug['revision']['start'] = self._io.pos()
+ self.revision = KaitaiStream.resolve_enum(self._root.CertificateEntry.CertificateRevision, self._io.read_u2le())
+ self._debug['revision']['end'] = self._io.pos()
+ self._debug['certificate_type']['start'] = self._io.pos()
+ self.certificate_type = KaitaiStream.resolve_enum(self._root.CertificateEntry.CertificateType, self._io.read_u2le())
+ self._debug['certificate_type']['end'] = self._io.pos()
+ self._debug['certificate_bytes']['start'] = self._io.pos()
+ self.certificate_bytes = self._io.read_bytes((self.length - 8))
+ self._debug['certificate_bytes']['end'] = self._io.pos()
+
+
+ class OptionalHeaderWindows(KaitaiStruct):
+
+ class SubsystemEnum(Enum):
+ unknown = 0
+ native = 1
+ windows_gui = 2
+ windows_cui = 3
+ posix_cui = 7
+ windows_ce_gui = 9
+ efi_application = 10
+ efi_boot_service_driver = 11
+ efi_runtime_driver = 12
+ efi_rom = 13
+ xbox = 14
+ windows_boot_application = 16
+ SEQ_FIELDS = ["image_base_32", "image_base_64", "section_alignment", "file_alignment", "major_operating_system_version", "minor_operating_system_version", "major_image_version", "minor_image_version", "major_subsystem_version", "minor_subsystem_version", "win32_version_value", "size_of_image", "size_of_headers", "check_sum", "subsystem", "dll_characteristics", "size_of_stack_reserve_32", "size_of_stack_reserve_64", "size_of_stack_commit_32", "size_of_stack_commit_64", "size_of_heap_reserve_32", "size_of_heap_reserve_64", "size_of_heap_commit_32", "size_of_heap_commit_64", "loader_flags", "number_of_rva_and_sizes"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ if self._parent.std.format == self._root.PeFormat.pe32:
+ self._debug['image_base_32']['start'] = self._io.pos()
+ self.image_base_32 = self._io.read_u4le()
+ self._debug['image_base_32']['end'] = self._io.pos()
+
+ if self._parent.std.format == self._root.PeFormat.pe32_plus:
+ self._debug['image_base_64']['start'] = self._io.pos()
+ self.image_base_64 = self._io.read_u8le()
+ self._debug['image_base_64']['end'] = self._io.pos()
+
+ self._debug['section_alignment']['start'] = self._io.pos()
+ self.section_alignment = self._io.read_u4le()
+ self._debug['section_alignment']['end'] = self._io.pos()
+ self._debug['file_alignment']['start'] = self._io.pos()
+ self.file_alignment = self._io.read_u4le()
+ self._debug['file_alignment']['end'] = self._io.pos()
+ self._debug['major_operating_system_version']['start'] = self._io.pos()
+ self.major_operating_system_version = self._io.read_u2le()
+ self._debug['major_operating_system_version']['end'] = self._io.pos()
+ self._debug['minor_operating_system_version']['start'] = self._io.pos()
+ self.minor_operating_system_version = self._io.read_u2le()
+ self._debug['minor_operating_system_version']['end'] = self._io.pos()
+ self._debug['major_image_version']['start'] = self._io.pos()
+ self.major_image_version = self._io.read_u2le()
+ self._debug['major_image_version']['end'] = self._io.pos()
+ self._debug['minor_image_version']['start'] = self._io.pos()
+ self.minor_image_version = self._io.read_u2le()
+ self._debug['minor_image_version']['end'] = self._io.pos()
+ self._debug['major_subsystem_version']['start'] = self._io.pos()
+ self.major_subsystem_version = self._io.read_u2le()
+ self._debug['major_subsystem_version']['end'] = self._io.pos()
+ self._debug['minor_subsystem_version']['start'] = self._io.pos()
+ self.minor_subsystem_version = self._io.read_u2le()
+ self._debug['minor_subsystem_version']['end'] = self._io.pos()
+ self._debug['win32_version_value']['start'] = self._io.pos()
+ self.win32_version_value = self._io.read_u4le()
+ self._debug['win32_version_value']['end'] = self._io.pos()
+ self._debug['size_of_image']['start'] = self._io.pos()
+ self.size_of_image = self._io.read_u4le()
+ self._debug['size_of_image']['end'] = self._io.pos()
+ self._debug['size_of_headers']['start'] = self._io.pos()
+ self.size_of_headers = self._io.read_u4le()
+ self._debug['size_of_headers']['end'] = self._io.pos()
+ self._debug['check_sum']['start'] = self._io.pos()
+ self.check_sum = self._io.read_u4le()
+ self._debug['check_sum']['end'] = self._io.pos()
+ self._debug['subsystem']['start'] = self._io.pos()
+ self.subsystem = KaitaiStream.resolve_enum(self._root.OptionalHeaderWindows.SubsystemEnum, self._io.read_u2le())
+ self._debug['subsystem']['end'] = self._io.pos()
+ self._debug['dll_characteristics']['start'] = self._io.pos()
+ self.dll_characteristics = self._io.read_u2le()
+ self._debug['dll_characteristics']['end'] = self._io.pos()
+ if self._parent.std.format == self._root.PeFormat.pe32:
+ self._debug['size_of_stack_reserve_32']['start'] = self._io.pos()
+ self.size_of_stack_reserve_32 = self._io.read_u4le()
+ self._debug['size_of_stack_reserve_32']['end'] = self._io.pos()
+
+ if self._parent.std.format == self._root.PeFormat.pe32_plus:
+ self._debug['size_of_stack_reserve_64']['start'] = self._io.pos()
+ self.size_of_stack_reserve_64 = self._io.read_u8le()
+ self._debug['size_of_stack_reserve_64']['end'] = self._io.pos()
+
+ if self._parent.std.format == self._root.PeFormat.pe32:
+ self._debug['size_of_stack_commit_32']['start'] = self._io.pos()
+ self.size_of_stack_commit_32 = self._io.read_u4le()
+ self._debug['size_of_stack_commit_32']['end'] = self._io.pos()
+
+ if self._parent.std.format == self._root.PeFormat.pe32_plus:
+ self._debug['size_of_stack_commit_64']['start'] = self._io.pos()
+ self.size_of_stack_commit_64 = self._io.read_u8le()
+ self._debug['size_of_stack_commit_64']['end'] = self._io.pos()
+
+ if self._parent.std.format == self._root.PeFormat.pe32:
+ self._debug['size_of_heap_reserve_32']['start'] = self._io.pos()
+ self.size_of_heap_reserve_32 = self._io.read_u4le()
+ self._debug['size_of_heap_reserve_32']['end'] = self._io.pos()
+
+ if self._parent.std.format == self._root.PeFormat.pe32_plus:
+ self._debug['size_of_heap_reserve_64']['start'] = self._io.pos()
+ self.size_of_heap_reserve_64 = self._io.read_u8le()
+ self._debug['size_of_heap_reserve_64']['end'] = self._io.pos()
+
+ if self._parent.std.format == self._root.PeFormat.pe32:
+ self._debug['size_of_heap_commit_32']['start'] = self._io.pos()
+ self.size_of_heap_commit_32 = self._io.read_u4le()
+ self._debug['size_of_heap_commit_32']['end'] = self._io.pos()
+
+ if self._parent.std.format == self._root.PeFormat.pe32_plus:
+ self._debug['size_of_heap_commit_64']['start'] = self._io.pos()
+ self.size_of_heap_commit_64 = self._io.read_u8le()
+ self._debug['size_of_heap_commit_64']['end'] = self._io.pos()
+
+ self._debug['loader_flags']['start'] = self._io.pos()
+ self.loader_flags = self._io.read_u4le()
+ self._debug['loader_flags']['end'] = self._io.pos()
+ self._debug['number_of_rva_and_sizes']['start'] = self._io.pos()
+ self.number_of_rva_and_sizes = self._io.read_u4le()
+ self._debug['number_of_rva_and_sizes']['end'] = self._io.pos()
+
+
+ class OptionalHeaderDataDirs(KaitaiStruct):
+ SEQ_FIELDS = ["export_table", "import_table", "resource_table", "exception_table", "certificate_table", "base_relocation_table", "debug", "architecture", "global_ptr", "tls_table", "load_config_table", "bound_import", "iat", "delay_import_descriptor", "clr_runtime_header"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['export_table']['start'] = self._io.pos()
+ self.export_table = self._root.DataDir(self._io, self, self._root)
+ self.export_table._read()
+ self._debug['export_table']['end'] = self._io.pos()
+ self._debug['import_table']['start'] = self._io.pos()
+ self.import_table = self._root.DataDir(self._io, self, self._root)
+ self.import_table._read()
+ self._debug['import_table']['end'] = self._io.pos()
+ self._debug['resource_table']['start'] = self._io.pos()
+ self.resource_table = self._root.DataDir(self._io, self, self._root)
+ self.resource_table._read()
+ self._debug['resource_table']['end'] = self._io.pos()
+ self._debug['exception_table']['start'] = self._io.pos()
+ self.exception_table = self._root.DataDir(self._io, self, self._root)
+ self.exception_table._read()
+ self._debug['exception_table']['end'] = self._io.pos()
+ self._debug['certificate_table']['start'] = self._io.pos()
+ self.certificate_table = self._root.DataDir(self._io, self, self._root)
+ self.certificate_table._read()
+ self._debug['certificate_table']['end'] = self._io.pos()
+ self._debug['base_relocation_table']['start'] = self._io.pos()
+ self.base_relocation_table = self._root.DataDir(self._io, self, self._root)
+ self.base_relocation_table._read()
+ self._debug['base_relocation_table']['end'] = self._io.pos()
+ self._debug['debug']['start'] = self._io.pos()
+ self.debug = self._root.DataDir(self._io, self, self._root)
+ self.debug._read()
+ self._debug['debug']['end'] = self._io.pos()
+ self._debug['architecture']['start'] = self._io.pos()
+ self.architecture = self._root.DataDir(self._io, self, self._root)
+ self.architecture._read()
+ self._debug['architecture']['end'] = self._io.pos()
+ self._debug['global_ptr']['start'] = self._io.pos()
+ self.global_ptr = self._root.DataDir(self._io, self, self._root)
+ self.global_ptr._read()
+ self._debug['global_ptr']['end'] = self._io.pos()
+ self._debug['tls_table']['start'] = self._io.pos()
+ self.tls_table = self._root.DataDir(self._io, self, self._root)
+ self.tls_table._read()
+ self._debug['tls_table']['end'] = self._io.pos()
+ self._debug['load_config_table']['start'] = self._io.pos()
+ self.load_config_table = self._root.DataDir(self._io, self, self._root)
+ self.load_config_table._read()
+ self._debug['load_config_table']['end'] = self._io.pos()
+ self._debug['bound_import']['start'] = self._io.pos()
+ self.bound_import = self._root.DataDir(self._io, self, self._root)
+ self.bound_import._read()
+ self._debug['bound_import']['end'] = self._io.pos()
+ self._debug['iat']['start'] = self._io.pos()
+ self.iat = self._root.DataDir(self._io, self, self._root)
+ self.iat._read()
+ self._debug['iat']['end'] = self._io.pos()
+ self._debug['delay_import_descriptor']['start'] = self._io.pos()
+ self.delay_import_descriptor = self._root.DataDir(self._io, self, self._root)
+ self.delay_import_descriptor._read()
+ self._debug['delay_import_descriptor']['end'] = self._io.pos()
+ self._debug['clr_runtime_header']['start'] = self._io.pos()
+ self.clr_runtime_header = self._root.DataDir(self._io, self, self._root)
+ self.clr_runtime_header._read()
+ self._debug['clr_runtime_header']['end'] = self._io.pos()
+
+
+ class DataDir(KaitaiStruct):
+ SEQ_FIELDS = ["virtual_address", "size"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['virtual_address']['start'] = self._io.pos()
+ self.virtual_address = self._io.read_u4le()
+ self._debug['virtual_address']['end'] = self._io.pos()
+ self._debug['size']['start'] = self._io.pos()
+ self.size = self._io.read_u4le()
+ self._debug['size']['end'] = self._io.pos()
+
+
+ class CoffSymbol(KaitaiStruct):
+ SEQ_FIELDS = ["name_annoying", "value", "section_number", "type", "storage_class", "number_of_aux_symbols"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['name_annoying']['start'] = self._io.pos()
+ self._raw_name_annoying = self._io.read_bytes(8)
+ io = KaitaiStream(BytesIO(self._raw_name_annoying))
+ self.name_annoying = self._root.Annoyingstring(io, self, self._root)
+ self.name_annoying._read()
+ self._debug['name_annoying']['end'] = self._io.pos()
+ self._debug['value']['start'] = self._io.pos()
+ self.value = self._io.read_u4le()
+ self._debug['value']['end'] = self._io.pos()
+ self._debug['section_number']['start'] = self._io.pos()
+ self.section_number = self._io.read_u2le()
+ self._debug['section_number']['end'] = self._io.pos()
+ self._debug['type']['start'] = self._io.pos()
+ self.type = self._io.read_u2le()
+ self._debug['type']['end'] = self._io.pos()
+ self._debug['storage_class']['start'] = self._io.pos()
+ self.storage_class = self._io.read_u1()
+ self._debug['storage_class']['end'] = self._io.pos()
+ self._debug['number_of_aux_symbols']['start'] = self._io.pos()
+ self.number_of_aux_symbols = self._io.read_u1()
+ self._debug['number_of_aux_symbols']['end'] = self._io.pos()
+
+ @property
+ def section(self):
+ if hasattr(self, '_m_section'):
+ return self._m_section if hasattr(self, '_m_section') else None
+
+ self._m_section = self._root.pe.sections[(self.section_number - 1)]
+ return self._m_section if hasattr(self, '_m_section') else None
+
+ @property
+ def data(self):
+ if hasattr(self, '_m_data'):
+ return self._m_data if hasattr(self, '_m_data') else None
+
+ _pos = self._io.pos()
+ self._io.seek((self.section.pointer_to_raw_data + self.value))
+ self._debug['_m_data']['start'] = self._io.pos()
+ self._m_data = self._io.read_bytes(1)
+ self._debug['_m_data']['end'] = self._io.pos()
+ self._io.seek(_pos)
+ return self._m_data if hasattr(self, '_m_data') else None
+
+
+ class PeHeader(KaitaiStruct):
+ SEQ_FIELDS = ["pe_signature", "coff_hdr", "optional_hdr", "sections"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['pe_signature']['start'] = self._io.pos()
+ self.pe_signature = self._io.ensure_fixed_contents(b"\x50\x45\x00\x00")
+ self._debug['pe_signature']['end'] = self._io.pos()
+ self._debug['coff_hdr']['start'] = self._io.pos()
+ self.coff_hdr = self._root.CoffHeader(self._io, self, self._root)
+ self.coff_hdr._read()
+ self._debug['coff_hdr']['end'] = self._io.pos()
+ self._debug['optional_hdr']['start'] = self._io.pos()
+ self._raw_optional_hdr = self._io.read_bytes(self.coff_hdr.size_of_optional_header)
+ io = KaitaiStream(BytesIO(self._raw_optional_hdr))
+ self.optional_hdr = self._root.OptionalHeader(io, self, self._root)
+ self.optional_hdr._read()
+ self._debug['optional_hdr']['end'] = self._io.pos()
+ self._debug['sections']['start'] = self._io.pos()
+ self.sections = [None] * (self.coff_hdr.number_of_sections)
+ for i in range(self.coff_hdr.number_of_sections):
+ if not 'arr' in self._debug['sections']:
+ self._debug['sections']['arr'] = []
+ self._debug['sections']['arr'].append({'start': self._io.pos()})
+ _t_sections = self._root.Section(self._io, self, self._root)
+ _t_sections._read()
+ self.sections[i] = _t_sections
+ self._debug['sections']['arr'][i]['end'] = self._io.pos()
+
+ self._debug['sections']['end'] = self._io.pos()
+
+ @property
+ def certificate_table(self):
+ if hasattr(self, '_m_certificate_table'):
+ return self._m_certificate_table if hasattr(self, '_m_certificate_table') else None
+
+ if self.optional_hdr.data_dirs.certificate_table.virtual_address != 0:
+ _pos = self._io.pos()
+ self._io.seek(self.optional_hdr.data_dirs.certificate_table.virtual_address)
+ self._debug['_m_certificate_table']['start'] = self._io.pos()
+ self._raw__m_certificate_table = self._io.read_bytes(self.optional_hdr.data_dirs.certificate_table.size)
+ io = KaitaiStream(BytesIO(self._raw__m_certificate_table))
+ self._m_certificate_table = self._root.CertificateTable(io, self, self._root)
+ self._m_certificate_table._read()
+ self._debug['_m_certificate_table']['end'] = self._io.pos()
+ self._io.seek(_pos)
+
+ return self._m_certificate_table if hasattr(self, '_m_certificate_table') else None
+
+
+ class OptionalHeader(KaitaiStruct):
+ SEQ_FIELDS = ["std", "windows", "data_dirs"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['std']['start'] = self._io.pos()
+ self.std = self._root.OptionalHeaderStd(self._io, self, self._root)
+ self.std._read()
+ self._debug['std']['end'] = self._io.pos()
+ self._debug['windows']['start'] = self._io.pos()
+ self.windows = self._root.OptionalHeaderWindows(self._io, self, self._root)
+ self.windows._read()
+ self._debug['windows']['end'] = self._io.pos()
+ self._debug['data_dirs']['start'] = self._io.pos()
+ self.data_dirs = self._root.OptionalHeaderDataDirs(self._io, self, self._root)
+ self.data_dirs._read()
+ self._debug['data_dirs']['end'] = self._io.pos()
+
+
+ class Section(KaitaiStruct):
+ SEQ_FIELDS = ["name", "virtual_size", "virtual_address", "size_of_raw_data", "pointer_to_raw_data", "pointer_to_relocations", "pointer_to_linenumbers", "number_of_relocations", "number_of_linenumbers", "characteristics"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['name']['start'] = self._io.pos()
+ self.name = (KaitaiStream.bytes_strip_right(self._io.read_bytes(8), 0)).decode(u"UTF-8")
+ self._debug['name']['end'] = self._io.pos()
+ self._debug['virtual_size']['start'] = self._io.pos()
+ self.virtual_size = self._io.read_u4le()
+ self._debug['virtual_size']['end'] = self._io.pos()
+ self._debug['virtual_address']['start'] = self._io.pos()
+ self.virtual_address = self._io.read_u4le()
+ self._debug['virtual_address']['end'] = self._io.pos()
+ self._debug['size_of_raw_data']['start'] = self._io.pos()
+ self.size_of_raw_data = self._io.read_u4le()
+ self._debug['size_of_raw_data']['end'] = self._io.pos()
+ self._debug['pointer_to_raw_data']['start'] = self._io.pos()
+ self.pointer_to_raw_data = self._io.read_u4le()
+ self._debug['pointer_to_raw_data']['end'] = self._io.pos()
+ self._debug['pointer_to_relocations']['start'] = self._io.pos()
+ self.pointer_to_relocations = self._io.read_u4le()
+ self._debug['pointer_to_relocations']['end'] = self._io.pos()
+ self._debug['pointer_to_linenumbers']['start'] = self._io.pos()
+ self.pointer_to_linenumbers = self._io.read_u4le()
+ self._debug['pointer_to_linenumbers']['end'] = self._io.pos()
+ self._debug['number_of_relocations']['start'] = self._io.pos()
+ self.number_of_relocations = self._io.read_u2le()
+ self._debug['number_of_relocations']['end'] = self._io.pos()
+ self._debug['number_of_linenumbers']['start'] = self._io.pos()
+ self.number_of_linenumbers = self._io.read_u2le()
+ self._debug['number_of_linenumbers']['end'] = self._io.pos()
+ self._debug['characteristics']['start'] = self._io.pos()
+ self.characteristics = self._io.read_u4le()
+ self._debug['characteristics']['end'] = self._io.pos()
+
+ @property
+ def body(self):
+ if hasattr(self, '_m_body'):
+ return self._m_body if hasattr(self, '_m_body') else None
+
+ _pos = self._io.pos()
+ self._io.seek(self.pointer_to_raw_data)
+ self._debug['_m_body']['start'] = self._io.pos()
+ self._m_body = self._io.read_bytes(self.size_of_raw_data)
+ self._debug['_m_body']['end'] = self._io.pos()
+ self._io.seek(_pos)
+ return self._m_body if hasattr(self, '_m_body') else None
+
+
+ class CertificateTable(KaitaiStruct):
+ SEQ_FIELDS = ["items"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['items']['start'] = self._io.pos()
+ self.items = []
+ i = 0
+ while not self._io.is_eof():
+ if not 'arr' in self._debug['items']:
+ self._debug['items']['arr'] = []
+ self._debug['items']['arr'].append({'start': self._io.pos()})
+ _t_items = self._root.CertificateEntry(self._io, self, self._root)
+ _t_items._read()
+ self.items.append(_t_items)
+ self._debug['items']['arr'][len(self.items) - 1]['end'] = self._io.pos()
+ i += 1
+
+ self._debug['items']['end'] = self._io.pos()
+
+
+ class MzPlaceholder(KaitaiStruct):
+ SEQ_FIELDS = ["magic", "data1", "ofs_pe"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['magic']['start'] = self._io.pos()
+ self.magic = self._io.ensure_fixed_contents(b"\x4D\x5A")
+ self._debug['magic']['end'] = self._io.pos()
+ self._debug['data1']['start'] = self._io.pos()
+ self.data1 = self._io.read_bytes(58)
+ self._debug['data1']['end'] = self._io.pos()
+ self._debug['ofs_pe']['start'] = self._io.pos()
+ self.ofs_pe = self._io.read_u4le()
+ self._debug['ofs_pe']['end'] = self._io.pos()
+
+
+ class OptionalHeaderStd(KaitaiStruct):
+ SEQ_FIELDS = ["format", "major_linker_version", "minor_linker_version", "size_of_code", "size_of_initialized_data", "size_of_uninitialized_data", "address_of_entry_point", "base_of_code", "base_of_data"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['format']['start'] = self._io.pos()
+ self.format = KaitaiStream.resolve_enum(self._root.PeFormat, self._io.read_u2le())
+ self._debug['format']['end'] = self._io.pos()
+ self._debug['major_linker_version']['start'] = self._io.pos()
+ self.major_linker_version = self._io.read_u1()
+ self._debug['major_linker_version']['end'] = self._io.pos()
+ self._debug['minor_linker_version']['start'] = self._io.pos()
+ self.minor_linker_version = self._io.read_u1()
+ self._debug['minor_linker_version']['end'] = self._io.pos()
+ self._debug['size_of_code']['start'] = self._io.pos()
+ self.size_of_code = self._io.read_u4le()
+ self._debug['size_of_code']['end'] = self._io.pos()
+ self._debug['size_of_initialized_data']['start'] = self._io.pos()
+ self.size_of_initialized_data = self._io.read_u4le()
+ self._debug['size_of_initialized_data']['end'] = self._io.pos()
+ self._debug['size_of_uninitialized_data']['start'] = self._io.pos()
+ self.size_of_uninitialized_data = self._io.read_u4le()
+ self._debug['size_of_uninitialized_data']['end'] = self._io.pos()
+ self._debug['address_of_entry_point']['start'] = self._io.pos()
+ self.address_of_entry_point = self._io.read_u4le()
+ self._debug['address_of_entry_point']['end'] = self._io.pos()
+ self._debug['base_of_code']['start'] = self._io.pos()
+ self.base_of_code = self._io.read_u4le()
+ self._debug['base_of_code']['end'] = self._io.pos()
+ if self.format == self._root.PeFormat.pe32:
+ self._debug['base_of_data']['start'] = self._io.pos()
+ self.base_of_data = self._io.read_u4le()
+ self._debug['base_of_data']['end'] = self._io.pos()
+
+
+
+ class CoffHeader(KaitaiStruct):
+ """
+ .. seealso::
+ 3.3. COFF File Header (Object and Image)
+ """
+
+ class MachineType(Enum):
+ unknown = 0
+ i386 = 332
+ r4000 = 358
+ wcemipsv2 = 361
+ alpha = 388
+ sh3 = 418
+ sh3dsp = 419
+ sh4 = 422
+ sh5 = 424
+ arm = 448
+ thumb = 450
+ armnt = 452
+ am33 = 467
+ powerpc = 496
+ powerpcfp = 497
+ ia64 = 512
+ mips16 = 614
+ mipsfpu = 870
+ mipsfpu16 = 1126
+ ebc = 3772
+ riscv32 = 20530
+ riscv64 = 20580
+ riscv128 = 20776
+ amd64 = 34404
+ m32r = 36929
+ arm64 = 43620
+ SEQ_FIELDS = ["machine", "number_of_sections", "time_date_stamp", "pointer_to_symbol_table", "number_of_symbols", "size_of_optional_header", "characteristics"]
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ self._debug['machine']['start'] = self._io.pos()
+ self.machine = KaitaiStream.resolve_enum(self._root.CoffHeader.MachineType, self._io.read_u2le())
+ self._debug['machine']['end'] = self._io.pos()
+ self._debug['number_of_sections']['start'] = self._io.pos()
+ self.number_of_sections = self._io.read_u2le()
+ self._debug['number_of_sections']['end'] = self._io.pos()
+ self._debug['time_date_stamp']['start'] = self._io.pos()
+ self.time_date_stamp = self._io.read_u4le()
+ self._debug['time_date_stamp']['end'] = self._io.pos()
+ self._debug['pointer_to_symbol_table']['start'] = self._io.pos()
+ self.pointer_to_symbol_table = self._io.read_u4le()
+ self._debug['pointer_to_symbol_table']['end'] = self._io.pos()
+ self._debug['number_of_symbols']['start'] = self._io.pos()
+ self.number_of_symbols = self._io.read_u4le()
+ self._debug['number_of_symbols']['end'] = self._io.pos()
+ self._debug['size_of_optional_header']['start'] = self._io.pos()
+ self.size_of_optional_header = self._io.read_u2le()
+ self._debug['size_of_optional_header']['end'] = self._io.pos()
+ self._debug['characteristics']['start'] = self._io.pos()
+ self.characteristics = self._io.read_u2le()
+ self._debug['characteristics']['end'] = self._io.pos()
+
+ @property
+ def symbol_table_size(self):
+ if hasattr(self, '_m_symbol_table_size'):
+ return self._m_symbol_table_size if hasattr(self, '_m_symbol_table_size') else None
+
+ self._m_symbol_table_size = (self.number_of_symbols * 18)
+ return self._m_symbol_table_size if hasattr(self, '_m_symbol_table_size') else None
+
+ @property
+ def symbol_name_table_offset(self):
+ if hasattr(self, '_m_symbol_name_table_offset'):
+ return self._m_symbol_name_table_offset if hasattr(self, '_m_symbol_name_table_offset') else None
+
+ self._m_symbol_name_table_offset = (self.pointer_to_symbol_table + self.symbol_table_size)
+ return self._m_symbol_name_table_offset if hasattr(self, '_m_symbol_name_table_offset') else None
+
+ @property
+ def symbol_name_table_size(self):
+ if hasattr(self, '_m_symbol_name_table_size'):
+ return self._m_symbol_name_table_size if hasattr(self, '_m_symbol_name_table_size') else None
+
+ _pos = self._io.pos()
+ self._io.seek(self.symbol_name_table_offset)
+ self._debug['_m_symbol_name_table_size']['start'] = self._io.pos()
+ self._m_symbol_name_table_size = self._io.read_u4le()
+ self._debug['_m_symbol_name_table_size']['end'] = self._io.pos()
+ self._io.seek(_pos)
+ return self._m_symbol_name_table_size if hasattr(self, '_m_symbol_name_table_size') else None
+
+ @property
+ def symbol_table(self):
+ if hasattr(self, '_m_symbol_table'):
+ return self._m_symbol_table if hasattr(self, '_m_symbol_table') else None
+
+ _pos = self._io.pos()
+ self._io.seek(self.pointer_to_symbol_table)
+ self._debug['_m_symbol_table']['start'] = self._io.pos()
+ self._m_symbol_table = [None] * (self.number_of_symbols)
+ for i in range(self.number_of_symbols):
+ if not 'arr' in self._debug['_m_symbol_table']:
+ self._debug['_m_symbol_table']['arr'] = []
+ self._debug['_m_symbol_table']['arr'].append({'start': self._io.pos()})
+ _t__m_symbol_table = self._root.CoffSymbol(self._io, self, self._root)
+ _t__m_symbol_table._read()
+ self._m_symbol_table[i] = _t__m_symbol_table
+ self._debug['_m_symbol_table']['arr'][i]['end'] = self._io.pos()
+
+ self._debug['_m_symbol_table']['end'] = self._io.pos()
+ self._io.seek(_pos)
+ return self._m_symbol_table if hasattr(self, '_m_symbol_table') else None
+
+
+ class Annoyingstring(KaitaiStruct):
+ SEQ_FIELDS = []
+ def __init__(self, _io, _parent=None, _root=None):
+ self._io = _io
+ self._parent = _parent
+ self._root = _root if _root else self
+ self._debug = collections.defaultdict(dict)
+
+ def _read(self):
+ pass
+
+ @property
+ def name_from_offset(self):
+ if hasattr(self, '_m_name_from_offset'):
+ return self._m_name_from_offset if hasattr(self, '_m_name_from_offset') else None
+
+ if self.name_zeroes == 0:
+ io = self._root._io
+ _pos = io.pos()
+ io.seek(((self._parent._parent.symbol_name_table_offset + self.name_offset) if self.name_zeroes == 0 else 0))
+ self._debug['_m_name_from_offset']['start'] = io.pos()
+ self._m_name_from_offset = (io.read_bytes_term(0, False, True, False)).decode(u"ascii")
+ self._debug['_m_name_from_offset']['end'] = io.pos()
+ io.seek(_pos)
+
+ return self._m_name_from_offset if hasattr(self, '_m_name_from_offset') else None
+
+ @property
+ def name_offset(self):
+ if hasattr(self, '_m_name_offset'):
+ return self._m_name_offset if hasattr(self, '_m_name_offset') else None
+
+ _pos = self._io.pos()
+ self._io.seek(4)
+ self._debug['_m_name_offset']['start'] = self._io.pos()
+ self._m_name_offset = self._io.read_u4le()
+ self._debug['_m_name_offset']['end'] = self._io.pos()
+ self._io.seek(_pos)
+ return self._m_name_offset if hasattr(self, '_m_name_offset') else None
+
+ @property
+ def name(self):
+ if hasattr(self, '_m_name'):
+ return self._m_name if hasattr(self, '_m_name') else None
+
+ self._m_name = (self.name_from_offset if self.name_zeroes == 0 else self.name_from_short)
+ return self._m_name if hasattr(self, '_m_name') else None
+
+ @property
+ def name_zeroes(self):
+ if hasattr(self, '_m_name_zeroes'):
+ return self._m_name_zeroes if hasattr(self, '_m_name_zeroes') else None
+
+ _pos = self._io.pos()
+ self._io.seek(0)
+ self._debug['_m_name_zeroes']['start'] = self._io.pos()
+ self._m_name_zeroes = self._io.read_u4le()
+ self._debug['_m_name_zeroes']['end'] = self._io.pos()
+ self._io.seek(_pos)
+ return self._m_name_zeroes if hasattr(self, '_m_name_zeroes') else None
+
+ @property
+ def name_from_short(self):
+ if hasattr(self, '_m_name_from_short'):
+ return self._m_name_from_short if hasattr(self, '_m_name_from_short') else None
+
+ if self.name_zeroes != 0:
+ _pos = self._io.pos()
+ self._io.seek(0)
+ self._debug['_m_name_from_short']['start'] = self._io.pos()
+ self._m_name_from_short = (self._io.read_bytes_term(0, False, True, False)).decode(u"ascii")
+ self._debug['_m_name_from_short']['end'] = self._io.pos()
+ self._io.seek(_pos)
+
+ return self._m_name_from_short if hasattr(self, '_m_name_from_short') else None
+
+
+ @property
+ def pe(self):
+ if hasattr(self, '_m_pe'):
+ return self._m_pe if hasattr(self, '_m_pe') else None
+
+ _pos = self._io.pos()
+ self._io.seek(self.mz.ofs_pe)
+ self._debug['_m_pe']['start'] = self._io.pos()
+ self._m_pe = self._root.PeHeader(self._io, self, self._root)
+ self._m_pe._read()
+ self._debug['_m_pe']['end'] = self._io.pos()
+ self._io.seek(_pos)
+ return self._m_pe if hasattr(self, '_m_pe') else None
+
+
diff --git a/python/examples/kaitai/view.py b/python/examples/kaitai/view.py
new file mode 100644
index 00000000..888049ac
--- /dev/null
+++ b/python/examples/kaitai/view.py
@@ -0,0 +1,220 @@
+import traceback
+import binaryninjaui
+from binaryninja.settings import Settings
+from binaryninja import log
+from binaryninja import _binaryninjacore as core
+from binaryninjaui import View, ViewType, ViewFrame, UIContext, HexEditor
+from binaryninja import binaryview
+from PySide2.QtWidgets import QScrollArea, QWidget, QVBoxLayout, QGroupBox, QTreeWidget, QTreeWidgetItem, QLineEdit
+from PySide2.QtCore import Qt
+
+import types
+
+import kshelpers
+from kaitaistruct import KaitaiStruct
+import io
+
+class KaitaiView(QScrollArea, View):
+ def __init__(self, parent, binaryView):
+ QScrollArea.__init__(self, parent)
+
+ View.__init__(self)
+ self.setupView(self)
+
+ # BinaryViewType
+ self.binaryView = binaryView
+
+ self.rootSelectionStart = 0
+ self.rootSelectionEnd = 1
+
+ self.ioRoot = None
+ self.ioCurrent = None
+
+ container = QWidget(self)
+ layout = QVBoxLayout()
+
+ self.treeGroup = QGroupBox("Data Tree:")
+ treeLayout = QVBoxLayout()
+ self.treeWidget = QTreeWidget()
+ self.treeWidget.setColumnCount(4)
+ self.treeWidget.setHeaderLabels(['label','value','start','end'])
+ self.treeWidget.itemSelectionChanged.connect(self.onTreeSelect)
+ self.structPath = QLineEdit("root")
+ self.structPath.setDisabled(True)
+ treeLayout.addWidget(self.structPath)
+ treeLayout.addWidget(self.treeWidget)
+ self.treeGroup.setLayout(treeLayout)
+
+ self.hexGroup = QGroupBox("Hex View:")
+ self.hexLayout = QVBoxLayout()
+ self.hexWidget = HexEditor(binaryView, ViewFrame.viewFrameForWidget(self), 0)
+ self.hexLayout.addWidget(self.hexWidget)
+ self.hexGroup.setLayout(self.hexLayout)
+
+ layout.addWidget(self.treeGroup)
+ layout.addWidget(self.hexGroup)
+ #layout.addStretch(1)
+ container.setLayout(layout)
+ self.setWidgetResizable(True)
+ self.setWidget(container)
+
+ self.kaitaiParse()
+
+ # parse the file using Kaitai, construct the TreeWidget
+ def kaitaiParse(self):
+ parsed = None
+
+ kaitaiIO = kshelpers.KaitaiBinaryViewIO(self.binaryView)
+ if not kaitaiIO:
+ print 'ERROR: initializing kaitai binary view'
+ parsed = kshelpers.parse_io(kaitaiIO)
+ if not parsed:
+ print 'ERROR: parsing the binary view'
+
+ tree = kshelpers.build_qtree(parsed)
+ if not tree:
+ return
+
+ self.ioRoot = tree.ksobj._io
+ self.ioCurrent = tree.ksobj._io
+
+ self.treeWidget.clear()
+ self.treeWidget.setSortingEnabled(False) # temporarily, for efficiency
+ # two options with how we create the hierarchy
+ if False:
+ # treat root as top level "file" container
+ tree.setLabel('file')
+ tree.setValue(None)
+ tree.setStart(0)
+ tree.setEnd(0)
+ self.treeWidget.insertTopLevelItem(0, tree)
+ else:
+ # add root's children as top level items
+ self.treeWidget.insertTopLevelItems(0, tree.takeChildren())
+
+ #self.treeWidget.expandAll()
+ width = self.treeWidget.width()
+ self.treeWidget.setColumnWidth(0, .4*width)
+ self.treeWidget.setColumnWidth(1, .2*width)
+ self.treeWidget.setColumnWidth(2, .1*width)
+ self.treeWidget.setColumnWidth(3, .1*width)
+ # enable sorting
+ self.treeWidget.setSortingEnabled(True)
+ self.treeWidget.sortByColumn(2, Qt.AscendingOrder)
+
+ # TODO: select first item, maybe expand a few things
+ self.rootSelectionStart = 0
+ self.rootSelectionEnd = 1
+ self.hexWidget.setSelectionRange(0,1)
+ self.treeWidget.setUniformRowHeights(True)
+
+ # callback!
+ def getData(self):
+ return self.binaryView
+
+ # callback!
+ def getCurrentOffset(self):
+ middle = self.rootSelectionStart + int((self.rootSelectionEnd - self.rootSelectionStart)/2)
+ return middle
+
+ def setCurrentOffset(self, offset):
+ print 'setCurrentOffset(0x%X)' % offset
+ self.rootSelectionStart = offset
+ UIContext.updateStatus(True)
+
+ def getFont(self):
+ return binaryninjaui.getMonospaceFont(self)
+
+ def navigate(self, addr):
+ return False
+
+ def onTreeSelect(self, wtf=None):
+ # get KaitaiTreeWidgetItem
+ item = self.treeWidget.selectedItems()[0]
+
+ # build path, inform user
+ structPath = item.label
+ itemTmp = item
+ while itemTmp.parent():
+ itemTmp = itemTmp.parent()
+ structPath = itemTmp.label + '.' + structPath
+ self.structPath.setText('root.' + structPath)
+
+ #
+ (start, end) = (item.start, item.end)
+ if start == None or end == None:
+ return
+
+ # determine current IO we're in (the Kaitai input/output abstraction)
+ _io = None
+ # if the tree item is linked to a KaitaiNode, simply read the IO
+ if item.ksobj:
+ _io = item.ksobj._parent._io
+ else:
+ # else we're a leaf
+ parent = item.parent()
+ if parent:
+ # a leaf with a parent -> read parent's IO
+ _io = parent.ksobj._io
+ else:
+ # a leaf without a parent -> we must be at root -> use root IO
+ _io = self.ioRoot
+
+ # if the selection is in the root view, store the interval so that upon
+ # getCurrentOffset() callback, we return the middle and feature map is
+ # updated
+ if _io == self.ioRoot:
+ self.rootSelectionStart = start
+ self.rootSelectionEnd = end
+
+ # current kaitai object is on a different io? then swap HexEditor
+ if _io != self.ioCurrent:
+ # delete old view
+ layoutItem = self.hexLayout.takeAt(0)
+ hexEditorWidget = layoutItem.widget()
+ hexEditorWidget.setParent(None)
+ hexEditorWidget.deleteLater()
+ self.hexWidget = None
+
+ # if it's the original file IO, wrap the already-open file binary view
+ if _io == self.ioRoot:
+ self.hexWidget = HexEditor(self.binaryView, ViewFrame.viewFrameForWidget(self), 0)
+ # otherwise delete old view, create a temporary view
+ else:
+ # create new view
+ length = _io.size()
+ _io.seek(0)
+ data = _io.read_bytes(length)
+ bv = binaryview.BinaryView.new(data)
+ self.hexWidget = HexEditor(bv, ViewFrame.viewFrameForWidget(self), 0)
+
+ self.hexLayout.addWidget(self.hexWidget)
+ self.ioCurrent = _io
+
+ # now position selection in whatever HexEditor is current
+ #print 'selecting to [0x%X, 0x%X)' % (start, end)
+ self.hexWidget.setSelectionRange(start, end)
+
+ # set hex group title to reflect current selection
+ self.hexGroup.setTitle('Hex View @ [0x%X, 0x%X)' % (start, end))
+
+class KaitaiViewType(ViewType):
+ def __init__(self):
+ super(KaitaiViewType, self).__init__("Kaitai", "Kaitai")
+
+ # binaryView: BinaryView
+ def getPriority(self, binaryView, filename):
+ # data.file: FileMetadata
+ # data.raw: BinaryView
+
+ if binaryView == binaryView.file.raw:
+ #print 'returning priority=100 for FileView'
+ return 100
+ else:
+ #print 'returning priority 0, not given a raw view'
+ return 0
+
+ def create(self, binaryView, view_frame):
+ return KaitaiView(view_frame, binaryView)
+
+ViewType.registerViewType(KaitaiViewType())