Ejemplo n.º 1
0
def test_disasm_against_objdump(objdump_path, binary_path):
    # TODO: code repetition from test_disasm_standalone, encapsulate inner functionality.

    start_time = time.time()
    total_inst = 0
    match_inst = 0

    print(('Processing file:', binary_path))
    elf_file = ELFFile(open(binary_path, 'rb'))

    if elf_file.num_segments() == 0:
        print('There are no program headers in this file.')
        return

    objdump = ObjdumpWrapper(objdump_path)
    disasm = HexagonDisassembler(objdump_compatible=True)

    for segment in elf_file.iter_segments():
        if segment['p_flags'] & P_FLAGS.PF_X:

            print("Offset: {:x}".format(segment['p_offset']))
            print("VirtAddr: {:x}".format(segment['p_vaddr']))
            print("FileSiz: {:x}".format(segment['p_filesz']))

            segment_data = segment.data()
            data_pos = 0

            while data_pos + INST_SIZE <= len(segment_data):

                addr = segment['p_vaddr'] + data_pos

                inst_as_int = struct.unpack(
                    '<I', segment_data[data_pos:data_pos + 4])[0]

                disasm_output = disasm.disasm_one_inst(inst_as_int,
                                                       addr).text.strip()

                objdump_output = objdump.disasm_packet_raw(
                    segment_data[data_pos:min(data_pos + 4 * 4, segment_data)],
                    addr).strip()

                if (objdump_output != disasm_output):
                    print("[{:08x}] {:s}".format(addr, objdump_output))
                    print("[{:08x}] {:s}".format(addr, disasm_output))
                    print()
                else:
                    match_inst += 1

                data_pos += 4
                total_inst += 1

    elapsed_time = time.time() - start_time

    print("Elapsed time: {0:.2f}".format(elapsed_time))
    print('Match: {0:.2f}%'.format(match_inst / total_inst * 100))
Ejemplo n.º 2
0
def test_disasm_against_objdump(objdump_path, binary_path):
    # TODO: code repetition from test_disasm_standalone, encapsulate inner functionality.

    start_time = time.time()
    total_inst = 0
    match_inst = 0

    print(('Processing file:', binary_path))
    elf_file = ELFFile(open(binary_path, 'rb'))

    if elf_file.num_segments() == 0:
        print('There are no program headers in this file.')
        return

    objdump = ObjdumpWrapper(objdump_path)
    disasm = HexagonDisassembler(objdump_compatible=True)

    for segment in elf_file.iter_segments():
        if segment['p_flags'] & P_FLAGS.PF_X:

            print("Offset: {:x}".format(segment['p_offset']))
            print("VirtAddr: {:x}".format(segment['p_vaddr']))
            print("FileSiz: {:x}".format(segment['p_filesz']))

            segment_data = segment.data()
            data_pos = 0

            while data_pos + INST_SIZE <= len(segment_data):

                addr = segment['p_vaddr'] + data_pos

                inst_as_int = struct.unpack('<I', segment_data[data_pos: data_pos + 4])[0]

                disasm_output = disasm.disasm_one_inst(inst_as_int, addr).text.strip()

                objdump_output = objdump.disasm_packet_raw(
                    segment_data[data_pos: min(data_pos + 4 * 4, segment_data)],
                    addr).strip()

                if (objdump_output != disasm_output):
                    print("[{:08x}] {:s}".format(addr, objdump_output))
                    print("[{:08x}] {:s}".format(addr, disasm_output))
                    print()
                else:
                    match_inst += 1

                data_pos += 4
                total_inst += 1

    elapsed_time = time.time() - start_time

    print("Elapsed time: {0:.2f}".format(elapsed_time))
    print('Match: {0:.2f}%'.format(match_inst / total_inst * 100))
Ejemplo n.º 3
0
def test_disasm_standalone(binary_path, timeout=None):

    profile = cProfile.Profile()
    profile.enable()

    start_time = time.time()

    print(('Processing file:', binary_path))
    elf_file = ELFFile(open(binary_path, 'rb'))

    if elf_file.num_segments() == 0:
        print('There are no program headers in this file.')
        return

    disasm = HexagonDisassembler()

    total_inst = 0

    for segment in elf_file.iter_segments():
        if segment['p_flags'] & P_FLAGS.PF_X:
            print("Offset: {:x}".format(segment['p_offset']))
            print("VirtAddr: {:x}".format(segment['p_vaddr']))
            print("FileSiz: {:x}".format(segment['p_filesz']))

            segment_data = segment.data()
            data_pos = 0

            while data_pos + INST_SIZE <= len(segment_data):

                addr = segment['p_vaddr'] + data_pos

                inst_as_int = struct.unpack(
                    '<I', segment_data[data_pos:data_pos + 4])[0]

                dis = disasm.disasm_one_inst(inst_as_int, addr)
                print("[{:08x}] {:s}".format(addr, dis.text))

                data_pos += 4
                total_inst += 1

                if timeout and (time.time() - start_time) > timeout:
                    break

    profile.disable()
    prof_stats = pstats.Stats(profile)
    prof_stats.strip_dirs().sort_stats('cumulative').print_stats(20)

    print("Total instructions: " + str(total_inst))
    elapsed_time = time.time() - start_time
    print("Elapsed time: " + str(elapsed_time))
