コード例 #1
0
ファイル: helpers.py プロジェクト: uqcybersquad/capa
def read_bytes_at(ea, count):
    """ """
    segm_end = idc.get_segm_end(ea)
    if ea + count > segm_end:
        return idc.get_bytes(ea, segm_end - ea)
    else:
        return idc.get_bytes(ea, count)
コード例 #2
0
ファイル: idayara.py プロジェクト: thezedwards/kordesii
def _read_bytes(start_ea, end_ea):
    """
    Description:
        Reads and returns the bytes from <start_ea> to <end_ea>. Reads are returned in sections
        READ_LENGTH in length to avoid potential memory concerns for extremely large ranges.

    Input:
        start_ea - The start of the range
        end_ea - The end of the range

    Output:
        A string of the bytes in the given range
    """
    global SECTION_START

    block_start = start_ea
    block_end = end_ea
    while block_start < end_ea:
        while block_start < end_ea and idc.get_bytes(block_start, 1) is None:
            block_start += 1
        if block_start >= end_ea:
            break
        block_end = block_start + 1
        while block_end < end_ea and idc.get_bytes(block_end, 1) is not None:
            block_end += 1

        SECTION_START = block_start
        while block_start < block_end:
            yield idc.get_bytes(block_start,
                                min(READ_LENGTH, block_end - block_start))
            SECTION_START += READ_LENGTH
            block_start += READ_LENGTH

        block_start = block_end + 1
コード例 #3
0
    def extract_info_from_IDA(self):
        prots = ida_bytes.get_qword(self.ea + 0x10)
        if prots:
            count = ida_bytes.get_qword(prots)
            entrysize = 0x8
            p_ea = prots + 8
            for i in range(count):
                proto_ea = idc.get_qword(p_ea)
                self.prots.append(proto_ea)
                p_ea += entrysize

        type_info = ida_bytes.get_qword(self.ea + 0x48)
        for idx in range(0, 4):
            # 0: inst_meths
            # 1: class_meths
            # 2: opt_inst_meths
            # 3: opt_class_meths
            meth_list = ida_bytes.get_qword(self.ea + 0x18 + idx * 8)
            if meth_list:
                entrysize = ida_bytes.get_dword(meth_list)
                count = ida_bytes.get_dword(meth_list + 4)
                ea = meth_list + 8
                for i in range(0, count):
                    sel = idc.get_bytes(idc.Qword(ea), idc.get_item_size(idc.Qword(ea)) - 1)
                    meth_type = idc.get_bytes(idc.Qword(type_info), idc.get_item_size(idc.Qword(type_info)) - 1)
                    self.meths[sel] = meth_type
                    ea += entrysize
                    type_info += 8
コード例 #4
0
    def __get_instruction_bytes_wildcarded(pattern, addr, instr_type, op1_type,
                                           op2_type):
        """Replaces bytes related to memory addresses with wildcards.

    TODO: To be replaced by ida_idp.ph_calcrel()

    Args:
      pattern: current buffer containing the bytes of the current instruction.
      addr: the address of the current instruction to be wildcarded
      instr_type: type of the current instruction
      op1_type: type of the first operand
      op2_type: type of the second operand

    Returns:
      String: hex-encoded representation of the bytes obtained at addr where
              all the operands that refers to memmory addresses are wildcarded.
    """

        type_calls = frozenset(
            [idaapi.NN_call, idaapi.NN_callfi, idaapi.NN_callni])
        type_jumps = frozenset(
            [idaapi.NN_jmp, idaapi.NN_jmpfi, idaapi.NN_jmpni])

        inst_prefix = binascii.hexlify(idc.get_bytes(addr, 1)).decode('utf-8')
        drefs = [x for x in idautils.DataRefsFrom(addr)]

        logging.debug('[VTGREP] Wildcarding: %s',
                      idc.generate_disasm_line(addr, 0))

        # Known 2 bytes opcodes
        if inst_prefix in ('0f', 'f2', 'f3'):
            pattern = binascii.hexlify(idc.get_bytes(addr, 2)).decode('utf-8')
            inst_num_bytes = 2

        # CALLs or JUMPs using 2 bytes opcodes
        elif inst_prefix == 'ff' and (instr_type in type_jumps
                                      or instr_type in type_calls):

            pattern = binascii.hexlify(idc.get_bytes(addr, 2)).decode('utf-8')
            inst_num_bytes = 2

        # A PUSH instruction using an inmediate value (mem offset)
        elif (inst_prefix == 'ff' and drefs
              and (op1_type == idaapi.o_imm or op2_type == idaapi.o_imm)):

            pattern = binascii.hexlify(idc.get_bytes(addr, 2)).decode('utf-8')
            inst_num_bytes = 2

        # No prefix is used
        else:
            pattern = inst_prefix
            inst_num_bytes = 1

        pattern += ' ' + '??' * (idc.get_item_size(addr) -
                                 inst_num_bytes) + ' '
        return pattern
