Ejemplo n.º 1
0
def emotet_control_flow_unflatten(func_addr, filename):
    with open(filename, 'rb') as fstream:
        cont = Container.from_stream(fstream)

    machine = Machine(cont.arch)
    mdis = machine.dis_engine(cont.bin_stream, loc_db=cont.loc_db)
    asmcfg = mdis.dis_multiblock(func_addr)

    ir_arch = machine.ira(mdis.loc_db)
    ircfg = ir_arch.new_ircfg_from_asmcfg(asmcfg)

    state_register = get_state_register(asmcfg,
                                        get_loc_key_at(cont.loc_db, func_addr))
    if not state_register:
        print("[-] Function was not obfuscated")
        return

    to_patch_offsets = resolve_offsets(state_register, asmcfg, ircfg, ir_arch)
    to_patch_offsets.sort(key=lambda tup: tup[0])
    fix_func_cfg(filename, to_patch_offsets)

    print("[+] Function was deobfuscated!")
Ejemplo n.º 2
0
class Block:
    def __init__(self, raw, address):
        self.cont = Container.fallback_container(raw + b'\xC3',
                                                 vm=None,
                                                 addr=address)
        self.address = address
        self.machine = Machine('x86_64')
        self.mdis = self.machine.dis_engine(self.cont.bin_stream,
                                            loc_db=self.cont.loc_db)
        self.asmcfg = self.mdis.dis_multiblock(self.address)
        self.head = self.asmcfg.getby_offset(self.address).loc_key
        self.orignal_ira = self.machine.ira(self.mdis.loc_db)
        self.orginal_ircfg = self.orignal_ira.new_ircfg_from_asmcfg(
            self.asmcfg)
        self.common_simplifier = IRCFGSimplifierCommon(self.orignal_ira)
        self.common_simplifier.simplify(self.orginal_ircfg, self.head)
        self.custom_ira1 = IRADelModCallStack(self.mdis.loc_db)
        self.custom_ira2 = IRAOutRegs(self.mdis.loc_db)
        self.ircfg = self.custom_ira1.new_ircfg_from_asmcfg(self.asmcfg)
        self.simplify()

    def simplify(self):
        simplifier = IRCFGSimplifierCommon(self.custom_ira1)
        simplifier.simplify(self.ircfg, self.head)
        for loc in self.ircfg.leaves():
            irblock = self.ircfg.blocks.get(loc)
            if irblock is None:
                continue
            regs = {}
            for reg in self.custom_ira1.get_out_regs(irblock):
                regs[reg] = reg
            assignblks = list(irblock)
            newAssignBlk = AssignBlock(regs, assignblks[-1].instr)
            assignblks.append(newAssignBlk)
            newIrBlock = IRBlock(irblock.loc_key, assignblks)
            self.ircfg.blocks[loc] = newIrBlock
        simplifier = CustomIRCFGSimplifierSSA(self.custom_ira2)
        simplifier.simplify(self.ircfg, self.head)
Ejemplo n.º 3
0
    cont = Container.from_stream(fstream)

arch = args.architecture if args.architecture else cont.arch
machine = Machine(arch)

# Check elements
elements = set()
regs = machine.mn.regs.all_regs_ids_byname
for element in args.element:
    try:
        elements.add(regs[element])
    except KeyError:
        raise ValueError("Unknown element '%s'" % element)

mdis = machine.dis_engine(cont.bin_stream, dont_dis_nulstart_bloc=True)
ir_arch = machine.ira(mdis.loc_db)

# Common argument forms
init_ctx = {}
if args.rename_args:
    if arch == "x86_32":
        # StdCall example
        for i in range(4):
            e_mem = ExprMem(
                ExprId("ESP_init", 32) + ExprInt(4 * (i + 1), 32), 32)
            init_ctx[e_mem] = ExprId("arg%d" % i, 32)

# Disassemble the targeted function
asmcfg = mdis.dis_multiblock(int(args.func_addr, 0))

