예제 #1
0
def do_instrument(target, output, bbs, disable_tls, daemon_mode, verbose,
                  daemonize, interp, bbcoverage, stateful, detailed_bbcoverage,
                  bb_index_path, path):
    ELFPATCHER_PATH = os.path.abspath(os.path.join("..", "ELFPatcher"))
    sys.path.append(ELFPATCHER_PATH)
    from elfpatcher import ELF

    elf = ELF(target)

    tlog('Start patching for %s' % target)

    if (not elf.check_imported_library('libc.so.6')
            and not elf.check_imported_library('libc.so.0')):
        die('The binary does not have libc.so.6/0 imported.')

    if daemon_mode == 'desock':
        init_entry = 'afl_manual_init'
        if stateful:
            elf.add_imported_library('libdesock-state.so')
        else:
            elf.add_imported_library('libdesock.so')
            # elf.add_imported_library('libdesock3-xiaomithrift.so')
            # elf.add_imported_library('libdesock3-persistent.so')
    elif daemon_mode == 'client':
        # init_entry = 'afl_manual_init_daemon'
        die('Historical use only.')
    else:
        init_entry = 'afl_manual_init'

    libaflinit_so = 'libaflinit.so'
    if bbcoverage:
        libaflinit_so = 'libaflinit-cov.so'
    elif detailed_bbcoverage:
        libaflinit_so = 'libaflinit-detailed-cov.so'
    elif path:
        libaflinit_so = 'libaflinit-path.so'
        # libaflinit_so = 'libaflinit-persistent2.so'
    elf.add_imported_symbol(init_entry, 'afl_init_entry', libaflinit_so)

    if daemonize:
        elf.add_imported_library('libdedaemon.so')

    if interp:
        elf.change_interp(interp)

    # avoid write to invalid address before initialization complete
    elf.add_data('afl_area_initial', '\x00' * 0x10000)
    elf.add_pointer('shm_pointer', 'afl_area_initial')

    if bbcoverage:
        elf.add_data('afl_area_cov_initial', '\x00' * 0x10000)
        elf.add_pointer('shm_cov_pointer', 'afl_area_cov_initial')
    elif detailed_bbcoverage:
        elf.add_data('afl_area_detailed_cov_initial', '\x00' * 0x10000)
        elf.add_pointer('shm_detailed_cov_pointer',
                        'afl_area_detailed_cov_initial')
    elif path:
        elf.add_data('afl_area_path_initial', '\xff\xff\xff\xff' * 0x400000)
        elf.add_pointer('shm_path_pointer', 'afl_area_path_initial')
        elf.add_data('afl_area_path_index_initial', '\x00\x00\x00\x00')
        elf.add_pointer('shm_path_index_pointer',
                        'afl_area_path_index_initial')

    afl_init_stub = afl_init
    if bbcoverage:
        afl_init_stub = afl_init_cov
    elif detailed_bbcoverage:
        afl_init_stub = afl_init_detailed_cov
    elif path:
        afl_init_stub = afl_init_path
    elf.add_code('afl_init', afl_init_stub)
    elf.add_init_function('afl_init')

    if disable_tls:
        elf.add_data('afl_prev_loc', '\x00' * 4)
        trampoline_template = trampoline_template_single_thread
        if bbcoverage:
            trampoline_template = trampoline_template_single_thread_cov
        elif detailed_bbcoverage:
            trampoline_template = trampoline_template_single_thread_detailed_cov
        elif path:
            trampoline_template = trampoline_template_single_thread_path
    else:
        elf.add_tls_bss_data('afl_prev_loc', 4, 'afl_prev_loc_offset')
        trampoline_template = trampoline_template_with_tls
        if bbcoverage:
            trampoline_template = trampoline_template_with_tls_cov
        elif detailed_bbcoverage:
            trampoline_template = trampoline_template_with_tls_detailed_cov
        elif path:
            trampoline_template = trampoline_template_with_tls_path
            # trampoline_template = trampoline_template_with_tls_path_and_pmode

    bb_index = ['bb,index,magic\n']

    for index, bb in enumerate(bbs):
        magic = new_magic(bb, bbcoverage)
        trampoline = ''
        if detailed_bbcoverage:
            trampoline = trampoline_template.format(magic=magic,
                                                    magic_shift=magic >> 1,
                                                    block_index=index)
        elif path:
            trampoline = trampoline_template.format(magic=magic,
                                                    magic_shift=magic >> 1,
                                                    offset=bb)
        else:
            trampoline = trampoline_template.format(magic=magic,
                                                    magic_shift=magic >> 1)

        try:
            elf.insert_code(where=bb, label="patch_%#x" % bb, code=trampoline)
        except Exception, e:
            log('[-] No.%d basic block @ %#x failed: %s.' %
                (index + 1, bb, str(e)))
            continue
        if (index + 1) % 10000 == 0:
            tlog('%d/%d basic blocks processed.' % (index + 1, len(bbs)))
        if verbose:
            log('No.%d basic block @ %#x (magic = %#x).' %
                (index + 1, bb, magic))
        if detailed_bbcoverage:
            bb_index.append('%#x,%d,%#x\n' % (bb, index, magic))
