def main(): print("[*] loading crypto constants") for const in non_sparse_consts: const["byte_array"] = convert_to_byte_array(const) for start in idautils.Segments(): print("[*] searching for crypto constants in %s" % idc.get_segm_name(start)) ea = start while ea < idc.get_segm_end(start): bbbb = list(struct.unpack("BBBB", idc.get_bytes(ea, 4))) for const in non_sparse_consts: if bbbb != const["byte_array"][:4]: continue if map(lambda x:ord(x), idc.get_bytes(ea, len(const["byte_array"]))) == const["byte_array"]: print(("0x%0" + str(digits) + "X: found const array %s (used in %s)") % (ea, const["name"], const["algorithm"])) idc.set_name(ea, const["name"]) if const["size"] == "B": idc.create_byte(ea) elif const["size"] == "L": idc.create_dword(ea) elif const["size"] == "Q": idc.create_qword(ea) idc.make_array(ea, len(const["array"])) ea += len(const["byte_array"]) - 4 break ea += 4 ea = start if idc.get_segm_attr(ea, idc.SEGATTR_TYPE) == 2: while ea < idc.get_segm_end(start): d = ida_bytes.get_dword(ea) for const in sparse_consts: if d != const["array"][0]: continue tmp = ea + 4 for val in const["array"][1:]: for i in range(8): if ida_bytes.get_dword(tmp + i) == val: tmp = tmp + i + 4 break else: break else: print(("0x%0" + str(digits) + "X: found sparse constants for %s") % (ea, const["algorithm"])) cmt = idc.get_cmt(idc.prev_head(ea), 0) if cmt: idc.set_cmt(idc.prev_head(ea), cmt + ' ' + const["name"], 0) else: idc.set_cmt(idc.prev_head(ea), const["name"], 0) ea = tmp break ea += 1 print("[*] finished")
def getFuncRanges_ida7(ea, doAllFuncs): if doAllFuncs: funcs = [] funcGen = idautils.Functions(idc.get_segm_start(ea), idc.get_segm_end(ea)) for i in funcGen: funcs.append(i) funcRanges = [] for i in range(len(funcs) - 1): funcRanges.append( (funcs[i], funcs[i+1]) ) funcRanges.append( (funcs[-1], idc.get_segm_end(ea)) ) return funcRanges else: #just get the range of the current function fakeRanges = [( idc.get_func_attr(idc.here(), idc.FUNCATTR_START), idc.get_func_attr(idc.here(), idc.FUNCATTR_END)), ] return fakeRanges
def recover_frame_entries(seg_ea): if seg_ea == idc.BADADDR: return DEBUG("Recover entries from section : {}".format(idc.get_segm_name(seg_ea))) ea = idc.get_segm_start(seg_ea) end_ea = idc.get_segm_end(seg_ea) while ea != idc.BADADDR and ea < end_ea: ea = format_entries(ea)
def processAllSegments(self): for seg in idautils.Segments(): if using_ida7api: segStart = idc.get_segm_start(seg) segEnd = idc.get_segm_end(seg) else: segStart = idc.SegStart(seg) segEnd = idc.SegEnd(seg) if self.params.searchPushArgs: self.lookForOpArgs(segStart, segEnd) if self.params.searchDwordArray: self.lookForDwordArray(segStart, segEnd)
def processCode(self): if (self.params.startAddr==idc.BADADDR) and (self.params.endAddr==idc.BADADDR): if using_ida7api: self.params.startAddr = idc.get_segm_start(idc.here()) self.params.endAddr = idc.get_segm_end(idc.here()) else: self.params.startAddr = idc.SegStart(idc.here()) self.params.endAddr = idc.SegEnd(idc.here()) logger.info('Processing current segment only: 0x%08x - 0x%08x', self.params.startAddr, self.params.endAddr) else: logger.info('Processing range 0x%08x - 0x%08x', self.params.startAddr, self.params.endAddr) if self.params.searchDwordArray: self.lookForDwordArray(self.params.startAddr, self.params.endAddr) if self.params.searchPushArgs: self.lookForOpArgs(self.params.startAddr, self.params.endAddr)
def get_function_bounds(ea): """Get the bounds of the function containing `ea`. We want to discover jump table targets that are missed by IDA, and it's possible that they aren't marked as being part of the current function, and perhaps are after the assumed range of the current function. Ideally they will fall before the beginning of the next function, though. We need to be pretty careful with the case that one function tail-calls another. IDA will sometimes treat the end of the tail-called function (e.g. a thunk) as if it is the end of the caller. For this reason, we start with loose bounds using the prev/next functions, then try to narrow with the bounds of the function containing `ea`. TODO(pag): Handle discontinuous regions (e.g. because of function chunks). It may be worth to return an object here that can we queried for membership using the `__in__` method. """ seg_start, seg_end = idc.get_segm_start(ea), idc.get_segm_end(ea) min_ea = seg_start max_ea = seg_end if is_invalid_ea(min_ea) or not is_code(ea): return ea, ea # Get an upper bound using the next function. next_func_ea = idc.get_next_func(ea) if not is_invalid_ea(next_func_ea): max_ea = min(next_func_ea, max_ea) # Get a lower bound using the previous function. prev_func_ea = idc.get_prev_func(ea) if not is_invalid_ea(prev_func_ea): min_ea = max(min_ea, prev_func_ea) prev_func = idaapi.get_func(prev_func_ea) if prev_func and prev_func.end_ea < ea: min_ea = max(min_ea, prev_func.end_ea) # Try to tighten the bounds using the function containing `ea`. func = idaapi.get_func(ea) if func: min_ea = max(min_ea, func.start_ea) max_ea = min(max_ea, func.end_ea) return min_ea, max_ea
def promptForRange(self): # Only run if QT not available, so not bothering with ida7 check #check if a range has already been selected - if so skip prompt if using_ida7api: selstart = idc.read_selection_start() selend = idc.read_selection_end() segstart = idc.get_segm_start(idc.here()) segend = idc.get_segm_end(idc.here()) else: selstart = idc.SelStart() selend = idc.SelEnd() seg = idc.SegStart(idc.here()) self.params.endAddr = idc.SegEnd(idc.here()) if selstart != idc.BADADDR: self.params.startAddr = selstart self.params.endAddr = selend logger.info('Processing range 0x%08x - 0x%08x', self.params.startAddr, self.params.endAddr) else: self.params.startAddr = segstart self.params.endAddr = segend logger.info('Processing current segment only')
def check_vtable(start, end=None): # We recognize a vtable by looking for an array of at least 2 pointers to code followed by a # NULL. # If no end was specified, go until the end of the segment. if end is None: end = idc.get_segm_end(start) # Check each address in the table. Stop once we've found something other than a pointer to # code. ended_with_zero = False ea = start while ea < end: method = idc.get_qword(ea) if method == 0: ended_with_zero = True break if not idc.is_code(idc.get_full_flags(method)): break ea += 8 # Compute the length. length = (ea - start) / 8 possible_vtable = ended_with_zero and length >= 2 return possible_vtable, length
def reload_info(self): if not dbg.is_process_suspended(): return False base_addr = None if self.base_expr is None: base_addr = idc.get_reg_value(dbg.registers.stack) else: base_addr = idaapi.str2ea(self.base_expr) if base_addr == idc.BADADDR: idaapi.warning("Invalid base expr: %s" % self.base_expr) return False if not idaapi.is_loaded(base_addr): idaapi.warning("Memory address is not loaded: $#x" % base_addr) return False self.ClearLines() dbg.set_thread_info() try: segm_end = idc.get_segm_end(base_addr) n_entries = config.n_stack_entries or ((segm_end-base_addr) // dbg.ptr_size) for i in range(n_entries): offset = i * dbg.ptr_size ptr = base_addr + offset if not idaapi.is_loaded(ptr): break value = idc.get_qword(ptr) self.add_line("%02d:%04X %s" % (i, offset, self.parse_value(ptr))) except Exception as e: idaapi.warning(str(e)) return False return True
def parse_prelink_info(): """Find and parse the kernel __PRELINK_INFO dictionary.""" segments = _find_prelink_info_segments() for segment in segments: seg_start = idc.get_segm_start(segment) seg_end = idc.get_segm_end(segment) #prelink_info_string = idc.get_strlit_contents(segment) prelink_info_string = idc.get_bytes(seg_start, seg_end-seg_start) if prelink_info_string[:5] != b"<dict": continue if prelink_info_string != None: prelink_info_string = prelink_info_string.replace(b"\x00", b"") prelink_info_string = prelink_info_string.decode() prelink_info = kplist.kplist_parse(prelink_info_string) if prelink_info: return prelink_info _log(0, 'Could not find __PRELINK_INFO') return None
def update_structs_from_xrefs(track_members=True): """ Find xrefs to a struct pointer and change all the offsets to be struct offsets. This is useful for updating references to function pointers in EFI tables. For example: mov rax, cs:qword_whatever call qword ptr [rax+150h] Becomes: mov rax, cs:gBootServices call [rax+EFI_BOOT_SERVICES.UninstallMultipleProtocolInterfaces] """ for seg_beg in Segments(): seg_end = get_segm_end(seg_beg) head = next_head(seg_beg, seg_end) while head != BADADDR: head_ptr = Pointer(head) if is_structure_type(head_ptr.type.rstrip(" *")): print("Updating structures for xref: %s" % head_ptr) struc = Structure(head_ptr.type.rstrip(" *")) _update_from_ptr(head_ptr, struc, track_members) head = next_head(head, seg_end)
def process_region(segname, name, start, end): assert end >= start if segname in skip: _log(2, 'Skipping segment {}', segname) return newname = '{}.{}'.format(segname, name) if kext: newname = '{}:{}'.format(kext, newname) if start == end: _log(2, 'Skipping empty region {} at {:x}', newname, start) return ida_segstart = idc.get_segm_start(start) if ida_segstart == idc.BADADDR: _log(0, "IDA doesn't think this is a real segment: {:x} - {:x}", start, end) return ida_segend = idc.get_segm_end(ida_segstart) if start != ida_segstart or end != ida_segend: _log(0, 'IDA thinks segment {} {:x} - {:x} should be {:x} - {:x}', newname, start, end, ida_segstart, ida_segend) return _log(2, 'Rename {:x} - {:x}: {} -> {}', start, end, idc.get_segm_name(start), newname) idc.set_segm_name(start, newname)
def find_main_arena(): main_arena = idc.get_name_ea_simple("main_arena") # from libc6-dbg if main_arena != idc.BADADDR: return main_arena ea = idc.get_segm_start(idc.get_name_ea_simple("_IO_2_1_stdin_")) end_ea = idc.get_segm_end(ea) # &main_arena->next offsets = { 4: [1088, 1096], # 32 bits 8: [2152, 2160] # 64 bits }[config.ptr_size] if ea == idc.BADADDR or end_ea == idc.BADADDR: return None while ea < end_ea: ptr = config.get_ptr(ea) # ptr to main_arena if idaapi.is_loaded(ptr) and ptr < ea: if (ea - ptr) in offsets: return ptr ea += config.ptr_size return None
import idc import idautils import ida_offset reftype = ida_offset.get_default_reftype(next(idautils.Segments())) for segea in idautils.Segments(): for head in idautils.Heads(idc.get_segm_start(segea), idc.get_segm_end(segea)): if not ida_bytes.is_code(ida_bytes.get_full_flags(head)): continue for i in range(2): if idc.get_segm_start(idc.get_operand_value(head, i)) == idc.BADADDR: continue ida_offset.op_offset(head, i, reftype) print("ok")
def enum_segments(): for segstart in idautils.Segments(): segend = idc.get_segm_end(segstart) segname = idc.get_segm_name(segstart) yield segstart, segend, segname
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 name in self.Protocols['Edk2Guids']: if self.Protocols['Edk2Guids'][name] == cur_guid: prot_name = name + '_' + '{addr:#x}'.format( addr=ea) record = { 'address': ea, 'service': 'unknown', 'guid': cur_guid, 'protocol_name': name, 'protocol_place': 'edk2_guids' } find = True break for name in self.Protocols['EdkGuids']: if self.Protocols['EdkGuids'][name] == cur_guid: prot_name = name + '_' + '{addr:#x}'.format( addr=ea) prot_name = name + '_' + '{addr:#x}'.format( addr=ea) record = { 'address': ea, 'service': 'unknown', 'guid': cur_guid, 'protocol_name': name, 'protocol_place': 'edk_guids' } find = True break for name in self.Protocols['AmiGuids']: if self.Protocols['AmiGuids'][name] == cur_guid: prot_name = name + '_' + '{addr:#x}'.format( addr=ea) prot_name = name + '_' + '{addr:#x}'.format( addr=ea) record = { 'address': ea, 'service': 'unknown', 'guid': cur_guid, 'protocol_name': name, 'protocol_place': 'ami_guids' } find = True 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
# sublicense, and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT # SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # # Author(s): Thomas Riedmaier import ida_kernwin import idc import idautils filename = ida_kernwin.ask_file(True, '*.txt', 'Please select txt to export basic blocks') with open(filename, 'w') as f: for segea in idautils.Segments(): for funcea in idautils.Functions(segea, idc.get_segm_end(segea)): for block in ida_gdl.FlowChart(ida_funcs.get_func(funcea)): print >> f, "%s/%s,0x%08x" % ( idaapi.get_root_filename(), idc.get_segm_name(segea), block.start_ea - idc.get_segm_start(segea))
def main(): print("[*] loading crypto constants") for const in non_sparse_consts: const["byte_array"] = convert_to_byte_array(const) for start in idautils.Segments(): print("[*] searching for crypto constants in %s" % idc.get_segm_name(start)) ea = start while ea < idc.get_segm_end(start): bbbb = list(struct.unpack("BBBB", idc.get_bytes(ea, 4))) for const in non_sparse_consts: if bbbb != const["byte_array"][:4]: continue if map(lambda x: ord(x), idc.get_bytes(ea, len( const["byte_array"]))) == const["byte_array"]: print(("0x%0" + str(digits) + "X: found const array %s (used in %s)") % (ea, const["name"], const["algorithm"])) idc.set_name(ea, const["name"]) if const["size"] == "B": idc.create_byte(ea) elif const["size"] == "L": idc.create_dword(ea) elif const["size"] == "Q": idc.create_qword(ea) idc.make_array(ea, len(const["array"])) ea += len(const["byte_array"]) - 4 break ea += 4 ea = start if idc.get_segm_attr(ea, idc.SEGATTR_TYPE) == 2: while ea < idc.get_segm_end(start): d = ida_bytes.get_dword(ea) for const in sparse_consts: if d != const["array"][0]: continue tmp = ea + 4 for val in const["array"][1:]: for i in range(8): if ida_bytes.get_dword(tmp + i) == val: tmp = tmp + i + 4 break else: break else: print(("0x%0" + str(digits) + "X: found sparse constants for %s") % (ea, const["algorithm"])) cmt = idc.get_cmt(idc.prev_head(ea), 0) if cmt: idc.set_cmt(idc.prev_head(ea), cmt + ' ' + const["name"], 0) else: idc.set_cmt(idc.prev_head(ea), const["name"], 0) ea = tmp break ea += 1 print("[*] finished")
def isValidPointer_ida7(va): for segStart in idautils.Segments(): if (va >= segStart) and (va < idc.get_segm_end(segStart)): return True return False
def vtable_length(ea, end=None, scan=False): """Find the length of a virtual method table. This function checks whether the effective address could correspond to a virtual method table and calculates its length, including the initial empty entries. By default (when scan is False), this function returns the length of the vtable if the address could correspond to a vtable, or 0 if the address definitely could not be a vtable. Arguments: ea: The linear address of the start of the vtable. Options: end: The end address to search through. Defaults to the end of the section. scan: Set to True to indicate that this function is being called to scan memory for virtual method tables. Instead of returning the length of the vtable or 0, this function will return a tuple (possible, length). Additionally, as a slight optimization, this function will sometimes look ahead in order to increase the amount of data that can be skipped, reducing duplication of effort between subsequent calls. Returns: If scan is False (the default), then this function returns the length of the vtable in words, including the initial empty entries. Otherwise, this function returns a tuple (possible, length). If the address could correspond to the start of a vtable, then possible is True and length is the length of the vtable in words, including the initial empty entries. Otherwise, if the address is definitely not the start of a vtable, then possible is False and length is the number of words that can be skipped when searching for the next vtable. """ # TODO: This function should be reorganized. The better way of doing it is to count the number # of zero entries, then the number of nonzero entries, then decide based on that. Less # special-casing that way. # TODO: We should have a static=True/False flag to indicate whether we want to include the # empty entries. def return_value(possible, length): if scan: return possible, length return length if possible else 0 # Initialize default values. if end is None: end = idc.get_segm_end(ea) words = idau.ReadWords(ea, end) # Iterate through the first VTABLE_OFFSET words. If any of them are nonzero, then we can skip # past all the words we just saw. for idx, word in enumerate(islice(words, VTABLE_OFFSET)): if word != 0: return return_value(False, idx + 1) # Now this first word after the padding section is special. first = next(words, None) if first is None: # We have 2 zeros followed by the end of our range. return return_value(False, VTABLE_OFFSET) elif first == 0: # We have VTABLE_OFFSET + 1 zero entries. zeros = VTABLE_OFFSET + 1 if scan: # To avoid re-reading the data we just read in the case of a zero-filled section, let's # look ahead a bit until we find the first non-zero value. for word in words: if word is None: return return_value(False, zeros) if word != 0: break zeros += 1 else: # We found no nonzero words before the end. return return_value(False, zeros) # We can skip all but the last VTABLE_OFFSET zeros. return return_value(False, zeros - VTABLE_OFFSET) # TODO: We should verify that all vtable entries refer to code. # Now we know that we have at least one nonzero value, our job is easier. Get the full length # of the vtable, including the first VTABLE_OFFSET entries and the subsequent nonzero entries, # until either we find a zero word (not included) or run out of words in the stream. length = VTABLE_OFFSET + 1 + idau.iterlen( takewhile(lambda word: word != 0, words)) # Now it's simple: We are valid if the length is long enough, invalid if it's too short. return return_value(length >= MIN_VTABLE_LENGTH, length)
def getSegEnd(self, ea): if idaapi.IDA_SDK_VERSION < 700: return idc.SegEnd(ea) else: return idc.get_segm_end(ea)
def getSegmentEnd(self, addr): return idc.get_segm_end(addr)
def __init__(self): self._segs = [ Segment(va, idc.get_segm_end(va)) for va in idautils.Segments() ] self._segs.sort()
def cmd_get_segment_end(self, a): return self.fmt_addr(idc.get_segm_end(int(a, 0)))
def parse_heap(self, address=None): results = [] tcache_chunks = [] tcache_size = 0 arena = self.get_arena(address) heap_base = self.get_heap_base(address) fastbins = self.get_all_fastbins_chunks(address) if self.tcache_enabled: tcache_chunks = self.get_all_tcache_chunks(address) tcache_size = sizeof( self.tcache_perthread_s) + self.malloc_alignment if not heap_base: return results heap_size = idc.get_segm_end(heap_base) - heap_base ''' For prevent incorrect parsing in glibc > 2.25 (i386) where MALLOC_ALIGNMENT != PTR_SIZE*2 ''' chunk_addr = self.mem2chunk(heap_base + self.malloc_alignment) stop_parse = False count = 0 while not stop_parse: # chunk_addr <= arena.top chunk = self.get_chunk(chunk_addr) real_size = chunk.norm_size if real_size == 0 or real_size > heap_size: status = 'Corrupt' stop_parse = True elif chunk_addr == arena.top: status = 'arena->top' stop_parse = True else: status = self.get_chunk(chunk_addr + real_size).prev_inuse in_freelist = None if status: if chunk_addr in fastbins: in_freelist = 'fastbin' elif chunk_addr in tcache_chunks: in_freelist = 'tcache' else: in_freelist = 'bins' status = 'Used' if not in_freelist else 'Freed (%s)' % in_freelist if count == 0 and self.tcache_enabled: if real_size == tcache_size: status = 'tcache_perthread' results.append({ 'address': chunk_addr, 'prev': chunk.prev_inuse, 'size': real_size, 'status': status, 'fd': chunk.fd, 'bk': chunk.bk }) chunk_addr = chunk_addr + real_size count += 1 return results
# See https://www.hex-rays.com/products/ida/support/ida74_idapython_no_bc695_porting_guide.shtml from os.path import expanduser home = expanduser("~") patchpoints = set() max_offset = 0 for seg_ea in idautils.Segments(): name = idc.get_segm_name(seg_ea) #print("Segment: " + name) if name != "__text" and name != ".text": continue start = idc.get_segm_start(seg_ea) end = idc.get_segm_end(seg_ea) first = 0 subtract_addr = 0 #print("Start: " + hex(start) + " End: " + hex(end)) for func_ea in idautils.Functions(start, end): f = idaapi.get_func(func_ea) if not f: continue for block in idaapi.FlowChart(f): if start <= block.start_ea < end: if first == 0: if block.start_ea >= 0x1000: subtract_addr = 0x1000 first = 1 max_offset = max(max_offset, block.start_ea)
def main(): print("[*] loading crypto constants") for const in non_sparse_consts: const["byte_array"] = convert_to_byte_array(const) for start in idautils.Segments(): print("[*] searching for crypto constants in %s" % idc.get_segm_name(start)) ea = start while ea < idc.get_segm_end(start): bbbb = list(struct.unpack("BBBB", idc.get_bytes(ea, 4))) for const in non_sparse_consts: if bbbb != const["byte_array"][:4]: continue if list( map(lambda x: x if type(x) == int else ord(x), idc.get_bytes(ea, len( const["byte_array"])))) == const["byte_array"]: print(("0x%0" + str(digits) + "X: found const array %s (used in %s)") % (ea, const["name"], const["algorithm"])) idc.set_name(ea, const["name"], ida_name.SN_FORCE) if const["size"] == "B": idc.create_byte(ea) elif const["size"] == "L": idc.create_dword(ea) elif const["size"] == "Q": idc.create_qword(ea) idc.make_array(ea, len(const["array"])) ea += len(const["byte_array"]) - 4 break ea += 4 ea = start if idc.get_segm_attr(ea, idc.SEGATTR_TYPE) == idc.SEG_CODE: while ea < idc.get_segm_end(start): d = ida_bytes.get_dword(ea) for const in sparse_consts: if d != const["array"][0]: continue tmp = ea + 4 for val in const["array"][1:]: for i in range(8): if ida_bytes.get_dword(tmp + i) == val: tmp = tmp + i + 4 break else: break else: print(("0x%0" + str(digits) + "X: found sparse constants for %s") % (ea, const["algorithm"])) cmt = idc.get_cmt(idc.prev_head(ea), 0) if cmt: idc.set_cmt(idc.prev_head(ea), cmt + ' ' + const["name"], 0) else: idc.set_cmt(idc.prev_head(ea), const["name"], 0) ea = tmp break ea += 1 print("[*] searching for crypto constants in immediate operand") funcs = idautils.Functions() for f in funcs: flags = idc.get_func_flags(f) if (not flags & (idc.FUNC_LIB | idc.FUNC_THUNK)): ea = f f_end = idc.get_func_attr(f, idc.FUNCATTR_END) while (ea < f_end): imm_operands = [] insn = ida_ua.insn_t() ida_ua.decode_insn(insn, ea) for i in range(len(insn.ops)): if insn.ops[i].type == ida_ua.o_void: break if insn.ops[i].type == ida_ua.o_imm: imm_operands.append(insn.ops[i].value) if len(imm_operands) == 0: ea = idc.find_code(ea, idc.SEARCH_DOWN) continue for const in operand_consts: if const["value"] in imm_operands: print(("0x%0" + str(digits) + "X: found immediate operand constants for %s") % (ea, const["algorithm"])) cmt = idc.get_cmt(ea, 0) if cmt: idc.set_cmt(ea, cmt + ' ' + const["name"], 0) else: idc.set_cmt(ea, const["name"], 0) break ea = idc.find_code(ea, idc.SEARCH_DOWN) print("[*] finished")
return (0x71, 10) elif number == 0: # ok < no conditional return (0x90, 0x90) elif number == 4: # ok return (0x78, 10) elif number == 2: # ok return (0x70, 10) else: return (0x00, 0x00) align = lambda size, alignment: ((size // alignment) + 1) * alignment if __name__ == "__main__": start = idc.get_segm_by_sel(0) end = idc.get_segm_end(start) data = idaapi.get_many_bytes(start + fnc_start, fnc_end - fnc_start + 2) matches = yara.compile(source=rules).match(data=data) count = 0 match = list() for hit in matches: if hit.rule == 'nanomite': match = hit.strings for hit in match: (offset, name, pattern) = hit number = data[offset + 1] encoded = data[offset + 2:offset + 2 + 8] jmp_addr = encode(encoded) jmp_addr_off = (jmp_addr - (start + fnc_start + offset + 2) & 0xffffffff) & 0xffffffff ins, jmp_off = nanomite(number) if ins == 0x00 or jmp_addr < 0x401000 or jmp_addr > 0x40c000:
def DumpSegPTE(ea): DumpPTE(idc.get_segm_start(ea), idc.get_segm_end(ea))
def SegEnd(ea): return idc.get_segm_end(ea)
def cb_segment_changed(self, value): s_ea = self.sender().itemData(value) self.set_address(idc.get_segm_start(s_ea), idc.get_segm_end(s_ea)) self.update_progress_bars()
import idc # Locate function signatures. # # based on: https://reverseengineering.stackexchange.com/a/14726 # func_sigs maps from function address to a record of the function's name and # type. func_sigs = {} func_addrs = [] for seg in idautils.Segments(): # Skip extern segment; as used by IDA for external functions. if idc.get_segm_attr(seg, SEGATTR_TYPE) == idc.SEG_XTRN: #print("skipping segment ", idc.get_segm_name(seg)) continue for fn in idautils.Functions(seg, idc.get_segm_end(seg)): func_addr = fn func_name = idc.get_name(func_addr) if func_name is None: func_name = "" func_type = idc.get_type(func_addr) if func_type is None: func_type = "" func_sig = {"func_name": func_name, "func_type": func_type} func_sigs[func_addr] = func_sig func_addrs.append(func_addr) # Sort function addresses to be used as key. func_addrs.sort() # Example output:
def untag_pointers(): _log(2, 'Starting tagged pointer conversion') for seg in idautils.Segments(): untag_pointers_in_range(idc.get_segm_start(seg), idc.get_segm_end(seg)) _log(2, 'Tagged pointer conversion complete')
def _process_mod_init_func_section_for_metaclasses(segstart, found_metaclass): """Process a __mod_init_func section for OSMetaClass information.""" segend = idc.get_segm_end(segstart) for func in idau.ReadWords(segstart, segend): _process_mod_init_func_for_metaclasses(func, found_metaclass)
def getLastAddress(self): return idc.get_segm_end([ea for ea in idautils.Segments()][-1]) - 1