summaryrefslogtreecommitdiff
path: root/python/examples
diff options
context:
space:
mode:
Diffstat (limited to 'python/examples')
-rw-r--r--python/examples/kaitai/view.py152
1 files changed, 92 insertions, 60 deletions
diff --git a/python/examples/kaitai/view.py b/python/examples/kaitai/view.py
index 341d4dc1..c37711d8 100644
--- a/python/examples/kaitai/view.py
+++ b/python/examples/kaitai/view.py
@@ -12,7 +12,7 @@ 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.QtWidgets import QScrollArea, QWidget, QVBoxLayout, QGroupBox, QTreeWidget, QTreeWidgetItem, QLineEdit, QHeaderView
from PySide2.QtCore import Qt
if sys.version_info[0] == 2:
@@ -20,6 +20,14 @@ if sys.version_info[0] == 2:
else:
from . import kshelpers
+class MyQTreeWidget(QTreeWidget):
+ def __init__(self):
+ QTreeWidget.__init__(self)
+
+ def resizeEvent(self, event):
+ QTreeWidget.resizeEvent(self, event)
+ self.scrollTo(self.currentIndex())
+
class KaitaiView(QScrollArea, View):
def __init__(self, parent, binaryView):
QScrollArea.__init__(self, parent)
@@ -37,30 +45,23 @@ class KaitaiView(QScrollArea, View):
self.ioCurrent = None
container = QWidget(self)
- layout = QVBoxLayout()
+ self.layout = QVBoxLayout()
- self.treeGroup = QGroupBox("Data Tree:")
- treeLayout = QVBoxLayout()
- self.treeWidget = QTreeWidget()
+ self.treeWidget = MyQTreeWidget()
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.layout.addWidget(self.treeWidget)
+ self.layout.addWidget(self.structPath)
+ self.layout.addWidget(self.hexWidget)
+ #self.layout.addStretch(1)
+ container.setLayout(self.layout)
self.setWidgetResizable(True)
self.setWidget(container)
@@ -98,12 +99,7 @@ class KaitaiView(QScrollArea, View):
# 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)
@@ -114,17 +110,52 @@ class KaitaiView(QScrollArea, View):
self.hexWidget.setSelectionRange(0,1)
self.treeWidget.setUniformRowHeights(True)
- # callback!
+ # Qt callbacks
+ def resizeEvent(self, event):
+ width = self.treeWidget.width()
+ self.treeWidget.setColumnWidth(0, .6*width)
+ self.treeWidget.setColumnWidth(1, .2*width)
+ self.treeWidget.setColumnWidth(2, .1*width)
+ self.treeWidget.setColumnWidth(3, .1*width)
+
+ QScrollArea.resizeEvent(self, event)
+
+ # binja callbacks
def getData(self):
return self.binaryView
- # callback!
+ def getStart(self):
+ result = self.binaryView.start
+ #print('getStart() returning '+str(result))
+ return result
+
+ def getEnd(self):
+ result = self.binaryView.end
+ #print('getEnd() returning '+str(result))
+ return result
+
+ def getLength(self):
+ result = len(self.binaryView)
+ #print('getLength() returning '+str(result))
+ return result
+
def getCurrentOffset(self):
- middle = self.rootSelectionStart + int((self.rootSelectionEnd - self.rootSelectionStart)/2)
- return middle
+ result = self.rootSelectionStart + int((self.rootSelectionEnd - self.rootSelectionStart)/2)
+ #result = self.rootSelectionStart
+ #print('getCurrentOffset() returning '+str(result))
+ return result
+
+ def getSelectionOffsets(self):
+ result = None
+ if self.hexWidget:
+ result = self.hexWidget.getSelectionOffsets()
+ else:
+ result = (self.rootSelectionStart, self.rootSelectionStart)
+ #print('getSelectionOffsets() returning '+str(result))
+ return result
def setCurrentOffset(self, offset):
- print('setCurrentOffset(0x%X)' % offset)
+ #print('setCurrentOffset(0x%X)' % offset)
self.rootSelectionStart = offset
UIContext.updateStatus(True)
@@ -132,6 +163,11 @@ class KaitaiView(QScrollArea, View):
return binaryninjaui.getMonospaceFont(self)
def navigate(self, addr):
+ #print('navigate()')
+ return False
+
+ def navigateToFileOffset(self, offset):
+ #print('navigateToFileOffset()')
return False
def onTreeSelect(self, wtf=None):
@@ -176,7 +212,7 @@ class KaitaiView(QScrollArea, View):
# current kaitai object is on a different io? then swap HexEditor
if _io != self.ioCurrent:
# delete old view
- layoutItem = self.hexLayout.takeAt(0)
+ layoutItem = self.layout.takeAt(2)
hexEditorWidget = layoutItem.widget()
hexEditorWidget.setParent(None)
hexEditorWidget.deleteLater()
@@ -194,7 +230,7 @@ class KaitaiView(QScrollArea, View):
bv = binaryview.BinaryView.new(data)
self.hexWidget = HexEditor(bv, ViewFrame.viewFrameForWidget(self), 0)
- self.hexLayout.addWidget(self.hexWidget)
+ self.layout.addWidget(self.hexWidget)
self.ioCurrent = _io
# now position selection in whatever HexEditor is current
@@ -202,7 +238,7 @@ class KaitaiView(QScrollArea, View):
self.hexWidget.setSelectionRange(start, end)
# set hex group title to reflect current selection
- self.hexGroup.setTitle('Hex View @ [0x%X, 0x%X)' % (start, end))
+ #self.hexGroup.setTitle('Hex View @ [0x%X, 0x%X)' % (start, end))
class KaitaiViewType(ViewType):
def __init__(self):
@@ -210,39 +246,35 @@ class KaitaiViewType(ViewType):
# binaryView: BinaryView
def getPriority(self, binaryView, filename):
- # data.file: FileMetadata
- # data.raw: BinaryView
+ #return 100
+ #print('len(bv)=0x%X executable=%d bytes=%s' % (len(binaryView), binaryView.executable, repr(binaryView.read(0,4))))
- priority = 0
- isExec = binaryView.executable
- weRecognize = kshelpers.idData(binaryView.read(0,16), len(binaryView)) != None
-
- # NOTE: ui/shared/hexeditor.cpp has the hex editor at priority 20 when
- # executable, and 10 otherwise
+ # executable means the view is mapped like an OS loader would load an executable (eg: view=ELF)
+ # !executable means executable image is not mapped (eg: view=Raw) (or something like .png is loaded)
+ if binaryView.executable:
+ return 0
- if not weRecognize:
- priority = 0
- else:
- if isExec:
- priority = 21
- else:
- priority = 11
+ if binaryView.start != 0:
+ return 0
+
+ if os.path.getsize(binaryView.file.filename) != len(binaryView):
+ return 0
+
+ dataSample = binaryView.read(0, 16)
+ if len(dataSample) != 16:
+ return 0
-# if isExec and weRecognize:
-# print('priority=25 to slightly beat out the hex editor case=(executable, recognize)')
-# priority = 25
-# if isExec and not weRecognize:
-# print('priority=15 to lose to the hex editor case=(executable, !recognize)')
-# priority = 15
-# if not isExec and weRecognize:
-# print('priority=100 to beat out everything case=(!executable, recognize)')
-# priority = 100
-# if not isExec and not weRecognize:
-# print('priority=5 to lose to hex editor case=(!executable, !recognize)')
-# priority = 5
-
- #print('returning priority=%d for KaitaiViewType' % priority)
- return priority
+ # if we don't recognize it, return 0
+ ksModuleName = kshelpers.idData(dataSample, len(binaryView))
+ if not ksModuleName:
+ return 0
+
+ # for executables, yield triage (25)
+ if ksModuleName in ['elf', 'microsoft_pe', 'mach_o']:
+ return 24
+
+ #
+ return 100
def create(self, binaryView, view_frame):
return KaitaiView(view_frame, binaryView)