def state_entry(self, **kwargs): if isinstance(self.proj.loader.main_bin, BackedCGC): kwargs['permissions_backer'] = ( True, self.proj.loader.main_bin.permissions_map) kwargs['add_options'] = {o.CGC_ZERO_FILL_UNCONSTRAINED_MEMORY } | kwargs.get('add_options', set()) state = super(SimCGC, self).state_entry(**kwargs) if isinstance(self.proj.loader.main_bin, BackedCGC): for reg, val in self.proj.loader.main_bin.initial_register_values( ): if reg in state.arch.registers: setattr(state.regs, reg, val) elif reg == 'eflags': pass elif reg == 'fctrl': state.regs.fpround = (val & 0xC00) >> 10 elif reg == 'fstat': state.regs.fc3210 = (val & 0x4700) elif reg == 'ftag': empty_bools = [((val >> (x * 2)) & 3) == 3 for x in xrange(8)] tag_chars = [ claripy.BVV(0 if x else 1, 8) for x in empty_bools ] for i, tag in enumerate(tag_chars): setattr(state.regs, 'fpu_t%d' % i, tag) elif reg in ('fiseg', 'fioff', 'foseg', 'fooff', 'fop'): pass elif reg == 'mxcsr': state.regs.sseround = (val & 0x600) >> 9 else: l.error("What is this register %s I have to translate?", reg) # Update allocation base state.cgc.allocation_base = self.proj.loader.main_bin.current_allocation_base # Do all the writes writes_backer = self.proj.loader.main_bin.writes_backer stdout = 1 for size in writes_backer: if size == 0: continue str_to_write = state.posix.files[1].content.load( state.posix.files[1].pos, size) a = SimActionData(state, 'file_1_0', 'write', addr=claripy.BVV(state.posix.files[1].pos, state.arch.bits), data=str_to_write, size=size) state.posix.write(stdout, str_to_write, size) state.log.add_action(a) else: # Set CGC-specific variables state.regs.eax = 0 state.regs.ebx = 0 state.regs.ecx = 0x4347c000 state.regs.edx = 0 state.regs.edi = 0 state.regs.esi = 0 state.regs.esp = 0xbaaaaffc state.regs.ebp = 0 state.regs.cc_dep1 = 0x202 # default eflags state.regs.cc_op = 0 # OP_COPY state.regs.cc_dep2 = 0 # doesn't matter state.regs.cc_ndep = 0 # doesn't matter # fpu values state.regs.mm0 = 0 state.regs.mm1 = 0 state.regs.mm2 = 0 state.regs.mm3 = 0 state.regs.mm4 = 0 state.regs.mm5 = 0 state.regs.mm6 = 0 state.regs.mm7 = 0 state.regs.fpu_tags = 0 state.regs.fpround = 0 state.regs.fc3210 = 0x0300 state.regs.ftop = 0 # sse values state.regs.sseround = 0 state.regs.xmm0 = 0 state.regs.xmm1 = 0 state.regs.xmm2 = 0 state.regs.xmm3 = 0 state.regs.xmm4 = 0 state.regs.xmm5 = 0 state.regs.xmm6 = 0 state.regs.xmm7 = 0 # segmentation registers state.regs.ds = 0 state.regs.es = 0 state.regs.fs = 0 state.regs.gs = 0 state.regs.ss = 0 state.regs.cs = 0 return state
def _merge_paths(self, base_path, merge_info_list): def find_real_ref(ref, ref_list): """ Returns the last element r in ref_list that satisfies r == ref """ for r in reversed(ref_list): if r == ref: return r return None # Perform merging all_outputs = [] # Merge all outputs together into all_outputs # The order must be kept since actions should be applied one by one in order # Complexity of the current implementation sucks... # TODO: Optimize the complexity of the following loop for _, _, outputs in merge_info_list: for ref in reversed(outputs): if ref not in all_outputs: all_outputs.append(ref) all_outputs = reversed(all_outputs) merged_path = base_path.copy() # We make a copy first # merged_path.actions = [ ] merged_path.trim_history() merged_path.history._events = () # merged_path.events = [ ] merged_state = merged_path.state merged_path.info['actionqueue_list'].append( self._new_actionqueue( (merged_path.addr, self._get_last_actionqueue(merged_path).id))) for ref in all_outputs: last_ip = None all_values = [] all_guards = [] for _, merge_info in enumerate(merge_info_list): final_path, _, outputs = merge_info # First we should build the value if ref in outputs: # Find the real ref real_ref = find_real_ref(ref, outputs) # Read the final value if real_ref.type == 'mem': v = real_ref.value elif real_ref.type == 'reg': v = real_ref.value elif real_ref.type.startswith('file'): v = real_ref.value else: raise VeritestingError('FINISH ME') if real_ref.type == 'reg' and real_ref.offset == self.project.arch.ip_offset: # Sanity check! if last_ip is None: last_ip = v else: if merged_state.se.is_true(last_ip != v, exact=False): raise VeritestingError( "We don't want to merge IP - something is seriously wrong" ) # Then we build one more layer of our ITETree guards = final_path.info['guards'] guard = merged_state.se.And( *guards) if guards else merged_state.se.true all_values.append(v) all_guards.append(guard) max_value_size = max([v.size() for v in all_values]) # Optimization: if all values are of the same size, we can remove one to reduce the number of ITEs # FIXME: this optimization doesn't make sense at all. #sizes_of_value = set([ v.size() for v in all_values ]) #if len(sizes_of_value) == 1 and len(all_values) == len(merge_info_list): # all_values = all_values[ 1 : ] # all_guards = all_guards[ 1 : ] # Write the output to merged_state merged_actions = [] if real_ref.type == 'mem': for actual_addr in real_ref.actual_addrs: # Create the merged_action, and memory.store_cases will fill it up merged_action = SimActionData(merged_state, 'mem', 'write', addr=merged_state.se.BVV( actual_addr, self.project.arch.bits), size=max_value_size) merged_state.memory.store_cases(actual_addr, all_values, all_guards, endness='Iend_BE', action=merged_action) merged_actions.append(merged_action) elif real_ref.type == 'reg': if real_ref.offset != self.project.arch.ip_offset: # Create the merged_action, and memory.store_cases will fill it up merged_action = SimActionData(merged_state, 'reg', 'write', addr=real_ref.offset, size=max_value_size) merged_state.registers.store_cases(real_ref.offset, all_values, all_guards, endness='Iend_BE', action=merged_action) else: # Create the merged_action, and memory.store_cases will fill it up merged_action = SimActionData(merged_state, 'reg', 'write', addr=real_ref.offset, size=max_value_size) merged_state.registers.store(real_ref.offset, last_ip, action=merged_action) merged_actions.append(merged_action) elif real_ref.type.startswith('file'): # No matter it's a read or a write, we should always write it at the desired place # However, we don't have to create the SimAction here for actual_addr in real_ref.actual_addrs: # FIXME: We assume no new files were opened file_id = real_ref.type[real_ref.type.index('_') + 1:] file_id = merged_state.posix.filename_to_fd( file_id[:file_id.index('_')]) merged_action = SimActionData(merged_state, real_ref.type, real_ref.action, addr=actual_addr, size=max_value_size) merged_state.posix.files[file_id].content.store_cases( actual_addr, all_values, all_guards, endness='Iend_BE', action=merged_action) merged_actions.append(merged_action) else: l.error('Unsupported Ref type %s in path merging', real_ref.type) if merged_actions: for merged_action in merged_actions: merged_path.history._events += (merged_action, ) self._get_last_actionqueue(merged_path).actions.append( merged_action) # Merge *all* actions """ for i, merge_info in enumerate(merge_info_list): final_path, _, _ = merge_info guards = final_path.info['guards'] guard = merged_state.se.And(*guards) if guards else None for action in final_path.actions: if action.type == 'tmp': continue # Encode the constraint into action.condition action = action.copy() if guard is not None: if action.condition is None: action.condition = action._make_object(guard) else: action.condition.ast = merged_state.se.And(action.condition.ast, guard) if 'actions' not in merged_path.info: merged_path.info['actions'] = [ ] merged_path.info['actions'].append(action) """ # Fix trace of the merged path merged_path.history.addr = -1 merged_path.history._runstr = 'Veritesting' # Add extra constraints from original paths to the merged path # It's really important to not lose them. Yan has a lot to say about it. all_constraints = [] for final_path, _, _ in merge_info_list: if final_path.info['guards']: se = final_path.state.se guards = final_path.info['guards'] # There are also some extra constraints that are encoded in SimActionConstraint objects # We don't want to lose them for sure. # # constraints = [ ] #for a in [ b for b in final_path.actions if b.type == 'constraint' ]: # if not final_path.state.se.is_true(a.constraint.ast): # print "CONSTRAINT: ", a.constraint.ast, "CONDITION: ", a.condition # __import__('ipdb').set_trace() constraints = [(a.constraint if a.condition is None else se.And(a.constraint, a.condition)) for a in final_path.actions if a.type == 'constraint'] all_constraints.append(se.And(*(guards + constraints))) if all_constraints: merged_state.add_constraints(merged_state.se.Or(*all_constraints)) # Fixing the callstack of the merged path merged_path.callstack = merge_info_list[0][0].callstack # Fix the loop_ctrs new_loop_ctrs = defaultdict(int) for final_path, _, _ in merge_info_list: for loop_head_addr, looping_times in final_path.info[ 'loop_ctrs'].iteritems(): if looping_times > new_loop_ctrs[loop_head_addr]: new_loop_ctrs[loop_head_addr] = looping_times merged_path.info['loop_ctrs'] = new_loop_ctrs # # Clean the stage # if 'guards' in merged_path.info: del merged_path.info['guards'] # Clear the Path._run, otherwise Path.successors will not generate a new run merged_path._run = None return merged_path
def state_entry(self, **kwargs): state = super(SimCGC, self).state_entry(**kwargs) if isinstance(self.proj.loader.main_bin, BackedCGC): for reg, val in self.proj.loader.main_bin.initial_register_values( ): if reg in state.arch.registers: setattr(state.regs, reg, val) elif reg == 'eflags': pass elif reg == 'fctrl': state.regs.fpround = (val & 0xC00) >> 10 elif reg == 'fstat': state.regs.fc3210 = (val & 0x4700) elif reg == 'ftag': empty_bools = [((val >> (x * 2)) & 3) == 3 for x in xrange(8)] tag_chars = [ state.BVV(0 if x else 1, 8) for x in empty_bools ] for i, tag in enumerate(tag_chars): setattr(state.regs, 'fpu_t%d' % i, tag) elif reg in ('fiseg', 'fioff', 'foseg', 'fooff', 'fop'): pass elif reg == 'mxcsr': state.regs.sseround = (val & 0x600) >> 9 else: l.error("What is this register %s I have to translate?", reg) # Do all the writes writes_backer = self.proj.loader.main_bin.writes_backer stdout = 1 for size in writes_backer: if size == 0: continue str_to_write = state.posix.files[1].content.load( state.posix.files[1].pos, size) a = SimActionData(state, 'file_1_0', 'write', addr=state.BVV(state.posix.files[1].pos, state.arch.bits), data=str_to_write, size=size) state.posix.write(stdout, str_to_write, size) state.log.add_action(a) else: # Set CGC-specific variables state.regs.eax = 0 state.regs.ebx = 0 state.regs.ecx = 0 state.regs.edx = 0 state.regs.edi = 0 state.regs.esi = 0 state.regs.esp = 0xbaaaaffc state.regs.ebp = 0 #state.regs.eflags = s.BVV(0x202, 32) # fpu values state.regs.mm0 = 0 state.regs.mm1 = 0 state.regs.mm2 = 0 state.regs.mm3 = 0 state.regs.mm4 = 0 state.regs.mm5 = 0 state.regs.mm6 = 0 state.regs.mm7 = 0 state.regs.fpu_tags = 0 state.regs.fpround = 0 state.regs.fc3210 = 0x0300 state.regs.ftop = 0 # sse values state.regs.sseround = 0 state.regs.xmm0 = 0 state.regs.xmm1 = 0 state.regs.xmm2 = 0 state.regs.xmm3 = 0 state.regs.xmm4 = 0 state.regs.xmm5 = 0 state.regs.xmm6 = 0 state.regs.xmm7 = 0 return state