def _op_float_op_just_low(self, args): chopped = [arg[(self._vector_size - 1):0].raw_to_fp() for arg in args] result = getattr(claripy, 'fp' + self._generic_name)(claripy.fp.RM.default(), *chopped).to_bv() return claripy.Concat(args[0][(args[0].length - 1):self._vector_size], result)
def raw_simple_merging(solver_type): s1 = solver_type() s2 = solver_type() w = claripy.BVS("w", 8) x = claripy.BVS("x", 8) y = claripy.BVS("y", 8) z = claripy.BVS("z", 8) m = claripy.BVS("m", 8) s1.add([x == 1, y == 10]) s2.add([x == 2, z == 20, w == 5]) _, sm = s1.merge([s2], m, [ 0, 1 ]) nose.tools.assert_equal(s1.eval(x, 1), (1,)) nose.tools.assert_equal(s2.eval(x, 1), (2,)) sm1 = sm.branch() sm1.add(x == 1) nose.tools.assert_equal(sm1.eval(x, 1), (1,)) nose.tools.assert_equal(sm1.eval(y, 1), (10,)) nose.tools.assert_equal(sm1.eval(z, 1), (0,)) nose.tools.assert_equal(sm1.eval(w, 1), (0,)) sm2 = sm.branch() sm2.add(x == 2) nose.tools.assert_equal(sm2.eval(x, 1), (2,)) nose.tools.assert_equal(sm2.eval(y, 1), (0,)) nose.tools.assert_equal(sm2.eval(z, 1), (20,)) nose.tools.assert_equal(sm2.eval(w, 1), (5,)) sm1 = sm.branch() sm1.add(m == 0) nose.tools.assert_equal(sm1.eval(x, 1), (1,)) nose.tools.assert_equal(sm1.eval(y, 1), (10,)) nose.tools.assert_equal(sm1.eval(z, 1), (0,)) nose.tools.assert_equal(sm1.eval(w, 1), (0,)) sm2 = sm.branch() sm2.add(m == 1) nose.tools.assert_equal(sm2.eval(x, 1), (2,)) nose.tools.assert_equal(sm2.eval(y, 1), (0,)) nose.tools.assert_equal(sm2.eval(z, 1), (20,)) nose.tools.assert_equal(sm2.eval(w, 1), (5,)) m2 = claripy.BVS("m2", 32) _, smm = sm1.merge([sm2], m2, [0, 1]) smm_1 = smm.branch() smm_1.add(x == 1) nose.tools.assert_equal(smm_1.eval(x, 1), (1,)) nose.tools.assert_equal(smm_1.eval(y, 1), (10,)) nose.tools.assert_equal(smm_1.eval(z, 1), (0,)) nose.tools.assert_equal(smm_1.eval(w, 1), (0,)) smm_2 = smm.branch() smm_2.add(m == 1) nose.tools.assert_equal(smm_2.eval(x, 1), (2,)) nose.tools.assert_equal(smm_2.eval(y, 1), (0,)) nose.tools.assert_equal(smm_2.eval(z, 1), (20,)) nose.tools.assert_equal(smm_2.eval(w, 1), (5,)) so = solver_type() so.add(w == 0) sa = so.branch() sb = so.branch() sa.add(x == 1) sb.add(x == 2) _, sm = sa.merge([sb], m, [0, 1]) smc = sm.branch() smd = sm.branch() smc.add(y == 3) smd.add(y == 4) _, smm = smc.merge([smd], m2, [0, 1]) wxy = claripy.Concat(w, x, y) smm_1 = smm.branch() smm_1.add(wxy == 0x000103) nose.tools.assert_true(smm_1.satisfiable()) smm_1 = smm.branch() smm_1.add(wxy == 0x000104) nose.tools.assert_true(smm_1.satisfiable()) smm_1 = smm.branch() smm_1.add(wxy == 0x000203) nose.tools.assert_true(smm_1.satisfiable()) smm_1 = smm.branch() smm_1.add(wxy == 0x000204) nose.tools.assert_true(smm_1.satisfiable()) smm_1 = smm.branch() smm_1.add(wxy != 0x000103) smm_1.add(wxy != 0x000104) smm_1.add(wxy != 0x000203) smm_1.add(wxy != 0x000204) nose.tools.assert_false(smm_1.satisfiable())
def get_value(self, state, endness=None, **kwargs): if endness is None: endness = state.arch.memory_endness vals = [] for loc in self.locations: vals.append(loc.get_value(state, endness, **kwargs)) return claripy.Concat(*vals)
import angr import claripy #Solve just like the example given in class proj = angr.Project("./cracksymb") chars = [claripy.BVS(f'c%d' % i, 8) for i in range(0x17)] input_str = claripy.Concat(*chars + [claripy.BVV(b'\n')]) # + \n initial_state = proj.factory.entry_state(stdin=input_str, add_options={angr.options.LAZY_SOLVES} ) # use as stdin for c in chars: # make sure all chars are printable initial_state.solver.add(c >= 0x20, c <= 0x7e) simgr = proj.factory.simulation_manager(initial_state) simgr.explore(find=0x4033c2) # flag correct if simgr.found: print(simgr.found[0].posix.dumps(0)) #flag{l1n34r_syst3ms_<3}
def state_entry(self, args=None, env=None, argc=None, **kwargs): state = super(SimWindows, self).state_entry(**kwargs) if args is None: args = [] if env is None: env = {} # Prepare argc if argc is None: argc = claripy.BVV(len(args), state.arch.bits) elif type(argc) in (int, long): # pylint: disable=unidiomatic-typecheck argc = claripy.BVV(argc, state.arch.bits) # Make string table for args and env table = StringTableSpec() table.append_args(args) table.append_env(env) # calculate full command line, since this is windows and that's how everything works cmdline = claripy.BVV(0, 0) for arg in args: if cmdline.length != 0: cmdline = cmdline.concat(claripy.BVV(' ')) if type(arg) is str: if '"' in arg or '\0' in arg: raise AngrSimOSError("Can't handle windows args with quotes or nulls in them") arg = claripy.BVV(arg) elif isinstance(arg, claripy.ast.BV): for byte in arg.chop(8): state.solver.add(byte != claripy.BVV('"')) state.solver.add(byte != claripy.BVV(0, 8)) else: raise TypeError("Argument must be str or bitvector") cmdline = cmdline.concat(claripy.BVV('"'), arg, claripy.BVV('"')) cmdline = cmdline.concat(claripy.BVV(0, 8)) wcmdline = claripy.Concat(*(x.concat(0, 8) for x in cmdline.chop(8))) if not state.satisfiable(): raise AngrSimOSError("Can't handle windows args with quotes or nulls in them") # Dump the table onto the stack, calculate pointers to args, env stack_ptr = state.regs.sp stack_ptr -= 16 state.memory.store(stack_ptr, claripy.BVV(0, 8*16)) stack_ptr -= cmdline.length / 8 state.memory.store(stack_ptr, cmdline) state.mem[self.acmdln_ptr].long = stack_ptr stack_ptr -= wcmdline.length / 8 state.memory.store(stack_ptr, wcmdline) state.mem[self.wcmdln_ptr].long = stack_ptr argv = table.dump(state, stack_ptr) envp = argv + ((len(args) + 1) * state.arch.bytes) # Put argc on stack and fix the stack pointer newsp = argv - state.arch.bytes state.memory.store(newsp, argc, endness=state.arch.memory_endness) state.regs.sp = newsp # store argc argv envp in the posix plugin state.posix.argv = argv state.posix.argc = argc state.posix.environ = envp state.regs.sp = state.regs.sp - 0x80 # give us some stack space to work with # fake return address from entry point return_addr = self.return_deadend kernel32 = self.project.loader.shared_objects.get('kernel32.dll', None) if kernel32: # some programs will use the return address from start to find the kernel32 base return_addr = kernel32.get_symbol('ExitProcess').rebased_addr if state.arch.name == 'X86': state.mem[state.regs.sp].dword = return_addr # first argument appears to be PEB tib_addr = state.regs.fs.concat(state.solver.BVV(0, 16)) peb_addr = state.mem[tib_addr + 0x30].dword.resolved state.mem[state.regs.sp + 4].dword = peb_addr return state
def _op_generic_GetMSBs(self, args): size = self._vector_count * self._vector_size bits = [claripy.Extract(i, i, args[0]) for i in range(size - 1, 6, -8)] return claripy.Concat(*bits)
def _op_generic_CatOddLanes(self, args): vec_0 = args[0].chop(self._vector_size) vec_1 = args[1].chop(self._vector_size) return claripy.Concat(*(vec_0[::2] + vec_1[::2]))
flag_addr = p.loader.find_symbol("flag").rebased_addr print("Flag @", hex(flag_addr)) flag_size = 0xd # use unicorn for faster simulation init_state = p.factory.entry_state(add_options=angr.options.unicorn) # setup symbolic memory for our flag .. flag = [claripy.BVS("flag_%d" % i, 8) for i in range(flag_size)] # .. add some constraints to enforce ASCII characters .. for c in flag: init_state.solver.add(c < 0x7f) init_state.solver.add(c > 0x20) flag = claripy.Concat(*flag) # .. and store it into the state init_state.memory.store(flag_addr, flag) # run the simulation until completion sm = p.factory.simulation_manager(init_state) sm.run() final_state = sm.deadended[0] # enforce exit code final_state.solver.add(final_state.regs.dil == 0) result = final_state.solver.eval(flag, cast_to=bytes) print("The flag is", result)
def test_expression(): bc = claripy.backends.concrete e = claripy.BVV(0x01020304, 32) nose.tools.assert_equal(len(e), 32) r = e.reversed nose.tools.assert_equal(bc.convert(r), 0x04030201) nose.tools.assert_equal(len(r), 32) nose.tools.assert_equal([ bc.convert(i) for i in r.chop(8) ], [ 4, 3, 2, 1 ] ) e1 = r[31:24] nose.tools.assert_equal(bc.convert(e1), 0x04) nose.tools.assert_equal(len(e1), 8) nose.tools.assert_equal(bc.convert(e1[2]), 1) nose.tools.assert_equal(bc.convert(e1[1]), 0) ee1 = e1.zero_extend(8) nose.tools.assert_equal(bc.convert(ee1), 0x0004) nose.tools.assert_equal(len(ee1), 16) ee1 = claripy.BVV(0xfe, 8).sign_extend(8) nose.tools.assert_equal(bc.convert(ee1), 0xfffe) nose.tools.assert_equal(len(ee1), 16) xe1 = [ bc.convert(i) for i in e1.chop(1) ] nose.tools.assert_equal(xe1, [ 0, 0, 0, 0, 0, 1, 0, 0 ]) a = claripy.BVV(1, 1) nose.tools.assert_equal(bc.convert(a+a), 2) x = claripy.BVV(1, 32) nose.tools.assert_equal(x.length, 32) y = claripy.LShR(x, 10) nose.tools.assert_equal(y.length, 32) r = claripy.BVV(0x01020304, 32) rr = r.reversed rrr = rr.reversed #nose.tools.assert_is(bc.convert(r), bc.convert(rrr)) #nose.tools.assert_is(type(bc.convert(rr)), claripy.A) nose.tools.assert_equal(bc.convert(rr), 0x04030201) nose.tools.assert_is(r.concat(rr), claripy.Concat(r, rr)) rsum = r+rr nose.tools.assert_equal(bc.convert(rsum), 0x05050505) r = claripy.BVS('x', 32) rr = r.reversed rrr = rr.reversed nose.tools.assert_is(r, rrr) # test identity nose.tools.assert_is(r, rrr) nose.tools.assert_is_not(r, rr) ii = claripy.BVS('ii', 32) ij = claripy.BVS('ij', 32) nose.tools.assert_is(ii, ii) nose.tools.assert_is_not(ii, ij) si = claripy.SI(bits=32, stride=2, lower_bound=20, upper_bound=100) sj = claripy.SI(bits=32, stride=2, lower_bound=10, upper_bound=10) sk = claripy.SI(bits=32, stride=2, lower_bound=20, upper_bound=100) nose.tools.assert_true(claripy.backends.vsa.identical(si, si)) nose.tools.assert_false(claripy.backends.vsa.identical(si, sj)) nose.tools.assert_true(claripy.backends.vsa.identical(si, sk)) nose.tools.assert_is_not(si, sj) nose.tools.assert_is_not(sj, sk) nose.tools.assert_is_not(sk, si) # test hash cache nose.tools.assert_is(a+a, a+a) # test replacement old = claripy.BVS('old', 32, explicit_name=True) new = claripy.BVS('new', 32, explicit_name=True) ooo = claripy.BVV(0, 32) old_formula = claripy.If((old + 1)%256 == 0, old+10, old+20) print old_formula.dbg_repr() new_formula = old_formula.replace(old, new) print new_formula.dbg_repr() ooo_formula = new_formula.replace(new, ooo) print ooo_formula.dbg_repr() nose.tools.assert_not_equal(hash(old_formula), hash(new_formula)) nose.tools.assert_not_equal(hash(old_formula), hash(ooo_formula)) nose.tools.assert_not_equal(hash(new_formula), hash(ooo_formula)) nose.tools.assert_equal(old_formula.variables, { 'old' }) nose.tools.assert_equal(new_formula.variables, { 'new' }) nose.tools.assert_equal(ooo_formula.variables, ooo.variables) nose.tools.assert_true(old_formula.symbolic) nose.tools.assert_true(new_formula.symbolic) nose.tools.assert_true(new_formula.symbolic) nose.tools.assert_equal(str(old_formula).replace('old', 'new'), str(new_formula)) nose.tools.assert_equal(bc.convert(ooo_formula), 20) # test dict replacement old = claripy.BVS('old', 32, explicit_name=True) new = claripy.BVS('new', 32, explicit_name=True) c = (old + 10) - (old + 20) d = (old + 1) - (old + 2) cr = c.replace_dict({(old+10).cache_key: (old+1), (old+20).cache_key: (old+2)}) nose.tools.assert_is(cr, d) # test AST collapse s = claripy.SI(bits=32, stride=0, lower_bound=10, upper_bound=10) b = claripy.BVV(20, 32) sb = s+b nose.tools.assert_is_instance(sb.args[0], claripy.ast.Base) bb = b+b # this was broken previously -- it was checking if type(bb.args[0]) == A, # and it wasn't, but was instead a subclass. leaving this out for now # nose.tools.assert_not_is_instance(bb.args[0], claripy.ast.Base) # ss = s+s # (see above) # nose.tools.assert_not_is_instance(ss.args[0], claripy.ast.Base) sob = s|b # for now, this is collapsed. Presumably, Fish will make it not collapse at some point nose.tools.assert_is_instance(sob.args[0], claripy.ast.Base) # make sure the AST collapses for delayed ops like reversing rb = b.reversed #nose.tools.assert_is_instance(rb.args[0], claripy.ast.Base) # TODO: Properly delay reversing: should not be eager nose.tools.assert_is_not(rb, bb) nose.tools.assert_is(rb, rb) # test some alternate bvv creation methods nose.tools.assert_is(claripy.BVV('AAAA'), claripy.BVV(0x41414141, 32)) nose.tools.assert_is(claripy.BVV('AAAA', 32), claripy.BVV(0x41414141, 32)) nose.tools.assert_is(claripy.BVV('AB'), claripy.BVV(0x4142, 16)) nose.tools.assert_is(claripy.BVV('AB', 16), claripy.BVV(0x4142, 16)) nose.tools.assert_raises(claripy.errors.ClaripyValueError, claripy.BVV, 'AB', 8)
def string_to_ast(string): return claripy.Concat(*(claripy.BVV(ord(c), 8) for c in string))
if found: return found[0] raise Exception("No address found for function : " + function_name) binary = str( os.path.join(os.path.dirname(os.path.abspath(__file__)), "sub1or2")) project = angr.Project(binary, auto_load_libs=False) cfg = project.analyses.CFGFast(normalize=True) function_name = "sub1or2" start_address = get_function_address(cfg, function_name) entry_state = project.factory.entry_state() symbolic_integer = claripy.BVS("y_intle:32", 32) symbolic_integer_le = claripy.Concat(claripy.Extract(7, 0, symbolic_integer), claripy.Extract(15, 8, symbolic_integer), claripy.Extract(23, 16, symbolic_integer), claripy.Extract(31, 24, symbolic_integer)) print("vex for 0x40053b: ") project.factory.block(0x40053b).vex.pp() call_state = project.factory.call_state(start_address, symbolic_integer_le, ret_addr=0x0) simulation_manager = project.factory.simulation_manager(call_state) while simulation_manager.active: for i in range(0, len(simulation_manager.active)): state = simulation_manager.active[i] memaddr4 = state.solver.eval(state.regs.rbp) - 4 memval4 = state.memory.load(memaddr4, 4, endness=archinfo.Endness.LE) if state.addr == 0x400537: print("after the first decrement of x we have y:")
logging.getLogger('angr').setLevel(logging.INFO) # num_keys = get_arg() proj = angr.Project( program_name, main_opts={"base_addr": 0}, # PIE binary ) # create an array of bitvectors so that the value of each can easily be # constrained to the range of printable ASCII characters key_bytes = [ claripy.BVS("byte_%d" % i, 8) for i in range(num_bytes_of_flag * 8) ] key_bytes_AST = claripy.Concat(*key_bytes) # we want to generate valid keys, so a symbolic variable is passed to # the state rather than a concrete value state = proj.factory.full_init_state(args=["./" + program_name], add_options=angr.options.unicorn) # impose constraints on bitvectors the symbolic key is composed of for byte in key_bytes: state.solver.add(byte >= 0x21, byte <= 0x7e) sm = proj.factory.simulation_manager(state) # find path to message indicating key was correct sm.explore(find=find_address)
buf[0x6060] = 21 start = 0 while True: start = buf.find(b'\xBF\x94\x50\x40\x00', start) if start == -1: break AVOID.append(start + 0x400000) start += len(b'\xBF\x94\x50\x40\x00') with open('./angrybird_patch', 'wb') as f: f.write(buf) if __name__ == "__main__": patch_and_anaylze() proj = angr.Project('./angrybird_patch', load_options={'auto_load_libs': False}) flag = claripy.Concat(claripy.BVV(0, 8 * (20)), claripy.BVV(b'\n')) state = proj.factory.blank_state(addr=0x4007B8) simgr = proj.factory.simulation_manager(state) print(AVOID) print(FIND) simgr.explore(find=FIND, avoid=AVOID) found = simgr.found[0] print(found.posix.dumps(0)) print(found.state.posix.dumps(1))
def _op_generic_InterleaveLO(self, args): s = self._vector_size c = self._vector_count dst_vector = [ args[0][(i+1)*s-1:i*s] for i in xrange(c/2) ] src_vector = [ args[1][(i+1)*s-1:i*s] for i in xrange(c/2) ] return claripy.Concat(*itertools.chain.from_iterable(reversed(zip(dst_vector, src_vector))))
def _op_vector_mapped(self, args): chopped_args = ([claripy.Extract((i + 1) * self._vector_size - 1, i * self._vector_size, a) for a in args] for i in reversed(range(self._vector_count))) return claripy.Concat(*(self._op_mapped(ca) for ca in chopped_args))
def state_blank(self, flag_page=None, allocate_stack_page_count=0x100, **kwargs): """ :param flag_page: Flag page content, either a string or a list of BV8s :param allocate_stack_page_count: Number of pages to pre-allocate for stack """ # default stack as specified in the cgc abi if kwargs.get('stack_end', None) is None: kwargs['stack_end'] = 0xbaaab000 if kwargs.get('stack_size', None) is None: kwargs['stack_size'] = 1024 * 1024 * 8 s = super(SimCGC, self).state_blank(**kwargs) # pylint:disable=invalid-name # pre-grow the stack. unsure if this is strictly required or just a hack around a compiler bug if hasattr(s.memory, 'allocate_stack_pages'): s.memory.allocate_stack_pages(kwargs['stack_end'] - 1, allocate_stack_page_count * 0x1000) # Map the flag page if o.ABSTRACT_MEMORY not in s.options: s.memory.map_region(0x4347c000, 4096, 1) # Create the CGC plugin s.get_plugin('cgc') # Set maximum bytes a single receive syscall should read s.cgc.max_receive_size = kwargs.get("cgc_max_recv_size", 0) # Set up the flag page if flag_page is None: flag_page = [ s.solver.BVS("cgc-flag-byte-%d" % i, 8, key=('flag', i), eternal=True) for i in range(0x1000) ] elif type(flag_page) is bytes: flag_page = [s.solver.BVV(c, 8) for c in flag_page] elif type(flag_page) is list: pass else: raise ValueError( "Bad flag page: expected None, bytestring, or list, but got %s" % type(flag_page)) s.cgc.flag_bytes = flag_page if s.mode != 'static': s.memory.store(0x4347c000, claripy.Concat(*s.cgc.flag_bytes), priv=True) # set up the address for concrete transmits and receive s.unicorn.cgc_transmit_addr = self.syscall_from_number(2).addr s.unicorn.cgc_receive_addr = self.syscall_from_number(3).addr s.unicorn.cgc_random_addr = self.syscall_from_number(7).addr s.libc.max_str_len = 1000000 s.libc.max_strtol_len = 10 s.libc.max_memcpy_size = 0x100000 s.libc.max_buffer_size = 0x100000 return s
def _op_concat(self, args): return claripy.Concat(*args)
def _prepare_chall_resp(self, state): # now we need to find the challenge response stuff # first break constraints at And's constraints = [] for c in state.solver.constraints: if c.op == "And": constraints.extend(c.args) else: constraints.append(c) # filter for possible flag constraints filtered_constraints = [] for c in constraints: if any( v.startswith("cgc-flag") or v.startswith("random") for v in c.variables): filtered_constraints.append(c) self.filter_uncontrolled_constraints(state) # now separate into constraints we can probably control, and those we can't controllable_constraints = [] uncontrollable_constraints = [] if not state.has_plugin("chall_resp_info"): # register a blank one state.register_plugin("chall_resp_info", ChallRespInfo()) chall_resp_info = state.get_plugin("chall_resp_info") for c in filtered_constraints: if any(v.startswith("aeg_stdin") for v in c.variables) or \ any(v in chall_resp_info.vars_we_added for v in c.variables): controllable_constraints.append(c) elif any(v.startswith("output_var") for v in c.variables): # an output like a leak pass else: # uncontrollable constraints will show up as zen constraints etc uncontrollable_constraints.append(c) if len(controllable_constraints) > 0: l.debug("Challenge response detected!") file_1 = state.posix.stdout stdout = file_1.load(0, file_1.size) stdout_len = state.solver.eval(file_1.size) stdout_bvs = [ claripy.BVS("file_stdout_%#x" % i, 8, explicit_name=True) for i in range(stdout_len) ] stdout_bv = claripy.Concat(*stdout_bvs) state.add_constraints(stdout == stdout_bv) # we call simplify to separate the contraints/dependencies state.solver.simplify() merged_solver = state.solver._solver._merged_solver_for( lst=[self._mem] + controllable_constraints) # todo here we can verify that there are actually stdout bytes here, otherwise we have little hope # add the important stdout vars to mem needed_vars = [] for bv in stdout_bvs: if len(bv.variables & merged_solver.variables) != 0: needed_vars.append(bv) # add the str_to_int vars and int_to_str vars for _, v in chall_resp_info.str_to_int_pairs: needed_vars.append(v) for v, _ in chall_resp_info.int_to_str_pairs: needed_vars.append(v) self._mem = claripy.Concat(self._mem, *needed_vars)
def _op_generic_InterleaveHI(self, args): s = self._vector_size c = self._vector_count left_vector = [ args[0][(i+1)*s-1:i*s] for i in range(c//2, c) ] right_vector = [ args[1][(i+1)*s-1:i*s] for i in range(c//2, c) ] return claripy.Concat(*itertools.chain.from_iterable(zip(reversed(left_vector), reversed(right_vector))))
import claripy import pdb arch = archinfo.ArchPPC32(archinfo.Endness.BE) s = angr.SimState(arch=arch, mode="symbolic") x = s.solver.BVS('x', 32, explicit_name=True) #code = bytes(bytearray.fromhex("3c601234")) # lis tyenv = pyvex.block.IRTypeEnv(arch, [ 'Ity_I32','Ity_I32','Ity_I32' ]) imark = pyvex.stmt.IMark(0x100, 4, 0) a = claripy.Concat( x[31:16], s.solver.BVV(0, 16)) c = pyvex.const.UN(a) constExpr = pyvex.expr.Const(c) wr = pyvex.stmt.WrTmp(1, constExpr) rd = pyvex.expr.RdTmp(1) put = pyvex.stmt.Put(rd, 28) advance = pyvex.stmt.Put(pyvex.expr.Const(pyvex.const.U32(0x104)), 1168) statements = [imark, wr, put, advance] nxt = pyvex.expr.Const(pyvex.const.U32(0x104)) irsb1 = pyvex.IRSB.from_py(tyenv, statements, nxt, 'Ijk_Boring', 0x100, arch)
def _compose_objects(cls, objects, size, endness, **kwargs): if endness == 'Iend_LE': objects = reversed(objects) return claripy.Concat(*objects)
p = angr.Project("i_can_count_8484ceff57cb99e3bdb3017f8c8a2467", auto_load_libs=False) # calculate all the addresses as they depend on the loading address CHECK_FLAG_ADDR = p.loader.find_symbol('check_flag').rebased_addr FLAG_BUF_ADDR = p.loader.find_symbol('flag_buf').rebased_addr PRINT_FLAG_ADDR = p.loader.main_object.mapped_base + 0x0000f87 WRONG_FLAG_ADDR = p.loader.main_object.mapped_base + 0x0000fae # create a state at the beginning of the check_flag function st = p.factory.blank_state(addr=CHECK_FLAG_ADDR) # create solvable variables for the flag characters flag_chars = [claripy.BVS('flag_%d' % i, 8) for i in range(0x13)] flag = claripy.Concat(*flag_chars) # flag characters can only be digits for k in flag_chars: st.solver.add(k >= ord('0')) st.solver.add(k <= ord('9')) # make the flag_buf memory depending on user input and solvable for i in range(len(flag_chars)): st.mem[FLAG_BUF_ADDR + i:].byte = flag_chars[i] sm = p.factory.simulation_manager(st) print("Calculating Flag") # try to find a solution that prints out the flag and does not return before
def test_some_vector_ops(): engine = HeavyVEXMixin(None) s = SimState(arch="AMD64") def translate(state, op, args): return engine._perform_vex_expr_Op(op, args) a = s.solver.BVV(0xFFFF0000000100020003000400050006, 128) b = s.solver.BVV(0x00020002000200020002000200020002, 128) calc_result = translate(s, "Iop_Sub16x8", (a, b)) correct_result = s.solver.BVV(0xFFFDFFFEFFFF00000001000200030004, 128) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_CmpEQ16x8", (a, b)) correct_result = s.solver.BVV(0x000000000000FFFF0000000000000000, 128) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_CmpEQ8x16", (a, b)) correct_result = s.solver.BVV(0x0000FF00FF00FFFFFF00FF00FF00FF00, 128) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_CmpGT16Sx8", (a, b)) correct_result = s.solver.BVV(0x0000000000000000FFFFFFFFFFFFFFFF, 128) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_CmpGT16Ux8", (a, b)) correct_result = s.solver.BVV(0xFFFF000000000000FFFFFFFFFFFFFFFF, 128) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_InterleaveLO16x8", (a, b)) correct_result = s.solver.BVV(0x00030002000400020005000200060002, 128) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_InterleaveLO8x16", (a, b)) correct_result = s.solver.BVV(0x00000302000004020000050200000602, 128) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_Min8Ux16", (a, b)) correct_result = s.solver.BVV(0x00020000000100020002000200020002, 128) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_Min8Sx16", (a, b)) correct_result = s.solver.BVV(0xFFFF0000000100020002000200020002, 128) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_QNarrowBin16Sto8Ux16", (a, b)) correct_result = s.solver.BVV(0x00000102030405060202020202020202, 128) assert s.solver.is_true(calc_result == correct_result) c = s.solver.BVV(0xFF008877, 32) d = s.solver.BVV(0x11111111, 32) calc_result = translate(s, "Iop_HAdd8Sx4", (c, d)) correct_result = s.solver.BVV(0x0808CC44, 32) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_QAdd8Sx4", (c, d)) correct_result = s.solver.BVV(0x1011997F, 32) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_QAdd8Ux4", (c, d)) correct_result = s.solver.BVV(0xFF119988, 32) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_QSub8Sx4", (c, d)) correct_result = s.solver.BVV(0xEEEF8066, 32) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_QSub8Ux4", (c, d)) correct_result = s.solver.BVV(0xEE007766, 32) assert s.solver.is_true(calc_result == correct_result) e = s.solver.BVV(0xFF00887766554433, 64) f = s.solver.BVV(0x0202000200020002, 64) calc_result = translate(s, "Iop_QNarrowBin16Sto8Ux8", (e, f)) correct_result = s.solver.BVV(0x0000FFFFFF020202, 64) assert s.solver.is_true(calc_result == correct_result) gg = claripy.BVV(0x111111112222222233333333FFFFFFFF, 128) h = claripy.BVV(0x1111111100000000FFFFFFFFFFFFFFFF, 128) calc_result = translate(s, "Iop_CmpEQ32Fx4", (gg, h)) correct_result = claripy.BVV(0xFFFFFFFF000000000000000000000000, 128) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_Clz32x4", (gg, )) correct_result = claripy.BVV(0x00000003000000020000000200000000, 128) assert s.solver.is_true(calc_result == correct_result) i = claripy.BVV(0x1001000000001000, 64) j = claripy.BVV(0x100000000000F000, 64) calc_result = translate(s, "Iop_Mull16Sx4", (i, j)) correct_result = claripy.BVV(0x10010000000000000000000FF000000, 128) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_Mull16Ux4", (i, j)) correct_result = claripy.BVV(0x100100000000000000000000F000000, 128) assert s.solver.is_true(calc_result == correct_result) k = claripy.BVV(0xE7, 8) ll = claripy.BVV(0x1234, 16) m = claripy.BVV(0x12345678, 32) calc_result = translate(s, "Iop_Dup8x8", (k, )) correct_result = claripy.BVV(0xE7E7E7E7E7E7E7E7, 64) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_Dup8x16", (k, )) correct_result = claripy.BVV(0xE7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7, 128) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_Dup16x4", (ll, )) correct_result = claripy.BVV(0x1234123412341234, 64) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_Dup16x8", (ll, )) correct_result = claripy.BVV(0x12341234123412341234123412341234, 128) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_Dup32x2", (m, )) correct_result = claripy.BVV(0x1234567812345678, 64) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_Dup32x4", (m, )) correct_result = claripy.BVV(0x12345678123456781234567812345678, 128) assert s.solver.is_true(calc_result == correct_result) n = claripy.BVV(0x0123456789ABCDEF, 64) o = claripy.BVV(0xAF, 8) p = claripy.BVV(0xDFEC, 16) q = claripy.BVV(0xBFCFDFEF, 32) r = claripy.BVV(0x0102030405060708, 64) ss = claripy.BVS("index", 8) # According to the source code of LibVex, the index is a U8 constant calc_result = translate(s, "Iop_GetElem8x8", (n, claripy.BVV(0, 8))) correct_result = claripy.BVV(0xEF, 8) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_GetElem8x8", (n, claripy.BVV(1, 8))) correct_result = claripy.BVV(0xCD, 8) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_GetElem8x8", (n, claripy.BVV(6, 8))) correct_result = claripy.BVV(0x23, 8) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_GetElem8x8", (n, claripy.BVV(7, 8))) correct_result = claripy.BVV(0x01, 8) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_GetElem16x4", (n, claripy.BVV(0, 8))) correct_result = claripy.BVV(0xCDEF, 16) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_GetElem16x4", (n, claripy.BVV(3, 8))) correct_result = claripy.BVV(0x0123, 16) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_GetElem32x2", (n, claripy.BVV(0, 8))) correct_result = claripy.BVV(0x89ABCDEF, 32) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_GetElem32x2", (n, claripy.BVV(1, 8))) correct_result = claripy.BVV(0x01234567, 32) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_SetElem8x8", (n, claripy.BVV(0, 8), o)) correct_result = claripy.BVV(0x0123456789ABCDAF, 64) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_SetElem8x8", (n, claripy.BVV(1, 8), o)) correct_result = claripy.BVV(0x0123456789ABAFEF, 64) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_SetElem8x8", (n, claripy.BVV(6, 8), o)) correct_result = claripy.BVV(0x01AF456789ABCDEF, 64) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_SetElem8x8", (n, claripy.BVV(7, 8), o)) correct_result = claripy.BVV(0xAF23456789ABCDEF, 64) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_SetElem16x4", (n, claripy.BVV(0, 8), p)) correct_result = claripy.BVV(0x0123456789ABDFEC, 64) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_SetElem16x4", (n, claripy.BVV(3, 8), p)) correct_result = claripy.BVV(0xDFEC456789ABCDEF, 64) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_SetElem32x2", (n, claripy.BVV(0, 8), q)) correct_result = claripy.BVV(0x01234567BFCFDFEF, 64) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_SetElem32x2", (n, claripy.BVV(1, 8), q)) correct_result = claripy.BVV(0xBFCFDFEF89ABCDEF, 64) assert s.solver.is_true(calc_result == correct_result) # Symbolic indexes calc_result = translate(ss, "Iop_GetElem8x8", (r, ss)) correct_result = claripy.If( ss == 7, claripy.BVV(0x01, 8), claripy.If( ss == 6, claripy.BVV(0x02, 8), claripy.If( ss == 5, claripy.BVV(0x03, 8), claripy.If( ss == 4, claripy.BVV(0x04, 8), claripy.If( ss == 3, claripy.BVV(0x05, 8), claripy.If( ss == 2, claripy.BVV(0x06, 8), claripy.If(ss == 1, claripy.BVV(0x07, 8), claripy.BVV(0x08, 8)), ), ), ), ), ), ) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_GetElem16x4", (r, ss)) correct_result = claripy.If( ss == 3, claripy.BVV(0x0102, 16), claripy.If( ss == 2, claripy.BVV(0x0304, 16), claripy.If(ss == 1, claripy.BVV(0x0506, 16), claripy.BVV(0x0708, 16)), ), ) assert s.solver.is_true(calc_result == correct_result) calc_result = translate(s, "Iop_GetElem32x2", (r, ss)) correct_result = claripy.If(ss == 1, claripy.BVV(0x01020304, 32), claripy.BVV(0x05060708, 32)) assert s.solver.is_true(calc_result == correct_result) r_slices = r.chop(8) calc_result = translate(s, "Iop_SetElem8x8", (r, ss, o)) correct_result = claripy.Concat( claripy.If(ss == 7, o, r_slices[0]), claripy.If(ss == 6, o, r_slices[1]), claripy.If(ss == 5, o, r_slices[2]), claripy.If(ss == 4, o, r_slices[3]), claripy.If(ss == 3, o, r_slices[4]), claripy.If(ss == 2, o, r_slices[5]), claripy.If(ss == 1, o, r_slices[6]), claripy.If(ss == 0, o, r_slices[7]), ) assert s.solver.is_true(calc_result == correct_result) r_slices = r.chop(16) calc_result = translate(s, "Iop_SetElem16x4", (r, ss, p)) correct_result = claripy.Concat( claripy.If(ss == 3, p, r_slices[0]), claripy.If(ss == 2, p, r_slices[1]), claripy.If(ss == 1, p, r_slices[2]), claripy.If(ss == 0, p, r_slices[3]), ) assert s.solver.is_true(calc_result == correct_result) r_slices = r.chop(32) calc_result = translate(s, "Iop_SetElem32x2", (r, ss, q)) correct_result = claripy.Concat( claripy.If(ss == 1, q, r_slices[0]), claripy.If(ss == 0, q, r_slices[1]), ) assert s.solver.is_true(calc_result == correct_result)
#!/usr/bin/env python3 import angr import claripy p = angr.Project('./angrme') base = 0x400000 flag_chars = [claripy.BVS('flag_%d' % i, 8) for i in range(0x24)] flag = claripy.Concat(*flag_chars + [claripy.BVV(b'\n')]) state = p.factory.entry_state(stdin=flag) sm = p.factory.simulation_manager(state) good = base + 0x2370 bad = base + 0x2390 sm.explore(find=good, avoid=bad) print(sm.found[0].posix.dumps(0))
#!/usr/bin/env python3 import time import angr import claripy before = time.time() binary = "./dist/tellme" proj = angr.Project(binary) start = claripy.BVV(b"flag{") flag = claripy.BVS("flag", 16 * 8) end = claripy.BVV(b"}\n") flagsym = claripy.Concat(start, flag, end) opts = angr.options.unicorn.union({"ZERO_FILL_UNCONSTRAINED_REGISTERS"}) state = proj.factory.full_init_state(args=[binary], add_options=opts, stdin=flagsym) for c in flag.chop(8): state.solver.add(c != 0) state.solver.add(c != ord("\n")) state.solver.add(c >= ord(" ")) state.solver.add(c <= ord("~")) simman = proj.factory.simulation_manager(state) #simman.explore(find=lambda s: b"You got it!" in s.posix.dumps(1)) simman.explore(find=0x004014aa, avoid=[0x004014b8]) for s in simman.found: print(s.solver.eval(flagsym, cast_to=bytes))
def _cgc_prepare_paths(self, state=None): ''' prepare the initial paths for CGC binaries :param state: optional state to use instead of preparing a fresh one ''' # FixedRandom, FixedInReceive, and FixedOutTransmit always are applied as defaults simuvex.SimProcedures['cgc']['random'] = FixedRandom simuvex.SimProcedures['cgc']['receive'] = FixedInReceive simuvex.SimProcedures['cgc']['transmit'] = FixedOutTransmit # if we're in crash mode we want the authentic system calls if not self.crash_mode: self._set_cgc_simprocedures() project = angr.Project(self.binary) self._set_hooks(project) if not self.pov: fs = {'/dev/stdin': simuvex.storage.file.SimFile( "/dev/stdin", "r", size=len(self.input))} else: fs = self._prepare_dialogue() entry_state = None if state is None: options = set() options.add(so.CGC_ZERO_FILL_UNCONSTRAINED_MEMORY) options.add(so.CGC_NO_SYMBOLIC_RECEIVE_LENGTH) options.add(so.REPLACEMENT_SOLVER) options.add(so.UNICORN_THRESHOLD_CONCRETIZATION) # try to enable unicorn, continue if it doesn't exist try: options.add(so.UNICORN) options.add(so.UNICORN_SYM_REGS_SUPPORT) self.unicorn_enabled = True l.debug("unicorn tracing enabled") except AttributeError: pass self.remove_options |= so.simplification | set(so.LAZY_SOLVES) | set(so.SUPPORT_FLOATING_POINT) self.add_options |= options entry_state = project.factory.entry_state( fs=fs, add_options=self.add_options, remove_options=self.remove_options) csr = entry_state.unicorn.cooldown_symbolic_registers entry_state.unicorn.concretization_threshold_registers = 25000 / csr entry_state.unicorn.concretization_threshold_memory = 25000 / csr else: # hookup the new files for name in fs: fs[name].set_state(state) for fd in state.posix.files: if state.posix.files[fd].name == name: state.posix.files[fd] = fs[name] break state.scratch.executed_block_count = 0 for option in self.add_options: state.options.add(option) for option in self.remove_options: state.options.discard(option) entry_state = state if not self.pov: entry_state.cgc.input_size = len(self.input) if len(self._hooks): self._set_simproc_limits(entry_state) # preconstrain flag page self._preconstrain_flag_page(entry_state, self.cgc_flag_bytes) entry_state.memory.store(0x4347c000, claripy.Concat(*self.cgc_flag_bytes)) pg = project.factory.path_group( entry_state, immutable=True, save_unsat=True, hierarchy=False, save_unconstrained=self.crash_mode) pg.use_technique(angr.exploration_techniques.Oppologist()) l.info("oppologist enabled") return pg
# cek = [0x5B,0x43,0x6D,0x67,0x1C,0x38,0x10,0x33,0x14,0x52,0x33,0x7A,0x27,0x1B,0x3D,0x3D,0x40,0x6A,0x0F,0x68,0x60,0x0C,0x6E,0x5C,0x19,0x58,0x3D,0x46,0x5C,0x79,0x67,0x6F,0x5E,0x51,0x49,0x65,0x6B,0x7D,0x18,0x6B,0x7C,0x78,0x58,0x74,0x4B,0x27,0x27,0x50,0x1D,0x58,0x2E,0x6F,0x45,0x10,0x3A,0x5A,0x1C,0x7D,0x20,0x53,0x64,0x4B,0x31,0x20,0x46,0x74,0x38,0x5A,0x9,0x0D,0x59,0x38,0x11,0x24,0x18,0x46,0x15,0x1B,0x44,0x66,0x5A,0x15,0x1E,0x66,0x39,0x5C,0x6D,0x1A,0x0C,0x29,0x5C,0x4B,0x31,0x71,0x10,0x5B,0x1,0x7B,0x16,0x61,0x6,0x9,0x0B,0x1B,0x7E,0x42,0x2B,0x10,0x1E,0x55,0x5E,0x62,0x2,0x74,0x2A,0x0B,0x15,0x75,0x79,0x1C,0x59,0x5D,0x18,0x79,0x40,0x5,0x2E,0x29,0x1B,0x3,0x3C,0x2,0x23,0x41,0x2F,0x2E,0x6,0x9,0x77,0x65,0x3E,0x2C,0x6E,0x6D,0x43,0x7,0x9,0x76,0x4,0x2D,0x53,0x43,0x35,0x6F,0x54,0x10,0x1C,0x62,0x0,0x3E,0x12,0x2D,0x68,0x5E,0x5,0x57,0x49,0x59,0x57,0x40,0x62,0x10,0x62,0x14,0x78,0x59,0x61,0x62,0x6E,0x2,0x7C,0x30,0x4C,0x4C,0x49,0x18,0x4,0x1B,0x51,0x4B,0x1C,0x4E,0x19,0x4E,0x2E,0x2D,0x42,0x3,0x10,0x46,0x33,0x46,0x4C,0x7,0x41,0x6,0x38,0x6A,0x13,0x46,0x71,0x12,0x18,0x26,0x3F,0x42,0x5D,0x47,0x39,0x11,0x11,0x58,0x3A,0x7D,0x22,0x35,0x5E,0x45,0x34,0x48,0x59,0x37,0x68,0x7A,0x49,0x78,0x28,0x39,0x52,0x48,0x56,0x0B,0x1C,0x4C,0x75,0x7A,0x17,0x17,0x0B,0x47,0x3D,0x6F,0x3C,0x3A,0x20,0x31,0x51,0x43,0x18,0x64,0x20,0x27,0x6E,0x7A,0x11,0x4C,0x18,0x69,0x67,0x4F,0x6C,0x31,0x2B,0x23,0x39,0x71,0x49,0x75,0x66,0x6C,0x51,0x3A,0x62,0x3C,0x5A,0x68,0x14,0x42,0x72,0x27,0x0E,0x24,0x71,0x4B,0x72,0x25,0x20,0x0A,0x5A,0x34,0x37,0x70,0x48,0x2B,0x30,0x8,0x74,0x60,0x65,0x47,0x65,0x5,0x51,0x74,0x65,0x2F,0x43,0x6E,0x4,0x76,0x1F,0x5C,0x26,0x43,0x0F,0x6E,0x53,0x29,0x40,0x66,0x35,0x23,0x4,0x42,0x5,0x1B,0x23,0x65,0x55,0x9,0x1A,0x0,0x31,0x6A,0x15,0x22,0x18,0x78,0x65,0x64,0x49,0x3E,0x53,0x4F,0x47,0x49,0x0F,0x18,0x55,0x2C,0x21,0x49,0x1,0x17,0x2F,0x6E,0x63,0x7B,0x5B,0x3B,0x32,0x2,0x6A,0x13,0x66,0x26,0x3B,0x18,0x24,0x39,0x2C,0x3F,0x66,0x74,0x63,0x26,0x1A,0x10,0x8,0x43,0x71,0x38,0x6D,0x29,0x1E,0x2D,0x41,0x56,0x38,0x40,0x4A,0x37,0x5F,0x57,0x29,0x49,0x41,0x74,0x4A,0x1B,0x9,0x69,0x59,0x3A,0x2,0x1B,0x9,0x6B,0x71,0x4C,0x55,0x3C,0x5B,0x6A,0x7B,0x32,0x74,0x52,0x0E,0x33,0x0F,0x18,0x7E,0x5A,0x4D,0x20,0x55,0x4A,0x34,0x0E,0x7A,0x66,0x42,0x3B,0x5E,0x68,0x5F,0x4A,0x28,0x16,0x38,0x4,0x55,0x54,0x1A,0x5,0x1B,0x52,0x2,0x40,0x79,0x56,0x6D,0x23,0x7,0x73,0x1,0x67,0x58,0x51,0x0F,0x54,0x23,0x2D,0x11,0x48,0x15,0x4E,0x55,0x3F,0x3C,0x24,0x28,0x10,0x2A,0x4E,0x26,0x38,0x2F,0x0C,0x4E,0x74,0x5B,0x6C,0x2A,0x61,0x6,0x0C,0x12,0x42,0x23,0x4,0x63,0x38,0x3B,0x55,0x1F,0x67,0x26,0x38,0x4F,0x1,0x26,0x29,0x2B,0x4A,0x1C,0x0E,0x2F,0x7B,0x30,0x26,0x3D,0x6B,0x3,0x3F,0x6C,0x28,0x7C,0x62,0x6C,0x44,0x66,0x2B,0x54,0x50,0x0F,0x6C,0x38,0x45,0x6A,0x41,0x41,0x0B,0x73,0x78,0x60,0x2F,0x12,0x40,0x53,0x15,0x8,0x1C,0x1D,0x2B,0x0,0x5E,0x30,0x49,0x3E,0x64,0x0B,0x19,0x72,0x1,0x11,0x79,0x29,0x0A,0x17,0x2,0x6,0x4C,0x29,0x58,0x23,0x55,0x32,0x38,0x7E,0x65,0x5,0x26,0x37,0x5B,0x13,0x7,0x16,0x5,0x0D,0x0A,0x6D,0x59,0x73,0x71,0x64,0x74,0x48,0x42,0x57,0x48,0x20,0x25,0x73,0x30,0x1B,0x22,0x23,0x0B,0x70,0x3E,0x4C,0x31,0x7D,0x41,0x36,0x46,0x58,0x7C,0x2C,0x4,0x0A,0x71,0x3,0x34,0x3B,0x4A,0x1A,0x47,0x10,0x3A,0x67,0x1F,0x51,0x6F,0x44,0x70,0x73,0x32,0x6B,0x22,0x13,0x64,0x77,0x72,0x6,0x17,0x66,0x31,0x38,0x2F,0x0E,0x54,0x50,0x61,0x7E,0x74,0x74,0x25,0x0B,0x48,0x7C,0x5F,0x0C,0x25,0x3F,0x75,0x51,0x11,0x19,0x3F,0x44,0x27,0x25,0x79,0x64,0x6E,0x68,0x41,0x37,0x50,0x9,0x1A,0x4F,0x5D,0x72,0x71,0x52,0x6E,0x17,0x0C,0x25,0x5D,0x26,0x21,0x0F,0x6A,0x3E,0x2E,0x3B,0x4B,0x1A,0x0B,0x54,0x6,0x38,0x60,0x25,0x55,0x3C,0x3,0x2C,0x6D,0x77,0x5A,0x3A,0x73,0x17,0x79,0x2B,0x4A,0x54,0x33,0x69,0x46,0x62,0x77,0x0D,0x50,0x73,0x2C,0x12,0x5E,0x3A,0x5D,0x3F,0x64,0x0F,0x40,0x2E,0x64,0x59,0x6E,0x1D,0x67,0x1A,0x16,0x1C,0x0B,0x14,0x10,0x5F,0x17,0x3,0x28,0x45,0x54,0x23,0x5,0x5D,0x69,0x79,0x0C,0x72,0x5,0x1E,0x19,0x51,0x4E,0x5,0x23,0x6A,0x0F,0x35,0x5B,0x7B,0x23,0x5C,0x19,0x2F,0x51,0x53,0x7A,0x75,0x58,0x18,0x5B,0x3A,0x2,0x42,0x53,0x15,0x42,0x1B,0x0,0x1F,0x21,0x61,0x66,0x25,0x1,0x39,0x63,0x4D,0x1,0x75,0x51,0x4A,0x5F,0x8,0x4B,0x12,0x56,0x8,0x0F,0x3E,0x11,0x40,0x68,0x8,0x7C,0x19,0x0E,0x4F,0x21,0x1E,0x7D,0x12,0x3A,0x4B,0x5A,0x51,0x65,0x18,0x7E,0x1B,0x7B,0x66] # cek2 = [0x53,0x62,0x2,0x59,0x51,0x73,0x30,0x40,0x6,0x15,0x6A,0x55,0x29,0x9,0x4E,0x6A,0x76,0x2C,0x61,0x5B,0x12,0x79,0x6D,0x72,0x1E,0x2F,0x3F,0x34,0x6E] import angr import claripy FLAG_LEN = 28 STDIN_FD = 0 base_addr = 0x8049000 proj = angr.Project("./soal",main_opts={'base_addr':base_addr}) flag_chars = [claripy.BVS('flag_%d' % i, 8) for i in range(FLAG_LEN)] flag = claripy.Concat( *flag_chars + [claripy.BVV(b'\n')]) # Add \n for scanf() to accept the input state = proj.factory.full_init_state( args=['./soal'], add_options=angr.options.unicorn, stdin=flag, ) # Add constraints that all characters are printable for k in flag_chars: state.solver.add(k >= ord('!')) state.solver.add(k <= ord('~')) simgr = proj.factory.simulation_manager(state) find_addr = 0x080490C5 # SUCCESS avoid_addr = 0x080490DD # FAILURE simgr.explore(find=find_addr, avoid=avoid_addr)
def test_vsa_constraint_to_si(): # Set backend b = claripy.backends.vsa s = claripy.SolverVSA() #pylint:disable=unused-variable SI = claripy.SI BVV = claripy.BVV claripy.vsa.strided_interval.allow_dsis = False # # If(SI == 0, 1, 0) == 1 # s1 = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=2) ast_true = (claripy.If(s1 == BVV(0, 32), BVV(1, 1), BVV(0, 1)) == BVV(1, 1)) ast_false = (claripy.If(s1 == BVV(0, 32), BVV(1, 1), BVV(0, 1)) != BVV(1, 1)) trueside_sat, trueside_replacement = b.constraint_to_si(ast_true) nose.tools.assert_equal(trueside_sat, True) nose.tools.assert_equal(len(trueside_replacement), 1) nose.tools.assert_true(trueside_replacement[0][0] is s1) # True side: claripy.SI<32>0[0, 0] nose.tools.assert_true( claripy.backends.vsa.is_true(trueside_replacement[0][1] == claripy.SI(bits=32, stride=0, lower_bound=0, upper_bound=0))) falseside_sat, falseside_replacement = b.constraint_to_si(ast_false) nose.tools.assert_equal(falseside_sat, True) nose.tools.assert_equal(len(falseside_replacement), 1) nose.tools.assert_true(falseside_replacement[0][0] is s1) # False side; claripy.SI<32>1[1, 2] nose.tools.assert_true( claripy.backends.vsa.identical(falseside_replacement[0][1], SI(bits=32, stride=1, lower_bound=1, upper_bound=2)) ) # # If(SI == 0, 1, 0) <= 1 # s1 = SI(bits=32, stride=1, lower_bound=0, upper_bound=2) ast_true = (claripy.If(s1 == BVV(0, 32), BVV(1, 1), BVV(0, 1)) <= BVV(1, 1)) ast_false = (claripy.If(s1 == BVV(0, 32), BVV(1, 1), BVV(0, 1)) > BVV(1, 1)) trueside_sat, trueside_replacement = b.constraint_to_si(ast_true) nose.tools.assert_equal(trueside_sat, True) # Always satisfiable falseside_sat, falseside_replacement = b.constraint_to_si(ast_false) nose.tools.assert_equal(falseside_sat, False) # Not sat # # If(SI == 0, 20, 10) > 15 # s1 = SI(bits=32, stride=1, lower_bound=0, upper_bound=2) ast_true = (claripy.If(s1 == BVV(0, 32), BVV(20, 32), BVV(10, 32)) > BVV(15, 32)) ast_false = (claripy.If(s1 == BVV(0, 32), BVV(20, 32), BVV(10, 32)) <= BVV(15, 32)) trueside_sat, trueside_replacement = b.constraint_to_si(ast_true) nose.tools.assert_equal(trueside_sat, True) nose.tools.assert_equal(len(trueside_replacement), 1) nose.tools.assert_true(trueside_replacement[0][0] is s1) # True side: SI<32>0[0, 0] nose.tools.assert_true( claripy.backends.vsa.identical(trueside_replacement[0][1], SI(bits=32, stride=0, lower_bound=0, upper_bound=0)) ) falseside_sat, falseside_replacement = b.constraint_to_si(ast_false) nose.tools.assert_equal(falseside_sat, True) nose.tools.assert_equal(len(falseside_replacement), 1) nose.tools.assert_true(falseside_replacement[0][0] is s1) # False side; SI<32>1[1, 2] nose.tools.assert_true( claripy.backends.vsa.identical(falseside_replacement[0][1], SI(bits=32, stride=1, lower_bound=1, upper_bound=2)) ) # # If(SI == 0, 20, 10) >= 15 # s1 = SI(bits=32, stride=1, lower_bound=0, upper_bound=2) ast_true = (claripy.If(s1 == BVV(0, 32), BVV(15, 32), BVV(10, 32)) >= BVV(15, 32)) ast_false = (claripy.If(s1 == BVV(0, 32), BVV(15, 32), BVV(10, 32)) < BVV(15, 32)) trueside_sat, trueside_replacement = b.constraint_to_si(ast_true) nose.tools.assert_equal(trueside_sat, True) nose.tools.assert_equal(len(trueside_replacement), 1) nose.tools.assert_true(trueside_replacement[0][0] is s1) # True side: SI<32>0[0, 0] nose.tools.assert_true( claripy.backends.vsa.identical(trueside_replacement[0][1], SI(bits=32, stride=0, lower_bound=0, upper_bound=0)) ) falseside_sat, falseside_replacement = b.constraint_to_si(ast_false) nose.tools.assert_equal(falseside_sat, True) nose.tools.assert_equal(len(falseside_replacement), 1) nose.tools.assert_true(falseside_replacement[0][0] is s1) # False side; SI<32>0[0,0] nose.tools.assert_true( claripy.backends.vsa.identical(falseside_replacement[0][1], SI(bits=32, stride=1, lower_bound=1, upper_bound=2)) ) # # Extract(0, 0, Concat(BVV(0, 63), If(SI == 0, 1, 0))) == 1 # s2 = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=2) ast_true = (claripy.Extract(0, 0, claripy.Concat(BVV(0, 63), claripy.If(s2 == 0, BVV(1, 1), BVV(0, 1)))) == 1) ast_false = (claripy.Extract(0, 0, claripy.Concat(BVV(0, 63), claripy.If(s2 == 0, BVV(1, 1), BVV(0, 1)))) != 1) trueside_sat, trueside_replacement = b.constraint_to_si(ast_true) nose.tools.assert_equal(trueside_sat, True) nose.tools.assert_equal(len(trueside_replacement), 1) nose.tools.assert_true(trueside_replacement[0][0] is s2) # True side: claripy.SI<32>0[0, 0] nose.tools.assert_true( claripy.backends.vsa.identical(trueside_replacement[0][1], SI(bits=32, stride=0, lower_bound=0, upper_bound=0)) ) falseside_sat, falseside_replacement = b.constraint_to_si(ast_false) nose.tools.assert_equal(falseside_sat, True) nose.tools.assert_equal(len(falseside_replacement), 1) nose.tools.assert_true(falseside_replacement[0][0] is s2) # False side; claripy.SI<32>1[1, 2] nose.tools.assert_true( claripy.backends.vsa.identical(falseside_replacement[0][1], SI(bits=32, stride=1, lower_bound=1, upper_bound=2)) ) # # Extract(0, 0, ZeroExt(32, If(SI == 0, BVV(1, 32), BVV(0, 32)))) == 1 # s3 = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=2) ast_true = (claripy.Extract(0, 0, claripy.ZeroExt(32, claripy.If(s3 == 0, BVV(1, 32), BVV(0, 32)))) == 1) ast_false = (claripy.Extract(0, 0, claripy.ZeroExt(32, claripy.If(s3 == 0, BVV(1, 32), BVV(0, 32)))) != 1) trueside_sat, trueside_replacement = b.constraint_to_si(ast_true) nose.tools.assert_equal(trueside_sat, True) nose.tools.assert_equal(len(trueside_replacement), 1) nose.tools.assert_true(trueside_replacement[0][0] is s3) # True side: claripy.SI<32>0[0, 0] nose.tools.assert_true( claripy.backends.vsa.identical(trueside_replacement[0][1], SI(bits=32, stride=0, lower_bound=0, upper_bound=0)) ) falseside_sat, falseside_replacement = b.constraint_to_si(ast_false) nose.tools.assert_equal(falseside_sat, True) nose.tools.assert_equal(len(falseside_replacement), 1) nose.tools.assert_true(falseside_replacement[0][0] is s3) # False side; claripy.SI<32>1[1, 2] nose.tools.assert_true( claripy.backends.vsa.identical(falseside_replacement[0][1], SI(bits=32, stride=1, lower_bound=1, upper_bound=2)) ) # # Extract(0, 0, ZeroExt(32, If(Extract(32, 0, (SI & claripy.SI)) < 0, BVV(1, 1), BVV(0, 1)))) # s4 = claripy.SI(bits=64, stride=1, lower_bound=0, upper_bound=0xffffffffffffffff) ast_true = ( claripy.Extract(0, 0, claripy.ZeroExt(32, claripy.If(claripy.Extract(31, 0, (s4 & s4)).SLT(0), BVV(1, 32), BVV(0, 32)))) == 1) ast_false = ( claripy.Extract(0, 0, claripy.ZeroExt(32, claripy.If(claripy.Extract(31, 0, (s4 & s4)).SLT(0), BVV(1, 32), BVV(0, 32)))) != 1) trueside_sat, trueside_replacement = b.constraint_to_si(ast_true) nose.tools.assert_equal(trueside_sat, True) nose.tools.assert_equal(len(trueside_replacement), 1) nose.tools.assert_true(trueside_replacement[0][0] is s4[31:0]) # True side: claripy.SI<32>0[0, 0] nose.tools.assert_true( claripy.backends.vsa.identical(trueside_replacement[0][1], SI(bits=32, stride=1, lower_bound=-0x80000000, upper_bound=-1)) ) falseside_sat, falseside_replacement = b.constraint_to_si(ast_false) nose.tools.assert_equal(falseside_sat, True) nose.tools.assert_equal(len(falseside_replacement), 1) nose.tools.assert_true(falseside_replacement[0][0] is s4[31:0]) # False side; claripy.SI<32>1[1, 2] nose.tools.assert_true( claripy.backends.vsa.identical(falseside_replacement[0][1], SI(bits=32, stride=1, lower_bound=0, upper_bound=0x7fffffff)) ) # # TOP_SI != -1 # s5 = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=0xffffffff) ast_true = (s5 == claripy.SI(bits=32, stride=1, lower_bound=0xffffffff, upper_bound=0xffffffff)) ast_false = (s5 != claripy.SI(bits=32, stride=1, lower_bound=0xffffffff, upper_bound=0xffffffff)) trueside_sat, trueside_replacement = b.constraint_to_si(ast_true) nose.tools.assert_true(trueside_sat) nose.tools.assert_equal(len(trueside_replacement), 1) nose.tools.assert_true(trueside_replacement[0][0] is s5) nose.tools.assert_true(claripy.backends.vsa.identical(trueside_replacement[0][1], SI(bits=32, stride=1, lower_bound=0xffffffff, upper_bound=0xffffffff) ) ) falseside_sat, falseside_replacement = b.constraint_to_si(ast_false) nose.tools.assert_true(falseside_sat) nose.tools.assert_equal(len(falseside_replacement), 1) nose.tools.assert_true(falseside_replacement[0][0] is s5) nose.tools.assert_true(claripy.backends.vsa.identical(falseside_replacement[0][1], SI(bits=32, stride=1, lower_bound=0, upper_bound=0xfffffffe) ) )
def _standardize_value(arg, ty, state, alloc): check = ty is not None if isinstance(arg, SimActionObject): return SimCC._standardize_value(arg.ast, ty, state, alloc) elif isinstance(arg, PointerWrapper): if check and not isinstance(ty, SimTypePointer): raise TypeError("Type mismatch: expected %s, got pointer-wrapper" % ty.name) real_value = SimCC._standardize_value(arg.value, ty.pts_to if check else None, state, alloc) return alloc(real_value, state) elif isinstance(arg, str): # TODO: when we switch to py3, distinguish between str and bytes # by null-terminating str but not bytes :/ arg += '\0' ref = False if check: if isinstance(ty, SimTypePointer) and \ isinstance(ty.pts_to, SimTypeChar): ref = True elif isinstance(ty, SimTypeFixedSizeArray) and \ isinstance(ty.elem_type, SimTypeChar): ref = False if len(arg) > ty.length: raise TypeError("String %s is too long for %s" % (repr(arg), ty.name)) arg = arg.ljust(ty.length, '\0') elif isinstance(ty, SimTypeArray) and \ isinstance(ty.elem_type, SimTypeChar): ref = True if ty.length is not None: if len(arg) > ty.length: raise TypeError("String %s is too long for %s" % (repr(arg), ty.name)) arg = arg.ljust(ty.length, '\0') elif isinstance(ty, SimTypeString): ref = False if len(arg) > ty.length + 1: raise TypeError("String %s is too long for %s" % (repr(arg), ty.name)) arg = arg.ljust(ty.length + 1, '\0') else: raise TypeError("Type mismatch: Expected %s, got char*" % ty.name) val = SimCC._standardize_value(map(ord, arg), SimTypeFixedSizeArray(SimTypeChar(), len(arg)), state, alloc) if ref: val = alloc(val, state) return val elif isinstance(arg, list): ref = False subty = None if check: if isinstance(ty, SimTypePointer): ref = True subty = ty.pts_to elif isinstance(ty, SimTypeFixedSizeArray): ref = False subty = ty.elem_type if len(arg) != ty.length: raise TypeError("Array %s is the wrong length for %s" % (repr(arg), ty.name)) elif isinstance(ty, SimTypeArray): ref = True subty = ty.elem_type if ty.length is not None: if len(arg) != ty.length: raise TypeError("Array %s is the wrong length for %s" % (repr(arg), ty.name)) else: raise TypeError("Type mismatch: Expected %s, got char*" % ty.name) else: types = map(type, arg) if types[1:] != types[:-1]: raise TypeError("All elements of list must be of same type") val = claripy.Concat(*[SimCC._standardize_value(sarg, subty, state, alloc) for sarg in arg]) if ref: val = alloc(val, state) return val elif isinstance(arg, tuple): if check: if not isinstance(ty, SimStruct): raise TypeError("Type mismatch: Expected %s, got tuple (i.e. struct)" % ty.name) if len(arg) != len(ty.fields): raise TypeError("Wrong number of fields in struct, expected %d got %d" % (len(ty.fields), len(arg))) return claripy.Concat(*[SimCC._standardize_value(sarg, sty, state, alloc) for sarg, sty in zip(arg, ty.fields.values())]) else: return claripy.Concat(*[SimCC._standardize_value(sarg, None, state, alloc) for sarg in arg]) elif isinstance(arg, (int, long)): if check and isinstance(ty, SimTypeFloat): return SimCC._standardize_value(float(arg), ty, state, alloc) val = state.se.BVV(arg, ty.size if check else state.arch.bits) if state.arch.memory_endness == 'Iend_LE': val = val.reversed return val elif isinstance(arg, float): sort = claripy.FSORT_FLOAT if check: if isinstance(ty, SimTypeDouble): sort = claripy.FSORT_DOUBLE elif isinstance(ty, SimTypeFloat): pass else: raise TypeError("Type mismatch: expectd %s, got float" % ty.name) else: sort = claripy.FSORT_DOUBLE if state.arch.bits == 64 else claripy.FSORT_FLOAT val = claripy.fpToIEEEBV(claripy.FPV(arg, sort)) if state.arch.memory_endness == 'Iend_LE': val = val.reversed # pylint: disable=no-member return val elif isinstance(arg, claripy.ast.FP): val = claripy.fpToIEEEBV(arg) if state.arch.memory_endness == 'Iend_LE': val = val.reversed # pylint: disable=no-member return val elif isinstance(arg, claripy.ast.Base): # yikes if state.arch.memory_endness == 'Iend_LE' and arg.length == state.arch.bits: arg = arg.reversed return arg else: raise TypeError("I don't know how to serialize %s." % repr(arg))
import re from tqdm import tqdm import claripy # Define which rers problem we are solving problem = "Problem11" problemset = "TrainingSeqReachRers2019" proj = angr.Project(f'rers/{problemset}/{problem}/{problem}') # Restrict input input_len = 8 # We create a bitvector representing stdin input_chars = [claripy.BVS('inputbyte_%d' % i, 8) for i in range(input_len)] sym_input = claripy.Concat(*input_chars) # Setup the initial state, and point it to the symbolic input state = proj.factory.entry_state(stdin=sym_input) simgr = proj.factory.simgr(state) # Add constraints on input bytes, we know the valid inputs (look at the rers code) for k in input_chars: state.solver.add(k >= 0x01) state.solver.add(k <= 0x10) # Explore for a few iterations # Explore runs until a new state is found that satisfies the "find" condition, # e.g. stderr contains the string "error" n_iterations = 50