Ejemplo n.º 1
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
Ejemplo n.º 2
0
 def get_protocols(self):
     """found UEFI protocols information in idb"""
     for service_name in self.gBServices:
         for address in self.gBServices[service_name]:
             ea, found = address, False
             if self.arch == 'x86':
                 for _ in range(1, 25):
                     ea = idc.prev_head(ea)
                     if (idc.get_operand_value(ea, 0) > self.base
                             and idc.print_insn_mnem(ea) == 'push'):
                         found = True
                         break
             if self.arch == 'x64':
                 for _ in range(1, 16):
                     ea = idc.prev_head(ea)
                     if (idc.get_operand_value(ea, 1) > self.base
                             and idc.print_insn_mnem(ea) == 'lea'):
                         found = True
                         break
             if not found:
                 continue
             for xref in idautils.DataRefsFrom(ea):
                 if idc.print_insn_mnem(xref):
                     continue
                 if not check_guid(xref):
                     continue
                 cur_guid = get_guid(xref)
                 record = {
                     'address': xref,
                     'service': service_name,
                     'guid': cur_guid,
                 }
                 if not self.Protocols['all'].count(record):
                     self.Protocols['all'].append(record)
Ejemplo n.º 3
0
def decrypt_all_strings(decrypt_string_func_ea):
    global STRING_DICTIONARY
    for ref in idautils.CodeRefsTo(decrypt_string_func_ea, 1):
        # this function can be better. I hate it rn but oh well

        prev_instruction_ea = 0x472DAC if ref == translate_ea(
            0x1db3) else idc.prev_head(ref)

        if idc.print_insn_mnem(
                prev_instruction_ea) == 'push' or idc.print_insn_mnem(
                    prev_instruction_ea) == 'lea':
            encrypted_blob_ea = idc.get_operand_value(
                prev_instruction_ea,
                1) if ref == translate_ea(0x1db3) else idc.get_operand_value(
                    prev_instruction_ea, 0)
            length = int.from_bytes(idaapi.get_bytes(encrypted_blob_ea - 4, 4),
                                    'little')
            #print(hex(prev_instruction_ea) + " and " + hex(encrypted_blob_ea) + " and " + hex(length))
            encrypted_blob = [
                x for x in idaapi.get_bytes(encrypted_blob_ea, length)
            ]
            encrypted_blob = decrypt_config(encrypted_blob, length)
            string = ''
            for each in encrypted_blob:
                if each != 0:
                    string += chr(each)
            STRING_DICTIONARY[translate_ea_to_offset(
                encrypted_blob_ea)] = string
    return
Ejemplo n.º 4
0
def get_FULL_CONFIG():
    global config_extract_ea, FULL_CONFIG

    # get FULL_CONFIG size
    curr_ea = config_extract_ea
    stop_bytes = 0  # this should be 0xDEADBEEF
    FULL_CONFIG_ea = 0

    while True:
        next_instruction_ea = idc.next_head(curr_ea)
        if idc.print_insn_mnem(next_instruction_ea) == 'cmp':
            stop_bytes = idc.get_operand_value(next_instruction_ea, 1)
            break
        elif idc.print_insn_mnem(next_instruction_ea) == 'lea':
            FULL_CONFIG_ea = idc.get_operand_value(next_instruction_ea, 1)
        curr_ea = next_instruction_ea

    config_length = 0

    while True:
        if int.from_bytes(idaapi.get_bytes(FULL_CONFIG_ea + config_length, 4),
                          'little') == stop_bytes:
            break
        config_length += 1

    FULL_CONFIG = [
        each_byte
        for each_byte in idaapi.get_bytes(FULL_CONFIG_ea, config_length)
    ]
    FULL_CONFIG = decrypt_config(FULL_CONFIG, config_length)