# Generate IR
Ejemplo n.º 4
0
Archivo: disas.py Proyecto: s0i37/DBA
		if args.diff:
			if not new_eips:
				break
			if trace.cpu.eip_before == new_eip:
				new_eip = new_eips.pop(0)
				print "%d:" % diff_no,
				diff_no += 1
			else:
				continue
		
		
		if args.ir:
			loc_db = LocationDB()
			instr = machine.mn.dis(trace.cpu.opcode, 32)
			ira = machine.ira(loc_db)
			ircfg = ira.new_ircfg()
			ira.add_instr_to_ircfg(instr, ircfg)
			for lbl, irblock in ircfg.blocks.items():
				print irblock.to_string(loc_db)
		else:
			print "{takt}:{offset}: {disas}".format( takt=trace.cpu.takt, offset=hex(trace.cpu.eip_before), disas=mnem ),
		
		if args.regs:
			print ';',
			for reg in args.regs.split(','):
				print "%s=0x%X," % (reg, trace.cpu.get(reg)),
		if args.mems:
			print ';',
			for mem in args.mems.split(','):
				try:
Ejemplo n.º 5
0
start_addr = 0x491aa0

# symbol table
loc_db = LocationDB()

# open the binary for analysis
container = Container.from_stream(open(file_path, 'rb'), loc_db)

# cpu abstraction
machine = Machine(container.arch)

# init disassemble engine
mdis = machine.dis_engine(container.bin_stream, loc_db=loc_db)

# initialize intermediate representation
ira = machine.ira(mdis.loc_db)

# disassemble the function at address
asm_cfg = mdis.dis_multiblock(start_addr)

# translate asm_cfg into ira_cfg
ira_cfg = ira.new_ircfg_from_asmcfg(asm_cfg)

# set opaque predicate counter
opaque_counter = 0

# dictionary of byte patches
patches = {}

# walk over all basic blocks
for basic_block in asm_cfg.blocks:
Ejemplo n.º 6
0
fdesc = open(sys.argv[1], 'rb')

cont = Container.from_stream(fdesc)

machine = Machine(cont.arch)

mdis = machine.dis_engine(cont.bin_stream, loc_db=cont.loc_db)

addr = cont.entry_point
asmcfg = mdis.dis_multiblock(addr)

#####################################
#    End common section             #
#####################################

# Get an IRA converter
# The sub call are modelised by default operators
# call_func_ret and call_func_stack
ir_arch_analysis = machine.ira(mdis.loc_db)

# Get the IR of the asmcfg
ircfg_analysis = ir_arch_analysis.new_ircfg_from_asmcfg(asmcfg)

# Display each IR basic blocks
for irblock in viewvalues(ircfg_analysis.blocks):
    print(irblock)

# Output ir control flow graph in a dot file
open('bin_ira_cfg.dot', 'w').write(ircfg_analysis.dot())
Ejemplo n.º 7
0
    cont = Container.from_stream(fstream)

arch = args.architecture if args.architecture else cont.arch
machine = Machine(arch)

# Check elements
elements = set()
regs = machine.mn.regs.all_regs_ids_byname
for element in args.element:
    try:
        elements.add(regs[element])
    except KeyError:
        raise ValueError("Unknown element '%s'" % element)

mdis = machine.dis_engine(cont.bin_stream, dont_dis_nulstart_bloc=True)
ir_arch = machine.ira(mdis.loc_db)

# Common argument forms
init_ctx = {}
if args.rename_args:
    if arch == "x86_32":
        # StdCall example
        for i in range(4):
            e_mem = ExprMem(ExprId("ESP_init", 32) + ExprInt(4 * (i + 1), 32), 32)
            init_ctx[e_mem] = ExprId("arg%d" % i, 32)

# Disassemble the targeted function
asmcfg = mdis.dis_multiblock(int(args.func_addr, 0))

# Generate IR
ircfg = ir_arch.new_ircfg_from_asmcfg(asmcfg)
Ejemplo n.º 8
0
from miasm.analysis.machine import Machine
from miasm.core.bin_stream import bin_stream_str
from miasm.arch.x86.disasm import dis_x86_32
from miasm.arch.x86.ira import ir_a_x86_64
from miasm.arch.x86.regs import all_regs_ids, all_regs_ids_init
# from miasm.ir.symbexec import symbexec
from miasm.analysis.cst_propag import add_state, propagate_cst_expr
from miasm.expression.simplifications import expr_simp
from miasm.analysis.data_flow import dead_simp, \
    merge_blocks, remove_empty_assignblks