Ejemplo n.º 4
0
def test_disasm_standalone(binary_path, timeout = None):

    profile = cProfile.Profile()
    profile.enable()

    start_time = time.time()

    print(('Processing file:', binary_path))
    elf_file = ELFFile(open(binary_path, 'rb'))

    if elf_file.num_segments() == 0:
        print('There are no program headers in this file.')
        return

    disasm = HexagonDisassembler()

    total_inst = 0

    for segment in elf_file.iter_segments():
        if segment['p_flags'] & P_FLAGS.PF_X:
            print("Offset: {:x}".format(segment['p_offset']))
            print("VirtAddr: {:x}".format(segment['p_vaddr']))
            print("FileSiz: {:x}".format(segment['p_filesz']))

            segment_data = segment.data()
            data_pos = 0

            while data_pos + INST_SIZE <= len(segment_data):

                addr = segment['p_vaddr'] + data_pos

                inst_as_int = struct.unpack('<I', segment_data[data_pos: data_pos + 4])[0]

                dis = disasm.disasm_one_inst(inst_as_int, addr)
                print("[{:08x}] {:s}".format(addr, dis.text))

                data_pos += 4
                total_inst += 1

                if timeout and (time.time() - start_time) > timeout:
                    break

    profile.disable()
    prof_stats = pstats.Stats(profile)
    prof_stats.strip_dirs().sort_stats('cumulative').print_stats(20)

    print("Total instructions: " + str(total_inst))
    elapsed_time = time.time() - start_time
    print("Elapsed time: " + str(elapsed_time))
Ejemplo n.º 5
0
def generate_function(org_func_name, org_func, symtab, base_elf, metadata,
                      func_symtab):
    """
    generates a helper function to call the original version of an overwritten firmware function
    
    :param org_func_name:   name of the new function
    :param org_func:        original function name, the one we replaced
    :param symtab:          symbol table
    :param base_elf:        base firmware ELF file
    :param metadata:        base firmware metadata
    :param func_symtab:     table of new symbols needed by generated functions
    """
    addr_str, ret_type, param_str = resolve_symbol_all(org_func, symtab)
    if (addr_str == '"unknown"'):
        print "error: trying to generate fw_org function for a function with unknown location"
        exit(1)
    address = int(addr_str, 0)

    # read first 5 instruction of destination function
    # we have to read 5 instructions in case the first packet contains only 1 instruction,
    # then the we have to relocate 2 packages (with up to 5 instructions in total)
    elf_pos, elf_blob = get_offset_in_elf(metadata, address)
    base_elf.seek(elf_pos)
    data = struct.unpack("<IIIII", base_elf.read(20))

    disasm = HexagonDisassembler(objdump_compatible=True)
    disasm0 = HexagonDisassembler(objdump_compatible=True)
    next_prefix = ""

    # generate function start text
    function_decl = "%s %s(%s)" % (ret_type, org_func_name, param_str)
    function_def = "%s {\n\tasm(\n" % function_decl
    function_decl += ";"

    # iterate over the four instructions fetched
    reloc_size = 0
    for pos in range(0, 5):
        reloc_size += 1
        # disassemble instruction with correct position
        hi = disasm.disasm_one_inst(data[pos], address + pos * 4)
        # disassemble instruction again with position 0 to check for PC relative immediates
        hi0 = disasm0.disasm_one_inst(data[pos], pos * 4)

        if (hi.immext is not None):
            if (hi.start_packet):
                next_prefix = "{ "
            continue

        disasm_output = hi.text.strip()
        disasm_output_hi0 = hi0.text.strip()
        # if we have a realtive immediate
        if (disasm_output != disasm_output_hi0):
            # loop over all immediates
            for pos_imm, imm in enumerate(hi.imm_ops):
                imm0 = hi0.imm_ops[pos_imm]
                # check for difference -> PC relative immediate
                if (imm0 != imm):
                    # generate a dummy symbol at the destination address
                    # and write our target relative to this, by this we
                    # force the compiler to generate a relocation for
                    # the immediate for us
                    dest_address = address + imm0.value
                    symbol = "sym_0x%X" % dest_address
                    func_symtab[symbol] = dest_address
                    rel_adr = "%s" % symbol
                    disasm_output = disasm_output.replace(
                        ("0x%X" % imm.value).lower(), rel_adr)

        function_def += '\t\t"%s%s\\n\\t" \n' % (next_prefix, disasm_output)
        next_prefix = ""

        if ((pos != 0) & (hi.end_packet)):
            break

    # generate a jump instruction to the start of remaining original function
    org_func_start = (address + (reloc_size << 2))
    symbol = "sym_0x%X" % org_func_start
    func_symtab[symbol] = org_func_start
    function_def += '\t\t"{ jump %s }"\n' % symbol
    function_def += "\t);\n}"
    return function_decl, function_def, func_symtab