Ejemplo n.º 5
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
Ejemplo n.º 6
0
    def run(self, arg=0):
        print("hell2")
        idaapi.msg("run() called with %d!\n" % arg)
        heads = Heads(get_segm_start(get_screen_ea()), get_segm_end(get_screen_ea()))
        funcCalls = []
        xor = []
        antiVM = []
        for i in heads:
            # Color the Calls off-white
            if print_insn_mnem(i) == "call":
                funcCalls.append(i)
            # Color Anti-VM instructions Red and print their location
            elif print_insn_mnem(i) in ("sidt", "sgdt",  "sldt", "smsw", "str", "in", "cpuid"):
                antiVM.append(i)
            # Color non-zeroing out xor instructions Orange
            elif print_insn_mnem(i) == "xor" and (print_operand(i,0) != print_operand(i,1)):
                xor.append(i)

        print("Number of calls: %d" % (len(funcCalls)))
        for i in funcCalls:
            set_color(i, CIC_ITEM, 0xc7fdff)

        print("Number of potential Anti-VM instructions: %d" % (len(antiVM)))
        for i in antiVM:
            print("Anti-VM potential at %x" % i)
            set_color(i, CIC_ITEM, 0x0000ff)

        print("Number of xor: %d" % (len(xor)))
        for i in xor:
            set_color(i, CIC_ITEM, 0x00a5ff)
def resolve_all_APIs(resolve_ea, mode):
    if resolve_ea is None:
        print('resolve fails..')
        return

    for ref in idautils.CodeRefsTo(resolve_ea, 1):
        # only 1 ref

        curr_ea = ref
        while True:
            prev_instruction_ea = idc.prev_head(curr_ea)
            if mode == 1:
                if idc.print_insn_mnem(prev_instruction_ea) == 'push':
                    hash_val = idc.get_operand_value(prev_instruction_ea, 0)
                    if hash_val in export_hashes:
                        print(hex(ref) + ' : ' + export_hashes[hash_val])
                        idc.set_cmt(ref, export_hashes[hash_val], 0)
                    break
            else:
                if idc.print_insn_mnem(prev_instruction_ea) == 'mov':
                    hash_val = idc.get_operand_value(prev_instruction_ea, 1)
                    print(hex(hash_val))
                    if hash_val in export_hashes:
                        print(hex(ref) + ' : ' + export_hashes[hash_val])
                        idc.set_cmt(ref, export_hashes[hash_val], 0)
                    break
            curr_ea = prev_instruction_ea
Ejemplo n.º 8
0
def hand_register(line, start_ea, reg_target):
    current = line
    while (current >= start_ea):
        current = idc.prev_head(current)
        if (idc.print_insn_mnem(current) == 'jmp'):
            return hand_block(line, current, reg_target)
        if (idc.print_operand(current, 0)
                == reg_target) and (idc.print_insn_mnem(current)
                                    in ['mov', 'lea']):
            return idc.print_operand(current, 1)
Ejemplo n.º 9
0
def test_basic(strings_exe):
    """Tests some basic functionality and stability."""
    strings_exe = str(strings_exe)

    with kordesii.IDA(strings_exe):
        import idc
        from kordesii.utils import utils
        from kordesii.utils import ida_re

        assert idc.get_input_file_path() == strings_exe
        assert idc.print_insn_mnem(0x00401525) == 'mov'
        assert utils.get_function_addr('GetProcAddress') == 0x40a028
        assert utils.get_string(0x0040C000) == b'Idmmn!Vnsme '

        regex = ida_re.Pattern(b'Idmmn!Vnsme')
        match = regex.search()
        assert match
        assert match.start() == 0x0040C000
        assert match.group() == b'Idmmn!Vnsme'

        # Ensure we can only start one at a time.
        with pytest.raises(ValueError):
            kordesii.IDA(r'C:\dummy.exe').start()
        pass

    # Ensure we can't use modules after closing.
    with pytest.raises(AttributeError):
        idc.print_insn_mnem(0x00401525)

    # Now test that we can spin it up again.
    with kordesii.IDA(strings_exe):
        # import idc  # reimporting is not required.
        assert idc.get_input_file_path() == strings_exe

    # Now test manually starting and stopping.
    ida = kordesii.IDA(strings_exe)
    ida.start()
    import idc
    assert idc.get_input_file_path() == strings_exe
    ida.stop()

    # can't access imports outside
    with pytest.raises(AttributeError):
        idc.get_input_file_path()

    # now try starting the same instance again.
    ida.start()
    assert idc.get_input_file_path() == strings_exe
    ida.stop()

    # Try opening a file that is not actually an exe.
    # It should still work, just not be very helpful.
    with kordesii.IDA(__file__):
        assert idc.get_input_file_path() == __file__
        assert idc.print_insn_mnem(0x00401525) == ''