예제 #2
0
def test_arm_afl(target, output, daemon_mode, disable_tls, bbs):
    import sys
    import datetime

    def die(s):
        sys.stdout.write(s + '\n') or exit()

    def log(s):
        sys.stdout.write(s + '\n')

    def tlog(msg):
        log('%s %s' % (str(datetime.datetime.now()), msg))

    trampoline_template_with_tls = """
    stmfd sp!, {{r0 - r4}}      @ save registers
    ldr r0, =afl_prev_loc_offset
    ldr r1, [r0]                @ afl_prev_loc offset
    mrc p15, 0, r0, c13, c0, 3  @ tls pointer
    ldrh r2, [r0, r1]           @ load afl_prev_loc, zero-extended
    movw r4, #{magic:#x}        @ cur_loc, zero-extended
    eor r2, r2, r4              @ afl_prev_loc ^ cur_loc
    ldr r3, =shm_pointer
    ldr r3, [r3]                @ shm_pointer
    ldrb r4, [r3, r2]
    add r4, r4, #1              @ shm[xored] += 1
    strb r4, [r3, r2]
    movw r2, #{magic_shift:#x}  @ cur_loc >> 1
    strh r2, [r0, r1]           @ afl_prev_loc = cur_loc >> 1
    ldmfd sp!, {{r0 - r4}}      @ restore registers
    """

    trampoline_template_single_thread = """
    stmfd sp!, {{r0, r2 - r4}}  @ save registers
    ldr r0, =afl_prev_loc
    ldrh r2, [r0]               @ load afl_prev_loc, zero-extended
    movw r4, #{magic:#x}        @ cur_loc, zero-extended
    eor r2, r2, r4              @ afl_prev_loc ^ cur_loc
    ldr r3, =shm_pointer
    ldr r3, [r3]                @ shm_pointer
    ldrb r4, [r3, r2]
    add r4, r4, #1              @ shm[xored] += 1
    strb r4, [r3, r2]
    movw r2, #{magic_shift:#x}  @ cur_loc >> 1
    strh r2, [r0]               @ afl_prev_loc = cur_loc >> 1
    ldmfd sp!, {{r0, r2 - r4}}  @ restore registers
    """

    afl_init = """
    stmfd sp!, {lr}
    ldr r3, =afl_init_entry
    ldr r3, [r3]
    blx r3                  @ call afl_init_entry(r0, r1, r2)
    ldr r3, =shm_pointer
    str r0, [r3]            @ save shm_pointer
    ldmfd sp!, {pc}
    """

    # it is okay we have duplicate magics, since what we actually need is making
    # magic1 ^ magic2 unique. it helps nothing by making magic itself unique.
    # magics = []
    from zlib import crc32

    def new_magic(seed):
        return crc32(str(seed)) % 2**16

    elf = ELF(target)

    tlog('Start patching for %s' % target)

    if (not elf.check_imported_library('libc.so.6')
            and not elf.check_imported_library('libc.so.0')):
        die('The binary does not have libc.so.6/0 imported.')

    if daemon_mode == 'desock':
        init_entry = 'afl_manual_init'
        elf.add_imported_library('libdesock.so')
    elif daemon_mode == 'client':
        init_entry = 'afl_manual_init_daemon'
    else:
        init_entry = 'afl_manual_init'
    elf.add_imported_symbol(init_entry, 'afl_init_entry', 'libaflinit.so')

    # avoid write to invalid address before initialization complete
    elf.add_data('afl_area_initial', '\x00' * 0x10000)
    elf.add_pointer('shm_pointer', 'afl_area_initial')

    elf.add_code('afl_init', afl_init)
    elf.add_init_function('afl_init')

    if disable_tls:
        elf.add_data('afl_prev_loc', '\x00' * 4)
        trampoline_template = trampoline_template_single_thread
    else:
        elf.add_tls_bss_data('afl_prev_loc', 4, 'afl_prev_loc_offset')
        trampoline_template = trampoline_template_with_tls

    for index, bb in enumerate(bbs):
        magic = new_magic(bb)
        trampoline = trampoline_template.format(magic=magic,
                                                magic_shift=magic >> 1)
        try:
            elf.insert_code(where=bb, label="patch_%#x" % bb, code=trampoline)
        except Exception, e:
            log('[-] No.%d basic block @ %#x failed: %s.' %
                (index + 1, bb, str(e)))
            continue
        if (index + 1) % 10000 == 0:
            tlog('%d basic blocks processed.' % (index + 1))