예제 #1
0
 def iterateList(self, mappings):
   ''' iterate forward, then backward, until null or duplicate '''    
   done = [0]
   obj = self
   #print 'going forward '
   for fieldname in [forward, backward]:
     link = getattr(obj, fieldname)
     addr = utils.getaddress(link)
     log.debug('iterateList got a <%s>/0x%x'%(link.__class__.__name__,addr))
     nb=0
     while addr not in done:
       #print '%x %s'%(addr, addr in done)
       done.append(addr)
       memoryMap = utils.is_valid_address_value( addr, mappings, structType)
       if memoryMap == False:
         raise ValueError('the link of this linked list has a bad value')
       st = memoryMap.readStruct( addr, structType)
       model.keepRef(st, structType, addr)
       log.debug("keepRefx2 %s.%s @%x"%(structType, fieldname, addr  ))
       yield addr
       # next
       link = getattr(st, fieldname)
       addr = utils.getaddress(link)
     #print 'going backward after %x'%(addr)
   raise StopIteration
예제 #2
0
def show_dumpname(structname, dumpname, address, rtype='python'):
  """ shows the values for klass at @address in memdump.
  
  :param structname the ctypes structure name (string)
  :type structName string
  :param dumpname the memdump filename
  :param address the address from where to read the structure
  :param rtype the return type format ( string, pickle, json )
  :type rtype ['string', 'pickle', 'json', 'python']
  
  :returns (instance, validated) instance the loaded ctypes and validated a boolean flag 
      if validated is True, all constraints were OK in instance.
  """
  from haystack import dump_loader
  log.debug('haystack show %s %s %x'%(dumpname, structname, address ))
  
  structType = getKlass(structname)
  mappings = dump_loader.load(dumpname)
  finder = StructFinder(mappings)
  # validate the input address.
  memoryMap = utils.is_valid_address_value(address, finder.mappings)
  if not memoryMap:
    log.error("the address is not accessible in the memoryMap")
    raise ValueError("the address is not accessible in the memoryMap")
  
  instance,validated = finder.loadAt( memoryMap, address, structType)
  
  out = _show_output(instance, validated, rtype)
  return out
예제 #3
0
  def test_keepRef(self):
    self.assertNotEqual( self.mappings, None )
      
    for fname, ftype in self.heap_obj.getFields():
      attr = getattr(self.heap_obj, fname)
      if isCStringPointer(ftype):
        # ignore that - attr_addr = getaddress(attr.ptr)
        continue
      elif isPointerType(ftype):
        attr_addr = getaddress(attr)
      else:
        continue
      if attr_addr == 0:
        continue
      self.assertTrue( utils.is_valid_address_value(attr_addr, self.mappings), '%s: 0x%x is not valid'%(fname, attr_addr))
      # the book should register struct type, not pointer to strut type
      attr_type = model.get_subtype(ftype)
      # look in the books
      saved = model.getRefByAddr( attr_addr )
      _class, _addr, _obj = saved[0]

      self.assertEquals( attr_addr, _addr)
      self.assertEquals( attr_type, _class, '%s != %s' %(type(ftype), type(_class)))
      self.assertTrue( model.hasRef( model.get_subtype(ftype), attr_addr))
    
    return      
예제 #4
0
 def iterateList(self, mappings):
     ''' iterate forward, then backward, until null or duplicate '''
     done = [0]
     obj = self
     #print 'going forward '
     for fieldname in [forward, backward]:
         link = getattr(obj, fieldname)
         addr = utils.getaddress(link)
         log.debug('iterateList got a <%s>/0x%x' %
                   (link.__class__.__name__, addr))
         nb = 0
         while addr not in done:
             #print '%x %s'%(addr, addr in done)
             done.append(addr)
             memoryMap = utils.is_valid_address_value(
                 addr, mappings, structType)
             if memoryMap == False:
                 raise ValueError(
                     'the link of this linked list has a bad value')
             st = memoryMap.readStruct(addr, structType)
             model.keepRef(st, structType, addr)
             log.debug("keepRefx2 %s.%s @%x" %
                       (structType, fieldname, addr))
             yield addr
             # next
             link = getattr(st, fieldname)
             addr = utils.getaddress(link)
         #print 'going backward after %x'%(addr)
     raise StopIteration
