Ejemplo n.º 1
0
 def getSegName(seg, segm):
     count = 0
     h = ''
     while (idaapi.get_segm_name(seg, 0) + h) in segm.keys():
         count += 1
         h = str(count)
     name = idaapi.get_segm_name(seg, 0) + h
     return name
Ejemplo n.º 2
0
def strings_init():
    strings_added = 0
    retry = []
    text_seg = get_text_seg()
    if text_seg is None:
        debug('Failed to get text segment')
        return strings_added

    # This may be inherently flawed as it will only search for defined functions
    # and as of IDA Pro 6.95 it fails to autoanalyze many GO functions, currently
    # this works well since we redefine/find (almost) all the functions prior to
    # this being used. Could be worth a strategy rethink later one or on diff archs
    for addr in Functions(text_seg.startEA, text_seg.endEA):
        name = GetFunctionName(addr)

        end_addr = Chunks(addr).next()[1]
        if (end_addr < addr):
            error('Unable to find good end for the function %s' % name)
            pass

        debug('Found function %s starting/ending @ 0x%x 0x%x' %
              (name, addr, end_addr))

        while addr <= end_addr:
            if is_string_load(addr):
                if 'rodata' not in idaapi.get_segm_name(
                        addr) and 'text' not in idaapi.get_segm_name(addr):
                    debug('Should a string be in the %s section?' %
                          idaapi.get_segm_name(addr))
                string_addr = GetOperandValue(addr, 1)
                addr_3 = FindCode(FindCode(addr, SEARCH_DOWN), SEARCH_DOWN)
                string_len = GetOperandValue(addr_3, 1)
                if create_string(string_addr, string_len):
                    if create_offset(addr):
                        strings_added += 1
                else:
                    # There appears to be something odd that goes on with IDA making some strings, always works
                    # the second time, so lets just force a retry...
                    retry.append((addr, string_addr, string_len))

                # Skip the extra mov lines since we know it won't be a load on any of them
                addr = FindCode(addr_3, SEARCH_DOWN)
            else:
                addr = FindCode(addr, SEARCH_DOWN)

    for instr_addr, string_addr, string_len in retry:
        if create_string(string_addr, string_len):
            if create_offset(instr_addr):
                strings_added += 1
        else:
            error(
                'Unable to make a string @ 0x%x with length of %d for usage in function @ 0x%x'
                % (string_addr, string_len, instr_addr))

    return strings_added
	def segm_added(self, segm):
		if idaapi.get_segm_name(segm) == 'HEADER':
			self.base_address = segm.startEA
			self.is_iOS12 = is_iOS_12(self.base_address)
		if idaapi.get_segm_name(segm) == '__thread_starts':
			self.relocs_address = segm.startEA
			self.relocs_size = segm.endEA-segm.startEA
		if idaapi.get_segm_name(segm) == '__kmod_info':
			self.is_kernelcache = True
			if self.is_iOS12 and self.relocs_address is not None:
				print 'iOS12 kernelcache detected!'
				print 'let\'s fix relocs'
				fix_relocs(self.base_address, self.relocs_address, self.relocs_size)
		return 0
Ejemplo n.º 4
0
 def getAddressDetails(self, address):
     # FIXME: look for nearest .text, then get prev
     segm = get_prev_seg(address)
     moduleName = get_segm_name(segm)
     moduleBase = segm.startEA
     offset = address - moduleBase
     return (offset, moduleName)
Ejemplo n.º 5
0
 def segm_added(self, s):
     self._send_event(SegmAddedEvent(idaapi.get_segm_name(s),
                                     idaapi.get_segm_class(s),
                                     s.start_ea, s.end_ea,
                                     s.orgbase, s.align, s.comb,
                                     s.perm, s.bitness, s.flags))
     return 0
Ejemplo n.º 6
0
    def list_segments(self):
        """ Return the list of segments in the current binary and their characteristics """
        
        self.segments = list()
        self.segments_idx = list()


        for n in xrange(get_segm_qty()):
            seg = getnseg(n)

            if not seg: 
                continue

            # For some linux binaries
            # Ida does not recognize the segment
            # permissions (usually for plt)
            if seg.perm == 0:
                continue

            segentry = SegmentEntry(
                name = idaapi.get_segm_name(seg),
                start = seg.startEA,
                end = seg.endEA,
                size = seg.size(),
                r = (seg.perm & idaapi.SEGPERM_READ) >> 2,
                w = (seg.perm & idaapi.SEGPERM_WRITE) >> 1,
                x = (seg.perm & idaapi.SEGPERM_EXEC),
                segclass = idaapi.get_segm_class(seg)
            )

            self.segments.append(segentry) 
            self.segments_idx.append(n)

        return self.segments
Ejemplo n.º 7
0
def create_string(addr, string_len):
    if idaapi.get_segm_name(addr) is None:
        debug(
            'Cannot load a string which has no segment - not creating string @ 0x%02x'
            % addr)
        return False

    debug('Found string load @ 0x%x with length of %d' % (addr, string_len))
    # This may be overly aggressive if we found the wrong area...
    if GetStringType(addr) is not None and GetString(addr) is not None and len(
            GetString(addr)) != string_len:
        debug('It appears that there is already a string present @ 0x%x' %
              addr)
        MakeUnknown(addr, string_len, DOUNK_SIMPLE)

    if GetString(addr) is None and MakeStr(addr, addr + string_len):
        return True
    else:
        # If something is already partially analyzed (incorrectly) we need to MakeUnknown it
        MakeUnknown(addr, string_len, DOUNK_SIMPLE)
        if MakeStr(addr, addr + string_len):
            return True
        debug('Unable to make a string @ 0x%x with length of %d' %
              (addr, string_len))

    return False
