python binding can't add label in mlil
What is the feature you'd like to have? add python workflow api to add label in mlil like llil.add_label_for_address
Is your feature request related to a problem? when solve indirect branch jump, its suppose to use mlil data flow analyze to calculate possible dest and replace 'jump' MLIL to 'if' MLIL , so a easy way to create label in mlil is necessary
Are any alternative solutions acceptable? i have not found yet
Additional Information: my code here ,can't work and i can't find a solution
import json
from binaryninja import(
Workflow,
AnalysisContext,
Variable,
Activity,
MediumLevelILFunction,
MediumLevelILConstPtr,
MediumLevelILConstData,
MediumLevelILConst,
MediumLevelILLoad,
MediumLevelILVar,
MediumLevelILAdd,
MediumLevelILSub,
MediumLevelILXor,
MediumLevelILMul,
MediumLevelILJump,
PossibleValueSet,
RegisterValueType,
MediumLevelILLabel,
LowLevelILLabel,
)
mlil_const=MediumLevelILConstPtr | MediumLevelILConstData | MediumLevelILConst
def search_var_def(var:Variable,mlil:MediumLevelILFunction,cond):
var_def=mlil.get_var_definitions(var)
# print(hex(var_def[0].address))
if len(var_def)==1 and isinstance(var_def[0].src,mlil_const):
print("def==1",var_def)
return
if (len(var_def)==2):
# print(var_def)
if isinstance(var_def[0].src,mlil_const) and isinstance(var_def[1].src,mlil_const):
if cond["value"]==None:
for key in var_def[0].branch_dependence.keys():
cond["value"]=mlil[key].condition.expr_index
break
return {var:{"t":var_def[0].src.value.value,"f":var_def[1].src.value.value}}
return
if len(var_def)>2:
print("def>2",var_def)
return None
var_def=var_def[0]
var_def_src=var_def.src
# print(var_def_src)
if isinstance(var_def_src,mlil_const):
print("const:",var_def_src)
return
if isinstance(var_def_src,MediumLevelILLoad):
# print("load:",var_def_src.operands)
table=var_def.get_possible_reg_values_after(var_def.dest.storage)
# print(table.mapping)
var_def_token=list(var_def_src.traverse(lambda x: x))
for token in var_def_token:
if isinstance(token,MediumLevelILVar):
mp=search_var_def(token.var,mlil,cond)
if mp==None:
return
# print(table,var_def,var_def.dest.storage)
if (table.type==RegisterValueType.UndeterminedValue):
print("undetermined table,check data section")
return
# print(mp,table.mapping)
try:
return {var:{"t":table.mapping[mp[token.var]["t"]],"f":table.mapping[mp[token.var]["f"]]}}
except KeyError:
return {var:{"t":table.mapping[mp[token.var]["t"]//8],"f":table.mapping[mp[token.var]["f"]//8]}}
return
Lvalue=search_var_def(var_def_src.left.var,mlil,cond)
Rvalue=search_var_def(var_def_src.right.var,mlil,cond)
tmp=Lvalue|Rvalue
if isinstance(var_def_src,MediumLevelILAdd):
Tvalue=tmp[var_def_src.left.var]["t"]+tmp[var_def_src.right.var]["t"]
Fvalue=tmp[var_def_src.left.var]["f"]+tmp[var_def_src.right.var]["f"]
return {var:{"t":Tvalue,"f":Fvalue}}
elif isinstance(var_def_src,MediumLevelILSub):
Tvalue=tmp[var_def_src.left.var]["t"]-tmp[var_def_src.right.var]["t"]
Fvalue=tmp[var_def_src.left.var]["f"]-tmp[var_def_src.right.var]["f"]
return {var:{"t":Tvalue,"f":Fvalue}}
elif isinstance(var_def_src,MediumLevelILXor):
Tvalue=tmp[var_def_src.left.var]["t"]^tmp[var_def_src.right.var]["t"]
Fvalue=tmp[var_def_src.left.var]["f"]^tmp[var_def_src.right.var]["f"]
return {var:{"t":Tvalue,"f":Fvalue}}
elif isinstance(var_def_src,MediumLevelILMul):
Tvalue=tmp[var_def_src.left.var]["t"]*tmp[var_def_src.right.var]["t"]
Fvalue=tmp[var_def_src.left.var]["f"]*tmp[var_def_src.right.var]["f"]
return {var:{"t":Tvalue,"f":Fvalue}}
else:
print("Unsupported operation:",var_def_src)
return None
def handle_two_direct_indirect_jump(ctx:AnalysisContext):
bv=ctx.function.view
mlil=ctx.function.mlil
llil=ctx.function.llil
update=False
for instr in mlil.instructions:
if isinstance(instr,MediumLevelILJump) and isinstance(instr.dest,MediumLevelILVar):
# print(instr.get_possible_reg_values(instr.dest.var.storage))
if instr.get_possible_reg_values(instr.dest.var.storage).type==RegisterValueType.UndeterminedValue:
# print(instr.dest.var)
cond={"value":None}
res=search_var_def(instr.dest.var, mlil,cond)
# print(cond)
if res==None or cond["value"]==None:
raise RuntimeError("calc fail,check {}".format(hex(instr.address)))
ctx.function.set_user_indirect_branches(instr.address, [(ctx.function.arch,res[instr.dest.var]["t"]),(ctx.function.arch,res[instr.dest.var]["f"])],ctx.function.arch)
print(hex(res[instr.dest.var]["t"]),llil.get_instruction_start(res[instr.dest.var]["t"]))
print(hex(res[instr.dest.var]["f"]),llil.get_instruction_start(res[instr.dest.var]["f"]))
t_instr=llil[llil.get_instruction_start(res[instr.dest.var]["t"])].mapped_medium_level_il
f_instr=llil[llil.get_instruction_start(res[instr.dest.var]["f"])].mapped_medium_level_il
print(hex(res[instr.dest.var]["t"]),t_instr)
print(hex(res[instr.dest.var]["f"]),f_instr)
t_label=mlil.get_label_for_source_instruction(t_instr.instr_index)
f_label=mlil.get_label_for_source_instruction(f_instr.instr_index)
print("set indirect jump at {} to {}:{},{}:{}".format(hex(instr.address),hex(res[instr.dest.var]["t"]),t_label,hex(res[instr.dest.var]["f"]),f_label))
if_instr=mlil.if_expr(cond["value"],t_label,f_label,instr.source_location)
mlil.replace_expr(instr.expr_index,if_instr)
mlil.append(if_instr)
update=True
if update:
mlil.finalize()
mlil.generate_ssa_form()
wf=Workflow("").clone("satori.function.deobf")
wf.register_activity(Activity(configuration=json.dumps({
"name":"satori.function.handle_two_direct_indirect_jump.activity",
"title":"handle_two_direct_indirect_jump",
"description":"handle_two_direct_indirect_jump",
"eligibility":{
"auto":{
"default":True
}
}
}),action=lambda context: handle_two_direct_indirect_jump(context)))
wf.insert("core.function.generateHighLevelIL",["satori.function.handle_two_direct_indirect_jump.activity"])
wf.register()
get_label_for_source_instruction can only be used when doing rewriting via a "copy transformation". See Adding Instructions and Replacing Multiple Instructions (Copy Transformation) and Using GOTO/IF Instructions and IL Labels for more information on how to work with labels when rewriting IL.