Esempio n. 1
0
def miasm_anal(r2_op, r2_address, r2_buffer, r2_length):
    """Define an instruction behavior using miasm."""

    # Cast radare2 variables
    opcode = ffi.cast("char*", r2_buffer)


    # Prepare the opcode
    opcode = ffi.unpack(opcode, r2_length)


    # Disassemble the opcode
    try:
        machine = miasm_machine()
        mode = machine.dis_engine().attrib
        instr = machine.mn().dis(opcode, mode)
        instr.offset = r2_address
        if instr.dstflow():
            # Adjust arguments values using the instruction offset
            instr.dstflow2label(AsmSymbolPool())
        dis_len = instr.l
    except:
        # Can't do anything with an invalid instruction
        return


    # Cast the RAnalOp structure and fill some fields
    r2_analop = ffi.cast("RAnalOp_r2m2*", r2_op)
    r2_analop.mnemonic = alloc_string(instr.name)
    r2_analop.size = dis_len
    r2_analop.type = R_ANAL_OP_TYPE_UNK
    r2_analop.eob = 0   # End Of Block

    # Convert miasm expressions to ESIL
    get_esil(r2_analop, instr)


    ### Architecture agnostic analysis

    # Instructions that *DO NOT* stop a basic bloc
    if instr.breakflow() is False:
        return
    else:
        r2_analop.eob = 1  # End Of Block


    # Assume that an instruction starting with 'RET' is a return
    # Note: add it to miasm2 as getpc() ?
    if instr.name[:3].upper().startswith("RET"):
        r2_analop.type = R_ANAL_OP_TYPE_RET

    # Instructions that explicitly provide the destination
    if instr and instr.dstflow():
        expr = instr.getdstflow(None)[0]

        if instr.is_subcall():
            r2_anal_subcall(r2_analop, expr)
            return

        if r2_analop.type == R_ANAL_OP_TYPE_UNK and instr.splitflow():
            r2_anal_splitflow(r2_analop, r2_address, instr, expr)
            return

        if isinstance(expr, ExprInt):
            r2_analop.type = R_ANAL_OP_TYPE_JMP
            r2_analop.jump = int(expr.arg) & 0xFFFFFFFFFFFFFFFF

        elif isinstance(expr, ExprId):
            if isinstance(expr.name, AsmLabel):
                # Get the miasm2 AsmLabel address
                r2_analop.type = R_ANAL_OP_TYPE_JMP
                r2_analop.jump = label2address(expr) & 0xFFFFFFFFFFFFFFFF
            else:
                r2_analop.type = R_ANAL_OP_TYPE_UJMP

        elif isinstance(expr, ExprMem):
            r2_analop.type = R_ANAL_OP_TYPE_MJMP

        else:
            print >> sys.stderr, "miasm_anal(): don't know what to do with: %s" % instr
Esempio n. 2
0
def miasm_anal(r2_op, r2_address, r2_buffer, r2_length):
    """Define an instruction behavior using miasm."""

    # Return the cached result if any
    global LRU_CACHE
    result = LRU_CACHE.get(r2_address, None)
    if result is not None:
        result.fill_ranalop(r2_op)
        return

    # Cheap garbage collection
    if False and len(LRU_CACHE.keys()) >= 10:
        to_delete = [addr for addr in LRU_CACHE.keys() if addr < r2_address]
        for key in to_delete[:5]:
            del LRU_CACHE[key]

    # Cast radare2 variables
    opcode = ffi.cast("char*", r2_buffer)

    # Prepare the opcode
    opcode = ffi.unpack(opcode, r2_length)

    # Disassemble the opcode
    loc_db = LocationDB()
    try:
        machine = miasm_machine()
        mode = machine.dis_engine().attrib
        instr = machine.mn().dis(opcode, mode)
        instr.offset = r2_address
        if instr.dstflow():
            # Adjust arguments values using the instruction offset
            instr.dstflow2label(loc_db)
        dis_len = instr.l
    except:
        # Can't do anything with an invalid instruction
        return

    result = CachedRAnalOp()
    result.mnemonic = instr.name
    result.size = dis_len
    result.type = R_ANAL_OP_TYPE_UNK
    result.eob = 0   # End Of Block

    # Convert miasm expressions to ESIL
    get_esil(result, instr, loc_db)

    # # # Architecture agnostic analysis

    # Instructions that *DO NOT* stop a basic bloc
    if instr.breakflow() is False:
        result.fill_ranalop(r2_op)
        LRU_CACHE[r2_address] = result
        return
    else:
        result.eob = 1  # End Of Block

    # Assume that an instruction starting with 'RET' is a return
    # Note: add it to miasm2 as getpc() ?
    if instr.name[:3].upper().startswith("RET"):
        result.type = R_ANAL_OP_TYPE_RET

    # Instructions that explicitly provide the destination
    if instr and instr.dstflow():
        expr = instr.getdstflow(None)[0]

        if instr.is_subcall():
            r2_anal_subcall(result, expr, loc_db)
            result.fill_ranalop(r2_op)
            LRU_CACHE[r2_address] = result
            return

        if result.type == R_ANAL_OP_TYPE_UNK and instr.splitflow():
            r2_anal_splitflow(result, r2_address, instr, expr, loc_db)
            result.fill_ranalop(r2_op)
            LRU_CACHE[r2_address] = result
            return

        if isinstance(expr, ExprInt):
            result.type = R_ANAL_OP_TYPE_JMP
            result.jump = int(expr.arg) & 0xFFFFFFFFFFFFFFFF

        elif isinstance(expr, ExprId):
            result.type = R_ANAL_OP_TYPE_UJMP

        elif isinstance(expr, ExprLoc):
            addr = loc_db.get_location_offset(expr.loc_key)
            result.type = R_ANAL_OP_TYPE_JMP
            result.jump = addr & 0xFFFFFFFFFFFFFFFF

        elif isinstance(expr, ExprMem):
            result.type = R_ANAL_OP_TYPE_MJMP

        else:
            msg = "miasm_anal(): don't know what to do with: %s" % instr
            print >> sys.stderr, msg

    result.fill_ranalop(r2_op)
    LRU_CACHE[r2_address] = result