Ejemplo n.º 8
0
def pointer_renamer():
    renamed = 0

    text_seg = get_text_seg()
    if text_seg is None:
        debug('Failed to get text segment')
        return renamed

    for addr in Functions(text_seg.startEA, text_seg.endEA):
        name = GetFunctionName(addr)

        # Look at data xrefs to the function - find the pointer that is located in .rodata
        data_ref = idaapi.get_first_dref_to(addr)
        while data_ref != BADADDR:
            if 'rodata' in idaapi.get_segm_name(data_ref):
                # Only rename things that are currently listed as an offset; eg. off_9120B0
                if 'off_' in GetTrueName(data_ref):
                    if MakeName(data_ref, ('%s_ptr' % name)):
                        renamed += 1
                    else:
                        error(
                            'error attempting to name pointer @ 0x%02x for %s'
                            % (data_ref, name))

            data_ref = idaapi.get_next_dref_to(addr, data_ref)

    return renamed
Ejemplo n.º 9
0
    def __init__(self, seg):

        self.content = None

        self.segclass = idaapi.get_segm_class(seg)
        self.name = idaapi.get_segm_name(seg)

        self.content = function.functions_node(seg.startEA, seg.endEA)
Ejemplo n.º 10
0
    def __init__(self, seg):

        self.content = None

        self.segclass = idaapi.get_segm_class(seg)
        self.name = idaapi.get_segm_name(seg)

        self.content = function.functions_node(seg.startEA, seg.endEA)
Ejemplo n.º 11
0
def dump_binary(path):
    max_addr = 0
    # Check if we have a buggy IDA or not
    try:
        idaapi.get_many_bytes_ex(0, 1)
    except TypeError:
        buggy = True
    else:
        buggy = False
    if buggy:
        f = idaapi.qfile_t()
        try:
            f.open(path, 'wb+')
        except TypeError:
            # Another ugly hack for IDA 6/7 compat (unicode strings)
            f.open(str(path), 'wb+')
        segments = [idaapi.getnseg(x) for x in range(idaapi.get_segm_qty())]

        # no need for IDA 7 compat, it's not buggy
        max_addr = segments[-1].endEA

        if max_addr > 200 * 1024 * 1024:
            askyn = idaapi.ask_yn if hasattr(idaapi,
                                             "ask_yn") else idaapi.askyn_c
            if askyn(
                    idaapi.ASKBTN_NO, "Dump file is over 200MB,"
                    " do you want to dump it anyway ?") != idaapi.ASKBTN_YES:
                return None

        idaapi.base2file(f.get_fp(), 0, 0, max_addr)
        f.close()
        return [("dump", 0, max_addr, 0, max_addr)]

    else:
        sections = []
        current_offset = 0
        with open(path, 'wb+') as f:
            # over all segments
            for n in range(idaapi.get_segm_qty()):
                seg = idaapi.getnseg(n)
                if hasattr(seg, "start_ea"):
                    start_ea = seg.start_ea
                else:
                    start_ea = seg.startEA
                if hasattr(seg, "end_ea"):
                    end_ea = seg.end_ea
                else:
                    end_ea = seg.endEA
                size = end_ea - start_ea
                # Only works with fixed IDAPython.
                f.write(idaapi.get_many_bytes_ex(start_ea, size)[0])
                sections.append((idaapi.get_segm_name(seg), start_ea, size,
                                 current_offset, size))
                current_offset += size
        dump_log.debug(repr(sections))
        return sections
Ejemplo n.º 12
0
Archivo: file.py Proyecto: wisdark/capa
def extract_file_section_names():
    """extract section names

    IDA must load resource sections for this to be complete
        - '-R' from console
        - Check 'Load resource sections' when opening binary in IDA manually
    """
    for seg in capa.features.extractors.ida.helpers.get_segments(
            skip_header_segments=True):
        yield Section(idaapi.get_segm_name(seg)), seg.start_ea
Ejemplo n.º 13
0
def code_segments_iter():
    """Iterates over the possible code sections within an input binary."""
    for i in range(idaapi.get_segm_qty()):
        seg = idaapi.getnseg(i)

        if not seg: continue
        seg_class = idaapi.get_segm_class(seg)

        if seg_class != "CODE": continue
        seg_name = idaapi.get_segm_name(seg.startEA)

        yield seg.startEA, seg.endEA, seg_name
Ejemplo n.º 14
0
def output_segments(out):
    """Dump binary segmentation."""
    info = idaapi.get_inf_structure()
    size = "r32" if info.is_32bit else "r64"
    out.writelines(('(', info.get_proc_name()[1], ' ', size, ' ('))
    for seg in idautils.Segments():
        out.write("\n({} {} {:d} ({:#x} {:d}))".format(
            idaapi.get_segm_name(seg),
            "code" if idaapi.segtype(seg) == idaapi.SEG_CODE else "data",
            idaapi.get_fileregion_offset(seg),
            seg, idaapi.getseg(seg).size()))
    out.write("))\n")
Ejemplo n.º 15
0
def output_segments(out):
    """Dump binary segmentation."""
    info = idaapi.get_inf_structure()
    size = "r32" if info.is_32bit else "r64"
    out.writelines(('(', info.get_proc_name()[1], ' ', size, ' ('))
    for seg in idautils.Segments():
        out.write("\n({} {} {:d} ({:#x} {:d}))".format(
            idaapi.get_segm_name(seg),
            "code" if idaapi.segtype(seg) == idaapi.SEG_CODE else "data",
            idaapi.get_fileregion_offset(seg), seg,
            idaapi.getseg(seg).size()))
    out.write("))\n")
