Ejemplo n.º 1
0
bool kernel_debug_search(vmi_instance_t vmi, struct cv_info_pdb70 *pdb_header) {
    addr_t i;
    for(i=0; i < max_mem; i += PAGE_SIZE) {
        uint8_t pe[VMI_PS_4KB];
        if ( VMI_FAILURE == vmi_read_pa(vmi, i, VMI_PS_4KB, pe, NULL) )
            continue;

        uint32_t c;
        for (c=0;c<VMI_PS_4KB-PDB_FILENAME_LENGTH;c++) {
            if(!strncmp((char*)&pe[c], "ntkrnlmp.pdb", PDB_FILENAME_LENGTH) ||
               !strncmp((char*)&pe[c], "ntoskrnl.pdb", PDB_FILENAME_LENGTH) ||
               !strncmp((char*)&pe[c], "ntkrnlpa.pdb", PDB_FILENAME_LENGTH) ||
               !strncmp((char*)&pe[c], "ntkrpamp.pdb", PDB_FILENAME_LENGTH)
            ) {
                if ( VMI_FAILURE == vmi_read_pa(vmi, i+c - 2*sizeof(uint32_t) - sizeof(struct guid), sizeof(struct cv_info_pdb70)+PDB_FILENAME_LENGTH, pdb_header,NULL) )
                    continue;

                if ( pdb_header->cv_signature != RSDS)
                    continue;
                else
                    return 1;
            }
        }
    }
    return 0;
}
Ejemplo n.º 2
0
int
find_pname_offset(
    vmi_instance_t vmi,
    check_magic_func check)
{
    addr_t block_pa = 0;
    addr_t offset = 0;
    uint32_t value = 0;
    void *bm = 0;

    bm = boyer_moore_init((unsigned char *)"Idle", 4);

#define BLOCK_SIZE 1024 * 1024 * 1
    unsigned char block_buffer[BLOCK_SIZE];

    if (NULL == check) {
        check = get_check_magic_func(vmi);
    }

    for (block_pa = 4096; block_pa + BLOCK_SIZE < vmi->max_physical_address; block_pa += BLOCK_SIZE) {
        if ( VMI_FAILURE == vmi_read_pa(vmi, block_pa, BLOCK_SIZE, block_buffer, NULL) ) {
            continue;
        }

        for (offset = 0; offset < BLOCK_SIZE; offset += 8) {
            memcpy(&value, block_buffer + offset, 4);

            if (check(value)) { // look for specific magic #
                dbprint
                    (VMI_DEBUG_MISC, "--%s: found magic value 0x%.8"PRIx32" @ offset 0x%.8"PRIx64"\n",
                     __FUNCTION__, value, block_pa + offset);

                unsigned char haystack[0x500];

                if ( VMI_FAILURE == vmi_read_pa(vmi, block_pa + offset, 0x500, haystack, NULL) ) {
                    continue;
                }

                int i = boyer_moore2(bm, haystack, 0x500);

                if (-1 == i) {
                    continue;
                }
                else {
                    vmi->init_task = block_pa + offset;
                    dbprint
                        (VMI_DEBUG_MISC, "--%s: found Idle process at 0x%.8"PRIx64" + 0x%x\n",
                         __FUNCTION__, block_pa + offset, i);
                    boyer_moore_fini(bm);
                    return i;
                }
            }
        }
    }
    boyer_moore_fini(bm);
    return 0;
}
Ejemplo n.º 3
0
Archivo: core.c Proyecto: dalevy/libvmi
addr_t
get_ntoskrnl_base(
    vmi_instance_t vmi,
    addr_t page_paddr)
{
    uint8_t page[VMI_PS_4KB];
    addr_t ret = 0;
    access_context_t ctx = {
        .translate_mechanism = VMI_TM_NONE,
        .addr = page_paddr
    };

    for(; ctx.addr + VMI_PS_4KB < vmi->max_physical_address; ctx.addr += VMI_PS_4KB) {

        uint8_t page[VMI_PS_4KB];
        if(VMI_FAILURE == peparse_get_image(vmi, &ctx, VMI_PS_4KB, page))
            continue;

        struct pe_header *pe_header = NULL;
        struct dos_header *dos_header = NULL;
        void *optional_pe_header = NULL;
        uint16_t optional_header_type = 0;
        struct export_table et;

        peparse_assign_headers(page, &dos_header, &pe_header, &optional_header_type, &optional_pe_header, NULL, NULL);
        addr_t export_header_offset =
            peparse_get_idd_rva(IMAGE_DIRECTORY_ENTRY_EXPORT, &optional_header_type, optional_pe_header, NULL, NULL);

        if(!export_header_offset || ctx.addr + export_header_offset >= vmi->max_physical_address)
            continue;

        uint32_t nbytes = vmi_read_pa(vmi, ctx.addr + export_header_offset, &et, sizeof(struct export_table));
        if(nbytes == sizeof(struct export_table) && !(et.export_flags || !et.name) ) {

            if(ctx.addr + et.name + 12 >= vmi->max_physical_address) {
                continue;
            }

            unsigned char name[13] = {0};
            vmi_read_pa(vmi, ctx.addr + et.name, name, 12);
            if(!strcmp("ntoskrnl.exe", (char*)name)) {
                ret = ctx.addr;
                break;
            }
        } else {
            continue;
        }
    }

    return ret;
}
Ejemplo n.º 4
0
addr_t
get_ntoskrnl_base(
    vmi_instance_t vmi,
    addr_t page_paddr)
{
    uint8_t page[VMI_PS_4KB];
    addr_t ret = 0;

    for(; page_paddr + VMI_PS_4KB < vmi->size; page_paddr += VMI_PS_4KB) {

        uint8_t page[VMI_PS_4KB];
        status_t rc = peparse_get_image_phys(vmi, page_paddr, VMI_PS_4KB, page);
        if(VMI_FAILURE == rc) {
            continue;
        }

        struct pe_header *pe_header = NULL;
        struct dos_header *dos_header = NULL;
        void *optional_pe_header = NULL;
        uint16_t optional_header_type = 0;
        struct export_table et;

        peparse_assign_headers(page, &dos_header, &pe_header, &optional_header_type, &optional_pe_header, NULL, NULL);
        addr_t export_header_offset =
            peparse_get_idd_rva(IMAGE_DIRECTORY_ENTRY_EXPORT, &optional_header_type, optional_pe_header, NULL, NULL);

        if(!export_header_offset || page_paddr + export_header_offset > vmi->size)
            continue;

        uint32_t nbytes = vmi_read_pa(vmi, page_paddr + export_header_offset, &et, sizeof(struct export_table));
        if(nbytes == sizeof(struct export_table) && !(et.export_flags || !et.name) ) {

            if(page_paddr + et.name + 12 > vmi->size) {
                continue;
            }

            unsigned char name[13] = {0};
            vmi_read_pa(vmi, page_paddr + et.name, name, 12);
            if(!strcmp("ntoskrnl.exe", (char*)name)) {
                ret = page_paddr;
                break;
            }
        } else {
            continue;
        }
    }

    return ret;
}
Ejemplo n.º 5
0
status_t check_sections(vmi_instance_t vmi, addr_t image_base_p, uint8_t *pe) {

    struct pe_header *pe_header = NULL;
    struct dos_header *dos_header = NULL;
    uint16_t optional_header_type = 0;
    peparse_assign_headers(pe, &dos_header, &pe_header, &optional_header_type, NULL, NULL, NULL);

    uint32_t c;
    for(c=0; c < pe_header->number_of_sections; c++) {

        struct section_header section;
        addr_t section_addr = image_base_p
            + dos_header->offset_to_pe
            + sizeof(struct pe_header)
            + pe_header->size_of_optional_header
            + c*sizeof(struct section_header);

        // Read the section from memory
        if ( VMI_FAILURE == vmi_read_pa(vmi, section_addr, sizeof(struct section_header), (uint8_t *)&section, NULL) )
            return VMI_FAILURE;

        //printf("S: %s\n", section.short_name);

        // The character array is not null terminated, so only print the first 8 characters!
        if ( !strncmp(section.short_name, "INITKDBG", 8) )
            return VMI_SUCCESS;
    }

    return VMI_FAILURE;
}
Ejemplo n.º 6
0
char *
windows_get_eprocess_name(
    vmi_instance_t vmi,
    addr_t paddr)
{
    size_t name_length = 16;   //TODO verify that this is correct for all versions
    windows_instance_t windows = vmi->os_data;

    if (windows == NULL) {
        return NULL;
    }

    addr_t name_paddr = paddr + windows->pname_offset;
    char *name = (char *) g_malloc0(name_length);

    if ( !name )
        return NULL;

    if ( VMI_FAILURE == vmi_read_pa(vmi, name_paddr, name_length, name, NULL)) {
        return name;
    }
    else {
        free(name);
        return NULL;
    }
}
Ejemplo n.º 7
0
static addr_t
find_kdversionblock_address(
    vmi_instance_t vmi)
{
    addr_t kdvb_address = 0;
    addr_t paddr = 0;
    unsigned char buf[12];

    for (paddr = 0; paddr < vmi_get_memsize(vmi); paddr += 4) {
        if (12 == vmi_read_pa(vmi, paddr, buf, 12)) {
            if (VMI_PM_IA32E == vmi->page_mode) {
                if (memcmp(buf, "\x00\xf8\xff\xffKDBG", 8) == 0) {
                    kdvb_address = paddr - 0xc;
                    break;
                }
            }
            else {
                if (memcmp
                    (buf, "\x00\x00\x00\x00\x00\x00\x00\x00KDBG",
                     12) == 0) {
                    kdvb_address = paddr - 0x8;
                    break;
                }
            }
        }
    }

    return kdvb_address;
}
Ejemplo n.º 8
0
void print_pe_header(vmi_instance_t vmi, addr_t image_base_p, uint8_t *pe) {

    struct pe_header *pe_header = NULL;
    struct dos_header *dos_header = NULL;
    uint16_t optional_header_type = 0;
    peparse_assign_headers(pe, &dos_header, &pe_header, &optional_header_type, NULL, NULL, NULL);

    printf("\tSignature: %u.\n", pe_header->signature);
    printf("\tMachine: %u.\n", pe_header->machine);
    printf("\t# of sections: %u.\n", pe_header->number_of_sections);
    printf("\t# of symbols: %u.\n", pe_header->number_of_symbols);
    printf("\tTimestamp: %u.\n", pe_header->time_date_stamp);
    printf("\tCharacteristics: %u.\n", pe_header->characteristics);
    printf("\tOptional header size: %u.\n", pe_header->size_of_optional_header);
    printf("\tOptional header type: 0x%x\n", optional_header_type);

    uint32_t c;
    for(c=0; c < pe_header->number_of_sections; c++) {

        struct section_header section;
        addr_t section_addr = image_base_p
            + dos_header->offset_to_pe
            + sizeof(struct pe_header)
            + pe_header->size_of_optional_header
            + c*sizeof(struct section_header);

        // Read the section from memory
        vmi_read_pa(vmi, section_addr, (uint8_t *)&section, sizeof(struct section_header));

        // The character array is not null terminated, so only print the first 8 characters!
        printf("\tSection %u: %.8s\n", c+1, section.short_name);
    }
}
Ejemplo n.º 9
0
status_t is_WINDOWS_KERNEL(vmi_instance_t vmi, addr_t base_p, uint8_t *pe) {

    status_t ret = VMI_FAILURE;

    void *optional_pe_header = NULL;
    uint16_t optional_header_type = 0;
    struct export_table et;

    peparse_assign_headers(pe, NULL, NULL, &optional_header_type, &optional_pe_header, NULL, NULL);
    addr_t export_header_offset = peparse_get_idd_rva(IMAGE_DIRECTORY_ENTRY_EXPORT, &optional_header_type, optional_pe_header, NULL, NULL);

    // The kernel's export table is continuously allocated on the PA level with the PE header
    // This trick may not work for other PE headers (though may work for some drivers)
    uint32_t nbytes = vmi_read_pa(vmi, base_p + export_header_offset, &et, sizeof(struct export_table));
    if(nbytes == sizeof(struct export_table) && !(et.export_flags || !et.name) ) {

        char *name = vmi_read_str_pa(vmi, base_p + et.name);

        if(name) {
            if(strcmp("ntoskrnl.exe", name)==0)
                ret = VMI_SUCCESS;

            free(name);
        }
    }

    return ret;
}
Ejemplo n.º 10
0
status_t
peparse_get_image_phys(
    vmi_instance_t vmi,
    addr_t base_paddr,
    size_t len,
    const uint8_t * const image)
{

    uint32_t nbytes = vmi_read_pa(vmi, base_paddr, (void *)image, len);

    if(nbytes != len) {
        dbprint(VMI_DEBUG_MISC, "--PEPARSE: failed to read a continuous PE header\n");
        return VMI_FAILURE;
    }

    if(VMI_SUCCESS != peparse_validate_pe_image(image, len)) {
        dbprint(VMI_DEBUG_MISC, "--PEPARSE: failed to validate a continuous PE header\n");
        if(vmi->init_mode & VMI_INIT_COMPLETE) {
            dbprint(VMI_DEBUG_MISC, "--PEPARSE: You might want to use peparse_get_image_virt here!\n");
        }

        return VMI_FAILURE;
    }

    return VMI_SUCCESS;
}
Ejemplo n.º 11
0
static int vmifs_read(const char *path, char *buf, size_t size, off_t offset,
                      struct fuse_file_info *fi)
{
    (void) fi;
    if(strcmp(path, mem_path) != 0)
        return -ENOENT;

