예제 #1
0
def main():
    p = angr.Project('normalread') # adjusted version of normalread

    state = p.factory.blank_state(remove_options={simuvex.s_options.LAZY_SOLVES})

    image_name = "test.png"

    content = simuvex.SimSymbolicMemory(memory_id="file_%s" % image_name)
    content.set_state(state)
    
    #storing content in the simulated file can decrease number of paths and constraint solving time
    #f = open('test.png', 'r')
    #content.store(0, f.read())

    image_file = simuvex.SimFile(image_name, 'rw', size=255, content=content)

    state.posix.fs = {image_name: image_file} # set state filesystem

    path = p.factory.path(state=state)
    ex = p.surveyors.Explorer(start=path)
    
    deCount = 0

    while len(ex.active) > 0:
	ex.run(10)
        print ex
	if len(ex.deadended) > deCount:
            for x in range(deCount,len(ex.deadended)):
                try:
		    print ex.deadended[x].state.posix.dumps(1) # dump the std output
                except: pass
                try:
                    print ex.deadended[x].state.posix.dumps(2) # dump the std err
                except: pass
            deCount = len(ex.deadended)
예제 #2
0
=--------------------------------=
"""
password_len = 0xf

# Create our symbolic input for our symbolic memory region
s_password = state.se.BVS('password_bytes', password_len * 8)

# Create our symbolic memory region for our symbolic file
content = simuvex.SimSymbolicMemory(
    memory_id='file_{}'.format(password_filename))
content.set_state(state)
content.store(0, s_password)

# Associate our symbolic file with the correct file name
password_file = simuvex.SimFile(password_filename,
                                'rw',
                                size=15,
                                content=content)
fs = {password_filename: password_file}
state.posix.fs = fs

# Explore until the "Congrats" message and avoid all other messages
pg = p.factory.path_group(state)
pg.explore(find=0x400743, avoid=(0x400683, 0x4006b6, 0x400732))

state = pg.found[0].state

# Grab current files from our files dict
files = state.posix.files

# The largest file ID is the content of the file we care about
"""
예제 #3
0
    def execute_one_file(self, input_file):
        """
        :param input_file:       
        """
        starttime = time.clock()
        l.debug("input: %s nopfunc %s skiplibs:%s" %
                (input_file, repr(self.nop_funcs), repr(self.skip_libs)))

        # init
        self.path_unqueued.clear()
        global_cache.clear()

        load_options = {}
        load_options['skip_libs'] = self.skip_libs

        p = angr.Project(self.exec_file, load_options=load_options)

        for nopf in self.nop_funcs:
            l.debug("hook %x with nop" % int(nopf, 16))
            p.hook(int(nopf, 16), simuvex.SimProcedures['stubs']['Nop'])

        for k in p.loader.shared_objects.keys():
            if k not in self.check_libs and k != os.path.basename(
                    self.exec_file):
                self.exclude_addrs.append(
                    (p.loader.shared_objects[k].get_min_addr(),
                     p.loader.shared_objects[k].get_max_addr()))

        global_cache.set_exclude_addrs(self.exclude_addrs)

        # import IPython
        # IPython.embed()
        args = [input_file if x == "@@" else x for x in self.args]

        if self.opexpr:
            add_options_c = {
                simuvex.s_options.CACHE_OP_EXPR, simuvex.s_options.CONCRETE_RUN
            }
            add_options_s = {
                simuvex.s_options.CACHE_OP_EXPR, simuvex.s_options.SYMBOLIC_RUN
            }
        else:
            add_options_c = {simuvex.s_options.CONCRETE_RUN}
            add_options_s = {simuvex.s_options.SYMBOLIC_RUN}

        if self.size_restrict == 0 or self.size_restrict == 1:
            add_options_c.update({
                simuvex.s_options.CACHE_WRITE_ADDRESS,
                simuvex.s_options.CACHE_READ_ADDRESS
            })
            add_options_s.update({
                simuvex.s_options.CACHE_WRITE_ADDRESS,
                simuvex.s_options.CACHE_READ_ADDRESS
            })
            add_options_c.add(simuvex.s_options.CACHE_SIMPROCEDURE_PARMS)
            add_options_s.add(simuvex.s_options.CACHE_SIMPROCEDURE_PARMS)

        # if not self.size_restrict is None:
        # add_options_c.add(simuvex.s_options.CACHE_SIMPROCEDURE_PARMS)
        # add_options_s.add(simuvex.s_options.CACHE_SIMPROCEDURE_PARMS)

        # init concrete running
        init_state = p.factory.entry_state(
            concrete_fs=True,
            args=args,
            add_options=add_options_c,
            remove_options={simuvex.s_options.LAZY_SOLVES})
        pg = p.factory.path_group(init_state)

        # init symbolic running
        init_state_s = p.factory.entry_state(args=args,
                                             add_options=add_options_s)
        # constraint file content
        try:
            with open(input_file, "rb") as fp:
                inputbytes = fp.read()
        except IOError:  # if the file doesn't exist return error
            l.error("open queue %s failed" % input_file)
            return
        # symbyte = []
        # for i in xrange(len(inputbytes)):
        #     symbyte.append(init_state_s.se.BVS("queue_%d" % i,8))
        # import ipdb
        # ipdb.set_trace()
        # init_state_s.add_constraints(symbyte[-1] == inputbytes[i])
        # symbytes = init_state_s.se.Concat(*symbyte)
        # backing = simuvex.SimSymbolicMemory(memory_id = "file_%s" % input_file)
        # backing.set_state(init_state_s)
        # backing.store(0, symbytes)

        # constraint file length
        if self.size_restrict == 0:
            inputsize = os.path.getsize(input_file)
            sym_inputfile = simuvex.SimFile(input_file, 'rw', size=inputsize)
        else:
            sym_inputfile = simuvex.SimFile(input_file, 'rw')
        sym_inputfile.set_state(init_state_s)
        fs = {input_file: sym_inputfile}
        init_state_s.posix.fs = fs
        path0 = p.factory.path(init_state_s)

        # set breakpoint for debug
        if self.bp:
            import ipdb
            init_state.inspect.b('instruction',
                                 when=simuvex.BP_BEFORE,
                                 instruction=self.bp,
                                 action='ipdb')
            init_state_s.inspect.b('instruction',
                                   when=simuvex.BP_BEFORE,
                                   instruction=self.bp,
                                   action='ipdb')

        # init bitmap
        try:
            with open(self.bitmap_file, "r") as fp:
                bitmap = fp.read()
        except IOError:  # if the file doesn't exist return error
            l.error("open bitmap file failed")
            sys.exit(1)
        l.debug(
            "bitmap length: %d" %
            len(filter(lambda x: True if ord(x) != 0xff else False, bitmap)))

        try:
            with open(self.static_file, "r") as fp:
                staticmap = fp.read()
        except IOError:  # if the file doesn't exist return error
            l.info("static_map doesn't exsit, use general mode")
            staticmap = array.array('c', [chr(0xff) for x in range(65536)])
        l.debug("staticmap length: %d" % len(
            filter(lambda x: True if ord(x) == 0xff else False, staticmap)))

        # start explore
        index = 0
        while True:
            index += 1
            global_cache.switch_enable(True)

            # concrete run
            pg.step(n=1, step_func=self.conc_step_func)
            if len(pg.active) == 0:
                if len(pg.errored) > 0:
                    l.warning("path ended with an error " +
                              repr(pg.errored[0].error))
                break
            target = pg.active[0].addr
            nextpaths = path0.step()
            l.debug("index: %d size: %d path0: %x" %
                    (index, len(nextpaths), path0.addr))
            if (len(nextpaths) < 1):
                l.error("symbolic execution has none path!")
                return

            # symbolic run
            found = None
            for np in nextpaths:
                l.debug("nextpath: %x target: %x" % (np.addr, target))

                matched = self.checkpath_withtrace(np.addr, target)
                matchstatic = self.checkpath_withbitmap(
                    path0.addr, np.addr, staticmap)
                # no match count

                checkall = False
                if matched:
                    found = np
                    l.debug("path %x has matched" % np.addr)

                    nmc = 0
                    if matchstatic is None and not global_cache.is_addr_in_exclude(
                            np.addr):
                        nmc += 1
                    else:
                        nmc = 0
                    if nmc > 5:
                        l.info('Trace out of staticmap, abort!')
                        return
                    if self.mult_conspath == True and self.size_restrict is None:
                        checkall = True
                if (not matched or checkall) and matchstatic is not None:
                    pathkey = self.checkpath_withbitmap(
                        path0.addr, np.addr, bitmap)
                    if not pathkey is None:

                        if global_cache.is_addr_in_exclude(np.addr):
                            l.debug("path %x out of check range" % np.addr)
                        else:
                            l.info("new path %x has found" % np.addr)
                            # retrieve the input symbolic file
                            infiles = [
                                v for k, v in np.state.posix.files.items()
                                if v.name == input_file
                            ]  #and v.closed == False]
                            if len(infiles) > 1:
                                openinfiles = filter(
                                    lambda x: x.closed == False, infiles)
                                if len(openinfiles) == 1:
                                    infiles = openinfiles
                                else:
                                    l.warning(
                                        "There are %d inputfiles found, It must be one!"
                                        % len(infiles))
                                    infiles = infiles[-1:]

                            if len(infiles) != 1:
                                l.error(
                                    "There are %d inputfiles found, It must be one!"
                                    % len(infiles))

                            # solve constrants and generate input
                            elif not self.is_path_queued(pathkey):
                                if self.loop_mode == 'FULL' or (
                                        self.loop_mode == 'LOG' and
                                        self.should_check_unqueued(pathkey)):

                                    def try_generate():
                                        try:
                                            # np.state.se.remove_constraints(len(inputbytes))
                                            # import ipdb
                                            # ipdb.set_trace()
                                            input = np.state.se.any_str(
                                                infiles[0].all_bytes())
                                            l.info("new input has generated")
                                            l.debug("input is: " + input)
                                        except Exception as e:
                                            l.debug(
                                                "path is unsat. reason is: " +
                                                repr(e))
                                            if self.path_unqueued.has_key(
                                                    pathkey):
                                                self.path_unqueued[
                                                    pathkey] += 1
                                            else:
                                                self.path_unqueued[pathkey] = 1
                                            return
                                        try:
                                            queue_index = 0
                                            for _, _, files in os.walk(
                                                    self.output_queuedir):
                                                for file in files:
                                                    if file[0:3] == 'id:':
                                                        queue_index += 1
                                            queue_name = self.generate_queuename(
                                                path0.addr, np.addr, index,
                                                queue_index)
                                            with open(
                                                    os.path.join(
                                                        self.output_queuedir,
                                                        queue_name),
                                                    "wb") as fp:
                                                fp.write(input)
                                                self.path_queued[
                                                    pathkey] = None
                                        except IOError:
                                            l.error("create queue %s failed!" %
                                                    queue_name)
                                            return

                                    try_generate()
                                    pass
                                else:
                                    self.path_unqueued[pathkey] += 1

                            else:
                                l.debug("path %x has generated queue" %
                                        np.addr)
                    else:
                        l.debug("path %x has tested by afl" % np.addr)

            if found is None:
                l.error(
                    "symbolic execution can't find same path as concretely run!"
                )
                for x in nextpaths:
                    if x.errored:
                        l.error("path ended with an error " + repr(x.error))
                return
            else:
                path0 = found

        l.info("The path length: %d with input %s" % (index, input_file))
        l.info("execution time: %f" % (time.clock() - starttime))