Ejemplo n.º 16
0
def code_segments_iter():
    """Iterates over the possible code sections within an input binary."""
    for i in range(idaapi.get_segm_qty()):
        seg = idaapi.getnseg(i)

        if not seg: continue
        seg_class = idaapi.get_segm_class(seg)

        if seg_class != "CODE": continue
        seg_name = idaapi.get_segm_name(seg.startEA)

        yield seg.startEA, seg.endEA, seg_name
Ejemplo n.º 17
0
def ida_iter_segments():
    seg = idaapi.get_first_seg()
    while seg:

        # TODO: CRITICAL!! Figure out how to calculate segment file size
        yield SegmentTuple(name=idaapi.get_segm_name(seg),
                           perm=seg.perm,
                           startEA=seg.startEA,
                           endEA=seg.endEA,
                           offset=ida_loader.get_fileregion_offset(
                               seg.startEA))

        seg = idaapi.get_next_seg(seg.startEA)
Ejemplo n.º 18
0
 def imp_cb(self, ea, name, ord1):
     """Callback passed to idaapi.enum_import_name in buildImportDictionary().
     Sets the name of the PE segment in which the import table resides, and
     inserts current import in dictionary of imported APIS"""
     if self.firstImport:
         self.imports_segment_name = idaapi.get_segm_name(ea)
         self.firstImport = False
     demangled_name = idc.Demangle(name, idc.GetLongPrm(idc.INF_SHORT_DN))
     if not demangled_name:
         self.import_dict[ea] = (name, self.curr_mod_name)
     else:
         self.import_dict[ea] = (demangled_name, self.curr_mod_name)
     return True
Ejemplo n.º 19
0
 def imp_cb(self, ea, name, ord1):
     """Callback passed to idaapi.enum_import_name in buildImportDictionary().
     Sets the name of the PE segment in which the import table resides, and
     inserts current import in dictionary of imported APIS"""
     if self.firstImport:
         self.imports_segment_name = idaapi.get_segm_name(ea)
         self.firstImport = False
     demangled_name = idc.Demangle(name, idc.GetLongPrm(idc.INF_SHORT_DN))
     if not demangled_name:
         self.import_dict[ea] = (name, self.curr_mod_name)
     else:
         self.import_dict[ea] = (demangled_name, self.curr_mod_name)
     return True
Ejemplo n.º 20
0
def is_string_load(addr):
    patterns = []
    # Check for first parts instruction and what it is loading -- also ignore function pointers we may have renamed
    if (GetMnem(addr) != 'mov' and GetMnem(addr) != 'lea') and (
            GetOpType(addr, 1) != 2 or GetOpType(addr, 1) != 5) or GetOpnd(
                addr, 1)[-4:] == '_ptr':
        return False

    # Validate that the string offset actually exists inside the binary
    if idaapi.get_segm_name(GetOperandValue(addr, 1)) is None:
        return False

    # Could be unk_, asc_, 'offset ', XXXXh, ignored ones are loc_ or inside []
    if GetOpnd(addr, 0) in VALID_REGS and not ('[' in GetOpnd(
            addr, 1) or 'loc_' in GetOpnd(addr, 1)) and (
                ('offset ' in GetOpnd(addr, 1) or 'h' in GetOpnd(addr, 1)) or
                ('unk' == GetOpnd(addr, 1)[:3])):
        from_reg = GetOpnd(addr, 0)
        # Check for second part
        addr_2 = FindCode(addr, SEARCH_DOWN)
        try:
            dest_reg = GetOpnd(addr_2, 0)[GetOpnd(addr_2, 0).index('[') +
                                          1:GetOpnd(addr_2, 0).index('[') + 4]
        except ValueError:
            return False
        if GetMnem(addr_2) == 'mov' and dest_reg in VALID_DEST and (
                '[%s' % dest_reg) in GetOpnd(addr_2, 0) and GetOpnd(
                    addr_2, 1) == from_reg:
            # Check for last part, could be improved
            addr_3 = FindCode(addr_2, SEARCH_DOWN)
            # GetOpType 1 is a register, potentially we can just check that GetOpType returned 5?
            if GetMnem(addr_3) == 'mov' and (
                ('[%s+' % dest_reg) in GetOpnd(addr_3, 0) or GetOpnd(
                    addr_3, 0) in VALID_DEST) and 'offset ' not in GetOpnd(
                        addr_3, 1) and 'dword ptr ds' not in GetOpnd(
                            addr_3,
                            1) and GetOpType(addr_3, 1) != 1 and GetOpType(
                                addr_3, 1) != 2 and GetOpType(addr_3, 1) != 4:
                try:
                    dumb_int_test = GetOperandValue(addr_3, 1)
                    if dumb_int_test > 0 and dumb_int_test < sys.maxsize:
                        return True
                except ValueError:
                    return False

    return False
Ejemplo n.º 21
0
def dump_loader_info(output_filename):
    """Dump information for BAP's loader into output_filename."""
    from idautils import Segments
    import idc

    idaapi.autoWait()

    with open(output_filename, 'w+') as out:
        info = idaapi.get_inf_structure()
        size = "r32" if info.is_32bit else "r64"
        out.write("(%s %s (" % (info.get_proc_name()[1], size))
        for seg in Segments():
            out.write("\n(%s %s %d (0x%X %d))" % (
                idaapi.get_segm_name(seg),
                "code" if idaapi.segtype(seg) == idaapi.SEG_CODE else "data",
                idaapi.get_fileregion_offset(seg),
                seg, idaapi.getseg(seg).size()))
        out.write("))\n")
