Source code for binaryninja.mediumlevelil

# 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.importctypesimportstruct# Binary Ninja componentsimportbinaryninjafrombinaryninjaimport_binaryninjacoreascorefrombinaryninja.enumsimportMediumLevelILOperation,InstructionTextTokenType,ILBranchDependencefrombinaryninjaimportbasicblock#required for MediumLevelILBasicBlock argumentfrombinaryninjaimportfunctionfrombinaryninjaimporttypesfrombinaryninjaimportlowlevelil# 2-3 compatibilityfrombinaryninjaimportrange

def__str__(self):tokens=self.tokensiftokensisNone:return"invalid"result=""fortokenintokens:result+=token.textreturnresultdef__repr__(self):return"<il: %s>"%str(self)@propertydeftokens(self):"""MLIL tokens (read-only)"""count=ctypes.c_ulonglong()tokens=ctypes.POINTER(core.BNInstructionTextToken)()if((self.instr_indexisnotNone)and(self.function.source_functionisnotNone)and(self.expr_index==core.BNGetMediumLevelILIndexForInstruction(self.function.handle,self.instr_index))):ifnotcore.BNGetMediumLevelILInstructionText(self.function.handle,self.function.source_function.handle,self.function.arch.handle,self.instr_index,tokens,count):returnNoneelse:ifnotcore.BNGetMediumLevelILExprText(self.function.handle,self.function.arch.handle,self.expr_index,tokens,count):returnNoneresult=binaryninja.function.InstructionTextToken.get_instruction_lines(tokens,count.value)core.BNFreeInstructionText(tokens,count.value)returnresult@propertydefil_basic_block(self):"""IL basic block object containing this expression (read-only) (only available on finalized functions)"""returnMediumLevelILBasicBlock(self.function.source_function.view,core.BNGetMediumLevelILBasicBlockForInstruction(self.function.handle,self.instr_index),self.function)@propertydefssa_form(self):"""SSA form of expression (read-only)"""returnMediumLevelILInstruction(self.function.ssa_form,core.BNGetMediumLevelILSSAExprIndex(self.function.handle,self.expr_index))@propertydefnon_ssa_form(self):"""Non-SSA form of expression (read-only)"""returnMediumLevelILInstruction(self.function.non_ssa_form,core.BNGetMediumLevelILNonSSAExprIndex(self.function.handle,self.expr_index))@propertydefvalue(self):"""Value of expression if constant or a known value (read-only)"""value=core.BNGetMediumLevelILExprValue(self.function.handle,self.expr_index)result=function.RegisterValue(self.function.arch,value)returnresult@propertydefpossible_values(self):"""Possible values of expression using path-sensitive static data flow analysis (read-only)"""value=core.BNGetMediumLevelILPossibleExprValues(self.function.handle,self.expr_index)result=function.PossibleValueSet(self.function.arch,value)core.BNFreePossibleValueSet(value)returnresult@propertydefbranch_dependence(self):"""Set of branching instructions that must take the true or false path to reach this instruction"""count=ctypes.c_ulonglong()deps=core.BNGetAllMediumLevelILBranchDependence(self.function.handle,self.instr_index,count)result={}foriinrange(0,count.value):result[deps[i].branch]=ILBranchDependence(deps[i].dependence)core.BNFreeILBranchDependenceList(deps)returnresult@propertydeflow_level_il(self):"""Low level IL form of this expression"""expr=self.function.get_low_level_il_expr_index(self.expr_index)ifexprisNone:returnNonereturnlowlevelil.LowLevelILInstruction(self.function.low_level_il.ssa_form,expr)@propertydefllil(self):"""Alias for low_level_il"""returnself.low_level_il@propertydefssa_memory_version(self):"""Version of active memory contents in SSA form for this instruction"""returncore.BNGetMediumLevelILSSAMemoryVersionAtILInstruction(self.function.handle,self.instr_index)@propertydefprefix_operands(self):"""All operands in the expression tree in prefix order"""result=[MediumLevelILOperationAndSize(self.operation,self.size)]foroperandinself.operands:ifisinstance(operand,MediumLevelILInstruction):result+=operand.prefix_operandselse:result.append(operand)returnresult@propertydefpostfix_operands(self):"""All operands in the expression tree in postfix order"""result=[]foroperandinself.operands:ifisinstance(operand,MediumLevelILInstruction):result+=operand.postfix_operandselse:result.append(operand)result.append(MediumLevelILOperationAndSize(self.operation,self.size))returnresult@propertydefvars_written(self):"""List of variables written by instruction"""ifself.operationin[MediumLevelILOperation.MLIL_SET_VAR,MediumLevelILOperation.MLIL_SET_VAR_FIELD,MediumLevelILOperation.MLIL_SET_VAR_SSA,MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD,MediumLevelILOperation.MLIL_SET_VAR_ALIASED,MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD,MediumLevelILOperation.MLIL_VAR_PHI]:return[self.dest]elifself.operationin[MediumLevelILOperation.MLIL_SET_VAR_SPLIT,MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA]:return[self.high,self.low]elifself.operationin[MediumLevelILOperation.MLIL_CALL,MediumLevelILOperation.MLIL_SYSCALL,MediumLevelILOperation.MLIL_TAILCALL]:returnself.outputelifself.operationin[MediumLevelILOperation.MLIL_CALL_UNTYPED,MediumLevelILOperation.MLIL_SYSCALL_UNTYPED,MediumLevelILOperation.MLIL_TAILCALL_UNTYPED,MediumLevelILOperation.MLIL_CALL_SSA,MediumLevelILOperation.MLIL_CALL_UNTYPED_SSA,MediumLevelILOperation.MLIL_SYSCALL_SSA,MediumLevelILOperation.MLIL_SYSCALL_UNTYPED_SSA,MediumLevelILOperation.MLIL_TAILCALL_SSA,MediumLevelILOperation.MLIL_TAILCALL_UNTYPED_SSA]:returnself.output.vars_writtenelifself.operationin[MediumLevelILOperation.MLIL_CALL_OUTPUT,MediumLevelILOperation.MLIL_CALL_OUTPUT_SSA]:returnself.destreturn[]@propertydefvars_read(self):"""List of variables read by instruction"""ifself.operationin[MediumLevelILOperation.MLIL_SET_VAR,MediumLevelILOperation.MLIL_SET_VAR_FIELD,MediumLevelILOperation.MLIL_SET_VAR_SPLIT,MediumLevelILOperation.MLIL_SET_VAR_SSA,MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA,MediumLevelILOperation.MLIL_SET_VAR_ALIASED]:returnself.src.vars_readelifself.operationin[MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD,MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD]:return[self.prev]+self.src.vars_readelifself.operationin[MediumLevelILOperation.MLIL_CALL,MediumLevelILOperation.MLIL_SYSCALL,MediumLevelILOperation.MLIL_TAILCALL,MediumLevelILOperation.MLIL_CALL_SSA,MediumLevelILOperation.MLIL_SYSCALL_SSA,MediumLevelILOperation.MLIL_TAILCALL_SSA]:result=[]forparaminself.params:result+=param.vars_readreturnresultelifself.operationin[MediumLevelILOperation.MLIL_CALL_UNTYPED,MediumLevelILOperation.MLIL_SYSCALL_UNTYPED,MediumLevelILOperation.MLIL_TAILCALL_UNTYPED,MediumLevelILOperation.MLIL_CALL_UNTYPED_SSA,MediumLevelILOperation.MLIL_SYSCALL_UNTYPED_SSA,MediumLevelILOperation.MLIL_TAILCALL_UNTYPED_SSA]:returnself.params.vars_readelifself.operationin[MediumLevelILOperation.MLIL_CALL_PARAM,MediumLevelILOperation.MLIL_CALL_PARAM_SSA,MediumLevelILOperation.MLIL_VAR_PHI]:returnself.srcelifself.operationin[MediumLevelILOperation.MLIL_CALL_OUTPUT,MediumLevelILOperation.MLIL_CALL_OUTPUT_SSA]:return[]result=[]foroperandinself.operands:if(isinstance(operand,function.Variable))or(isinstance(operand,SSAVariable)):result.append(operand)elifisinstance(operand,MediumLevelILInstruction):result+=operand.vars_readreturnresult@propertydefexpr_type(self):"""Type of expression"""result=core.BNGetMediumLevelILExprType(self.function.handle,self.expr_index)ifresult.type:platform=Noneifself.function.source_function:platform=self.function.source_function.platformreturntypes.Type(result.type,platform=platform,confidence=result.confidence)returnNone

