Ejemplo n.º 1
0
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")
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
    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)
Ejemplo n.º 5
0
    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)
Ejemplo n.º 6
0
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
Ejemplo n.º 7
0
    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')
Ejemplo n.º 8
0
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
Ejemplo n.º 9
0
    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
Ejemplo n.º 10
0
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
Ejemplo n.º 11
0
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)
Ejemplo n.º 12
0
 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)
Ejemplo n.º 13
0
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
Ejemplo n.º 14
0
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")
Ejemplo n.º 15
0
def enum_segments():
    for segstart in idautils.Segments():
        segend = idc.get_segm_end(segstart)
        segname = idc.get_segm_name(segstart)
        yield segstart, segend, segname
Ejemplo n.º 16
0
 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
Ejemplo n.º 17
0
# 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))
Ejemplo n.º 18
0
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")
Ejemplo n.º 19
0
def isValidPointer_ida7(va):
    for segStart in idautils.Segments():
        if (va >= segStart) and (va < idc.get_segm_end(segStart)):
            return True
    return False
Ejemplo n.º 20
0
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)
Ejemplo n.º 21
0
 def getSegEnd(self, ea):
     if idaapi.IDA_SDK_VERSION < 700:
         return idc.SegEnd(ea)
     else:
         return idc.get_segm_end(ea)
Ejemplo n.º 22
0
 def getSegmentEnd(self, addr):
     return idc.get_segm_end(addr)
Ejemplo n.º 23
0
def isValidPointer_ida7(va):
    for segStart in idautils.Segments():
        if (va >= segStart) and (va < idc.get_segm_end(segStart)):
            return True
    return False
Ejemplo n.º 24
0
 def __init__(self):
     self._segs = [
         Segment(va, idc.get_segm_end(va)) for va in idautils.Segments()
     ]
     self._segs.sort()
Ejemplo n.º 25
0
 def cmd_get_segment_end(self, a):
     return self.fmt_addr(idc.get_segm_end(int(a, 0)))
Ejemplo n.º 26
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
Ejemplo n.º 27
0
# 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)
Ejemplo n.º 28
0
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")
Ejemplo n.º 29
0
        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:
Ejemplo n.º 30
0
def DumpSegPTE(ea):
    DumpPTE(idc.get_segm_start(ea), idc.get_segm_end(ea))
Ejemplo n.º 31
0
def SegEnd(ea):
    return idc.get_segm_end(ea)
Ejemplo n.º 32
0
 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()   
Ejemplo n.º 33
0
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:
Ejemplo n.º 34
0
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')
Ejemplo n.º 35
0
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)
Ejemplo n.º 36
0
 def getLastAddress(self):
     return idc.get_segm_end([ea for ea in idautils.Segments()][-1]) - 1