Ejemplo n.º 22
0
def dump_loader_info(output_filename):
    """Dump information for BAP's loader into output_filename."""
    from idautils import Segments
    import idc

    idaapi.autoWait()

    with open(output_filename, 'w+') as out:
        info = idaapi.get_inf_structure()
        size = "r32" if info.is_32bit else "r64"
        out.write("(%s %s (" % (info.get_proc_name()[1], size))
        for seg in Segments():
            out.write("\n(%s %s %d (0x%X %d))" % (
                idaapi.get_segm_name(seg),
                "code" if idaapi.segtype(seg) == idaapi.SEG_CODE else "data",
                idaapi.get_fileregion_offset(seg),
                seg, idaapi.getseg(seg).size()))
        out.write("))\n")
Ejemplo n.º 23
0
def dump_binary(path):
    max_addr = 0
    # Check if we have a buggy IDA or not
    try:
        idaapi.get_many_bytes_ex(0, 1)
    except TypeError:
        buggy = True
    else:
        buggy = False
    if buggy:
        f = idaapi.qfile_t()
        f.open(path, 'wb+')
        segments = [idaapi.getnseg(x) for x in range(idaapi.get_segm_qty())]
        max_addr = segments.endEA  # no need for IDA 7 compat, it's not buggy
        if max_addr > 200 * 1024 * 1024:
            if idaapi.ask_yn(
                    idaapi.ASKBTN_NO, "Dump file is over 200MB,"
                    " do you want to dump it anyway ?") != idaapi.ASKBTN_YES:
                return None

        idaapi.base2file(f.get_fp(), 0, 0, max_addr)
        f.close()
        return [("dump", 0, max_addr, 0, max_addr)]

    else:
        sections = []
        current_offset = 0
        with open(path, 'wb+') as f:
            # over all segments
            for n in range(idaapi.get_segm_qty()):
                seg = idaapi.getnseg(n)
                start_ea = seg.start_ea if hasattr(seg,
                                                   "start_ea") else seg.startEA
                end_ea = seg.end_ea if hasattr(seg, "end_ea") else seg.endEA
                size = end_ea - start_ea
                # print "Start: %x, end: %x, size: %x" % (start, end, end-start)
                # Only works with fixed IDAPython.
                f.write(idaapi.get_many_bytes_ex(start_ea, size)[0])
                sections.append((idaapi.get_segm_name(seg), start_ea, size,
                                 current_offset, size))
                current_offset += size
        dump_log.debug(repr(sections))
        return sections
Ejemplo n.º 24
0
def get_info_about_call(call_addr,
                        call_arg,
                        stack_ptr,
                        current_function=False):
    one_row = []

    call_addr_str = '{:08X}'.format(call_addr)
    #when print current function, then add " <ip>"
    if current_function:
        call_addr_str += " <ip>"

    #"Call Address" column
    one_row.append(call_addr_str)

    #"Call Argument", column
    one_row.append(call_arg)

    function_name, call_offset_in_function, _, _ = get_func_name_and_call_offset(
        call_addr)

    #when print current function, then add " <curr fun>"
    if current_function:
        function_name += " <curr fun>"

    #"Function name" column
    one_row.append(function_name)

    #when print current function, then add " <curr pos>"
    if current_function:
        call_offset_in_function += " <curr pos>"

    #Function offset" column
    one_row.append(call_offset_in_function)

    #"Segment" columns
    one_row.append(idaapi.get_segm_name(idaapi.getseg(call_addr)))

    #"Stack pointer" column
    one_row.append(" 0x{:X}".format(stack_ptr))

    return one_row
def run_yara_on_segment(rule_text,
                        name=None,
                        start_ea=None,
                        callback_func=_yara_callback):
    '''
    Description:
        Applies yara rule to the bytes in the specified segment and returns raw results.
        Segments may be specified by name or start EA, but one or the other is required.
        Clears the matches each time to prevent duplicates.

    Input:
        name - The name of the target segment
        start_ea - The start EA of the target segment
        callback_func - A pointer to the callback function for YARA's matching to use

    Output:
        Returns a list of YARA's match results with items (location, description)
    '''
    global _YARA_MATCHES, FROM_FILE
    _YARA_MATCHES = []
    FROM_FILE = False

    if name is None and start_ea is None:
        raise Exception(
            "Either a segment name or start EA are required to YARA scan a specific segment."
        )

    rule = yara.compile(source=rule_text)
    found_segment = False
    for seg in map(idaapi.getseg, idautils.Segments()):
        if seg.startEA == start_ea or idaapi.get_segm_name(
                seg.startEA) == name:
            found_segment = True
            for bites in _read_bytes(seg.startEA, seg.endEA):
                rule.match(data=bites, callback=callback_func)

    if not found_segment:
        append_debug("Failed to find segment \"" + name + "\"")

    return _YARA_MATCHES
Ejemplo n.º 26
0
def get_sreg_base_x64(name):
    sdb = idaapi.dbg_get_thread_sreg_base(idc.GetCurrentThreadId(),
                                          int(getattr(cpu, name)))
    if not sdb:
        for n in xrange(idaapi.get_segm_qty()):
            seg = idaapi.getnseg(n)
            sgname = idaapi.get_segm_name(seg, 0)
            if sgname.startswith('TIB['):
                _sdb = seg.startEA + 0x1000
                sdb_self = int(
                    base64.b16encode(
                        idaapi.dbg_read_memory(_sdb + 0x30, 8)[::-1]), 16)
                if (sdb_self == _sdb):
                    sdb = _sdb
                    print("\nwarning: the segname:%s is zero,I give %016x" %
                          (name, sdb))
                break
    if not sdb:
        print(
            "\n\nwarning: the segname:%s is zero, U need set it by yourself\n"
            % (name))
    return sdb