예제 #5
0
def refresh(args):
  """
  Default function for the refresh command line option.
  Try to map a Structure from a specific offset in memory.
  Returns it in pickled or text format.
  
  See the command line --help .
  """
  log.debug(args)

  addr=int(args.addr,16)
  structType=getKlass(args.structName)

  mappings = MemoryMapper(pid=args.pid, memfile=args.memfile, dumpname=args.dumpname ).getMappings()
  finder = StructFinder(mappings)
  
  memoryMap = utils.is_valid_address_value(addr, finder.mappings)
  if not memoryMap:
    log.error("the address is not accessible in the memoryMap")
    raise ValueError("the address is not accessible in the memoryMap")
  instance,validated = finder.loadAt( memoryMap , 
          addr, structType)
  ##
  if args.interactive:
    import code
    code.interact(local=locals())

  if args.human:  rtype = 'string' 
  elif args.json:  rtype = 'json' 
  elif args.pickled:  rtype = 'pickled' 

  print _show_output(instance, validated, rtype)
  return
예제 #6
0
    def test_keepRef(self):
        self.assertNotEqual(self.mappings, None)

        for fname, ftype in self.heap_obj.getFields():
            attr = getattr(self.heap_obj, fname)
            if isCStringPointer(ftype):
                # ignore that - attr_addr = getaddress(attr.ptr)
                continue
            elif isPointerType(ftype):
                attr_addr = getaddress(attr)
            else:
                continue
            if attr_addr == 0:
                continue
            self.assertTrue(
                utils.is_valid_address_value(attr_addr, self.mappings),
                '%s: 0x%x is not valid' % (fname, attr_addr))
            # the book should register struct type, not pointer to strut type
            attr_type = model.get_subtype(ftype)
            # look in the books
            saved = model.getRefByAddr(attr_addr)
            _class, _addr, _obj = saved[0]

            self.assertEquals(attr_addr, _addr)
            self.assertEquals(attr_type, _class,
                              '%s != %s' % (type(ftype), type(_class)))
            self.assertTrue(model.hasRef(model.get_subtype(ftype), attr_addr))

        return
예제 #7
0
def show_dumpname(structname, dumpname, address, rtype='python'):
    """ shows the values for klass at @address in memdump.
  
  :param structname the ctypes structure name (string)
  :type structName string
  :param dumpname the memdump filename
  :param address the address from where to read the structure
  :param rtype the return type format ( string, pickle, json )
  :type rtype ['string', 'pickle', 'json', 'python']
  
  :returns (instance, validated) instance the loaded ctypes and validated a boolean flag 
      if validated is True, all constraints were OK in instance.
  """
    from haystack import dump_loader
    log.debug('haystack show %s %s %x' % (dumpname, structname, address))

    structType = getKlass(structname)
    mappings = dump_loader.load(dumpname)
    finder = StructFinder(mappings)
    # validate the input address.
    memoryMap = utils.is_valid_address_value(address, finder.mappings)
    if not memoryMap:
        log.error("the address is not accessible in the memoryMap")
        raise ValueError("the address is not accessible in the memoryMap")

    instance, validated = finder.loadAt(memoryMap, address, structType)

    out = _show_output(instance, validated, rtype)
    return out
예제 #8
0
def refresh(args):
    """
  Default function for the refresh command line option.
  Try to map a Structure from a specific offset in memory.
  Returns it in pickled or text format.
  
  See the command line --help .
  """
    log.debug(args)

    addr = int(args.addr, 16)
    structType = getKlass(args.structName)

    mappings = MemoryMapper(pid=args.pid,
                            memfile=args.memfile,
                            dumpname=args.dumpname).getMappings()
    finder = StructFinder(mappings)

    memoryMap = utils.is_valid_address_value(addr, finder.mappings)
    if not memoryMap:
        log.error("the address is not accessible in the memoryMap")
        raise ValueError("the address is not accessible in the memoryMap")
    instance, validated = finder.loadAt(memoryMap, addr, structType)
    ##
    if args.interactive:
        import code
        code.interact(local=locals())

    if args.human: rtype = 'string'
    elif args.json: rtype = 'json'
    elif args.pickled: rtype = 'pickled'

    print _show_output(instance, validated, rtype)
    return