コード例 #5
0
ファイル: helpers.py プロジェクト: th14g0d3v/capa
def read_bytes_at(ea, count):
    """ """
    # check if byte has a value, see get_wide_byte doc
    if not idc.is_loaded(ea):
        return b""

    segm_end = idc.get_segm_end(ea)
    if ea + count > segm_end:
        return idc.get_bytes(ea, segm_end - ea)
    else:
        return idc.get_bytes(ea, count)
コード例 #6
0
ファイル: findcrypt.py プロジェクト: you0708/ida
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")
コード例 #7
0
ファイル: brk.py プロジェクト: fcccode/IDAngr
def get_dbg_brk_linux32():
    '''
    Return the current brk value in the debugged process (only x86 Linux)
    '''
    #TODO this method is so weird, find a unused address to inject code not the base address

    code = ""
    code += '\xb8-\x00\x00\x00'  #mov eax, sys_brk ; 45
    code += '1\xdb'  #xor ebx, ebx
    code += '\xcd\x80'  #int 0x80

    eax = idc.get_reg_value("eax")
    ebx = idc.get_reg_value("ebx")
    eip = idc.get_reg_value("eip")
    efl = idc.get_reg_value("efl")

    base = idaapi.get_imagebase()

    #inj = idc.next_head(eip) #skip current instr
    inj = base

    save = idc.get_bytes(inj, len(code), use_dbg=True)

    for i in xrange(len(code)):
        idc.patch_dbg_byte(inj + i, ord(code[i]))

    #idc.MakeCode(inj)

    idc.set_reg_value(inj, "eip")

    idaapi.step_into()
    idc.GetDebuggerEvent(idc.WFNE_SUSP, -1)
    idaapi.step_into()
    idc.GetDebuggerEvent(idc.WFNE_SUSP, -1)
    idaapi.step_into()
    idc.GetDebuggerEvent(idc.WFNE_SUSP, -1)

    brk_res = idc.get_reg_value("eax")

    idc.set_reg_value(eax, "eax")
    idc.set_reg_value(ebx, "ebx")
    idc.set_reg_value(eip, "eip")
    idc.set_reg_value(efl, "efl")

    for i in xrange(len(save)):
        idc.patch_dbg_byte(inj + i, ord(save[i]))

    save = idc.get_bytes(inj, len(code), use_dbg=True)

    #idc.MakeCode(inj)

    return brk_res
コード例 #8
0
ファイル: brk.py プロジェクト: fcccode/IDAngr
def get_dbg_brk_linux64():
    '''
    Return the current brk value in the debugged process (only x86_64 Linux)
    '''
    #TODO this method is so weird, find a unused address to inject code not the base address

    code = ""
    code += 'H\xc7\xc0\x0c\x00\x00\x00'  #mov rax, sys_brk ; 12
    code += 'H1\xff'  #xor rdi, rdi
    code += '\x0f\x05'  #syscall

    rax = idc.get_reg_value("rax")
    rdi = idc.get_reg_value("rdi")
    rip = idc.get_reg_value("rip")
    efl = idc.get_reg_value("efl")

    base = idaapi.get_imagebase()

    #inj = idc.next_head(rip) #skip current instr
    inj = base

    save = idc.get_bytes(inj, len(code), use_dbg=True)

    for i in xrange(len(code)):
        idc.patch_dbg_byte(inj + i, ord(code[i]))

    #idc.MakeCode(inj)

    idc.set_reg_value(inj, "rip")

    idaapi.step_into()
    idc.GetDebuggerEvent(idc.WFNE_SUSP, -1)
    idaapi.step_into()
    idc.GetDebuggerEvent(idc.WFNE_SUSP, -1)
    idaapi.step_into()
    idc.GetDebuggerEvent(idc.WFNE_SUSP, -1)

    brk_res = idc.get_reg_value("rax")

    idc.set_reg_value(rax, "rax")
    idc.set_reg_value(rdi, "rdi")
    idc.set_reg_value(rip, "rip")
    idc.set_reg_value(efl, "efl")

    for i in xrange(len(save)):
        idc.patch_dbg_byte(inj + i, ord(save[i]))

    save = idc.get_bytes(inj, len(code), use_dbg=True)

    #idc.MakeCode(inj)

    return brk_res