Ejemplo n.º 27
0
def get_offset_name(ea):
    # Try and get the function name
    try:
        func = get_func(ea)
        name = idaapi.get_ea_name(func.start_ea)
        name = demangle(name, 0x60)  # MNG_NOTYPE | MNG_NORETTYPE
        if name:
            offset = ea - func.start_ea
            if offset:
                return '{}+{:X}'.format(name, offset)
            return name
    except exceptions.SarkNoFunction:
        pass

    # If that failed, use the segment name instead.
    segment = idaapi.getseg(ea)
    name = idaapi.get_segm_name(segment)
    offset_format = '{{:0{}X}}'.format(get_native_size() * 2)
    ea_text = offset_format.format(ea)
    if name:
        return '{}:{}'.format(name, ea_text)

    # Nothing found, simply return the address
    return ea_text
Ejemplo n.º 28
0
def findAllKEXT():
	"""
	findAllKEXT:
	
	Finds all KEXT contained in the kernelcache file. The mach-o
	headers will be converted into the appropiate structs, the
	new sections will be defined and the name and version number
	of the KEXT are extracted. In the end a window is shown that
	shows all contained KEXT.
	"""
	
	# Ask the user if he wants to add all the KEXT sections
	# to the IDA database. 
	answer = idc.AskYN(0, """Do you want to add all the KEXT sections to the IDA database?
	
If this was already done before or there was already code or data in the same place in the IDA database, IDA might react very slow, crash or just stop to work.""")
	
	# KEXT cache starts behind the __LINKEDIT segment
	# NOTE: IDA calls the segment __LINKEDIT_hidden
	
	linkedit = idaapi.get_segm_by_name("__LINKEDIT_hidden")
	if not linkedit:
		print "[-] cannot find KEXTCACHE: __LINKEDIT segment not found"
		return
	kextcache = idaapi.get_next_seg(linkedit.endEA)
	if not kextcache:
		print "[-] cannot find KEXTCACHE: __LINKEDIT not followed by any segment"
		return
	
	dummyName = idaapi.get_segm_name(kextcache)
	if dummyName != "__text":
		print "[-] cannot find KEXTCACHE: __LINKEDIT not followed by __text segment"
		return
	
	if answer == 1:
		# Destroy everything in the kextcache area
		idaapi.do_unknown_range(kextcache.startEA, kextcache.endEA-kextcache.startEA, DOUNK_DELNAMES)
	
	startEA = kextcache.startEA
	kextlist = []
	while True:
		sig = idc.Dword(startEA)
		if sig != 0xfeedface:
			"[-] expected the next KEXT but did not find correct signature"
			break
		
		seg_lc = None
		
		sections = []
		added = 0
		
		next = forceStruct(startEA, "mach_header")
		ncmds = get_member_from_struct(startEA, "mach_header", "ncmds")
		for i in range(ncmds):
			lc_addr = next
			cmd = get_member_from_struct(next, "load_command", "cmd")
			if cmd == 1:
				seg_lc = next
				next = forceStruct(seg_lc, "segment_command")
				nsecs = get_member_from_struct(seg_lc, "segment_command", "nsects")
				for j in range(nsecs):
					section = next
					next = forceStruct(section, "section")
					
					# Get basic information about segment (needed for ALL the code below)
					secStart = get_member_from_struct(section, "section", "addr")
					secEnd = secStart + get_member_from_struct(section, "section", "size")
					secname = idc.GetString(section)
					
					# We should tell IDA about what this section is
					s = idaapi.segment_t()
					s.startEA	  = secStart
					s.endEA		  = secEnd
					s.sel		  = idaapi.setup_selector(0)
					if secname == "__text":
						s.bitness = 0
					else:
						s.bitness = 1
					s.align		  = get_member_from_struct(section, "section", "align")
					s.comb		  = 0 # ???
					
					if secname == "__text" or secname == "stubs":
						sclass = "CODE"
					elif secname == "__bss":
						sclass = "BSS"
					else:
						sclass = "DATA"
					
					if len(sections) == 0:
						sec = {}
						sec["name"] = "MACH-O HEADER"
						sec["start"] = "%08X" % (startEA)
						sec["end"] = "%08X" % (secStart-1)
						sections.append(sec)
					
					sec = {}
					sec["name"] = secname
					sec["start"] = "%08X" % (secStart)
					sec["end"] = "%08X" % (secEnd-1)
					sections.append(sec)
					
					if answer == 1:
						# Destroy everything inside the segment
						idaapi.do_unknown_range(secStart, secEnd-secStart, DOUNK_DELNAMES)
					
						# Ensure that the whole section is undefined
						idaapi.add_segm_ex(s, secname, sclass, idaapi.ADDSEG_NOSREG|idaapi.ADDSEG_QUIET)
					
					if secname == "__text":
						idc.SetRegEx(secStart, "T", 1, 0)

					# special handling of constructor and destructor
					if secname == "__constructor" or secname == "__destructor":
						for z in range(secStart, secEnd, 4):
							idc.OpOffEx(z, -1, REF_OFF32, 0xFFFFFFFF, 0, 0)
					
					# We have to check for __data section because we want
					# to find the kmod_info structure
					if secname != "__data":
						continue
						
					kextName = None
					for z in range(secStart, secEnd, 4):
						k = z
						# We assume that all KEXT name start with "com."
						kextNameSig = idc.Dword(k)
						if kextNameSig == 0x2e6d6f63:
							forceStruct(k-12, "kmod_info")
							kextName = idc.GetString(k)
							kextVersion = idc.GetString(k+64)
							#print "-> %s - version: %s" % (kextName, kextVersion)
							
							dic = {}
							dic["addr"] = "%08X" % (startEA)
							dic["name"] = kextName
							dic["version"] = kextVersion
							kextlist.append(dic)
							added = 1
							break
					if kextName == None:
						print "ERROR COULD NOT FIND NAME"
					
			elif cmd == 0x1b:
				next = forceStruct(lc_addr, "uuid_command")
			elif cmd == 0x2:
				next = forceStruct(lc_addr, "symtab_command")
				#print "Found symbol table KEXT at %08x" % (startEA)
			else:
				print "Unknown load command %08x" % (cmd)
			
			if added:
				kextlist[len(kextlist)-1]["sections"] = sections
			
			next = lc_addr + get_member_from_struct(lc_addr, "load_command", "cmdsize")
		
		if seg_lc == None:
			startEA += 4
			while idc.Dword(startEA) != 0xfeedface:
				startEA += 4
			continue
		
		startEA = get_member_from_struct(seg_lc, "segment_command", "vmaddr")
		startEA += get_member_from_struct(seg_lc, "segment_command", "vmsize")

	c = MySelectionDialog("Retrieved KEXT", [ ["Address", 10], [ "Name", 65 ], ["Version", 65] ], formatKEXTresults(kextlist))
	selected_row = c.Show(True)
	if selected_row >= 0:
		sel = kextlist[selected_row]
		
		c = MySelectionDialog("Sections inside " + sel["name"], [ ["Name", 16], [ "Start", 10 ], ["End", 10] ], formatSECTIONresults(sel["sections"]))
		selected_row = c.Show(True)
		if selected_row >= 0:
			sel = sel["sections"][selected_row]
			
			idc.Jump(int(sel["start"], 16))
