def __PltResolver(jmprel, strtab, symtab, pltgot): seg_sec = idc.selector_by_name('.plt.sec') sec_start = idc.get_segm_by_sel(seg_sec) sec_end = idc.get_segm_end(sec_start) if sec_start == idaapi.BADADDR: print("[-] can't find .plt.sec segment") return idx = 0 while True: r_off = idc.get_wide_dword(jmprel + 0x8 * idx) r_info1 = idc.get_wide_byte(jmprel + 0x8 * idx + 0x4) r_info2 = idc.get_wide_byte(jmprel + 0x8 * idx + 0x5) if r_off > 0x7fffffff: return if r_info1 == 7: st_name = idc.get_wide_dword(symtab + r_info2 * 0x10) name = idc.get_strlit_contents(strtab + st_name) # rename got idc.set_name(r_off, name.decode("ascii") + '_ptr') plt_func = idc.get_wide_dword(r_off) # rename plt idc.set_name(plt_func, 'j_' + name.decode("ascii")) SetFuncFlags(plt_func) # rename plt.sec for addr in idautils.DataRefsTo(r_off): plt_sec_func = idaapi.get_func(addr) if plt_sec_func: plt_sec_func_addr = plt_sec_func.start_ea idc.set_name(plt_sec_func_addr, '_' + name.decode("ascii")) SetFuncFlags(plt_sec_func_addr) else: print("[!] idaapi.get_func({}) failed".format( hex(addr))) got_off = r_off - pltgot target = '+{}h'.format( hex(got_off).lower().replace('0x', '').replace('l', '').rjust(2, '0')) for func_ea in idautils.Functions(sec_start, sec_end): func = idaapi.get_func(func_ea) cur = func.start_ea end = func.endEA find = False while cur <= end: code = idc.GetDisasm(cur).lower().replace(' ', '') if target in code: find = True break cur = idc.NextHead(cur, end) if find: idc.set_name(func_ea, '_' + name) SetFuncFlags(func_ea) idx += 1
def get_j_val(ea): size = 0 j_val = 0 op1 = idc.get_wide_byte(ea) if op1 == 0x0f: # jz or jnz j_val = idc.get_wide_dword(ea + 2) size = 6 else: # jz short or jnz short j_val = idc.get_wide_byte(ea + 1) size = 2 return j_val, size
def decrypt_string(idx): if idx >= 0x36F4: return # out of bounds res = "" while True: c = idc.get_wide_byte(enc_strings + idx) ^ idc.get_wide_byte(bytes_arr + (idx & 0x3F)) if c == 0: break res += chr(c) idx += 1 return res
def isLocalAsciiString(self, ea, check_refs=True): r"""Check if the given address is the beginning of a valid local string. Args: ea (int): effective address to be checked Notes ----- 0. If selected, the string must have a data reference to it. 1. The string should be aligned (local alignment). 2. The string should only contain chars from our alpha-bet. 3. The string should be '\0' terminated. 4. If applicable, the string should be padded with the correct padding byte. 5. The string's length must follow one of the following rules: a) Larger than the local alignment. b) At least 2 bytes, and the first is '%' (for short format strings). c) Exactly one byte, and it should be a punctuation char. d) At least 3 bytes. Return Value: True iff the given address could be the start of a local string """ # line should be referenced (as data) if check_refs and not self._analyzer.locals_identifier.isDataConstant( ea): return False str_content = self.getAsciiString(ea) # check each of the chars if str_content is None or len( list( filter(lambda x: chr(x) in self._valid_alphabet, str_content))) != len(str_content): return False # check for a '\0' terminator if idc.get_wide_byte(ea + len(str_content)) != ord('\0'): return False # check for the correct padding if self._local_pad is not None: end_address = ea + len(str_content) + 1 for offset in range(padSize(end_address, self._local_alignment)): if idc.get_wide_byte(end_address + offset) != self._local_pad: return False # filtering heuristic if len(str_content) > self._local_alignment: return True elif len(str_content) > 1 and chr(str_content[0]) == '%': return True elif len(str_content) == 1 and chr( str_content[0]) in string.punctuation: return True else: return len(str_content) > 2
def patch(): ea = idc.find_binary(0, idc.SEARCH_NEXT | idc.SEARCH_DOWN | idc.SEARCH_CASE, PATTERN) start_addr = None pattern_len = _pattern_len(PATTERN) while not (ea == ida_idaapi.BADADDR or idc.get_segm_name(ea) != '.text'): # If we don't have start address saved, save it and search for the next pattern match if not start_addr: start_addr = ea # If start address was saved before, we got end address. It's time to patch else: # Remove marker patterns to prevent re-encryption on the next script run fill_with_nops(start_addr, start_addr + pattern_len) fill_with_nops(ea, ea + pattern_len) # Decrypt the code between markers for addr in range(start_addr + pattern_len, ea): ida_bytes.patch_byte(addr, ~idc.get_wide_byte(addr)) print('[0x%08X..0x%08X] Region patched' % (start_addr, ea + pattern_len)) start_addr = None ea = idc.find_binary( ea, idc.SEARCH_NEXT | idc.SEARCH_DOWN | idc.SEARCH_CASE, PATTERN) print('[PATCHING FINISHED]')
def decryptor(index, call_addr): decrypted_string = "" current_struct_start = struct_start + 8 * index current_struct_bytes = idc.get_bytes(current_struct_start, 8) print(current_struct_bytes.hex()) #structure parsing and xoring key = int.from_bytes(current_struct_bytes[0:1], byteorder='little', signed=False) length = int.from_bytes(current_struct_bytes[2:4], byteorder='little', signed=False) buffer_string_addr = int.from_bytes(current_struct_bytes[4:8], byteorder='little', signed=False) print(hex(key), hex(length), hex(buffer_string_addr)) #decrypting for i in range(0, length): decrypted_string += chr(key ^ idc.get_wide_byte(buffer_string_addr + i)) print(decrypted_string) #commenting assembly view idc.set_cmt(call_addr, decrypted_string, 0) #commenting decompile view on the same address as assembly view cfunc = idaapi.decompile(call_addr) tl = idaapi.treeloc_t() tl.ea = call_addr tl.itp = idaapi.ITP_SEMI cfunc.set_user_cmt(tl, decrypted_string) cfunc.save_user_cmts()
def get_header_idb(): """get file header from idb""" if idc.get_segm_name(0) == "HEADER": header = bytearray( [idc.get_wide_byte(ea) for ea in range(0, idc.get_segm_end(0))]) return header return bytearray(b"")
def isinthunk(winname, thunk): ea, name = thunk funcstart = idc.get_func_attr(ea, idc.FUNCATTR_START) funcend = idc.get_func_attr(ea, idc.FUNCATTR_END) if funcend - funcstart > 20: # Highest I've seen is 13 opcodes but this works ig return False addr = idc.next_head(funcstart, funcend) if addr == idc.BADADDR: return False b = idc.get_wide_byte(addr) if b in (0xEB, 0xE9): dis = idc.generate_disasm_line(addr, 0) try: funcname = dis[dis.find("jmp") + 3:].strip() if funcname.find("short") != -1: funcname = funcname[funcname.find("short") + 5:].strip() # When this function gets typed, a comment is added # Remove it if funcname.find(";") != -1: funcname = funcname[:funcname.find(";")] if funcname == winname: return True except: pass return False
def getKindEnumName(self, addr): try: struc_id = ida_struct.get_struc_id("type") offset_kind = idc.get_member_offset(struc_id, "kind") kind = idc.get_wide_byte(addr + offset_kind) & 0x1F return self.settings.typer.standardEnums[0][1][kind] except IndexError as e: pass
def _getbytes(self, start, l=1): out = [] for ad in range(l): offset = ad + start + self.base_address if not is_mapped(offset): raise IOError("not enough bytes") out.append(int_to_byte(get_wide_byte(offset))) return b''.join(out)
def decide(self): """Sum up the information from all of the seen records, and decide what is the alignment pattern. Return Value: (alignment, pad byte) if found a full pattern, (alignment, None) if no padding, and None for errors. """ # Sanity check if len(self._records) < 2: return None # Now check for a basic alignment rule seen_eas = list(map(lambda x: x[0], self._records)) # Deterministic results per binary, but still random random.seed(struct.unpack("!I", ida_nalt.retrieve_input_file_md5()[:4])[0]) while True: # Check against two random candidates, and always make sure the representative isn't rare measure_candidate = seen_eas[random.randint(0, len(seen_eas) - 1)] measure_candidate_alt = seen_eas[random.randint(0, len(seen_eas) - 1)] gcds = list(map(lambda x: gcd(measure_candidate, x), seen_eas)) gcds_alt = list(map(lambda x: gcd(measure_candidate_alt, x), seen_eas)) alignment = min(gcds) alignment_alt = min(gcds_alt) if alignment > alignment_alt: alignment = alignment_alt measure_candidate = measure_candidate_alt try_again = True elif alignment != alignment_alt: try_again = True else: try_again = False # Try to check if removing outliers will improve the alignment if try_again or gcds.count(alignment) <= len(gcds) * 0.01: # pick the next element, and try to improve the result seen_eas = list(filter(lambda x: gcd(measure_candidate, x) != alignment, seen_eas)) # we can't improve the results else: break # We shouldn't look for padding bytes (we have no size) if self._records[0][1] is None: return alignment # Alignment is 1, there is no padding to be found if alignment == 1: return (alignment, None) # Check if there is a common padding byte (skip the outliers) pad_byte = None for ea, size in filter(lambda x: x[0] % alignment == 0, self._records): for offset in range((alignment - ((ea + size) % alignment)) % alignment): test_byte = idc.get_wide_byte(ea + size + offset) if pad_byte is None: pad_byte = test_byte # Failed to find a single padding byte... elif pad_byte != test_byte: return (alignment, None) # Found a padding byte :) if pad_byte is not None: return (alignment, pad_byte) # There were no gaps to be padded, no padding is needed else: return (alignment, None)
def execute(self, ip=None): """ "Execute" the instruction at IP and store results in the context. The RIP/EIP register will be set to the value supplied in IP so that it is correct. :param ip: instruction address to execute (defaults to currently set ip) """ if not ip: ip = self.ip # Set instruction pointer to where we are currently executing. self.ip = ip # Determine if a rep* instruction and add termination condition. term_condition = None if idc.get_wide_byte(ip) in (0xF2, 0xF3): insn = idc.GetDisasm(ip) # IDA pro never has operands for rep opcodes. if insn.startswith("rep "): term_condition = lambda: self.registers.ecx == 0 elif insn.startswith(("repe ", "repz ")): term_condition = lambda: self.registers.ecx == 0 or self.registers.zf == 0 elif insn.startswith(("repne ", "repnz ")): term_condition = lambda: self.registers.ecx == 0 or self.registers.zf == 1 # Emulate instruction. mnem = idc.print_insn_mnem(ip) operands = self.operands instruction = self.OPCODES.get(mnem) if instruction: try: if term_condition: # As a safety measure, don't allow rep instructions to surpass # our max memory read limit. if self.registers.ecx > self.memory.MAX_MEM_READ: logger.warning( "0x{:08X} :: Emulation attempted to read {} instruction {} times. " "Ignoring instruction.".format(ip, mnem, self.registers.ecx) ) else: logger.debug("Emulating {} instruction {} times.".format(mnem, self.registers.ecx)) while not term_condition(): instruction(self, ip, mnem, operands) self.registers.ecx -= 1 else: instruction(self, ip, mnem, operands) except Exception: logger.exception("Failed to execute address 0x{:X}: {}".format(ip, idc.GetDisasm(ip))) else: logger.debug("{} instruction not implemented.".format(mnem)) # Record executed instruction. self.executed_instructions.append(ip) # After execution, set instruction pointer to next instruction assuming # standard code flow and if no jump was made. if self.ip == ip: self.ip = idc.next_head(ip)
def simplify_jumps(ea): # If we got long first conditional jump if idc.get_wide_byte(ea) == 0x0F: alternative_jmp_cmd = idc.get_wide_byte(ea + 1) ^ 1 interm_jmp_offt = 6 else: alternative_jmp_cmd = idc.get_wide_byte(ea) ^ 0xF1 interm_jmp_offt = 2 # Get intermediate jump's value if idc.get_wide_byte(ea + interm_jmp_offt) == 0x0F: interm_jmp_param = idc.get_wide_dword(ea + interm_jmp_offt + 2) final_jmp_addr = ea + interm_jmp_param + interm_jmp_offt + 6 else: interm_jmp_param = idc.get_wide_byte(ea + interm_jmp_offt + 1) final_jmp_addr = ea + interm_jmp_param + interm_jmp_offt + 2 # Check the last conditional jump # 75 ?? ... 0F 85 ?? ?? ?? ?? if idc.get_wide_byte(final_jmp_addr) == 0x0F and \ idc.get_wide_byte(final_jmp_addr + 1) == alternative_jmp_cmd: final_jmp_param = idc.get_wide_dword(final_jmp_addr + 2) final_jmp_target = (final_jmp_addr + final_jmp_param + 6) & 0xFFFFFFFF # 75 ?? ... 75 ?? elif idc.get_wide_byte(final_jmp_addr) ^ 0xF0 == alternative_jmp_cmd: final_jmp_param = idc.get_wide_byte(final_jmp_addr + 1) final_jmp_target = (final_jmp_addr + final_jmp_param + 2) & 0xFFFFFFFF # Make a little cleanup: remove garbage code elif interm_jmp_param < 0x10: fill_with_nops(ea + interm_jmp_offt, final_jmp_addr) return True else: return if final_jmp_target - ea < 0xFF: fill_with_nops(ea + interm_jmp_offt, final_jmp_target) else: fill_with_nops(ea + interm_jmp_offt, final_jmp_addr + 6) # Restore seconds jump idc.patch_byte(ea + interm_jmp_offt, 0x0F) idc.patch_byte(ea + interm_jmp_offt + 1, alternative_jmp_cmd) idc.patch_dword(ea + interm_jmp_offt + 2, final_jmp_target - (ea + interm_jmp_offt) - 6) idc.create_insn(ea + interm_jmp_offt) return True
def read_bytes_slowly(start, end): bytestr = [] for i in xrange(start, end): if idc.has_value(idc.get_full_flags(i)): bt = idc.get_wide_byte(i) bytestr.append(chr(bt)) else: bytestr.append("\x00") return "".join(bytestr)
def get_header_idb(): ''' get file header from idb ''' if idc.get_segm_name(0) == 'HEADER': header = bytearray( [idc.get_wide_byte(ea) for ea in range(0, idc.get_segm_end(0))]) return header return bytearray(b'')
def processStructField(self, addr, index): offset = addr + index sid = ida_struct.get_struc_id("structField") ptr = self.getPtr(sid, offset, "Name") ln = idc.get_wide_byte(ptr + 2) fieldName = self.get_str(ptr + 3, ln) Utils.rename(ptr, fieldName) ptr = self.getPtr(sid, offset, "typ") self.handle_offset(ptr)
def read_bytes_slowly(start, end): bytestr = bytearray() for i in xrange(start, end): if idc.has_value(idc.get_full_flags(i)): bt = idc.get_wide_byte(i) bytestr.append(bt) else: bytestr.append(0) return bytes(bytestr)
def read_bytes_slowly(start, end): bytestr = [] for i in xrange(start, end): if idc.has_value(idc.get_full_flags(i)): bt = idc.get_wide_byte(i) bytestr.append(chr(bt)) else: bytestr.append("\x00") return "".join(bytestr)
def get_guid(address): """get GUID located by address""" guid = list() guid.append(idc.get_wide_dword(address)) guid.append(idc.get_wide_word(address + 4)) guid.append(idc.get_wide_word(address + 6)) for addr in range(address + 8, address + 16, 1): guid.append(idc.get_wide_byte(addr)) return guid
def extractFunctionTypeSample(self, ea): """Extract features for a "code type" sample. Args: ea (int): effective address to be sampled Return Value: feature set (list of byte values) """ return list(map(lambda o: idc.get_wide_byte(ea + o), self._classifier_type_offsets))
def extractSample(self, ea): """Extract features for a sample. Args: ea (int): effective address to be sampled Return Value: feature set (list of byte values) """ return [idc.get_wide_byte(ea + o) for o in self._classifier_offsets]
def deobfuscate_rets(ea): if idc.get_wide_byte(ea) == 0x83: fill_with_nops(ea, ea + 7) else: fill_with_nops(ea, ea + 8) idc.patch_byte(ea, 0xC3) idc.create_insn(ea) return True
def parse_vtable(ea, typename): os = get_os() if os == OS_Linux: ea += 8 funcs = [] while ea != idc.BADADDR: eatemp = ea offs = idc.get_wide_dword(ea) # if ida_bytes.is_unknown(ida_bytes.get_full_flags(ea)): # break size = idc.get_item_size( ea ) # This is bad abd abadbadbadbabdbabdad but there's no other choice here if size != 4: # This looks like it might be a bug with IDA # Random points of a vtable are getting turned into unknown data if size != 1: break s = "".join([ "%02x" % idc.get_wide_byte(ea + i) for i in range(3, -1, -1) ]) #.replace("0x", "") if not s.lower().startswith("ffff"): ea = ida_bytes.next_not_tail(ea) continue offs = int(s, 16) ea += 3 name = idc.get_name(offs, ida_name.GN_VISIBLE) if name: if os == OS_Linux: if not (name.startswith("_Z") or name.startswith("__cxa")) or name.startswith("_ZTV"): break # If we've exceeded past this vtable elif name.startswith("??"): break else: if os == OS_Win: break # dd -offsettothis # This is even worseworsoewewrosorooese s = "%02x" % offs if not s.lower().startswith("ffff"): ea = ida_bytes.next_not_tail(ea) continue name = (1 << 32) - int(offs) funcs.append(name) ea = ida_bytes.next_not_tail(ea) return funcs, eatemp
def get_data_guids(self): ''' rename GUIDs in idb ''' EFI_GUID = 'EFI_GUID *' EFI_GUID_ID = idc.get_struc_id('EFI_GUID') segments = ['.text', '.data'] for segment in segments: seg_start, seg_end = 0, 0 for seg in idautils.Segments(): if idc.get_segm_name(seg) == segment: seg_start = idc.get_segm_start(seg) seg_end = idc.get_segm_end(seg) break ea = seg_start while (ea <= seg_end - 15): prot_name = '' if idc.get_name(ea, ida_name.GN_VISIBLE).find('unk_') != -1: find = False cur_guid = [] cur_guid.append(idc.get_wide_dword(ea)) cur_guid.append(idc.get_wide_word(ea + 4)) cur_guid.append(idc.get_wide_word(ea + 6)) for addr in range(ea + 8, ea + 16, 1): cur_guid.append(idc.get_wide_byte(addr)) if cur_guid == [0] * 11: ea += 1 continue for guid_place in [ 'ami_guids', 'asrock_guids', 'dell_guids', 'edk_guids', 'edk2_guids', 'lenovo_guids' ]: for name in self.Protocols[guid_place]: if self.Protocols[guid_place][name] == cur_guid: prot_name = name + '_' + \ '{addr:#x}'.format(addr=ea) record = { 'address': ea, 'service': 'unknown', 'guid': cur_guid, 'protocol_name': name, 'protocol_place': guid_place } find = True break if find: break if find and (idc.get_name(ea, ida_name.GN_VISIBLE) != prot_name): idc.SetType(ea, EFI_GUID) self.apply_struct(ea, 16, EFI_GUID_ID) idc.set_name(ea, prot_name) self.Protocols['data'].append(record) ea += 1
def extractFunctionStartSample(self, ea, code_type): """Extract features for a "function start" sample. Args: ea (int): effective address to be sampled code_type (int): code type of the wanted sample Return Value: feature set (list of byte values) """ return list(map(lambda o: idc.get_wide_byte(ea + o), self._classifiers_start_offsets[code_type]))
def get_data_guids(self): """rename GUIDs in idb""" EFI_GUID = "EFI_GUID" EFI_GUID_ID = idc.get_struc_id("EFI_GUID") segments = [".text", ".data"] for segment in segments: seg_start, seg_end = 0, 0 for seg in idautils.Segments(): if idc.get_segm_name(seg) == segment: seg_start = idc.get_segm_start(seg) seg_end = idc.get_segm_end(seg) break ea = seg_start while ea <= seg_end - 15: prot_name = str() if "unk" in idc.get_name(ea, ida_name.GN_VISIBLE): find = False cur_guid = list() cur_guid.append(idc.get_wide_dword(ea)) cur_guid.append(idc.get_wide_word(ea + 4)) cur_guid.append(idc.get_wide_word(ea + 6)) for addr in range(ea + 8, ea + 16, 1): cur_guid.append(idc.get_wide_byte(addr)) if cur_guid == [0] * 11: ea += 1 continue for guid_place in [ "ami_guids", "asrock_guids", "dell_guids", "edk_guids", "edk2_guids", "lenovo_guids", ]: for name in self.Protocols[guid_place]: if self.Protocols[guid_place][name] == cur_guid: prot_name = f"{name}_{ea:016X}" record = { "address": ea, "service": "unknown", "guid": cur_guid, "protocol_name": name, "protocol_place": guid_place, } find = True break if find: break if find and (idc.get_name(ea, ida_name.GN_VISIBLE) != prot_name): idc.SetType(ea, EFI_GUID) self.apply_struct(ea, 16, EFI_GUID_ID) idc.set_name(ea, prot_name) self.Protocols["data"].append(record) ea += 1
def resolve_calls_through_register(ea): next_instr_addr = idc.get_wide_dword(ea + 1) # Check if that's just a parameter passing through stack if ea & 0xFFFF0000 != next_instr_addr & 0xFFFF0000: return if next_instr_addr - ea > 0x100: return if idc.get_wide_byte(ea + 6) & 0xF0 in [0x20, 0xE0]: call_param = 0x9000 + idc.get_wide_byte(ea + 6) ^ 0x30 else: call_param = idc.get_wide_word(ea + 6) ^ 0x30 fill_with_nops(ea, next_instr_addr) idc.patch_byte(ea, 0xFF) idc.patch_word(ea + 1, call_param) idc.create_insn(ea) return True
def processMethods(self, offst): sid = ida_struct.get_struc_id("method__") name = self.getDword(sid, offst, "name") name += self.robase name = self.get_str(name + 3, idc.get_wide_byte(name + 2)) type_meth = self.getDword(sid, offst, "mtyp") type_meth_addr1 = self.robase + type_meth func_body1 = self.getDword(sid, offst, "ifn") func_addr1 = self.text_addr + func_body1 func_body2 = self.getDword(sid, offst, "tfn") func_addr2 = self.text_addr + func_body1 return "%s %x %x %x" % (name, type_meth_addr1, func_addr1, func_addr2)
def _get_memory(self): result = "" segment_starts = [ea for ea in idautils.Segments()] offsets = [] start_len = 0 for start in segment_starts: end = idc.get_segm_end(start) for ea in lrange(start, end): result += chr(idc.get_wide_byte(ea)) offsets.append((start, start_len, len(result))) start_len = len(result) return result, offsets
def isGlobalAsciiString(self, ea): r"""Check if the given address is the beginning of a valid global string. Args: ea (int): effective address to be checked Notes ----- 1. The string should be aligned (global alignment). 2. The string should only contain chars from our alpha-bet. 3. The string should be '\0' terminated. 4. If applicable, the string should be padded with the correct padding byte. 5. The string's length must be at least the required lower bound. Return Value: True iff the given address could be the start of a global string """ # start by checking the alignment if ea % self._global_alignment != 0: return False str_content = self.getAsciiString(ea) # check each of the chars if str_content is None or len( list( filter(lambda x: chr(x) in self._valid_alphabet, str_content))) != len(str_content): return False # check for a '\0' terminator if idc.get_wide_byte(ea + len(str_content)) != ord('\0'): return False # check for the correct padding if self._global_pad is not None: end_address = ea + len(str_content) + 1 for offset in range(padSize(end_address, self._global_alignment)): if idc.get_wide_byte(end_address + offset) != self._global_pad: return False # basic length return len(str_content) >= self._min_global_length
def get_func_end(self, start): if (idc.add_func(start)): return idc.find_func_end(start) ea = start while (idc.get_wide_byte(ea) != 0xCC): idc.create_insn(ea) ea += idc.get_item_size(ea) if (ea - start > self.jit_max_size): return 0 return ea
def extractFunctionMixedSample(self, ea, code_type): """Extract features for a "function start/end" sample. Args: ea (int): effective address to be sampled code_type (int): code type of the wanted sample Return Value: feature set (list of byte values) """ return [ idc.get_wide_byte(ea + o) for o in self._classifiers_mixed_offsets[code_type] ]
def get_native_function(self): ecx = idc.get_reg_value("ECX") esp = idc.get_reg_value("ESP") method_name = self.get_method_name(esp) if (idc.get_wide_byte(idc.get_wide_dword(ecx + 8) + 0x38) != 0): function = idc.get_wide_dword(idc.get_wide_dword(esp + 4) + 0x28) else: function = idc.get_wide_dword(idc.get_wide_dword(esp + 4) + 0x24) print("Resolved native function: 0x%x - %s" % (function, method_name)) if ((method_name not in self.ignore and not self.ignore_all) or (method_name in self.debug_if_equals) or (any(x for x in self.debug_if_contains if method_name is not None and x in method_name))): self.traced.append({"name": method_name, "ea": function, "type": "native", "hit": 0}) idc.add_bpt(function)
def read_leb128(ea, signed): """ Read LEB128 encoded data """ val = 0 shift = 0 while True: byte = idc.get_wide_byte(ea) val |= (byte & 0x7F) << shift shift += 7 ea += 1 if (byte & 0x80) == 0: break if shift > 64: DEBUG("Bad leb128 encoding at {0:x}".format(ea - shift/7)) return idc.BADADDR if signed and (byte & 0x40): val -= (1<<shift) return val, ea