def parse_hdr(self): ''' Refer: function [go12Init()] in https://golang.org/src/debug/gosym/pclntab.go ''' magic = idc.Dword(self.start_addr) & 0xFFFFFFFF if magic != Pclntbl.MAGIC: print magic, Pclntbl.MAGIC common._error("Invalid pclntbl header magic number!") idc.Exit(1) #raise Exception("Invalid pclntbl header magic number!") idc.MakeDword(self.start_addr) idc.MakeComm(self.start_addr, "Magic Number") idc.MakeNameEx(self.start_addr, "runtime_symtab", flags=idaapi.SN_FORCE) idaapi.autoWait() if idc.Word(self.start_addr + 4) & 0xFFFF != 0: raise Exception("Invalid pclntbl header") idc.MakeWord(self.start_addr + 4) self.min_lc = idc.Byte(self.start_addr + 6) & 0xFF if (self.min_lc != 1) and (self.min_lc != 2) and (self.min_lc != 4): raise Exception("Invalid pclntbl minimum LC!") idc.MakeComm(self.start_addr + 6, "instruction size quantum") idaapi.autoWait() self.ptr_sz = idc.Byte(self.start_addr + 7) & 0xFF if (self.ptr_sz != 4) and (self.ptr_sz != 8): raise Exception("Invalid pclntbl pointer size!") idc.MakeComm(self.start_addr + 7, "ptr size") idaapi.autoWait()
def read_mem(addr, forced_addr_sz=None, read_only=False): global ADDR_SZ if not read_only: if forced_addr_sz: idc.MakeUnknown(addr, forced_addr_sz, idc.DOUNK_SIMPLE) else: idc.MakeUnknown(addr, ADDR_SZ, idc.DOUNK_SIMPLE) idaapi.autoWait() if forced_addr_sz == 2: if not read_only: idc.MakeWord(addr) idaapi.autoWait() return idc.Word(addr) if forced_addr_sz == 4 or ADDR_SZ == 4: if not read_only: idc.MakeDword(addr) idaapi.autoWait() return idc.Dword(addr) if forced_addr_sz == 8 or ADDR_SZ == 8: if not read_only: idc.MakeQword(addr) idaapi.autoWait() return idc.Qword(addr)
def readDefinition(self, ea): # Read all the fields from the stream. self.type = MakeAndGetWord(ea) idc.MakeWord(ea + 2) self.name_address = MakeAndGetDword(ea + 4) self.definition_address = MakeAndGetDword(ea + 8, "definition address") self.group_tag = MakeAndGetString(ea + 12, 4, "group tag") # Read strings. self.name_str = ReadString(self.name_address) # Comment the field type. idc.MakeComm(ea, field_type.field_types[self.type]) # Check if we should comment the name string. if self.name_address < g_BaseAddress: idc.MakeComm(ea + 4, self.name_str) # Check the field type and read the definition accordingly. if self.type == field_type._field_block: # Read the tag block definition. tagBlock = tag_block_definition() tagBlock.readDefinition(self.definition_address) elif self.type == field_type._field_struct: # Ghetto hack to read the struct definition struct. MakeAndGetDword(self.definition_address) MakeAndGetDword(self.definition_address + 4, "group tag") MakeAndGetDword(self.definition_address + 8) blockAddress = MakeAndGetDword(self.definition_address + 12, "block definition address") # Read the tag block definition. tagBlock = tag_block_definition() tagBlock.readDefinition(blockAddress)
def MakeReg(name, offset, size, count=0): idc.MakeNameEx(offset, name, idc.SN_NOCHECK | idc.SN_NOWARN) if (size == 1): idc.MakeByte(offset) elif size == 2: idc.MakeWord(offset) elif size == 4: idc.MakeDword(offset) else: raise NotImplementedError("Register size invalid! Name: " + name) if (count != 0): idc.make_array(offset, count)
def MakeN(addr, size): ''' Make a integer with the given size at the given address. Args: addr (int): effective address. size (int): the size of the integer, one of 1, 2, 4, or 8. ''' if size == 1: idc.MakeByte(addr) elif size == 2: idc.MakeWord(addr) elif size == 4: idc.MakeDword(addr) elif size == 8: idc.MakeQword(addr)
def MakeAndGetWord(ea, comment=None): """ Creates a word at the specified address and returns the word value. :param ea: address to make word at :param comment: optional comment to place at the specified address :return: the value of the word at the specified address """ # Make the word value. idc.MakeWord(ea) # Check if the comment is valid and if so place it at the address. if comment is not None: idc.MakeComm(ea, comment) # Get the word value. return idc.Word(ea)
def locateLocalConstants(self, scs, sds): """Locate and define all of the local strings / numeric constants, that match our observed pattern. Args: scs (list): List of (sark) code segments. sds (list): List of (sark) data segments. """ self._analyzer.logger.info( "Locating local strings / constants in the code sections") for sc in scs: cur_ea = pad(sc.startEA, self._local_alignment) while cur_ea < sc.endEA: # check for a data constant if self.isDataConstant(cur_ea): # check for a string (refs already checked) if self._analyzer.str_identifier.isLocalAsciiString( cur_ea, check_refs=False): length = self._analyzer.str_identifier.defineAsciiString( cur_ea) padded_length = pad(length, self._local_alignment) if padded_length != length: idc.MakeUnknown(cur_ea + length, padded_length - length, 0) idc.MakeData(cur_ea + length, 0, padded_length - length, 0) cur_ea += padded_length # This means it is a constant else: if self._local_pad is None: idc.MakeData(cur_ea, 0, self._local_alignment, 0) else: # check the size of the constant using the byte padding for offset in xrange(self._local_alignment - 1, -1, -1): if idc.Byte(cur_ea + offset) != self._local_pad: break # prepare the bytes idc.MakeUnknown(cur_ea, self._local_alignment, 0) # the data constant - try to make it pretty if offset + 1 == 2: idc.MakeWord(cur_ea) elif offset + 1 == 4: idc.MakeDword(cur_ea) elif offset + 1 == 8: idc.MakeQword(cur_ea) else: idc.MakeData(cur_ea, 0, offset + 1, 0) # the padding idc.MakeData(cur_ea + offset + 1, 0, self._local_alignment - offset + 1, 0) # Now check for a pointer (only supports code pointers for now) if offset + 1 == self._analyzer.addressSize(): value = self._analyzer.parseAdderss(cur_ea) # only support pointers inside our local segment (more probable) if sc.startEA <= value and value < sc.endEA: self._analyzer.markCodePtr( cur_ea, value, aggressive=False) # try a pointer to a declared string else: for sd in sds: if sd.startEA <= value and value <= sd.endEA: line = sark.Line(value) if line.is_string and line.startEA == value: self._analyzer.markDataPtr( cur_ea, value, aggressive=False) break # now move onward cur_ea += self._local_alignment # found nothing, move on else: cur_ea += self._local_alignment