Ejemplo n.º 10
0
def parse_function(ea):
    func = ida_funcs.func_t(ea)
    res = ida_funcs.find_func_bounds(func, ida_funcs.FIND_FUNC_DEFINE)

    if res == ida_funcs.FIND_FUNC_UNDEF:
        idc.ask_yn(1, 'can not find func bounds.')
        exit(0)

    addr = func.start_ea
    hit_count = 0
    gnm_name = ''
    packet_count = 0
    while addr < func.end_ea:
        if idc.print_insn_mnem(addr) == 'call':
            sub_name = idc.print_operand(addr, 0)
            if 'SetAllocatedNodes@SchedulerProxy' in sub_name:
                arg_addrs = ida_typeinf.get_arg_addrs(addr)
                gnm_name_arg_addr = arg_addrs[1]
                if idc.print_insn_mnem(gnm_name_arg_addr) != 'lea':
                    idc.ask_yn(
                        1, 'gnm name not passed by lea: {:X}'.format(
                            gnm_name_arg_addr))
                    exit(0)
                name_addr = idc.get_operand_value(gnm_name_arg_addr, 1)
                gnm_name = idc.get_strlit_contents(name_addr).decode('ascii')
                hit_count += 1
            if 'set_packet_count' in sub_name:
                # we need to manually set set_packet_count function's type (press key Y)
                # or get_arg_addrs will return None
                arg_addrs = ida_typeinf.get_arg_addrs(addr)
                packet_count_arg_addr = arg_addrs[1]
                packet_count_inst = idc.print_insn_mnem(packet_count_arg_addr)
                if packet_count_inst == 'mov':
                    op_type = idc.get_operand_type(packet_count_arg_addr, 1)
                    if op_type == idc.o_imm:
                        packet_count = idc.get_operand_value(
                            packet_count_arg_addr, 1)
                    else:
                        packet_count = 0
                elif packet_count_inst == 'lea':
                    packet_count = 0
                else:
                    idc.ask_yn(
                        1, 'packet count passed by {} at {:X}'.format(
                            packet_count_inst, packet_count_arg_addr))
                    exit(0)

                hit_count += 1
        if hit_count == 2:
            break
        addr = idc.next_head(addr)
    return gnm_name, packet_count
Ejemplo n.º 11
0
def get_stacked_bytes(dec_func_addr):
    func_stacked_bytes_addr_dict = {}
    xrefs = idautils.CodeRefsTo(dec_func_addr, 0)

    for xref in xrefs:
        prev_addr = idc.prev_head(xref)
        prev_addr_2 = idc.prev_head(prev_addr)

        if idc.print_insn_mnem(prev_addr_2) == "call":
            func_name = idc.print_operand(prev_addr_2, 0)
            func_addr = idc.get_name_ea_simple(func_name)
            func_stacked_bytes_addr_dict[xref] = func_addr

    # enc_mod_addr = list(set(enc_mod_addr)) # [Debug] Get unique functions only

    for xref, stacked_bytes_addr in func_stacked_bytes_addr_dict.items():
        print(f"Address: {hex(stacked_bytes_addr)}")
        func_ea = idc.get_func_attr(stacked_bytes_addr, idc.FUNCATTR_START)
        bytes_collected = bytearray()  # Collected stack string store here

        for ins in idautils.FuncItems(func_ea):
            if ida_bytes.is_code(ida_bytes.get_full_flags(ins)):
                if idc.print_insn_mnem(ins) == "mov":
                    if idc.get_operand_type(ins, 1) == idc.o_imm:
                        # disasm = idc.GetDisasm(ins) # [Debug]
                        hex_str_len = len(
                            idc.print_operand(ins, 1).lstrip("0").rstrip("h"))
                        const_hex_byte = idc.print_operand(
                            ins, 1).lstrip("0").rstrip("h")

                        if hex_str_len != 8:  # Skip if const hex byte less than 8
                            append_zero = "0" * (8 - hex_str_len)
                            const_hex_byte = append_zero + const_hex_byte
                            # print(struct.pack("<I", int(const_hex_byte, 16))) # [Debug]

                        # else:
                        # print(struct.pack("<I", int(const_hex_byte, 16))) # [Debug]
                        bytes_collected += struct.pack("<I",
                                                       int(const_hex_byte, 16))

        if len(bytes_collected) >= 1:
            cmt_str = ""
            if dec_func_addr == 0x10001253:  # fn_name_addr
                print(f"{decode_fnname(bytes_collected[4:])}")
                cmt_str = decode_fnname(bytes_collected[4:])
            elif dec_func_addr == 0x1000122B:  # mod_name_addr
                print(f"{decode_modname(bytes_collected[4:])}")
                cmt_str = decode_modname(bytes_collected[4:])
            idc.set_cmt(xref, cmt_str, 1)  # Comment near xref decoder function
        else:
            print(f"[-] {hex(stacked_bytes_addr)} addr error")