コード例 #9
0
def getLZ77CompressedSize(compressed_ea):
    """
    Iterates the compressed data, and returns its size
    :param compressed_ea: the linear address of the compressed data
    :return: its size in bytes or <0 if this is an invalid format
    """
    dataHeader = 0
    chars = idc.get_bytes(compressed_ea, 4)
    for i in range(len(chars)):
        dataHeader |= ord(chars[i]) << 8 * i
    decompSize = (dataHeader & ~0xFF) >> 8

    # compression type must match
    if (dataHeader & 0xF0) >> 4 != 1:
        return -1

    # iterate, and figure out the number of bytes copied
    size = 0
    ea = compressed_ea + 4
    # iterate the blocks and keep count of the data size
    while size < decompSize:
        # parse block flags (compressed or not)
        flags = ord(idc.get_bytes(ea, 1))
        ea += 1

        # iterate the blocks, MSB first.
        for i in range(7, -1, -1):
            if flags & (1 << i):
                # block i is compressed
                chars = idc.get_bytes(ea, 2)
                block = ord(chars[0]) + (ord(chars[1]) << 8)
                size += ((block & 0xF0) >> 4) + 3
                ea += 2
                # check that the displacement doesn't underflow
                disp = ((block & 0xFF00) >> (16 - 4)) | block & 0xF
                if size - disp - 1 < 0:
                    return -2
            else:
                # block i is uncompressed, it's just one byte
                size += 1
                ea += 1
            # we might finish decompressing while processing blocks
            if size >= decompSize:
                # ensure that the rest of the flags are 0!
                # this is a practical restriction. (likely true, not technically part of the specs)
                for j in range(i, -1, -1):
                    if flags & (1 << j) != 0:
                        return -3
                break

    print('decompressed size: 0x%X' % decompSize)
    return ea - compressed_ea
コード例 #10
0
    def iterateByPaddingToTheLastInstruction(ea):
        debug(
            "iterateByPaddingToTheLastInstruction. Address: 0x{:X}".format(ea))
        for i in range(0, 16):
            ea -= 1
            bytes = idc.get_bytes(ea, 1)

            debug('ea: 0x{:X}'.format(ea))
            debug(idc.get_bytes(ea, 1)[0])
            if idc.get_bytes(ea, 1)[0] == 0xCC or idc.get_bytes(ea,
                                                                1)[0] == 0x90:
                print('continue')
                continue
            break
コード例 #11
0
def find_guid_in_address_space(start_address, end_address):
    """
    This function will try to parse memonique with an operand value as second
    parameter, then will try to validate it with registry
    :ivar int start_address: 
    """
    result = []
    for head in idautils.Heads(start_address, end_address):
        # search for direct value operand
        for operand_value in [
                idc.get_operand_value(head, 1),
                idc.get_operand_value(head, 0)
        ]:
            guid_bytes = idc.get_bytes(operand_value, 16)
            guid = guid_bytes_to_string(guid_bytes)
            try:
                result.append(build_com_from_class_definition(head, guid))
                break
            except WindowsError as e:
                pass

            try:
                result.append(build_com_from_interface_definition(head, guid))
                break
            except WindowsError as e:
                pass

    return result
コード例 #12
0
ファイル: decoderutils.py プロジェクト: amjobmann/kordesii
    def _get_bytes(self, location, size=None, code_page=None):
        """
        Extracts bytes from given location.

        :param location: Location to pull bytes
        :param size: Number of bytes to pull (determines size by looking for terminator if not provided)
        :param code_page: Known code_page used to determine terminator.
        :return: bytes or None
        """
        # Determine size by looking for terminator.
        # (Use provided encoding to determine terminator width.)
        if size is None:
            width = 1
            if code_page:
                if '16' in code_page:
                    width = 2
                elif '32' in code_page:
                    width = 4
            end_location = idc.find_binary(location, idc.SEARCH_DOWN, "00 " * width)
            if end_location == idc.BADADDR:
                logger.warning('Failed to extract bytes from 0x{:08X}'.format(location))
                return None

            size = end_location - location
            while size % width:  # ensure unicode strings are a valid length
                size += 1

        # Pull size amount of bytes from IDA.
        data = idc.get_bytes(location, size)
        if data is None:
            logger.warning('Failed to extract {} bytes from 0x{:08X}'.format(size, location))
        return data
