def __init__(self, ea): self.ea = ea self.funcname_or_segname = "" self.text = "" if not ida_bytes.is_code(ida_bytes.get_flags(ea)): ida_ua.create_insn(ea) # text t = ida_lines.generate_disasm_line(ea) if t: self.text = ida_lines.tag_remove(t) # funcname_or_segname n = ida_funcs.get_func_name(ea) \ or ida_segment.get_segm_name(ida_segment.getseg(ea)) if n: self.funcname_or_segname = n
def get_mem_string(cls, addr): """ 获取内存中的字符串 """ addr_t = addr dref = idautils.DataRefsFrom(addr_t) strs = [cls.strings[x] for x in dref if x in cls.strings] # 处理几种特殊情况 # LDR R1, =sub_xxxx # LDR R1, =loc_xxxx if idc.print_operand(addr, 1)[:5] in ['=sub_', '=loc_']: return [] # LDR R1, =unk_53B4B6 # .rodata:0053B4B6 http: # .rodata:0053B4BB //%s%s if strs != [] and strs[0].find('%') == -1: strs = [] dref = idautils.DataRefsFrom(addr_t) for x in dref: segname = ida_segment.get_segm_name(ida_segment.getseg(x)) if segname not in ['.text', '.bss']: strs.append(cls.get_string_from_mem(x)) # LDR R1, =(aFailedToGetAnI+0x22) # LDR R2, =(aSS - 0xCFA4) # ADD R2, PC, R2 if strs == []: dref = idautils.DataRefsFrom(addr_t) for x in dref: segname = ida_segment.get_segm_name(ida_segment.getseg(x)) if segname not in ['.text', '.bss']: strs.append(cls.get_string_from_mem(x)) elif len(list(idautils.DataRefsFrom(x))) == 0: reg_t = idc.print_operand(addr_t, 0) num1 = ida_bytes.get_wide_dword(x) while get_mnem(addr_t) != 'ADD' or (idc.print_operand(addr_t, 0) != reg_t and idc.print_operand(addr_t, 1) != 'PC'): addr_t = ida_bytes.next_head(addr_t, ida_idaapi.BADADDR) num2 = addr_t + 8 addr_t = num1 + num2 strs.append(cls.get_string_from_mem(addr_t)) # MOVW R1, #0x87B4 # MOVT.W R1, #0x52 if strs == [] and get_mnem(addr_t) == 'MOVW': reg_t = idc.print_operand(addr_t, 0) num1 = int(idc.print_operand(addr_t, 1).split('#')[1], 16) while get_mnem(addr_t) not in ['MOVTGT', 'MOVTLE', 'MOVT'] or idc.print_operand(addr_t, 0) != reg_t: addr_t = ida_bytes.next_head(addr_t, ida_idaapi.BADADDR) num2 = int(idc.print_operand(addr_t, 1).split('#')[1], 16) addr_t = (num2<<16) + num1 strs.append(cls.get_string_from_mem(addr_t)) return strs
def adjust_addr(sections, addr): """ Adjust the address if there are differences in section base addresses :param sections: Dictionary containing section info :param addr: Address that might need adjusted :return: Adjusted address """ bn_section_start = None section_name = None for name, section in sections.items(): if addr >= int(section['start']) and addr <= int(section['end']): bn_section_start = int(section['start']) section_name = name break # Make sure the section was found (this check should always pass) if section_name is None: print('Section not found in bnida analysis data for addr: {:08x}'.format(addr)) return None # Retrieve section start in IDA and adjust the addr ida_sections = idautils.Segments() for ea in ida_sections: segm = ida_segment.getseg(ea) if ida_segment.get_segm_name(segm) == section_name: return addr - bn_section_start + segm.start_ea print('Section not found - name:{} addr:{:08x}'.format(section_name, addr)) return None
def segm_added(self, s): self._send_event( SegmAddedEvent(ida_segment.get_segm_name(s), ida_segment.get_segm_class(s), s.start_ea, s.end_ea, s.orgbase, s.align, s.comb, s.perm, s.bitness, s.flags)) return 0
def find_segm_fixed(name): # ida_segments'getting segment by name returns a random one # segment_t.name is a bogus value # ... wtf? that "API" is a mess. it = ida_segment.get_first_seg() while ida_segment.get_segm_name(it) != name and it: it = ida_segment.get_next_seg(it.start_ea + 1) return it
def get_segments(): """ 返回所有segment的名字列表(但其实是section) """ seg_names = [] for ea in idautils.Segments(): seg = ida_segment.getseg(ea) seg_names.append(ida_segment.get_segm_name(seg)) return seg_names
def find_segm_fixed(name): # ida_segments'getting segment by name returns a random one # segment_t.name is a bogus value # ... wtf? that "API" is a mess. res = [] it = ida_segment.get_first_seg() while it: if ida_segment.get_segm_name(it) == name: res += [it] it = ida_segment.get_next_seg(it.start_ea + 1) return res
def handle(seg): name = ida_segment.get_segm_name(seg) try: mod, segname = name.split(':') except ValueError: return if segname == '__objc_protolist': self.handle_proto_seg(seg) elif segname == '__objc_classlist': self.handle_class_seg(seg)
def main(): print('[*] start debfuscation') for s in get_code_segments(): print('[*] try to deobfuscate {} section'.format( ida_segment.get_segm_name(s))) if s.use32(): junk_patterns = junk_patterns_x86 elif s.use64(): junk_patterns = junk_patterns_x64 else: print('[!] unsupported arch') print('[*] replace junk code to nop') for pattern, pattern_len in junk_patterns: addr_from = idc.find_binary(s.start_ea, ida_search.SEARCH_DOWN, pattern) while addr_from != idaapi.BADADDR and addr_from < s.end_ea: ida_bytes.patch_bytes(addr_from, '\x90' * pattern_len) addr_from = idc.find_binary(addr_from + pattern_len, ida_search.SEARCH_DOWN, pattern) print('[*] hide nop code') addr_from = ida_search.find_text( s.start_ea, 0, 0, 'nop', ida_search.SEARCH_CASE | ida_search.SEARCH_DOWN) while addr_from != idaapi.BADADDR and addr_from < s.end_ea: func_offset = idc.get_func_off_str(addr_from) if type(func_offset) == str and func_offset.find('+') == -1: addr_from = ida_search.find_text( idc.next_head(addr_from), 0, 0, 'nop', ida_search.SEARCH_CASE | ida_search.SEARCH_DOWN) else: i = 0 while True: if ida_bytes.get_byte(addr_from + i) == 0x90: i += 1 else: break if i >= 3: idc.add_hidden_range(addr_from, addr_from + i, 'nop', None, None, 0xFFFFFFFF) print("%08X" % addr_from) addr_from = ida_search.find_text( idc.next_head(addr_from + i), 0, 0, 'nop', ida_search.SEARCH_CASE | ida_search.SEARCH_DOWN) #print('[*] renanlyze') #idc.del_items(s.start_ea, size=s.size()) #time.sleep(1) #idc.plan_and_wait(s.start_ea, s.end_ea) print('[*] done')
def init_functions(force=False, target_seg_name=None): global func_initialized if not force and func_initialized: return # Linear sweep to find functions for ea in idautils.Segments(): # TODO: skip other segments that are not code. seg = ida_segment.getseg(ea) seg_name = ida_segment.get_segm_name(seg) # We only check target segment since it may take too much time. if target_seg_name and seg_name == target_seg_name: continue # TODO: we may use other strategy not just sweep linearly. print("Linear sweep analysis: %x -> %x (%s)" % (seg.start_ea, seg.end_ea, seg_name)) analyze_linear_sweep(seg.start_ea, seg.end_ea) # Find function pointer candidates for ea in idautils.Segments(): # TODO: skip other segments that are not code. seg = ida_segment.getseg(ea) seg_name = ida_segment.get_segm_name(seg) # We only check target segment since it may take too much time. if target_seg_name and seg_name == target_seg_name: continue # Analyze functions by pointers print("Function pointer analysis: %x -> %x (%s)" % (seg.start_ea, seg.end_ea, seg_name)) analyze_func_ptr(seg.start_ea, seg.end_ea) func_initialized = True
def processSegments(): segments = list() for n in xrange(ida_segment.get_segm_qty()): seg = ida_segment.getnseg(n) if seg: segm = { 'name': ida_segment.get_segm_name(seg), 'start_ea': seg.start_ea, 'class': ida_segment.get_segm_class(seg) } segments.append(segm) return segments
def __process_segments(self): segments = list() for n in xrange(ida_segment.get_segm_qty()): seg = ida_segment.getnseg(n) if seg: segm = { 'name' : ida_segment.get_segm_name(seg), 'start_rva' : seg.start_ea - self._base, 'class' : ida_segment.get_segm_class(seg), 'selector' : seg.sel } segments.append(segm) return segments
def dump_binary(path): sections = [] current_offset = 0 with open(path, 'wb+') as f: # over all segments for n in range(ida_segment.get_segm_qty()): seg = ida_segment.getnseg(n) start_ea = seg.start_ea end_ea = seg.end_ea size = end_ea - start_ea dump_log.debug("Dumping 0x%x bytes from 0x%x", size, start_ea) f.write(ida_bytes.get_bytes(start_ea, size)) sections.append((ida_segment.get_segm_name(seg), start_ea, size, current_offset, size)) current_offset += size dump_log.debug(repr(sections)) return sections
def __process_segments(self): segments = list() for n in range(0, ida_segment.get_segm_qty()): seg = ida_segment.getnseg(n) if seg: segm = { 'align' : self.__describe_alignment(seg.align), 'bitness' : self.__describe_bitness(seg.bitness), 'name' : ida_segment.get_segm_name(seg), 'rva_start' : seg.start_ea - self._base, 'rva_end' : seg.end_ea - self._base, 'permission': self.__describe_permission(seg.perm), 'selector' : seg.sel, 'type' : ida_segment.get_segm_class(seg), } segments.append(segm) return segments
def get_sections(): """ Get section names and start/end addrs from IDA database :return: Dict containing section info """ sections = {} for ea in idautils.Segments(): segm = ida_segment.getseg(ea) name = ida_segment.get_segm_name(segm) if name == 'LOAD': continue curr = {} curr['start'] = segm.start_ea curr['end'] = segm.end_ea sections[name] = curr return sections
def init_strings(force=False, target_seg_name=None): global string_initialized if not force and string_initialized: return for ea in idautils.Segments(): seg = ida_segment.getseg(ea) seg_name = ida_segment.get_segm_name(seg) # We only check target segment since it may take too much time. if target_seg_name and seg_name == target_seg_name: continue print("Initializing %x -> %x (%s)" % (seg.start_ea, seg.end_ea, seg_name)) # TODO: we may use other strategy to find string pointers analyze_str_ptr(seg.start_ea, seg.end_ea) analyze_ida_str() string_initialized = True
def get_line_comments(): """ Iterate through every address in a segment and check for comments :return: Dict containing line comments """ last_comment = '' comments = {} for ea in idautils.Segments(): segm = ida_segment.getseg(ea) name = ida_segment.get_segm_name(segm) if name == 'LOAD': continue for i in range(segm.start_ea, segm.end_ea): comment = get_single_line_comment(i) if comment and comment != last_comment: comments[i] = comment last_comment = comment return comments
import ida_netnode import ida_segment def add_segment(addr, size, name): seg = ida_segment.segment_t() seg.start_ea = addr seg.end_ea = seg.start_ea + size seg.bitness = 1 ida_segment.add_segm_ex(seg, name, "DATA", 0) add_segment(0x20000000, 0x10000, "RAM") 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)
def isExternalFunction(self, function_offset): function_segment = ida_segment.getseg(function_offset) function_segment_name = ida_segment.get_segm_name(function_segment) is_extern = function_segment_name in ["extern", "UNDEF"] return is_extern