diff options
Diffstat (limited to 'src/miasm/analysis/disasm_cb.py')
| -rw-r--r-- | src/miasm/analysis/disasm_cb.py | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/src/miasm/analysis/disasm_cb.py b/src/miasm/analysis/disasm_cb.py new file mode 100644 index 00000000..f180f0a2 --- /dev/null +++ b/src/miasm/analysis/disasm_cb.py @@ -0,0 +1,127 @@ +#-*- coding:utf-8 -*- + +from __future__ import print_function + +from future.utils import viewvalues + +from miasm.expression.expression import ExprInt, ExprId, ExprMem, match_expr +from miasm.expression.simplifications import expr_simp +from miasm.core.asmblock import AsmConstraintNext, AsmConstraintTo +from miasm.core.locationdb import LocationDB +from miasm.core.utils import upck32 + + +def get_lifter_model_call(arch, attrib): + arch = arch.name, attrib + if arch == ("arm", "arm"): + from miasm.arch.arm.lifter_model_call import LifterModelCallArmlBase as lifter_model_call + elif arch == ("x86", 32): + from miasm.arch.x86.lifter_model_call import LifterModelCall_x86_32 as lifter_model_call + elif arch == ("x86", 64): + from miasm.arch.x86.lifter_model_call import LifterModelCall_x86_64 as lifter_model_call + else: + raise ValueError('unknown architecture: %s' % arch.name) + return lifter_model_call + + +def arm_guess_subcall(dis_engine, cur_block, offsets_to_dis): + arch = dis_engine.arch + loc_db = dis_engine.loc_db + lifter_model_call = get_lifter_model_call(arch, dis_engine.attrib) + + lifter = lifter_model_call(loc_db) + ircfg = lifter_model_call.new_ircfg() + print('###') + print(cur_block) + lifter.add_asmblock_to_ircfg(cur_block, ircfg) + + to_add = set() + for irblock in viewvalues(ircfg.blocks): + pc_val = None + lr_val = None + for exprs in irblock: + for e in exprs: + if e.dst == lifter.pc: + pc_val = e.src + if e.dst == arch.regs.LR: + lr_val = e.src + if pc_val is None or lr_val is None: + continue + if not isinstance(lr_val, ExprInt): + continue + + l = cur_block.lines[-1] + if lr_val.arg != l.offset + l.l: + continue + l = loc_db.get_or_create_offset_location(int(lr_val)) + c = AsmConstraintNext(l) + + to_add.add(c) + offsets_to_dis.add(int(lr_val)) + + for c in to_add: + cur_block.addto(c) + + +def arm_guess_jump_table(dis_engine, cur_block, offsets_to_dis): + arch = dis_engine.arch + loc_db = dis_engine.loc_db + lifter_model_call = get_lifter_model_call(arch, dis_engine.attrib) + + jra = ExprId('jra') + jrb = ExprId('jrb') + + lifter = lifter_model_call(loc_db) + ircfg = lifter_model_call.new_ircfg() + lifter.add_asmblock_to_ircfg(cur_block, ircfg) + + for irblock in viewvalues(ircfg.blocks): + pc_val = None + for exprs in irblock: + for e in exprs: + if e.dst == lifter.pc: + pc_val = e.src + if pc_val is None: + continue + if not isinstance(pc_val, ExprMem): + continue + assert(pc_val.size == 32) + print(pc_val) + ad = pc_val.arg + ad = expr_simp(ad) + print(ad) + res = match_expr(ad, jra + jrb, set([jra, jrb])) + if res is False: + raise NotImplementedError('not fully functional') + print(res) + if not isinstance(res[jrb], ExprInt): + raise NotImplementedError('not fully functional') + base_ad = int(res[jrb]) + print(base_ad) + addrs = set() + i = -1 + max_table_entry = 10000 + max_diff_addr = 0x100000 # heuristic + while i < max_table_entry: + i += 1 + try: + ad = upck32(dis_engine.bin_stream.getbytes(base_ad + 4 * i, 4)) + except: + break + if abs(ad - base_ad) > max_diff_addr: + break + addrs.add(ad) + print([hex(x) for x in addrs]) + + for ad in addrs: + offsets_to_dis.add(ad) + l = loc_db.get_or_create_offset_location(ad) + c = AsmConstraintTo(l) + cur_block.addto(c) + +guess_funcs = [] + + +def guess_multi_cb(dis_engine, cur_block, offsets_to_dis): + for f in guess_funcs: + f(dis_engine, cur_block, offsets_to_dis) |