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))
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))