mn = Machine('x86_64')

# Create an intermediate representation object
loc_db = LocationDB()
ira = mn.ira(loc_db)

# create an empty ircfg
ircfg = ira.new_ircfg()

# Binary path and offset of the target function
offset = 0x1150
fname = "bin/simple_test.bin"

# Get Miasm's binary stream
bin_file = open(fname).read()
bin_stream = bin_stream_str(bin_file)

# Disassemble blocks of the function at 'offset'
mdis = mn.dis_engine(bin_stream)
disasm = mdis.dis_multiblock(offset)
Ejemplo n.º 9
0
machine = Machine("x86_32")
loc_db = LocationDB()

# Assemble and disassemble a MOV
## Ensure that attributes 'offset' and 'l' are set
line = machine.mn.fromstring("MOV EAX, EBX", loc_db, 32)
asm = machine.mn.asm(line)[0]

# Get back block
cont = Container.from_string(asm, loc_db = loc_db)
mdis = machine.dis_engine(cont.bin_stream, loc_db=loc_db)
mdis.lines_wd = 1
asm_block = mdis.dis_block(START_ADDR)

# Translate ASM -> IR
ira = machine.ira(mdis.loc_db)
ircfg = ira.new_ircfg()
ira.add_asmblock_to_ircfg(asm_block, ircfg)

# Instantiate a Symbolic Execution engine with default value for registers
symb = SymbolicExecutionEngine(ira)

# Emulate one IR basic block
## Emulation of several basic blocks can be done through .emul_ir_blocks
cur_addr = symb.run_at(ircfg, START_ADDR)

# Modified elements
print('Modified registers:')
symb.dump(mems=False)
print('Modified memory (should be empty):')
symb.dump(ids=False)
Ejemplo n.º 10
0
class SSAConverter(object):
    def __init__(self):
        self.machine = Machine('x86_64')
        self.dis_engine, self.ira = self.machine.dis_engine, self.machine.ira
        self.bs = bin_stream_ida()
        self.mdis = self.dis_engine(self.bs)

        self.ssa_cache = {}
        self.ssa_with_state_cache = {}
        return

    def Analyze(self, addr, deep=False):
        todo_list = []
        if addr in self.ssa_cache:
            return self.ssa_cache[addr]

        asmcfg = self.mdis.dis_multiblock(addr)

        ira = self.machine.ira(asmcfg.loc_db)
        try:
            ircfg = ira.new_ircfg_from_asmcfg(asmcfg)
        except:
            # Failed on converting
            self.ssa_cache[addr] = None
            return None

        modified = True
        while modified:
            modified = ircfg.simplify(expr_simp)

        ssa = SSADiGraph(ircfg)
        ssa.transform(asmcfg.loc_db.get_offset_location(addr))

        # for lbl, irblock in ircfg.blocks.items():
        #     print(irblock.to_string(ircfg.loc_db))

        if deep:
            for lbl, irblock in ircfg.blocks.items():
                for blk in irblock.assignblks:
                    for val in blk.values():
                        if (isinstance(val, ExprOp)
                                and val.op == "call_func_ret"
                                and isinstance(val.args[0], ExprLoc)):
                            callee_addr = asmcfg.loc_db.get_location_offset(
                                val.args[0].loc_key)

                            if callee_addr not in todo_list:
                                todo_list.append(callee_addr)

        self.ssa_cache[addr] = ircfg

        if deep:
            # Recursively analyze functions which are called by initial target function
            for callee_addr in todo_list:
                self.Analyze(callee_addr, deep)
        return ircfg

    def InitializeState(self, label, state_of_label):
        initial_state = {}
        for reg_id in attrib_to_regs[64]:
            initial_state[reg_id] = reg_id

        state_of_label[label] = initial_state
        return

    def AnalyzeWithState(self, addr, deep=False):
        if addr in self.ssa_with_state_cache:
            return self.ssa_with_state_cache[addr]
        ircfg = self.Analyze(addr, deep)
        if not ircfg:
            self.ssa_with_state_cache[addr] = None
            return None

        head = ircfg.loc_db.get_offset_location(addr)
        visited = []

        # Set initial state of head
        state_of_label = {}  # label:state
        self.InitializeState(head, state_of_label)

        todo_labels = [head]
        while todo_labels:
            lbl = todo_labels.pop(0)
            if lbl in visited:
                continue
            else:
                visited.append(lbl)
            irblock = ircfg.blocks[lbl]

            current_state = state_of_label[lbl]

            # Replace assignblocks to assignblocks with state
            new_assignblks = []
            for assignblk in irblock.assignblks:
                # Check assignblk is for phi-related blk
                is_phiblk = False
                if len(assignblk.values()):
                    sample_expr = assignblk.values()[0]
                    if isinstance(sample_expr,
                                  ExprOp) and sample_expr.op == "Phi":
                        is_phiblk = True

                if not is_phiblk:
                    new_assignblk = AssignBlockWithState(
                        assignblk, current_state.copy())
                else:
                    new_assignblk = assignblk
                new_assignblks.append(new_assignblk)

                # Process assignblocks and update current state
                dsts = assignblk.keys()
                for dst in dsts:
                    if not isinstance(dst, ExprId):
                        continue
                    if dst.name == "IRDst":
                        continue
                    assert ("." in dst.name)
                    org_name = dst.name[:dst.name.find(".")]
                    org_expr = ExprId(org_name, dst.size)
                    assert (org_expr in current_state)
                    current_state[org_expr] = dst

            irblock._assignblks = tuple(new_assignblks)

            # Add successors to todo list and update its initial state
            successor_labels = ircfg.successors(lbl)
            todo_labels += filter(lambda x: x not in visited, successor_labels)
            # Update state of successors label with latest current state
            for successor_label in successor_labels:
                state_of_label[successor_label] = current_state.copy()

        self.ssa_with_state_cache[addr] = ircfg
        return ircfg
