diff options
| author | Rusty Wagner <rusty@vector35.com> | 2019-03-26 16:42:55 -0400 |
|---|---|---|
| committer | Rusty Wagner <rusty@vector35.com> | 2019-03-26 17:04:04 -0400 |
| commit | 289cca29ff8d4a380c24d253edeaf8bd7c340fb2 (patch) | |
| tree | aba219c04a87c7da1430906a2148e9327cda325c /python/examples | |
| parent | 8b04c6ec72e8487883e5d71c141969dbf7eca050 (diff) | |
Add a tokenized text view class for UI plugins
Diffstat (limited to 'python/examples')
| -rw-r--r-- | python/examples/linear_mlil.py | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/python/examples/linear_mlil.py b/python/examples/linear_mlil.py new file mode 100644 index 00000000..403dddd2 --- /dev/null +++ b/python/examples/linear_mlil.py @@ -0,0 +1,139 @@ +# Copyright (c) 2019 Vector 35 Inc +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +from binaryninja.function import DisassemblyTextRenderer, DisassemblyTextLine +from binaryninja.lineardisassembly import LinearDisassemblyLine +from binaryninja.enums import LinearDisassemblyLineType, DisassemblyOption +from binaryninjaui import TokenizedTextView, TokenizedTextViewHistoryEntry, ViewType + + +class LinearMLILView(TokenizedTextView): + def __init__(self, parent, data): + super(LinearMLILView, self).__init__(parent, data) + self.data = data + self.function = data.entry_function + if self.function is not None: + self.setFunction(self.function) + self.updateLines() + + def generateLines(self): + if self.function is None: + return [] + + il = self.function.mlil + + # Set up IL display options + renderer = DisassemblyTextRenderer(il) + renderer.settings.set_option(DisassemblyOption.ShowAddress) + renderer.settings.set_option(DisassemblyOption.ShowVariableTypesWhenAssigned) + + # Sort basic blocks by IL instruction index + blocks = il.basic_blocks + blocks.sort(key = lambda block: block.start) + + # Function header + result = [] + result.append(LinearDisassemblyLine(LinearDisassemblyLineType.FunctionHeaderStartLineType, + self.function, None, 0, DisassemblyTextLine([], self.function.start))) + result.append(LinearDisassemblyLine(LinearDisassemblyLineType.FunctionHeaderLineType, + self.function, None, 0, DisassemblyTextLine(self.function.type_tokens, self.function.start))) + result.append(LinearDisassemblyLine(LinearDisassemblyLineType.FunctionHeaderEndLineType, + self.function, None, 0, DisassemblyTextLine([], self.function.start))) + + # Display IL instructions in order + lastAddr = self.function.start + lastBlock = None + lineIndex = 0 + for block in il: + if lastBlock is not None: + # Blank line between basic blocks + result.append(LinearDisassemblyLine(LinearDisassemblyLineType.CodeDisassemblyLineType, + self.function, block, 0, DisassemblyTextLine([], lastAddr))) + for i in block: + lines, length = renderer.get_disassembly_text(i.instr_index) + lastAddr = i.address + lineIndex = 0 + for line in lines: + result.append(LinearDisassemblyLine(LinearDisassemblyLineType.CodeDisassemblyLineType, + self.function, block, lineIndex, line)) + lineIndex += 1 + lastBlock = block + + result.append(LinearDisassemblyLine(LinearDisassemblyLineType.FunctionEndLineType, + self.function, lastBlock, lineIndex, DisassemblyTextLine([], lastAddr))) + + return result + + def updateLines(self): + self.setUpdatedLines(self.generateLines()) + + def navigate(self, addr): + # Find correct function based on most recent use + block = self.data.get_recent_basic_block_at(addr) + if block is None: + # If function isn't done analyzing yet, it may have a function start but no basic blocks + func = self.data.get_recent_function_at(addr) + else: + func = block.function + + if func is None: + # No function contains this address, fail navigation in this view + return False + + self.function = func + self.setFunction(self.function) + self.setLines(self.generateLines()) + return True + + def getHistoryEntry(self): + class LinearMLILHistoryEntry(TokenizedTextViewHistoryEntry): + def __init__(self, function): + super(LinearMLILHistoryEntry, self).__init__() + self.function = function + + result = LinearMLILHistoryEntry(self.function) + self.populateDefaultHistoryEntry(result) + return result + + def navigateToHistoryEntry(self, entry): + if hasattr(entry, 'function'): + self.function = entry.function + self.setFunction(self.function) + self.updateLines() + super(LinearMLILView, self).navigateToHistoryEntry(entry) + + +# View type for the new view +class LinearMLILViewType(ViewType): + def __init__(self): + super(LinearMLILViewType, self).__init__("Linear MLIL", "Linear MLIL") + + def getPriority(self, data, filename): + if data.executable: + # Use low priority so that this view is not picked by default + return 1 + return 0 + + def create(self, data, view_frame): + return LinearMLILView(view_frame, data) + + +# Register the view type so that it can be chosen by the user +ViewType.registerViewType(LinearMLILViewType()) |
