#!/usr/bin/env python import traceback import io import os import sys import struct import types import importlib from binaryninja import log from PySide2.QtCore import Qt from PySide2.QtWidgets import QTreeWidgetItem if sys.version_info[0] == 2: import kaitaistruct else: from . import kaitaistruct #------------------------------------------------------------------------------ # id and parse #------------------------------------------------------------------------------ # return the name of the kaitai module to service this data # # dsample: str data sample # length: int total length of data def idData(dataSample, length): result = None #log.log_debug('idData() here with sample: %s' % repr(dataSample)) if len(dataSample) < 16: return result if dataSample[0:4] == b'\x7fELF': result = 'elf' if dataSample[0:4] in [b'\xfe\xed\xfa\xce', b'\xce\xfa\xed\xfe', b'\xfe\xed\xfa\xcf', b'\xcf\xfa\xed\xfe']: result = 'mach_o' if dataSample[0:2] == b'MZ': result = 'microsoft_pe' if dataSample[0:8] == b'\x89PNG\x0d\x0a\x1a\x0a': result = 'png' if dataSample[2:11] == b'\xFF\xe0\x00\x10JFIF\x00': result = 'jpeg' if dataSample[0:4] == b'GIF8': result = 'gif' if dataSample[0:2] in [b'BM', b'BA', b'CI', b'CP', b'IC', b'PT'] and struct.unpack(' recurse! if isinstance(subObj[0], kaitaistruct.KaitaiStruct): child = KaitaiTreeWidgetItem() populateChild(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 = buildQtree(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() populateChild(ksobj, fieldName, fieldName, None, child) # TODO: explain this hack kstmp = kaitaistruct.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 populateChild(ksobj, fieldName, None, None, child) qwi.addChild(child) return qwi def createLeaf(fieldName, obj): objtype = type(obj) if objtype == types.FunctionType: #log.log_debug('reject %s because its a function' % fieldName) return None elif isinstance(obj, type): #log.log_debug('reject %s because its a type' % fieldName) return None elif sys.version_info[0] == 2 and callable(obj): #log.log_debug('reject %s because its a callable' % fieldName) return None elif sys.version_info[0] == 3 and hasattr(obj, '__call__'): #log.log_debug('reject %s because its a callable' % fieldName) return None fieldValue = None if isinstance(obj, str) or isinstance(obj, bytes): if len(obj) > 8: fieldValue = str(repr(obj[0:8])) + '...' else: fieldValue = repr(obj) elif sys.version_info[0] == 2 and objtype == types.UnicodeType: fieldValue = repr(obj) elif isinstance(obj, int): fieldValue = '0x%X (%d)' % (obj, obj) elif isinstance(obj, bool): fieldValue = '%s' % (obj) elif str(objtype).startswith('