예제 #1
1
    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
예제 #2
0
    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
예제 #3
0
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
예제 #4
0
 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
예제 #5
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
예제 #6
0
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
예제 #7
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.
    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
예제 #8
0
            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)
예제 #9
0
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')
예제 #10
0
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
예제 #11
0
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
예제 #12
0
    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
예제 #13
0
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
예제 #14
0
    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
예제 #15
0
    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
예제 #16
0
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
예제 #17
0
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
예제 #18
0
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
예제 #19
0
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)
예제 #20
0
 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