def testBasicMappingsLimits(self): mem = SMemory(Solver(), 32, 12) #start with no maps self.assertEqual(len(mem.mappings()), 0) #Check the search gives basically any value as the mem is free self.assertEqual(mem._search(0x1000, 0x20000000), 0x20000000) #alloc/map a litlle mem size = 0x1000 addr = mem.mmap(None, size, 'rwx') #Okay 1 map self.assertEqual(len(mem.mappings()), 1) #positive tests self.assertTrue(mem.isValid(addr)) self.assertTrue(mem.isValid(addr + size - 1)) for i in xrange(addr, addr + size): self.assertTrue(mem.isValid(i)) #negative tests self.assertFalse(mem.isValid(0)) self.assertFalse(mem.isValid(0xffffffff)) self.assertFalse(mem.isValid(-1)) self.assertFalse(mem.isValid(0xfffffffffffffffffffffffffff)) self.assertFalse(mem.isValid(addr - 1)) self.assertFalse(mem.isValid(addr + 0x1000)) #check all characters go and come back the same... for c in xrange(0, 0x100): mem.putchar(addr + 0x800, chr(c)) self.assertEqual(mem.getchar(addr + 0x800), chr(c))
def testMultiSymbolic(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)) #Make a char that ranges from 'A' to 'Z' v = my_solver.mkBitVec(32) my_solver.add(v>=ord('A')) my_solver.add(v<=ord('Z')) #assign it to the firt 10 bytes mem.putchar(addr+5, chr(v)) #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) #so now lets ask the memory for values pointed by addr c = mem.getchar(x) for val in my_solver.getallvalues(c,1000): self.assertTrue(val>=100 and val<110 or val >= ord('A') and val <= ord('Z'))
def testBasicMappingsLimits(self): mem = SMemory(Solver(), 32, 12) #start with no maps self.assertEqual(len(mem.mappings()), 0) #Check the search gives basically any value as the mem is free self.assertEqual(mem._search(0x1000, 0x20000000), 0x20000000) #alloc/map a litlle mem size = 0x1000 addr = mem.mmap(None, size, 'rwx') #Okay 1 map self.assertEqual(len(mem.mappings()), 1) #positive tests self.assertTrue(mem.isValid(addr)) self.assertTrue(mem.isValid(addr+size-1)) for i in xrange(addr, addr+size): self.assertTrue(mem.isValid(i)) #negative tests self.assertFalse(mem.isValid(0)) self.assertFalse(mem.isValid(0xffffffff)) self.assertFalse(mem.isValid(-1)) self.assertFalse(mem.isValid(0xfffffffffffffffffffffffffff)) self.assertFalse(mem.isValid(addr-1)) self.assertFalse(mem.isValid(addr+0x1000)) #check all characters go and come back the same... for c in xrange(0, 0x100): mem.putchar(addr+0x800, chr(c)) self.assertEqual(mem.getchar(addr+0x800), chr(c))
def testMultiSymbolic(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)) #Make a char that ranges from 'A' to 'Z' v = my_solver.mkBitVec(32) my_solver.add(v >= ord('A')) my_solver.add(v <= ord('Z')) #assign it to the firt 10 bytes mem.putchar(addr + 5, chr(v)) #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) #so now lets ask the memory for values pointed by addr c = mem.getchar(x) for val in my_solver.getallvalues(c, 1000): self.assertTrue(val >= 100 and val < 110 or val >= ord('A') and val <= ord('Z'))
def makeSymbolic(self, data, name='', WILDCARD='+'): if WILDCARD in data: size = len(data) symb = self.solver.mkArray(name=name, is_input=True, max_size=size) for j in xrange(size): if data[j] != WILDCARD: symb[j] = data[j] return [chr(symb[i]) for i in range(size)] else: return data
def makeSymbolic(self, data, name = '', WILDCARD='+'): if WILDCARD in data: size = len(data) symb = self.solver.mkArray(name=name, is_input=True, max_size=size) for j in xrange(size): if data[j] != WILDCARD: symb[j] = data[j] return [chr(symb[i]) for i in range(size)] else: return data
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 testBasicAnonMap(self): m = MMapAnon(0x10000000, 0x2000, 'rwx') #Check the size self.assertEqual(len(m), 0x2000) #check the outside limits self.assertRaises(MemoryException, m.putchar, 0x10000000-1, 'A') self.assertRaises(MemoryException, m.putchar, 0x10002000, 'A') self.assertRaises(MemoryException, m.getchar, 0x10000000-1) self.assertRaises(MemoryException, m.getchar, 0x10002000) #check it is initialized with zero self.assertEqual(m.getchar(0x10000000), chr(0)) self.assertEqual(m.getchar(0x10002000-1), chr(0)) #check all characters go and come back the same... #at the first byte of the mapping addr = 0x10000000 for c in xrange(0, 0x100): m.putchar(addr, chr(c)) self.assertEqual(m.getchar(addr), chr(c)) #at the last byte of the mapping addr = 0x10002000-1 for c in xrange(0, 0x100): m.putchar(addr, chr(c)) self.assertEqual(m.getchar(addr), chr(c))
def testBasicAnonMap(self): m = MMapAnon(0x10000000, 0x2000, 'rwx') #Check the size self.assertEqual(len(m), 0x2000) #check the outside limits self.assertRaises(MemoryException, m.putchar, 0x10000000 - 1, 'A') self.assertRaises(MemoryException, m.putchar, 0x10002000, 'A') self.assertRaises(MemoryException, m.getchar, 0x10000000 - 1) self.assertRaises(MemoryException, m.getchar, 0x10002000) #check it is initialized with zero self.assertEqual(m.getchar(0x10000000), chr(0)) self.assertEqual(m.getchar(0x10002000 - 1), chr(0)) #check all characters go and come back the same... #at the first byte of the mapping addr = 0x10000000 for c in xrange(0, 0x100): m.putchar(addr, chr(c)) self.assertEqual(m.getchar(addr), chr(c)) #at the last byte of the mapping addr = 0x10002000 - 1 for c in xrange(0, 0x100): m.putchar(addr, chr(c)) self.assertEqual(m.getchar(addr), chr(c))
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)
def generate_testcase(self, linux): self.test_number+= 1 solver = linux.solver assert solver.check() == 'sat' for symbol,size in solver.input_symbols: if isinstance(symbol, Array): buf = '' for i in range(size): buf += chr(solver.getvalue(symbol[i])) print "%s: "%symbol.name, repr(buf) else: print symbol, type(symbol) raise NotImplemented file(self._getFilename('test_%d.txt'%self.test_number),'a').write("%s: %s\n"%(symbol.name, repr(buf)))
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)