    unsigned long memsize = vmi_get_memsize(vmi);
    if(offset < memsize && size) {
        if(offset + size > memsize)
            size = memsize-offset;

        uint8_t *buffer = g_malloc0(sizeof(uint8_t)*size);
        size_t size_read = vmi_read_pa(vmi, offset, buffer, size);

        if(size != size_read) {
            g_free(buffer);
        } else {
            memcpy(buf, buffer, size);
            g_free(buffer);
        }

    } else {
        return 0;
    }

    return size;
}
Ejemplo n.º 12
0
int main(int argc, char **argv) {

	vmi_instance_t vmi;
	addr_t start_address;
	struct timeval ktv_start;
	struct timeval ktv_end;

	char *vm = argv[1];
	int buf_size = atoi(argv[2]);
	int loops = atoi(argv[3]);
	int mode = atoi(argv[4]);
	unsigned char *buf = malloc(buf_size);

	int i = 0;
	long int diff;
	long int *data = malloc(loops * sizeof(long int));

	int j = 0;
	uint32_t value = 0;

	if (mode != 1 && mode != 2) {
		printf("invalid mode\n");
		return 1;
	}

	/* initialize the xen access library */
	vmi_init(&vmi, VMI_AUTO | VMI_INIT_COMPLETE, vm);

	/* find address to work from */
	start_address = vmi_translate_ksym2v(vmi, "PsInitialSystemProcess");
	start_address = vmi_translate_kv2p(vmi, start_address);

	for (i = 0; i < loops; ++i) {
		if (mode == 1) {
			gettimeofday(&ktv_start, 0);
			vmi_read_pa(vmi, start_address, buf, buf_size);
			gettimeofday(&ktv_end, 0);
		} else {
			gettimeofday(&ktv_start, 0);
			for (j = 0; j < buf_size / 4; ++j) {
				vmi_read_32_pa(vmi, start_address + j * 4, &value);
			}
			gettimeofday(&ktv_end, 0);
		}

		print_measurement(ktv_start, ktv_end, &diff);
		data[i] = diff;
		memset(buf, 0, buf_size);
		sleep(1);
	}

	avg_measurement(data, loops);

	vmi_destroy(vmi);
	free(buf);
	return 0;
}
Ejemplo n.º 13
0
static addr_t
find_kdversionblock_address_fast(
    vmi_instance_t vmi)
{
    // Note: this function has several limitations:
    // -the KD version block signature cannot cross block (frame) boundaries
    // -reading PA 0 fails; hope the KD version block is not in frame 0
    // 
    // Todo:
    // -support matching across frames (can this happen in windows?)

    addr_t kdvb_address = 0;
    addr_t block_pa = 0;
    addr_t memsize = vmi_get_memsize(vmi);
    size_t read = 0;
    void *bm = 0;   // boyer-moore internal state
    int find_ofs = 0;

#define BLOCK_SIZE 1024 * 1024 * 1
    unsigned char haystack[BLOCK_SIZE];

    if (VMI_PM_IA32E == vmi->page_mode) {
        bm = boyer_moore_init("\x00\xf8\xff\xffKDBG", 8);
        find_ofs = 0xc;
    }
    else {
        bm = boyer_moore_init("\x00\x00\x00\x00\x00\x00\x00\x00KDBG",
                              12);
        find_ofs = 0x8;
    }   // if-else

    for (block_pa = 4096; block_pa < memsize; block_pa += BLOCK_SIZE) {
        read = vmi_read_pa(vmi, block_pa, haystack, BLOCK_SIZE);
        if (BLOCK_SIZE != read) {
            continue;
        }

        int match_offset = boyer_moore2(bm, haystack, BLOCK_SIZE);

        if (-1 != match_offset) {
            kdvb_address =
                block_pa + (unsigned int) match_offset - find_ofs;
            break;
        }   // if
    }   // outer for

    if (kdvb_address)
        dbprint("--Found KD version block at PA %.16"PRIx64"\n",
                kdvb_address);
    boyer_moore_fini(bm);
    return kdvb_address;
}
Ejemplo n.º 14
0
char *
vmi_read_str_pa(
    vmi_instance_t vmi,
    addr_t paddr)
{
    char *rtnval = NULL;
    size_t chunk_size = vmi->page_size - ((vmi->page_size - 1) & paddr);
    char *buf = (char *) safe_malloc(chunk_size);

    // read in chunk of data
    if (chunk_size != vmi_read_pa(vmi, paddr, buf, chunk_size)) {
        goto exit;
    }

    // look for \0 character, expand as needed
    size_t len = strnlen(buf, chunk_size);
    size_t buf_size = chunk_size;

    while (len == buf_size) {
        size_t offset = buf_size;

        buf_size += chunk_size;
        buf = realloc(buf, buf_size);
        if (chunk_size !=
            vmi_read_pa(vmi, paddr + offset, buf + offset,
                        chunk_size)) {
            goto exit;
        }
        len = strnlen(buf, buf_size);
    }

    rtnval = (char *) safe_malloc(len + 1);
    memcpy(rtnval, buf, len);
    rtnval[len] = '\0';

exit:
    free(buf);
    return rtnval;
}
Ejemplo n.º 15
0
///////////////////////////////////////////////////////////
// Easy access to physical memory
static status_t
vmi_read_X_pa(
    vmi_instance_t vmi,
    addr_t paddr,
    void *value,
    int size)
{
    size_t len_read = vmi_read_pa(vmi, paddr, value, size);

    if (len_read == size) {
        return VMI_SUCCESS;
    }
    else {
        return VMI_FAILURE;
    }
}
Ejemplo n.º 16
0
char *
windows_get_eprocess_name(
    vmi_instance_t vmi,
    addr_t paddr)
{
    int name_length = 16;   //TODO verify that this is correct for all versions
    addr_t name_paddr = paddr + vmi->os.windows_instance.pname_offset;
    char *name = (char *) safe_malloc(name_length);

    if (name_length == vmi_read_pa(vmi, name_paddr, name, name_length)) {
        return name;
    }
    else {
        free(name);
        return NULL;
    }
}
Ejemplo n.º 17
0
static addr_t
find_process_by_name(
    vmi_instance_t vmi,
    check_magic_func check,
    addr_t start_address,
    const char *name)
{

    dbprint(VMI_DEBUG_MISC, "--searching for process by name: %s\n", name);

    addr_t block_pa = 0;
    addr_t offset = 0;
    uint32_t value = 0;
    size_t read = 0;

    unsigned char block_buffer[VMI_PS_4KB];

    if (NULL == check) {
        check = get_check_magic_func(vmi);
    }

    for (block_pa = start_address; block_pa + VMI_PS_4KB < vmi->max_physical_address;
         block_pa += VMI_PS_4KB) {
        read = vmi_read_pa(vmi, block_pa, block_buffer, VMI_PS_4KB);
        if (VMI_PS_4KB != read) {
            continue;
        }

        for (offset = 0; offset < VMI_PS_4KB; offset += 8) {
            memcpy(&value, block_buffer + offset, 4);

            if (check(value)) { // look for specific magic #

                char *procname = windows_get_eprocess_name(vmi, block_pa + offset);
                if (procname) {
                    if (strncmp(procname, name, 50) == 0) {
                        free(procname);
                        return block_pa + offset;
                    }
                    free(procname);
                }
            }
        }
    }
    return 0;
}
Ejemplo n.º 18
0
static addr_t
find_process_by_name(
    vmi_instance_t vmi,
    check_magic_func check,
    addr_t start_address,
    const char *name)
{
    addr_t block_pa = 0;
    addr_t offset = 0;
    uint32_t value = 0;
    size_t read = 0;

#define BLOCK_SIZE 1024 * 1024 * 1
    unsigned char block_buffer[BLOCK_SIZE];

    if (NULL == check) {
        check = get_check_magic_func(vmi);
    }

    for (block_pa = start_address; block_pa < vmi->size;
         block_pa += BLOCK_SIZE) {
        read = vmi_read_pa(vmi, block_pa, block_buffer, BLOCK_SIZE);
        if (BLOCK_SIZE != read) {
            continue;
        }

        for (offset = 0; offset < BLOCK_SIZE; offset += 8) {
            memcpy(&value, block_buffer + offset, 4);

            if (check(value)) { // look for specific magic #

                char *procname =
                    windows_get_eprocess_name(vmi, block_pa + offset);
                if (procname) {
                    if (strncmp(procname, name, 50) == 0) {
                        free(procname);
                        return block_pa + offset;
                    }
                    free(procname);
                }
            }
        }
    }
    return 0;
}
Ejemplo n.º 19
0
status_t is_WINDOWS_KERNEL(vmi_instance_t vmi, addr_t base_p, uint8_t *pe) {

    status_t ret = VMI_FAILURE;

    void *optional_pe_header = NULL;
    uint16_t optional_header_type = 0;
    struct export_table et;

    peparse_assign_headers(pe, NULL, NULL, &optional_header_type, &optional_pe_header, NULL, NULL);
    addr_t export_header_offset = peparse_get_idd_rva(IMAGE_DIRECTORY_ENTRY_EXPORT, &optional_header_type, optional_pe_header, NULL, NULL);

    // The kernel's export table is continuously allocated on the PA level with the PE header
    // This trick may not work for other PE headers (though may work for some drivers)
    if ( base_p + export_header_offset < base_p + VMI_PS_4KB ) {
        if( VMI_SUCCESS == vmi_read_pa(vmi, base_p + export_header_offset, sizeof(struct export_table), &et, NULL) &&
            !(et.export_flags || !et.name))
        {

            char *name = vmi_read_str_pa(vmi, base_p + et.name);

            if(name) {
                if(strcmp("ntoskrnl.exe", name)==0)
                    ret = VMI_SUCCESS;

                free(name);
            }
        }
    }

    // The export header may be stripped from the kernel so check section names.
    // This is commonly the case with Windows 10.
    if ( ret == VMI_FAILURE ) {
        ret = check_sections(vmi, base_p, pe);
    }

    return ret;
}
Ejemplo n.º 20
0
END_TEST

