Exemple #1
0
// Idea from http://gleeda.blogspot.com/2010/12/identifying-memory-images.html
win_ver_t
find_windows_version(
    vmi_instance_t vmi,
    addr_t KdVersionBlock)
{
    windows_instance_t windows = NULL;

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

    windows = vmi->os_data;

    // no need to repeat this work if we already have the answer
    if (windows->version &&
        windows->version != VMI_OS_WINDOWS_UNKNOWN) {
        return windows->version;
    }

    uint16_t size = 0;

    vmi_read_16_pa(vmi, KdVersionBlock + 0x14, &size);

    if (memcmp(&size, "\x08\x02", 2) == 0) {
        dbprint("--OS Guess: Windows 2000\n");
        return VMI_OS_WINDOWS_2000;
    }
    else if (memcmp(&size, "\x90\x02", 2) == 0) {
        dbprint("--OS Guess: Windows XP\n");
        return VMI_OS_WINDOWS_XP;
    }
    else if (memcmp(&size, "\x18\x03", 2) == 0) {
        dbprint("--OS Guess: Windows 2003\n");
        return VMI_OS_WINDOWS_2003;
    }
    else if (memcmp(&size, "\x28\x03", 2) == 0) {
        dbprint("--OS Guess: Windows Vista\n");
        return VMI_OS_WINDOWS_VISTA;
    }
    else if (memcmp(&size, "\x30\x03", 2) == 0) {
        dbprint("--OS Guess: Windows 2008\n");
        return VMI_OS_WINDOWS_2008;
    }
    else if (memcmp(&size, "\x40\x03", 2) == 0) {
        dbprint("--OS Guess: Windows 7\n");
        return VMI_OS_WINDOWS_7;
    }
    else {
        dbprint("--OS Guess: Unknown (0x%.4x)\n", size);
        return VMI_OS_WINDOWS_UNKNOWN;
    }
}
Exemple #2
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);
        }
Exemple #3
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);
    }
Exemple #4
0
// Idea from http://gleeda.blogspot.com/2010/12/identifying-memory-images.html
win_ver_t
find_windows_version(
    vmi_instance_t vmi,
    addr_t kdbg)
{

    windows_instance_t windows = NULL;

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

    windows = vmi->os_data;

    // no need to repeat this work if we already have the answer
    if (windows->version &&
            windows->version != VMI_OS_WINDOWS_UNKNOWN) {
        return windows->version;
    }

    win_ver_t version = VMI_OS_WINDOWS_UNKNOWN;
    vmi_read_16_pa(vmi, kdbg + 0x14, (uint16_t*)&version);

    // Check if it's a version we know about.
    // The known KDBG magic values are defined in win_ver_t
    switch (version) {
        case VMI_OS_WINDOWS_2000:
        case VMI_OS_WINDOWS_XP:
        case VMI_OS_WINDOWS_2003:
        case VMI_OS_WINDOWS_VISTA:
        case VMI_OS_WINDOWS_2008:
        case VMI_OS_WINDOWS_7:
        case VMI_OS_WINDOWS_8:
            break;
        default:
            version = VMI_OS_WINDOWS_UNKNOWN;
            break;
    }

    return version;
}
Exemple #5
0
// Idea from http://gleeda.blogspot.com/2010/12/identifying-memory-images.html
void find_windows_version (vmi_instance_t vmi, addr_t KdVersionBlock)
{
    // no need to repeat this work if we already have the answer
    if (vmi->os.windows_instance.version && vmi->os.windows_instance.version != VMI_OS_WINDOWS_UNKNOWN){
        return;
    }

    // go find the answer and store it in vmi
    uint16_t size = 0;
    vmi_read_16_pa(vmi, KdVersionBlock + 0x14, &size);

    if (memcmp(&size, "\x08\x02", 2) == 0){
        dbprint("--OS Guess: Windows 2000\n");
        vmi->os.windows_instance.version = VMI_OS_WINDOWS_2000;
    }
    else if (memcmp(&size, "\x90\x02", 2) == 0){
        dbprint("--OS Guess: Windows XP\n");
        vmi->os.windows_instance.version = VMI_OS_WINDOWS_XP;
    }
    else if (memcmp(&size, "\x18\x03", 2) == 0){
        dbprint("--OS Guess: Windows 2003\n");
        vmi->os.windows_instance.version = VMI_OS_WINDOWS_2003;
    }
    else if (memcmp(&size, "\x28\x03", 2) == 0){
        dbprint("--OS Guess: Windows Vista\n");
        vmi->os.windows_instance.version = VMI_OS_WINDOWS_VISTA;
    }
    else if (memcmp(&size, "\x30\x03", 2) == 0){
        dbprint("--OS Guess: Windows 2008\n");
        vmi->os.windows_instance.version = VMI_OS_WINDOWS_2008;
    }
    else if (memcmp(&size, "\x40\x03", 2) == 0){
        dbprint("--OS Guess: Windows 7\n");
        vmi->os.windows_instance.version = VMI_OS_WINDOWS_7;
    }
    else{
        dbprint("--OS Guess: Unknown (0x%.4x)\n", size);
        vmi->os.windows_instance.version = VMI_OS_WINDOWS_UNKNOWN;
    }
}
Exemple #6
0
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;

}
Exemple #7
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;

}