Beispiel #1
0
def bp_func(bp_num, params):
    '''
    Function to use as a callback on breakpoints
    '''
    from ipython_shell import start_shell
    import api
    from utils import pp_print
    # The first argument of insn begin and mem write/read callbacks should
    # always be cpu_index
    cpu_index = params["cpu_index"]
    cpu = api.r_cpu(cpu_index)
    pp_print("[!] Breakpoint %s hit at address %x\n" % (bp_num, cpu.PC))
    start_shell()
Beispiel #2
0
def bp_func(bp_num, params):
    '''
    Function to use as a callback on breakpoints
    '''
    from ipython_shell import start_shell
    import api
    from utils import pp_print
    # The first argument of insn begin and mem write/read callbacks should
    # always be cpu_index
    cpu_index = params["cpu_index"] 
    cpu = api.r_cpu(cpu_index)
    pp_print("[!] Breakpoint %s hit at address %x\n" % (bp_num, cpu.PC))
    start_shell()
Beispiel #3
0
def mem_write(params):
    '''
        Callback for memory writes.
    '''
    global cm
    global page_status
    global current_layer
    global UNPACKER_LOG_PATH
    global UNPACKER_DUMP_PATH

    import api
    from cpus import X64CPU, X86CPU

    # Get callback parameters
    cpu_index = params["cpu_index"]
    vaddr = params["vaddr"]
    size = params["size"]
    haddr = params["haddr"]
    data = params["data"]

    # Get running process, as well as CPU object
    pgd = api.get_running_process(cpu_index)
    cpu = api.r_cpu(cpu_index)

    if not api.is_kernel_running(cpu_index):
        mask = 0xFFFFF000 if TARGET_LONG_SIZE == 4 else 0xFFFFFFFFFFFFF000
        page = vaddr & mask

        # Set page write status (update with current layer)
        page_status_w[page] = current_layer

        # Log the page write
        pc = cpu.RIP if isinstance(cpu, X64CPU) else cpu.EIP
        if TARGET_LONG_SIZE == 4:
            append_log("[W]  - PGD [%08x] - PAGE [%08x] - FROM [%08x]" %
                       (pgd, page, pc))
        else:
            append_log("[W]  - PGD [%016x] - PAGE [%016x] - FROM [%016x]" %
                       (pgd, page, pc))
