Esempio n. 1
0
def calc(key):
    key = key.replace('-', '')
    assert len(key) == 32

    p = angr.Project('./libnative-lib.so')
    useless_func_addr = p.entry + 0x00050F00
    p.hook(useless_func_addr,
           angr.Hook(simuvex.SimProcedures['stubs']['ReturnUnconstrained']),
           kwargs={'resolves': 'nothing'})
    useless_func_addr = p.entry + 0x7F70
    p.hook(useless_func_addr,
           angr.Hook(simuvex.SimProcedures['stubs']['ReturnUnconstrained']),
           kwargs={'resolves': 'nothing'})
    useless_addr = p.entry + 0xA977
    redirect_addr = p.entry + 0xAA10
    # p.hook(useless_addr, angr.Hook(simuvex.SimProcedures['stubs']['Redirect'], redirect_to=redirect_addr), kwargs={'resolves': 'nothing'})
    # def go(state):
    #     state.regs.ip = redirect_addr
    #     print 'f**k', state.regs.ip
    # p.hook(useless_addr, angr.Hook(simuvex.SimProcedures['stubs']['UserHook'], user_func=go, length=2))

    start_addr = p.entry + 0xA41D
    aim_addr = p.entry + 0xAA50

    state = p.factory.blank_state(addr=start_addr)
    x = []
    for i in xrange(32):
        # x.append(state.se.BVS('x{}'.format(i), 8))
        x.append(state.se.BVV(key[i], 8))

    state.memory.store(state.regs.sp + 0x50,
                       0xAA000000,
                       endness=state.arch.memory_endness)
    for i in xrange(8):
        str_addr = 0xBB000000 + i * 0x100
        state.memory.store(0xAA000000 + i * 4,
                           str_addr,
                           endness=state.arch.memory_endness)
        state.memory.store(str_addr - 4, 4, endness=state.arch.memory_endness)
        for j in xrange(4):
            state.memory.store(str_addr + j,
                               x[i * 4 + j],
                               endness=state.arch.memory_endness)

    path = p.factory.path(state)
    pg = p.factory.path_group(path)
    ex = pg.explore(find=aim_addr)
    # pg.explore(find=p.entry + 0x00009BE0)

    s = ex.found[0].state
    seed = s.se.any_int(s.regs.eax)
    return seed
Esempio n. 2
0
def calc(key):
    key = key.replace('-', '')
    assert len(key) == 32

    p = angr.Project('./libnative-lib.so')
    useless_func_addr = p.entry + 0x00050F00
    p.hook(useless_func_addr,
           angr.Hook(simuvex.SimProcedures['stubs']['ReturnUnconstrained']),
           kwargs={'resolves': 'nothing'})

    start_addr = p.entry + 0x00009B93
    aim_addr = p.entry + 0x0000A1AA

    state = p.factory.blank_state(addr=start_addr)
    x = []
    for i in xrange(32):
        # x.append(state.se.BVS('x{}'.format(i), 8))
        x.append(state.se.BVV(key[i], 8))

    state.memory.store(state.regs.sp + 0x40,
                       0xAA000000,
                       endness=state.arch.memory_endness)
    state.memory.store(state.regs.bp + 0x10,
                       0xCC000000,
                       endness=state.arch.memory_endness)
    state.memory.store(state.regs.bp + 0x14,
                       0xDD000000,
                       endness=state.arch.memory_endness)
    state.memory.store(state.regs.bp + 0x18,
                       0xEE000000,
                       endness=state.arch.memory_endness)
    state.memory.store(state.regs.bp + 0x1c,
                       0xFF000000,
                       endness=state.arch.memory_endness)
    for i in xrange(8):
        str_addr = 0xBB000000 + i * 0x100
        state.memory.store(0xAA000000 + i * 4,
                           str_addr,
                           endness=state.arch.memory_endness)
        state.memory.store(str_addr - 4, 4, endness=state.arch.memory_endness)
        for j in xrange(4):
            state.memory.store(str_addr + j,
                               x[i * 4 + j],
                               endness=state.arch.memory_endness)

    path = p.factory.path(state)
    pg = p.factory.path_group(path)
    ex = pg.explore(find=aim_addr)
    # pg.explore(find=p.entry + 0x00009BE0)

    s = ex.found[0].state
    a1 = s.se.any_int(
        s.memory.load(0xCC000000, endness=state.arch.memory_endness))
    a2 = s.se.any_int(
        s.memory.load(0xDD000000, endness=state.arch.memory_endness))
    a3 = s.se.any_int(
        s.memory.load(0xEE000000, endness=state.arch.memory_endness))
    a6 = s.se.any_int(
        s.memory.load(0xFF000000, endness=state.arch.memory_endness))
    return a1, a2, a3, a6