Ejemplo n.º 29
0
def get_segments():
    seg_names = []
    for seg in idautils.Segments():
        st = ida_segment.getseg(seg)
        seg_names.append(idaapi.get_segm_name(st))
    return seg_names
Ejemplo n.º 30
0
def writeMem(binfile, regs):
    segm = {}
    for n in xrange(idaapi.get_segm_qty()):
        seg = idaapi.getnseg(n)
        if seg:
            count = 0
            h = ''
            while (idaapi.get_segm_name(seg, 0) + h) in segm.keys():
                count += 1
                h = str(count)
            name = idaapi.get_segm_name(seg, 0) + h
            address = seg.startEA
            length = seg.endEA - seg.startEA

            db_data = idaapi.dbg_read_memory(address, length)
            if db_data:
                print('ok   ', name, seg.flags, length, 'bytes', length / 1024,
                      'kb')
                segm[name] = [address, length, db_data]
            else:
                print('faild', name, seg.flags, length, 'bytes', length / 1024,
                      'kb')
                pass
    nameoffset_p = 0
    dataoffset_p = 0
    all_ab_name = 0

    register_names = {
        16: 'rax',
        24: 'rcx',
        32: 'rdx',
        40: 'rbx',
        48: 'rsp',
        56: 'rbp',
        64: 'rsi',
        72: 'rdi',
        80: 'r8',
        88: 'r9',
        96: 'r10',
        104: 'r11',
        112: 'r12',
        120: 'r13',
        128: 'r14',
        136: 'r15',
        144: 'cc_op',
        152: 'cc_dep1',
        160: 'cc_dep2',
        168: 'cc_ndep',
        176: 'd',
        184: 'rip',
        192: 'ac',
        200: 'id',
        208: 'fs',
        216: 'sseround',
        224: 'ymm0',
        256: 'ymm1',
        288: 'ymm2',
        320: 'ymm3',
        352: 'ymm4',
        384: 'ymm5',
        416: 'ymm6',
        448: 'ymm7',
        480: 'ymm8',
        512: 'ymm9',
        544: 'ymm10',
        576: 'ymm11',
        608: 'ymm12',
        640: 'ymm13',
        672: 'ymm14',
        704: 'ymm15',
        736: 'ymm16',
        768: 'ftop',
        776: 'mm0',
        784: "mm1",
        792: "mm2",
        800: "mm3",
        808: "mm4",
        816: "mm5",
        824: "mm6",
        832: "mm7",
        840: 'fptag',
        848: 'fpround',
        856: 'fc3210',
        864: 'emnote',
        872: 'cmstart',
        880: 'cmlen',
        888: 'nraddr',
        904: 'gs',
        912: 'ip_at_syscall'
    }
    registers = {
        'rax': (16, 8),
        'eax': (16, 4),
        'ax': (16, 2),
        'al': (16, 1),
        'ah': (17, 1),
        'rcx': (24, 8),
        'ecx': (24, 4),
        'cx': (24, 2),
        'cl': (24, 1),
        'ch': (25, 1),
        'rdx': (32, 8),
        'edx': (32, 4),
        'dx': (32, 2),
        'dl': (32, 1),
        'dh': (33, 1),
        'rbx': (40, 8),
        'ebx': (40, 4),
        'bx': (40, 2),
        'bl': (40, 1),
        'bh': (41, 1),
        'rsp': (48, 8),
        'sp': (48, 8),
        'esp': (48, 4),
        'rbp': (56, 8),
        'bp': (56, 8),
        'ebp': (56, 4),
        'rsi': (64, 8),
        'esi': (64, 4),
        'si': (64, 2),
        'sil': (64, 1),
        'sih': (65, 1),
        'rdi': (72, 8),
        'edi': (72, 4),
        'di': (72, 2),
        'dil': (72, 1),
        'dih': (73, 1),
        'r8': (80, 8),
        'r9': (88, 8),
        'r10': (96, 8),
        'r11': (104, 8),
        'r12': (112, 8),
        'r13': (120, 8),
        'r14': (128, 8),
        'r15': (136, 8),
        'cc_op': (144, 8),
        'cc_dep1': (152, 8),
        'cc_dep2': (160, 8),
        'cc_ndep': (168, 8),
        'd': (176, 8),
        'dflag': (176, 8),
        'rip': (184, 8),
        'ip': (184, 8),
        'pc': (184, 8),
        'ac': (192, 8),
        'acflag': (192, 8),
        'id': (200, 8),
        'idflag': (200, 8),
        'fs': (208, 8),
        'fs_const': (208, 8),
        'sseround': (216, 8),
        'ymm0': (224, 32),
        'xmm0': (224, 16),
        'ymm1': (256, 32),
        'xmm1': (256, 16),
        'ymm2': (288, 32),
        'xmm2': (288, 16),
        'ymm3': (320, 32),
        'xmm3': (320, 16),
        'ymm4': (352, 32),
        'xmm4': (352, 16),
        'ymm5': (384, 32),
        'xmm5': (384, 16),
        'ymm6': (416, 32),
        'xmm6': (416, 16),
        'ymm7': (448, 32),
        'xmm7': (448, 16),
        'ymm8': (480, 32),
        'xmm8': (480, 16),
        'ymm9': (512, 32),
        'xmm9': (512, 16),
        'ymm10': (544, 32),
        'xmm10': (544, 16),
        'ymm11': (576, 32),
        'xmm11': (576, 16),
        'ymm12': (608, 32),
        'xmm12': (608, 16),
        'ymm13': (640, 32),
        'xmm13': (640, 16),
        'ymm14': (672, 32),
        'xmm14': (672, 16),
        'ymm15': (704, 32),
        'xmm15': (704, 16),
        'ymm16': (736, 32),
        'xmm16': (736, 16),
        'ftop': (768, 4),
        'fpreg': (776, 64),
        'fpu_regs': (776, 64),
        'mm0': (776, 8),
        'mm1': (784, 8),
        'mm2': (792, 8),
        'mm3': (800, 8),
        'mm4': (808, 8),
        'mm5': (816, 8),
        'mm6': (824, 8),
        'mm7': (832, 8),
        'fptag': (840, 8),
        'fpu_tags': (840, 8),
        'fpround': (848, 8),
        'fc3210': (856, 8),
        'emnote': (864, 4),
        'cmstart': (872, 8),
        'cmlen': (880, 8),
        'nraddr': (888, 8),
        'gs': (904, 8),
        'gs_const': (904, 8),
        'ip_at_syscall': (912, 8)
    }

    for regAddress in regs:
        INT = regs[regAddress]
        regName = register_names[regAddress]
        size = registers[regName][1]
        if size == 1:
            db_data = struct.pack("<B", INT)
        elif size == 2:
            db_data = struct.pack("<H", INT)
        elif size == 4:
            db_data = struct.pack("<I", INT)
        elif size == 8:
            db_data = struct.pack("<Q", INT)
        elif size == 16:
            db_data = struct.pack("<QQ", int(INT & 0xffffffffffffffff),
                                  int(INT >> 64))
        elif size == 32:
            db_data = struct.pack("<QQQQ", INT & 0xffffffffffffffff,
                                  (INT >> 64) & 0xffffffffffffffff,
                                  (INT >> 128) & 0xffffffffffffffff,
                                  INT >> 192)
        else:
            continue
        segm['registers' +
             str(regAddress)] = [regAddress, len(db_data), db_data]

    for name in segm:
        address, length, db_data = segm[name]
        ab_name = (name + '\x00').encode('utf-8')
        all_ab_name += len(ab_name)
    for name in segm:
        address, length, db_data = segm[name]
        ab_name = (name + '\x00').encode('utf-8')
        nameoffset = len(segm) * 32 + nameoffset_p
        dataoffset = len(segm) * 32 + all_ab_name + dataoffset_p
        db1 = struct.pack("<Q", nameoffset)
        db2 = struct.pack("<Q", address)
        db3 = struct.pack("<Q", length)
        db4 = struct.pack("<Q", dataoffset)
        binfile.write(db1)
        binfile.write(db2)
        binfile.write(db3)
        binfile.write(db4)
        nameoffset_p += len(ab_name)
        dataoffset_p += length
    for name in segm:
        address, length, db_data = segm[name]
        ab_name = (name + '\x00').encode('utf-8')
        binfile.write(ab_name)
    for name in segm:
        address, length, db_data = segm[name]
        binfile.write(db_data)
