From 13ff200ba134b8704f37eca99c42b70dab0d17dc Mon Sep 17 00:00:00 2001 From: Xusheng Date: Thu, 1 Jul 2021 12:34:30 +0800 Subject: Remove snippet and kaitai plugin. Note their individual links. --- python/examples/kaitai/kshelpers.py | 771 ------------------------------------ 1 file changed, 771 deletions(-) delete mode 100644 python/examples/kaitai/kshelpers.py (limited to 'python/examples/kaitai/kshelpers.py') diff --git a/python/examples/kaitai/kshelpers.py b/python/examples/kaitai/kshelpers.py deleted file mode 100644 index 40a6320e..00000000 --- a/python/examples/kaitai/kshelpers.py +++ /dev/null @@ -1,771 +0,0 @@ -#!/usr/bin/env python - -import traceback - -import io -import os -import re -import sys -import types -import struct -import binascii -import importlib -import collections - -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(' 8: - result = '%s...%s (0x%X==%d chars total)' % \ - (repr(obj[0:8]), repr(obj[-1]), len(obj), len(obj)) - else: - result = repr(obj) - elif isinstance(obj, bytes): - if len(obj) > 8: - result = binascii.hexlify(obj[0:8]).decode('utf-8') + '...' + \ - ('%02X' % obj[-1]) + ' (0x%X==%d bytes total)' % (len(obj), len(obj)) - else: - result = binascii.hexlify(obj).decode('utf-8') - # note: bool needs to appear before int (else int determination will dominate) - elif isinstance(obj, bool): - result = '%s' % (obj) - elif isinstance(obj, int): - result = '0x%X (%d)' % (obj, obj) - elif str(objType).startswith('0 and isinstance(subobj[0], kaitaistruct.KaitaiStruct): - result += [fieldName] - except Exception: - pass - - return result - -# compute all kaitai objects linked to from the given object -# -# IN: kaitai object -# OUT: [obj0, obj1, obj2, ...] -# -def getLinkedKaitaiObjects(ksobj): - result = set() - - for fieldName in getFieldNamesDescend(ksobj): - subobj = getattr(ksobj, fieldName, False) - if isinstance(subobj, list): - for tmp in subobj: - result.add(tmp) - else: - result.add(subobj) - - return result - -# compute all kaitai objects linked to from the given object, and from its -# descendents, and so on... -def getLinkedKaitaiObjectsAll(ksobj, depth=0): - #if depth > 2: - # return [] - - exercise(ksobj) - - result = set([ksobj]) - - linkedObjects = getLinkedKaitaiObjects(ksobj) - for subobj in linkedObjects: - subResult = getLinkedKaitaiObjectsAll(subobj, depth+1) - result = result.union(subResult) - - return result - -def getDepth(ksobj, depth=0): - result = depth - - exercise(ksobj) - for subObj in getLinkedKaitaiObjects(ksobj): - result = max(result, getDepth(subObj, depth+1)) - - return result - -#------------------------------------------------------------------------------ -# 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): - #log.log_debug('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): - #log.log_debug('tell() returning 0x%X' % (self.position)) - return self.position - - def read(self, length=None): - # if no length is given (eg: see read_bytes_full() in kaitaistruct.py) - if length == None: - length = len(self.binaryView) - self.position - - #log.log_debug('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 - -#------------------------------------------------------------------------------ -# 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 isinstance(value, int): - value = '%X'%value - self.setData(1, Qt.DisplayRole, value) - - def setStart(self, start): - if start == None: - self.start = None - elif isinstance(start, int): - self.start = start - start = '%X'%start - elif (sys.version_info[0] == 2) and type(start) == 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 - - if isinstance(end, int): - self.end = end - end = '%X'%end - elif (sys.version_info[0] == 2) and type(end) == 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 buildQtree(ksobj): - if not isinstance(ksobj, kaitaistruct.KaitaiStruct): - return None - - exceptions = ['_root', '_parent', '_io', 'SEQ_FIELDS', '_debug'] - - qwi = KaitaiTreeWidgetItem() - qwi.setKaitaiObject(ksobj) - - fieldNames = set() - - # first pass: access fields that may be properties, which could compute - # internal results (often '_m_XXX' fields) - for candidate in dir(ksobj): - if candidate.startswith('_') and (not candidate.startswith('_m_')): - continue - if candidate in exceptions: - continue - try: - getattr(ksobj, candidate) - fieldNames.add(candidate) - except Exception: - pass - - # second pass: collect the '_m_XXX' fields which have the debug start/end - # marks, remove the 'XXX' counterpart, if it exists - for candidate in filter(lambda x: x.startswith('_m_'), dir(ksobj)): - try: - if not getattr(ksobj, candidate, False): - continue - - fieldNames.add(candidate) - if candidate[3:] in fieldNames: - fieldNames.remove(candidate[3:]) - - except Exception: - pass - - for fieldName in fieldNames: - subObj = getattr(ksobj, fieldName) - - child = None - if isinstance(subObj, kaitaistruct.KaitaiStruct): - fieldLabel = fieldName - child = buildQtree(subObj) - if child: - populateChild(ksobj, fieldName, fieldName, None, child) - qwi.addChild(child) - - elif isinstance(subObj, list): - if len(subObj)<=0: - continue - - # CASE: is list of KaitaiObjects -> 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('