[docs]classMediumLevelILExpr(object):""" ``class MediumLevelILExpr`` hold the index of IL Expressions. .. note:: This class shouldn't be instantiated directly. Rather the helper members of MediumLevelILFunction should be \ used instead. """

[docs]classMediumLevelILFunction(object):""" ``class MediumLevelILFunction`` contains the list of MediumLevelILExpr objects that make up a binaryninja.function. MediumLevelILExpr objects can be added to the MediumLevelILFunction by calling ``append`` and passing the result of the various class methods which return MediumLevelILExpr objects. """

[docs]def__init__(self,arch=None,handle=None,source_func=None):self.arch=archself.source_function=source_funcifhandleisnotNone:self.handle=core.handle_of_type(handle,core.BNMediumLevelILFunction)ifself.source_functionisNone:self.source_function=binaryninja.function.Function(handle=core.BNGetMediumLevelILOwnerFunction(self.handle))ifself.archisNone:self.arch=self.source_function.archelse:ifself.source_functionisNone:self.handle=NoneraiseValueError("IL functions must be created with an associated function")ifself.archisNone:self.arch=self.source_function.archfunc_handle=self.source_function.handleself.handle=core.BNCreateMediumLevelILFunction(arch.handle,func_handle)

@propertydefbasic_blocks(self):"""list of MediumLevelILBasicBlock objects (read-only)"""count=ctypes.c_ulonglong()blocks=core.BNGetMediumLevelILBasicBlockList(self.handle,count)result=[]view=Noneifself.source_functionisnotNone:view=self.source_function.viewforiinrange(0,count.value):result.append(MediumLevelILBasicBlock(view,core.BNNewBasicBlockReference(blocks[i]),self))core.BNFreeBasicBlockList(blocks,count.value)returnresult@propertydefinstructions(self):"""A generator of mlil instructions of the current function"""forblockinself.basic_blocks:foriinblock:yieldi@propertydefssa_form(self):"""Medium level IL in SSA form (read-only)"""result=core.BNGetMediumLevelILSSAForm(self.handle)ifnotresult:returnNonereturnMediumLevelILFunction(self.arch,result,self.source_function)@propertydefnon_ssa_form(self):"""Medium level IL in non-SSA (default) form (read-only)"""result=core.BNGetMediumLevelILNonSSAForm(self.handle)ifnotresult:returnNonereturnMediumLevelILFunction(self.arch,result,self.source_function)@propertydeflow_level_il(self):"""Low level IL for this function"""result=core.BNGetLowLevelILForMediumLevelIL(self.handle)ifnotresult:returnNonereturnlowlevelil.LowLevelILFunction(self.arch,result,self.source_function)@propertydefllil(self):"""Alias for low_level_il"""returnself.low_level_ildef__setattr__(self,name,value):try:object.__setattr__(self,name,value)exceptAttributeError:raiseAttributeError("attribute '%s' is read only"%name)def__len__(self):returnint(core.BNGetMediumLevelILInstructionCount(self.handle))def__getitem__(self,i):ifisinstance(i,slice)orisinstance(i,tuple):raiseIndexError("expected integer instruction index")ifisinstance(i,MediumLevelILExpr):returnMediumLevelILInstruction(self,i.index)if(i<0)or(i>=len(self)):raiseIndexError("index out of range")returnMediumLevelILInstruction(self,core.BNGetMediumLevelILIndexForInstruction(self.handle,i),i)def__setitem__(self,i,j):raiseIndexError("instruction modification not implemented")def__iter__(self):count=ctypes.c_ulonglong()blocks=core.BNGetMediumLevelILBasicBlockList(self.handle,count)view=Noneifself.source_functionisnotNone:view=self.source_function.viewtry:foriinrange(0,count.value):yieldMediumLevelILBasicBlock(view,core.BNNewBasicBlockReference(blocks[i]),self)finally:core.BNFreeBasicBlockList(blocks,count.value)