Esempio n. 3
0
 def _hook_taint_procedures(self, project):
     self._hooks = {
         "scanf" : scanf_taint
     }
     for k, v in self._hooks.iteritems():
         project.hook_symbol(k, angr.Hook(v))
         v.taints = []
Esempio n. 4
0
def calc_one_byte(p, known_passwords, hook_func, start_addr, load_addr1,
                  load_addr2, cmp_flag_reg, cmp_addr):
    byte_pos = len(known_passwords)

    p.hook(load_addr1, angr.Hook(UserHook, user_func=hook_func, length=14))
    p.hook(load_addr2, angr.Hook(UserHook, user_func=hook_func, length=14))
    state = p.factory.blank_state(addr=start_addr)
    state, password = prepare_state(state, known_passwords)
    pg = p.factory.path_group(state, immutable=False)
    pg.step(4)
    pg.step(max_size=cmp_addr - load_addr2)

    s0 = pg.active[0].state.copy()
    s0.add_constraints(getattr(s0.regs, cmp_flag_reg) == 0x1)
    candidates = s0.se.any_n_int(password[byte_pos], 256)
    # assert len(candidates) == 1

    return chr(candidates[0])
Esempio n. 5
0
    def _try_summarize(self, f):
        l.debug('Attempting to hook: %s', f.name)

        if self._has_cycle(f):
            l.debug('Failed to hook: %s has cycles, skipping', f.name)
            return False

        if self._has_side_effect(f):
            l.debug('Failed to hook: %s has side effects, skipping', f.name)
            return False

        FHook = self._generate_hook(f)
        if FHook is None:
            l.debug('Failed to generate hook: %s', f.name)
            return False

        l.debug('Hook generated for: %s', f.name)
        self._is_summarized[f.addr] = angr.Hook(FHook)

        self._p.hook(f.addr, self._is_summarized[f.addr])
        return True
Esempio n. 6
0
def main():
    p = angr.Project('challenge-7.sys', load_options={'auto_load_libs': False})

    # Set a zero-length hook, so our function got executed before calling the
    # function tea_decrypt(0x100f0), and then we can keep executing the original
    # code. Thanks to this awesome design by @rhelmot!
    p.hook(0xadc31, angr.Hook(UserHook, user_func=before_tea_decrypt,
                              length=0))

    # Declare the prototype of the target function
    prototype = SimTypeFunction((SimTypeInt(False), ), SimTypeInt(False))
    # Initialize the function instance
    proc_big_68 = p.factory.callable(BIG_PROC,
                                     cc=p.factory.cc(func_ty=prototype),
                                     toc=None,
                                     concrete_only=True)
    # Call the function and get the final state
    proc_big_68.perform_call(0)
    state = proc_big_68.result_state
    # Load the string from memory
    return hex(state.se.any_int(state.memory.load(
        ARRAY_ADDRESS, 40)))[2:-1].decode('hex').strip('\0')
Esempio n. 7
0
def main():
    p = angr.Project('baby-re')

    win = 0x4028e9  # good
    fail = 0x402941  # fail
    main = 0x4025e7  # Address of main
    PASS_LEN = 13
    flag_addr = 0x7fffffffffeff98  # First rsi from scanf
    find = (win, )
    avoid = (fail, )

    def patch_scanf(state):
        print(state.regs.rsi)
        state.mem[state.regs.rsi:].char = state.se.BVS('c', 8)

    # IDA xrefs
    scanf_offsets = (0x4d, 0x85, 0xbd, 0xf5, 0x12d, 0x165, 0x19d, 0x1d5, 0x20d,
                     0x245, 0x27d, 0x2b5, 0x2ed)

    init = p.factory.blank_state(addr=main)

    # Patch scanfs (don't know how angr handles it)
    for offst in scanf_offsets:
        p.hook(main + offst,
               angr.Hook(UserHook, user_func=patch_scanf, length=5))

    pgp = p.factory.path_group(init)

    # Now stuff becomes interesting
    ex = pgp.explore(find=find, avoid=avoid)

    print(ex)
    s = ex.found[0].state
    flag = s.se.any_str(s.memory.load(flag_addr, 50))

    # The flag is 'Math is hard!'
    print("The flag is '{0}'".format(flag))
    return flag
