def populate_struc_enum_ids(self): logger.debug("Populating hash cache with current values") # force hash generation of struc and enums (without use_time) idx = idc.GetFirstStrucIdx() while idx != idc.BADADDR: self.get_struc_enum_object_id(idc.GetStrucId(idx), use_time=False) idx = idc.GetNextStrucIdx(idx) for idx in xrange(0, idc.GetEnumQty()): enum_id = idc.GetnEnum(idx) self.get_struc_enum_object_id(enum_id, use_time=False) enum_name = idc.GetEnumName(enum_id) for (const_id, const_value, bmask) in enum_member_iterate_all(enum_id): const_name = idc.GetConstName(const_id) self.get_enum_member_id(enum_id, enum_name, const_id, const_name, const_value, bmask, use_time=False) _yatools_hash_provider.populate_persistent_cache()
def yacheck_enums(self): values = yaunit.load('enums') for flag in flags: for prefix, enum_width, is_bitfield, num_fields in tests: name, ea, values = str(values[0][0]), values[0][1], values[1:] eid = idc.GetEnum(name) self.assertNotEqual(eid, idaapi.BADADDR) self.assertEqual(idc.GetEnumFlag(eid), flag) self.assertEqual(idc.GetEnumName(eid), name) self.assertEqual(idc.IsBitfield(eid), is_bitfield) self.assertEqual(idc.GetEnumCmt(eid, False), prefix + 'cmt') self.assertEqual(idc.GetEnumCmt(eid, True), prefix + 'rpt') if enum_width != 0: self.assertEqual(idc.GetEnumWidth(eid), enum_width) n = 0 for value, bmask in walk_enum(eid): self.assertLessEqual(n, num_fields) v = 1 << n if is_bitfield else n self.assertEqual(value, value, v) cid = idc.GetConstEx(eid, v, 0, bmask) self.assertNotEqual(cid, idaapi.BADADDR) field = '%s_%d' % (name, n) self.assertEqual(idc.GetConstName(cid), field) # FIXME comments are not working #self.assertEqual(idc.GetConstCmt(cid, False), field + 'cmt') #self.assertEqual(idc.GetConstCmt(cid, True), field + 'rpt') n += 1 self.assertEqual(n, num_fields) if ea != None: self.assertEqual(idaapi.get_enum_id(ea, 1)[0], eid)
def getName(self, val, reload=False): if not self._names or reload: self._names = {} cns = self.getConsts(reload) for x in cns: for y in cns[x]: self._names[y] = idc.GetConstName(cns[x][y]) return self._names.get(val)
def enum_member_created(self, enum, cid): ename = idc.GetEnumName(enum) cname = idc.GetConstName(cid) self.ctrl._handle_action({ 'action': 'enum_member_created', 'enum': enum, 'cid': cid, 'ename': ename, 'cname': cname }) return 0
def fix_names(self): """ Fix the table of imports and map enums to apis. """ start_addr = idc.AskAddr(idc.here(), "Enter table start address") ## check if address is within the base address and maximum address if (start_addr < idc.MinEA()) or (start_addr > idc.MaxEA()): idc.Warning("You have entered an invalid start address") idc.Exit self.start_addr = start_addr current_addr = self.start_addr #Current size of PoisonIvy IAT end_addr = current_addr + 568 # Walk the table 8 bytes at a time while current_addr <= end_addr: idc.MakeQword(current_addr) print "DEBUG: Current address - 0x%08x" % current_addr addr = idc.Qword(current_addr) print "DEBUG: address - 0x%08x" % addr if addr == -1: print "[!] Skipping address 0x%08x - 0x%08x" % (current_addr, addr) current_addr += 8 continue # Make the current address an offset idc.OpOff(current_addr,0,0) # We need to undefine the bytes incase IDA autoanalysis had converted an incorrect byte idc.MakeUnkn(addr, 1) # Create code at this address idc.MakeCode(addr) # Create function at the same address idc.MakeFunction(addr, addr+16) # Read the second operand at the address which should be the negative API address value imp_addr = idc.GetOperandValue(addr, 1) if imp_addr == -1: print "[!] Couldn't get operand at address - 0x%08x" % addr current_addr +=8 continue # try: # int_addr = int(imp_addr,16) # except ValueError as e: # print "[!] Failed on: %s - %s\n" % (imp_addr, e) # current_addr +=8 # continue # if we know about this value then let's do the work if imp_addr in self.enums.keys(): enum_id = self.enums[imp_addr] # Convert operand to enum idc.OpEnumEx(addr, 1, enum_id,0) const_id = idc.GetConstEx(enum_id, imp_addr, 0, -1) fn_name = "fn_"+idc.GetConstName(const_id) off_name = "ptr_"+idc.GetConstName(const_id) # Rename the function to the symbol name. # We append fn_ to the symbol for the function name # and ptr_ to the offset in the table. if not idc.MakeNameEx(addr, fn_name, idaapi.SN_NOWARN): print "[!] Failed to rename function %s at 0x%08x\n" % (fn_name, addr) if not idc.MakeNameEx(current_addr, off_name, idaapi.SN_NOWARN): print "[!] Failed to rename offset %s at 0x%08x\n" % (off_name,current_addr) current_addr += 8 return
def make_enum(self, object_version, address): enum_name = object_version.get_name() object_id = object_version.get_id() # build flags bitfield = False flags = object_version.get_object_flags() if flags & 0x1 == 0x1: bitfield = True flags = flags & ~0x1 try: enum_width = object_version.get_size() except KeyError: enum_width = None # check if enum already exists enum_id = idc.GetEnum(enum_name) enum_xrefs_ids = object_version.get_xrefed_ids() logger.debug( "%s:%d : Check here that enum_xrefs_ids is a set(YaToolObjectId) and correctly used" % (__file__, inspect.currentframe().f_lineno)) if enum_id != idc.BADADDR: # enum already exists, deleting all members for (const_id, const_value, bmask) in YaToolIDATools.enum_member_iterate_all(enum_id): if bmask == idc.BADADDR: bmask = -1 const_name = idc.GetConstName(const_id) if (enum_name, const_name, const_value) not in self.enum_member_ids: idc.DelConstEx(enum_id, const_value, 0, bmask) elif self.hash_provider.get_enum_member_id( enum_id, enum_name, const_id, const_name, const_value) not in enum_xrefs_ids: logger.debug("deleting not found constant : %s/%s" % (enum_name, const_name)) idc.DelConstEx(enum_id, const_value, 0, bmask) """ if the enum "bitfield" state has changed : change it! We can't access the functions """ if idc.IsBitfield(enum_id) != bitfield: idaapi.set_enum_bf(enum_id, bitfield) else: # create enum # SetEnumFlag return "'module' object has no attribute 'set_enum_flag'". enum_id = idc.AddEnum(address, enum_name, flags) if enum_width is not None: idc.SetEnumWidth(enum_id, enum_width) if bitfield: idc.SetEnumBf(enum_id, 1) # process comment try: repeatable_headercomment = self.sanitize_comment_to_ascii( object_version.get_header_comment(True)) idc.SetEnumCmt(enum_id, repeatable_headercomment, 1) except KeyError: pass try: nonrepeatable_headercomment = self.sanitize_comment_to_ascii( object_version.get_header_comment(False)) idc.SetEnumCmt(enum_id, nonrepeatable_headercomment, 0) except KeyError: pass self.enum_ids[object_id] = enum_id self.hash_provider.put_hash_struc_or_enum(enum_id, object_id) logger.debug("adding enum id %s : '0x%.016X'" % (self.hash_provider.hash_to_string(object_id), enum_id))