예제 #9
0
    def _loadListEntries(self, fieldname, mappings, maxDepth):
        ''' 
    we need to load the pointed entry as a valid struct at the right offset, 
    and parse it.
    
    When does it stop following FLink/BLink ?
      sentinel is headAddr only
    '''

        structType, offset = self._getListFieldInfo(fieldname)

        # DO NOT think HEAD is a valid entry.
        # if its a ListEntries, self has already been loaded anyway.
        headAddr = self._orig_address_ + utils.offsetof(type(self), fieldname)
        head = getattr(self, fieldname)

        for entry in head._iterateList(mappings):
            # DO NOT think HEAD is a valid entry
            if entry == headAddr:
                continue
            link = entry + offset
            log.debug('got a element of list at %s 0x%x/0x%x offset:%d' %
                      (fieldname, entry, link, offset))
            # use cache if possible, avoid loops.
            #XXX
            from haystack import model
            ref = model.getRef(structType, link)
            if ref:  # struct has already been loaded, bail out
                log.debug("%s loading from references cache %s/0x%lx" %
                          (fieldname, structType, link))
                continue  # do not reload
            else:
                #  OFFSET read, specific to a LIST ENTRY model
                memoryMap = utils.is_valid_address_value(
                    link, mappings, structType)
                if memoryMap is False:
                    log.error(
                        'error while validating address 0x%x type:%s @end:0x%x'
                        % (link, structType.__name__,
                           link + ctypes.sizeof(structType)))
                    log.error('self : %s , fieldname : %s' %
                              (self.__class__.__name__, fieldname))
                    raise ValueError(
                        'error while validating address 0x%x type:%s @end:0x%x'
                        % (link, structType.__name__,
                           link + ctypes.sizeof(structType)))
                st = memoryMap.readStruct(
                    link, structType)  # point at the right offset
                st._orig_addr_ = link
                model.keepRef(st, structType, link)
                log.debug("keepRef %s.%s @%x" % (structType, fieldname, link))
                # load the list entry structure members
                if not st.loadMembers(mappings, maxDepth - 1):
                    log.error('Error while loading members on %s' %
                              (self.__class__.__name__))
                    print st
                    raise ValueError('error while loading members')

        return True
예제 #10
0
  def _loadListEntries(self, fieldname, mappings, maxDepth):
    ''' 
    we need to load the pointed entry as a valid struct at the right offset, 
    and parse it.
    
    When does it stop following FLink/BLink ?
      sentinel is headAddr only
    '''
    
    structType, offset = self._getListFieldInfo(fieldname)
    
    # DO NOT think HEAD is a valid entry.
    # if its a ListEntries, self has already been loaded anyway.
    headAddr = self._orig_address_ + utils.offsetof( type(self), fieldname)
    head = getattr(self, fieldname)
    
    for entry in head._iterateList(mappings):
      # DO NOT think HEAD is a valid entry
      if entry == headAddr:
        continue
      link = entry + offset
      log.debug('got a element of list at %s 0x%x/0x%x offset:%d'%(fieldname, entry, link, offset))
      # use cache if possible, avoid loops.
      #XXX 
      from haystack import model
      ref = model.getRef( structType, link)
      if ref: # struct has already been loaded, bail out
        log.debug("%s loading from references cache %s/0x%lx"%(fieldname, structType, link ))
        continue # do not reload
      else:
        #  OFFSET read, specific to a LIST ENTRY model
        memoryMap = utils.is_valid_address_value( link, mappings, structType)
        if memoryMap is False:
          log.error('error while validating address 0x%x type:%s @end:0x%x'%(link, 
                  structType.__name__, link+ctypes.sizeof(structType)) )
          log.error('self : %s , fieldname : %s'%(self.__class__.__name__, fieldname))
          raise ValueError('error while validating address 0x%x type:%s @end:0x%x'%(link, 
                  structType.__name__, link+ctypes.sizeof(structType)) )
        st = memoryMap.readStruct( link, structType) # point at the right offset
        st._orig_addr_ = link
        model.keepRef(st, structType, link)
        log.debug("keepRef %s.%s @%x"%(structType, fieldname, link  ))
        # load the list entry structure members
        if not st.loadMembers(mappings, maxDepth-1):
          log.error('Error while loading members on %s'%(self.__class__.__name__))
          print st
          raise ValueError('error while loading members')

    return True
예제 #11
0
def _HEAP_getFreeListsWinXP(self, mappings):
    """ Understanding_the_LFH.pdf page 17 """
    freeList = []
    # 128 blocks
    start = ctypes.addressof(self.FreeLists)  # sentinel value
    logging.getLogger("listmodel").setLevel(level=logging.DEBUG)
    for freeBlock in self.FreeLists._iterateList(mappings):
        # try to get the size
        sizeaddr = freeBlock - Config.WORDSIZE
        memoryMap = utils.is_valid_address_value(sizeaddr, mappings)
        if memoryMap == False:
            raise ValueError("the link of this linked list has a bad value")
        val = memoryMap.readWord(sizeaddr)
        log.debug("\t - freeblock @%0.8x size:%d" % (freeBlock, val))
        yield freeBlock
    # free_chain = [freeBlock for freeBlock in self.iterateListField( mappings, 'FreeLists')]
    logging.getLogger("listmodel").setLevel(level=logging.INFO)

    raise StopIteration