Esempio n. 8
0
def get_possible_flags():
    # load the binary
    print '[*] loading the binary'
    p = angr.Project("whitehat_crypto400")

    # this is a statically-linked binary, and it's easer for angr if we use Python
    # summaries for the libc functions
    p.hook(0x4018B0,
           angr.Hook(simuvex.SimProcedures['libc.so.6']['__libc_start_main']))
    p.hook(0x422690, angr.Hook(simuvex.SimProcedures['libc.so.6']['memcpy']))
    p.hook(0x408F10, angr.Hook(simuvex.SimProcedures['libc.so.6']['puts']))

    # this is some anti-debugging initialization. It doesn't do much against angr,
    # but wastes time
    p.hook(0x401438,
           angr.Hook(simuvex.SimProcedures['stubs']['ReturnUnconstrained']),
           kwargs={'resolves': 'nothing'})

    # from playing with the binary, we can easily see that it requires strings of
    # length 8, so we'll hook the strlen calls and make sure we pass an 8-byte
    # string
    def hook_length(state):
        state.regs.rax = 8

    p.hook(0x40168e, angr.Hook(UserHook, user_func=hook_length, length=5))
    p.hook(0x4016BE, angr.Hook(UserHook, user_func=hook_length, length=5))

    # here, we create the initial state to start execution. argv[1] is our 8-byte
    # string, and we add an angr option to gracefully handle unsupported syscalls
    arg1 = claripy.BVS('arg1', 8 * 8)
    initial_state = p.factory.entry_state(
        args=["crypto400", arg1], add_options={"BYPASS_UNSUPPORTED_SYSCALL"})

    # and let's add a constraint that none of the string's bytes can be null
    for b in arg1.chop(8):
        initial_state.add_constraints(b != 0)

    # PathGroups are a basic building block of the symbolic execution engine. They
    # track a group of paths as the binary is executed, and allows for easier
    # management, pruning, and so forth of those paths
    pg = p.factory.path_group(initial_state, immutable=False)

    # here, we get to stage 2 using the PathGroup's find() functionality. This
    # executes until at least one path reaches the specified address, and can
    # discard paths that hit certain other addresses.
    print '[*] executing'
    pg.explore(find=0x4016A3).unstash(from_stash='found', to_stash='active')
    pg.explore(find=0x4016B7, avoid=[0x4017D6, 0x401699,
                                     0x40167D]).unstash(from_stash='found',
                                                        to_stash='active')
    pg.explore(find=0x4017CF, avoid=[0x4017D6, 0x401699,
                                     0x40167D]).unstash(from_stash='found',
                                                        to_stash='active')
    pg.explore(find=0x401825, avoid=[0x401811])

    # now, we're at stage 2. stage 2 is too complex for a SAT solver to solve, but
    # stage1 has narrowed down the keyspace enough to brute-force the rest, so
    # let's get the possible values for the passphrase and brute-force the rest.
    s = pg.found[0].state

    # to reduce the keyspace further, let's assume the bytes are printable
    for i in range(8):
        b = s.memory.load(0x6C4B20 + i, 1)
        s.add_constraints(b >= 0x21, b <= 0x7e)

    # now get the possible values. One caveat is that getting all possible values
    # for all 8 bytes pushes a lot of complexity to the SAT solver, and it chokes.
    # To avoid this, we're going to get the solutions to 2 bytes at a time, and
    # brute force the combinations.
    possible_values = [
        s.se.any_n_str(s.memory.load(0x6C4B20 + i, 2), 65536)
        for i in range(0, 8, 2)
    ]
    possibilities = tuple(itertools.product(*possible_values))
    return possibilities