Ejemplo n.º 12
0
def add_bp_to_virtual_calls(cur_addr, end):
    while cur_addr < end:
        if cur_addr == idc.BADADDR:
            break
        elif idc.print_insn_mnem(cur_addr) == 'call' or idc.print_insn_mnem(
                cur_addr) == 'BLR':
            if True in [
                    idc.print_operand(cur_addr, 0).find(reg) != -1
                    for reg in REGISTERS
            ]:  # idc.GetOpnd(cur_addr, 0) in REGISTERS:
                cond, bp_address = vtableAddress.write_vtable2file(cur_addr)
                if cond != '':
                    bp_vtable = AddBP.add(bp_address, cond)
        cur_addr = idc.next_head(cur_addr)
Ejemplo n.º 13
0
def get_con2_var_or_num(i_cnt, cur_addr):
    """
    :param i_cnt: the register of the virtual call
    :param cur_addr: the current address in the memory
    :return: "success" string and the address of the vtable's location. if it fails it sends the reason and -1
    """
    start_addr = idc.get_func_attr(cur_addr, idc.FUNCATTR_START)
    virt_call_addr = cur_addr
    cur_addr = idc.prev_head(cur_addr)
    dct_arch = get_arch_dct()
    if dct_arch == -1:
        return 'Wrong Architechture', "-1", cur_addr

    while cur_addr >= start_addr:
        if idc.print_insn_mnem(
                cur_addr)[:3] == dct_arch["opcode"] and idc.print_operand(
                    cur_addr, 0) == i_cnt:  # TODO lea ?
            opnd2 = idc.print_operand(cur_addr, 1)
            place = opnd2.find(dct_arch["separator"])
            if place != -1:  # if the function is not the first in the vtable
                register = opnd2[opnd2.find('[') + 1:place]
                if opnd2.find('*') == -1:
                    offset = opnd2[place +
                                   dct_arch["val_offset"]:opnd2.find(']')]
                else:
                    offset = "*"
                return register, offset, cur_addr
            else:
                offset = "0"
                if opnd2.find(']') != -1:
                    register = opnd2[opnd2.find('[') + 1:opnd2.find(']')]
                else:
                    register = opnd2
                return register, offset, cur_addr
        elif idc.print_insn_mnem(cur_addr)[:4] == "call":
            intr_func_name = idc.print_operand(cur_addr, 0)
            # In case the code has CFG -> ignores the function call before the virtual calls
            if "guard_check_icall_fptr" not in intr_func_name:
                if "nullsub" not in intr_func_name:
                    # intr_func_name = idc.Demangle(intr_func_name, idc.GetLongPrm(idc.INF_SHORT_DN))
                    print(
                        "Warning! At address 0x%08x: The vtable assignment might be in another function (Maybe %s),"
                        " could not place BP." %
                        (virt_call_addr, intr_func_name))
                cur_addr = start_addr
        cur_addr = idc.prev_head(cur_addr)
    return "out of the function", "-1", cur_addr

    return '', 0, cur_addr
