def main(): path = ida_kernwin.ask_file(0, '*.*', 'Select a dumped IAT file.') if not path: return for line in open(path, 'r'): line = line.replace('`', '') # take out ' if exists # parse an address if re.match('^[0-9a-f]{8} ', line): # 32bit addr = line[0:9] symbol = line[19:] bytewise = 4 optype = ida_bytes.FF_DWORD elif re.match('^[0-9a-f]{16} ', line): # 64bit addr = line[0:17] symbol = line[27:] bytewise = 8 optype = ida_bytes.FF_DWORD else: continue if re.match('^.+!.+$', symbol) is None: continue addr = int(addr, 16) _, api = symbol.rstrip().split('!') # only needs a function name # Remove garbage to make IDA understand API's signature # Discard after space (source code path) api = api.split(' ')[0] # Fix for ExitProcess often gets a wrong name if api.endswith('FSPErrorMessages::CMessageMapper::StaticCleanup+0xc'): api = api.replace( 'FSPErrorMessages::CMessageMapper::StaticCleanup+0xc', 'ExitProcess') # Fix for kernelbase.dll related stub functions if api.endswith('Implementation'): api = api.replace('Implementation', '') elif api.endswith('Stub'): api = api.replace('Stub', '') # IDA does not like + api = api.replace('+', '_') print(hex(addr), api) # Set a data type on the IDB ida_bytes.del_items(addr, bytewise, ida_bytes.DELIT_EXPAND) ida_bytes.create_data(addr, optype, bytewise, 0) if idc.set_name(addr, api, SN_CHECK | SN_NOWARN) == 1: continue # Try to name it as <name>_N up to _99 for i in range(100): if idc.set_name(addr, api + '_' + str(i), SN_CHECK | SN_NOWARN) == 1: break if i == 99: idc.set_name(addr, api, SN_CHECK) # Display an error message print( 'Load an appropriate FLIRT signature if it is not applied yet.\n' 'Then, use [Options] > [General] > [Analysis] > [Reanalyze program] to' ' reflect those API signatures.')
def make_array(ea, size): if ea != idc.BADADDR and ea != 0: flags = idc.get_full_flags(ea) if not idc.isByte(flags) or idc.get_item_size(ea) != 1: idc.del_items(ea, idc.DOUNK_SIMPLE, 1) ida_bytes.create_data(ea, ida_bytes.FF_BYTE, 1, ida_idaapi.BADADDR) idc.make_array(ea, size)
def main(): for segstart, segend, segname in enum_segments(): if segname not in ('.rdata', 'UPX1'): continue print(segname) for src, dst, size in find_pointers(segstart, segend): if idc.get_segm_name(dst) not in (".text", "UPX0"): continue if is_code(dst): continue print("new function pointer: 0x%x -> 0x%x" % (src, dst)) ida_auto.auto_make_code(dst) ida_auto.auto_make_proc(dst) ida_bytes.del_items(src, size) ida_bytes.create_data(src, idc.FF_QWORD if size == 8 else idc.FF_DWORD, size, idc.BADADDR) # this doesn't seem to always work :-( idc.op_plain_offset(src, -1, 0) ida_name.set_name(src, "j_%s_%x" % (src, dst))
def req_patch(self, hash): addr, value, length = hash['addr'], hash['value'], hash['len'] if length == 4: prev_value = idc.get_wide_dword(addr) if not ida_bytes.create_data(ea, FF_DWORD, 4, ida_idaapi.BADADDR): rs_log('[x] ida_bytes.create_data FF_DWORD failed') if not ida_bytes.patch_dword(addr, value): rs_log('[x] patch_dword failed') if not idc.op_plain_offset(addr, 0, 0): rs_log('[x] op_plain_offset failed') elif length == 8: prev_value = idc.get_qword(addr) if not ida_bytes.create_data(addr, FF_QWORD, 8, ida_idaapi.BADADDR): rs_log('[x] ida_bytes.create_data FF_QWORD failed') if not ida_bytes.patch_qword(addr, value): rs_log('[x] patch_qword failed') if not idc.op_plain_offset(addr, 0, 0): rs_log('[x] op_plain_offset failed') else: rs_log("[x] unsupported length: %d" % length) return rs_log("patched 0x%x = 0x%x (previous was 0x%x)" % (addr, value, prev_value))
def makeDQWord(self, api): match = re.search(r"\((?P<bitness>..)bit\)", api[2]) if match: bitness = int(match.group("bitness")) if bitness == 32: ida_bytes.create_data(api[0], FF_DWORD, 4, idaapi.BADADDR) elif bitness == 64: ida_bytes.create_data(api[0], FF_QWORD, 8, idaapi.BADADDR)
def _make_array_entry(ea, item_size): if item_size == 4: item_type = idc.FF_DWORD elif item_size == 8: item_type = idc.FF_QWORD else: raise ValueError("Invalid item size") ida_bytes.create_data(ea, item_type, item_size, ida_idaapi.BADADDR)
def __import_names(start_address, names): for addr in range(start_address, start_address + (len(names) * 4), 4): print('0x{:08x}'.format(addr)) ida_bytes.create_data(addr, idc.FF_DWORD, 4, ida_idaapi.BADADDR) name = names.pop(0) idc.set_name(addr, name, idc.SN_NOWARN) return True
def _make_array_entry(ea, item_size): if item_size == 4: item_type = idc.FF_DWORD elif item_size == 8: item_type = idc.FF_QWORD else: raise ValueError("Invalid item size") ida_bytes.create_data(ea, item_type, item_size, ida_idaapi.BADADDR)
def load(infos): for info in infos: ida_name.set_name(info['address'], info['name']) type = info.get('type', None) # TODO this code is kind of mashed together... not sure of the # right way. tid = ida_struct.get_struc_id(type) if type else BADADDR if type: ida_bytes.create_struct(info['address'], info['sz'], tid) ida_bytes.create_data( info['address'], info['flags'], info['sz'], tid)
def load(infos): for info in infos: ida_name.set_name(info['address'], info['name']) # TODO this code is kind of mashed together... not sure of the # right way. tid = ida_struct.get_struc_id( info['type']) if info['type'] else BADADDR if info['type']: print(info['type'], hex(tid)) ida_bytes.create_struct(info['address'], info['sz'], tid) ida_bytes.create_data(info['address'], info['flags'], info['sz'], tid)
def main(): for segstart, segend, segname in enum_segments(): for head in idautils.Heads(segstart, segend): if not is_code(head): continue # pattern: # # lea rax, unk_6BDF88 # mov [rsp+0], rax # mov qword ptr [rsp+8], 40h if ida_ua.ua_mnem(head) != "lea": continue next_head = ida_bytes.next_head(head, idc.BADADDR) if ida_ua.ua_mnem(next_head) != "mov": continue next_head2 = ida_bytes.next_head(next_head, idc.BADADDR) if ida_ua.ua_mnem(next_head2) != "mov": continue dst = idc.get_operand_value(head, 1) if idc.get_segm_name(dst) not in (".rdata", "UPX1"): continue size = idc.get_operand_value(next_head2, 1) if size > 0x100: continue if size <= 2: continue buf = ida_bytes.get_bytes(dst, size) if not buf: continue if b"\x00" in buf: continue try: s = buf.decode("ascii") except UnicodeDecodeError: continue print("string pointer: 0x%x -> 0x%x: %s" % (head, dst, s)) ida_bytes.del_items(dst, 1) ida_bytes.create_data(dst, idc.FF_BYTE, 1, idc.BADADDR) ida_bytes.set_cmt(dst, s, True) ida_name.set_name(dst, "s_%x" % (dst))
def create_table(self): screen_ea = idaapi.get_screen_ea() print("Creating table at: ", hex(screen_ea)) ida_bytes.del_items(screen_ea, 0, 4*6) ret = ida_bytes.create_data(screen_ea, ida_bytes.FF_DWORD, 4, idaapi.BADNODE) print("got return: ", ret) idc.MakeArray(screen_ea, 6)
def implement(self): if self._is_make_data: ea, flags, tid, len = self._type.split(":") ida_bytes.create_data(int(ea), int(flags), int(len), int(tid)) else: py_type = [encode_bytes(t) for t in self._type] if len(py_type) == 3: py_type = py_type[1:] if len(py_type) >= 2: ida_typeinf.apply_type( None, py_type[0], py_type[1], self._ea, ida_typeinf.TINFO_DEFINITE, )
def _defineImportThunk(self, start, thunk_val): """If the binary has the Import Thunk filled, define it as a data chunk of appropriate size. """ info = idaapi.get_inf_structure() if info.is_64bit(): curr_val = idc.get_qword(start) if (curr_val == thunk_val): return ida_bytes.create_data(start, idaapi.FF_QWORD, 8, idaapi.BADADDR) elif info.is_32bit(): curr_val = ida_bytes.get_dword(start) if (curr_val == thunk_val): return ida_bytes.create_data(start, idaapi.FF_DWORD, 4, idaapi.BADADDR) return False
def main(): for segstart, segend, segname in enum_segments(): if segname not in ('.rdata', 'UPX1' ): continue for src, dst, psize in find_pointers(segstart, segend): if idc.get_segm_name(dst) not in (".rdata", "UPX0"): continue if psize == 8: size = ida_bytes.get_qword(src + 0x8) else: size = ida_bytes.get_dword(src + 0x4) if size > 0x100: continue if size <= 2: continue buf = ida_bytes.get_bytes(dst, size) if not buf: continue if b"\x00" in buf: continue try: s = buf.decode("ascii") except UnicodeDecodeError: continue print("string pointer: 0x%x -> 0x%x: %s" % (src, dst, s)) ida_bytes.del_items(src, 1) ida_bytes.set_cmt(dst, s, True) # pointer ida_bytes.del_items(src, psize) ida_bytes.create_data(src, idc.FF_QWORD if size == 8 else idc.FF_DWORD, psize, idc.BADADDR) # this doesn't seem to always work :-( idc.op_plain_offset(src, -1, 0) ida_name.set_name(src, "s_%x" % (src)) ida_bytes.set_cmt(src, s, True) # size ida_bytes.del_items(src + psize, psize) ida_bytes.create_data(src + psize, idc.FF_QWORD if size == 8 else idc.FF_DWORD, psize, idc.BADADDR)
def init_vtable(self): my_start_idx = self.vtable_start_idx() # Fix: support 64bit work if idc.__EA64__: pointer_size = idaapi.DEF_ADDRSIZE pfn_make_ptr = lambda x: ida_bytes.create_data(x, idc.FF_QWORD, 8, idaapi.BADADDR) #MakeQword pfn_get_ptr_value = ida_bytes.get_qword else: pointer_size = idaapi.DEF_ADDRSIZE pfn_make_ptr = lambda x: ida_bytes.create_data(x, idc.FF_DWORD, 4, idaapi.BADADDR) #ida_bytes.MakeDword pfn_get_ptr_value = ida_bytes.get_dword for idx, ea in enumerate(range(self.vtable_start, self.vtable_end, pointer_size)): pfn_make_ptr(ea) idc.op_plain_offset(ea, 0, 0) dst = pfn_get_ptr_value(ea) if idx < my_start_idx: base_method = self.base.vmethods[idx] if base_method.is_dst_equal(dst): # Method from base class self.vmethods.append(self.base.vmethods[idx]) elif Method.s_is_pure_virtual_dst(dst): # New pure virtual override opvm = PureVirtualOverrideMethod(self, base_method, idx) opvm.refresh() self.vmethods.append(opvm) elif Method.s_is_deleted_virtual_dst(dst): # New deleted override dom = DeletedOverrideMethod(self, base_method, idx) dom.refresh() self.vmethods.append(dom) else: # New override om = OverrideMethod(dst, self, base_method, idx) om.refresh() self.vmethods.append(om) elif Method.s_is_pure_virtual_dst(dst): # New pure virtual pvm = PureVirtualMethod(self, 'vf%X' % (idx*4), idx) pvm.refresh() self.vmethods.append(pvm) elif Method.s_is_deleted_virtual_dst(dst): # New deleted virtual pvm = DeletedVirtualMethod(self, 'vf%X' % (idx*4), idx) pvm.refresh() self.vmethods.append(pvm) else: # New virtual vm = VirtualMethod(dst, self, 'vf%X' % (idx*4), idx) vm.refresh() self.vmethods.append(vm)
def load_file(f, neflags, format): f.seek(0) magic = f.read(4) version = struct.unpack("<I", f.read(4))[0] flags = struct.unpack("<I", f.read(4))[0] memType = struct.unpack("<I", f.read(4))[0] serviceType = struct.unpack("<I", f.read(4))[0] numInstances = struct.unpack("<I", f.read(4))[0] uuid = struct.unpack("<IIII", f.read(16)) driverId = struct.unpack("<I", f.read(4))[0] numThreads = struct.unpack("<I", f.read(4))[0] textVA = struct.unpack("<I", f.read(4))[0] textLen = struct.unpack("<I", f.read(4))[0] dataVA = struct.unpack("<I", f.read(4))[0] dataLen = struct.unpack("<I", f.read(4))[0] bssLen = struct.unpack("<I", f.read(4))[0] entry = struct.unpack("<I", f.read(4))[0] f.seek(MCLF_TEXT_INFO_OFFSET) idaapi.set_processor_type("arm", ida_idp.SETPROC_LOADER_NON_FATAL) # Set VA for .text and add the segment f.file2base(0, textVA, textVA + textLen, True) idaapi.add_segm(0, textVA, textVA + textLen, ".text", "CODE") # Set VA for .data and add the segment f.file2base(textLen, dataVA, dataVA + dataLen, True) idaapi.add_segm(0, dataVA, dataVA + dataLen, ".data", "DATA") # Add BSS segment after .text and .data idaapi.add_segm(0, dataVA + dataLen, dataVA + dataLen + bssLen, ".bss", "BSS") if entry % 4 == 1: #Thumb address is always +1 to set the T bit idaapi.add_entry(entry - 1, entry - 1, "_entry", 1) idc.split_sreg_range(entry - 1, "T", 0x1, ida_segregs.SR_user) else: idaapi.add_entry(entry, entry, "_entry", 1) idc.split_sreg_range(entry, "T", 0x0, ida_segregs.SR_user) ida_bytes.create_data(tlApiLibEntry, idaapi.FF_DWORD, 4, idaapi.BADADDR) idc.set_name(tlApiLibEntry, "tlApiLibEntry", ida_name.SN_CHECK) return 1
def __init__(self, logger, num_bits, is_elf, data_fptr_alignment=4, mixed_code_and_data=False): """Create the analyzer's base class instance. Args: logger (logger): logger instance num_bits (int): bitness of the CPU (32 bits by default) data_fptr_alignment (int, optional): byte alignment needed for global fptrs (4 by default) mixed_code_and_data (bool, optional): True iff the main code section includes RO data constants (False by default) """ self.logger = logger self._num_bits = num_bits self._is_elf = is_elf self.data_fptr_alignment = data_fptr_alignment self._mixed_code_and_data = mixed_code_and_data if num_bits == 64: self._address_parse_fn = idc.get_qword self._address_make_fn = lambda x: ida_bytes.create_data( x, idc.FF_QWORD, 8, idc.BADADDR) self.address_pack_format = "Q" elif num_bits == 32: self._address_parse_fn = idc.get_wide_dword self._address_make_fn = lambda x: ida_bytes.create_data( x, idc.FF_DWORD, 4, idc.BADADDR) self.address_pack_format = "L" else: self._address_parse_fn = idc.get_wide_word self._address_make_fn = lambda x: ida_bytes.create_data( x, idc.FF_WORD, 2, idc.BADADDR) self.address_pack_format = "H" # fields to be linked later on self.func_classifier = None self.fptr_identifier = None self.str_identifier = None self.locals_identifier = None self.switch_identifier = None # code types self._active_code_types = list(self.codeTypes())
def MakeN(addr: int, size: int) -> None: """ 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: ida_bytes.create_data(addr, ida_bytes.FF_BYTE, 1, ida_idaapi.BADADDR) elif size == 2: ida_bytes.create_data(addr, ida_bytes.FF_WORD, 2, ida_idaapi.BADADDR) elif size == 4: ida_bytes.create_data(addr, ida_bytes.FF_DWORD, 4, ida_idaapi.BADADDR) elif size == 8: ida_bytes.create_data(addr, ida_bytes.FF_QWORD, 8, ida_idaapi.BADADDR)
def is_qword(self, value): """ Property setter which allow to transform this object in a defined object on 8 bytes. If set as False the value is undefined whichever its previous type. :param value: True for setting this data object as being on 8 bytes, False for undefining the object type. :raise RuntimeError: If value was True and it was not able to correctly set the type for current item. """ if value: if not ida_bytes.create_data(self.ea, ida_bytes.FF_QWORD, 8, idc.BADADDR): raise RuntimeError("Unable to set type for {}".format(self)) else: del self.type
def nDB(ea, name): ida_bytes.create_data(ea, ida_bytes.FF_BYTE, 1, ida_idaapi.BADADDR) ida_name.set_name(ea, name, ida_name.SN_NOCHECK)
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.start_ea, self._local_alignment) while cur_ea < sc.end_ea: # 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: ida_bytes.del_items(cur_ea + length, 0, padded_length - length) ida_bytes.create_data(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: ida_bytes.create_data(cur_ea, 0, self._local_alignment, 0) else: # check the size of the constant using the byte padding for offset in range(self._local_alignment - 1, -1, -1): if idc.get_wide_byte( cur_ea + offset) != self._local_pad: break # prepare the bytes ida_bytes.del_items(cur_ea, 0, self._local_alignment) # the data constant - try to make it pretty if offset + 1 == 2: ida_bytes.create_data(cur_ea, idc.FF_WORD, 2, idc.BADADDR) elif offset + 1 == 4: ida_bytes.create_data(cur_ea, idc.FF_DWORD, 4, idc.BADADDR) elif offset + 1 == 8: ida_bytes.create_data(cur_ea, idc.FF_QWORD, 8, idc.BADADDR) else: ida_bytes.create_data(cur_ea, 0, offset + 1, 0) # the padding ida_bytes.create_data( 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.start_ea <= value and value < sc.end_ea: self._analyzer.markCodePtr( cur_ea, value, aggressive=False) # try a pointer to a declared string else: for sd in sds: if sd.start_ea <= value and value <= sd.end_ea: line = sark.Line(value) if line.is_string and line.start_ea == 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
for name, (addr, size) in data["peripherals"].items(): seg = ida_segment.getseg(addr) if seg: old_name = ida_segment.get_segm_name(seg) ida_segment.set_segm_name(seg, "%s_%s" % (old_name, name)) else: add_segment(addr, size, name) for name, (addr, reg_count, reg_size, clu_count, clu_size) in data["addresses"].items(): for m in range(clu_count): for n in range(reg_count): reg_name = name.replace('<m>', str(m)).replace('<n>', str(n)) reg_addr = addr + m * clu_size + n * reg_size ida_bytes.create_data(reg_addr, { 1: ida_bytes.byte_flag(), 2: ida_bytes.word_flag(), 4: ida_bytes.dword_flag() }[reg_size], reg_size, ida_netnode.BADNODE) ida_name.set_name(reg_addr, reg_name) base_addr = ida_segment.get_segm_by_name("ROM").start_ea for name, offset in data["interrupts"].items(): addr = base_addr + (16 + offset) * 4 name = "%s_%s" % ("arm" if offset < 0 else "irq", name.lower()) ida_bytes.del_items(addr, 0, 4) ida_bytes.create_dword(addr, 4, True) ida_name.set_name(addr, name, 0) if ida_bytes.get_dword(addr) > 0: ida_offset.op_plain_offset(addr, 0, 0)
def run(self, arg): for function in idautils.Functions(): values = {} #function = ida_kernwin.get_screen_ea() function_start = idc.get_func_attr(function, idc.FUNCATTR_START) function_end = idc.get_func_attr(function, idc.FUNCATTR_END) function_name = idc.get_func_name(function) if re.search("func\d+", function_name): try: decompiled_code = str(ida_hexrays.decompile(function)) lenght = re.search(r"i < (\w+); \+\+i", decompiled_code) if lenght != None: # Getting hex values displayed in the decompiled code values[function_name] = [] for z in re.findall("= (0[xX][0-9a-fA-F]+)", decompiled_code): values[function_name].append( binascii.hexlify( struct.pack( '<Q', int(int(z.replace("0x", ""), base=16)))).decode( "windows-1252").replace( "00", "")) # Getting values from xmmwords xmmwords = re.findall(r"xmmword_(\w+)", decompiled_code) for xmmword in xmmwords: #print(f"\nxmmword_{xmmword} -> {int(xmmword, 16)}") ida_bytes.create_data( int(xmmword, 16), ida_bytes.byte_flag(), 1, ida_netnode.BADNODE ) # create byte at the specified address data = binascii.hexlify( idaapi.get_bytes( int(xmmword, 16), int(lenght.group(1), 16))).decode("windows-1252") values[function_name].append(data) #print(binascii.hexlify(idaapi.get_bytes(int(xmmword, 16), int(lenght, 16)))) # get bytes except idaapi.DecompilationFailure: pass try: lenght = int(len(values[function_name]) / 2) string = self.to_decimal(values[function_name][0:lenght]) key = self.to_decimal(values[function_name][lenght::]) str_decrypted = "" for i in range(0, len(string)): str_decrypted += chr(string[i] ^ key[i % len(key)]) #idaapi.msg(f"{string[i]} ^ {key[i % len(key)]}\n") if str_decrypted != "": #idaapi.msg(str_decrypted+"\n") idc.set_func_cmt(function_start, str_decrypted, 0) rowPosition = self.plg.table.rowCount() self.plg.table.insertRow(rowPosition) self.plg.table.setItem( rowPosition, 0, QtWidgets.QTableWidgetItem( function_name.replace(".", "_"))) self.plg.table.setItem( rowPosition, 1, QtWidgets.QTableWidgetItem(str_decrypted)) except: pass
def nDD(ea, name): ida_bytes.create_data(ea, ida_bytes.FF_DWORD, 4, ida_idaapi.BADADDR) ida_name.set_name(ea, name, ida_name.SN_NOCHECK)
def __call__(self): ida_bytes.create_data(self.ea, self.flags, self.size, self.tid)
def run(self, arg): for function in idautils.Functions(): values = {} #function = ida_kernwin.get_screen_ea() function_start = idc.get_func_attr(function, idc.FUNCATTR_START) function_end = idc.get_func_attr(function, idc.FUNCATTR_END) function_name = idc.get_func_name(function) if re.search("func\d+", function_name): try: decompiled_code = str(ida_hexrays.decompile(function)) lenght = re.search(r"i < (\w+); \+\+i", decompiled_code) if lenght != None: # Getting hex values displayed in the decompiled code values[function_name] = [] for z in re.findall(" = 0[xX]([0-9a-fA-F]+)", decompiled_code): swapped_list = [] for i in range(0, len(z), 2): swapped_list.insert(0, z[i:i + 2]) z = "".join(map(str, swapped_list)) #print(f"\n{function_name}: {z}") values[function_name].append(z) #print(f"Appending: {z} {function_name}") # Getting values from xmmword and unk_ chunks xmmwords = re.findall(r"xmmword_(\w+)", decompiled_code) for xmmword in xmmwords: #print(f"\nxmmword_{xmmword} -> {int(xmmword, 16)}") ida_bytes.create_data( int(xmmword, 16), ida_bytes.byte_flag(), 1, ida_netnode.BADNODE ) # create byte at the specified address data = binascii.hexlify( idaapi.get_bytes( int(xmmword, 16), int(lenght.group(1), 16))).decode("windows-1252") values[function_name].append(data) #print(binascii.hexlify(idaapi.get_bytes(int(xmmword, 16), int(lenght, 16)))) # get bytes unks_data = re.findall(r"qmemcpy.*&unk_(.*),", decompiled_code) if unks_data != []: values[function_name] = [] for unk in unks_data: unk_data = data = binascii.hexlify( idaapi.get_bytes( int(unk, 16), int(lenght.group(1), 16))).decode("windows-1252") values[function_name].append(unk_data) #print(f"""\n{function_name} #unk_{unk}: {unk_data} #""") #print(f"Appending: {unk_data} {function_name}") except idaapi.DecompilationFailure: pass try: lenght = int(len(values[function_name]) / 2) #print(function_name) string = self.to_decimal(values[function_name][0:lenght]) key = self.to_decimal(values[function_name][lenght::]) # print(f""" # String: {string} # Key: {key} # Lenght: {lenght} # """) str_decrypted = "" for i in range(0, len(key)): str_decrypted += chr(string[i % len(string)] ^ key[i % len(key)]) #idaapi.msg(f"\n{hex(string[i % len(string)])} ^ {hex(key[i % len(key)])} {chr(string[i % len(string)] ^ key[i % len(key)])}\n") if str_decrypted != "": #idaapi.msg("Decrypted: "+str_decrypted+"\n") idc.set_func_cmt(function_start, str_decrypted, 0) rowPosition = self.plg.table.rowCount() self.plg.table.insertRow(rowPosition) self.plg.table.setItem( rowPosition, 0, QtWidgets.QTableWidgetItem( function_name.replace(".", "_"))) self.plg.table.setItem( rowPosition, 1, QtWidgets.QTableWidgetItem(str_decrypted)) except: pass
def __call__(self): ida_bytes.create_data( self.ea, ida_bytes.calc_dflags(self.flags, True), self.size, ida_struct.get_struc_id(self.sname) if self.sname else ida_netnode.BADNODE)
def load_file(f, neflags, format): f.seek(0) ida_idp.set_processor_type("metapc", ida_idp.SETPROC_LOADER) MGROUPStart = 0 magic = f.read(2) if magic == MZ_HEADER_MAGIC: f.seek(0x22) MGROUPStart = DW(f) * 16 f.seek(MGROUPStart) magic = f.read(2) headerSize = DW(f) segmentDataAlignment = DW(f) nextExeOff = DD(f) SegDataOff = DD(f) f.file2base(MGROUPStart, 0, SegDataOff, True) ida_segment.add_segm(0, 0, 0x50, "HEADER", "MODULE") f.seek(MGROUPStart + 2) headerSize = rnDW(f, "headerSize", MGROUPStart) segmentDataAlignment = rnDW(f, "segmentDataAlignment", MGROUPStart) nextExeOff = rnDD(f, "nextExeOff", MGROUPStart) SegDataOff = rnDD(f, "SegDataOff", MGROUPStart) ResDataOff = rnDD(f, "ResDataOff", MGROUPStart) flags = rnDW(f, "flags", MGROUPStart) version = rnDB(f, "version", MGROUPStart) revision = rnDB(f, "revision", MGROUPStart) AutoDataSegNo = rnDW(f, "AutoDataSegNo", MGROUPStart) HeapSize = rnDW(f, "HeapSize", MGROUPStart) StackSize = rnDW(f, "StackSize", MGROUPStart) StartProc = rnDD(f, "StartProc", MGROUPStart) LoadProc = rnDD(f, "LoadProc", MGROUPStart) FreeProc = rnDD(f, "FreeProc", MGROUPStart) nSegments = rnDW(f, "nSegments", MGROUPStart) pSegTable = rnDW(f, "pSegTable", MGROUPStart) cbResTab = rnDW(f, "cbResTab", MGROUPStart) pResTab = rnDW(f, "pResTab", MGROUPStart) cbEntTab = rnDW(f, "cbEntTab", MGROUPStart) pEntTab = rnDW(f, "pEntTab", MGROUPStart) cbNamTab = rnDW(f, "cbNamTab", MGROUPStart) pNamTab = rnDW(f, "pNamTab", MGROUPStart) cbStrTab = rnDW(f, "cbStrTab", MGROUPStart) pStrTab = rnDW(f, "pStrTab", MGROUPStart) cbNRNamTab = rnDW(f, "cbNRNamTab", MGROUPStart) pNRNamTab = rnDW(f, "pNRNamTab", MGROUPStart) ida_segment.add_segm(0, pSegTable, pSegTable + (nSegments * SEG_STRUCT_SIZE), "SEGTABLE", "MODULE") ida_segment.add_segm(0, pResTab, pResTab + cbResTab, "RESOURCES", "MODULE") ida_segment.add_segm(0, pEntTab, pEntTab + cbEntTab, "ENTTABLE", "MODULE") ida_segment.add_segm(0, pNamTab, pNamTab + cbNamTab, "ENTNAME", "MODULE") ida_segment.add_segm(0, pStrTab, pStrTab + cbStrTab, "IMPORTS", "MODULE") ida_segment.add_segm(0, pNRNamTab, pNRNamTab + cbNRNamTab, "NRENTNAME", "MODULE") #parse segtable segentsid = defSEGENT() base = SegDataOff // 16 importCount = 0 for i in range(nSegments): segEntStart = pSegTable + i * SEG_STRUCT_SIZE ida_bytes.create_struct(segEntStart, SEG_STRUCT_SIZE, segentsid) segStart = ida_bytes.get_word(segEntStart + 2) segLen = ida_bytes.get_word(segEntStart + 4) segImports = ida_bytes.get_word(segEntStart + 6) importCount += segImports f.file2base(MGROUPStart + SegDataOff + segStart * 16, SegDataOff + segStart * 16, SegDataOff + (segStart + segLen) * 16, True) segBase = (base + segStart) * 16 #segmentDef = ida_segment.segment_t() #segmentDef.start_ea = segBase #segmentDef.end_ea = (base+segStart+segLen)*16 #ida_segment.set_selector() print(base + segStart) ida_segment.add_segm(base + segStart, segBase, (base + segStart + segLen) * 16, "", "", 0) sel = ida_segment.find_selector(base + segStart) seg = ida_segment.getseg(segBase) ida_segment.set_segm_addressing(seg, 0) segtable[i] = seg segimportstable[i] = segImports if i + 1 == AutoDataSegNo: ida_segment.set_segm_name(seg, "DATA", 0) ida_segment.set_segm_class(seg, "DATA", 0) dataSel = sel else: ida_segment.set_segm_name(seg, "TEXT", 0) ida_segment.set_segm_class(seg, "CODE", 0) if AutoDataSegNo == 0: dataSel = sel ida_segregs.set_default_dataseg(dataSel) #parse enttable pENT = pEntTab currord = 1 while pENT < pEntTab + cbEntTab: bundleCount = ida_bytes.get_byte(pENT) bundleFlags = ida_bytes.get_byte(pENT + 1) if bundleCount == 0 and bundleFlags == 0: break pENT += 2 for i in range(bundleCount): if bundleFlags == 0xFF: ordFlags = ida_bytes.get_byte(pENT) if ordFlags & 0x80: toexport.append(currord) segNo = ida_bytes.get_byte(pENT + 3) segOff = ida_bytes.get_word(pENT + 4) enttable[currord] = (segtable[segNo - 1].start_ea // 16, segOff) pENT += 6 else: ordFlags = ida_bytes.get_byte(pENT) if ordFlags & 0x80: toexport.append(currord) segOff = ida_bytes.get_word(pENT + 1) enttable[currord] = (segtable[bundleFlags - 1].start_ea // 16, segOff) pENT += 3 currord += 1 modulename = readPASSTR(pNamTab) make_entry(StartProc, modulename + "_start") make_entry(LoadProc, modulename + "_load") make_entry(FreeProc, modulename + "_free") #export named ordinals namedordtable = loadExportsF(f) for i in toexport: if i in namedordtable: name = namedordtable[i] else: name = "Ordinal" + str(i) (base, off) = enttable[i] addr = base * 16 + off ida_entry.add_entry(i, addr, name, 1) #process imports ida_segment.add_segm(0xF000, 0xF0000, 0xF0000 + importCount * 2, "IMPORTS", "XTRN", 0) import_ea = 0xF0000 for seg in segtable: segend = segtable[seg].end_ea f.seek(MGROUPStart + segend) for i in range(segimportstable[seg]): count = DB(f) mode = DB(f) relocStart = DW(f) module = DW(f) proc = DW(f) if (module == 0xFFFF): (base, off) = enttable[proc] else: modulestr = readPASSTR(pStrTab + module) if (proc & 0x8000) != 0: # read by ord ordinal = proc & 0x7FFF procname = modulestr + "_Ordinal" + str(ordinal) if not modulestr in importedmodules: if os.path.isfile(modulestr + ".EXE"): importedmodules[modulestr] = loadExports( modulestr + ".EXE") else: filename = ida_kernwin.ask_file( 0, modulestr + ".EXE", "Select file to name exports") if filename is not None and os.path.isfile( filename): importedmodules[modulestr] = loadExports( filename) else: importedmodules[modulestr] = None if modulestr in importedmodules and ( importedmodules[modulestr] is not None ) and ordinal in importedmodules[modulestr]: procname = importedmodules[modulestr][ordinal] else: procname = readPASSTR(pStrTab + proc) ida_bytes.create_data(import_ea, ida_bytes.FF_WORD, 2, ida_idaapi.BADADDR) ida_name.force_name(import_ea, procname) ida_bytes.set_cmt(import_ea, "Imported from " + modulestr, 1) base = 0xF000 off = import_ea - 0xF0000 import_ea += 2 for xx in range(count): next = ida_bytes.get_word(segtable[seg].start_ea + relocStart) if mode == 0x20: ida_bytes.put_word(segtable[seg].start_ea + relocStart + 2, base) ida_bytes.put_word(segtable[seg].start_ea + relocStart, off) elif mode == 0x10: ida_bytes.put_word(segtable[seg].start_ea + relocStart, off) elif mode == 0x0: ida_bytes.put_word(segtable[seg].start_ea + relocStart, base) relocStart = next #print "import %d: seg %d mode %s count %d relocStart %s module %s proc %s" % (i, seg, hex(mode), count, hex(relocStart), modulestr, hex(proc)) return 1
def load_file(f: ida_idaapi.loader_input_t, neflags: Any, format: Any) -> int: """ load the given file into the current IDA Pro database. Args: f (file): the file-like object to load. neflags (Any): unused format (Any): unused Returns: int: 1 on success, 0 on failure """ # compute file size, then read the entire contents f.seek(0x0, os.SEEK_END) flen = f.tell() f.seek(0x0) buf = f.read(flen) # mark the proc type, so IDA can invoke the correct disassembler/processor. # this must match `processor.wasm_processor_t.psnames` ida_idp.set_processor_type('wasm', ida_idp.SETPROC_LOADER_NON_FATAL) f.seek(0x0) # load the entire file directly at address zero. f.file2base(0, 0, len(buf), True) p = 0 sections = wasm.decode_module(buf) for i, section in enumerate(sections): if i == 0: sname = 'header' else: if section.data.id == wasm.wasmtypes.SEC_UNK: if section.data.name: sname = section.data.name.tobytes().decode('utf-8') else: sname = '' else: sname = idawasm.const.WASM_SECTION_NAMES.get( section.data.id, 'unknown') if sname != 'header' and section.data.id in ( wasm.wasmtypes.SEC_CODE, wasm.wasmtypes.SEC_GLOBAL): stype = 'CODE' else: stype = 'DATA' # add IDA segment with type, name, size as appropriate slen = sum(section.data.get_decoder_meta()['lengths'].values()) ida_segment.add_segm(0, p, p + slen, sname, stype) if sname != 'header': loader = SECTION_LOADERS.get(section.data.id) if loader is not None: loader(section, p) load_section(section, p) p += slen # magic ida_bytes.create_data(0x0, ida_bytes.FF_DWORD, 4, ida_idaapi.BADADDR) ida_name.set_name(0x0, 'WASM_MAGIC', ida_name.SN_CHECK) # version ida_bytes.create_data(0x4, ida_bytes.FF_DWORD, 4, ida_idaapi.BADADDR) ida_name.set_name(0x4, 'WASM_VERSION', ida_name.SN_CHECK) return 1
def MakeQWord(self, ea): if idaapi.IDA_SDK_VERSION < 700: return idc.MakeQword(ea) else: return ida_bytes.create_data(ea, FF_QWORD, 8, idaapi.BADADDR)