Esempio n. 9
0
def hook_simproc(proj, addr_fr, addr_to, proc_type, libname='libc.so.6'):
    """ Hook a given function using a predesignated SimProcedure.
    """
    proj.hook(addr_fr,
              angr.Hook(simuvex.SimProcedures[libname][proc_type]),
              length=addr_to - addr_fr)
Esempio n. 10
0
    def setup_argv_atoi_constraints(self, state, atoi_added_constraints):
        # If we have string-array-atoi (argv-like) constraints, build the pointers
        # and the symbolic string
        atoi_special_addrs = dict(
        )  # looks like: {0xDEADBEEF: (operator.eq, 0)}
        need_to_hook_atoi = False
        if self.ida_func.startEA in self.plugin.extra_constraints:
            con_tuples = self.plugin.extra_constraints[self.ida_func.startEA]
            ctr = 0
            for (opr1, op, opr2) in con_tuples:
                if opr1[0] == 5:  # the string-array-atoi type
                    need_to_hook_atoi = True
                    (arr_addr, arr_idx) = opr1[1]

                    # Get AST for right operand
                    if opr2[0] == 0:
                        ast2 = state.memory.load(opr2[1]).reversed
                    elif opr2[0] == 2:
                        ast2 = getattr(state.regs, opr2[1].lower())
                    elif opr2[0] == 3:
                        ast2 = claripy.BVV(opr2[1], self.plugin.bitness)
                    else:
                        continue  # TODO: invalid right operand, show error

                    free_mem_addr = UNUSED_MEMORY_ADDR  # TODO: unused memory location, declare somewhere else

                    # Store (free_mem_addr - arr_idx * wordsize) at (arr_addr)
                    would_be_arr_base_addr = free_mem_addr - arr_idx * (
                        self.plugin.bitness / 8)
                    state.memory.store(
                        arr_addr,
                        claripy.BVV(would_be_arr_base_addr,
                                    self.plugin.bitness).reversed)

                    # Create a magic constant for my_atoi to detect.
                    str_addr = 0xDEADBEEF + ctr
                    ctr += 1

                    # Store a pointer to (str_addr) at (free_mem_addr)
                    state.memory.store(
                        free_mem_addr,
                        claripy.BVV(str_addr, self.plugin.bitness).reversed)

                    # Add it to the dict for my_atoi to see
                    atoi_special_addrs[str_addr] = (op, ast2)

                    # Make the memory at (free_mem_addr + wordsize) symbolic: our actual string
                    #st.memory.make_symbolic('user_constr_{}'.format(arr_idx), str_addr, 8 * len(opr1[1]))

                    self.log_signal.emit("arr_addr = {:X}".format(arr_addr))
                    self.log_signal.emit(
                        "would_be_arr_base_addr = {:X}".format(
                            would_be_arr_base_addr))
                    self.log_signal.emit(
                        "free_mem_addr = {:X}".format(free_mem_addr))

        if need_to_hook_atoi:
            # Custom version of the default atoi SimProcedure
            class my_atoi(simuvex.SimProcedure):
                def run(self, s, special_addrs=None, added_constraints=None):
                    self.argument_types = {0: self.ty_ptr(SimTypeString())}
                    self.return_type = SimTypeInt(self.state.arch, True)

                    res_symb_var = claripy.BVS('atoi_ret',
                                               self.state.arch.bits)

                    # If the argument is a special constrained variable
                    s_val = self.state.se.any_int(s)
                    if s.concrete and s_val in special_addrs:
                        print(
                            "Got a special memory addr: {:X}\n".format(s_val))
                        # Grab the operator and right operand
                        (op, r_opr) = special_addrs[s_val]

                        # Add the constraint of: (return_val `op` r_opr)
                        print("Adding claripy_op_mapping[{}]({}, {})\n".format(
                            op, res_symb_var, r_opr))
                        added_constraints.append(claripy_op_mapping[op](
                            res_symb_var, r_opr))
                    return res_symb_var

            self.plugin.angr_proj.hook_symbol(
                'atoi',
                angr.Hook(my_atoi,
                          special_addrs=atoi_special_addrs,
                          added_constraints=atoi_added_constraints))