Ejemplo n.º 14
0
def getBBconsts(bl):
	strings = []
	consts = []
	start = bl[0]
	end = bl[1]
	invoke_num = 0
	inst_addr = start
	while inst_addr < end:
		opcode = idc.print_insn_mnem(inst_addr)
		if opcode in ['la','jalr','call', 'jal']:
			inst_addr = idc.next_head(inst_addr)
			continue
		strings_src, consts_src = getConst(inst_addr, 0)
		strings_dst, consts_dst = getConst(inst_addr, 1)
		strings += strings_src
		strings += strings_dst
		consts += consts_src
		consts += consts_dst
		try:
			strings_dst, consts_dst = getConst(inst_addr, 2)
			consts += consts_dst
			strings += strings_dst
		except:
			pass

		inst_addr = idc.next_head(inst_addr)
	return strings, consts
Ejemplo n.º 15
0
 def find_main_x86(self):
     start = ida_ida.inf_get_start_ea()
     fn = idaapi.get_func(start)
     f_start, f_end = fn.start_ea, fn.end_ea
     eas = list(idautils.Heads(f_start, f_end))
     mnem = idc.print_insn_mnem(eas[-1])
     if mnem == 'jmp':
         return idc.get_operand_value(eas[-1], 0)
     elif mnem == 'call':
         for i in range(len(list(eas)) - 2, -1, -1):
             mnem = idc.print_insn_mnem(eas[i])
             if mnem == 'push':
                 return idc.get_operand_value(eas[i], 0)
     else:
         print(idc.GetDisasm(eas[-1]))
         return 0
Ejemplo n.º 16
0
def main():
    for func in idautils.Functions():
        #get function flags
        flags = idc.get_func_attr(func, FUNCATTR_FLAGS)

        # skip library & thunk functions
        if flags & FUNC_LIB or flags & FUNC_THUNK:
            continue

        dism_addr = list(idautils.FuncItems(func))
        for ea in dism_addr:
            mnem = idc.print_insn_mnem(ea)

            if mnem == "call":
                highlight_insn(ea, CALL_COLOR)

            elif mnem == "rdtsc":
                highlight_insn(ea, ANITDEBUG_COLOR, "Possible Anti-Debugging")

            elif mnem == "xor":
                op1 = idc.print_operand(ea, 0)
                op2 = idc.print_operand(ea, 1)
                if op1 == op2:
                    highlight_insn(ea, DEFAULT_COLOR, "{} = 0".format(op1))
                else:
                    highlight_insn(ea, XOR_COLOR, "Possible enc/dec")

    highlight_anti_debug()
Ejemplo n.º 17
0
def replace_sym_const(ea, api):
    for arg_n in api_list[api].keys():
        # Calling Convention: cdecl, stdcall
        push_cnt = 0
        ea_search = ea
        while push_cnt < arg_n:
            ea_search = idc.prev_head(ea_search)
            op = idc.print_insn_mnem(ea_search)
            if op == "push":
                push_cnt += 1

        operand = idc.print_operand(ea_search, 0)
        if operand.isdigit():
            operand = int(idc.print_operand(ea_search, 0))
        else:
            continue

        enum_name = api + "_" + str(arg_n)
        const = api_list[api][arg_n][operand]

        enum_id = ida_enum.get_enum(enum_name)
        if enum_id == BADADDR:
            # add new enum
            enum_qty = ida_enum.get_enum_qty()
            enum_id = ida_enum.add_enum(enum_qty, enum_name, 0)

        symbolic_id = ida_enum.get_enum_member_by_name(const)
        if symbolic_id == BADADDR:
            # add new enum member
            ida_enum.add_enum_member(enum_id, const, operand, 0xffffffff)

        ida_bytes.op_enum(ea_search, 0, enum_id, 0)
