summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorRusty Wagner <rusty@vector35.com>2019-07-23 22:40:39 -0400
committerRusty Wagner <rusty@vector35.com>2020-04-17 14:20:35 -0400
commit203717232e816d42973f05f1c9fbc950914d71dc (patch)
tree71b1316a95417ea36147230faf4aa7c44556ea0a /python
parent072c5cd6eee7af9671e6c4fe583e77bc3bcbdd1d (diff)
Early HLIL testing
Diffstat (limited to 'python')
-rw-r--r--python/__init__.py1
-rw-r--r--python/flowgraph.py20
-rw-r--r--python/function.py38
-rw-r--r--python/highlevelil.py729
-rw-r--r--python/lineardisassembly.py6
-rw-r--r--python/scriptingprovider.py2
6 files changed, 793 insertions, 3 deletions
diff --git a/python/__init__.py b/python/__init__.py
index 95cb1f82..f0c4446f 100644
--- a/python/__init__.py
+++ b/python/__init__.py
@@ -45,6 +45,7 @@ from binaryninja.function import *
from binaryninja.log import *
from binaryninja.lowlevelil import *
from binaryninja.mediumlevelil import *
+from binaryninja.highlevelil import *
from binaryninja.types import *
from binaryninja.typelibrary import *
from binaryninja.functionrecognizer import *
diff --git a/python/flowgraph.py b/python/flowgraph.py
index 32303c93..6c3f41f7 100644
--- a/python/flowgraph.py
+++ b/python/flowgraph.py
@@ -30,6 +30,7 @@ from binaryninja import function
from binaryninja import binaryview
from binaryninja import lowlevelil
from binaryninja import mediumlevelil
+from binaryninja import highlevelil
from binaryninja import basicblock
from binaryninja import log
from binaryninja import highlight
@@ -532,6 +533,10 @@ class FlowGraph(object):
return core.BNIsMediumLevelILFlowGraph(self.handle)
@property
+ def is_high_level_il(self):
+ return core.BNIsHighLevelILFlowGraph(self.handle)
+
+ @property
def il_function(self):
if self.is_low_level_il:
il_func = core.BNGetFlowGraphLowLevelILFunction(self.handle)
@@ -549,6 +554,14 @@ class FlowGraph(object):
if function is None:
return None
return mediumlevelil.MediumLevelILFunction(function.arch, il_func, function)
+ if self.is_high_level_il:
+ il_func = core.BNGetFlowGraphHighLevelILFunction(self.handle)
+ if not il_func:
+ return None
+ function = self.function
+ if function is None:
+ return None
+ return highlevelil.HighLevelILFunction(function.arch, il_func, function)
return None
@il_function.setter
@@ -556,12 +569,19 @@ class FlowGraph(object):
if isinstance(func, lowlevelil.LowLevelILFunction):
core.BNSetFlowGraphLowLevelILFunction(self.handle, func.handle)
core.BNSetFlowGraphMediumLevelILFunction(self.handle, None)
+ core.BNSetFlowGraphHighLevelILFunction(self.handle, None)
elif isinstance(func, mediumlevelil.MediumLevelILFunction):
core.BNSetFlowGraphLowLevelILFunction(self.handle, None)
core.BNSetFlowGraphMediumLevelILFunction(self.handle, func.handle)
+ core.BNSetFlowGraphHighLevelILFunction(self.handle, None)
+ elif isinstance(func, highlevelil.HighLevelILFunction):
+ core.BNSetFlowGraphLowLevelILFunction(self.handle, None)
+ core.BNSetFlowGraphMediumLevelILFunction(self.handle, None)
+ core.BNSetFlowGraphHighLevelILFunction(self.handle, func.handle)
elif func is None:
core.BNSetFlowGraphLowLevelILFunction(self.handle, None)
core.BNSetFlowGraphMediumLevelILFunction(self.handle, None)
+ core.BNSetFlowGraphHighLevelILFunction(self.handle, None)
else:
raise TypeError("expected IL function for setting il_function property")
diff --git a/python/function.py b/python/function.py
index 7cee467c..dfb83e34 100644
--- a/python/function.py
+++ b/python/function.py
@@ -1217,7 +1217,10 @@ class Function(object):
@property
def llil_if_available(self):
"""returns LowLevelILFunction used to represent Function low level IL, or None if not loaded (read-only)"""
- return binaryninja.lowlevelil.LowLevelILFunction(self.arch, core.BNGetFunctionLowLevelILIfAvailable(self.handle), self)
+ result = core.BNGetFunctionLowLevelILIfAvailable(self.handle)
+ if not result:
+ return None
+ return binaryninja.lowlevelil.LowLevelILFunction(self.arch, result, self)
@property
def lifted_il(self):
@@ -1227,7 +1230,10 @@ class Function(object):
@property
def lifted_il_if_available(self):
"""returns LowLevelILFunction used to represent lifted IL, or None if not loaded (read-only)"""
- return binaryninja.lowlevelil.LowLevelILFunction(self.arch, core.BNGetFunctionLiftedILIfAvailable(self.handle), self)
+ result = core.BNGetFunctionLiftedILIfAvailable(self.handle)
+ if not result:
+ return None
+ return binaryninja.lowlevelil.LowLevelILFunction(self.arch, result, self)
@property
def medium_level_il(self):
@@ -1242,7 +1248,28 @@ class Function(object):
@property
def mlil_if_available(self):
"""Function medium level IL, or None if not loaded (read-only)"""
- return binaryninja.mediumlevelil.MediumLevelILFunction(self.arch, core.BNGetFunctionMediumLevelILIfAvailable(self.handle), self)
+ result = core.BNGetFunctionMediumLevelILIfAvailable(self.handle)
+ if not result:
+ return None
+ return binaryninja.mediumlevelil.MediumLevelILFunction(self.arch, result, self)
+
+ @property
+ def high_level_il(self):
+ """Deprecated property provided for compatibility. Use hlil instead."""
+ return binaryninja.highlevelil.HighLevelILFunction(self.arch, core.BNGetFunctionHighLevelIL(self.handle), self)
+
+ @property
+ def hlil(self):
+ """Function high level IL (read-only)"""
+ return binaryninja.highlevelil.HighLevelILFunction(self.arch, core.BNGetFunctionHighLevelIL(self.handle), self)
+
+ @property
+ def hlil_if_available(self):
+ """Function high level IL, or None if not loaded (read-only)"""
+ result = core.BNGetFunctionHighLevelILIfAvailable(self.handle)
+ if not result:
+ return None
+ return binaryninja.highlevelil.HighLevelILFunction(self.arch, result, self)
@property
def function_type(self):
@@ -3004,6 +3031,8 @@ class DisassemblyTextRenderer(object):
self.handle = core.BNCreateLowLevelILDisassemblyTextRenderer(func.handle, settings_obj)
elif isinstance(func, binaryninja.mediumlevelil.MediumLevelILFunction):
self.handle = core.BNCreateMediumLevelILDisassemblyTextRenderer(func.handle, settings_obj)
+ elif isinstance(func, binaryninja.highlevelil.HighLevelILFunction):
+ self.handle = core.BNCreateHighLevelILDisassemblyTextRenderer(func.handle, settings_obj)
else:
raise TypeError("invalid function object")
else:
@@ -3024,6 +3053,9 @@ class DisassemblyTextRenderer(object):
mlil = core.BNGetDisassemblyTextRendererMediumLevelILFunction(self.handle)
if mlil:
return binaryninja.mediumlevelil.MediumLevelILFunction(handle = mlil)
+ hlil = core.BNGetDisassemblyTextRendererHighLevelILFunction(self.handle)
+ if hlil:
+ return binaryninja.highlevelil.HighLevelILFunction(handle = hlil)
return None
@property
diff --git a/python/highlevelil.py b/python/highlevelil.py
new file mode 100644
index 00000000..d657ddc4
--- /dev/null
+++ b/python/highlevelil.py
@@ -0,0 +1,729 @@
+# 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.
+
+import ctypes
+import struct
+
+# Binary Ninja components
+import binaryninja
+from binaryninja import _binaryninjacore as core
+from binaryninja.enums import HighLevelILOperation, InstructionTextTokenType
+from binaryninja import function
+from binaryninja import lowlevelil
+from binaryninja import mediumlevelil
+from binaryninja import basicblock
+
+# 2-3 compatibility
+from binaryninja import range
+
+
+class HighLevelILOperationAndSize(object):
+ def __init__(self, operation, size):
+ self._operation = operation
+ self._size = size
+
+ def __repr__(self):
+ if self._size == 0:
+ return "<%s>" % self._operation.name
+ return "<%s %d>" % (self._operation.name, self._size)
+
+ def __eq__(self, other):
+ if isinstance(other, HighLevelILOperation):
+ return other == self._operation
+ if isinstance(other, HighLevelILOperationAndSize):
+ return other.size == self._size and other.operation == self._operation
+ else:
+ return False
+
+ @property
+ def operation(self):
+ """ """
+ return self._operation
+
+ @operation.setter
+ def operation(self, value):
+ self._operation = value
+
+ @property
+ def size(self):
+ """ """
+ return self._size
+
+ @size.setter
+ def size(self, value):
+ self._size = value
+
+
+class HighLevelILInstruction(object):
+ """
+ ``class HighLevelILInstruction`` High Level Intermediate Language Instructions form an abstract syntax tree of
+ the code. Control flow structures are present as high level constructs in the HLIL tree.
+ """
+
+ ILOperations = {
+ HighLevelILOperation.HLIL_NOP: [],
+ HighLevelILOperation.HLIL_BLOCK: [("body", "expr_list")],
+ HighLevelILOperation.HLIL_IF: [("condition", "expr"), ("true", "expr"), ("false", "expr")],
+ HighLevelILOperation.HLIL_WHILE: [("condition", "expr"), ("body", "expr")],
+ HighLevelILOperation.HLIL_DO_WHILE: [("body", "expr"), ("condition", "expr")],
+ HighLevelILOperation.HLIL_FOR: [("init", "expr"), ("condition", "expr"), ("update", "expr"), ("body", "expr")],
+ HighLevelILOperation.HLIL_SWITCH: [("condition", "expr"), ("default", "expr"), ("cases", "expr_list")],
+ HighLevelILOperation.HLIL_CASE: [("condition", "expr"), ("body", "expr")],
+ HighLevelILOperation.HLIL_BREAK: [],
+ HighLevelILOperation.HLIL_JUMP: [("dest", "expr")],
+ HighLevelILOperation.HLIL_RET: [("src", "expr_list")],
+ HighLevelILOperation.HLIL_NORET: [],
+ HighLevelILOperation.HLIL_GOTO: [("target", "int")],
+ HighLevelILOperation.HLIL_LABEL: [("target", "int")],
+ HighLevelILOperation.HLIL_ASSIGN: [("dest", "expr"), ("src", "expr")],
+ HighLevelILOperation.HLIL_ASSIGN_UNPACK: [("dest", "expr_list"), ("src", "expr")],
+ HighLevelILOperation.HLIL_VAR: [("var", "var")],
+ HighLevelILOperation.HLIL_VAR_SSA: [("var", "var_ssa")],
+ HighLevelILOperation.HLIL_VAR_PHI: [("dest", "var_ssa"), ("src", "var_ssa_list")],
+ HighLevelILOperation.HLIL_STRUCT_FIELD: [("src", "expr"), ("offset", "int")],
+ HighLevelILOperation.HLIL_ARRAY_INDEX: [("src", "expr"), ("index", "expr")],
+ HighLevelILOperation.HLIL_SPLIT: [("high", "expr"), ("low", "expr")],
+ HighLevelILOperation.HLIL_DEREF: [("src", "expr")],
+ HighLevelILOperation.HLIL_DEREF_FIELD: [("src", "expr"), ("offset", "int")],
+ HighLevelILOperation.HLIL_ADDRESS_OF: [("src", "expr")],
+ HighLevelILOperation.HLIL_CONST: [("constant", "int")],
+ HighLevelILOperation.HLIL_CONST_PTR: [("constant", "int")],
+ HighLevelILOperation.HLIL_EXTERN_PTR: [("constant", "int"), ("offset", "int")],
+ HighLevelILOperation.HLIL_FLOAT_CONST: [("constant", "float")],
+ HighLevelILOperation.HLIL_IMPORT: [("constant", "int")],
+ HighLevelILOperation.HLIL_ADD: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_ADC: [("left", "expr"), ("right", "expr"), ("carry", "expr")],
+ HighLevelILOperation.HLIL_SUB: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_SBB: [("left", "expr"), ("right", "expr"), ("carry", "expr")],
+ HighLevelILOperation.HLIL_AND: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_OR: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_XOR: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_LSL: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_LSR: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_ASR: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_ROL: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_RLC: [("left", "expr"), ("right", "expr"), ("carry", "expr")],
+ HighLevelILOperation.HLIL_ROR: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_RRC: [("left", "expr"), ("right", "expr"), ("carry", "expr")],
+ HighLevelILOperation.HLIL_MUL: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_MULU_DP: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_MULS_DP: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_DIVU: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_DIVU_DP: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_DIVS: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_DIVS_DP: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_MODU: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_MODU_DP: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_MODS: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_MODS_DP: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_NEG: [("src", "expr")],
+ HighLevelILOperation.HLIL_NOT: [("src", "expr")],
+ HighLevelILOperation.HLIL_SX: [("src", "expr")],
+ HighLevelILOperation.HLIL_ZX: [("src", "expr")],
+ HighLevelILOperation.HLIL_LOW_PART: [("src", "expr")],
+ HighLevelILOperation.HLIL_CALL: [("dest", "expr"), ("params", "expr_list")],
+ HighLevelILOperation.HLIL_CMP_E: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_CMP_NE: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_CMP_SLT: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_CMP_ULT: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_CMP_SLE: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_CMP_ULE: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_CMP_SGE: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_CMP_UGE: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_CMP_SGT: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_CMP_UGT: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_TEST_BIT: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_BOOL_TO_INT: [("src", "expr")],
+ HighLevelILOperation.HLIL_ADD_OVERFLOW: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_SYSCALL: [("params", "expr_list")],
+ HighLevelILOperation.HLIL_TAILCALL: [("dest", "expr"), ("params", "expr_list")],
+ HighLevelILOperation.HLIL_BP: [],
+ HighLevelILOperation.HLIL_TRAP: [("vector", "int")],
+ HighLevelILOperation.HLIL_INTRINSIC: [("intrinsic", "intrinsic"), ("params", "expr_list")],
+ HighLevelILOperation.HLIL_UNDEF: [],
+ HighLevelILOperation.HLIL_UNIMPL: [],
+ HighLevelILOperation.HLIL_UNIMPL_MEM: [("src", "expr")],
+ HighLevelILOperation.HLIL_FADD: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_FSUB: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_FMUL: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_FDIV: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_FSQRT: [("src", "expr")],
+ HighLevelILOperation.HLIL_FNEG: [("src", "expr")],
+ HighLevelILOperation.HLIL_FABS: [("src", "expr")],
+ HighLevelILOperation.HLIL_FLOAT_TO_INT: [("src", "expr")],
+ HighLevelILOperation.HLIL_INT_TO_FLOAT: [("src", "expr")],
+ HighLevelILOperation.HLIL_FLOAT_CONV: [("src", "expr")],
+ HighLevelILOperation.HLIL_ROUND_TO_INT: [("src", "expr")],
+ HighLevelILOperation.HLIL_FLOOR: [("src", "expr")],
+ HighLevelILOperation.HLIL_CEIL: [("src", "expr")],
+ HighLevelILOperation.HLIL_FTRUNC: [("src", "expr")],
+ HighLevelILOperation.HLIL_FCMP_E: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_FCMP_NE: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_FCMP_LT: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_FCMP_LE: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_FCMP_GE: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_FCMP_GT: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_FCMP_O: [("left", "expr"), ("right", "expr")],
+ HighLevelILOperation.HLIL_FCMP_UO: [("left", "expr"), ("right", "expr")]
+ }
+
+ def __init__(self, func, expr_index, as_ast = True):
+ instr = core.BNGetHighLevelILByIndex(func.handle, expr_index)
+ self._function = func
+ self._expr_index = expr_index
+ self._operation = HighLevelILOperation(instr.operation)
+ self._size = instr.size
+ self._address = instr.address
+ self._source_operand = instr.sourceOperand
+ self._parent = instr.parent
+ self._as_ast = as_ast
+ operands = HighLevelILInstruction.ILOperations[instr.operation]
+ self._operands = []
+ i = 0
+ for operand in operands:
+ name, operand_type = operand
+ if operand_type == "int":
+ value = instr.operands[i]
+ value = (value & ((1 << 63) - 1)) - (value & (1 << 63))
+ elif operand_type == "float":
+ if instr.size == 4:
+ value = struct.unpack("f", struct.pack("I", instr.operands[i] & 0xffffffff))[0]
+ elif instr.size == 8:
+ value = struct.unpack("d", struct.pack("Q", instr.operands[i]))[0]
+ else:
+ value = instr.operands[i]
+ elif operand_type == "expr":
+ value = HighLevelILInstruction(func, instr.operands[i], self._as_ast)
+ elif operand_type == "intrinsic":
+ value = lowlevelil.ILIntrinsic(func.arch, instr.operands[i])
+ elif operand_type == "var":
+ value = function.Variable.from_identifier(self._function.source_function, instr.operands[i])
+ elif operand_type == "var_ssa":
+ var = function.Variable.from_identifier(self._function.source_function, instr.operands[i])
+ version = instr.operands[i + 1]
+ i += 1
+ value = mediumlevelil.SSAVariable(var, version)
+ elif operand_type == "int_list":
+ count = ctypes.c_ulonglong()
+ operand_list = core.BNHighLevelILGetOperandList(func.handle, self._expr_index, i, count)
+ value = []
+ for j in range(count.value):
+ value.append(operand_list[j])
+ core.BNHighLevelILFreeOperandList(operand_list)
+ elif operand_type == "expr_list":
+ count = ctypes.c_ulonglong()
+ operand_list = core.BNHighLevelILGetOperandList(func.handle, self._expr_index, i, count)
+ i += 1
+ value = []
+ for j in range(count.value):
+ value.append(HighLevelILInstruction(func, operand_list[j], self._as_ast))
+ core.BNHighLevelILFreeOperandList(operand_list)
+ elif operand_type == "var_ssa_list":
+ count = ctypes.c_ulonglong()
+ operand_list = core.BNHighLevelILGetOperandList(func.handle, self._expr_index, i, count)
+ i += 1
+ value = []
+ for j in range(count.value // 2):
+ var_id = operand_list[j * 2]
+ var_version = operand_list[(j * 2) + 1]
+ value.append(mediumlevelil.SSAVariable(function.Variable.from_identifier(self._function.source_function,
+ var_id), var_version))
+ core.BNHighLevelILFreeOperandList(operand_list)
+ self._operands.append(value)
+ self.__dict__[name] = value
+ i += 1
+
+ def __str__(self):
+ lines = self.lines
+ if lines is None:
+ return "invalid"
+ result = []
+ for line in lines:
+ cur = ""
+ for token in line.tokens:
+ cur += token.text
+ result.append(cur)
+ return '\n'.join(result)
+
+ def __repr__(self):
+ lines = self.lines
+ continuation = ""
+ if lines is None:
+ first_line = "<invalid>"
+ else:
+ first_line = ""
+ for token in lines[0].tokens:
+ first_line += token.text
+ if len(lines) > 1:
+ continuation = "..."
+ return "<%s: %s%s>" % (self._operation.name, first_line, continuation)
+
+ def __eq__(self, value):
+ if not isinstance(value, type(self)):
+ return False
+ return self._function == value.function and self._expr_index == value.expr_index
+
+ @property
+ def lines(self):
+ """HLIL text lines (read-only)"""
+ count = ctypes.c_ulonglong()
+ lines = core.BNGetHighLevelILExprText(self._function.handle, self._expr_index, self._as_ast, count)
+ result = []
+ for i in range(0, count.value):
+ addr = lines[i].addr
+ if lines[i].instrIndex != 0xffffffffffffffff:
+ il_instr = self._function[lines[i].instrIndex]
+ else:
+ il_instr = None
+ color = binaryninja.highlight.HighlightColor._from_core_struct(lines[i].highlight)
+ tokens = binaryninja.function.InstructionTextToken.get_instruction_lines(lines[i].tokens, lines[i].count)
+ result.append(binaryninja.function.DisassemblyTextLine(tokens, addr, il_instr, color))
+ core.BNFreeDisassemblyTextLines(lines, count.value)
+ return result
+
+ @property
+ def prefix_operands(self):
+ """All operands in the expression tree in prefix order"""
+ result = [HighLevelILOperationAndSize(self._operation, self._size)]
+ for operand in self._operands:
+ if isinstance(operand, HighLevelILInstruction):
+ result += operand.prefix_operands
+ else:
+ result.append(operand)
+ return result
+
+ @property
+ def postfix_operands(self):
+ """All operands in the expression tree in postfix order"""
+ result = []
+ for operand in self._operands:
+ if isinstance(operand, HighLevelILInstruction):
+ result += operand.postfix_operands
+ else:
+ result.append(operand)
+ result.append(HighLevelILOperationAndSize(self._operation, self._size))
+ return result
+
+ def __setattr__(self, name, value):
+ try:
+ object.__setattr__(self, name, value)
+ except AttributeError:
+ raise AttributeError("attribute '%s' is read only" % name)
+
+ @property
+ def function(self):
+ """ """
+ return self._function
+
+ @function.setter
+ def function(self, value):
+ self._function = value
+
+ @property
+ def expr_index(self):
+ """ """
+ return self._expr_index
+
+ @expr_index.setter
+ def expr_index(self, value):
+ self._expr_index = value
+
+ @property
+ def instr_index(self):
+ """Index of the statement that this expression belongs to (read-only)"""
+ return core.BNGetHighLevelILInstructionForExpr(self._function.handle, self._expr_index)
+
+ @property
+ def instr(self):
+ """The statement that this expression belongs to (read-only)"""
+ return self._function[self.instr_index]
+
+ @property
+ def ast(self):
+ """This expression with full AST printing (read-only)"""
+ if self._as_ast:
+ return self
+ return HighLevelILInstruction(self._function, self._expr_index, True)
+
+ @property
+ def non_ast(self):
+ """This expression without full AST printing (read-only)"""
+ if self._as_ast:
+ return self
+ return HighLevelILInstruction(self._function, self._expr_index, False)
+
+ @property
+ def operation(self):
+ """ """
+ return self._operation
+
+ @operation.setter
+ def operation(self, value):
+ self._operation = value
+
+ @property
+ def size(self):
+ """ """
+ return self._size
+
+ @size.setter
+ def size(self, value):
+ self._size = value
+
+ @property
+ def address(self):
+ """ """
+ return self._address
+
+ @address.setter
+ def address(self, value):
+ self._address = value
+
+ @property
+ def source_operand(self):
+ """ """
+ return self._source_operand
+
+ @source_operand.setter
+ def source_operand(self, value):
+ self._source_operand = value
+
+ @property
+ def operands(self):
+ """ """
+ return self._operands
+
+ @operands.setter
+ def operands(self, value):
+ self._operands = value
+
+ @property
+ def parent(self):
+ if self._parent >= core.BNGetHighLevelILExprCount(self._function.handle):
+ return None
+ return HighLevelILInstruction(self._function, self._parent, self._as_ast)
+
+ @property
+ def medium_level_il(self):
+ """Medium level IL form of this expression"""
+ expr = self._function.get_medium_level_il_expr_index(self._expr_index)
+ if expr is None:
+ return None
+ return mediumlevelil.MediumLevelILInstruction(self._function.medium_level_il.ssa_form, expr)
+
+ @property
+ def mlil(self):
+ """Alias for medium_level_il"""
+ return self.medium_level_il
+
+ @property
+ def il_basic_block(self):
+ """IL basic block object containing this expression (read-only) (only available on finalized functions)"""
+ return HighLevelILBasicBlock(self._function.source_function.view, core.BNGetHighLevelILBasicBlockForInstruction(self._function.handle, self._instr_index), self._function)
+
+
+class HighLevelILExpr(object):
+ """
+ ``class HighLevelILExpr`` hold the index of IL Expressions.
+
+ .. note:: This class shouldn't be instantiated directly. Rather the helper members of HighLevelILFunction should be \
+ used instead.
+ """
+ def __init__(self, index):
+ self._index = index
+
+ @property
+ def index(self):
+ """ """
+ return self._index
+
+ @index.setter
+ def index(self, value):
+ self._index = value
+
+
+class HighLevelILFunction(object):
+ """
+ ``class HighLevelILFunction`` contains the a HighLevelILInstruction object that makes up the abstract syntax tree of
+ a binaryninja.function.
+ """
+ def __init__(self, arch = None, handle = None, source_func = None):
+ self._arch = arch
+ self._source_function = source_func
+ if handle is not None:
+ self.handle = core.handle_of_type(handle, core.BNHighLevelILFunction)
+ if self._source_function is None:
+ self._source_function = binaryninja.function.Function(handle = core.BNGetHighLevelILOwnerFunction(self.handle))
+ if self._arch is None:
+ self._arch = self._source_function.arch
+ else:
+ if self._source_function is None:
+ self.handle = None
+ raise ValueError("IL functions must be created with an associated function")
+ if self._arch is None:
+ self._arch = self._source_function.arch
+ func_handle = self._source_function.handle
+ self.handle = core.BNCreateHighLevelILFunction(arch.handle, func_handle)
+
+ def __hash__(self):
+ return hash(('HLIL', self._source_function))
+
+ def __del__(self):
+ if self.handle is not None:
+ core.BNFreeHighLevelILFunction(self.handle)
+
+ def __eq__(self, value):
+ if not isinstance(value, HighLevelILFunction):
+ return False
+ return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents)
+
+ def __ne__(self, value):
+ if not isinstance(value, HighLevelILFunction):
+ return True
+ return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents)
+
+ @property
+ def current_address(self):
+ """Current IL Address (read/write)"""
+ return core.BNHighLevelILGetCurrentAddress(self.handle)
+
+ @current_address.setter
+ def current_address(self, value):
+ core.BNHighLevelILSetCurrentAddress(self.handle, self._arch.handle, value)
+
+ def set_current_address(self, value, arch = None):
+ if arch is None:
+ arch = self._arch
+ core.BNHighLevelILSetCurrentAddress(self.handle, arch.handle, value)
+
+ @property
+ def root(self):
+ """Root of the abstract syntax tree"""
+ expr_index = core.BNGetHighLevelILRootExpr(self.handle)
+ if expr_index >= core.BNGetHighLevelILExprCount(self.handle):
+ return None
+ return HighLevelILInstruction(self, expr_index)
+
+ @root.setter
+ def root(self, value):
+ core.BNSetHighLevelILRootExpr(value.expr_index)
+
+ @property
+ def basic_blocks(self):
+ """list of HighLevelILBasicBlock objects (read-only)"""
+ count = ctypes.c_ulonglong()
+ blocks = core.BNGetHighLevelILBasicBlockList(self.handle, count)
+ result = []
+ view = None
+ if self._source_function is not None:
+ view = self._source_function.view
+ for i in range(0, count.value):
+ result.append(HighLevelILBasicBlock(view, core.BNNewBasicBlockReference(blocks[i]), self))
+ core.BNFreeBasicBlockList(blocks, count.value)
+ return result
+
+ @property
+ def instructions(self):
+ """A generator of hlil instructions of the current function"""
+ for block in self.basic_blocks:
+ for i in block:
+ yield i
+
+ def __setattr__(self, name, value):
+ try:
+ object.__setattr__(self, name, value)
+ except AttributeError:
+ raise AttributeError("attribute '%s' is read only" % name)
+
+ def __len__(self):
+ return int(core.BNGetHighLevelILInstructionCount(self.handle))
+
+ def __getitem__(self, i):
+ if isinstance(i, slice) or isinstance(i, tuple):
+ raise IndexError("expected integer instruction index")
+ if isinstance(i, HighLevelILExpr):
+ return HighLevelILInstruction(self, i.index)
+ # for backwards compatibility
+ if isinstance(i, HighLevelILInstruction):
+ return i
+ if (i < 0) or (i >= len(self)):
+ raise IndexError("index out of range")
+ return HighLevelILInstruction(self, core.BNGetHighLevelILIndexForInstruction(self.handle, i), False)
+
+ def __setitem__(self, i, j):
+ raise IndexError("instruction modification not implemented")
+
+ def __iter__(self):
+ count = ctypes.c_ulonglong()
+ blocks = core.BNGetHighLevelILBasicBlockList(self.handle, count)
+ view = None
+ if self._source_function is not None:
+ view = self._source_function.view
+ try:
+ for i in range(0, count.value):
+ yield HighLevelILBasicBlock(view, core.BNNewBasicBlockReference(blocks[i]), self)
+ finally:
+ core.BNFreeBasicBlockList(blocks, count.value)
+
+ def __str__(self):
+ return str(self.root)
+
+ def expr(self, operation, a = 0, b = 0, c = 0, d = 0, e = 0, size = 0):
+ if isinstance(operation, str):
+ operation = HighLevelILOperation[operation]
+ elif isinstance(operation, HighLevelILOperation):
+ operation = operation.value
+ return HighLevelILExpr(core.BNHighLevelILAddExpr(self.handle, operation, size, a, b, c, d, e))
+
+ def append(self, expr):
+ """
+ ``append`` adds the HighLevelILExpr ``expr`` to the current HighLevelILFunction.
+
+ :param HighLevelILExpr expr: the HighLevelILExpr to add to the current HighLevelILFunction
+ :return: number of HighLevelILExpr in the current function
+ :rtype: int
+ """
+ return core.BNHighLevelILAddInstruction(self.handle, expr.index)
+
+ def add_operand_list(self, operands):
+ """
+ ``add_operand_list`` returns an operand list expression for the given list of integer operands.
+
+ :param list(int) operands: list of operand numbers
+ :return: an operand list expression
+ :rtype: HighLevelILExpr
+ """
+ operand_list = (ctypes.c_ulonglong * len(operands))()
+ for i in range(len(operands)):
+ operand_list[i] = operands[i]
+ return HighLevelILExpr(core.BNHighLevelILAddOperandList(self.handle, operand_list, len(operands)))
+
+ def operand(self, n, expr):
+ """
+ ``operand`` sets the operand number of the expression ``expr`` and passes back ``expr`` without modification.
+
+ :param int n:
+ :param HighLevelILExpr expr:
+ :return: returns the expression ``expr`` unmodified
+ :rtype: HighLevelILExpr
+ """
+ core.BNHighLevelILSetExprSourceOperand(self.handle, expr.index, n)
+ return expr
+
+ def finalize(self):
+ """
+ ``finalize`` ends the function and computes the list of basic blocks.
+
+ :rtype: None
+ """
+ core.BNFinalizeHighLevelILFunction(self.handle)
+
+ def create_graph(self, settings = None):
+ if settings is not None:
+ settings_obj = settings.handle
+ else:
+ settings_obj = None
+ return binaryninja.flowgraph.CoreFlowGraph(core.BNCreateHighLevelILFunctionGraph(self.handle, settings_obj))
+
+ @property
+ def arch(self):
+ """ """
+ return self._arch
+
+ @arch.setter
+ def arch(self, value):
+ self._arch = value
+
+ @property
+ def source_function(self):
+ """ """
+ return self._source_function
+
+ @source_function.setter
+ def source_function(self, value):
+ self._source_function = value
+
+ @property
+ def medium_level_il(self):
+ """Medium level IL for this function"""
+ result = core.BNGetMediumLevelILForHighLevelILFunction(self.handle)
+ if not result:
+ return None
+ return mediumlevelil.MediumLevelILFunction(self._arch, result, self._source_function)
+
+ @property
+ def mlil(self):
+ """Alias for medium_level_il"""
+ return self.medium_level_il
+
+ def get_medium_level_il_expr_index(self, expr):
+ medium_il = self.medium_level_il
+ if medium_il is None:
+ return None
+ medium_il = medium_il.ssa_form
+ if medium_il is None:
+ return None
+ result = core.BNGetMediumLevelILExprIndexFromHighLevelIL(self.handle, expr)
+ if result >= core.BNGetMediumLevelILExprCount(medium_il.handle):
+ return None
+ return result
+
+
+class HighLevelILBasicBlock(basicblock.BasicBlock):
+ def __init__(self, view, handle, owner):
+ super(HighLevelILBasicBlock, self).__init__(handle, view)
+ self.il_function = owner
+
+ def __iter__(self):
+ for idx in range(self.start, self.end):
+ yield self.il_function[idx]
+
+ def __getitem__(self, idx):
+ size = self.end - self.start
+ if idx > size or idx < -size:
+ raise IndexError("list index is out of range")
+ if idx >= 0:
+ return self.il_function[idx + self.start]
+ else:
+ return self.il_function[self.end + idx]
+
+ def _create_instance(self, handle, view):
+ """Internal method by super to instantiate child instances"""
+ return HighLevelILBasicBlock(view, handle, self.il_function)
+
+ def __hash__(self):
+ return hash((self.start, self.end, self.il_function))
+
+ def __contains__(self, instruction):
+ if type(instruction) != HighLevelILInstruction or instruction.il_basic_block != self:
+ return False
+ if instruction.instr_index >= self.start and instruction.instr_index <= self.end:
+ return True
+ else:
+ return False
+
+ @property
+ def il_function(self):
+ """ """
+ return self._il_function
+
+ @il_function.setter
+ def il_function(self, value):
+ self._il_function = value
diff --git a/python/lineardisassembly.py b/python/lineardisassembly.py
index ec213a19..10124bad 100644
--- a/python/lineardisassembly.py
+++ b/python/lineardisassembly.py
@@ -300,6 +300,12 @@ class LinearViewObject(object):
settings = settings.handle
return LinearViewObject(core.BNCreateLinearViewMappedMediumLevelILSSAForm(view.handle, settings))
+ @classmethod
+ def hlil(cls, view, settings = None):
+ if settings is not None:
+ settings = settings.handle
+ return LinearViewObject(core.BNCreateLinearViewHighLevelIL(view.handle, settings))
+
class LinearViewCursor(object):
def __init__(self, root_object, handle = None):
diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py
index 81167e8e..73cb2a0d 100644
--- a/python/scriptingprovider.py
+++ b/python/scriptingprovider.py
@@ -625,9 +625,11 @@ class PythonScriptingInstance(ScriptingInstance):
if self.active_func is None:
self.locals["current_llil"] = None
self.locals["current_mlil"] = None
+ self.locals["current_hlil"] = None
else:
self.locals["current_llil"] = self.active_func.llil
self.locals["current_mlil"] = self.active_func.mlil
+ self.locals["current_hlil"] = self.active_func.hlil
def get_selected_data(self):