コード例 #13
0
def copy_bytes():
    """
    Copy selected bytes to clipboard
    """
    if using_ida7api:
        start = idc.read_selection_start()
        end = idc.read_selection_end()
        if idaapi.BADADDR in (start, end):
            ea = idc.here()
            start = idaapi.get_item_head(ea)
            end = idaapi.get_item_end(ea)
        # # reference https://stackoverflow.com/questions/6624453/whats-the-correct-way-to-convert-bytes-to-a-hex-string-in-python-3
        data = idc.get_bytes(start, end - start).hex()
        print("Bytes copied: %s" % data)
        copy_to_clip(data)
    else:
        start = idc.SelStart()
        end = idc.SelEnd()
        if idaapi.BADADDR in (start, end):
            ea = idc.here()
            start = idaapi.get_item_head(ea)
            end = idaapi.get_item_end(ea)
        # reference https://stackoverflow.com/questions/6624453/whats-the-correct-way-to-convert-bytes-to-a-hex-string-in-python-3
        # not work in ida7.5 python3.7.7
        # data = idc.GetManyBytes(start, end-start).encode('hex')
        data = idc.GetManyBytes(start, end - start).hex()
        print("Bytes copied: %s" % data)
        copy_to_clip(data)
    return
コード例 #14
0
    def activate(self, ctx):
        """
        :param ctx: idaapi.action_activation_ctx_t
        :return:    None
        """
        ea = get_screen_ea()

        if get_func(ea) is None:
            print("address = " + hex(ea))

            data = get_bytes(ea, 16)
            guid = str(UUID(bytes_le=data))
        else:
            name, data = extract_guid(ea)
            guid = str(UUID(bytes_le=data))

            print("Local variable EFI_GUID extraction for " + name)

        print("data = " + " ".join("%02x" % x for x in bytes(data)))
        print("guid = " + guid)

        try:
            import clipboard

            clipboard.copy(guid)
        except ImportError:
            print("clipboard module is not available.")
def decryptor(index, call_addr):
    decrypted_string = ""
    current_struct_start = struct_start + 8 * index
    current_struct_bytes = idc.get_bytes(current_struct_start, 8)
    print(current_struct_bytes.hex())
    #structure parsing and xoring
    key = int.from_bytes(current_struct_bytes[0:1],
                         byteorder='little',
                         signed=False)
    length = int.from_bytes(current_struct_bytes[2:4],
                            byteorder='little',
                            signed=False)
    buffer_string_addr = int.from_bytes(current_struct_bytes[4:8],
                                        byteorder='little',
                                        signed=False)
    print(hex(key), hex(length), hex(buffer_string_addr))
    #decrypting
    for i in range(0, length):
        decrypted_string += chr(key
                                ^ idc.get_wide_byte(buffer_string_addr + i))
    print(decrypted_string)
    #commenting assembly view
    idc.set_cmt(call_addr, decrypted_string, 0)
    #commenting decompile view on the same address as assembly view
    cfunc = idaapi.decompile(call_addr)
    tl = idaapi.treeloc_t()
    tl.ea = call_addr
    tl.itp = idaapi.ITP_SEMI
    cfunc.set_user_cmt(tl, decrypted_string)
    cfunc.save_user_cmts()
コード例 #16
0
def find_binary_instruction_start(
    search_start_location,
    search_direction,
    target,
    min_location=idc.get_inf_attr(idc.INF_MIN_EA),
    max_location=idc.get_inf_attr(idc.INF_MAX_EA)):
    """
    Description:
        Given a starting location, target, and direction, find an instruction starting with the target bytes.

    Input:
        search_start_location - The EA to start searching at
        search_direction - either idc.SEARCH_UP or idc.SEARCH_DOWN
        target - The target as space separated bytes (i.e. '55' for 'push ebp')
        min_location - The minimum EA to accept results for (default: idc.get_inf_attr(idc.INF_MIN_EA))
        max_location - The maximum EA to accept results for (default: idc.get_inf_attr(idc.INF_MAX_EA))

    Output:
        Returns the first matching location if found, otherwise idc.BADADDR
    """
    target = target.upper()
    while search_start_location < max_location:
        ea = idc.find_binary(search_start_location, search_direction, target)
        if (min_location <= ea < max_location
                and ea == idc.get_item_head(ea) and idc.get_bytes(
                    ea,
                    idc.get_item_size(ea)).encode('hex').upper().startswith(
                        target.replace(' ', ''))):
            return ea
        else:
            search_start_location = ea + (1 if search_direction
                                          == idc.SEARCH_DOWN else -1)
    return idc.BADADDR