Ejemplo n.º 18
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
Ejemplo n.º 19
0
def disassemble_func(address):
    func_dis = {}
    symbolic_calls = {}
    inst_num = 0
    flags = get_func_flags(address)
    last_addr = address
    asm = ''
    for addr in FuncItems(address):
        ins = DecodeInstruction(addr)
        # print('decoded')
        byte_instr = get_bytes(addr, ins.size)
        asm = asm + str(binascii.hexlify(byte_instr))
        inst_num = inst_num + 1
        last_addr = addr
        if idc.print_insn_mnem(addr) in ["call"]:
            # print('Call:'+str(ins))
            call_address = idc.get_operand_value(addr, 0)
            # print(call_address)
            start_addr = first_func_chunk(call_address)
            symbolic_calls[start_addr] = idc.get_func_name(call_address)

    func_dis['bytecode'] = asm
    func_dis['symbolic_calls'] = symbolic_calls
    func_dis['start_address'] = first_fusnc_chunk(address)
    func_dis['end_address'] = last_addr
    func_dis['segment_address'] = get_segm_start(address)
    func_dis['segment_name'] = SegName(address)
    func_dis['name'] = idc.get_func_name(address)
    func_dis['inst_numbers'] = inst_num
    # attenzione sta cosa ci da la roba riconosciuta con flirt.
    func_dis['library_flag'] = flags & FUNC_LIB
    return func_dis
Ejemplo n.º 20
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
Ejemplo n.º 21
0
 def get_code_refs(self):
     xrefs = list(idautils.CodeRefsTo(self.addr, 1))
     if len(xrefs) < 2:
         mnem = idc.print_insn_mnem(self.addr).lower()
         if mnem == "nop" or mnem == "jmp":
             return 9999
     return len(xrefs)
Ejemplo n.º 22
0
def cfg_construct(func):
    func_start = func.startEA
    func_end = func.endEA
    cfg = nx.DiGraph()
    seq_blocks, main_blocks = obtain_block_sequence(func)
    i = 0
    visited = {}
    for bl in seq_blocks:
        start = seq_blocks[bl][0]
        end = seq_blocks[bl][1]
        src_node = (start, end)
        if end in seq_blocks and idc.print_insn_mnem(
                idc.PrevHead(end)) != 'jmp':
            next_start = seq_blocks[end][0]
            next_end = seq_blocks[end][1]
            next_node = (next_start, next_end)
            cfg.add_edge(src_node, next_node)
        if start == func_start:
            cfg.add_node(src_node, c='start')
            start_node = src_node
        if end == func_end:
            cfg.add_node(src_node, c='end')
        refs = idautils.CodeRefsFrom(PrevHead(end), 0)

        for ref in refs:
            #print ref
            if ref in seq_blocks:
                dst_node = (seq_blocks[ref][0], seq_blocks[ref][1])
                cfg.add_edge(src_node, dst_node)
    return cfg, start_node
Ejemplo n.º 23
0
def is_conformant_instr(va, mnems, op_specs):
    """Check if instruction at @va conforms to operand specifications list.

    Args:
        va (numbers.Integral): Virtual address of instruction to assess.
        mnems (str or iterable of str): Optional instruction mnemonic(s) to
            check for.
        op_specs (iterable of OpSpec): Iterable containing zero or more operand
            specification tuples (operand position, type, and name).

    Returns:
        True if conformant
        False if nonconformant
    """
    if (not mnems) and (not op_specs):
        msg = 'Must specify either a mnemonic or an operand specification list'
        raise ValueError(msg)

    mnem_current = idc.print_insn_mnem(va)
    if mnems:
        if isinstance(mnems, basestring):
            if mnem_current != mnems:
                return False
        else:
            if mnem_current not in mnems:
                return False

    for spec in op_specs:
        if not is_conformant_operand(va, spec):
            return False

    return True
Ejemplo n.º 24
0
    def _does_instruction_match(self, ea, instruction, regex=False):
        i = 0
        op_cnt = 0
        op_ok_cnt = 0
        match = False
        insn_t = idaapi.insn_t()
        ins_size = idaapi.decode_insn(insn_t, ea)
        mnem = idc.print_insn_mnem(ea)

        if (not instruction.mnem) or (instruction.mnem == mnem) or (
                regex and re.match(instruction.mnem, mnem)):
            for operand in instruction.operands:
                if operand:
                    op_cnt += 1
                    op = idc.print_operand(ea, i)

                    if regex:
                        if re.match(operand, op):
                            op_ok_cnt += 1
                    elif operand == op:
                        op_ok_cnt += 1
                i += 1

            if op_cnt == op_ok_cnt:
                match = True

        return match