Ejemplo n.º 11
0
    open('data.dot', 'w').write(flow_graph.dot())


ad = int(args.addr, 16)
loc_db = LocationDB()
print('disasm...')
cont = Container.from_stream(open(args.filename, 'rb'), loc_db)
machine = Machine("x86_32")

mdis = machine.dis_engine(cont.bin_stream, loc_db=loc_db)
mdis.follow_call = True
asmcfg = mdis.dis_multiblock(ad)
print('ok')

print('generating dataflow graph for:')
ir_arch_analysis = machine.ira(loc_db)
ircfg = ir_arch_analysis.new_ircfg_from_asmcfg(asmcfg)
deadrm = DeadRemoval(ir_arch_analysis)

for irblock in viewvalues(ircfg.blocks):
    print(irblock)

if args.symb:
    block_flow_cb = intra_block_flow_symb
else:
    block_flow_cb = intra_block_flow_raw

gen_block_data_flow_graph(ir_arch_analysis, ircfg, ad, block_flow_cb)

print('*' * 40)
print("""
Ejemplo n.º 12
0
    cont = Container.from_stream(fstream, loc_db)

arch = args.architecture if args.architecture else cont.arch
machine = Machine(arch)

# Check elements
elements = set()
regs = machine.mn.regs.all_regs_ids_byname
for element in args.element:
    try:
        elements.add(regs[element])
    except KeyError:
        raise ValueError("Unknown element '%s'" % element)

mdis = machine.dis_engine(cont.bin_stream, dont_dis_nulstart_bloc=True, loc_db=loc_db)
ir_arch = machine.ira(loc_db)

# Common argument forms
init_ctx = {}
if args.rename_args:
    if arch == "x86_32":
        # StdCall example
        for i in range(4):
            e_mem = ExprMem(ExprId("ESP_init", 32) + ExprInt(4 * (i + 1), 32), 32)
            init_ctx[e_mem] = ExprId("arg%d" % i, 32)

# Disassemble the targeted function
asmcfg = mdis.dis_multiblock(int(args.func_addr, 0))

# Generate IR
ircfg = ir_arch.new_ircfg_from_asmcfg(asmcfg)