예제 #12
0
def _HEAP_getFreeListsWinXP(self, mappings):
    ''' Understanding_the_LFH.pdf page 17 '''
    freeList = []
    # 128 blocks
    start = ctypes.addressof(self.FreeLists)  # sentinel value
    logging.getLogger('listmodel').setLevel(level=logging.DEBUG)
    for freeBlock in self.FreeLists._iterateList(mappings):
        # try to get the size
        sizeaddr = freeBlock - Config.WORDSIZE
        memoryMap = utils.is_valid_address_value(sizeaddr, mappings)
        if memoryMap == False:
            raise ValueError('the link of this linked list has a bad value')
        val = memoryMap.readWord(sizeaddr)
        log.debug('\t - freeblock @%0.8x size:%d' % (freeBlock, val))
        yield freeBlock
    #free_chain = [freeBlock for freeBlock in self.iterateListField( mappings, 'FreeLists')]
    logging.getLogger('listmodel').setLevel(level=logging.INFO)

    raise StopIteration
예제 #13
0
def watch(opt):
    ''' structname watch vaddr [refreshrate] [varname]'''
    addr = opt.addr
    refresh = opt.refresh_rate
    varname = opt.varname
    # get structure class
    structType = abouchet.getKlass(opt.structName)
    # verify target compliance
    if varname is not None:
        varname = varname.split('.')
        if not check_varname_for_type(varname, structType):
            return False
    # load the struct
    mappings = memory_mapper.MemoryMapper(opt).getMappings()
    finder = abouchet.StructFinder(mappings)
    # get the target memory map
    memoryMap = utils.is_valid_address_value(addr, finder.mappings)
    if not memoryMap:
        log.error("the address is not accessible in the memoryMap")
        raise ValueError("the address is not accessible in the memoryMap")
    instance, validated = finder.loadAt(memoryMap, addr, structType)
    #instance.loadMembers(mappings)

    pyObj = instance.toPyObject()
    #print pyObj
    # print as asked every n secs.
    while True:
        clear()
        if varname is None:
            print pyObj
        else:
            print get_varname_value(varname, pyObj)

        if refresh == 0:
            break
        time.sleep(refresh)
        instance, validated = finder.loadAt(memoryMap, addr, structType)
        pyObj = instance.toPyObject()
예제 #14
0
def watch(opt):
  ''' structname watch vaddr [refreshrate] [varname]'''
  addr = opt.addr
  refresh = opt.refresh_rate
  varname = opt.varname
  # get structure class  
  structType = abouchet.getKlass(opt.structName)
  # verify target compliance
  if varname is not None:
    varname = varname.split('.')
    if not check_varname_for_type(varname, structType):
      return False
  # load the struct
  mappings = memory_mapper.MemoryMapper(opt).getMappings()
  finder = abouchet.StructFinder(mappings)
  # get the target memory map
  memoryMap = utils.is_valid_address_value(addr, finder.mappings)
  if not memoryMap:
    log.error("the address is not accessible in the memoryMap")
    raise ValueError("the address is not accessible in the memoryMap")
  instance,validated = finder.loadAt( memoryMap , addr, structType)
  #instance.loadMembers(mappings)
  
  pyObj = instance.toPyObject()
  #print pyObj
  # print as asked every n secs.
  while True:
    clear()
    if varname is None:
      print pyObj
    else:
      print get_varname_value(varname, pyObj)
    
    if refresh == 0:
      break
    time.sleep(refresh)
    instance,validated = finder.loadAt( memoryMap , addr, structType)
    pyObj = instance.toPyObject()
예제 #15
0
 def setUpClass(self):
   d = {'pickled': True, 
       'dumpname': 'test/dumps/ssh/ssh.1/', 
       'structName': 'sslsnoop.ctypes_openssh.session_state',
       'addr': '0xb84ee318',
       'pid': None,
       'memfile': None,
       'interactive': None,
       'human': None,
       'json': None,
       }
   args = type('args', ( object,), d)
   # setup haystack
   from haystack import config
   config.make_config_from_memdump(d['dumpname'])
   #
   addr = int(args.addr,16)
   structType = abouchet.getKlass(args.structName)
   self.mappings = memory_mapper.MemoryMapper(dumpname=args.dumpname).getMappings()
   self.finder = abouchet.StructFinder(self.mappings)
   memoryMap = utils.is_valid_address_value(addr, self.finder.mappings)
   # done          
   self.session_state, self.found = self.finder.loadAt( memoryMap, addr, structType)
   self.pyobj = self.session_state.toPyObject()