def run_yara_on_segments(rule_text,
                         names=None,
                         excluded_names=None,
                         start_eas=None,
                         excluded_eas=None,
                         callback_func=_yara_callback):
    '''
    Description:
        Applies yara rule to the bytes in the specified segments and returns raw results.
        Segemnts may be specified by name or start EA, but one or the other is required.
        Alternatively, names or start EAs may be provided to exclude. In this case all other segments will be scanned.
        Clears the matches each time to prevent duplicates.

    Input:
        names - The names of the target segments
        excluded_names - The names of the excluded segments
        start_eas - The start EAs of the target segments
        excluded_eas - The start EAs of the excluded segments
        callback_func - A pointer to the callback function for YARA's matching to use

    Output:
        Returns a list of YARA's match results with items (location, description)
    '''
    global _YARA_MATCHES, FROM_FILE
    _YARA_MATCHES = []
    FROM_FILE = False

    if names is None and excluded_names is None and start_eas is None and excluded_eas is None:
        raise Exception(
            "Either segment names, start EAs, excluded names, or excluded EAs are required to YARA scan by segment."
        )

    if (names and excluded_names) or (start_eas and excluded_eas):
        raise Exception(
            "Do not specify names and excluded names or start eas and excluded eas."
        )

    results = []
    if names:
        for name in names:
            results.extend(
                run_yara_on_segment(rule_text,
                                    name=name,
                                    callback_func=callback_func))
    elif start_eas:
        for start_ea in start_eas:
            results.extend(
                run_yara_on_segment(rule_text,
                                    start_ea=start_ea,
                                    callback_func=callback_func))
    else:
        segs_eas = list(idautils.Segments())
        if excluded_names:
            for seg_ea in segs_eas:
                seg_name = idaapi.get_segm_name(seg_ea)
                if seg_name not in excluded_names:
                    results.extend(
                        run_yara_on_segment(rule_text,
                                            name=seg_name,
                                            callback_func=callback_func))
        elif excluded_eas:
            for seg_ea in segs_eas:
                if seg_ea not in excluded_eas:
                    results.extend(
                        run_yara_on_segment(rule_text,
                                            start_ea=seg_ea,
                                            callback_func=callback_func))

    _YARA_MATCHES = results  # For conformity sake, make sure _YARA_MATCHES is set with all results
    return _YARA_MATCHES
