summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorKyleMiles <krm504@nyu.edu>2021-07-20 16:28:33 -0400
committerKyleMiles <krm504@nyu.edu>2021-07-26 16:09:18 -0400
commitd999ff47c7c81030e5c592f93d8a1415de058882 (patch)
tree1f8fa0df54d4a3324ebc713179e128b0a662e9d8 /python
parent661d7c953e7a81e82f3eb6a70c03041354d73bfd (diff)
Python API : Fix copyright year, add .vars to IL functions, remove BNGetFunctionILVariables, prevent variables without types (from Mapped MLIL) from erroring out in function.Variable's __repr__, added BNGetLowLevel-Registers, RegisterStacks, Flags, MemoryVersions, and their respective SSA versions, added `LowLevelILFunction`- `.vars`, `.ssa_vars`, `.registers`, `.register_stacks`, `.flags`, `.memory_versions` and ssa versions.
Diffstat (limited to 'python')
-rw-r--r--python/function.py21
-rw-r--r--python/highlevelil.py57
-rw-r--r--python/lowlevelil.py142
-rw-r--r--python/mediumlevelil.py48
4 files changed, 243 insertions, 25 deletions
diff --git a/python/function.py b/python/function.py
index 64aacb05..e3d0521c 100644
--- a/python/function.py
+++ b/python/function.py
@@ -828,7 +828,9 @@ class Variable(object):
self._type = var_type
def __repr__(self):
- return "<var %s %s%s>" % (self.type.get_string_before_name(), self.name, self.type.get_string_after_name())
+ if self.type is None:
+ return f"<var unknown-type {self.name}>"
+ return f"<var {self.type.get_string_before_name()} {self.name}{self.type.get_string_after_name()}>"
def __str__(self):
return self.name
@@ -2264,23 +2266,6 @@ class Function(object):
core.BNFreeVariableNameAndTypeList(v, count.value)
return result
- def get_il_vars(self, il_type: FunctionGraphType) -> List[Variable]:
- """
- Get a (read-only) list of the variables used in the given IL. Only
- accepts ``MediumLevelILFunctionGraph`` or ``HighLevelILFunctionGraph``
- for ``il_type``, otherwise nothing will be returned.
- """
-
- count = ctypes.c_ulonglong()
- v = core.BNGetFunctionILVariables(self.handle, il_type, count)
-
- result = []
- for i in range(0, count.value):
- result.append(Variable(self, v[i].type, v[i].index, v[i].storage))
-
- core.BNFreeVariableList(v, count.value)
- return result
-
@property
def indirect_branches(self):
"""List of indirect branches (read-only)"""
diff --git a/python/highlevelil.py b/python/highlevelil.py
index 55d979f8..45f6def4 100644
--- a/python/highlevelil.py
+++ b/python/highlevelil.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2019 Vector 35 Inc
+# Copyright (c) 2019-2021 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
@@ -20,11 +20,12 @@
import ctypes
import struct
+from typing import List
# Binary Ninja components
import binaryninja
from binaryninja import _binaryninjacore as core
-from binaryninja.enums import HighLevelILOperation, InstructionTextTokenType
+from binaryninja.enums import HighLevelILOperation, FunctionGraphType
from binaryninja import function
from binaryninja import lowlevelil
from binaryninja import mediumlevelil
@@ -661,6 +662,13 @@ class HighLevelILFunction(object):
if self.handle is not None:
core.BNFreeHighLevelILFunction(self.handle)
+ def __repr__(self):
+ arch = self.source_function.arch
+ if arch:
+ return "<hlil func: %s@%#x>" % (arch.name, self.source_function.start)
+ else:
+ return "<hlil func: %#x>" % self.source_function.start
+
def __eq__(self, other):
if not isinstance(other, self.__class__):
return NotImplemented
@@ -916,6 +924,51 @@ class HighLevelILFunction(object):
self._source_function = value
@property
+ def il_form(self) -> "binaryninja.enums.FunctionGraphType":
+ if len(self.basic_blocks) < 1:
+ return FunctionGraphType.InvalidILViewType
+ return FunctionGraphType(core.BNGetBasicBlockFunctionGraphType(self.basic_blocks[0].handle))
+
+ @property
+ def vars(self) -> List["binaryninja.function.Variable"]:
+ """This gets just the HLIL variables - you may be interested in the union of `HighLevelIlFunction.source_function.param_vars` for all the variables used in the function"""
+ if self.source_function is None:
+ return []
+
+ if self.il_form == FunctionGraphType.HighLevelILFunctionGraph or self.il_form == FunctionGraphType.HighLevelILSSAFormFunctionGraph:
+ count = ctypes.c_ulonglong()
+ core_variables = core.BNGetHighLevelILVariables(self.handle, count)
+ result = []
+ for var_i in range(count.value):
+ result.append(function.Variable(self.source_function, core_variables[var_i].type, core_variables[var_i].index, core_variables[var_i].storage))
+ core.BNFreeVariableList(core_variables)
+ return result
+ return []
+
+ @property
+ def ssa_vars(self) -> List["binaryninja.mediumlevelil.SSAVariable"]:
+ """This gets just the HLIL SSA variables - you may be interested in the union of `HighLevelIlFunction.source_function.param_vars` for all the variables used in the function"""
+ if self.source_function is None:
+ return []
+
+ if self.il_form == FunctionGraphType.HighLevelILSSAFormFunctionGraph:
+ variable_count = ctypes.c_ulonglong()
+ core_variables = core.BNGetHighLevelILVariables(self.handle, variable_count)
+ result = []
+ for var_i in range(variable_count.value):
+ version_count = ctypes.c_ulonglong()
+ versions = core.BNGetHighLevelILVariableSSAVersions(self.handle, core_variables[var_i], version_count)
+
+ for version_i in range(version_count.value):
+ result.append(mediumlevelil.SSAVariable(function.Variable(self.source_function, core_variables[var_i].type, core_variables[var_i].index, core_variables[var_i].storage), versions[version_i]))
+ core.BNFreeILInstructionList(versions)
+
+ core.BNFreeVariableList(core_variables)
+ return result
+
+ return []
+
+ @property
def medium_level_il(self):
"""Medium level IL for this function"""
result = core.BNGetMediumLevelILForHighLevelILFunction(self.handle)
diff --git a/python/lowlevelil.py b/python/lowlevelil.py
index 11600924..a8814d8e 100644
--- a/python/lowlevelil.py
+++ b/python/lowlevelil.py
@@ -24,9 +24,11 @@ import struct
# Binary Ninja components
import binaryninja
from binaryninja import _binaryninjacore as core
-from binaryninja.enums import LowLevelILOperation, LowLevelILFlagCondition, InstructionTextTokenType
+from binaryninja.enums import LowLevelILOperation, LowLevelILFlagCondition, FunctionGraphType, VariableSourceType
from binaryninja import basicblock #required for LowLevelILBasicBlock
+from typing import List, Union
+
# 2-3 compatibility
from binaryninja import range
@@ -40,6 +42,7 @@ class LowLevelILLabel(object):
self.handle = handle
+# TODO : It would be nice to add a `.versions` to IL vars (regs, stack regs, flags) to see all the SSA versions of the given variable. Would need to associate the source function
class ILRegister(object):
def __init__(self, arch, reg):
self._arch = arch
@@ -55,7 +58,7 @@ class ILRegister(object):
return self._arch.regs[self._name]
def __repr__(self):
- return self._name
+ return f"<reg {self._name}>"
def __str__(self):
return self._name
@@ -123,7 +126,7 @@ class ILRegisterStack(object):
return self._arch.reg_stacks[self._name]
def __repr__(self):
- return self._name
+ return f"<reg-stack {self._name}>"
def __str__(self):
return self._name
@@ -180,7 +183,7 @@ class ILFlag(object):
self._name = self._arch.get_flag_name(self._index)
def __repr__(self):
- return self._name
+ return f"<flag {self._name}>"
def __str__(self):
return self._name
@@ -1496,6 +1499,137 @@ class LowLevelILFunction(object):
def source_function(self, value):
self._source_function = value
+ @property
+ def il_form(self) -> "binaryninja.enums.FunctionGraphType":
+ if len(self.basic_blocks) < 1:
+ return FunctionGraphType.InvalidILViewType
+ return FunctionGraphType(core.BNGetBasicBlockFunctionGraphType(self.basic_blocks[0].handle))
+
+ @property
+ def registers(self) -> List[ILRegister]:
+ """ List of registers used in this IL """
+ count = ctypes.c_ulonglong()
+ registers = core.BNGetLowLevelRegisters(self.handle, count)
+
+ result = []
+ for var_i in range(count.value):
+ result.append(ILRegister(self.arch, registers[var_i]))
+ core.BNFreeLLILVariablesList(registers)
+ return result
+
+ @property
+ def register_stacks(self) -> List[ILRegisterStack]:
+ """ List of register stacks used in this IL """
+ count = ctypes.c_ulonglong()
+ registerStacks = core.BNGetLowLevelRegisterStacks(self.handle, count)
+
+ result = []
+ for var_i in range(count.value):
+ result.append(ILRegisterStack(self.arch, registerStacks[var_i]))
+ core.BNFreeLLILVariablesList(registerStacks)
+ return result
+
+ @property
+ def flags(self) -> List[ILFlag]:
+ """ List of flags used in this IL """
+ count = ctypes.c_ulonglong()
+ flags = core.BNGetLowLevelFlags(self.handle, count)
+
+ result = []
+ for var_i in range(count.value):
+ result.append(ILFlag(self.arch, flags[var_i]))
+ core.BNFreeLLILVariablesList(flags)
+ return result
+
+ @property
+ def ssa_registers(self) -> List[SSARegister]:
+ """ List of SSA registers used in this IL """
+ if self.il_form != FunctionGraphType.LowLevelILSSAFormFunctionGraph:
+ return []
+
+ register_count = ctypes.c_ulonglong()
+ registers = core.BNGetLowLevelRegisters(self.handle, register_count)
+ result = []
+ for var_i in range(register_count.value):
+ version_count = ctypes.c_ulonglong()
+ versions = core.BNGetLowLevelRegisterSSAVersions(self.handle, registers[var_i], version_count)
+
+ for version_i in range(version_count.value):
+ result.append(SSARegister(ILRegister(self.arch, registers[var_i]), versions[version_i]))
+ core.BNFreeLLILVariableVersionList(versions)
+
+ core.BNFreeLLILVariablesList(registers)
+ return result
+
+ @property
+ def ssa_register_stacks(self) -> List[SSARegisterStack]:
+ """ List of SSA register stacks used in this IL """
+ if self.il_form != FunctionGraphType.LowLevelILSSAFormFunctionGraph:
+ return []
+
+ register_stack_count = ctypes.c_ulonglong()
+ register_stacks = core.BNGetLowLevelRegisterStacks(self.handle, register_stack_count)
+ result = []
+ for var_i in range(register_stack_count.value):
+ version_count = ctypes.c_ulonglong()
+ versions = core.BNGetLowLevelRegisterStackSSAVersions(self.handle, register_stacks[var_i], version_count)
+
+ for version_i in range(version_count.value):
+ result.append(SSARegisterStack(ILRegisterStack(self.arch, register_stacks[var_i]), versions[version_i]))
+ core.BNFreeLLILVariableVersionList(versions)
+
+ core.BNFreeLLILVariablesList(register_stacks)
+ return result
+
+ @property
+ def ssa_flags(self) -> List[SSAFlag]:
+ """ List of SSA flags used in this IL """
+ if self.il_form != FunctionGraphType.LowLevelILSSAFormFunctionGraph:
+ return []
+
+ flag_count = ctypes.c_ulonglong()
+ flags = core.BNGetLowLevelFlags(self.handle, flag_count)
+ result = []
+ for var_i in range(flag_count.value):
+ version_count = ctypes.c_ulonglong()
+ versions = core.BNGetLowLevelFlagSSAVersions(self.handle, flags[var_i], version_count)
+
+ for version_i in range(version_count.value):
+ result.append(SSAFlag(ILFlag(self.arch, flags[var_i]), versions[version_i]))
+ core.BNFreeLLILVariableVersionList(versions)
+
+ core.BNFreeLLILVariablesList(flags)
+ return result
+
+ @property
+ def memory_versions(self) -> List[int]:
+ """ List of memory versions used in this IL """
+ count = ctypes.c_ulonglong()
+ memory_versions = core.BNGetLowLevelMemoryVersions(self.handle, count)
+
+ result = []
+ for version_i in range(count.value):
+ result.append(memory_versions[version_i])
+ core.BNFreeLLILVariableVersionList(memory_versions)
+ return result
+
+ @property
+ def vars(self) -> List[Union[ILRegister, ILRegisterStack, ILFlag]]:
+ """This is the union `LowLevelILFunction.registers`, `LowLevelILFunction.register_stacks`, and `LowLevelILFunction.flags`"""
+ if self._source_function is None:
+ return []
+
+ if self.il_form in [FunctionGraphType.LiftedILFunctionGraph, FunctionGraphType.LowLevelILFunctionGraph, FunctionGraphType.LowLevelILSSAFormFunctionGraph]:
+ return self.registers + self.register_stacks + self.flags
+ return []
+
+ @property
+ def ssa_vars(self) -> List["binaryninja.mediumlevelil.SSAVariable"]:
+ """This is the union `LowLevelILFunction.ssa_registers`, `LowLevelILFunction.ssa_register_stacks`, and `LowLevelILFunction.ssa_flags`"""
+ if self.il_form == FunctionGraphType.LowLevelILSSAFormFunctionGraph:
+ return self.ssa_registers + self.ssa_register_stacks + self.ssa_flags
+ return []
+
def get_instruction_start(self, addr, arch = None):
if arch is None:
arch = self._arch
diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py
index 93f83d1b..c2e9a5eb 100644
--- a/python/mediumlevelil.py
+++ b/python/mediumlevelil.py
@@ -20,11 +20,12 @@
import ctypes
import struct
+from typing import List
# Binary Ninja components
import binaryninja
from binaryninja import _binaryninjacore as core
-from binaryninja.enums import MediumLevelILOperation, InstructionTextTokenType, ILBranchDependence, DataFlowQueryOption
+from binaryninja.enums import MediumLevelILOperation, FunctionGraphType, ILBranchDependence
from binaryninja import basicblock #required for MediumLevelILBasicBlock argument
from binaryninja import function
from binaryninja import types
@@ -1239,6 +1240,51 @@ class MediumLevelILFunction(object):
def source_function(self, value):
self._source_function = value
+ @property
+ def il_form(self) -> "binaryninja.enums.FunctionGraphType":
+ if len(self.basic_blocks) < 1:
+ return FunctionGraphType.InvalidILViewType
+ return FunctionGraphType(core.BNGetBasicBlockFunctionGraphType(self.basic_blocks[0].handle))
+
+ @property
+ def vars(self) -> List["binaryninja.function.Variable"]:
+ """This gets just the MLIL variables - you may be interested in the union of `MediumLevelIlFunction.source_function.param_vars` for all the variables used in the function"""
+ if self.source_function is None:
+ return []
+
+ if self.il_form in [FunctionGraphType.MediumLevelILFunctionGraph, FunctionGraphType.MediumLevelILSSAFormFunctionGraph, FunctionGraphType.MappedMediumLevelILFunctionGraph, FunctionGraphType.MappedMediumLevelILSSAFormFunctionGraph]:
+ count = ctypes.c_ulonglong()
+ core_variables = core.BNGetMediumLevelILVariables(self.handle, count)
+ result = []
+ for var_i in range(count.value):
+ result.append(function.Variable(self.source_function, core_variables[var_i].type, core_variables[var_i].index, core_variables[var_i].storage))
+ core.BNFreeVariableList(core_variables)
+ return result
+ return []
+
+ @property
+ def ssa_vars(self) -> List["binaryninja.mediumlevelil.SSAVariable"]:
+ """This gets just the MLIL SSA variables - you may be interested in the union of `MediumLevelIlFunction.source_function.param_vars` for all the variables used in the function"""
+ if self.source_function is None:
+ return []
+
+ if self.il_form in [FunctionGraphType.MediumLevelILSSAFormFunctionGraph, FunctionGraphType.MappedMediumLevelILSSAFormFunctionGraph]:
+ variable_count = ctypes.c_ulonglong()
+ core_variables = core.BNGetMediumLevelILVariables(self.handle, variable_count)
+ result = []
+ for var_i in range(variable_count.value):
+ version_count = ctypes.c_ulonglong()
+ versions = core.BNGetMediumLevelILVariableSSAVersions(self.handle, core_variables[var_i], version_count)
+
+ for version_i in range(version_count.value):
+ result.append(SSAVariable(function.Variable(self.source_function, core_variables[var_i].type, core_variables[var_i].index, core_variables[var_i].storage), versions[version_i]))
+ core.BNFreeILInstructionList(versions)
+
+ core.BNFreeVariableList(core_variables)
+ return result
+
+ return []
+
class MediumLevelILBasicBlock(basicblock.BasicBlock):
def __init__(self, view, handle, owner):