/* test vmi_get_dgpma */
// we use vmi_read_pa() to verify vmi_get_dgpma()
START_TEST (test_vmi_get_dgpma)
{
    vmi_instance_t vmi = NULL;
    vmi_init(&vmi, VMI_AUTO | VMI_INIT_COMPLETE, get_testvm());
    vmi_shm_snapshot_create(vmi);

    addr_t pa = 0x1000; // just because vmi_read_page() deny to fetch frame 0.
    size_t count = 4096;
    unsigned long max_size = vmi_get_max_physical_address(vmi);
    void *buf_readpa = malloc(count);
    void *buf_dgpma = NULL;
    for (; pa + count <= max_size; pa += count) {
        size_t read_pa = vmi_read_pa(vmi, pa, buf_readpa, count);
        size_t read_dgpma = vmi_get_dgpma(vmi, pa, &buf_dgpma, count);

        if (read_pa == 0 && read_dgpma == 0) {
            continue;
        }

        fail_unless(read_pa == read_dgpma, "vmi_get_dgpma(0x%"PRIx64
            ") read size %d dosn't conform to %d of vmi_read_pa()",
            pa, read_dgpma, read_pa);

        int cmp = memcmp(buf_readpa, buf_dgpma, read_pa);
        fail_unless(0 == cmp, "vmi_get_dgpma(0x%"PRIx64
            ") contents dosn't conform to vmi_read_pa()", pa);
    }
    free(buf_readpa);

    vmi_shm_snapshot_destroy(vmi);
    vmi_destroy(vmi);
}
Ejemplo n.º 21
0
Archivo: kdbg.c Proyecto: bentau/libvmi
status_t
find_kdbg_address_faster(
    vmi_instance_t vmi,
    addr_t *kdbg_pa,
    addr_t *kernel_pa,
    addr_t *kernel_va)
{

    dbprint(VMI_DEBUG_MISC, "**Trying find_kdbg_address_faster\n");

    status_t ret = VMI_FAILURE;

    // This scan requires the location of the KPCR
    // which we get from the GS/FS register on live machines.
    // For file mode this needs to be further investigated.
    if (VMI_FILE == vmi->mode) {
        return ret;
    }

    void *bm = boyer_moore_init((unsigned char *)"KDBG", 4);
    int find_ofs = 0x10;

    reg_t cr3 = 0, fsgs = 0;
    if (VMI_FAILURE == driver_get_vcpureg(vmi, &cr3, CR3, 0)) {
        goto done;
    }

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

    // We start the search from the KPCR, which has to be mapped into the kernel.
    // We further know that the Windows kernel is page aligned
    // so we are just checking if the page has a valid PE header
    // and if the first item in the export table is "ntoskrnl.exe".
    // Once the kernel is found, we find the .data section
    // and limit the string search for "KDBG" into that region.

    // start searching at the lower part from the kpcr
    // then switch to the upper part if needed
    int step = -VMI_PS_4KB;
    addr_t page_paddr;
    access_context_t ctx = {
        .translate_mechanism = VMI_TM_NONE,
    };

scan:
    if ( VMI_FAILURE == vmi_pagetable_lookup(vmi, cr3, fsgs, &page_paddr) )
        goto done;

    page_paddr &= ~VMI_BIT_MASK(0,11);

    for (; page_paddr + step < vmi->max_physical_address; page_paddr += step) {

        uint8_t page[VMI_PS_4KB];
        ctx.addr = page_paddr;
        status_t rc = peparse_get_image(vmi, &ctx, VMI_PS_4KB, page);
        if (VMI_FAILURE == rc) {
            continue;
        }

        struct pe_header *pe_header = NULL;
        struct dos_header *dos_header = NULL;
        void *optional_pe_header = NULL;
        uint16_t optional_header_type = 0;
        struct export_table et;

        peparse_assign_headers(page, &dos_header, &pe_header, &optional_header_type, &optional_pe_header, NULL, NULL);
        addr_t export_header_offset =
            peparse_get_idd_rva(IMAGE_DIRECTORY_ENTRY_EXPORT, &optional_header_type, optional_pe_header, NULL, NULL);

        if (!export_header_offset || page_paddr + export_header_offset >= vmi->max_physical_address)
            continue;

        if ( VMI_SUCCESS == vmi_read_pa(vmi, page_paddr + export_header_offset, sizeof(struct export_table), &et, NULL)) {
            if ( !(et.export_flags || !et.name) && page_paddr + et.name + 12 >= vmi->max_physical_address)
                continue;

            unsigned char name[13] = {0};
            if ( VMI_FAILURE == vmi_read_pa(vmi, page_paddr + et.name, 12, name, NULL) )
                continue;

            if (strcmp("ntoskrnl.exe", (const char *)name)) {
                continue;
            }
        } else {
            continue;
        }

        uint32_t c;
        for (c=0; c < pe_header->number_of_sections; c++) {

            struct section_header section;
            addr_t section_addr = page_paddr
                                  + dos_header->offset_to_pe
                                  + sizeof(struct pe_header)
                                  + pe_header->size_of_optional_header
                                  + c*sizeof(struct section_header);

            // Read the section header from memory
            if ( VMI_FAILURE == vmi_read_pa(vmi, section_addr, sizeof(struct section_header), (uint8_t *)&section, NULL) )
                continue;

            // .data check
            if (memcmp(section.short_name, "\x2E\x64\x61\x74\x61", 5) != 0) {
                continue;
            }

            uint8_t *haystack = alloca(section.size_of_raw_data);
            if ( VMI_FAILURE == vmi_read_pa(vmi, page_paddr + section.virtual_address, section.size_of_raw_data, haystack, NULL) )
                continue;

            int match_offset = boyer_moore2(bm, haystack, section.size_of_raw_data);

            if (-1 != match_offset) {
                // We found the structure, but let's verify it.
                // The kernel is always mapped into VA at the same offset
                // it is found on physical memory + the kernel boundary.

                // Read "KernBase" from the haystack
                uint64_t *kernbase = (uint64_t *)&haystack[(unsigned int) match_offset + sizeof(uint64_t)];
                int zeroes = __builtin_clzll(page_paddr);

                if ((*kernbase) << zeroes == page_paddr << zeroes) {

                    *kernel_pa = page_paddr;
                    *kernel_va = *kernbase;
                    *kdbg_pa = page_paddr + section.virtual_address + (unsigned int) match_offset - find_ofs;

                    ret = VMI_SUCCESS;

                    dbprint(VMI_DEBUG_MISC,
                            "--Found KdDebuggerDataBlock at PA %.16"PRIx64"\n", *kdbg_pa);

                    goto done;
                } else {
                    dbprint(VMI_DEBUG_MISC,
                            "--WARNING: KernBase in KdDebuggerDataBlock at PA %.16"PRIx64" doesn't point back to this page.\n",
                            page_paddr + section.virtual_address + (unsigned int) match_offset - find_ofs);
                }
            }

            break;
        }
    }

    if (step<0) {
        step = VMI_PS_4KB;
        goto scan;
    }

done:
    boyer_moore_fini(bm);
    return ret;
}
Ejemplo n.º 22
0
int
find_pname_offset(
    vmi_instance_t vmi,
    check_magic_func check)
{
    addr_t block_pa = 0;
    addr_t offset = 0;
    uint32_t value = 0;
    size_t read = 0;
    void *bm = 0;

    bm = boyer_moore_init("Idle", 4);

#define BLOCK_SIZE 1024 * 1024 * 1
    unsigned char block_buffer[BLOCK_SIZE];

    if (NULL == check) {
        check = get_check_magic_func(vmi);
    }

    for (block_pa = 4096; block_pa < vmi->size; block_pa += BLOCK_SIZE) {
        read = vmi_read_pa(vmi, block_pa, block_buffer, BLOCK_SIZE);
        if (BLOCK_SIZE != read) {
            continue;
        }

        for (offset = 0; offset < BLOCK_SIZE; offset += 8) {
            memcpy(&value, block_buffer + offset, 4);

            if (check(value)) { // look for specific magic #
                dbprint
                    ("--%s: found magic value 0x%.8"PRIx32" @ offset 0x%.8"PRIx64"\n",
                     __FUNCTION__, value, block_pa + offset);

                unsigned char haystack[0x500];

                read =
                    vmi_read_pa(vmi, block_pa + offset, haystack,
                                0x500);
                if (0x500 != read) {
                    continue;
                }

                int i = boyer_moore2(bm, haystack, 0x500);

                if (-1 == i) {
                    continue;
                }
                else {
                    vmi->init_task =
                        block_pa + offset +
                        vmi->os.windows_instance.tasks_offset;
                    dbprint
                        ("--%s: found Idle process at 0x%.8"PRIx64" + 0x%x\n",
                         __FUNCTION__, block_pa + offset, i);
                    boyer_moore_fini(bm);
                    return i;
                }
            }
        }
    }
    boyer_moore_fini(bm);
    return 0;
}
Ejemplo n.º 23
0
void print_guid(vmi_instance_t vmi, addr_t kernel_base_p, uint8_t* pe) {

    uint16_t major_os_version;
    uint16_t minor_os_version;
    uint32_t size_of_image;

    struct pe_header *pe_header = NULL;
    uint16_t optional_header_type = 0;
    struct optional_header_pe32 *oh32 = NULL;
    struct optional_header_pe32plus *oh32plus = NULL;

    peparse_assign_headers(pe, NULL, &pe_header, &optional_header_type, NULL, &oh32, &oh32plus);
    addr_t debug_offset = peparse_get_idd_rva(IMAGE_DIRECTORY_ENTRY_DEBUG, NULL, NULL, oh32, oh32plus);

    if(optional_header_type == IMAGE_PE32_MAGIC) {

        major_os_version=oh32->major_os_version;
        minor_os_version=oh32->minor_os_version;
        size_of_image=oh32->size_of_image;

    } else
    if(optional_header_type == IMAGE_PE32_PLUS_MAGIC) {

        major_os_version=oh32plus->major_os_version;
        minor_os_version=oh32plus->minor_os_version;
        size_of_image=oh32plus->size_of_image;

    }

    struct image_debug_directory debug_directory;
    vmi_read_pa(vmi, kernel_base_p + debug_offset, (uint8_t *)&debug_directory, sizeof(struct image_debug_directory));

    if(debug_directory.type == IMAGE_DEBUG_TYPE_MISC) {
        printf("This operating system uses .dbg instead of .pdb\n");

        if(major_os_version == 5 && minor_os_version == 0)
        {
            printf("GUID: %.8x%.8x\n",pe_header->time_date_stamp,size_of_image);
        }

        return;
    } else
    if(debug_directory.type != IMAGE_DEBUG_TYPE_CODEVIEW) {
        printf("The header is not in CodeView format, unable to deal with that!\n");
        return;
    }

    struct cv_info_pdb70 *pdb_header = malloc(debug_directory.size_of_data);
    vmi_read_pa(vmi, kernel_base_p + debug_directory.address_of_raw_data, pdb_header, debug_directory.size_of_data);

    // The PDB header has to be PDB 7.0
    // http://www.debuginfo.com/articles/debuginfomatch.html
    if(pdb_header->cv_signature != RSDS) {
       printf("The CodeView debug information has to be in PDB 7.0 for the kernel!\n");
       return;
    }

     printf("\tGUID: ");
     printf("%.8x", pdb_header->signature.data1);
     printf("%.4x", pdb_header->signature.data2);
     printf("%.4x", pdb_header->signature.data3);

     int c;
     for(c=0;c<8;c++) printf("%.2x", pdb_header->signature.data4[c]);

     printf("%.1x", pdb_header->age & 0xf);
     printf("\n");
     printf("\tKernel filename: %s\n", pdb_header->pdb_file_name);

     free(pdb_header);
}
Ejemplo n.º 24
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;
}
Ejemplo n.º 25
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);
}
Ejemplo n.º 26
0
int
main(
    int argc,
    char **argv)
{
    vmi_instance_t vmi;
    char *filename = NULL;
    FILE *f = NULL;
    unsigned char memory[PAGE_SIZE];
    unsigned char zeros[PAGE_SIZE];

    memset(zeros, 0, PAGE_SIZE);
    uint32_t offset = 0;
    addr_t address = 0;

    /* this is the VM or file that we are looking at */
    char *name = argv[1];

    /* this is the file name to write the memory image to */
    filename = strndup(argv[2], 50);

    /* initialize the libvmi library */
    if (vmi_init(&vmi, VMI_AUTO | VMI_INIT_PARTIAL, name) ==
        VMI_FAILURE) {
        printf("Failed to init LibVMI library.\n");
        goto error_exit;
    }

    /* open the file for writing */
    if ((f = fopen(filename, "w+")) == NULL) {
        printf("failed to open file for writing.\n");
        goto error_exit;
    }

    while (address < vmi_get_memsize(vmi)) {

        /* write memory to file */
        if (PAGE_SIZE == vmi_read_pa(vmi, address, memory, PAGE_SIZE)) {
            /* memory mapped, just write to file */
            size_t written = fwrite(memory, 1, PAGE_SIZE, f);

            if (written != PAGE_SIZE) {
                printf("failed to write memory to file.\n");
                goto error_exit;
            }
        }
        else {
            /* memory not mapped, write zeros to maintain offset */
            size_t written = fwrite(zeros, 1, PAGE_SIZE, f);

            if (written != PAGE_SIZE) {
                printf("failed to write zeros to file.\n");
                goto error_exit;
            }
        }

        /* move on to the next page */
        address += PAGE_SIZE;
    }

error_exit:
    if (f)
        fclose(f);

    /* cleanup any memory associated with the libvmi instance */
    vmi_destroy(vmi);

    return 0;
}
Ejemplo n.º 27
0
Archivo: kdbg.c Proyecto: bentau/libvmi
status_t find_kdbg_address(
    vmi_instance_t vmi,
    addr_t *kdbg_pa,
    addr_t *kernel_va)
{

    dbprint(VMI_DEBUG_MISC, "**Trying find_kdbg_address\n");

    status_t ret = VMI_FAILURE;
    *kdbg_pa = 0;
    addr_t paddr = 0;
    unsigned char haystack[VMI_PS_4KB];
    addr_t memsize = vmi_get_max_physical_address(vmi);

    void *bm64 = boyer_moore_init((unsigned char *)"\x00\xf8\xff\xffKDBG", 8);
    void *bm32 = boyer_moore_init((unsigned char *)"\x00\x00\x00\x00\x00\x00\x00\x00KDBG",
                                  12);
    uint32_t find_ofs_64 = 0xc, find_ofs_32 = 0x8, find_ofs = 0;

    for (; paddr<memsize; paddr+=VMI_PS_4KB) {

        find_ofs = 0;

        if (VMI_FAILURE == vmi_read_pa(vmi, paddr, VMI_PS_4KB, &haystack, NULL))
            continue;

        int match_offset = boyer_moore2(bm64, haystack, VMI_PS_4KB);
        if (-1 != match_offset) {
            find_ofs = find_ofs_64;
        } else {
            match_offset = boyer_moore2(bm32, haystack, VMI_PS_4KB);
        }

        if (-1 != match_offset) {

            if (!find_ofs) {
                find_ofs = find_ofs_32;
            }

            // Read "KernBase" from the haystack
            long unsigned int kernbase_offset = 0;
            kdbg_symbol_offset("KernBase", &kernbase_offset);

            if ( match_offset - find_ofs + kernbase_offset + sizeof(uint64_t) >= VMI_PS_4KB )
                continue;

            memcpy(kernel_va, &haystack[(unsigned int) match_offset - find_ofs + kernbase_offset], sizeof(uint64_t));
            *kdbg_pa = paddr + (unsigned int) match_offset - find_ofs;

            ret = VMI_SUCCESS;

            break;
        }
    }

    dbprint(VMI_DEBUG_MISC, "--Found KdDebuggerDataBlock at PA %.16"PRIx64"\n", *kdbg_pa);

    boyer_moore_fini(bm32);
    boyer_moore_fini(bm64);
    return ret;
}
Ejemplo n.º 28
0
Archivo: kdbg.c Proyecto: bentau/libvmi
status_t
find_kdbg_address_fast(
    vmi_instance_t vmi,
    addr_t *kdbg_pa,
    addr_t *kernel_pa,
    addr_t *kernel_va)
{

    dbprint(VMI_DEBUG_MISC, "**Trying find_kdbg_address_fast\n");

    status_t ret = VMI_FAILURE;
    reg_t cr3;
    if (VMI_FAILURE == driver_get_vcpureg(vmi, &cr3, CR3, 0)) {
        return ret;
    }

    addr_t memsize = vmi_get_max_physical_address(vmi);
    GSList *va_pages = vmi_get_va_pages(vmi, (addr_t)cr3);
    void *bm = 0;   // boyer-moore internal state
    unsigned char haystack[VMI_PS_4KB];
    int find_ofs = 0;

    if (VMI_PM_IA32E == vmi->page_mode) {
        bm = boyer_moore_init((unsigned char *)"\x00\xf8\xff\xffKDBG", 8);
        find_ofs = 0xc;
    } else {
        bm = boyer_moore_init((unsigned char *)"\x00\x00\x00\x00\x00\x00\x00\x00KDBG",
                              12);
        find_ofs = 0x8;
    }   // if-else

    GSList *va_pages_loop = va_pages;
    while (va_pages_loop) {

        page_info_t *vap = (page_info_t *)va_pages_loop->data;

        // We might get pages that are greater than 4Kb
        // so we are just going to split them to 4Kb pages
        while (vap && vap->size >= VMI_PS_4KB) {
            vap->size -= VMI_PS_4KB;
            addr_t page_paddr = vap->paddr+vap->size;

            if (page_paddr + VMI_PS_4KB - 1 > memsize) {
                continue;
            }

            if ( VMI_FAILURE == vmi_read_pa(vmi, page_paddr, VMI_PS_4KB, haystack, NULL) )
                continue;

            int match_offset = boyer_moore2(bm, haystack, VMI_PS_4KB);

            if (-1 != match_offset) {

                addr_t tmp_kva = 0, tmp_kpa = 0;
                addr_t tmp_kdbg = page_paddr + (unsigned int) match_offset - find_ofs;

                if (VMI_FAILURE == vmi_read_64_pa(vmi, tmp_kdbg + sizeof(DBGKD_DEBUG_DATA_HEADER64), &tmp_kva)) {
                    continue;
                }

                if ( VMI_FAILURE == vmi_pagetable_lookup(vmi, cr3, tmp_kva, &tmp_kpa) )
                    continue;

                *kdbg_pa = tmp_kdbg;
                *kernel_va = tmp_kva;
                *kernel_pa = tmp_kpa;

                ret = VMI_SUCCESS;

                goto done;
            }
        }
        g_free(vap);
        va_pages_loop = va_pages_loop->next;
    }

done:
    // free the rest of the list
    while (va_pages_loop) {
        g_free(va_pages_loop->data);
        va_pages_loop = va_pages_loop->next;
    }
    g_slist_free(va_pages);

    if (VMI_SUCCESS == ret)
        dbprint(VMI_DEBUG_MISC, "--Found KdDebuggerDataBlock at PA %.16"PRIx64"\n", *kdbg_pa);
    boyer_moore_fini(bm);
    return ret;
}
Ejemplo n.º 29
0
void print_guid(vmi_instance_t vmi, addr_t kernel_base_p, uint8_t* pe) {

    uint32_t size_of_image;

    bool debug_directory_valid = 0;
    struct pe_header *pe_header = NULL;
    uint16_t optional_header_type = 0;
    struct optional_header_pe32 *oh32 = NULL;
    struct optional_header_pe32plus *oh32plus = NULL;

    peparse_assign_headers(pe, NULL, &pe_header, &optional_header_type, NULL, &oh32, &oh32plus);
    addr_t debug_offset = peparse_get_idd_rva(IMAGE_DIRECTORY_ENTRY_DEBUG, NULL, NULL, oh32, oh32plus);

    switch(optional_header_type)
    {
    case IMAGE_PE32_MAGIC:
        size_of_image=oh32->size_of_image;
        break;
    case IMAGE_PE32_PLUS_MAGIC:
        size_of_image=oh32plus->size_of_image;
        break;
    default:
        return;
    }

    struct image_debug_directory debug_directory = { 0 };
    struct cv_info_pdb70 *pdb_header = g_malloc0(sizeof(struct cv_info_pdb70)+PDB_FILENAME_LENGTH+1);
    if ( VMI_FAILURE == vmi_read_pa(vmi, kernel_base_p + debug_offset, sizeof(struct image_debug_directory), (uint8_t *)&debug_directory, NULL) )
        return;

    printf("\tPE GUID: %.8x%.5x\n",pe_header->time_date_stamp,size_of_image);

    switch(debug_directory.type)
    {
    case IMAGE_DEBUG_TYPE_CODEVIEW:
        // OK
        debug_directory_valid = 1;
        break;
    case IMAGE_DEBUG_TYPE_MISC:
        printf("This operating system uses .dbg instead of .pdb\n");
        return;
    default:
        //printf("The debug directory header is not in CodeView format, will do a brute-force search!\n");
        break;
    }

    if (debug_directory_valid) {
        if(debug_directory.size_of_data > VMI_PS_4KB/4) {
            // Normal size of the debug directory on Windows 7 for example is 0x25 bytes.
            printf("The size of the debug directory is huge, something might be wrong.\n");
            goto done;
        }

        if ( VMI_FAILURE == vmi_read_pa(vmi, kernel_base_p + debug_directory.address_of_raw_data, sizeof(struct cv_info_pdb70)+PDB_FILENAME_LENGTH, pdb_header, NULL) )
            goto done;

        // The PDB header has to be PDB 7.0
        // http://www.debuginfo.com/articles/debuginfomatch.html
        if(RSDS != pdb_header->cv_signature) {
            printf("The CodeView debug information has to be in PDB 7.0 for the kernel!\n");
            goto done;
        }

    } else {
        if(!kernel_debug_search(vmi, pdb_header))
            goto done;
    }

     printf("\tPDB GUID: ");
     printf("%.8x", pdb_header->signature.data1);
     printf("%.4x", pdb_header->signature.data2);
     printf("%.4x", pdb_header->signature.data3);

     int c;
     for(c=0;c<8;c++) printf("%.2x", pdb_header->signature.data4[c]);

     printf("%.1x", pdb_header->age & 0xf);
     printf("\n");
     printf("\tKernel filename: %s\n", (char*)pdb_header->pdb_file_name);

     if(!strcmp("ntoskrnl.pdb", (char*)pdb_header->pdb_file_name)) {
        printf("\tSingle-processor without PAE\n");
     } else
     if(!strcmp("ntkrnlmp.pdb", (char*)pdb_header->pdb_file_name)) {
        printf("\tMulti-processor without PAE\n");
     } else
     if(!strcmp("ntkrnlpa.pdb", (char*)pdb_header->pdb_file_name)) {
        printf("\tSingle-processor with PAE (version 5.0 and higher)\n");
     } else
     if(!strcmp("ntkrpamp.pdb", (char*)pdb_header->pdb_file_name)) {
        printf("\tMulti-processor with PAE (version 5.0 and higher)\n");
     }

done:
    free(pdb_header);
}