Beispiel #4
0
def disassemble(addr, cpu_index):
    '''
	Disassemble instruction. Receives 2 parameters:
		:param addr: Address from instruction to disassemble
		:type addr: int
		:param cpu_index: CPU index 
		:type cpu_index: int
	'''

    global logger
    global num_ins

    pgd = api.get_running_process(cpu_index)

    if api.get_os_bits() == 32:
        md = Cs(CS_ARCH_X86, CS_MODE_32)
        content = api.r_va(pgd, addr, 0x4)
    else:
        md = Cs(CS_ARCH_X86, CS_MODE_64)
        content = api.r_va(pgd, addr, 0x6)

    md.detail = True

    for insn in md.disasm(content, addr):

        if insn.mnemonic == "call":

            if len(insn.operands) > 0:

                mycpu = api.r_cpu(0)

                simbolo = None

                if api.get_os_bits() == 32:
                    simbolo = api.va_to_sym(pgd, mycpu.EIP)
                else:
                    simbolo = api.va_to_sym(pgd, mycpu.RIP)

                if simbolo != None and api.get_os_bits() != 32:

                    ## Microsoft x64 calling convention
                    ##

                    logger.info(
                        "[API]0x%x:\t%s\t%s\t[RIP]:0x%x\t%s\t[PGD]: %x",
                        insn.address, insn.mnemonic, insn.op_str, mycpu.RIP,
                        simbolo, pgd)
                    num_ins = num_ins + 1

                    ## RCX - Arg 1

                    try:

                        rcx_content = api.r_va(pgd, mycpu.RCX, 0x100)
                        logger.info("[RCX]: 0x%x [Data]: %s", mycpu.RCX,
                                    smart_format(rcx_content, 0x100, True))

                    except:
                        logger.info("[RCX]: 0x%x", mycpu.RCX)

                    ## RDX - Arg 2

                    try:

                        rdx_content = api.r_va(pgd, mycpu.RDX, 0x100)
                        logger.info("[RDX]: 0x%x [Data]: %s", mycpu.RDX,
                                    smart_format(rdx_content, 0x100, True))

                    except:
                        logger.info("[RDX]: 0x%x", mycpu.RDX)

                    ## R8 - Arg 3

                    try:

                        r8_content = api.r_va(pgd, mycpu.R8, 0x100)
                        logger.info("[R8]: 0x%x [Data]: %s", mycpu.R8,
                                    smart_format(r8_content, 0x100, True))

                    except:
                        logger.info("[R8]: 0x%x", mycpu.R8)

                    ## R9 - Arg 4

                    try:

                        r9_content = api.r_va(pgd, mycpu.R9, 0x100)
                        logger.info("[R9]: 0x%x [Data]: %s", mycpu.R9,
                                    smart_format(r9_content, 0x100, True))

                    except:
                        logger.info("[R9]: 0x%x", mycpu.R9)

                    ## RAX - return value

                    try:
                        rax_content = api.r_va(pgd, mycpu.RAX, 0x100)
                        logger.info("[RAX]: 0x%x [Data]: %s", mycpu.RAX,
                                    smart_format(rax_content, 0x100, True))

                    except:

                        logger.info("[RAX]: 0x%x", mycpu.RAX)

                    logger.info("--")

                elif simbolo != None:

                    ## x86 call conventions
                    # cdecl -> arguments are pushed on the stack in the reverse order. EAX return
                    # syscall -> arguments are pushed on the stack right to left.
                    # optlink -> arguments are pushed on the stack right to left.
                    # ...

                    logger.info(
                        "[API]0x%x:\t%s\t%s\t[EIP]:0x%x\t%s\t[PGD]: %x",
                        insn.address, insn.mnemonic, insn.op_str, mycpu.EIP,
                        simbolo, pgd)
                    num_ins = num_ins + 1

                    bytestoread = 0x200

                    try:
                        eax_content = api.r_va(pgd, mycpu.EAX, bytestoread)
                        logger.info(
                            "[EAX]: 0x%x [Data]: %s", mycpu.EAX,
                            smart_format(eax_content, bytestoread, True))

                    except:
                        logger.info("[EAX]: 0x%x", mycpu.EAX)

                    try:
                        ecx_content = api.r_va(pgd, mycpu.ECX, bytestoread)
                        logger.info(
                            "[ECX]: 0x%x [Data]: %s", mycpu.ECX,
                            smart_format(ecx_content, bytestoread, True))

                    except:
                        logger.info("[ECX]: 0x%x", mycpu.ECX)

                    try:
                        edx_content = api.r_va(pgd, mycpu.EDX, bytestoread)
                        logger.info(
                            "[EDX]: 0x%x [Data]: %s", mycpu.EDX,
                            smart_format(edx_content, bytestoread, True))

                    except:
                        logger.info("[EDX]: 0x%x", mycpu.EDX)

                    try:
                        ebp_arg2_content = api.r_va(pgd, mycpu.EBP + 8,
                                                    bytestoread)
                        logger.info(
                            "[EBP+8]: 0x%x [Data]: %s", mycpu.EBP + 8,
                            smart_format(ebp_arg2_content, bytestoread, True))
                    except:
                        logger.info("[EBP+8]: 0x%x", mycpu.EBP + 8)

                    try:
                        ebp_arg3_content = api.r_va(pgd, mycpu.EBP + 12,
                                                    bytestoread)
                        logger.info(
                            "[EBP+12]: 0x%x [Data]: %s", mycpu.EBP + 12,
                            smart_format(ebp_arg3_content, bytestoread, True))
                    except:
                        logger.info("[EBP+12]: 0x%x", mycpu.EBP + 12)

                    try:
                        ebp_arg4_content = api.r_va(pgd, mycpu.EBP + 16,
                                                    bytestoread)
                        logger.info(
                            "[EBP+16]: 0x%x [Data]: %s", mycpu.EBP + 16,
                            smart_format(ebp_arg4_content, bytestoread, True))
                    except:
                        logger.info("[EBP+16]: 0x%x", mycpu.EBP + 16)

                    try:
                        ebp_arg5_content = api.r_va(pgd, mycpu.EBP + 20,
                                                    bytestoread)
                        logger.info(
                            "[EBP+20]: 0x%x [Data]: %s", mycpu.EBP + 20,
                            smart_format(ebp_arg5_content, bytestoread, True))
                    except:
                        logger.info("[EBP+20]: 0x%x", mycpu.EBP + 20)

                    try:
                        ebp_arg6_content = api.r_va(pgd, mycpu.EBP + 24,
                                                    bytestoread)
                        logger.info(
                            "[EBP+24]: 0x%x [Data]: %s", mycpu.EBP + 24,
                            smart_format(ebp_arg6_content, bytestoread, True))
                    except:
                        logger.info("[EBP+24]: 0x%x", mycpu.EBP + 24)

                    logger.info("--")