Ejemplo n.º 32
0
def get_segm_name(ea: int) -> Optional[str]:
    return idaapi.get_segm_name(idaapi.getseg(ea))
Ejemplo n.º 33
0
    idc.plan_and_wait(segment_start, segment_end)

    print("[+] Identified %d new functions" % (nfunc))

    print("[+] Looking for interesting functions")
    find_interesting(segment_start, segment_end)

    return 1


# for easy testing
if __name__ == "__main__":
    print("[+] find_interesting():")

    for seg in idautils.Segments():
        st = ida_segment.getseg(seg)
        name = idaapi.get_segm_name(st)

        if name == "iBoot" or name == "SecureROM" or name == "iBEC" \
                or name == "BootRom" or name == "LLB":

            segm_start = st.start_ea
            segm_end = idc.get_segm_attr(segm_start, idc.SEGATTR_END)
            find_interesting(segm_start, segm_end)
            break

    # ida_pro.qexit()

# EOF
Ejemplo n.º 34
0
    def writeMem(self, binfile):
        regs = self.getRegs()
        segm = self.init_segm_mem()
        for n in xrange(idaapi.get_segm_qty()):
            seg = idaapi.getnseg(n)
            if seg:
                count = 0
                h = ''
                while (idaapi.get_segm_name(seg, 0) + h) in segm.keys():
                    count += 1
                    h = str(count)
                name = idaapi.get_segm_name(seg, 0) + h
                address = seg.startEA
                length = seg.endEA - seg.startEA

                db_data = idaapi.dbg_read_memory(address, length)
                if db_data:
                    print('ok   ', name, seg.flags, length, 'bytes',
                          length / 1024, 'kb')
                    segm[name] = [address, length, db_data]
                else:
                    print('faild', name, seg.flags, length, 'bytes',
                          length / 1024, 'kb')
                    pass
        nameoffset_p = 0
        dataoffset_p = 0
        all_ab_name = 0

        for regAddress in regs:
            INT = regs[regAddress]
            regName = self.register_names[regAddress]
            size = self.registers[regName][1]
            try:
                if size == 1:
                    db_data = struct.pack("<B", INT)
                elif size == 2:
                    db_data = struct.pack("<H", INT)
                elif size == 4:
                    db_data = struct.pack("<I", INT)
                elif size == 8:
                    db_data = struct.pack("<Q", INT)
                elif size == 16:
                    db_data = struct.pack("<QQ", int(INT & 0xffffffffffffffff),
                                          int(INT >> 64))
                elif size == 32:
                    db_data = struct.pack("<QQQQ", INT & 0xffffffffffffffff,
                                          (INT >> 64) & 0xffffffffffffffff,
                                          (INT >> 128) & 0xffffffffffffffff,
                                          INT >> 192)
                else:
                    continue
                segm['registers' +
                     str(regAddress)] = [regAddress,
                                         len(db_data), db_data]
                print(" (%-10s : %-5d) (%-x) (%d)" % (regName, regAddress,
                                                      (INT), len(db_data)))
            except Exception as e:
                print("--------- error:", e, regName, hex(INT), size,
                      "--------- ")

        for name in segm:
            address, length, db_data = segm[name]
            ab_name = (name + '\x00').encode('utf-8')
            all_ab_name += len(ab_name)
        for name in segm:
            address, length, db_data = segm[name]
            ab_name = (name + '\x00').encode('utf-8')
            nameoffset = len(segm) * 32 + nameoffset_p
            dataoffset = len(segm) * 32 + all_ab_name + dataoffset_p
            db1 = struct.pack("<Q", nameoffset)
            db2 = struct.pack("<Q", address)
            db3 = struct.pack("<Q", length)
            db4 = struct.pack("<Q", dataoffset)
            binfile.write(db1)
            binfile.write(db2)
            binfile.write(db3)
            binfile.write(db4)
            nameoffset_p += len(ab_name)
            dataoffset_p += length
        for name in segm:
            address, length, db_data = segm[name]
            ab_name = (name + '\x00').encode('utf-8')
            binfile.write(ab_name)
        for name in segm:
            address, length, db_data = segm[name]
            binfile.write(db_data)
Ejemplo n.º 35
0
 def name(self):
     return idaapi.get_segm_name(self.segment)
Ejemplo n.º 36
0
 def getSegmentName(self, ea):
     return idaapi.get_segm_name(ea)
Ejemplo n.º 37
0
 def name(self):
     return idaapi.get_segm_name(self.segment_t)
Ejemplo n.º 38
0
 def getSegmentName(self, ea):
     return idaapi.get_segm_name(ea)