Example #1
0
/* Tries to find the kernel page directory by doing an exhaustive search
 * through the memory space for the System process.  The page directory
 * location is then pulled from this eprocess struct.
 */
static status_t
get_kpgd_method2(
    vmi_instance_t vmi)
{
    addr_t sysproc = 0;
    windows_instance_t windows = NULL;

    if (vmi->os_data == NULL) {
        errprint("VMI_ERROR: No OS data initialized\n");
        return VMI_FAILURE;
    }

    windows = vmi->os_data;
    sysproc = windows->sysproc;

    /* get address for System process */
    if (!sysproc) {
        if ((sysproc = windows_find_eprocess(vmi, "System")) == 0) {
            dbprint(VMI_DEBUG_MISC, "--failed to find System process.\n");
            goto error_exit;
        }
        printf("LibVMI Suggestion: set win_sysproc=0x%"PRIx64" in libvmi.conf for faster startup.\n",
             sysproc);
    }
    dbprint(VMI_DEBUG_MISC, "--got PA to PsInitialSystemProcess (0x%.16"PRIx64").\n",
            sysproc);

    /* get address for page directory (from system process) */
    if (VMI_FAILURE ==
        vmi_read_addr_pa(vmi,
                         sysproc +
                         windows->pdbase_offset,
                         &vmi->kpgd)) {
        dbprint(VMI_DEBUG_MISC, "--failed to resolve PD for System process\n");
        goto error_exit;
    }

    if (!vmi->kpgd) {
        dbprint(VMI_DEBUG_MISC, "--kpgd was zero\n");
        goto error_exit;
    }
    dbprint(VMI_DEBUG_MISC, "**set kpgd (0x%.16"PRIx64").\n", vmi->kpgd);

    if (VMI_FAILURE ==
        vmi_read_addr_pa(vmi,
                     sysproc + windows->tasks_offset,
                     &vmi->init_task)) {
        dbprint(VMI_DEBUG_MISC, "--failed to resolve address of System process\n");
        goto error_exit;
    }
    vmi->init_task -= windows->tasks_offset;
    dbprint(VMI_DEBUG_MISC, "**set init_task (0x%.16"PRIx64").\n", vmi->init_task);

    return VMI_SUCCESS;

error_exit:
    return VMI_FAILURE;
}
Example #2
0
static status_t
get_kpgd_method0(
    vmi_instance_t vmi)
{
    addr_t sysproc = 0;
    windows_instance_t windows = NULL;

    if (vmi->os_data == NULL) {
        errprint("VMI_ERROR: No OS data initialized\n");
        return VMI_FAILURE;
    }

    windows = vmi->os_data;

    if (VMI_FAILURE == vmi_read_addr_ksym(vmi, "PsActiveProcessHead", &sysproc)) {
        dbprint(VMI_DEBUG_MISC, "--failed to resolve PsActiveProcessHead\n");
        goto error_exit;
    }
    if (VMI_FAILURE == vmi_read_addr_va(vmi, sysproc, 0, &sysproc)) {
        dbprint(VMI_DEBUG_MISC, "--failed to translate PsActiveProcessHead\n");
        goto error_exit;
    }
    sysproc = vmi_translate_kv2p(vmi, sysproc) - windows->tasks_offset;
    dbprint(VMI_DEBUG_MISC, "--got PA to PsActiveProcessHead (0x%.16"PRIx64").\n", sysproc);

    if (VMI_FAILURE ==
        vmi_read_addr_pa(vmi,
                         sysproc +
                         windows->pdbase_offset,
                         &vmi->kpgd)) {
        dbprint(VMI_DEBUG_MISC, "--failed to resolve pointer for system process\n");
        goto error_exit;
    }

    if (!vmi->kpgd) {
        dbprint(VMI_DEBUG_MISC, "--kpgd was zero\n");
        goto error_exit;
    }
    dbprint(VMI_DEBUG_MISC, "**set kpgd (0x%.16"PRIx64").\n", vmi->kpgd);

    if (VMI_FAILURE ==
        vmi_read_addr_pa(vmi,
                     sysproc + windows->tasks_offset,
                     &vmi->init_task)){
        dbprint(VMI_DEBUG_MISC, "--failed to resolve address of System process\n");
        goto error_exit;
    }
    vmi->init_task -= windows->tasks_offset;
    dbprint(VMI_DEBUG_MISC, "**set init_task (0x%.16"PRIx64").\n", vmi->init_task);

    return VMI_SUCCESS;

error_exit:
    return VMI_FAILURE;
}
Example #3
0
status_t init_kdversion_block (vmi_instance_t vmi)
{
    addr_t KdVersionBlock_phys = 0;
    addr_t DebuggerDataList = 0, ListPtr = 0;

    KdVersionBlock_phys = find_kdversionblock_address_fast(vmi);
    //KdVersionBlock_phys = find_kdversionblock_address(vmi);
    if (!KdVersionBlock_phys){
        goto error_exit;
    }

    // Use heuristic to find windows version
    find_windows_version(vmi, KdVersionBlock_phys);

    // get the virtual address for KdVersionBlock from the physical
    if (VMI_FAILURE == vmi_read_addr_pa(vmi, KdVersionBlock_phys, &DebuggerDataList)){
        goto error_exit;
    }
    if (VMI_FAILURE == vmi_read_addr_va(vmi, DebuggerDataList, 0, &ListPtr)){
        goto error_exit;
    }

    if (ListPtr && !vmi->os.windows_instance.kdversion_block){
        vmi->os.windows_instance.kdversion_block = ListPtr;
        printf("LibVMI Suggestion: set win_kdvb=0x%llx in libvmi.conf for faster startup.\n", vmi->os.windows_instance.kdversion_block);
    }
    dbprint("**set KdVersionBlock address=0x%llx\n", vmi->os.windows_instance.kdversion_block);

    return VMI_SUCCESS;
error_exit:
    vmi->os.windows_instance.version = VMI_OS_WINDOWS_UNKNOWN;
    return VMI_FAILURE;
}
Example #4
0
static event_response_t file_name_cb(drakvuf_t drakvuf, drakvuf_trap_info_t *info) {
    vmi_instance_t vmi = drakvuf_lock_and_get_vmi(drakvuf);
    struct file_watch *watch = (struct file_watch*)info->trap->data;
    filetracer *f = watch->f;

    if (info->trap_pa == watch->file_name_buffer)
    {
        addr_t file_name = 0;
        uint16_t length = 0;
        vmi_read_addr_pa(vmi, watch->file_name_buffer, &file_name);
        vmi_read_16_pa(vmi, watch->file_name_length, &length);

        //printf("File name @ 0x%lx. Length: %u\n", file_name, length);

        if (file_name && length > 0 && length < VMI_PS_4KB) {
            char *procname = drakvuf_get_current_process_name(drakvuf, info->vcpu, info->regs);
            unicode_string_t str = { .contents = NULL };
            str.length = length;
            str.encoding = "UTF-16";
            str.contents = (unsigned char *)g_malloc0(length);
            vmi_read_va(vmi, file_name, 0, str.contents, length);
            unicode_string_t str2 = { .contents = NULL };
            status_t rc = vmi_convert_str_encoding(&str, &str2, "UTF-8");

            if (VMI_SUCCESS == rc) {

                switch(f->format) {
                case OUTPUT_CSV:
                    printf("filetracer,%" PRIu32 ",0x%" PRIx64 ",%s,%s\n",
                           info->vcpu, info->regs->cr3, procname, str2.contents);
                    break;
                default:
                case OUTPUT_DEFAULT:
                    printf("[FILETRACER] VCPU:%" PRIu32 " CR3:0x%" PRIx64 ",%s %s\n",
                           info->vcpu, info->regs->cr3, procname, str2.contents);
                    break;
                };

                g_free(str2.contents);
            }

            free(str.contents);
            free(procname);
            //printf("Requesting to free writetrap @ %p\n", info->trap);
            info->trap->data=f;
            drakvuf_remove_trap(drakvuf, info->trap, free_writetrap);
        }
Example #5
0
status_t
init_kdversion_block(
    vmi_instance_t vmi)
{
    addr_t KdVersionBlock_phys = 0;
    addr_t DebuggerDataList = 0, ListPtr = 0;
    windows_instance_t windows = NULL;

    if (vmi->os_data == NULL) {
        return VMI_FAILURE;
    }

    windows = vmi->os_data;

    KdVersionBlock_phys = find_kdversionblock_address_fast(vmi);
    //KdVersionBlock_phys = find_kdversionblock_address(vmi);
    if (!KdVersionBlock_phys) {
        goto error_exit;
    }

    // get the virtual address for KdVersionBlock from the physical
    if (VMI_FAILURE ==
        vmi_read_addr_pa(vmi, KdVersionBlock_phys, &DebuggerDataList)) {
        goto error_exit;
    }
    if (VMI_FAILURE ==
        vmi_read_addr_va(vmi, DebuggerDataList, 0, &ListPtr)) {
        goto error_exit;
    }

    if (ListPtr && !windows->kdversion_block) {
        windows->kdversion_block = ListPtr;
        printf
            ("LibVMI Suggestion: set win_kdvb=0x%"PRIx64" in libvmi.conf for faster startup.\n",
             windows->kdversion_block);
    }
    dbprint("**set KdVersionBlock address=0x%"PRIx64"\n",
            windows->kdversion_block);

    return VMI_SUCCESS;

error_exit:
    return VMI_FAILURE;
}
Example #6
0
void carve_file_from_memory(drakvuf_t *drakvuf, addr_t ph_base,
        addr_t block_size) {

    addr_t aligned_file_size = struct_sizes[FILE_OBJECT];
    if(PM2BIT(drakvuf->pm) == BIT32) {
        // 8-byte alignment on 32-bit mode
        if(struct_sizes[FILE_OBJECT] % 8) {
            aligned_file_size += 8 - (struct_sizes[FILE_OBJECT] % 8);
        }
    } else {
        // 16-byte alignment on 64-bit mode
        if(struct_sizes[FILE_OBJECT] % 16) {
            aligned_file_size += 16 - (struct_sizes[FILE_OBJECT] % 16);
        }
    }

    addr_t file_base = ph_base + block_size - aligned_file_size;
    addr_t file_name = file_base + offsets[FILE_OBJECT_FILENAME];

    addr_t file_name_str = 0;
    uint16_t length = 0;

    vmi_read_addr_pa(drakvuf->vmi, file_name + offsets[UNICODE_STRING_BUFFER], &file_name_str);
    vmi_read_16_pa(drakvuf->vmi, file_name + offsets[UNICODE_STRING_LENGTH], &length);

    if (file_name_str && length) {
        unicode_string_t str = { .contents = NULL };
        str.length = length;
        str.encoding = "UTF-16";
        str.contents = malloc(length);
        vmi_read_va(drakvuf->vmi, file_name, 0, str.contents, length);
        unicode_string_t str2 = { .contents = NULL };
        status_t rc = vmi_convert_str_encoding(&str, &str2, "UTF-8");

        if (VMI_SUCCESS == rc) {
            PRINT_DEBUG("\tFile closing: %s.\n", str2.contents);
            volatility_extract_file(drakvuf, file_base);
            g_free(str2.contents);
        }

        free(str.contents);
    }
Example #7
0
status_t linux_init (vmi_instance_t vmi)
{
    status_t ret = VMI_FAILURE;

    if (vmi->cr3){
        vmi->kpgd = vmi->cr3;
    }
    else if (VMI_SUCCESS == linux_system_map_symbol_to_address(vmi, "swapper_pg_dir", &vmi->kpgd)){
        dbprint("--got vaddr for swapper_pg_dir (0x%.16llx).\n", vmi->kpgd);
        if (driver_is_pv(vmi)){
            vmi->kpgd = vmi_translate_kv2p(vmi, vmi->kpgd);
            if (vmi_read_addr_pa(vmi, vmi->kpgd, &(vmi->kpgd)) == VMI_FAILURE){
                errprint("Failed to get physical addr for kpgd.\n");
                goto _exit;
            }
        }
        else{
            vmi->kpgd = vmi_translate_kv2p(vmi, vmi->kpgd);
        }
    }
    else{
        errprint("swapper_pg_dir not found and CR3 not set, exiting\n");
        goto _exit;
    }

    vmi->kpgd = vmi->cr3;
    dbprint("**set vmi->kpgd (0x%.16llx).\n", vmi->kpgd);

    addr_t address = vmi_translate_ksym2v(vmi, "init_task");
    address += vmi->os.linux_instance.tasks_offset;
    if (VMI_FAILURE == vmi_read_addr_va(vmi, address, 0, &(vmi->init_task))){
        errprint("Failed to get task list head 'init_task'.\n");
        goto _exit;
    }

    ret = VMI_SUCCESS;
_exit:
    return ret;
}
Example #8
0
File: core.c Project: dalevy/libvmi
static status_t
init_from_rekall_profile(vmi_instance_t vmi)
{

    status_t ret = VMI_FAILURE;
    windows_instance_t windows = vmi->os_data;
    dbprint(VMI_DEBUG_MISC, "**Trying to init from Rekall profile\n");

    reg_t kpcr = 0;
    addr_t kpcr_rva = 0;

    // try to find the kernel if we are not connecting to a file and the kernel pa/va were not already specified.
    if(vmi->mode != VMI_FILE && ! ( windows->ntoskrnl && windows->ntoskrnl_va ) ) {

        switch ( vmi->page_mode ) {
            case VMI_PM_IA32E:
                if (VMI_FAILURE == driver_get_vcpureg(vmi, &kpcr, GS_BASE, 0))
                    goto done;
                break;
            case VMI_PM_LEGACY: /* Fall-through */
            case VMI_PM_PAE:
                if (VMI_FAILURE == driver_get_vcpureg(vmi, &kpcr, FS_BASE, 0))
                    goto done;
                break;
            default:
                goto done;
        };

        if (VMI_SUCCESS == rekall_profile_symbol_to_rva(windows->rekall_profile, "KiInitialPCR", NULL, &kpcr_rva)) {
            if ( kpcr <= kpcr_rva || vmi->page_mode == VMI_PM_IA32E && kpcr < 0xffff800000000000 ) {
                dbprint(VMI_DEBUG_MISC, "**vCPU0 doesn't seem to have KiInitialPCR mapped, can't init from Rekall profile.\n");
                goto done;
            }

            // If the Rekall profile has KiInitialPCR we have Win 7+
            windows->ntoskrnl_va = kpcr - kpcr_rva;
            windows->ntoskrnl = vmi_translate_kv2p(vmi, windows->ntoskrnl_va);
        } else if(kpcr == 0x00000000ffdff000) {
            // If we are in live mode without KiInitialPCR, the KPCR has to be
            // at this VA (XP/Vista) and the KPCR trick [1] is still valid.
            // [1] http://moyix.blogspot.de/2008/04/finding-kernel-global-variables-in.html
            addr_t kdvb = 0, kdvb_offset = 0, kernbase_offset = 0;
            rekall_profile_symbol_to_rva(windows->rekall_profile, "_KPCR", "KdVersionBlock", &kdvb_offset);
            rekall_profile_symbol_to_rva(windows->rekall_profile, "_DBGKD_GET_VERSION64", "KernBase", &kernbase_offset);
            vmi_read_addr_va(vmi, kpcr+kdvb_offset, 0, &kdvb);
            vmi_read_addr_va(vmi, kdvb+kernbase_offset, 0, &windows->ntoskrnl_va);
            windows->ntoskrnl = vmi_translate_kv2p(vmi, windows->ntoskrnl_va);
        } else {
            goto done;
        }

        dbprint(VMI_DEBUG_MISC, "**KernBase PA=0x%"PRIx64"\n", windows->ntoskrnl);

        /*
         * If the CR3 value points to a pagetable that hasn't been setup yet
         * we need to resort to finding a valid pagetable the old fashioned way.
         */
        if (windows->ntoskrnl_va && !windows->ntoskrnl)
        {
            windows_find_cr3(vmi);
            windows->ntoskrnl = vmi_translate_kv2p(vmi, windows->ntoskrnl_va);
        }
    }

    // This could happen if we are in file mode or for Win XP
    if (!windows->ntoskrnl) {

        windows->ntoskrnl = get_ntoskrnl_base(vmi, vmi->kpgd);

        // get KdVersionBlock/"_DBGKD_GET_VERSION64"->KernBase
        addr_t kdvb = 0, kernbase_offset = 0;
        rekall_profile_symbol_to_rva(windows->rekall_profile, "KdVersionBlock", NULL, &kdvb);
        rekall_profile_symbol_to_rva(windows->rekall_profile, "_DBGKD_GET_VERSION64", "KernBase", &kernbase_offset);

        dbprint(VMI_DEBUG_MISC, "**KdVersionBlock RVA 0x%lx. KernBase RVA: 0x%lx\n", kdvb, kernbase_offset);
        dbprint(VMI_DEBUG_MISC, "**KernBase PA=0x%"PRIx64"\n", windows->ntoskrnl);

        if (windows->ntoskrnl && kdvb && kernbase_offset) {
            vmi_read_addr_pa(vmi, windows->ntoskrnl + kdvb + kernbase_offset, &windows->ntoskrnl_va);

            if(!windows->ntoskrnl_va) {
                vmi_read_32_pa(vmi, windows->ntoskrnl + kdvb + kernbase_offset, (uint32_t*)&windows->ntoskrnl_va);
            }

            if(!windows->ntoskrnl_va) {
                dbprint(VMI_DEBUG_MISC, "**failed to find Windows kernel VA via KdVersionBlock\n");
                goto done;
            }
        } else {
            dbprint(VMI_DEBUG_MISC, "**Failed to find required offsets and/or kernel base PA\n");
            goto done;
        }
    }

    dbprint(VMI_DEBUG_MISC, "**KernBase VA=0x%"PRIx64"\n", windows->ntoskrnl_va);

    addr_t ntbuildnumber_rva;
    uint16_t ntbuildnumber = 0;

    // Let's do some sanity checking
    if (VMI_FAILURE == rekall_profile_symbol_to_rva(windows->rekall_profile, "NtBuildNumber", NULL, &ntbuildnumber_rva)) {
        goto done;
    }
    if (VMI_FAILURE == vmi_read_16_pa(vmi, windows->ntoskrnl + ntbuildnumber_rva, &ntbuildnumber)) {
        goto done;
    }

    if (ntbuild2version(ntbuildnumber) == VMI_OS_WINDOWS_UNKNOWN) {
        dbprint(VMI_DEBUG_MISC, "Unknown Windows NtBuildNumber: %u, the Rekall Profile may be incorrect for this Windows!\n", ntbuildnumber);
    }

    // The system map seems to be good, lets grab all the required offsets
    if(!windows->pdbase_offset) {
        if (VMI_FAILURE == rekall_profile_symbol_to_rva(windows->rekall_profile, "_KPROCESS", "DirectoryTableBase", &windows->pdbase_offset)) {
            goto done;
        }
    }
    if(!windows->tasks_offset) {
        if (VMI_FAILURE == rekall_profile_symbol_to_rva(windows->rekall_profile, "_EPROCESS", "ActiveProcessLinks", &windows->tasks_offset)) {
            goto done;
        }
    }
    if(!windows->pid_offset) {
        if (VMI_FAILURE == rekall_profile_symbol_to_rva(windows->rekall_profile, "_EPROCESS", "UniqueProcessId", &windows->pid_offset)) {
            goto done;
        }
    }
    if(!windows->pname_offset) {
        if (VMI_FAILURE == rekall_profile_symbol_to_rva(windows->rekall_profile, "_EPROCESS", "ImageFileName", &windows->pname_offset)) {
            goto done;
        }
    }

    ret = VMI_SUCCESS;
    dbprint(VMI_DEBUG_MISC, "**init from Rekall profile success\n");

    done: return ret;

}
Example #9
0
File: core.c Project: dalevy/libvmi
static status_t
get_kpgd_method0(
    vmi_instance_t vmi)
{
    addr_t sysproc_va = 0;
    addr_t sysproc_pa = 0;
    addr_t active_process_head = 0;
    windows_instance_t windows = NULL;
    vmi_pid_t pid = 4;
    size_t len = sizeof(vmi_pid_t);
    addr_t kpgd = 0;

    if (vmi->os_data == NULL) {
        errprint("VMI_ERROR: No OS data initialized\n");
        return VMI_FAILURE;
    }

    windows = vmi->os_data;

    if (VMI_FAILURE == vmi_read_addr_ksym(vmi, "PsActiveProcessHead", &active_process_head)) {
        dbprint(VMI_DEBUG_MISC, "--failed to resolve PsActiveProcessHead\n");
        goto error_exit;
    }

    dbprint(VMI_DEBUG_MISC, "--starting search from PsActiveProcessHead (0x%.16"PRIx64") using kpgd (0x%.16"PRIx64").\n",
            active_process_head, vmi->kpgd);

    sysproc_va = eprocess_list_search(vmi, active_process_head - windows->tasks_offset, windows->pid_offset, len, &pid);

    if (sysproc_va == 0) {
        dbprint(VMI_DEBUG_MISC, "--failed to find system process with pid 4\n");
        goto error_exit;
    }

    sysproc_va -= windows->tasks_offset;
    dbprint(VMI_DEBUG_MISC, "--Found System process at %lx\n", sysproc_va);
    sysproc_pa = vmi_translate_kv2p(vmi, sysproc_va);

    if (sysproc_pa == 0) {
        dbprint(VMI_DEBUG_MISC, "--failed to translate System process\n");
        goto error_exit;
    }

    dbprint(VMI_DEBUG_MISC, "--Found System process physical address at %lx\n", sysproc_pa);

    if (VMI_FAILURE ==
        vmi_read_addr_pa(vmi,
                         sysproc_pa +
                         windows->pdbase_offset,
                         &kpgd)) {
        dbprint(VMI_DEBUG_MISC, "--failed to resolve pointer for system process\n");
        goto error_exit;
    }

    if (!kpgd) {
        dbprint(VMI_DEBUG_MISC, "--kpgd was zero\n");
        goto error_exit;
    }
    vmi->kpgd = kpgd;
    dbprint(VMI_DEBUG_MISC, "**set kpgd (0x%.16"PRIx64").\n", vmi->kpgd);

    vmi->init_task = sysproc_va;
    dbprint(VMI_DEBUG_MISC, "**set init_task (0x%.16"PRIx64").\n", vmi->init_task);

    return VMI_SUCCESS;

error_exit:
    return VMI_FAILURE;
}
Example #10
0
static status_t
init_from_sysmap(vmi_instance_t vmi)
{

    status_t ret = VMI_FAILURE;
    windows_instance_t windows = vmi->os_data;
    dbprint(VMI_DEBUG_MISC, "**Trying to init from sysmap\n");

    reg_t kpcr = 0;
    addr_t kpcr_rva = 0;

    if(vmi->mode != VMI_FILE) {

        if (vmi->page_mode == VMI_PM_IA32E) {
            if (VMI_FAILURE == driver_get_vcpureg(vmi, &kpcr, GS_BASE, 0)) {
                goto done;
            }
        } else if (vmi->page_mode == VMI_PM_LEGACY || vmi->page_mode == VMI_PM_PAE) {
            if (VMI_FAILURE == driver_get_vcpureg(vmi, &kpcr, FS_BASE, 0)) {
                goto done;
            }
        }

        if (VMI_SUCCESS == windows_system_map_symbol_to_address(vmi, "KiInitialPCR", NULL, &kpcr_rva)) {
            // If the sysmap has KiInitialPCR we have Win 7+
            windows->ntoskrnl_va = kpcr - kpcr_rva;
            windows->ntoskrnl = vmi_translate_kv2p(vmi, windows->ntoskrnl_va);
        } else if(kpcr == 0x00000000ffdff000) {
            // If we are in live mode without KiInitialPCR, the KPCR has to be
            // at this VA (XP/Vista) and the KPCR trick [1] is still valid.
            // [1] http://moyix.blogspot.de/2008/04/finding-kernel-global-variables-in.html
            addr_t kdvb = 0, kdvb_offset = 0, kernbase_offset = 0;
            windows_system_map_symbol_to_address(vmi, "_KPCR", "KdVersionBlock", &kdvb_offset);
            windows_system_map_symbol_to_address(vmi, "_DBGKD_GET_VERSION64", "KernBase", &kernbase_offset);
            vmi_read_addr_va(vmi, kpcr+kdvb_offset, 0, &kdvb);
            vmi_read_addr_va(vmi, kdvb+kernbase_offset, 0, &windows->ntoskrnl_va);
            windows->ntoskrnl = vmi_translate_kv2p(vmi, windows->ntoskrnl_va);
        } else {
            goto done;
        }

        dbprint(VMI_DEBUG_MISC, "**KernBase PA=0x%"PRIx64"\n", windows->ntoskrnl);

    }

    // This could happen if we are in file mode or for Win XP
    if (!windows->ntoskrnl) {

        windows->ntoskrnl = get_ntoskrnl_base(vmi, vmi->kpgd);

        // get KdVersionBlock/"_DBGKD_GET_VERSION64"->KernBase
        addr_t kdvb = 0, kernbase_offset = 0;
        windows_system_map_symbol_to_address(vmi, "KdVersionBlock", NULL, &kdvb);
        windows_system_map_symbol_to_address(vmi, "_DBGKD_GET_VERSION64", "KernBase", &kernbase_offset);

        dbprint(VMI_DEBUG_MISC, "**KdVersionBlock RVA 0x%lx. KernBase RVA: 0x%lx\n", kdvb, kernbase_offset);
        dbprint(VMI_DEBUG_MISC, "**KernBase PA=0x%"PRIx64"\n", windows->ntoskrnl);

        if (windows->ntoskrnl && kdvb && kernbase_offset) {
            vmi_read_addr_pa(vmi, windows->ntoskrnl + kdvb + kernbase_offset, &windows->ntoskrnl_va);

            if(!windows->ntoskrnl_va) {
                vmi_read_32_pa(vmi, windows->ntoskrnl + kdvb + kernbase_offset, (uint32_t*)&windows->ntoskrnl_va);
            }

            if(!windows->ntoskrnl_va) {
                dbprint(VMI_DEBUG_MISC, "**failed to find Windows kernel VA via KdVersionBlock\n");
                goto done;
            }
        } else {
            dbprint(VMI_DEBUG_MISC, "**Failed to find required offsets and/or kernel base PA\n");
            goto done;
        }
    }

    dbprint(VMI_DEBUG_MISC, "**KernBase VA=0x%"PRIx64"\n", windows->ntoskrnl_va);

    addr_t ntbuildnumber_rva;
    uint16_t ntbuildnumber = 0;

    // Let's do some sanity checking
    if (VMI_FAILURE == windows_system_map_symbol_to_address(vmi, "NtBuildNumber", NULL, &ntbuildnumber_rva)) {
        goto done;
    }
    if (VMI_FAILURE == vmi_read_16_pa(vmi, windows->ntoskrnl + ntbuildnumber_rva, &ntbuildnumber)) {
        goto done;
    }

    if (ntbuild2version(ntbuildnumber) == VMI_OS_WINDOWS_UNKNOWN) {
        dbprint(VMI_DEBUG_MISC, "Unknown Windows NtBuildNumber: %u. The Rekall Profile may be incorrect for this Windows!\n", ntbuildnumber);
        goto done;
    }

    // The system map seems to be good, lets grab all the required offsets
    if(!windows->pdbase_offset) {
        if (VMI_FAILURE == windows_system_map_symbol_to_address(vmi, "_KPROCESS", "DirectoryTableBase", &windows->pdbase_offset)) {
            goto done;
        }
    }
    if(!windows->tasks_offset) {
        if (VMI_FAILURE == windows_system_map_symbol_to_address(vmi, "_EPROCESS", "ActiveProcessLinks", &windows->tasks_offset)) {
            goto done;
        }
    }
    if(!windows->pid_offset) {
        if (VMI_FAILURE == windows_system_map_symbol_to_address(vmi, "_EPROCESS", "UniqueProcessId", &windows->pid_offset)) {
            goto done;
        }
    }
    if(!windows->pname_offset) {
        if (VMI_FAILURE == windows_system_map_symbol_to_address(vmi, "_EPROCESS", "ImageFileName", &windows->pname_offset)) {
            goto done;
        }
    }

    ret = VMI_SUCCESS;
    dbprint(VMI_DEBUG_MISC, "**init from sysmap success\n");

    done: return ret;

}
Example #11
0
status_t linux_init(vmi_instance_t vmi) {
    status_t ret = VMI_FAILURE;
    os_interface_t os_interface = NULL;

    if (vmi->config == NULL) {
        errprint("VMI_ERROR: No config table found\n");
        return VMI_FAILURE;
    }

    if (vmi->os_data != NULL) {
        errprint("VMI_ERROR: os data already initialized, reinitializing\n");
        free(vmi->os_data);
    }

    vmi->os_data = safe_malloc(sizeof(struct linux_instance));
    bzero(vmi->os_data, sizeof(struct linux_instance));

    g_hash_table_foreach(vmi->config, (GHFunc)linux_read_config_ghashtable_entries, vmi);

    if (VMI_SUCCESS
            == linux_system_map_symbol_to_address(vmi, "swapper_pg_dir", NULL,
                    &vmi->kpgd)) {
        dbprint("--got vaddr for swapper_pg_dir (0x%.16"PRIx64").\n",
                vmi->kpgd);
        if (driver_is_pv(vmi)) {
            vmi->kpgd = vmi_translate_kv2p(vmi, vmi->kpgd);
            if (vmi_read_addr_pa(vmi, vmi->kpgd, &(vmi->kpgd)) == VMI_FAILURE) {
                errprint(
                        "Failed to get physical addr for kpgd using swapper_pg_dir.\n");
            }
        }
    }

    if (!vmi->kpgd) {
        ret = driver_get_vcpureg(vmi, &vmi->kpgd, CR3, 0);
        if (ret != VMI_SUCCESS) {
            errprint(
                    "Driver does not support cr3 read and kpgd could not be set, exiting\n");
            goto _exit;
        }
    }

    dbprint("**set vmi->kpgd (0x%.16"PRIx64").\n", vmi->kpgd);

    ret = linux_system_map_symbol_to_address(vmi, "init_task", NULL,
            &vmi->init_task);
    if (ret != VMI_SUCCESS) {
        errprint("VMI_ERROR: Could not get init_task from System.map\n");
        return ret;
    }

    os_interface = safe_malloc(sizeof(struct os_interface));
    bzero(os_interface, sizeof(struct os_interface));
    os_interface->os_get_offset = linux_get_offset;
    os_interface->os_pid_to_pgd = linux_pid_to_pgd;
    os_interface->os_pgd_to_pid = linux_pgd_to_pid;
    os_interface->os_ksym2v = linux_system_map_symbol_to_address;
    os_interface->os_usym2rva = NULL;
    os_interface->os_rva2sym = NULL;
    os_interface->os_teardown = linux_teardown;

    vmi->os_interface = os_interface;

    _exit: return ret;
}
Example #12
0
File: kdbg.c Project: bentau/libvmi
/*
 * This functions is responsible for setting up
 * Windows specific variables:
 *  - ntoskrnl (*)
 *  - ntoskrnl_va (*)
 *  - kdbg_offset (*)
 *  - kdbg_va (*)
 * The variables marked with (*) can be also specified
 * in the libvmi config.
 */
status_t
init_from_kdbg(
    vmi_instance_t vmi)
{
    status_t ret = VMI_FAILURE;
    addr_t kernbase_pa = 0;
    addr_t kernbase_va = 0;
    addr_t kdbg_pa = 0;

    if (vmi->os_data == NULL) {
        goto exit;
    }

    windows_instance_t windows = vmi->os_data;

    /* If all 3 values are specified in the config, we can calculate ntoskrnl_va,
     * but can't verify if there is no arch for doing translations.
     */
    if (windows->kdbg_va && windows->kdbg_offset && windows->ntoskrnl
            && !vmi->arch_interface) {
        /* All values were user specified, so set them, but we can't use
         * translations to verify them */
        windows->ntoskrnl_va = windows->kdbg_va - windows->kdbg_offset;
        goto done;
    }

    if (!vmi->arch_interface) {
        /* nothing that requires a virtual-to-physical translation will work
         * so skip straight to the physical only methods. */
        goto find_kdbg;
    }

    /* Otherwise, look up what we need and check for consistency */

    if (windows->kdbg_va) {
        dbprint(VMI_DEBUG_MISC, "**using KdDebuggerDataBlock address=0x%"PRIx64" from config\n",
                windows->kdbg_va);

        if (VMI_SUCCESS != windows_kdbg_lookup(vmi, "KernBase", &windows->ntoskrnl_va)) {
            dbprint(VMI_DEBUG_MISC, "**Error reading KernBase value, falling back to search methods\n");
            goto find_kdbg;
        }

        dbprint(VMI_DEBUG_MISC, "**KernBase VA=0x%"PRIx64"\n", windows->ntoskrnl_va);

        if (windows->kdbg_offset) {
            /* only needed ntoskrnl_va, verify the other values */
            if (windows->kdbg_va != (windows->ntoskrnl_va + windows->kdbg_offset)) {
                errprint("Invalid configuration values for win_kdvb and win_kdbg\n");
                goto exit;
            }

        } else {
            windows->kdbg_offset = windows->kdbg_va - windows->ntoskrnl_va;
        }
    } else if (windows->ntoskrnl && windows->kdbg_offset) {
        /* Calculate ntoskrnl_va and kdbg_va */
        unsigned long offset = 0;
        kdbg_symbol_offset("KernBase", &offset);
        if (VMI_FAILURE == vmi_read_addr_pa(vmi, windows->ntoskrnl + windows->kdbg_offset + offset, &windows->ntoskrnl_va)) {
            errprint("Inconsistent addresses passed in the config!\n");
            goto exit;
        }

        dbprint(VMI_DEBUG_MISC, "**KernBase VA=0x%"PRIx64"\n", windows->ntoskrnl_va);

        windows->kdbg_va = windows->ntoskrnl_va - windows->kdbg_offset;
        dbprint(VMI_DEBUG_MISC, "**set KdDebuggerDataBlock address=0x%"PRIx64"\n",
                windows->kdbg_va);
    } else {
        /* only ntoskrnl or kdbg_offset were given, which are not
         * enough to find and calculate the others, so fall back to search methods. */
        goto find_kdbg;
    }

    addr_t test = 0;

    if (!windows->ntoskrnl) {
        if ( VMI_FAILURE == vmi_translate_kv2p(vmi, windows->ntoskrnl_va, &windows->ntoskrnl) )
            goto find_kdbg;

        dbprint(VMI_DEBUG_MISC, "**set KernBase PA=0x%"PRIx64"\n", windows->ntoskrnl);
    } else if (VMI_FAILURE == vmi_translate_kv2p(vmi, windows->ntoskrnl_va, &test) || test != windows->ntoskrnl) {
        errprint("Invalid configuration values, win_ntoskrnl not match translated KernBase physical address\n");
        goto exit;
    }

    goto done;

    // We don't have the standard config informations
    // so lets try our kdbg search method
find_kdbg:
    dbprint(VMI_DEBUG_MISC, "**Attempting KdDebuggerDataBlock search methods\n");

    if (VMI_SUCCESS == find_kdbg_address_instant(vmi, &kdbg_pa, &kernbase_pa, &kernbase_va)) {
        goto found;
    }
    if (VMI_SUCCESS == find_kdbg_address_faster(vmi, &kdbg_pa, &kernbase_pa, &kernbase_va)) {
        goto found;
    }
    if (VMI_SUCCESS == find_kdbg_address_fast(vmi, &kdbg_pa, &kernbase_pa, &kernbase_va)) {
        goto found;
    }

    /* NOTE: This is the only method that does anything for VMI_FILE */
    if (VMI_SUCCESS == find_kdbg_address(vmi, &kdbg_pa, &kernbase_va)) {
        kernbase_pa = get_ntoskrnl_base(vmi, 0);
        goto found;
    }

    dbprint(VMI_DEBUG_MISC, "**All KdDebuggerDataBlock search methods failed\n");
    goto exit;

found:
    windows->ntoskrnl_va = kernbase_va;
    dbprint(VMI_DEBUG_MISC, "**set KernBase VA=0x%"PRIx64"\n", windows->ntoskrnl_va);

    if (!windows->ntoskrnl) {
        windows->ntoskrnl = kernbase_pa;
        printf("LibVMI Suggestion: set win_ntoskrnl=0x%"PRIx64" in libvmi.conf for faster startup.\n",
               windows->ntoskrnl);
    } else if (windows->ntoskrnl != kernbase_pa) {
        errprint("LibVMI found physical kernel base address 0x%"PRIx64" that conflicts with provided value from config file!\n",
                 kernbase_pa);
        goto exit;
    }

    if (!windows->kdbg_offset) {
        windows->kdbg_offset = kdbg_pa - windows->ntoskrnl;
        printf("LibVMI Suggestion: set win_kdbg=0x%"PRIx64" in libvmi.conf for faster startup.\n",
               windows->kdbg_offset);
    } else if (windows->kdbg_offset != kdbg_pa - kernbase_pa) {
        errprint("LibVMI found win_kdbg offset 0x%"PRIx64" that conflicts with provided value from config file!\n",
                 kdbg_pa - kernbase_pa);
        goto exit;
    }

    if (!windows->kdbg_va) {
        windows->kdbg_va = windows->ntoskrnl_va + windows->kdbg_offset;
        printf("LibVMI Suggestion: set win_kdvb=0x%"PRIx64" in libvmi.conf for faster startup.\n",
               windows->kdbg_va);
    } else if (windows->kdbg_va != windows->ntoskrnl_va + windows->kdbg_offset) {
        errprint("LibVMI found win_kdvb offset 0x%"PRIx64" that conflicts with provided value from config file!\n",
                 windows->ntoskrnl_va + windows->kdbg_offset);
        goto exit;
    }

done:
    if (!kdbg_pa) {
        kdbg_pa = windows->ntoskrnl + windows->kdbg_offset;
    }
    windows->version = find_windows_version(vmi, kdbg_pa);
    if (VMI_OS_WINDOWS_UNKNOWN == windows->version) {
        errprint("Unsupported Windows version or incorrect configuration\n");
    }

    ret = VMI_SUCCESS;
exit:
    return ret;
}