[docs]defappend(self,expr):""" ``append`` adds the MediumLevelILExpr ``expr`` to the current MediumLevelILFunction. :param MediumLevelILExpr expr: the MediumLevelILExpr to add to the current MediumLevelILFunction :return: number of MediumLevelILExpr in the current function :rtype: int """returncore.BNMediumLevelILAddInstruction(self.handle,expr.index)

[docs]defgoto(self,label):""" ``goto`` returns a goto expression which jumps to the provided MediumLevelILLabel. :param MediumLevelILLabel label: Label to jump to :return: the MediumLevelILExpr that jumps to the provided label :rtype: MediumLevelILExpr """returnMediumLevelILExpr(core.BNMediumLevelILGoto(self.handle,label.handle))

[docs]defif_expr(self,operand,t,f):""" ``if_expr`` returns the ``if`` expression which depending on condition ``operand`` jumps to the MediumLevelILLabel ``t`` when the condition expression ``operand`` is non-zero and ``f`` when it's zero. :param MediumLevelILExpr operand: comparison expression to evaluate. :param MediumLevelILLabel t: Label for the true branch :param MediumLevelILLabel f: Label for the false branch :return: the MediumLevelILExpr for the if expression :rtype: MediumLevelILExpr """returnMediumLevelILExpr(core.BNMediumLevelILIf(self.handle,operand.index,t.handle,f.handle))

