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 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 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 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)
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)
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 parent class! @todo: Instead of concretizing all possible values in range raise exception and make executor for arr on each mapped page """ if issymbolic(addr): logger.debug("Write to symbolic address %s", addr) addr_min, addr_max = self.solver.minmax(addr) logger.debug("Range: %x <-> %x Data: %s", addr_min, addr_max, data) #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] = chr(data) else: #concrete addr case if not self.isWriteable(addr): raise MemoryException("No Access Writting", addr) if issymbolic(data): self.symbol[addr] = chr(data) self.addr2symbol.add(addr) else: #both concrete self.addr2symbol.discard(addr) super(SMemory, self).putchar(addr, data)
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) if addr_max - addr_min > 0x10000000: raise MemoryException( "Dangling symbolic pointer [0x%08x-0x%08x]" % (addr_min, addr_max), addr) #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 chr(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 chr(self.solver.simplify(self.symbol[addr])) return super(SMemory, self).getchar(addr)
#add the constraint new_state.solver.add(counter == new_counter) #and set the PC of the new state to the concrete pc-dest new_state.cpu.setRegister(e.reg_name, new_counter) #add the state to the list of pending states executor.putState(new_state) #keep analizing one of the states already loaded up new_counter = vals[0] current_state.solver.add(counter == new_counter) new_state.cpu.setRegister(e.reg_name, new_counter) except SymbolicPCException, e: #if PC gets "tainted" with symbols do stuff assert issymbolic(current_state.cpu.PC) #get all possible PC destinations (raise if more tahn 100 options) vals = list( current_state.solver.getallvalues(current_state.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 = current_state.cpu.PC for new_pc in vals[1:]: new_state = current_state.branch()
new_state.solver.add(counter == new_counter) #and set the PC of the new state to the concrete pc-dest new_state.cpu.setRegister(e.reg_name, new_counter ) #add the state to the list of pending states executor.putState(new_state) #keep analizing one of the states already loaded up new_counter = vals[0] current_state.solver.add(counter == new_counter) new_state.cpu.setRegister(e.reg_name, new_counter) except SymbolicPCException, e: #if PC gets "tainted" with symbols do stuff assert issymbolic(current_state.cpu.PC) #get all possible PC destinations (raise if more tahn 100 options) vals = list(current_state.solver.getallvalues(current_state.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 = current_state.cpu.PC for new_pc in vals[1:]: new_state = current_state.branch() #add the constraint new_state.solver.add(new_state.cpu.PC == new_pc) #and set the PC of the new state to the concrete pc-dest new_state.cpu.PC = new_pc