def make_fields(self, structure, offset, size): assert( offset%Config.WORDSIZE == 0 ) #vaddr and offset should be aligned #log.debug('checking String') fields = [] bytes = structure.bytes while size >= Config.WORDSIZE: #print 're_string.find_ascii(bytes, %d, %d)'%(offset,size) index, ssize = re_string.find_ascii(bytes, offset, size) if index == 0: if (ssize < size) and bytes[offset+index+ssize]=='\x00': # space for a \x00 ssize +=1 f = Field(structure, offset+index, FieldType.STRINGNULL, ssize, False) else: f = Field(structure, offset+index, FieldType.STRING, ssize, False) #print repr(structure.bytes[f.offset:f.offset+f.size]) fields.append(f) size -= ssize # reduce unknown field offset += ssize if ssize%Config.WORDSIZE: rest = Config.WORDSIZE - ssize%Config.WORDSIZE size -= rest # goto next aligned offset += rest else: size -= Config.WORDSIZE # reduce unkown field offset += Config.WORDSIZE # look in head return fields
def _make_gaps(self, structure, fields): fields.sort() gaps = [] nextoffset = 0 for i, f in enumerate(fields): if f.offset > nextoffset : # add temp padding field self._aligned_gaps(structure, f.offset, nextoffset, gaps) elif f.offset < nextoffset : #log.debug(structure) #log.debug(f) #log.debug('%s < %s '%(f.offset, nextoffset) ) #for f1 in fields: # log.debug(f1) assert(False) # f.offset < nextoffset # No overlaps authorised # do next field nextoffset = f.offset + len(f) # conclude on QUEUE insertion lastfield_size = len(structure)-nextoffset if lastfield_size > 0 : if lastfield_size < Config.WORDSIZE: gap = Field( structure, nextoffset, FieldType.UNKNOWN, lastfield_size, True) log.debug('_make_gaps: adding last field at offset %d:%d'%(gap.offset, gap.offset+len(gap) )) gaps.append(gap) else: self._aligned_gaps(structure, len(structure), nextoffset, gaps) return gaps
def _analyze(self, structure): slen = len(structure) offset = 0 # call on analyzers fields = [] nb = -1 gaps = [Field( structure, 0, FieldType.UNKNOWN, len(structure), False)] # find zeroes # find strings # find smallints # find pointers for analyser in [ self.zero_a, self.utf16_a, self.ascii_a, self.int_a, self.ptr_a]: for field in gaps: if field.padding: fields.append(field) continue log.debug('Using %s on %d:%d'%(analyser.__class__.__name__, field.offset, field.offset+len(field))) fields.extend( analyser.make_fields(structure, field.offset, len(field)) ) #for f1 in fields: # log.debug('after %s'%f1) #print fields if len(fields) != nb: # no change in fields, keep gaps nb = len(fields) gaps = self._make_gaps(structure, fields) if len(gaps) == 0: return fields, gaps return fields, gaps
def _aligned_gaps(self, structure, endoffset, nextoffset, gaps): ''' if nextoffset is aligned add a gap to gaps, or if nextoffset is not aligned add (padding + gap) to gaps ''' if nextoffset%Config.WORDSIZE == 0: gap = Field( structure, nextoffset, FieldType.UNKNOWN, endoffset-nextoffset, False) log.debug('_make_gaps: adding field at offset %d:%d'%(gap.offset, gap.offset+len(gap) )) gaps.append(gap) else: # unaligned field should be splitted s1 = Config.WORDSIZE - nextoffset%Config.WORDSIZE gap1 = Field( structure, nextoffset, FieldType.UNKNOWN, s1, True) gap2 = Field( structure, nextoffset+s1, FieldType.UNKNOWN, endoffset-nextoffset-s1, False) log.debug('_make_gaps: Unaligned field at offset %d:%d'%(gap1.offset, gap1.offset+len(gap1) )) log.debug('_make_gaps: adding field at offset %d:%d'%(gap2.offset, gap2.offset+len(gap2) )) gaps.append(gap1) gaps.append(gap2) return
def checkSmallInt(self, structure, bytes, offset, endianess='<'): """ check for small value in signed and unsigned forms """ val = unpackWord( bytes[ offset:offset + self.config.get_word_size()], endianess) # print endianess, val if val < 0xffff: field = Field( structure, offset, FieldType.SMALLINT, self.config.get_word_size(), False) field.value = val field.endianess = endianess return field # check signed int elif ((2 ** (self.config.get_word_size() * 8) - 0xffff) < val): field = Field( structure, offset, FieldType.SIGNED_SMALLINT, self.config.get_word_size(), False) field.value = val field.endianess = endianess return field return None
def _find_zeroes(self, structure, offset, size): ''' iterate over the bytes until a byte if not \x00 ''' bytes = structure.bytes #print 'offset:%x blen:%d'%(offset, len(bytes)) #print repr(bytes) assert( (offset)%Config.WORDSIZE == 0 ) #aligned_off = (offset)%Config.WORDSIZE start = offset #if aligned_off != 0: # align to next # start += (Config.WORDSIZE - aligned_off) # size -= (Config.WORDSIZE - aligned_off) # iterate matches = array.array('i') for i in range(start, start+size, Config.WORDSIZE ): # PERF TODO: bytes or struct test ? #print repr(bytes[start+i:start+i+Config.WORDSIZE]) if bytes[start+i:start+i+Config.WORDSIZE] == self._zeroes: matches.append(start+i) #print matches # collate if len(matches) == 0: return [] # lets try to get fields fields = [] # first we need to collate neighbors collates = list() prev = matches[0]-Config.WORDSIZE x = [] # PERF TODO: whats is algo here for i in matches: if i-Config.WORDSIZE == prev: x.append(i) else: collates.append(x) x = [i] prev = i collates.append(x) #log.debug(collates) # we now have collated, lets create fields for field in collates: flen = len(field) if flen > 1: size = Config.WORDSIZE * flen elif flen == 1: size = Config.WORDSIZE else: continue # make a field fields.append( Field(structure, start+field[0], self._typename, size, False) ) # we have all fields return fields
def checkSmallInt(self, structure, bytes, offset, endianess='<'): ''' check for small value in signed and unsigned forms ''' val = unpackWord(bytes[offset:offset+Config.WORDSIZE], endianess) #print endianess, val if val < 0xffff: field = Field(structure, offset, FieldType.SMALLINT, Config.WORDSIZE, False) field.value = val field.endianess = endianess return field elif ( (2**(Config.WORDSIZE*8) - 0xffff) < val): # check signed int field = Field(structure, offset, FieldType.SIGNED_SMALLINT, Config.WORDSIZE, False) field.value = val field.endianess = endianess return field return None
def make_fields(self, structure, offset, size): assert( offset%Config.WORDSIZE == 0 ) #vaddr and offset should be aligned #log.debug('checking String') fields = [] bytes = structure.bytes while size > Config.WORDSIZE: #print 're_string.rfind_utf16(bytes, %d, %d)'%(offset,size) index = re_string.rfind_utf16(bytes, offset, size) if index > -1: f = Field(structure, offset+index, FieldType.STRING16, size-index, False) #print repr(structure.bytes[f.offset:f.offset+f.size]) fields.append(f) size = index # reduce unknown field in prefix else: size -= Config.WORDSIZE # reduce unkown field # look in head return fields