Ejemplo n.º 25
0
    def _is_bad_instruction(self,
                            ea,
                            bad_instructions=['j', 'b'],
                            no_clobber=[]):
        bad = False
        mnem = idc.print_insn_mnem(ea)

        if mnem and mnem[0] in bad_instructions:
            bad = True
        else:
            if idaapi.IDA_SDK_VERSION < 700:
                for register in no_clobber:
                    if (idaapi.insn_t_get_canon_feature(idaapi.cmd.itype)
                            & idaapi.CF_CHG1) == idaapi.CF_CHG1:
                        if idc.print_operand(ea, 0) == register:
                            bad = True
            else:
                insn = idaapi.insn_t()
                #insn.itype = idaapi.cmd.itype   # ml
                for register in no_clobber:
                    if (insn.get_canon_feature()
                            & idaapi.CF_CHG1) == idaapi.CF_CHG1:
                        if idc.print_operand(ea, 0) == register:
                            bad = True
        return bad
Ejemplo n.º 26
0
    def track_register(self, ea, target_dest_reg):

        f_start = idc.get_func_attr(ea, idc.FUNCATTR_START)
        f_end = idc.get_func_attr(ea, idc.FUNCATTR_END)

        curr_ea = ea
        dst = None
        src = None

        target = target_dest_reg.lower()
        target_dest_reg = target_dest_reg.lower()

        target_value = None
        target_ea = idc.BADADDR
        target_type = None
        previous_call = None

        ret_dict = {}

        while curr_ea != idc.BADADDR:
            #instruction = idc.GetDisasm(curr_ea)

            # print "0x%08x %s" % (curr_ea, instruction)

            # looking for the previous place this register was assigned a value
            mnem = idc.print_insn_mnem(curr_ea).lower()
            dst = idc.print_operand(curr_ea, 0).lower()
            src = idc.print_operand(curr_ea, 1).lower()

            if dst == target and self.is_set_argument_instr(mnem):
                target = src
                target_value = src
                target_ea = curr_ea
                # print "            new target set %s (type=%d)" % (target, idc.get_operand_type(curr_ea, 1))
                if target.startswith("="):
                    break

            if dst == target == "r0" and self.is_call_instr(mnem):
                target_value = "<return from previous call>"
                previous_call = curr_ea
                break
            # step to previous instruction
            curr_ea = idc.prev_head(curr_ea - 1, f_start)

        if target_value:
            # print ">>> 0x%08x, %s is set to %s @ 0x%08x" % (ea, target_dest_reg, target_value, target_ea)
            ret_dict = {
                "target": target_dest_reg,
                "value": target_value,
                "target_ea": target_ea,
                "ea": ea
            }

            if previous_call:
                ret_dict["previous_call"] = previous_call

            return ret_dict

        # fall through if nothing is found
        return {}
Ejemplo n.º 27
0
 def calls_from(self) -> Iterable[Tuple[int, int]]:
     """Iterates call address and callee address of the calls within this function."""
     for ea in self.heads():
         if idc.print_insn_mnem(ea) == "call":
             for xref in idautils.XrefsFrom(ea, idaapi.XREF_FAR):
                 func_ea = xref.to
                 if func_ea:
                     yield ea, func_ea
Ejemplo n.º 28
0
def get_sequences(start, end):
    seq = []
    inst_addr = start
    while inst_addr <= end:
        opcode = idc.print_insn_mnem(inst_addr)
        seq.append(opcode)
        inst_addr = idc.next_head(inst_addr)
    return seq
Ejemplo n.º 29
0
def getDispatchCode(ea):
    # get dispatch code out of an instruction
    first, second = (idc.print_operand(ea, 0), idc.get_operand_value(ea, 1))
    if first == 'eax':
        return second
    raise ValueError(
        "Search resulted in address %08x, but instruction '%s' does fulfill requested constraints"
        % (ea, idc.print_insn_mnem(ea)))
Ejemplo n.º 30
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)
Ejemplo n.º 31
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))