# Copyright (c) 2015-2016 Vector 35 LLC # # 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 # Binary Ninja components import _binaryninjacore as core from .enums import LowLevelILOperation, LowLevelILFlagCondition, InstructionTextTokenType import function import basicblock class LowLevelILLabel(object): def __init__(self, handle = None): if handle is None: self.handle = (core.BNLowLevelILLabel * 1)() core.BNLowLevelILInitLabel(self.handle) else: self.handle = handle class LowLevelILInstruction(object): """ ``class LowLevelILInstruction`` Low Level Intermediate Language Instructions are infinite length tree-based instructions. Tree-based instructions use infix notation with the left hand operand being the destination operand. Infix notation is thus more natural to read than other notations (e.g. x86 ``mov eax, 0`` vs. LLIL ``eax = 0``). """ ILOperations = { LowLevelILOperation.LLIL_NOP: [], LowLevelILOperation.LLIL_SET_REG: [("dest", "reg"), ("src", "expr")], LowLevelILOperation.LLIL_SET_REG_SPLIT: [("hi", "reg"), ("lo", "reg"), ("src", "expr")], LowLevelILOperation.LLIL_SET_FLAG: [("dest", "flag"), ("src", "expr")], LowLevelILOperation.LLIL_LOAD: [("src", "expr")], LowLevelILOperation.LLIL_STORE: [("dest", "expr"), ("src", "expr")], LowLevelILOperation.LLIL_PUSH: [("src", "expr")], LowLevelILOperation.LLIL_POP: [], LowLevelILOperation.LLIL_REG: [("src", "reg")], LowLevelILOperation.LLIL_CONST: [("value", "int")], LowLevelILOperation.LLIL_FLAG: [("src", "flag")], LowLevelILOperation.LLIL_FLAG_BIT: [("src", "flag"), ("bit", "int")], LowLevelILOperation.LLIL_ADD: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_ADC: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_SUB: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_SBB: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_AND: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_OR: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_XOR: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_LSL: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_LSR: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_ASR: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_ROL: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_RLC: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_ROR: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_RRC: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_MUL: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_MULU_DP: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_MULS_DP: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_DIVU: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_DIVU_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_DIVS: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_DIVS_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_MODU: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_MODU_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_MODS: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_MODS_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_NEG: [("src", "expr")], LowLevelILOperation.LLIL_NOT: [("src", "expr")], LowLevelILOperation.LLIL_SX: [("src", "expr")], LowLevelILOperation.LLIL_ZX: [("src", "expr")], LowLevelILOperation.LLIL_JUMP: [("dest", "expr")], LowLevelILOperation.LLIL_JUMP_TO: [("dest", "expr"), ("targets", "int_list")], LowLevelILOperation.LLIL_CALL: [("dest", "expr")], LowLevelILOperation.LLIL_RET: [("dest", "expr")], LowLevelILOperation.LLIL_NORET: [], LowLevelILOperation.LLIL_IF: [("condition", "expr"), ("true", "int"), ("false", "int")], LowLevelILOperation.LLIL_GOTO: [("dest", "int")], LowLevelILOperation.LLIL_FLAG_COND: [("condition", "cond")], LowLevelILOperation.LLIL_CMP_E: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_CMP_NE: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_CMP_SLT: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_CMP_ULT: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_CMP_SLE: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_CMP_ULE: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_CMP_SGE: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_CMP_UGE: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_CMP_SGT: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_CMP_UGT: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_TEST_BIT: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_BOOL_TO_INT: [("src", "expr")], LowLevelILOperation.LLIL_SYSCALL: [], LowLevelILOperation.LLIL_BP: [], LowLevelILOperation.LLIL_TRAP: [("value", "int")], LowLevelILOperation.LLIL_UNDEF: [], LowLevelILOperation.LLIL_UNIMPL: [], LowLevelILOperation.LLIL_UNIMPL_MEM: [("src", "expr")] } def __init__(self, func, expr_index, instr_index=None): instr = core.BNGetLowLevelILByIndex(func.handle, expr_index) self.function = func self.expr_index = expr_index self.instr_index = instr_index self.operation = LowLevelILOperation(instr.operation) self.size = instr.size self.address = instr.address self.source_operand = instr.sourceOperand if instr.flags == 0: self.flags = None else: self.flags = func.arch.get_flag_write_type_name(instr.flags) if self.source_operand == 0xffffffff: self.source_operand = None operands = LowLevelILInstruction.ILOperations[instr.operation] self.operands = [] for i in xrange(0, len(operands)): name, operand_type = operands[i] if operand_type == "int": value = instr.operands[i] elif operand_type == "expr": value = LowLevelILInstruction(func, instr.operands[i]) elif operand_type == "reg": if (instr.operands[i] & 0x80000000) != 0: value = instr.operands[i] else: value = func.arch.get_reg_name(instr.operands[i]) elif operand_type == "flag": value = func.arch.get_flag_name(instr.operands[i]) elif operand_type == "cond": value = LowLevelILFlagCondition(instr.operands[i]) elif operand_type == "int_list": count = ctypes.c_ulonglong() operands = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) value = [] for i in xrange(count.value): value.append(operands[i]) core.BNLowLevelILFreeOperandList(operands) self.operands.append(value) self.__dict__[name] = value def __str__(self): tokens = self.tokens if tokens is None: return "invalid" result = "" for token in tokens: result += token.text return result def __repr__(self): return "" % str(self) @property def tokens(self): """LLIL tokens (read-only)""" count = ctypes.c_ulonglong() tokens = ctypes.POINTER(core.BNInstructionTextToken)() if (self.instr_index is not None) and (self.function.source_function is not None): if not core.BNGetLowLevelILInstructionText(self.function.handle, self.function.source_function.handle, self.function.arch.handle, self.instr_index, tokens, count): return None else: if not core.BNGetLowLevelILExprText(self.function.handle, self.function.arch.handle, self.expr_index, tokens, count): return None result = [] for i in xrange(0, count.value): token_type = InstructionTextTokenType(tokens[i].type) text = tokens[i].text value = tokens[i].value size = tokens[i].size operand = tokens[i].operand context = tokens[i].context address = tokens[i].address result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) core.BNFreeInstructionText(tokens, count.value) return result def __setattr__(self, name, value): try: object.__setattr__(self, name, value) except AttributeError: raise AttributeError("attribute '%s' is read only" % name) class LowLevelILExpr(object): """ ``class LowLevelILExpr`` hold the index of IL Expressions. .. note:: This class shouldn't be instantiated directly. Rather the helper members of LowLevelILFunction should be \ used instead. """ def __init__(self, index): self.index = index class LowLevelILFunction(object): """ ``class LowLevelILFunction`` contains the list of LowLevelILExpr objects that make up a function. LowLevelILExpr objects can be added to the LowLevelILFunction by calling ``append`` and passing the result of the various class methods which return LowLevelILExpr objects. LowLevelILFlagCondition values used as parameters in the ``flag_condition`` method. ======================= ========== =============================== LowLevelILFlagCondition Operator Description ======================= ========== =============================== LLFC_E == Equal LLFC_NE != Not equal LLFC_SLT s< Signed less than LLFC_ULT u< Unsigned less than LLFC_SLE s<= Signed less than or equal LLFC_ULE u<= Unsigned less than or equal LLFC_SGE s>= Signed greater than or equal LLFC_UGE u>= Unsigned greater than or equal LLFC_SGT s> Signed greather than LLFC_UGT u> Unsigned greater than LLFC_NEG - Negative LLFC_POS + Positive LLFC_O overflow Overflow LLFC_NO !overflow No overflow ======================= ========== =============================== """ def __init__(self, arch, 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.BNLowLevelILFunction) else: func_handle = None if self.source_function is not None: func_handle = self.source_function.handle self.handle = core.BNCreateLowLevelILFunction(arch.handle, func_handle) def __del__(self): core.BNFreeLowLevelILFunction(self.handle) def __eq__(self, value): if not isinstance(value, LowLevelILFunction): return False return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) def __ne__(self, value): if not isinstance(value, LowLevelILFunction): 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.BNLowLevelILGetCurrentAddress(self.handle) @current_address.setter def current_address(self, value): core.BNLowLevelILSetCurrentAddress(self.handle, value) @property def temp_reg_count(self): """Number of temporary registers (read-only)""" return core.BNGetLowLevelILTemporaryRegisterCount(self.handle) @property def temp_flag_count(self): """Number of temporary flags (read-only)""" return core.BNGetLowLevelILTemporaryFlagCount(self.handle) @property def basic_blocks(self): """list of LowLevelILBasicBlock objects (read-only)""" count = ctypes.c_ulonglong() blocks = core.BNGetLowLevelILBasicBlockList(self.handle, count) result = [] view = None if self.source_function is not None: view = self.source_function.view for i in xrange(0, count.value): result.append(LowLevelILBasicBlock(view, core.BNNewBasicBlockReference(blocks[i]), self)) core.BNFreeBasicBlockList(blocks, count.value) return result 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.BNGetLowLevelILInstructionCount(self.handle)) def __getitem__(self, i): if isinstance(i, slice) or isinstance(i, tuple): raise IndexError("expected integer instruction index") if isinstance(i, LowLevelILExpr): return LowLevelILInstruction(self, i.index) if (i < 0) or (i >= len(self)): raise IndexError("index out of range") return LowLevelILInstruction(self, core.BNGetLowLevelILIndexForInstruction(self.handle, i), i) def __setitem__(self, i, j): raise IndexError("instruction modification not implemented") def __iter__(self): count = ctypes.c_ulonglong() blocks = core.BNGetLowLevelILBasicBlockList(self.handle, count) view = None if self.source_function is not None: view = self.source_function.view try: for i in xrange(0, count.value): yield LowLevelILBasicBlock(view, core.BNNewBasicBlockReference(blocks[i]), self) finally: core.BNFreeBasicBlockList(blocks, count.value) def clear_indirect_branches(self): core.BNLowLevelILClearIndirectBranches(self.handle) def set_indirect_branches(self, branches): branch_list = (core.BNArchitectureAndAddress * len(branches))() for i in xrange(len(branches)): branch_list[i].arch = branches[i][0].handle branch_list[i].address = branches[i][1] core.BNLowLevelILSetIndirectBranches(self.handle, branch_list, len(branches)) def expr(self, operation, a = 0, b = 0, c = 0, d = 0, size = 0, flags = None): if isinstance(operation, str): operation = LowLevelILOperation[operation] elif isinstance(operation, LowLevelILOperation): operation = operation.value if isinstance(flags, str): flags = self.arch.get_flag_write_type_by_name(flags) elif flags is None: flags = 0 return LowLevelILExpr(core.BNLowLevelILAddExpr(self.handle, operation, size, flags, a, b, c, d)) def append(self, expr): """ ``append`` adds the LowLevelILExpr ``expr`` to the current LowLevelILFunction. :param LowLevelILExpr expr: the LowLevelILExpr to add to the current LowLevelILFunction :return: number of LowLevelILExpr in the current function :rtype: int """ return core.BNLowLevelILAddInstruction(self.handle, expr.index) def nop(self): """ ``nop`` no operation, this instruction does nothing :return: The no operation expression :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_NOP) def set_reg(self, size, reg, value, flags = 0): """ ``set_reg`` sets the register ``reg`` of size ``size`` to the expression ``value`` :param int size: size of the register parameter in bytes :param str reg: the register name :param LowLevelILExpr value: an expression to set the register to :param str flags: which flags are set by this operation :return: The expression ``reg = value`` :rtype: LowLevelILExpr """ if isinstance(reg, str): reg = self.arch.regs[reg].index return self.expr(LowLevelILOperation.LLIL_SET_REG, reg, value.index, size = size, flags = flags) def set_reg_split(self, size, hi, lo, value, flags = 0): """ ``set_reg_split`` uses ``hi`` and ``lo`` as a single extended register setting ``hi:lo`` to the expression ``value``. :param int size: size of the register parameter in bytes :param str hi: the high register name :param str lo: the low register name :param LowLevelILExpr value: an expression to set the split regiters to :param str flags: which flags are set by this operation :return: The expression ``hi:lo = value`` :rtype: LowLevelILExpr """ if isinstance(hi, str): hi = self.arch.regs[hi].index if isinstance(lo, str): lo = self.arch.regs[lo].index return self.expr(LowLevelILOperation.LLIL_SET_REG_SPLIT, hi, lo, value.index, size = size, flags = flags) def set_flag(self, flag, value): """ ``set_flag`` sets the flag ``flag`` to the LowLevelILExpr ``value`` :param str flag: the low register name :param LowLevelILExpr value: an expression to set the flag to :return: The expression FLAG.flag = value :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_SET_FLAG, self.arch.get_flag_by_name(flag), value.index) def load(self, size, addr): """ ``laod`` Reads ``size`` bytes from the expression ``addr`` :param int size: number of bytes to read :param LowLevelILExpr addr: the expression to read memory from :return: The expression ``[addr].size`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_LOAD, addr.index, size=size) def store(self, size, addr, value): """ ``store`` Writes ``size`` bytes to expression ``addr`` read from expression ``value`` :param int size: number of bytes to write :param LowLevelILExpr addr: the expression to write to :param LowLevelILExpr value: the expression to be written :return: The expression ``[addr].size = value`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_STORE, addr.index, value.index, size=size) def push(self, size, value): """ ``push`` writes ``size`` bytes from expression ``value`` to the stack, adjusting the stack by ``size``. :param int size: number of bytes to write and adjust the stack by :param LowLevelILExpr value: the expression to write :return: The expression push(value) :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_PUSH, value.index, size=size) def pop(self, size): """ ``pop`` reads ``size`` bytes from the stack, adjusting the stack by ``size``. :param int size: number of bytes to read from the stack :return: The expression ``pop`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_POP, size=size) def reg(self, size, reg): """ ``reg`` returns a register of size ``size`` with name ``name`` :param int size: the size of the register in bytes :param str reg: the name of the register :return: A register expression for the given string :rtype: LowLevelILExpr """ if isinstance(reg, str): reg = self.arch.regs[reg].index return self.expr(LowLevelILOperation.LLIL_REG, reg, size=size) def const(self, size, value): """ ``const`` returns an expression for the constant integer ``value`` with size ``size`` :param int size: the size of the constant in bytes :param int value: integer value of the constant :return: A constant expression of given value and size :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_CONST, value, size=size) def flag(self, reg): """ ``flag`` returns a flag expression for the given flag name. :param str reg: name of the flag expression to retrieve :return: A flag expression of given flag name :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_FLAG, self.arch.get_flag_by_name(reg)) def flag_bit(self, size, reg, bit): """ ``flag_bit`` sets the flag named ``reg`` and size ``size`` to the constant integer value ``bit`` :param int size: the size of the flag :param str reg: flag value :param int bit: integer value to set the bit to :return: A constant expression of given value and size ``FLAG.reg = bit`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_FLAG_BIT, self.arch.get_flag_by_name(reg), bit, size=size) def add(self, size, a, b, flags=None): """ ``add`` adds expression ``a`` to expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression :param str flags: flags to set :return: The expression ``add.{}(a, b)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_ADD, a.index, b.index, size=size, flags=flags) def add_carry(self, size, a, b, flags=None): """ ``add_carry`` adds with carry expression ``a`` to expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression :param str flags: flags to set :return: The expression ``adc.{}(a, b)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_ADC, a.index, b.index, size=size, flags=flags) def sub(self, size, a, b, flags=None): """ ``sub`` subtracts expression ``b`` from expression ``a`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression :param str flags: flags to set :return: The expression ``sub.{}(a, b)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_SUB, a.index, b.index, size=size, flags=flags) def sub_borrow(self, size, a, b, flags=None): """ ``sub_borrow`` subtracts with borrow expression ``b`` from expression ``a`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression :param str flags: flags to set :return: The expression ``sbc.{}(a, b)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_SBB, a.index, b.index, size=size, flags=flags) def and_expr(self, size, a, b, flags=None): """ ``and_expr`` bitwise and's expression ``a`` and expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression :param str flags: optional, flags to set :return: The expression ``and.{}(a, b)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_AND, a.index, b.index, size=size, flags=flags) def or_expr(self, size, a, b, flags=None): """ ``or_expr`` bitwise or's expression ``a`` and expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression :param str flags: optional, flags to set :return: The expression ``or.{}(a, b)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_OR, a.index, b.index, size=size, flags=flags) def xor_expr(self, size, a, b, flags=None): """ ``xor_expr`` xor's expression ``a`` with expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression :param str flags: optional, flags to set :return: The expression ``xor.{}(a, b)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_XOR, a.index, b.index, size=size, flags=flags) def shift_left(self, size, a, b, flags=None): """ ``shift_left`` subtracts with borrow expression ``b`` from expression ``a`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression :param str flags: optional, flags to set :return: The expression ``lsl.{}(a, b)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_LSL, a.index, b.index, size=size, flags=flags) def logical_shift_right(self, size, a, b, flags=None): """ ``logical_shift_right`` shifts logically right expression ``a`` by expression ``b`` potentially setting flags ``flags``and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression :param str flags: optional, flags to set :return: The expression ``lsr.{}(a, b)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_LSR, a.index, b.index, size=size, flags=flags) def arith_shift_right(self, size, a, b, flags=None): """ ``arith_shift_right`` shifts arithmatic right expression ``a`` by expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression :param str flags: optional, flags to set :return: The expression ``asr.{}(a, b)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_ASR, a.index, b.index, size=size, flags=flags) def rotate_left(self, size, a, b, flags=None): """ ``rotate_left`` bitwise rotates left expression ``a`` by expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression :param str flags: optional, flags to set :return: The expression ``rol.{}(a, b)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_ROL, a.index, b.index, size=size, flags=flags) def rotate_left_carry(self, size, a, b, flags=None): """ ``rotate_left_carry`` bitwise rotates left with carry expression ``a`` by expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression :param str flags: optional, flags to set :return: The expression ``rcl.{}(a, b)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_RLC, a.index, b.index, size=size, flags=flags) def rotate_right(self, size, a, b, flags=None): """ ``rotate_right`` bitwise rotates right expression ``a`` by expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression :param str flags: optional, flags to set :return: The expression ``ror.{}(a, b)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_ROR, a.index, b.index, size=size, flags=flags) def rotate_right_carry(self, size, a, b, flags=None): """ ``rotate_right_carry`` bitwise rotates right with carry expression ``a`` by expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression :param str flags: optional, flags to set :return: The expression ``rcr.{}(a, b)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_RRC, a.index, b.index, size=size, flags=flags) def mult(self, size, a, b, flags=None): """ ``mult`` multiplies expression ``a`` by expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression :param str flags: optional, flags to set :return: The expression ``sbc.{}(a, b)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_MUL, a.index, b.index, size=size, flags=flags) def mult_double_prec_signed(self, size, a, b, flags=None): """ ``mult_double_prec_signed`` multiplies signed with double precision expression ``a`` by expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression :param str flags: optional, flags to set :return: The expression ``muls.dp.{}(a, b)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_MULS_DP, a.index, b.index, size=size, flags=flags) def mult_double_prec_unsigned(self, size, a, b, flags=None): """ ``mult_double_prec_unsigned`` multiplies unsigned with double precision expression ``a`` by expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression :param str flags: optional, flags to set :return: The expression ``muls.dp.{}(a, b)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_MULU_DP, a.index, b.index, size=size, flags=flags) def div_signed(self, size, a, b, flags=None): """ ``div_signed`` signed divide expression ``a`` by expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression :param str flags: optional, flags to set :return: The expression ``divs.{}(a, b)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_DIVS, a.index, b.index, size=size, flags=flags) def div_double_prec_signed(self, size, hi, lo, b, flags=None): """ ``div_double_prec_signed`` signed double precision divide using expression ``hi`` and expression ``lo`` as a single double precision register by expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes :param LowLevelILExpr hi: high LHS expression :param LowLevelILExpr lo: low LHS expression :param LowLevelILExpr b: RHS expression :param str flags: optional, flags to set :return: The expression ``divs.dp.{}(hi:lo, b)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_DIVS_DP, hi.index, lo.index, b.index, size=size, flags=flags) def div_unsigned(self, size, a, b, flags=None): """ ``div_unsigned`` unsigned divide expression ``a`` by expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression :param str flags: optional, flags to set :return: The expression ``divs.{}(a, b)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_DIVS, a.index, b.index, size=size, flags=flags) def div_double_prec_unsigned(self, size, hi, lo, b, flags=None): """ ``div_double_prec_unsigned`` unsigned double precision divide using expression ``hi`` and expression ``lo`` as a single double precision register by expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes :param LowLevelILExpr hi: high LHS expression :param LowLevelILExpr lo: low LHS expression :param LowLevelILExpr b: RHS expression :param str flags: optional, flags to set :return: The expression ``divs.dp.{}(hi:lo, b)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_DIVS_DP, hi.index, lo.index, b.index, size=size, flags=flags) def mod_signed(self, size, a, b, flags=None): """ ``mod_signed`` signed modulus expression ``a`` by expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression :param str flags: optional, flags to set :return: The expression ``mods.{}(a, b)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_MODS, a.index, b.index, size=size, flags=flags) def mod_double_prec_signed(self, size, hi, lo, b, flags=None): """ ``mod_double_prec_signed`` signed double precision modulus using expression ``hi`` and expression ``lo`` as a single double precision register by expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes :param LowLevelILExpr hi: high LHS expression :param LowLevelILExpr lo: low LHS expression :param LowLevelILExpr b: RHS expression :param str flags: optional, flags to set :return: The expression ``mods.dp.{}(hi:lo, b)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_MODS_DP, hi.index, lo.index, b.index, size=size, flags=flags) def mod_unsigned(self, size, a, b, flags=None): """ ``mod_unsigned`` unsigned modulus expression ``a`` by expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression :param str flags: optional, flags to set :return: The expression ``modu.{}(a, b)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_MODS, a.index, b.index, size=size, flags=flags) def mod_double_prec_unsigned(self, size, hi, lo, b, flags=None): """ ``mod_double_prec_unsigned`` unsigned double precision modulus using expression ``hi`` and expression ``lo`` as a single double precision register by expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. :param int size: the size of the result in bytes :param LowLevelILExpr hi: high LHS expression :param LowLevelILExpr lo: low LHS expression :param LowLevelILExpr b: RHS expression :param str flags: optional, flags to set :return: The expression ``modu.dp.{}(hi:lo, b)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_MODS_DP, hi.index, lo.index, b.index, size=size, flags=flags) def neg_expr(self, size, value, flags=None): """ ``neg_expr`` two's complement sign negation of expression ``value`` of size ``size`` potentially setting flags :param int size: the size of the result in bytes :param LowLevelILExpr value: the expression to negate :param str flags: optional, flags to set :return: The expression ``neg.{}(value)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_NEG, value.index, size=size, flags=flags) def not_expr(self, size, value, flags=None): """ ``not_expr`` bitwise inverse of expression ``value`` of size ``size`` potentially setting flags :param int size: the size of the result in bytes :param LowLevelILExpr value: the expression to bitwise invert :param str flags: optional, flags to set :return: The expression ``not.{}(value)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_NOT, value.index, size=size, flags=flags) def sign_extend(self, size, value, flags=None): """ ``sign_extend`` two's complement sign-extends the expression in ``value`` to ``size`` bytes :param int size: the size of the result in bytes :param LowLevelILExpr value: the expression to sign extn :param str flags: optional, flags to set :return: The expression ``sx.(value)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_SX, value.index, size=size, flags=flags) def zero_extend(self, size, value): """ ``zero_extend`` zero-extends the expression in ``value`` to ``size`` bytes :param int size: the size of the result in bytes :param LowLevelILExpr value: the expression to zero extend :return: The expression ``sx.(value)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_ZX, value.index, size=size) def jump(self, dest): """ ``jump`` returns an expression which jumps (branches) to the expression ``dest`` :param LowLevelILExpr dest: the expression to jump to :return: The expression ``jump(dest)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_JUMP, dest.index) def call(self, dest): """ ``call`` returns an expression which first pushes the address of the next instruction onto the stack then jumps (branches) to the expression ``dest`` :param LowLevelILExpr dest: the expression to call :return: The expression ``call(dest)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_CALL, dest.index) def ret(self, dest): """ ``ret`` returns an expression which jumps (branches) to the expression ``dest``. ``ret`` is a special alias for jump that makes the disassembler top disassembling. :param LowLevelILExpr dest: the expression to jump to :return: The expression ``jump(dest)`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_RET, dest.index) def no_ret(self): """ ``no_ret`` returns an expression halts disassembly :return: The expression ``noreturn`` :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_NORET) def flag_condition(self, cond): """ ``flag_condition`` returns a flag_condition expression for the given LowLevelILFlagCondition :param LowLevelILFlagCondition cond: Flag condition expression to retrieve :return: A flag_condition expression :rtype: LowLevelILExpr """ if isinstance(cond, str): cond = LowLevelILFlagCondition[cond] elif isinstance(cond, LowLevelILFlagCondition): cond = cond.value return self.expr(LowLevelILOperation.LLIL_FLAG_COND, cond) def compare_equal(self, size, a, b): """ ``compare_equal`` returns comparison expression of size ``size`` checking if expression ``a`` is equal to expression ``b`` :param int size: size in bytes :param LowLevelILExpr a: LHS of comparison :param LowLevelILExpr b: RHS of comparison :return: a comparison expression. :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_CMP_E, a.index, b.index, size = size) def compare_not_equal(self, size, a, b): """ ``compare_not_equal`` returns comparison expression of size ``size`` checking if expression ``a`` is not equal to expression ``b`` :param int size: size in bytes :param LowLevelILExpr a: LHS of comparison :param LowLevelILExpr b: RHS of comparison :return: a comparison expression. :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_CMP_NE, a.index, b.index, size = size) def compare_signed_less_than(self, size, a, b): """ ``compare_signed_less_than`` returns comparison expression of size ``size`` checking if expression ``a`` is signed less than expression ``b`` :param int size: size in bytes :param LowLevelILExpr a: LHS of comparison :param LowLevelILExpr b: RHS of comparison :return: a comparison expression. :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_CMP_SLT, a.index, b.index, size = size) def compare_unsigned_less_than(self, size, a, b): """ ``compare_unsigned_less_than`` returns comparison expression of size ``size`` checking if expression ``a`` is unsigned less than expression ``b`` :param int size: size in bytes :param LowLevelILExpr a: LHS of comparison :param LowLevelILExpr b: RHS of comparison :return: a comparison expression. :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_CMP_ULT, a.index, b.index, size = size) def compare_signed_less_equal(self, size, a, b): """ ``compare_signed_less_equal`` returns comparison expression of size ``size`` checking if expression ``a`` is signed less than or equal to expression ``b`` :param int size: size in bytes :param LowLevelILExpr a: LHS of comparison :param LowLevelILExpr b: RHS of comparison :return: a comparison expression. :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_CMP_SLE, a.index, b.index, size = size) def compare_unsigned_less_equal(self, size, a, b): """ ``compare_unsigned_less_equal`` returns comparison expression of size ``size`` checking if expression ``a`` is unsigned less than or equal to expression ``b`` :param int size: size in bytes :param LowLevelILExpr a: LHS of comparison :param LowLevelILExpr b: RHS of comparison :return: a comparison expression. :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_CMP_ULE, a.index, b.index, size = size) def compare_signed_greater_equal(self, size, a, b): """ ``compare_signed_greater_equal`` returns comparison expression of size ``size`` checking if expression ``a`` is signed greater than or equal toexpression ``b`` :param int size: size in bytes :param LowLevelILExpr a: LHS of comparison :param LowLevelILExpr b: RHS of comparison :return: a comparison expression. :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_CMP_SGE, a.index, b.index, size = size) def compare_unsigned_greater_equal(self, size, a, b): """ ``compare_unsigned_greater_equal`` returns comparison expression of size ``size`` checking if expression ``a`` is unsigned greater than or equal to expression ``b`` :param int size: size in bytes :param LowLevelILExpr a: LHS of comparison :param LowLevelILExpr b: RHS of comparison :return: a comparison expression. :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_CMP_UGE, a.index, b.index, size = size) def compare_signed_greater_than(self, size, a, b): """ ``compare_signed_greater_than`` returns comparison expression of size ``size`` checking if expression ``a`` is signed greater than or equal to expression ``b`` :param int size: size in bytes :param LowLevelILExpr a: LHS of comparison :param LowLevelILExpr b: RHS of comparison :return: a comparison expression. :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_CMP_SGT, a.index, b.index, size = size) def compare_unsigned_greater_than(self, size, a, b): """ ``compare_unsigned_greater_than`` returns comparison expression of size ``size`` checking if expression ``a`` is unsigned greater than or equal to expression ``b`` :param int size: size in bytes :param LowLevelILExpr a: LHS of comparison :param LowLevelILExpr b: RHS of comparison :return: a comparison expression. :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_CMP_UGT, a.index, b.index, size = size) def test_bit(self, size, a, b): return self.expr(LowLevelILOperation.LLIL_TEST_BIT, a.index, b.index, size = size) def system_call(self): """ ``system_call`` return a system call expression. :return: a system call expression. :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_SYSCALL) def breakpoint(self): """ ``breakpoint`` returns a processor breakpoint expression. :return: a breakpoint expression. :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_BP) def trap(self, value): """ ``trap`` returns a processor trap (interrupt) expression of the given integer ``value``. :param int value: trap (interrupt) number :return: a trap expression. :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_TRAP, value) def undefined(self): """ ``undefined`` returns the undefined expression. This should be used for instructions which perform functions but aren't important for dataflow or partial emulation purposes. :return: the unimplemented expression. :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_UNDEF) def unimplemented(self): """ ``unimplemented`` returns the unimplemented expression. This should be used for all instructions which aren't implemented. :return: the unimplemented expression. :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_UNIMPL) def unimplemented_memory_ref(self, size, addr): """ ``unimplemented_memory_ref`` a memory reference to expression ``addr`` of size ``size`` with unimplemented operation. :param int size: size in bytes of the memory reference :param LowLevelILExpr addr: expression to reference memory :return: the unimplemented memory reference expression. :rtype: LowLevelILExpr """ return self.expr(LowLevelILOperation.LLIL_UNIMPL_MEM, addr.index, size = size) def goto(self, label): """ ``goto`` returns a goto expression which jumps to the provided LowLevelILLabel. :param LowLevelILLabel label: Label to jump to :return: the LowLevelILExpr that jumps to the provided label :rtype: LowLevelILExpr """ return LowLevelILExpr(core.BNLowLevelILGoto(self.handle, label.handle)) def if_expr(self, operand, t, f): """ ``if_expr`` returns the ``if`` expression which depending on condition ``operand`` jumps to the LowLevelILLabel ``t`` when the condition expression ``operand`` is non-zero and ``f`` when it's zero. :param LowLevelILExpr operand: comparison expression to evaluate. :param LowLevelILLabel t: Label for the true branch :param LowLevelILLabel f: Label for the false branch :return: the LowLevelILExpr for the if expression :rtype: LowLevelILExpr """ return LowLevelILExpr(core.BNLowLevelILIf(self.handle, operand.index, t.handle, f.handle)) def mark_label(self, label): """ ``mark_label`` assigns a LowLevelILLabel to the current IL address. :param LowLevelILLabel label: :rtype: None """ core.BNLowLevelILMarkLabel(self.handle, label.handle) def add_label_list(self, labels): """ ``add_label_list`` returns a label list expression for the given list of LowLevelILLabel objects. :param list(LowLevelILLabel) lables: the list of LowLevelILLabel to get a label list expression from :return: the label list expression :rtype: LowLevelILExpr """ label_list = (ctypes.POINTER(core.BNLowLevelILLabel) * len(labels))() for i in xrange(len(labels)): label_list[i] = labels[i].handle return LowLevelILExpr(core.BNLowLevelILAddLabelList(self.handle, label_list, len(labels))) 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: LowLevelILExpr """ operand_list = (ctypes.c_ulonglong * len(operands))() for i in xrange(len(operands)): operand_list[i] = operands[i] return LowLevelILExpr(core.BNLowLevelILAddOperandList(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 LowLevelILExpr expr: :return: returns the expression ``expr`` unmodified :rtype: LowLevelILExpr """ core.BNLowLevelILSetExprSourceOperand(self.handle, expr.index, n) return expr def finalize(self): """ ``finalize`` ends the function and computes the list of basic blocks. :rtype: None """ core.BNFinalizeLowLevelILFunction(self.handle) def add_label_for_address(self, arch, addr): """ ``add_label_for_address`` adds a low-level IL label for the given architecture ``arch`` at the given virtual address ``addr`` :param Architecture arch: Architecture to add labels for :param int addr: the IL address to add a label at """ if arch is not None: arch = arch.handle core.BNAddLowLevelILLabelForAddress(self.handle, arch, addr) def get_label_for_address(self, arch, addr): """ ``get_label_for_address`` returns the LowLevelILLabel for the given Architecture ``arch`` and IL address ``addr``. :param Architecture arch: :param int addr: IL Address label to retrieve :return: the LowLevelILLabel for the given IL address :rtype: LowLevelILLabel """ if arch is not None: arch = arch.handle label = core.BNGetLowLevelILLabelForAddress(self.handle, arch, addr) if label is None: return None return LowLevelILLabel(label) class LowLevelILBasicBlock(basicblock.BasicBlock): def __init__(self, view, handle, owner): super(LowLevelILBasicBlock, self).__init__(view, handle) self.il_function = owner def __iter__(self): for idx in xrange(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 LLIL_TEMP(n): return n | 0x80000000 def LLIL_REG_IS_TEMP(n): return (n & 0x80000000) != 0 def LLIL_GET_TEMP_REG_INDEX(n): return n & 0x7fffffff