コード例 #17
0
ファイル: tracing.py プロジェクト: thezedwards/kordesii
def handle_mov(ea, state):
    """Updates the stack based on a mov instruction. Used by create_stack

        :param ea: instruction location
        :param state: the current TraceState

        :return: None - updates stack or regs
    """
    op1 = get_opnd_replacement(ea, POS_FIRST)
    if idc.get_operand_type(ea, POS_FIRST) != idc.o_reg:
        offset = get_operand_value_replacement(ea, POS_FIRST, state)
        set_stack(offset, ea, POS_SECOND, state)
    else:
        type_ = idc.get_operand_type(ea, POS_SECOND)
        val = None
        if type_ == idc.o_reg:
            val = state.get_reg_value(get_opnd_replacement(ea, POS_SECOND))
        elif type_ == idc.o_mem:
            bytes = idc.get_bytes(idc.get_operand_value(ea, POS_SECOND), get_byte_size_of_operand(ea, POS_SECOND))
            if bytes:
                val = 0
                for x in range(len(bytes)):
                    val += ord(bytes[x]) << (8 * x)
        elif type_ == idc.o_imm:
            val = idc.get_operand_value(ea, POS_SECOND)
        else:
            offset = get_operand_value_replacement(ea, POS_SECOND, state)
            val, ea = state.stack.get(offset, (None, ea))
        state.set_reg_value(op1, val, ea)
コード例 #18
0
def resolvePointers(fileRange, pointerRange, verbose=True):
    """

    :param fileRange: tuple of (int, int) representing the file to resolve pointers in
    :param pointerRange: tuple of (int, int) representing range of pointers to resolve
    :param verbose: if True, all changes are printed
    :return:
    """
    if verbose:
        print("(%07X, %07X): expand unknown arrays" %
              (fileRange[0], fileRange[1]))
    expandUnkArrays(*fileRange, verbose=False)

    ea = fileRange[0]
    while ea < fileRange[1]:
        ea = next.unkptr(ea, fileRange[1], rom=True, ui=False, hexOut=False)
        if ea != idaapi.BADADDR:
            # get data at ea
            chars = idc.get_bytes(ea, 4)
            dword = 0
            for i in range(len(chars)):
                dword += ord(chars[i]) << 8 * i

            if pointerRange[0] <= dword < pointerRange[1]:
                if verbose: print('%07X: %07X' % (ea, dword))
                idc.op_plain_offset(ea, 0, 0)
コード例 #19
0
def getUnkPointers(fileRange, verbose=True, rom=True):
    """
    reports back all suspect unknown pointers within the file
    :param fileRange:
    :param verbose:
    :return:
    """
    if verbose:
        print("(%07X, %07X): expand unknown arrays" %
              (fileRange[0], fileRange[1]))
    expandUnkArrays(*fileRange, verbose=False)

    output = []

    ea = fileRange[0]
    while ea < fileRange[1]:
        ea = next.unkptr(ea, fileRange[1], rom=rom, ui=False, hexOut=False)
        if ea != idaapi.BADADDR:
            # get data at ea
            chars = idc.get_bytes(ea, 4)
            dword = 0
            for i in range(len(chars)):
                dword += ord(chars[i]) << 8 * i
            output.append((ea, dword))

    if verbose:
        print("(%07X, %07X): collapsing unknowns " %
              (fileRange[0], fileRange[1]))
    collapseUnknowns(*fileRange, verbose=False)

    return output
コード例 #20
0
def parse_table(ea):
    table = u64(idc.get_bytes(ea, 8))
    addr = table

    func_table = []
    while True:
        pm4type, opcode, handler = read_entry(addr)
        if handler == 0:
            break
        # get gnm name and packet count
        gnm_name, packet_count = parse_function(handler)
        # decompile the handler
        func = ida_hexrays.decompile(handler)
        lines = func.get_pseudocode()
        code_lines = []
        for sline in lines:
            line = ida_lines.tag_remove(sline.line)
            code_lines.append(line)

        print('{}\t{} {} {:X} {:08X}'.format(gnm_name, packet_count, pm4type,
                                             opcode, handler))
        if not gnm_name:
            gnm_name = 'sub_{:X}'.format(handler)
        func_table.append(
            (gnm_name, packet_count, pm4type, opcode, handler, code_lines))
        addr += 16
    return func_table