예제 #4
0
파일: solve.py 프로젝트: trecakov/angr-doc
def main():
    p = angr.Project("license", load_options={'auto_load_libs': False})

    # Create a blank state
    state = p.factory.blank_state()

    # Build the file whose name is weird
    license_name = "_a\nb\tc_"

    # This is the license file
    # From analyzing the binary, we know that the license file should have five
    # lines in total, and each line has 6 characters. Not setting file content
    # may also work, but in that case, angr will produce many more paths, and we
    # will spent much more time in path trimming.

    bytes = None
    constraints = []
    for i in xrange(5):
        line = []
        for j in xrange(6):
            line.append(state.se.BVS('license_file_byte_%d_%d' % (i, j), 8))
            state.add_constraints(line[-1] != 0x0a)
        if bytes is None:
            bytes = state.se.Concat(*line)
        else:
            bytes = state.se.Concat(bytes, state.se.BVV(0x0a, 8), *line)
    content = simuvex.SimSymbolicMemory(memory_id="file_%s" % license_name)
    content.set_state(state)
    content.store(0, bytes)

    license_file = simuvex.SimFile(license_name,
                                   'rw',
                                   content=content,
                                   size=len(bytes) / 8)

    # Build the file system dict
    # This interface might change in the near future
    fs = {license_name: license_file}
    state.posix.fs = fs

    path = p.factory.path(state=state)

    ex = p.surveyors.Explorer(start=path,
                              find=(0x400e93, ),
                              avoid=(0x400bb1, 0x400b8f, 0x400b6d, 0x400a85,
                                     0x400ebf, 0x400a59))
    ex.run()

    # One path will be found
    found = ex.found[0]
    rsp = found.state.regs.rsp
    flag_addr = rsp + 0x278 - 0xd8  # Ripped from IDA
    # Perform an inline call to strlen() in order to determine the length of the
    # flag
    FAKE_ADDR = 0x100000
    strlen = lambda state, arguments: \
        simuvex.SimProcedures['libc.so.6']['strlen'](FAKE_ADDR, p.arch).execute(
            state, arguments=arguments
        )
    flag_length = strlen(found.state, arguments=[flag_addr]).ret_expr
    # In case it's not null-terminated, we get the least number as the length
    flag_length_int = min(found.state.se.any_n_int(flag_length, 3))
    # Read out the flag!
    flag_int = found.state.se.any_int(
        found.state.memory.load(flag_addr, flag_length_int))
    flag = hex(flag_int)[2:-1].decode("hex")
    return flag