Beispiel #5
0
def mem_write(params):
    '''
        Callback for memory writes.
    '''
    global cm
    global page_status_x
    global page_status_w
    global current_layer
    global UNPACKER_LOG_PATH
    global UNPACKER_DUMP_PATH
    global section_maps
    global written_files
    global ntdll_space

    import api
    from cpus import X64CPU, X86CPU

    # Get callback parameters
    cpu_index = params["cpu_index"]
    vaddr = params["vaddr"]
    size = params["size"]
    haddr = params["haddr"]
    data = params["data"]

    # Get running process, as well as CPU object
    pgd = api.get_running_process(cpu_index)
    cpu = api.r_cpu(cpu_index)
    pc = cpu.RIP if isinstance(cpu, X64CPU) else cpu.EIP

    if pgd not in page_status_w:
        page_status_w[pgd] = {}

    if not api.is_kernel_running(cpu_index):
        mask = 0xFFFFF000 if TARGET_LONG_SIZE == 4 else 0xFFFFFFFFFFFFF000
        page = vaddr & mask

        overlapping_section_maps = []
        # Check if the memory was mapped to file, so we record a file write for such file
        for base, size, file_offset, file_name in section_maps:
            if page >= (base & mask) and page < ((
                (base + size) & mask) + 0x1000):
                overlapping_section_maps.append(
                    (base, size, file_offset, file_name))

        # If it comes from ntdll and affects to a mapped file, just ignore it,
        # it is likely due to relocations or loader/stuff and is prone to FPs.
        if (pc >= ntdll_space[0] and pc < (ntdll_space[0] + ntdll_space[1])
            ) and len(overlapping_section_maps) > 0:
            return

        # Set page write status (update with current layer)
        page_status_w[pgd][page] = current_layer

        # Log the page write
        if TARGET_LONG_SIZE == 4:
            append_log("[W]  - PGD [%08x] - PAGE [%08x] - FROM [%08x]" %
                       (pgd, page, pc))
        else:
            append_log("[W]  - PGD [%016x] - PAGE [%016x] - FROM [%016x]" %
                       (pgd, page, pc))

        # Only reflect on mapped file if it doesn't come from ntdll, to avoid FPs due to relocation
        # fixing.
        # Finally, check if the memory was mapped to file, so we record a file write for such file
        for base, size, file_offset, file_name in overlapping_section_maps:
            if file_name not in written_files:
                written_files[file_name] = [
                    ((page - (base & mask)) + file_offset, 0x1000)
                ]
            else:
                written_files[file_name].append(
                    ((page - (base & mask)) + file_offset, 0x1000))
            append_log(
                "^^^---> PAGE is section mapped, FILE [%s] - Offset %x - Size %x"
                % (file_name, (page - (base & mask)) + file_offset, size))
Beispiel #6
0
def gdb_read_thread_register(thread_id, thread_list, gdb_register_index):
    '''
    Given a GDB register index, return an str with its value. Obtain
    the value either from the running CPU or the saved KTRAP_FRAME.
    NOTE: Not all registers are supported, if so, 0's are returned.
    '''
    from utils import ConfigurationManager as conf_m
    from api import r_cpu
    from cpus import RT_SEGMENT
    from cpus import RT_REGULAR

    if conf_m.platform == "i386-softmmu":
        from cpus import gdb_map_i386_softmmu as gdb_map
    elif conf_m.platform == "x86_64-softmmu":
        from cpus import gdb_map_x86_64_softmmu as gdb_map
    else:
        raise NotImplementedError(
            "[gdb_read_thread_register] Architecture not supported yet")

    # If it is not mapped to a CPU register or KTRAP_FRAME value,
    # we just return 0s.
    if gdb_register_index not in gdb_map:
        return "\0" * (conf_m.bitness / 8)
    else:
        str_size = gdb_map[gdb_register_index][2]

    cpu_index = None
    thread = None

    some_thread_running = False
    # First, check if we can read the register from the CPU object
    for element in thread_list:
        if element['id'] == thread_id:
            thread = element
            cpu_index = element['running']
            if cpu_index:
                some_thread_running = True

    if thread is None:
        return None

    if cpu_index is None and not some_thread_running:
        cpu_index = 0

    if cpu_index is not None:
        cpu = r_cpu(cpu_index)
        val = 0
        try:
            if gdb_map[gdb_register_index][3] == RT_SEGMENT:
                val = getattr(cpu, gdb_map[gdb_register_index][0])['base']
            else:
                val = getattr(cpu, gdb_map[gdb_register_index][0])
        except:
            val = 0
        if val == -1:
            val = 0
        return val_to_str(val, str_size)
    # If the thread is not running, read it from the KTRAP_FRAME
    else:
        if os_family == OS_FAMILY_WIN:
            from windows_vmi import win_read_thread_register_from_ktrap_frame
            val = 0
            try:
                val = win_read_thread_register_from_ktrap_frame(
                    thread, gdb_map[gdb_register_index][1])
            except Exception as e:
                pp_debug(
                    "Exception after win_read_thread_register_from_ktrap_frame: "
                    + str(e))
            if val == -1:
                val = 0
            return val_to_str(val, str_size)
        elif os_family == OS_FAMILY_LINUX:
            raise NotImplementedError(
                "gdb_read_thread_register not implemented yet on Linux guests")