コード例 #21
0
ファイル: tools.py プロジェクト: okandok/vmpanalysis
def get_displ_reg(arg_inst, opt_index):
    base_reg = -1
    index_reg = -1
    disp = 0

    # capstone 解码内存引用寄存器
    for cs_insn in md.disasm(idc.get_bytes(arg_inst.ea, arg_inst.size),
                             arg_inst.size):
        cs_opt0 = cs_insn.operands[opt_index]

        # ps: mov eax, [edi+ecx+0x10]
        # 基地址寄存器
        if cs_opt0.value.mem.base:
            base_reg = capstone_reg_map[cs_insn.reg_name(
                cs_opt0.value.mem.base)]

        # 变地寄存器
        if cs_opt0.value.mem.index:
            index_reg = capstone_reg_map[cs_insn.reg_name(
                cs_opt0.value.mem.index)]

        # 偏移
        if cs_opt0.value.mem.disp:
            disp = cs_opt0.value.mem.disp
        break

    return base_reg, index_reg, disp
コード例 #22
0
    def extract(self):
        """
        Extracts all binary ranges specified in env['binFiles'] into *.bin files in the folder env['binPath']
        """
        # grab necessary variables from the environment and assert that they were given
        gameFiles = self.get('gameFiles')
        binPath = self.get('dismProjPath') + self.get('binPath')
        if not gameFiles or not binPath:
            print(
                'ERROR: environmental variables for dismProjPath, gameFiles, and binPath'
                + ' must be provided.')
            return

        keys = gameFiles.keys()
        keys.sort()
        for file in keys:
            if '.bin' in file:
                # get bytes in specified range
                bytes = idc.get_bytes(gameFiles[file][0],
                                      gameFiles[file][1] - gameFiles[file][0])

                # write bytes to bin file
                bpath = binPath + file
                print("Extracting %s into %s... " % (file, bpath))
                binfile = open(bpath, 'wb')
                binfile.write(bytes)
                binfile.close()
        print("Extraction complete!")
コード例 #23
0
def read_memory(segments, ea, size):
    if IDA_MODULE:
        return idc.get_bytes(ea, size)

    for segment_ea, data in segments.items():
        if (ea <= segment_ea + len(data)) and (ea >= segment_ea):
            offset = ea - segment_ea
            return data[offset:offset + size]
コード例 #24
0
ファイル: file.py プロジェクト: wisdark/capa
def check_segment_for_pe(seg):
    """check segment for embedded PE

    adapted for IDA from:
    https://github.com/vivisect/vivisect/blob/7be4037b1cecc4551b397f840405a1fc606f9b53/PE/carve.py#L19

    args:
        seg (IDA segment_t)
    """
    seg_max = seg.end_ea
    mz_xor = [(
        capa.features.extractors.helpers.xor_static(b"MZ", i),
        capa.features.extractors.helpers.xor_static(b"PE", i),
        i,
    ) for i in range(256)]

    todo = []
    for (mzx, pex, i) in mz_xor:
        for off in capa.features.extractors.ida.helpers.find_byte_sequence(
                seg.start_ea, seg.end_ea, mzx):
            todo.append((off, mzx, pex, i))

    while len(todo):
        off, mzx, pex, i = todo.pop()

        # The MZ header has one field we will check e_lfanew is at 0x3c
        e_lfanew = off + 0x3C

        if seg_max < (e_lfanew + 4):
            continue

        newoff = struct.unpack(
            "<I",
            capa.features.extractors.helpers.xor_static(
                idc.get_bytes(e_lfanew, 4), i))[0]

        peoff = off + newoff
        if seg_max < (peoff + 2):
            continue

        if idc.get_bytes(peoff, 2) == pex:
            yield (off, i)

        for nextres in capa.features.extractors.ida.helpers.find_byte_sequence(
                off + 1, seg.end_ea, mzx):
            todo.append((nextres, mzx, pex, i))
コード例 #25
0
ファイル: guids.py プロジェクト: tuxinggougou/ida-efitools2
def _process_segment(seg_beg, seg_end):
    for addr in range(seg_beg, seg_end, 4):
        guid_bytes_le = get_bytes(addr, _GUID_SIZE)
        if guid_bytes_le != _zero_guid_bytes and guid_bytes_le != _ffff_guid_bytes:
            guid_name = _guids_db.get(guid_bytes_le, None)
            if guid_name:
                # Just marks it as a GUID structure
                guid = GUID(addr=addr, name=guid_name)
                print("Found %s @ 0x%X" % (guid, addr))
コード例 #26
0
 def _getOriginData(self, address, size):
     res = []
     for offset in range(0, size, 64):
         tmp = get_bytes(address + offset, 64)
         if tmp == None:
             res.extend([pack("<Q", get_qword(address + offset + i)) for i in range(0, 64, 8)])
         else:
             res.append(tmp)
     res = b"".join(res)
     return res[:size]
コード例 #27
0
def _emit_fnbytes(emit_instr_cb, header, footer, indent, fva=None, warn=True):
    """Emit function bytes in a format defined by the callback and
    headers/footers provided.

    Warns if any instruction operands are not consistent with
    position-independent code, in which case the user may need to templatize
    the position-dependent portions.
    """
    fva = fva or idc.here()
    fva = idc.get_func_attr(fva, idc.FUNCATTR_START)
    va_end = idc.get_func_attr(fva, idc.FUNCATTR_END)

    # Operand types observed in position-independent code:
    optypes_position_independent = set([
        ida_ua.o_reg,  # 1: General Register (al,ax,es,ds...)
        ida_ua.o_phrase,  # 3: Base + Index
        ida_ua.o_displ,  # 4: Base + Index + Displacement
        ida_ua.o_imm,  # 5: Immediate
        ida_ua.o_near,  # 7: Immediate Near Address
    ])

    # Notably missing because I want to note and handle these if/as they are
    # encountered:
    # ida_ua.o_idpspec0 = 8: FPP register
    # ida_ua.o_idpspec1 = 9: 386 control register
    # ida_ua.o_idpspec2 = 10: 386 debug register
    # ida_ua.o_idpspec3 = 11: 386 trace register

    va = fva
    nm = idc.get_name(fva)
    optypes_found = set()
    s = header.format(name=nm)
    while va not in (va_end, idc.BADADDR):
        size = idc.get_item_size(va)
        the_bytes = idc.get_bytes(va, size)

        for i in range(0, 8):
            optype = idc.get_operand_type(va, i)
            if optype:
                optypes_found.add(optype)

        s += indent + emit_instr_cb(va, the_bytes, size)
        va = idc.next_head(va)
    s += footer

    position_dependent = optypes_found - optypes_position_independent
    if position_dependent:
        msg = ('This code may have position-dependent operands (optype %s)' %
               (', '.join([str(o) for o in position_dependent])))
        if warn:
            Warning(msg)
        else:
            logger.warn(msg)

    return s
コード例 #28
0
def try_make_function(function_start,
                      function_end=idc.BADADDR,
                      target_location=None,
                      require_term=True,
                      end_mnem_bytes=None):
    """
    Description:
        Given a function location, attempt to create a function.
        If function creation fails, delete any partially created functions.
        If function creation succeeds, ensure all of the function's bytes are analyzed as code.

    Input:
        function_start - The start_ea of the function to create
        function_end - The end_ea of the function to create. IDA will calculate if not provided.
        target_location - If provided, fail function creation if it does not include this EA
        require_term - If provided, fail function creation if the last instruction is not a ret or jmp
        end_mnem_bytes - If provided, fail function creation if the last instruction is not the provided bytes
                         Instructions are entered as space separated bytes (i.e. '55' for 'push ebp')

    Output:
        Returns a tuple (function_start, function_end) for the created function if successful, None otherwise
    """
    if function_start <= function_end:
        if idc.add_func(function_start, function_end):
            logger.debug('Created a function 0x%X - 0x%X.' %
                         (function_start, function_end))
            if require_term:
                last_mnem_ea = idc.get_item_head(
                    idaapi.get_func(function_start).end_ea - 1)
                last_mnem = idc.print_insn_mnem(last_mnem_ea)
                if (end_mnem_bytes is None and 'ret' not in last_mnem and 'jmp' not in last_mnem) or \
                        (end_mnem_bytes and idc.get_bytes(last_mnem_ea, idc.get_item_size(last_mnem_ea)).encode('hex').upper() != end_mnem_bytes.upper()):
                    idc.del_func(function_start)
                    logger.debug(
                        'Deleted function at 0x%X - the function didn\'t end with the correct mnem/bytes.'
                        % function_start)
                    return
            if target_location is not None:
                if function_start <= target_location < idaapi.get_func(
                        function_start).end_ea:
                    idc.plan_and_wait(function_start,
                                      idaapi.get_func(function_start).end_ea)
                    return function_start, function_end
                else:
                    idc.del_func(function_start)
                    logger.debug(
                        'Deleted function at 0x%X - the function didn\'t contain the target location.'
                        % function_start)
                    return
        else:
            logger.debug(
                'Tried to create a function 0x%X - 0x%X, but IDA wouldn\'t do it.'
                % (function_start, function_end))
    else:
        logger.debug('The end address was not greater than the start address!')
コード例 #29
0
    def __init__(self, ea, info, cs):
        """Initialization function."""
        # Init the node structure
        node_t.__init__(self)

        # Check if it's a code instruction
        try:
            is_c = is_code(get_flags(ea))
        except:
            is_c = isCode(GetFlags(ea))
        if not is_c:
            raise CodeException

        #
        # fill node_t struct
        #

        # NodeInfo
        self.info = NodeInfo()
        inst_elements = []

        try:
            size = create_insn(ea)
            bytes = get_bytes(ea, size)
        except:
            size = MakeCode(ea)
            bytes = GetManyBytes(ea, size)

        (address, size, mnemonic, op_str) = cs.disasm_lite(bytes, ea, count=1).next()
        self.info.opcode = mnemonic.encode("ascii", "ignore")

        op_str_ascci = op_str.encode("ascii", "ignore")
        self.info.inst_str = self.info.opcode + " " + op_str_ascci

        splitted = op_str_ascci.split(", ")
        self.info.nargs = 0

        if len(splitted) >= 1:
            self.info.arg1 = splitted[0]
            self.info.nargs += 1
            if len(splitted) >= 2:
                self.info.arg2 = splitted[1]
                self.info.nargs += 1
                if len(splitted) >= 3:
                    self.info.arg3 = splitted[2]
                    self.info.nargs += 1

        # No node will be root but this is acceptable for CFGs
        self.info.is_root = False

        self.info.address = ea
        self.info.has_address = True

        # node_t
        self.node_id = self._genid()
コード例 #30
0
    def extract_info_from_IDA(self):
        for xref in idautils.XrefsTo(self.ea):
            frm = xref.frm
            if idc.SegName(frm) == '__objc_classrefs':
                self.classref = frm
            if idc.SegName(frm) == '__objc_superrefs':
                self.superref = frm

        base_ivars = ida_bytes.get_qword(self.info + 0x30)
        if base_ivars and idc.SegName(base_ivars) == '__objc_const':
            entrysize = ida_bytes.get_dword(base_ivars)
            count = ida_bytes.get_dword(base_ivars + 4)
            ea = base_ivars + 8
            for i in range(count):
                offset = ida_bytes.get_dword(idc.get_qword(ea))
                _type = idc.get_bytes(idc.Qword(ea + 0X10), idc.get_item_size(idc.Qword(ea + 0X10)) - 1)
                _name = idc.get_bytes(idc.Qword(ea + 0X08), idc.get_item_size(idc.Qword(ea + 0X08)) - 1)
                # self.ivars[offset] = _type
                self.ivars[_name] = _type
                ea += entrysize

        base_props = ida_bytes.get_qword(self.info + 0x40)
        if base_props and idc.SegName(base_props) == '__objc_const':
            entrysize = ida_bytes.get_dword(base_props)
            count = ida_bytes.get_dword(base_props + 4)
            ea = base_props + 8
            for i in range(count):
                _type = idc.get_bytes(idc.Qword(ea + 0X08), idc.get_item_size(idc.Qword(ea + 0X08)) - 1)
                _name = idc.get_bytes(idc.Qword(ea), idc.get_item_size(idc.Qword(ea)) - 1)
                self.props[_name] = _type
                ea += entrysize

        base_prots = ida_bytes.get_qword(self.info + 0x28)
        if base_prots and idc.SegName(base_prots) == '__objc_const':
            count = ida_bytes.get_qword(base_prots)
            entrysize = 0x8
            p_ea = base_prots + 8
            for i in range(count):
                proto_ea = idc.get_qword(p_ea)
                self.prots.append(proto_ea)
                Protocol.add_implementing_class(proto_ea, self.ea)
                p_ea += entrysize
コード例 #31
0
 def getBinary(self):
     result = b""
     segment_starts = [ea for ea in idautils.Segments()]
     offsets = []
     start_len = 0
     for start in segment_starts:
         end = idc.SegEnd(start)
         result += idc.get_bytes(start, end - start)
         offsets.append((start, start_len, len(result)))
         start_len = len(result)
     return result