def putchar(self, addr, data): """ Concrete/Symbolic putchar implementation @param addr: the address to put a concrete or symbolic content @param data: the content to put in C{addr} @todo: if addr is Readable/Executable? Double checked when accesing parebnt class!!! """ if issymbolic(addr): logger.debug("Write to symbolic address %s", addr) addr_min, addr_max = self.solver.minmax(addr) logger.debug("Range: %x <-> %x", addr_min, addr_max) #Mark and intialize symbolic range for i in xrange(addr_min, addr_max+1): if not self.isWriteable(i): raise MemoryException("No Access Writting", i) for i in xrange(addr_min, addr_max+1): if not i in self.addr2symbol: self.symbol[i] = self.getchar(i) self.addr2symbol.add(i) self.symbol[addr] = data else: #concrete addr case if not self.isWriteable(addr): raise MemoryException("No Access Writting", addr) if issymbolic(data): self.symbol[addr] = data self.addr2symbol.add(addr) else: #both concrete self.addr2symbol.discard(addr) super(SMemory, self).putchar(addr, data)
def test_one_concrete_one_symbolic(self): #global mainsolver my_solver = Solver() mem = SMemory(my_solver, 32, 12) addr_for_symbol1 = mem.mmap(None, 0x1000, 'rwx') mem.putchar(addr_for_symbol1, 'A') symbol1 = my_solver.mkBitVec(8) my_solver.add(OR(symbol1==ord('B'), symbol1==ord('C'))) mem.putchar(addr_for_symbol1+1, symbol1) values = list(my_solver.getallvalues(symbol1)) self.assertIn(ord('B'), values) self.assertIn(ord('C'), values) symbol2 = my_solver.mkBitVec(32) my_solver.add(symbol2>=addr_for_symbol1) my_solver.add(symbol2<=addr_for_symbol1+1) c = mem.getchar(symbol2) self.assertTrue(issymbolic(c)) values = list(my_solver.getallvalues(c)) self.assertIn(ord('A'), values) self.assertIn(ord('B'), values) self.assertIn(ord('C'), values)
def getchar(self, addr): """ Concrete/Symbolic getchar implementation @rtype: str[1] or BitVec[8] @param addr: the address to obtain its content @return: a character or a symbol stored in C{addr} @todo: if addr is Readable/Executable? Double checked when accesing parebnt class!!! """ if issymbolic(addr): logger.debug("Read from symbolic address %s", str(addr).replace("\n","")) addr_min, addr_max = self.solver.minmax(addr) self.solver.add(addr.uge(addr_min)) self.solver.add(addr.ule(addr_max)) logger.debug("Range: %x <-> %x", addr_min, addr_max) #Symbolic address case for i in xrange(addr_min, addr_max+1): if not self.isReadable(i): raise MemoryException("No Access Reading", i) if not i in self.addr2symbol: self.symbol[i] = self.getchar(i) self.addr2symbol.add(i) return self.solver.simplify(self.symbol[addr]) if not self.isReadable(addr): raise MemoryException("No Access Reading", addr) #if the pointed value is a symbol... if self.isSymbolic(addr): return self.solver.simplify(self.symbol[addr]) return super(SMemory, self).getchar(addr)
def test_mix_of_concrete_and_symbolic(self): my_solver = Solver() mem = SMemory(my_solver, 32, 12) start_mapping_addr = mem.mmap(None, 0x1000, 'rwx') concretes = [0, 2, 4, 6] symbolics = [1, 3, 5, 7] for range in concretes: mem.putchar(start_mapping_addr+range, 'C') for range in symbolics: mem.putchar(start_mapping_addr+range, my_solver.mkBitVec(8)) for range in concretes: self.assertTrue(isconcrete(mem.getchar(start_mapping_addr+range))) for range in concretes: self.assertFalse(issymbolic(mem.getchar(start_mapping_addr+range))) for range in symbolics: self.assertTrue(issymbolic(mem.getchar(start_mapping_addr+range))) for range in symbolics: self.assertFalse(isconcrete(mem.getchar(start_mapping_addr+range))) for range in symbolics: mem.putchar(start_mapping_addr+range, 'C') for range in concretes: mem.putchar(start_mapping_addr+range, my_solver.mkBitVec(8)) for range in symbolics: self.assertTrue(isconcrete(mem.getchar(start_mapping_addr+range))) for range in symbolics: self.assertFalse(issymbolic(mem.getchar(start_mapping_addr+range))) for range in concretes: self.assertTrue(issymbolic(mem.getchar(start_mapping_addr+range))) for range in concretes: self.assertFalse(isconcrete(mem.getchar(start_mapping_addr+range)))
def testBasicSymbolic(self): my_solver = Solver() mem = SMemory(my_solver, 32, 12) #alloc/map a little mem size = 0x10000 addr = mem.mmap(None, size, 'rwx') #initialize first 10 bytes as [100, 101, 102, .. 109] for i in xrange(addr, addr+10): mem.putchar(i, chr(100+i-addr)) #mak a free symbol of 32 bits x = my_solver.mkBitVec(32) #constraint it to range into [addr, addr+10) my_solver.add(x>=addr) my_solver.add(x<addr+10) #Well.. x is symbolic self.assertTrue(issymbolic(x)) #It shall be a solution self.assertTrue(my_solver.check(), 'sat') #if we ask for a possible solution (an x that comply with the constraints) sol = my_solver.getvalue(x) #it should comply.. self.assertTrue(sol >= addr and sol<addr+10) #min and max value should be addr and addr+9 m, M = my_solver.minmax(x) self.assertEqual(m, addr) self.assertEqual(M, addr+9) #If we ask for all possible solutions... for val in my_solver.getallvalues(x): #any solution must comply.. self.assertTrue(sol >= addr and sol<addr+10) #so now lets ask the memory for values pointed by addr c = mem.getchar(x) for val in my_solver.getallvalues(c): self.assertTrue(val>=100 and val<110) #constarint the address a litlle more my_solver.add(x<=addr) #It shall be a solution self.assertTrue(my_solver.check(), 'sat') #if we ask for a possible solution sol = my_solver.getvalue(x) #it must be addr self.assertTrue(sol == addr) #lets ask the memory for the value under that address c = mem.getchar(x) sol = my_solver.getvalue(c) self.assertTrue(sol==100)
raise NotImplemented file(folder+os.sep+'test_%d.txt'%test_case_no,'a').write("%s: %s\n"%(symbol.name, repr(buf))) print "starting" try: while len(states) !=0: #select a suitable state to analize current_state = get_state() try: #load the state linux = pickle.load(file(folder+os.sep+current_state,'r')) #execute until exception or finnish while linux.execute(): linux.cpu.PC = linux.solver.simplify(linux.cpu.PC) #if PC gets "tainted" with symbols do stuff if issymbolic(linux.cpu.PC): #get all possible PC destinations (raise if more tahn 100 options) vals = list(linux.solver.getallvalues(linux.cpu.PC, maxcnt = 100)) print "Symbolic PC found, possible detinations are: ", ["%x"%x for x in vals] #Shuffle the possibilities, random.shuffle(vals) #we will keep one state for the current analisys and save #all the rest to files current_pc = linux.cpu.PC for new_pc in vals[1:]: name = 'dump_%016x_%d.pkl'%(new_pc, linux.cpu.icount) print "\tSaving state %s PC: 0x%x"%(name, new_pc) linux.solver.push() #add the constraint linux.solver.add(current_pc == new_pc) #and set the PC to the concretye destination