Esempio n. 11
0
    def _linux_prepare_paths(self):
        '''
        prepare the initial paths for Linux binaries
        '''

        # Only requesting custom base if this is a PIE
        if self._p.loader.main_bin.pic:
            project = angr.Project(
                self.binary,
                load_options={
                    'main_opts': {
                        'custom_base_addr': self.qemu_base_addr
                    }
                },
                exclude_sim_procedures_list=self.exclude_sim_procedures_list)
        else:
            project = angr.Project(
                self.binary,
                exclude_sim_procedures_list=self.exclude_sim_procedures_list)
            known_libc_functions = get_known_libc_functionaddr(self.binary)
            #known_libc_functions_new = {}
            #for key,val in known_libc_functions.items():
            #known_libc_functions_new[val] = key
            simfuncs = simuvex.procedures.SimProcedures[
                'libc.so.6']  #changed for RHG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1
            #func_to_hook = {}
            #func_to_hook = {'memcpy':0x0805CA00,'scanf':0x0804F1F0,'printf':0x0804F190,'strlen':0x0805b800,'__libc_start_main':0x08048eb0}
            for addr, name in known_libc_functions.items():
                if name in simfuncs:
                    project.hook(
                        int(addr, 16),
                        angr.Hook(simuvex.SimProcedures['libc.so.6'][name]))

        if not self.crash_mode:
            self._set_linux_simprocedures(project)

        self._set_hooks(project)

        # fix stdin to the size of the input being traced
        fs = {
            '/dev/stdin':
            simuvex.storage.file.SimFile("/dev/stdin",
                                         "r",
                                         size=self.input_max_size)
        }

        options = set()
        options.add(so.CGC_ZERO_FILL_UNCONSTRAINED_MEMORY)
        options.add(so.BYPASS_UNSUPPORTED_SYSCALL)
        options.add(so.REPLACEMENT_SOLVER)
        options.add(so.UNICORN)
        options.add(so.UNICORN_HANDLE_TRANSMIT_SYSCALL)
        if self.crash_mode:
            options.add(so.TRACK_ACTION_HISTORY)

        self.remove_options |= so.simplification
        self.add_options |= options
        entry_state = project.factory.full_init_state(
            fs=fs,
            concrete_fs=True,
            chroot=self.chroot,
            add_options=self.add_options,
            remove_options=self.remove_options,
            args=self.argv)

        if self.preconstrain_input:
            self._preconstrain_state(entry_state)

        # increase size of libc limits
        entry_state.libc.buf_symbolic_bytes = 1024
        entry_state.libc.max_str_len = 1024

        pg = project.factory.path_group(entry_state,
                                        immutable=True,
                                        save_unsat=True,
                                        hierarchy=False,
                                        save_unconstrained=self.crash_mode)

        # Step forward until we catch up with QEMU
        if pg.active[0].addr != self.trace[0]:
            pg = pg.explore(find=project.entry)
            pg = pg.drop(stash="unsat")
            pg = pg.unstash(from_stash="found", to_stash="active")

        # don't step here, because unlike CGC we aren't going to be starting
        # anywhere but the entry point
        return pg
Esempio n. 12
0
    def run(self):
        print("Jumped into Hook :)")
        return 0x30


#Input 38 Chars long
#input_size = 0x26
input_size = 38

find_addr = 0x400cae

b = angr.Project("./antidebug")

b.hook(0x4008cd, fixpid, length=5)
b.hook(0x4006c0,
       angr.Hook(simuvex.SimProcedures['stubs']['ReturnUnconstrained']),
       kwargs={'resolves': 'nothing'})

argv1 = angr.claripy.BVS("argv1", input_size * 8)

#initial_state = b.factory.full_init_state(args=["./antidebug", argv1], add_options={"BYPASS_UNSUPPORTED_SYSCALL"}, add_options=simuvex.o.unicorn, remove_options={simuvex.o.LAZY_SOLVES})
initial_state = b.factory.entry_state(
    args=["./antidebug", argv1], add_options={"BYPASS_UNSUPPORTED_SYSCALL"})

for byte in argv1.chop(8):
    initial_state.add_constraints(byte != '\x00')  # null
    initial_state.add_constraints(byte >= ' ')  # '\x20'
    initial_state.add_constraints(byte <= '~')  # '\x7e'

#initial_state.add_constraints(argv1.chop(8)[38] == '\x00')