Beispiel #1
0
addr_t v2p_ia32e (vmi_instance_t vmi,
    addr_t dtb,
    addr_t vaddr,
    page_info_t *info)
{
    uint64_t pml4e = 0, pdpte = 0, pde = 0, pte = 0;

    // are we in compatibility mode OR 64-bit mode ???

    // validate address based on above (e.g., is it canonical?)

    // determine what MAXPHYADDR is

    dbprint(VMI_DEBUG_PTLOOKUP, "--PTLookup: lookup vaddr = 0x%.16"PRIx64"\n", vaddr);
    dbprint(VMI_DEBUG_PTLOOKUP, "--PTLookup: dtb = 0x%.16"PRIx64"\n", dtb);
    pml4e = get_pml4e(vmi, vaddr, dtb, &info->l4_a);
    dbprint(VMI_DEBUG_PTLOOKUP, "--PTLookup: pml4e = 0x%.16"PRIx64"\n", pml4e);

    if (ENTRY_PRESENT(vmi->os_type, pml4e)) {
        info->l4_v = pml4e;

        pdpte = get_pdpte_ia32e(vmi, vaddr, pml4e, &info->l3_a);
        dbprint(VMI_DEBUG_PTLOOKUP, "--PTLookup: pdpte = 0x%.16"PRIx64"\n", pdpte);

        if (ENTRY_PRESENT(vmi->os_type, pdpte)) {
            info->l3_v = pdpte;
            if (PAGE_SIZE_FLAG(pdpte)) { // pdpte maps a 1GB page
                info->paddr = get_gigpage_ia32e(vaddr, pdpte);
                info->size = VMI_PS_1GB;
                dbprint(VMI_DEBUG_PTLOOKUP, "--PTLookup: 1GB page\n");
            }
            else {
                pde = get_pde_ia32e(vmi, vaddr, pdpte, &info->l2_a);
                dbprint(VMI_DEBUG_PTLOOKUP, "--PTLookup: pde = 0x%.16"PRIx64"\n", pde);
            }

            if (ENTRY_PRESENT(vmi->os_type, pde)) {
                info->l2_v = pde;
                if (PAGE_SIZE_FLAG(pde)) { // pde maps a 2MB page
                    info->paddr = get_2megpage_ia32e(vaddr, pde);
                    info->size = VMI_PS_2MB;
                    dbprint(VMI_DEBUG_PTLOOKUP, "--PTLookup: 2MB page\n");
                }
                else {
                    pte = get_pte_ia32e(vmi, vaddr, pde, &info->l1_a);
                    dbprint(VMI_DEBUG_PTLOOKUP, "--PTLookup: pte = 0x%.16"PRIx64"\n", pte);
                }

                if (ENTRY_PRESENT(vmi->os_type, pte)) {
                    info->l1_v = pte;
                    info->size = VMI_PS_4KB;
                    info->paddr = get_paddr_ia32e(vaddr, pte);
                }
            }
        }
    }

    dbprint(VMI_DEBUG_PTLOOKUP, "--PTLookup: paddr = 0x%.16"PRIx64"\n", info->paddr);
    return info->paddr;
}
Beispiel #2
0
static void extract_ca_file(filedelete* f,
                            drakvuf_t drakvuf,
                            const drakvuf_trap_info_t* info,
                            vmi_instance_t vmi,
                            addr_t control_area,
                            access_context_t* ctx,
                            const char* filename,
                            uint64_t fo_flags)
{
    addr_t subsection = control_area + f->control_area_size;
    addr_t segment = 0;
    addr_t test = 0;
    addr_t test2 = 0;
    size_t filesize = 0;

    /* Check whether subsection points back to the control area */
    ctx->addr = control_area + f->offsets[CONTROL_AREA_SEGMENT];
    if ( VMI_FAILURE == vmi_read_addr(vmi, ctx, &segment) )
        return;

    ctx->addr = segment + f->offsets[SEGMENT_CONTROLAREA];
    if ( VMI_FAILURE == vmi_read_addr(vmi, ctx, &test) || test != control_area )
        return;

    ctx->addr = segment + f->offsets[SEGMENT_SIZEOFSEGMENT];
    if ( VMI_FAILURE == vmi_read_64(vmi, ctx, &test) )
        return;

    ctx->addr = segment + f->offsets[SEGMENT_TOTALNUMBEROFPTES];
    if ( VMI_FAILURE == vmi_read_32(vmi, ctx, (uint32_t*)&test2) )
        return;

    if ( test != (test2 * 4096) )
        return;

    const int curr_sequence_number = ++f->sequence_number;

    char* file = NULL;
    if ( asprintf(&file, "%s/file.%06d.mm", f->dump_folder, curr_sequence_number) < 0 )
        return;

    FILE* fp = fopen(file, "w");
    free(file);
    if (!fp)
        return;

    while (subsection)
    {
        /* Check whether subsection points back to the control area */
        ctx->addr = subsection + f->offsets[SUBSECTION_CONTROLAREA];
        if ( VMI_FAILURE == vmi_read_addr(vmi, ctx, &test) || test != control_area )
            break;

        addr_t base = 0;
        addr_t start = 0;
        uint32_t ptes = 0;

        ctx->addr = subsection + f->offsets[SUBSECTION_SUBSECTIONBASE];
        if ( VMI_FAILURE == vmi_read_addr(vmi, ctx, &base) )
            break;

        ctx->addr = subsection + f->offsets[SUBSECTION_PTESINSUBSECTION];
        if ( VMI_FAILURE == vmi_read_32(vmi, ctx, &ptes) )
            break;

        ctx->addr = subsection + f->offsets[SUBSECTION_STARTINGSECTOR];
        if ( VMI_FAILURE == vmi_read_32(vmi, ctx, (uint32_t*)&start) )
            break;

        /*
         * The offset into the file is stored implicitely
         * based on the PTE's location within the Subsection.
         */
        addr_t subsection_offset = start * 0x200;
        addr_t ptecount;
        for (ptecount=0; ptecount < ptes; ptecount++)
        {
            addr_t pteoffset = base + f->mmpte_size * ptecount;
            addr_t fileoffset = subsection_offset + ptecount * 0x1000;

            addr_t pte = 0;
            ctx->addr = pteoffset;
            if ( VMI_FAILURE == vmi_read(vmi, ctx, f->mmpte_size, &pte, NULL) )
                break;

            if ( ENTRY_PRESENT(1, pte) )
            {
                uint8_t page[4096];

                if ( VMI_FAILURE == vmi_read_pa(vmi, VMI_BIT_MASK(12,48) & pte, 4096, &page, NULL) )
                    continue;

                if ( !fseek ( fp, fileoffset, SEEK_SET ) )
                {
                    if ( fwrite(page, 4096, 1, fp) )
                        filesize = MAX(filesize, fileoffset + 4096);
                }
            }
        }

        ctx->addr = subsection + f->offsets[SUBSECTION_NEXTSUBSECTION];
        if ( !vmi_read_addr(vmi, ctx, &subsection) )
            break;
    }

    fclose(fp);

    print_extraction_information(f, drakvuf, info, filename, filesize, fo_flags, curr_sequence_number);
    save_file_metadata(f, info, curr_sequence_number, control_area, filename, filesize, fo_flags);
}
Beispiel #3
0
GSList* get_va_pages_ia32e(vmi_instance_t vmi, addr_t dtb) {

    GSList *ret = NULL;
    uint8_t entry_size = 0x8;

    #define PDES_AND_PTES_PER_PAGE 0x200 // 0x1000/0x8

    uint64_t pml4e;
    for(pml4e=0;pml4e<PDES_AND_PTES_PER_PAGE;pml4e++) {

        addr_t vaddr = pml4e << 39;
        addr_t pml4e_a = 0;
        uint64_t pml4e_value = get_pml4e(vmi, vaddr, dtb, &pml4e_a);

        if(!ENTRY_PRESENT(vmi->os_type, pml4e_value)) {
            continue;
        }

        uint64_t pdpte;
        for(pdpte=0;pdpte<PDES_AND_PTES_PER_PAGE;pdpte++) {

            vaddr = (pml4e << 39) | (pdpte << 30);

            addr_t pdpte_a = 0;
            uint64_t pdpte_value = get_pdpte_ia32e(vmi, vaddr, pml4e_value, &pdpte_a);
            if(!ENTRY_PRESENT(vmi->os_type, pdpte_value)) {
                continue;
            }

            if(PAGE_SIZE_FLAG(pdpte_value)) {
                page_info_t *p = g_malloc0(sizeof(page_info_t));
                p->vaddr = vaddr;
                p->paddr = get_gigpage_ia32e(vaddr, pdpte_value);
                p->size = VMI_PS_1GB;
                p->l4_a = pml4e_a;
                p->l4_v = pml4e_value;
                p->l3_a = pdpte_a;
                p->l3_v = pdpte_value;
                ret = g_slist_append(ret, p);
                continue;
            }

            uint64_t pgd_curr = pdba_base_ia32e(pdpte_value);
            uint64_t j;
            for(j=0;j<PTRS_PER_PAE_PGD;j++,pgd_curr+=entry_size) {

                uint64_t soffset = vaddr + (j * PTRS_PER_PAE_PGD * PTRS_PER_PAE_PTE * entry_size);

                uint64_t entry;
                if(VMI_FAILURE == vmi_read_64_pa(vmi, pgd_curr, &entry)) {
                    continue;
                }

                if(ENTRY_PRESENT(vmi->os_type, entry)) {

                    if(PAGE_SIZE_FLAG(entry)) {
                        page_info_t *p = g_malloc0(sizeof(page_info_t));
                        p->vaddr = soffset;
                        p->paddr = get_2megpage_ia32e(vaddr, entry);
                        p->size = VMI_PS_2MB;
                        p->l4_a = pml4e_a;
                        p->l4_v = pml4e_value;
                        p->l3_a = pdpte_a;
                        p->l3_v = pdpte_value;
                        p->l2_a = pgd_curr;
                        p->l2_v = entry;
                        ret = g_slist_append(ret, p);
                        continue;
                    }

                    uint64_t pte_curr = pte_pfn_ia32e(entry);
                    uint64_t k;
                    for(k=0;k<PTRS_PER_PAE_PTE;k++,pte_curr+=entry_size) {
                        uint64_t pte_entry;
                        if(VMI_FAILURE == vmi_read_64_pa(vmi, pte_curr, &pte_entry)) {
                            continue;
                        }

                        if(ENTRY_PRESENT(vmi->os_type, pte_entry)) {
                            page_info_t *p = g_malloc0(sizeof(page_info_t));
                            p->vaddr = soffset + k * VMI_PS_4KB;
                            p->paddr = get_paddr_ia32e(vaddr, pte_entry);
                            p->size = VMI_PS_4KB;
                            p->l4_a = pml4e_a;
                            p->l4_v = pml4e_value;
                            p->l3_a = pdpte_a;
                            p->l3_v = pdpte_value;
                            p->l2_a = pgd_curr;
                            p->l2_v = entry;
                            p->l1_a = pte_curr;
                            p->l1_v = pte_entry;
                            ret = g_slist_append(ret, p);
                            continue;
                        }
                    }
                }
            }
        }
    }

    return ret;
}
Beispiel #4
0
GSList* get_va_pages_ia32e(vmi_instance_t vmi, addr_t dtb) {

    GSList *ret = NULL;
    uint8_t entry_size = 0x8;

    #define IA32E_ENTRIES_PER_PAGE 0x200 // 0x1000/0x8

    uint64_t *pml4_page = malloc(VMI_PS_4KB);

    addr_t pml4e_location = dtb & VMI_BIT_MASK(12,51);
    if (VMI_PS_4KB != vmi_read_pa(vmi, pml4e_location, pml4_page, VMI_PS_4KB)) {
        free(pml4_page);
        return ret;
    }

    uint64_t *pdpt_page = malloc(VMI_PS_4KB);
    uint64_t *pgd_page = malloc(VMI_PS_4KB);
    uint64_t *pt_page = malloc(VMI_PS_4KB);

    uint64_t pml4e_index;
    for(pml4e_index = 0; pml4e_index < IA32E_ENTRIES_PER_PAGE; pml4e_index++, pml4e_location += entry_size) {

        uint64_t pml4e_value = pml4_page[pml4e_index];

        if(!ENTRY_PRESENT(vmi->os_type, pml4e_value)) {
            continue;
        }

        uint64_t pdpte_location = pml4e_value & VMI_BIT_MASK(12,51);

        if (VMI_PS_4KB != vmi_read_pa(vmi, pdpte_location, pdpt_page, VMI_PS_4KB)) {
            continue;
        }

        uint64_t pdpte_index;
        for(pdpte_index = 0; pdpte_index < IA32E_ENTRIES_PER_PAGE; pdpte_index++, pdpte_location++) {

            uint64_t pdpte_value = pdpt_page[pdpte_index];

            if(!ENTRY_PRESENT(vmi->os_type, pdpte_value)) {
                continue;
            }

            if(PAGE_SIZE(pdpte_value)) {
                page_info_t *info = g_malloc0(sizeof(page_info_t));
                info->vaddr = (pml4e_index << 39) | (pdpte_index << 30);
                info->paddr = get_gigpage_ia32e(info->vaddr, pdpte_value);
                info->size = VMI_PS_1GB;
                info->x86_ia32e.pml4e_location = pml4e_location;
                info->x86_ia32e.pml4e_value = pml4e_value;
                info->x86_ia32e.pdpte_location = pdpte_location;
                info->x86_ia32e.pdpte_value = pdpte_value;
                ret = g_slist_prepend(ret, info);
                continue;
            }

            uint64_t pgd_location = pdpte_value & VMI_BIT_MASK(12,51);

            if (VMI_PS_4KB != vmi_read_pa(vmi, pgd_location, pgd_page, VMI_PS_4KB)) {
                continue;
            }

            uint64_t pgde_index;
            for(pgde_index = 0; pgde_index < IA32E_ENTRIES_PER_PAGE; pgde_index++, pgd_location += entry_size) {

                uint64_t pgd_value = pgd_page[pgde_index];

                if(ENTRY_PRESENT(vmi->os_type, pgd_value)) {

                    if(PAGE_SIZE(pgd_value)) {
                        page_info_t *info = g_malloc0(sizeof(page_info_t));
                        info->vaddr = (pml4e_index << 39) | (pdpte_index << 30) |
                                        (pgde_index << 21);
                        info->paddr = get_2megpage_ia32e(info->vaddr, pgd_value);
                        info->size = VMI_PS_2MB;
                        info->x86_ia32e.pml4e_location = pml4e_location;
                        info->x86_ia32e.pml4e_value = pml4e_value;
                        info->x86_ia32e.pdpte_location = pdpte_location;
                        info->x86_ia32e.pdpte_value = pdpte_value;
                        info->x86_ia32e.pgd_location = pgd_location;
                        info->x86_ia32e.pgd_value = pgd_value;
                        ret = g_slist_prepend(ret, info);
                        continue;
                    }

                    uint64_t pte_location = (pgd_value & VMI_BIT_MASK(12,51));
                    if (VMI_PS_4KB != vmi_read_pa(vmi, pte_location, pt_page, VMI_PS_4KB)) {
                        continue;
                    }

                    uint64_t pte_index;
                    for(pte_index = 0; pte_index < IA32E_ENTRIES_PER_PAGE; pte_index++, pte_location += entry_size) {
                        uint64_t pte_value = pt_page[pte_index];

                        if(ENTRY_PRESENT(vmi->os_type, pte_value)) {
                            page_info_t *info = g_malloc0(sizeof(page_info_t));
                            info->vaddr = (pml4e_index << 39) | (pdpte_index << 30) |
                                            (pgde_index << 21) | (pte_index << 12);
                            info->paddr = get_paddr_ia32e(info->vaddr, pte_value);
                            info->size = VMI_PS_4KB;
                            info->x86_ia32e.pml4e_location = pml4e_location;
                            info->x86_ia32e.pml4e_value = pml4e_value;
                            info->x86_ia32e.pdpte_location = pdpte_location;
                            info->x86_ia32e.pdpte_value = pdpte_value;
                            info->x86_ia32e.pgd_location = pgd_location;
                            info->x86_ia32e.pgd_value = pgd_value;
                            info->x86_ia32e.pte_location = pte_location;
                            info->x86_ia32e.pte_value = pte_value;
                            ret = g_slist_prepend(ret, info);
                            continue;
                        }
                    }
                }
            }
        }
    }

    free(pt_page);
    free(pgd_page);
    free(pdpt_page);
    free(pml4_page);

    return ret;
}
Beispiel #5
0
status_t v2p_ia32e (vmi_instance_t vmi,
    addr_t dtb,
    addr_t vaddr,
    page_info_t *info)
{
    status_t status = VMI_FAILURE;

    // are we in compatibility mode OR 64-bit mode ???

    // validate address based on above (e.g., is it canonical?)

    // determine what MAXPHYADDR is

    dbprint(VMI_DEBUG_PTLOOKUP, "--PTLookup: lookup vaddr = 0x%.16"PRIx64"\n", vaddr);
    dbprint(VMI_DEBUG_PTLOOKUP, "--PTLookup: dtb = 0x%.16"PRIx64"\n", dtb);

    status = get_pml4e(vmi, vaddr, dtb, &info->x86_ia32e.pml4e_location, &info->x86_ia32e.pml4e_value);
    if (status != VMI_SUCCESS) {
        goto done;
    }

    if (!ENTRY_PRESENT(vmi->os_type, info->x86_ia32e.pml4e_value)) {
        status = VMI_FAILURE;
        goto done;
    }

    status = get_pdpte_ia32e(vmi, vaddr, info->x86_ia32e.pml4e_value, &info->x86_ia32e.pdpte_location,
                             &info->x86_ia32e.pdpte_value);
    if (status != VMI_SUCCESS) {
        goto done;
    }

    if (!ENTRY_PRESENT(vmi->os_type, info->x86_ia32e.pdpte_value)) {
        status = VMI_FAILURE;
        goto done;
    }

    if (PAGE_SIZE(info->x86_ia32e.pdpte_value)) { // pdpte maps a 1GB page
        info->size = VMI_PS_1GB;
        info->paddr = get_gigpage_ia32e(vaddr, info->x86_ia32e.pdpte_value);
        status = VMI_SUCCESS;
        dbprint(VMI_DEBUG_PTLOOKUP, "--PTLookup: 1GB page\n");
        goto done;
    }

    status = get_pde_ia32e(vmi, vaddr, info->x86_ia32e.pdpte_value, &info->x86_ia32e.pgd_location,
                           &info->x86_ia32e.pgd_value);
    if (status != VMI_SUCCESS) {
        goto done;
    }

    if (!ENTRY_PRESENT(vmi->os_type, info->x86_ia32e.pgd_value)) {
        status = VMI_FAILURE;
        goto done;
    }

    if (PAGE_SIZE(info->x86_ia32e.pgd_value)) { // pde maps a 2MB page
        info->size = VMI_PS_2MB;
        info->paddr = get_2megpage_ia32e(vaddr, info->x86_ia32e.pgd_value);
        status = VMI_SUCCESS;
        dbprint(VMI_DEBUG_PTLOOKUP, "--PTLookup: 2MB page\n");
        goto done;
    }

    status = get_pte_ia32e(vmi, vaddr, info->x86_ia32e.pgd_value, &info->x86_ia32e.pte_location,
                           &info->x86_ia32e.pte_value);
    if (status != VMI_SUCCESS) {
        goto done;
    }

    if (!ENTRY_PRESENT(vmi->os_type, info->x86_ia32e.pte_value)) {
        status = VMI_FAILURE;
        goto done;
    }

    info->size = VMI_PS_4KB;
    info->paddr = get_paddr_ia32e(vaddr, info->x86_ia32e.pte_value);
    status = VMI_SUCCESS;

done:
    dbprint(VMI_DEBUG_PTLOOKUP, "--PTLookup: paddr = 0x%.16"PRIx64"\n", info->paddr);
    return status;
}