[docs]defadd_label_list(self,labels):""" ``add_label_list`` returns a label list expression for the given list of MediumLevelILLabel objects. :param list(MediumLevelILLabel) labels: the list of MediumLevelILLabel to get a label list expression from :return: the label list expression :rtype: MediumLevelILExpr """label_list=(ctypes.POINTER(core.BNMediumLevelILLabel)*len(labels))()foriinrange(len(labels)):label_list[i]=labels[i].handlereturnMediumLevelILExpr(core.BNMediumLevelILAddLabelList(self.handle,label_list,len(labels)))

[docs]defis_ssa_var_live(self,ssa_var):""" ``is_ssa_var_live`` determines if ``ssa_var`` is live at any point in the function :param SSAVariable ssa_var: the SSA variable to query :return: whether the variable is live at any point in the function :rtype: bool """var_data=core.BNVariable()var_data.type=ssa_var.var.source_typevar_data.index=ssa_var.var.indexvar_data.storage=ssa_var.var.storagereturncore.BNIsMediumLevelILSSAVarLive(self.handle,var_data,ssa_var.version)

def__iter__(self):foridxinrange(self.start,self.end):yieldself.il_function[idx]def__getitem__(self,idx):size=self.end-self.startifidx>sizeoridx<-size:raiseIndexError("list index is out of range")ifidx>=0:returnself.il_function[idx+self.start]else:returnself.il_function[self.end+idx]def_create_instance(self,handle,view):"""Internal method by super to instantiate child instances"""returnMediumLevelILBasicBlock(view,handle,self.il_function)def__hash__(self):returnhash((self.start,self.end,self.il_function))