Example #1
0
 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!!!
     """
     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] = 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)
Example #2
0
    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'))
Example #3
0
    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))
Example #4
0
    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)
Example #5
0
    def sys_access(self, cpu, buf, mode):
        '''
        Checks real user's permissions for a file 
        @rtype: int
        
        @param cpu: current CPU.
        @param buf: a buffer containing the pathname to the file to check its permissions.
        @param mode: the access permissions to check.
        @return: 
            -  C{0} if the calling process can access the file in the desired mode.
            - C{-1} if the calling process can not access the file in the desired mode.
        '''
        filename = ""
        for i in xrange(0,255):
            c = chr(cpu.load(buf+i,8))
            if c == '\x00':
                break
            filename += c

            #if path.isfile(PATH) and access(PATH, MODE):
            #    print "File exists and is readable"
            #else:
            #    print "Either file is missing or is not readable"
        if os.access(filename, mode):
            return 0
        else:
            return -1
Example #6
0
    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)
Example #7
0
 def _read_string(self, cpu, buf):
     """
     Reads a null terminated concrete buffer form memory
     @todo: FIX. move to cpu or memory 
     """
     filename = ""
     for i in xrange(0,1024):
         c = chr(cpu.load(buf+i,8))
         if c == '\x00':
             break
         filename += c
     return filename
Example #8
0
    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))
Example #9
0
def generate_testcase(linux):
    global test_case_no
    test_case_no += 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(folder+os.sep+'test_%d.txt'%test_case_no,'a').write("%s: %s\n"%(symbol.name, repr(buf)))
Example #10
0
 def sys_write(self, cpu, fd, buf, size):
     '''
     Writes to a file descriptor 
     @rtype: int
     
     @param cpu: current CPU.
     @param fd: the file descriptor of the file to write.
     @param buf: the buffer where the bytes to write are taken. 
     @param size: it writes up to C{size} bytes from the buffer C{buf} 
                  to the file referred to by the file descriptor C{fd}.      
     @return: the amount of bytes written.
     @todo: Out eax number of bytes actually sent | EAGAIN | EBADF | EFAULT | EINTR | EINVAL | EIO | ENOSPC | EPIPE
     '''
     for i in xrange(0, size):
         value = chr(cpu.load(buf+i,8))
         if not isinstance(value, str):
             logger.warning("Writing symbolic values to file %s", self.files[fd].name)
             value = str(value)
         self.files[fd].write(value)
     return size 
Example #11
0
    def sys_writev32(self, cpu, fd, iov, count):
        '''
        Works just like C{sys_write} except that multiple buffers are written out. (32 bit version)
        @rtype: int
        
        @param cpu: current CPU.
        @param fd: the file descriptor of the file to write.
        @param iov: the buffer where the the bytes to write are taken. 
        @param count: amount of C{iov} buffers to write into the file.
        @return: the amount of bytes written in total.
        '''
        total = 0
        for i in xrange(0, count):
            buf = cpu.load(iov+i*8,32)
            size = cpu.load(iov+i*8+4,32)

            #data = ""
            for i in xrange(0,size):
                #data += chr()
                self.files[fd].write(chr(cpu.load(buf+i,8)))
            total+=size
        return total
Example #12
0
    def sys_writev(self, cpu, fd, iov, count):
        '''
        Works just like C{sys_write} except that multiple buffers are written out (for Linux 64 bits).
        @rtype: int
        
        @param cpu: current CPU.
        @param fd: the file descriptor of the file to write.
        @param iov: the buffer where the the bytes to write are taken. 
        @param count: amount of C{iov} buffers to write into the file.
        @return: the amount of bytes written in total.
        '''
        total = 0
        for i in xrange(0, count):
            buf = cpu.load(iov+i*16,64)
            size = cpu.load(iov+i*16+8,64)

            data = ""
            for i in xrange(0,size):
                data += chr(cpu.load(buf+i,8))

            self.files[fd].write(data)
            total+=size
        return total
Example #13
0
    else:
        argv.append(args.argv[i])


env = [ '%s=%s' % (key, val) for (key,val) in os.environ.items() ]
for i in range(len(args.env)):
    if WILDCARD in args.env[i]:
        print "Environment variable %d has simbols"%i
        name = "ENV%d"%i
        size = len(args.env[i])
        senv = linux.solver.mkArray(name=name, is_input=True, max_size=size)
        for j in range(size):
            if args.env[i][j] != WILDCARD:
                senv[j] = args.env[i][j]
        input_symbols.append((name, size))
        env.append([chr(senv[j]) for j in range(size)])

#pass stdin, stdout, stderr as kw arguments to exe
linux.exe(args.program, argv, env, stdin=args.stdin, stdout=args.stdout, stderr=args.stderr)
del env
del argv

pickle.dump(linux,file(folder+os.sep+'dump_init.pkl','w+'),2)
time_start = time.clock()
count = 0
test_case_no = 0
states = ['dump_init.pkl']

def get_state():
    nnstates = {}
    for nn in states: