Пример #1
0
def getFormatString(addr):
    op_num = 1
    # idc.get_operand_type Return value
    #define o_void        0  // No Operand                           ----------
    #define o_reg         1  // General Register (al, ax, es, ds...) reg
    #define o_mem         2  // Direct Memory Reference  (DATA)      addr
    #define o_phrase      3  // Memory Ref [Base Reg + Index Reg]    phrase
    #define o_displ       4  // Memory Reg [Base Reg + Index Reg + Displacement] phrase+addr
    #define o_imm         5  // Immediate Value                      value
    #define o_far         6  // Immediate Far Address  (CODE)        addr
    #define o_near        7  // Immediate Near Address (CODE)        addr
    #define o_idpspec0    8  // IDP specific type
    #define o_idpspec1    9  // IDP specific type
    #define o_idpspec2   10  // IDP specific type
    #define o_idpspec3   11  // IDP specific type
    #define o_idpspec4   12  // IDP specific type
    #define o_idpspec5   13  // IDP specific type
    # 如果第二个不是立即数则下一个
    if (idc.get_operand_type(addr, op_num) != 5):
        op_num = op_num + 1
    if idc.get_operand_type(addr, op_num) != 5:
        return "get fail"
    op_string = print_operand(
        addr,
        op_num).split(" ")[0].split("+")[0].split("-")[0].replace("(", "")
    string_addr = idc.get_name_ea_simple(op_string)
    if string_addr == BADADDR:
        return "get fail"
    string = str(get_strlit_contents(string_addr, -1, STRTYPE_TERMCHR))
    return [string_addr, string]
Пример #2
0
    def find_ehfuncinfo_addr(self):
        for eh_addr in self.frmhdlr_xref:
            addr_ = eh_addr
            for i in range(0, self.MAX_SEARCH):
                addr_ = idc.prev_head(addr_)
                mnem = idc.print_insn_mnem(addr_)

                ### locate the ehfuncInfo address
                if mnem == 'mov' and idc.get_operand_type(
                        addr_, 0) == o_reg and idc.get_operand_type(
                            addr_, 1) == o_imm:
                    op1 = idc.print_operand(addr_, 0)
                    op2 = idc.print_operand(addr_, 1)

                    ## eh function info address
                    eh_func_info_addr = get_operand_value(addr_, 1)

                    #print(hex(addr_), mnem, op1, op2,hex(eh_func_info_addr))

                    ### locate the ptryBlockMapAddr
                    for ad in idautils.XrefsTo(addr_, flags=0):
                        seh_init_addr = ad.frm
                    print(
                        "[+] seh_frame_addr: {} ehFuncInfo_struct_addr: {}\n------------------------------------------------------------------"
                        .format(hex(addr_), hex(eh_func_info_addr)))

                    ### locate the xref of the _cxxframehandler ehfuncinfo
                    self.parse_func_info_entry(seh_init_addr, addr_,
                                               eh_func_info_addr)
        return
Пример #3
0
    def find_value(self, func_addr, instr_addr, register):
        """
        Attempts to resolve the value of the given register at the given address.
        If the value cannot be resolved, None is returned.
        """
        reg_num = idaapi.ph_get_regnames().index(register)

        # go back from the current instruction to the start of the function
        for instr_addr in list(instructions(func_addr, instr_addr))[::-1]:
            # look for instrucations that move a value into the desired register
            mnemonic = idc.GetMnem(instr_addr)
            if mnemonic == 'mov':

                op1_type = idc.get_operand_type(instr_addr, 0)
                op1_value = idc.get_operand_value(instr_addr, 0)

                if op1_type == idc.o_reg and op1_value == reg_num:
                    op2_type = idc.get_operand_type(instr_addr, 1)
                    op2_value = idc.get_operand_value(instr_addr, 1)

                    # if this instruction sets the register to an immediate value
                    if op2_type == idc.o_imm:
                        # return that value
                        return op2_value
                    else:
                        # it is not an immediate value, so we say we cannot
                        # resolve the value
                        return None

        # we did not find an allocation of the register,
        # so we return None to indicate that
        return None
Пример #4
0
    def get_branch_type(self):
        if self.bbl == None:
            return -1

        addr = self.addr
        while addr != self.bbl.end_ea:
            mnem = idc.print_insn_mnem(addr).lower()
            if mnem.startswith("call"):
                if op_type[idc.get_operand_type(addr,0)] != "o_near" and\
                    op_type[idc.get_operand_type(addr,0)] != "o_far":
                    return ICALL
                else:
                    return CALL
            addr = idc.next_head(addr)

        addr = idc.prev_head(self.bbl.end_ea)
        mnem = idc.print_insn_mnem(addr).lower()
        if mnem in u_jumps or mnem in c_jumps:
            if op_type[idc.get_operand_type(addr,0)] != "o_near" and\
                op_type[idc.get_operand_type(addr,0)] != "o_far":
                return IJMP
            else:
                if mnem in u_jumps:
                    return JMP
                else:
                    return CJMP
        elif self.bbl.type >= 2 and self.bbl.type <= 5:
            return RET

        return NA
Пример #5
0
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)
Пример #6
0
        def do_unpatch_call(va_callsite):
            size = idc.get_item_size(va_callsite)
            ida_xref.del_cref(va_callsite, fva_stub, 0)
            cmt = idc.get_cmt(va_callsite, 0)

            newcmt = cmt

            # Remove automated comments
            if newcmt.startswith(g_patched_call_cmt):
                newcmt = newcmt[newcmt.find('\n') + 1:]
                if newcmt.find('\n') == -1:
                    newcmt = ''
                else:
                    newcmt = newcmt[newcmt.find('\n') + 1:]
                if newcmt.startswith(g_cmt_pointed):
                    if newcmt.find('\n') == -1:
                        newcmt = ''
                    else:
                        newcmt = newcmt[newcmt.find('\n') + 1:]

            if newcmt != cmt:
                idc.set_cmt(va_callsite, newcmt, 0)

            if idc.get_operand_type(va_callsite, 0) == ida_ua.o_mem:
                patch_import(va_callsite, idc.BADADDR)
            elif idc.get_operand_type(va_callsite, 0) == ida_ua.o_reg:
                va_imp = self._get_imp_for_register_call(va_callsite)
                if va_imp:
                    patch_pointer_width(va_imp, idc.BADADDR)
            else:
                revert_patch(va_callsite, size)
Пример #7
0
 def set_types(self):
     '''
     handle (EFI_BOOT_SERVICES *) type
     and (EFI_SYSTEM_TABLE *) for x64 images
     '''
     RAX = 0
     O_REG = 1
     O_MEM = 2
     EFI_BOOT_SERVICES = 'EFI_BOOT_SERVICES *'
     EFI_SYSTEM_TABLE = 'EFI_SYSTEM_TABLE *'
     empty = True
     for service in self.gBServices:
         for address in self.gBServices[service]:
             ea = address
             num_of_attempts = 10
             for _ in range(num_of_attempts):
                 ea = idc.prev_head(ea)
                 if (idc.print_insn_mnem(ea) == 'mov'
                         and idc.get_operand_type(ea, 1) == O_MEM):
                     if (idc.get_operand_type(ea, 0) == O_REG
                             and idc.get_operand_value(ea, 0) == RAX):
                         gvar = idc.get_operand_value(ea, 1)
                         gvar_type = idc.get_type(gvar)
                         '''
                         if (EFI_SYSTEM_TABLE *)
                         '''
                         if ((gvar_type != 'EFI_SYSTEM_TABLE *') and \
                             (idc.print_operand(address, 0).find('rax') == 1)
                         ):
                             if self._find_est(gvar, ea, address):
                                 print(
                                     '[ {0} ] Type ({type}) successfully applied'
                                     .format(
                                         '{addr:#010x}'.format(addr=gvar),
                                         type=EFI_SYSTEM_TABLE))
                                 empty = False
                                 break
                         '''
                         otherwise it (EFI_BOOT_SERVICES *)
                         '''
                         if (gvar_type != 'EFI_BOOT_SERVICES *'
                                 and gvar_type != 'EFI_SYSTEM_TABLE *'):
                             if idc.SetType(gvar, EFI_BOOT_SERVICES):
                                 empty = False
                                 idc.set_name(
                                     gvar,
                                     'gBs_{addr:#x}'.format(addr=gvar))
                                 print(
                                     '[ {0} ] Type ({type}) successfully applied'
                                     .format(
                                         '{addr:#010x}'.format(addr=gvar),
                                         type=EFI_BOOT_SERVICES))
                         break
     if empty:
         print(' * list is empty')
def calNconstants(bl):
	start = bl[0]
	end = bl[1]
	invoke_num = 0
	inst_addr = start
	while inst_addr < end:
		optype1 = idc.get_operand_type(inst_addr, 0)
		optype2 = idc.get_operand_type(inst_addr, 1)
		if optype1 == 5 or optype2 == 5:
			invoke_num += 1
		inst_addr = idc.next_head(inst_addr)
	return invoke_num
Пример #9
0
 def set_types(self):
     """
     handle (EFI_BOOT_SERVICES *) type
     """
     RAX = 0
     O_REG = 1
     O_MEM = 2
     EFI_BOOT_SERVICES = "EFI_BOOT_SERVICES *"
     empty = True
     for service in self.gBServices:
         for address in self.gBServices[service]:
             ea = address
             num_of_attempts = 10
             for _ in range(num_of_attempts):
                 ea = idc.prev_head(ea)
                 if (idc.GetMnem(ea) == "mov"
                         and idc.get_operand_type(ea, 1) == O_MEM):
                     if (idc.get_operand_type(ea, 0) == O_REG
                             and idc.get_operand_value(ea, 0) == RAX):
                         gBs_var = idc.get_operand_value(ea, 1)
                         gBs_var_type = idc.get_type(gBs_var)
                         if (gBs_var_type == "EFI_BOOT_SERVICES *"):
                             empty = False
                             print("[{0}] EFI_BOOT_SERVICES->{1}".format(
                                 "{addr:#010x}".format(addr=address),
                                 service))
                             print("\t [address] {0}".format(
                                 "{addr:#010x}".format(addr=gBs_var)))
                             print("\t [message] type already applied")
                             break
                         if idc.SetType(gBs_var, EFI_BOOT_SERVICES):
                             empty = False
                             idc.MakeName(
                                 gBs_var,
                                 "gBs_{addr:#x}".format(addr=gBs_var))
                             print("[{0}] EFI_BOOT_SERVICES->{1}".format(
                                 "{addr:#010x}".format(addr=address),
                                 service))
                             print("\t [address] {0}".format(
                                 "{addr:#010x}".format(addr=gBs_var)))
                             print("\t [message] type successfully applied")
                         else:
                             empty = False
                             print("[{0}] EFI_BOOT_SERVICES->{1}".format(
                                 "{addr:#010x}".format(addr=address),
                                 service))
                             print("\t [address] {0}".format(
                                 "{addr:#010x}".format(addr=gBs_var)))
                             print("\t [message] type not applied")
                         break
     if empty:
         print(" * list is empty")
Пример #10
0
    def findRspRbpDifference(curr_ea):
        difference = 0
        for i in range(0, 256):
            mnem = idc.print_insn_mnem(curr_ea)
            debug(mnem)
            idaapi.decode_insn(insn, curr_ea)
            if mnem == 'push':
                push_offset = 8
                difference += push_offset
            elif mnem == 'sub':
                if idc.get_operand_value(
                        curr_ea, 0
                ) == OperandValueRegister.RSP and idc.get_operand_type(
                        curr_ea, 1) == OperandType.IMMEDIATE_VALUE:
                    rsp_substraction = idc.get_operand_value(curr_ea, 1)
                    difference += rsp_substraction
            elif mnem == 'mov' or mnem == 'lea':
                #debug('type: ', idc.get_operand_type(curr_ea, 0), ' val: ', idc.get_operand_value(curr_ea, 0))
                debug(idc.generate_disasm_line(curr_ea, 0))
                if idc.get_operand_value(curr_ea,
                                         0) == OperandValueRegister.RBP:
                    debug(
                        mnem, ' type: ', idc.get_operand_type(curr_ea,
                                                              1), ' val: ',
                        'bp: 0x{:X}'.format(idc.get_operand_value(curr_ea, 1)))

                    #case 1: mov
                    if mnem == 'mov':
                        if idc.get_operand_type(
                                curr_ea, 1
                        ) == OperandType.GENERAL_REG and idc.get_operand_value(
                                curr_ea, 1) == OperandValueRegister.RSP:
                            displacement = 0

                    #case 2: lea
                    if mnem == 'lea':
                        if idc.get_operand_type(curr_ea,
                                                1) == OperandType.MEMORY_REG:
                            if idc.get_operand_value(curr_ea,
                                                     1) > 0xF000000000000000:
                                displacement = 0x10000000000000000 - idc.get_operand_value(
                                    curr_ea, 1)
                                difference += displacement
                            else:
                                displacement = idc.get_operand_value(
                                    curr_ea, 1)
                                difference -= displacement
                    break

            curr_ea += insn.size
        return difference
Пример #11
0
    def find_iat_ptrs(self, pe, image_base, size, get_word):
        """Find all likely IAT pointers"""
        iat_ptrs = []

        next_offset = image_base

        while next_offset < image_base + size:
            offset = next_offset
            next_offset = ida_bytes.next_addr(offset)

            # Attempt to read the current instruction's effective memory address operand (if present)
            mnem = idc.print_insn_mnem(offset).lower()
            ptr = 0

            if mnem in ["call", "push", "jmp"]:
                if idc.get_operand_type(offset, 0) == idc.o_mem:
                    # Get memory offset for branch instructions
                    ptr = idc.get_operand_value(offset, 0)
            elif mnem in ["mov", "lea"]:
                if idc.get_operand_type(
                        offset, 0) == idc.o_reg and idc.get_operand_type(
                            offset, 1) == idc.o_mem:
                    # Get memory offset for mov/lea instructions
                    ptr = idc.get_operand_value(offset, 1)

            # Does the instruction's memory address operand seem somewhat valid?!
            if ptr < 0x1000:
                continue

            # Resolve pointer from memory operand
            iat_offset = get_word(ptr)

            # Ignore offset if it is in our image
            if image_base <= iat_offset <= image_base + size:
                continue

            # Get module and API name for offset
            module, api = self.resolve_address(iat_offset)

            # Ignore the offset if it is in a debug segment or stack etc
            if api and module and module.endswith(".dll"):
                if not iat_offset in iat_ptrs:
                    # Add IAT offset, address to patch, module name and API name to list
                    iat_ptrs.append(
                        (iat_offset, offset + idc.get_item_size(offset) - 4,
                         module, api))

        self.ret = iat_ptrs
        return self.ret
Пример #12
0
 def set_types(self):
     """
     handle (EFI_BOOT_SERVICES *) type
     and (EFI_SYSTEM_TABLE *) for x64 images
     """
     REG_RAX = 0
     EFI_BOOT_SERVICES = "EFI_BOOT_SERVICES *"
     EFI_SYSTEM_TABLE = "EFI_SYSTEM_TABLE *"
     empty = True
     for service in self.gBServices:
         for address in self.gBServices[service]:
             ea = address
             num_of_attempts = 10
             for _ in range(num_of_attempts):
                 ea = idc.prev_head(ea)
                 if (
                     idc.print_insn_mnem(ea) == "mov"
                     and idc.get_operand_type(ea, 1) == idc.o_mem
                 ):
                     if (
                         idc.get_operand_type(ea, 0) == idc.o_reg
                         and idc.get_operand_value(ea, 0) == REG_RAX
                     ):
                         gvar = idc.get_operand_value(ea, 1)
                         gvar_type = idc.get_type(gvar)
                         # if (EFI_SYSTEM_TABLE *)
                         if (gvar_type != "EFI_SYSTEM_TABLE *") and (
                             idc.print_operand(address, 0).find("rax") == 1
                         ):
                             if self._find_est(gvar, ea, address):
                                 print(
                                     f"[ {gvar:016X} ] Type ({EFI_SYSTEM_TABLE}) successfully applied"
                                 )
                                 empty = False
                                 break
                         # otherwise it (EFI_BOOT_SERVICES *)
                         if (
                             gvar_type != "EFI_BOOT_SERVICES *"
                             and gvar_type != "EFI_SYSTEM_TABLE *"
                         ):
                             if idc.SetType(gvar, EFI_BOOT_SERVICES):
                                 empty = False
                                 idc.set_name(gvar, f"gBS_{gvar:X}")
                                 print(
                                     f"[ {gvar:016X} ] Type ({EFI_BOOT_SERVICES}) successfully applied"
                                 )
                         break
     if empty:
         print(" * list is empty")
Пример #13
0
def format_args(call_addr, fmt_num, index):
    func = idaapi.get_func(call_addr)
    start = func.start_ea
    string = ""
    # 这里i是指对应在整个调用中的参数的位置,
    # !! 从1开始因为测试的时候考虑printf第一个格式化字符串,后面的就是后推一个,
    # !! 应该snprintf参数解析错误的bug就是这里, 应该..1改成format_function_offset_dict[func_name]就好了
    for i in range(index + 1, fmt_num + index + 1):
        # 只查寄存器传递的,push传递的还没考虑,
        if (i >= 6):
            break
        # 从调用位置向上遍历查找对应的传参寄存器
        line = call_addr
        reg = arg_reg[i]
        while line >= start:
            line = prev_head(line)
            line_arg = idc.print_operand(line, 0)
            # !! 只比较寄存器存在bug (add rdi, 0x10), 可能被认为是0x10是参数,
            if reg == line_arg:
                idc.set_color(line, CIC_ITEM, 0x00fff0)
                # 如果是寄存器传寄存器(mov rdi, rax;), 调用函数尝试回溯rax,
                if (idc.get_operand_type(line, 1) !=
                        1) and (idc.print_insn_mnem(line) in ['mov', 'lea']):
                    string += ", '%s'" % (idc.print_operand(line, 1))
                else:
                    string += ", '%s'" % (hand_register(
                        line, start, idc.print_operand(line, 1)))
                break
    return string
Пример #14
0
def get_opnd_replacement(ea, pos):
    """ A replacement for IDA's idc.print_operand that can de-alias register names"""
    # TODO: Support renames in other operand types
    if idc.get_operand_type(ea, pos) == idc.o_reg:
        return idaapi.get_reg_name(idc.get_operand_value(ea, pos), get_byte_size_of_operand(ea, pos))
    else:
        return idc.print_operand(ea, pos)
Пример #15
0
def find_ref_loc(config, ea, ref):
    """
    type config: Config
    type ea: idc.ea_t
    type ref: idc.ea_t
    """
    logger = logging.getLogger("idb2pat:find_ref_loc")
    if ea == BADADDR:
        logger.debug("Bad parameter: ea")
        return BADADDR
    if ref == BADADDR:
        logger.debug("Bad parameter: ref")
        return BADADDR

    if idc.get_operand_type(ea, 0) == o_near:
        ref = (ref - ida_bytes.get_item_end(ea)) & (
            (1 << config.pointer_size * 8) - 1)

    if ida_bytes.is_code(ida_bytes.get_full_flags(ea)):
        for i in zrange(
                ea,
                max(ea, 1 + ida_bytes.get_item_end(ea) - config.pointer_size)):
            if ida_bytes.get_dword(i) == ref:
                return i

    return BADADDR
def getConst(ea, offset):
	strings = []
	consts = []
	optype1 = idc.get_operand_type(ea, offset)
	if optype1 == idaapi.o_imm:
		imm_value = idc.get_operand_value(ea, offset)
		if 0<= imm_value <= 10:
			consts.append(imm_value)
		else:
			if idaapi.isLoaded(imm_value) and ida_segment.getseg(imm_value):
				str_value = idc.get_strlit_contents(imm_value)
				if str_value is None:
					str_value = idc.get_strlit_contents(imm_value+0x40000)
					if str_value is None:
						consts.append(imm_value)
					else:
						re = all(40 <= ord(c) < 128 for c in str_value)
						if re:
							strings.append(str_value)
						else:
							consts.append(imm_value)
				else:
					re = all(40 <= ord(c) < 128 for c in str_value)
					if re:
						strings.append(str_value)
					else:
						consts.append(imm_value)
			else:
				consts.append(imm_value)
	return strings, consts
Пример #17
0
def find_event_names():
    event_names = []
    #get address value of named address
    offset_name = 'CreateEventA'
    named_addr = ida_name.get_name_ea(BADADDR, offset_name)

    #get all unique xrefs to found named address
    xref_lst = []
    for xref in idautils.XrefsTo(named_addr):
        if xref.frm not in xref_lst:
            xref_lst.append(xref.frm)

    #get addresses where arguments of called function are pushed
    for xref in xref_lst:
        args = idaapi.get_arg_addrs(xref)

        if idc.get_operand_type(args[3], 0) == idaapi.o_imm:
            #		select last argument and read string to which it points
            op_val = idc.get_operand_value(args[3], 0)
            event_name = get_strlit_contents(op_val)
            if event_name != None:
                event_name = event_name.decode('ascii')
                event_names.append(event_name)

    return event_names
Пример #18
0
def find_all_ioctls():
    """
    From the currently selected address attempts to traverse all blocks inside the current function to find all immediate values which
    are used for a comparison/sub immediately before a jz. Returns a list of address, second operand pairs.
    """

    ioctls = []
    # Find the currently selected function and get a list of all of it's basic blocks
    addr = idc.get_screen_ea()
    f = idaapi.get_func(addr)
    fc = idaapi.FlowChart(f, flags=idaapi.FC_PREDS)
    for block in fc:
        # grab the last two instructions in the block
        last_inst = idc.prev_head(block.end_ea)
        penultimate_inst = idc.prev_head(last_inst)
        # If the penultimate instruction is cmp or sub against an immediate value immediately preceding a 'jz'
        # then it's a decent guess that it's an IOCTL code (if this is a dispatch function)
        if idc.print_insn_mnem(penultimate_inst) in [
                'cmp', 'sub'
        ] and idc.get_operand_type(penultimate_inst, 1) == 5:
            if idc.print_insn_mnem(last_inst) == 'jz':
                value = get_operand_value(penultimate_inst)
                ioctls.append((penultimate_inst, value))
                ioctl_tracker.add_ioctl(penultimate_inst, value)
    return ioctls
Пример #19
0
    def m64_mmpagingfile(self):
        """
       The MmPagingFile pointer can be defined as PVOID *MMPAGING_FILE[16]. Support for locating this
        pointer is not mandatory, but essential to verify if an MMPAGING_FILE structure corresponds
        to a virtual store. Although this pointer was previously exported as nt!MmPagingFile in Windows
        7, the pointer has not been exported by any Windows 10 kernel to date. This function traverses
        MmStorecheckPagefiles. The same signature as x86 could not be used due to compiler optimzations
        using the LEA instruction to get the address of the global variable. Disassembly snippet from
        Windows 10 1809 x64 shown below.

        MmStoreCheckPagefiles      MmStoreCheckPagefiles proc near         ;
        MmStoreCheckPagefiles                      mov     r9d, cs:Count
        MmStoreCheckPagefiles+7                    xor     r8d, r8d
        MmStoreCheckPagefiles+A                    test    r9d, r9d
        MmStoreCheckPagefiles+D                    jz      short loc_14072F307
        MmStoreCheckPagefiles+F                    lea     eax, [r8+1]
        MmStoreCheckPagefiles+13                   lea     r10, unk_14043E5E0
        """
        (addr, name) = self.find_ida_name("MmStoreCheckPagefiles")

        for insn_addr, insn, op0, op1 in self.iter_fn(addr):
            if insn == "lea":
                if idc.get_operand_type(insn_addr, 1) == idc.o_mem:
                    return idc.get_operand_value(insn_addr,
                                                 1) - idaapi.get_imagebase()

        self.logger.error("MmPagingFile could not be resolved.")
        return None
Пример #20
0
 def handle_mov(self, state):
     """Updates the state of the stack string finding based on a mov instruction"""
     op1 = tracing.get_opnd_replacement(state.ea, POS_FIRST)
     if "[" in op1:
         offset = tracing.get_operand_value_replacement(state.ea, POS_FIRST, state)
         self.set_stack(offset, state.ea, POS_SECOND, state)
     else:
         reg = tracing.get_reg_fam(op1)
         type_ = idc.get_operand_type(state.ea, POS_SECOND)
         if reg:
             if type_ != idc.o_phrase and type_ != idc.o_displ:
                 if type_ == idc.o_reg:
                     reg2 = tracing.get_reg_fam(tracing.get_opnd_replacement(state.ea, POS_SECOND))
                     if reg2 and reg2[0] in state.regs:
                         val = state.regs[reg2[0]][0]
                     else:
                         val = None
                 else:
                     val = idc.get_operand_value(state.ea, POS_SECOND)
                 if val is not None:
                     state.regs[reg[0]] = (val, state.ea)
             else:
                 offset = tracing.get_operand_value_replacement(state.ea, POS_SECOND, state)
                 value = state.stack.get(offset, None)
                 if value is not None:
                     state.regs[reg[0]] = value
                 else:
                     self.clear_reg_if_needed(reg, state.regs)
Пример #21
0
def parse_function_type(ea: int, end: Optional[int] = None) -> str:
    frame = idc.get_func_attr(ea, FUNCATTR_FRAME)
    if frame is None:
        return ""
    if end is None:  # try to find end
        func = function_at(ea)
        if not func:
            return "?"
        end = prev_addr(get_func_attr(func, FUNCATTR_END))
    end_addr = end
    mnem = GetDisasm(end_addr)

    if "ret" not in mnem:
        # it's not a real end, get instruction before...
        end_addr = prev_addr(end)
        if end_addr == BADADDR:
            # cannot get the real end
            return ""
        mnem = GetDisasm(end_addr)

    if "ret" not in mnem:
        # cannot get the real end
        return ""

    op = get_operand_type(end_addr, 0)
    if op == o_void:
        # retn has NO parameters
        return "__cdecl"
    # retn has parameters
    return "__stdcall"
Пример #22
0
def get_first_function(ea):
    """ see above, but returns the first pushed value """
    maybe_start = idc.get_func_attr(ea, idc.FUNCATTR_START)
    limit = 0
    if maybe_start == idc.BADADDR:
        limit = 10

    cur_ea = ea
    limit_count = 0
    while cur_ea != idc.BADADDR:
        # are we over limit or up to the func start?
        limit_count += 1
        limit_exceeded = (limit > 0 and limit_count > limit)
        too_far = (maybe_start != idc.BADADDR and cur_ea < maybe_start)
        if limit_exceeded or too_far:
            LOG.error(
                "Failed to find string walking backwards from {:08X}".format(
                    ea))
            return None

        prev_ins = idautils.DecodePreviousInstruction(cur_ea)
        prev_ea = prev_ins.ea

        # did we find it?
        if idc.GetMnem(prev_ea) == 'push':
            if idc.get_operand_type(prev_ea, 0) in [idc.o_mem, idc.o_imm]:
                # push offset found!
                pushed_addr = idc.GetOperandValue(prev_ea, 0)
                # it's not data, then probably good
                if idc.isCode(idc.GetFlags(pushed_addr)):
                    return pushed_addr

        cur_ea = prev_ea
Пример #23
0
    def get_opcode_omem(self, offset):
        """Get opcode's direct memory address"""
        mnem = self.get_mnemonic(offset).lower()
        ptr = 0

        if mnem in ["call", "push", "jmp"]:
            if idc.get_operand_type(offset, 0) == idc.o_mem:
                ptr = idc.get_operand_value(offset, 0)
        elif mnem in ["mov", "lea"]:
            if idc.get_operand_type(offset,
                                    0) == idc.o_reg and idc.get_operand_type(
                                        offset, 1) == idc.o_mem:
                ptr = idc.get_operand_value(offset, 1)

        self.ret = ptr
        return self.ret
 def lookForOpArgs(self, start, end):
     for head in idautils.Heads(start, end):
         try:
             for i in range(2):
                 if using_ida7api:
                     t = idc.get_operand_type(head, i)
                 else:
                     t = idc.GetOpType(head, i)
                 if t == idc.o_imm:
                     if using_ida7api:
                         opval = idc.get_operand_value(head, i)
                         insn = idautils.DecodeInstruction(head)
                         opmask = OPERAND_MASK.get(insn.ops[i].dtype)
                         if opmask:
                             opval = opval & opmask
                     else:
                         opval = idc.GetOperandValue(head, i)
                     if self.params.useXORSeed:
                         opval = opval ^ self.params.XORSeed
                     for h in self.params.hashTypes:
                         hits = self.dbstore.getSymbolByTypeHash(
                             h.hashType, opval)
                         for sym in hits:
                             logger.info("0x%08x: %s", head, str(sym))
                             self.addHit(head, sym)
                             self.markupLine(head, sym,
                                             self.params.useDecompiler)
         except Exception as err:
             logger.exception("Exception: %s", str(err))
Пример #25
0
	def set_jit_info(self, method_id, start):

		end = self.get_func_end(start)

		if (end < start or end - start > self.jit_max_size):
			return

		method = next((x for x in self.as3dump if x["id"] == method_id), None)

		if (method is None):
			return

		stackvars = self.get_stack_vars(start, end)
		save_eip = self.get_save_eip(method, stackvars)

		ea = start
		while (ea < end):
	
			if ("ebp" in idc.print_operand(ea, 0) and idc.get_operand_type(ea, 1) == idc.o_imm):
	
				op0 = idc.get_operand_value(ea, 0)
				op1 = idc.get_operand_value(ea, 1)
	
				if (op0 == save_eip):
					idc.set_cmt(ea, method["instructions"][op1], 0)
		
			ea += idc.get_item_size(ea)
Пример #26
0
def handle_test(ea, state):
    """
        If a test of a register against itself occurs and the next instruction is a jnz,
        then the register can be set to zero (code is followed linearly, jumps are ignored),
        unless the next instruction is a jmp.

        :param ea: instruction location
        :param state: the current TraceState
    """
    if idc.get_operand_type(ea, POS_FIRST) == idc.o_reg and idc.get_operand_type(ea, POS_SECOND) == idc.o_reg:
        op1 = get_opnd_replacement(ea, POS_FIRST)
        op2 = get_opnd_replacement(ea, POS_SECOND)
        next_ea = ea + idc.get_item_size(ea)
        if op1 == op2 and idc.print_insn_mnem(next_ea) == 'jnz':
            next_ea += idc.get_item_size(next_ea)
            if not idc.print_insn_mnem(next_ea).startswith('j'):
                state.set_reg_value(op1, 0, ea)
Пример #27
0
 def set_types(self):
     """
     handle (EFI_BOOT_SERVICES *) type
     and (EFI_SYSTEM_TABLE *) for x64 images
     """
     RAX = 0
     O_REG = 1
     O_MEM = 2
     EFI_BOOT_SERVICES = 'EFI_BOOT_SERVICES *'
     EFI_SYSTEM_TABLE = 'EFI_SYSTEM_TABLE *'
     empty = True
     for service in self.gBServices:
         for address in self.gBServices[service]:
             ea = address
             num_of_attempts = 10
             for _ in range(num_of_attempts):
                 ea = idc.prev_head(ea)
                 if (idc.print_insn_mnem(ea) == 'mov'
                         and idc.get_operand_type(ea, 1) == O_MEM):
                     if (idc.get_operand_type(ea, 0) == O_REG
                             and idc.get_operand_value(ea, 0) == RAX):
                         gvar = idc.get_operand_value(ea, 1)
                         gvar_type = idc.get_type(gvar)
                         # if (EFI_SYSTEM_TABLE *)
                         if ((gvar_type != 'EFI_SYSTEM_TABLE *')
                                 and (idc.print_operand(
                                     address, 0).find('rax') == 1)):
                             if self._find_est(gvar, ea, address):
                                 print(
                                     f'[ {gvar:016X} ] Type ({EFI_SYSTEM_TABLE}) successfully applied'
                                 )
                                 empty = False
                                 break
                         # otherwise it (EFI_BOOT_SERVICES *)
                         if (gvar_type != 'EFI_BOOT_SERVICES *'
                                 and gvar_type != 'EFI_SYSTEM_TABLE *'):
                             if idc.SetType(gvar, EFI_BOOT_SERVICES):
                                 empty = False
                                 idc.set_name(gvar, f'gBS_{gvar:X}')
                                 print(
                                     f'[ {gvar:016X} ] Type ({EFI_BOOT_SERVICES}) successfully applied'
                                 )
                         break
     if empty:
         print(' * list is empty')
Пример #28
0
def can_be_ignored(instr_addr):
    """
    Checks whether or not an instruction can be ignored.
    An instruction can be ignored if it does not actually an arithmetic or bitwise computation,
    although it has a mnemonic that falls into that category.
    Example: xor eax, eax
    """
    # ignore instructions that are "abused" for non-arithmetic purposes
    if idc.GetMnem(instr_addr) in ['xor', 'sub']:
        same_op_type = idc.get_operand_type(instr_addr,
                                            0) == idc.get_operand_type(
                                                instr_addr, 1)
        same_op_value = idc.get_operand_value(instr_addr,
                                              0) == idc.get_operand_value(
                                                  instr_addr, 1)
        if same_op_type and same_op_value:
            return True

        return False
Пример #29
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
Пример #30
0
    def type(self):
        """
            Property allowing to get the type of the operand. This type
            correspond to the :class:`BipOpType` value .
            Wrapper on ``idc.GetOpType`` (old) or ``idc.get_operand_type``
            (new).

            :return: The type of the operand as defined in :class:`BipOpType` .
            :rtype: int
        """
        return idc.get_operand_type(self.ea, self.opnum)
Пример #31
0
	def get_stack_vars(self, start, end):

		stackvars = {}
	
		ea = start
		while (ea < end):
	
			if ("ebp" in idc.print_operand(ea, 0) and idc.get_operand_type(ea, 1) == idc.o_imm):
	
				op0 = idc.get_operand_value(ea, 0)
				op1 = idc.get_operand_value(ea, 1)
	
				if (op0 in stackvars):
					stackvars[op0]["values"].append(op1)
				else:
					stackvars[op0] = {"values": [], "hits": 0}
	
			ea += idc.get_item_size(ea)

		return stackvars
Пример #32
0
 def lookForOpArgs(self, start, end):
     for head in idautils.Heads(start, end):
         try:
             for i in range(2):
                 if using_ida7api:
                     t = idc.get_operand_type(head, i)
                 else:
                     t = idc.GetOpType(head, i)
                 if t == idc.o_imm:
                     if using_ida7api:
                         opval = idc.get_operand_value(head, i)
                     else:
                         opval = idc.GetOperandValue(head, i)
                     for h in self.params.hashTypes:
                         hits = self.dbstore.getSymbolByTypeHash(h.hashType, opval)
                         for sym in hits:
                             logger.info("0x%08x: %s", head, str(sym))
                             self.addHit(head, sym)
                             self.markupLine(head, sym)
         except Exception, err:
            logger.exception("Exception: %s", str(err))
Пример #33
0
    def run(self):
        logger.debug('Starting up')
        try:
            here = idc.here()
            logger.info('Using ea: 0x%08x', here)
            if using_ida7api:
                mnem = idc.print_insn_mnem(here)
            else:
                mnem =  idc.GetMnem(here)
            if not mnem.startswith('call'):
                logger.info('Not running at a call instruction. Bailing out now')
                return

            if using_ida7api:
                optype = idc.get_operand_type(here, 0) 
            else:
                optype = idc.GetOpType(here, 0) 
            if optype == idc.o_near:
                logger.info("Cannot (or shouldn't) run when call optype is o_near")
                return

            dlg = ApplyCalleeTypeWidget()
            oldTo = idaapi.set_script_timeout(0)
            res = dlg.exec_()
            idaapi.set_script_timeout(oldTo)

            if res == QtWidgets.QDialog.Accepted:
                logger.debug('Dialog accepted. Input type: %d', dlg.inputType)
            else:
                logger.debug('Dialog rejected')
                return

            tinfo = None
            #check user input type
            if dlg.inputType == dlg.USER_TYPE:
                decl = self.convertUserType(str(dlg.getUserText()))
                tinfo = self.getUserDeclType(decl)
            elif dlg.inputType == dlg.STANDARD_TYPE:
                tinfo = self.getBuiltinGlobalType()
            elif dlg.inputType == dlg.LOCAL_TYPE:
                tinfo = self.getLocalType()
            else:
                logger.info('Bad user input type')
                return
            if tinfo is None:
                logger.debug('Bailing due to null tinfo')
                return
            #logger.info('Deserialize result: %r', ret)
            #not 100% sure if i need to explicitly convert from func to funcptr - seemed
            # to pretty much work without this, but doing it just to be sure
            if not tinfo.is_funcptr():
                logger.debug('Converting to func pointer')
                tinfo.create_ptr(tinfo)
            typename = idaapi.print_tinfo('', 0, 0, idaapi.PRTYPE_1LINE, tinfo, '', '')
            logger.info('Applying tinfo: "%s"', str(typename))
            #both applying callee type & setting op type -> not sure if both are needed?
            # set op type causes change in hexrays decompilation
            # apply callee type updates ida's stack analysis
            ret = idaapi.apply_callee_tinfo(here, tinfo)
            if using_ida7api:
                ret = idaapi.set_op_tinfo(here, 0, tinfo)
            else:
                ret = idaapi.set_op_tinfo2(here, 0, tinfo)
            logger.debug('set_op_tinfo2 result: %r', ret)

        except Exception, err:
            logger.exception("Exception caught: %s", str(err))