diff options
| author | KyleMiles <krm504@nyu.edu> | 2021-07-20 16:28:33 -0400 |
|---|---|---|
| committer | KyleMiles <krm504@nyu.edu> | 2021-07-26 16:09:18 -0400 |
| commit | d999ff47c7c81030e5c592f93d8a1415de058882 (patch) | |
| tree | 1f8fa0df54d4a3324ebc713179e128b0a662e9d8 /python | |
| parent | 661d7c953e7a81e82f3eb6a70c03041354d73bfd (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.py | 21 | ||||
| -rw-r--r-- | python/highlevelil.py | 57 | ||||
| -rw-r--r-- | python/lowlevelil.py | 142 | ||||
| -rw-r--r-- | python/mediumlevelil.py | 48 |
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): |
