def apply_rebuild_revert(binary, args, crash_file, ltrace_pattern, patches, \
                         on_stdin=False):
    successful_patches = []
    applied_patches = []
    # apply all valid_patches
    for file_to_patch, patch in patches:
        patch = apply_possible_fixing_patch(file_to_patch, patch)
        if patch:
            applied_patches.append((file_to_patch, patch))

    status = os.system('./9-rebuild.sh > /dev/null')
    result = os.WEXITSTATUS(status)

    if result != 0:
        print "REBUILD apply_rebuild_revert failed"
        # revert all patches
        for file_to_patch, patch in applied_patches:
            revert_patch(file_to_patch,
                         patch)  # by construction, this cannot fail
        return []  # no successful patches

    if on_stdin:
        exit, ltrace_output = run_ltrace_stdin(binary, args, crash_file,
                                               ltrace_pattern)
    else:
        exit, ltrace_output = run_ltrace(binary, args, crash_file,
                                         ltrace_pattern)

    if not crash_signal.did_crash(ltrace_output[-1]):
        print '[+] SUCCESS - Program no longer crashes'
        print '[+] Patch:\n', patch.text
        if TEST:
            record_test_output('[+] SUCCESS - Program no longer crashes\n')
            record_test_output('[+] Patch:\n' +
                               '\n'.join(patch.text.split('\n')))
        print 'successful patches equals applied: %d' % len(applied_patches)
        successful_patches = applied_patches
    else:
        print '[-] Fail: still crashes.'
        if TEST:
            record_test_output('[-] Fail: still crashes.\n')
        successful_patches = []

    # revert all patches
    for file_to_patch, patch in applied_patches:
        revert_patch(file_to_patch, patch)  # by construction, this cannot fail

    if len(successful_patches) == 0:
        return []
    else:
        successful_patches = applied_patches
        return successful_patches
def run(binary, crash_file, args, \
        addr2line_offset, range_backward, range_forward, \
        bug_kind, source_dir, on_stdin, patch_path="p.patch", \
        line_num_offset=0):
    success = False  # successfully removes the crash for the crash_file
    successful_patches = []

    if bug_kind == "memcpy":
        ltrace_pattern = "[email protected]*"

        match_template = "memcpy(:[1], :[2], :[_]);"
        rewrite_template = \
"""
// ROOIBOS START
memcpy(:[1], :[2], 1);
// ROOIBOS END
"""
    elif bug_kind == "strcpy":
        ltrace_pattern = "[email protected]*"

        match_template = "strcpy(:[1], :[2]);"
        rewrite_template = \
"""
// ROOIBOS START
strncpy(:[1], :[2], 1);
:[1][1] = 0;
// ROOIBOS END
"""
    else:
        print "Unknown bug kind %s" % bug_kind
        assert (False)

    if on_stdin:
        exit, ltrace_output = run_ltrace_stdin(binary, args, crash_file,
                                               ltrace_pattern)
    else:
        exit, ltrace_output = run_ltrace(binary, args, crash_file,
                                         ltrace_pattern)

    valid_patches = []

    print 'check did crash'
    print 'ltrace_output', ltrace_output

    if crash_signal.did_crash(ltrace_output[-1]):
        print 'YES'

        mmap = dump_memory_map(binary, args, crash_file)
        ltrace_output = ltrace_output[::-1]
        patch_locations = process_ltrace(ltrace_output, mmap)

        print 'ltraced'

        patch_locations_tmp = []
        for patch_location in patch_locations:
            try:  # skip cases where there's no int at the end (like 'discriminator')
                m = re.search('(.*):(.*)', patch_location)
                if m.group(1) and m.group(2):
                    file_to_patch = m.group(1)
                    line_num = m.group(2)
                    line_num = int(line_num)
                    patch_locations_tmp.append((file_to_patch, line_num))
            except:
                print 'Discriminator @', file_to_patch, line_num
                pass

        patch_locations = patch_locations_tmp

        if DEBUG_PATCH_LOCATIONS:
            print '~=~= patch locations ~=~='
            print '\n'.join(
                map(lambda x: "%s:%d" % (x[0], x[1]), patch_locations))

        for file_to_patch, line_num in patch_locations:
            zero_offset = -1
            line_num = line_num + zero_offset

            line_num = line_num + addr2line_offset

            patch = generate_replacement_patch(\
                    file_to_patch, \
                    line_num, \
                    range_backward, \
                    range_forward, \
                    match_template, \
                    rewrite_template)

            if patch:
                valid_patches.append((file_to_patch, patch))

            for i, valid_patch in enumerate(valid_patches):
                successful_patches = apply_rebuild_revert(\
                        binary, \
                        args, \
                        crash_file, \
                        ltrace_pattern, \
                        [valid_patch], \
                        on_stdin=on_stdin)

                # multiple patches fix this bug if successful_patches > 1
                # for strcpy, etc, we are traversing from the last to first
                # in trace
                for j, (file_to_patch,
                        successful_patch) in enumerate(successful_patches):
                    print "SUCCESSFUL PATCH %s\n" % successful_patch.text
                    if DUMP_ALL_PATCHES:
                        dump_patch(patch_path + '_' + str(i) + '_' + str(j),
                                   successful_patch.text)
                    else:
                        # return the first one
                        dump_patch(patch_path, successful_patch.text)
                        os.system('./9-rebuild.sh > /dev/null')
                        return True

        if len(successful_patches) > 0:
            success = True

        os.system('./9-rebuild.sh > /dev/null')
        return success
示例#3
0
        rewrite_template = \
"""
// ROOIBOS START
memcpy(:[1], :[2], 1);
// ROOIBOS END
"""
    else:
        print "Unknown bug kind %s" % bug_kind
        assert(False)

    exit,ltrace_output = run_ltrace(binary, args, crash_file, ltrace_pattern)

    valid_patches = []

    # check last line if we crashed
    if crash_signal.did_crash(ltrace_output[-1]):

        mmap = dump_memory_map(binary, args, crash_file)
        # if we did, reverse the trace and start processing from the end
        ltrace_output = ltrace_output[::-1]
        patch_locations = process_ltrace(ltrace_output,mmap)

        # filter valid locations by regex
        patch_locations_tmp = []
        for patch_location in patch_locations:
            m = re.search('(.*):(.*)', patch_location)
            if m.group(1) and m.group(2):
                file_to_patch = m.group(1)
                line_num = m.group(2)
                line_num = int(line_num)
                patch_locations_tmp.append((file_to_patch,line_num))