OR: WHY I HATE KERNELS LMAO

Turns out, the System.map file doesn’t accurately represent the kernel address space. Instead, KASLR shifts the kernel’s address space listed in System.map by a random constant. This has been the case since it was turned on by default in Linux 4.12.

https://marcograss.github.io/security/linux/2016/01/24/exploiting-infoleak-linux-kaslr-bypass.html

https://forums.grsecurity.net/viewtopic.php?f=7&t=3367

https://bneuburg.github.io/volatility/kaslr/2017/05/05/KASLR2.html


THE DRAVUF & LibVMI WORKAROUND:

drakvuf_init()drakvuf_init_os() _drakvuf_init_os()vmi_init_os()linux_init()

linux_filemode_init() or init_kaslr()

Antes, no drakvuf, os endereços dos simbolos de interesse eram obtidos através do system.map mas com KASLR, ele é quase inútil. Basicamente pq os endereços apresentados pelo system.map são os endereços dos simbolos antes do KASLR ser aplicado… Veja:

https://stackoverflow.com/questions/31854883/symbol-addresses-in-boot-system-map-are-not-identical-to-those-in-proc-kallsy

  1. linux_init()
    1. init_from_json_profile()
    2. linux_symbol_to_address()
    3. linux_filemode_init()
    4. init_kaslr()
struct linux_instance {
 
    char *sysmap; /**< system map file for domain's running kernel */
 
    addr_t tasks_offset; /**< task_struct->tasks */
 
    addr_t mm_offset; /**< task_struct->mm */
 
    addr_t pid_offset; /**< task_struct->pid */
 
    addr_t pgd_offset; /**< mm_struct->pgd */
 
    addr_t name_offset; /**< task_struct->comm */
 
    addr_t kaslr_offset; /**< offset generated at boot time for KASLR */
 
    addr_t init_task_fixed; /**< Rekall's location for init task, ignoring KASLR */
 
};
status_t linux_init(vmi_instance_t vmi, GHashTable *config)
{
 
    status_t rc;
    os_interface_t os_interface = NULL;
 
    if (!config) {
        errprint("No config table found\n");
        return VMI_FAILURE;
    }
 
    if (vmi->os_data != NULL) {
        errprint("os data already initialized, reinitializing\n");
        g_free(vmi->os_data);
    }
 
    vmi->os_data = g_try_malloc0(sizeof(struct linux_instance));
    if ( !vmi->os_data )
        return VMI_FAILURE;
 
    linux_instance_t linux_instance = vmi->os_data;
 
    g_hash_table_foreach(config, (GHFunc)linux_read_config_ghashtable_entries, vmi);
		
		/*
		Talvez seja necessário assumir que isso retorna "VMI_SUCCESS", só assim o offset 
		do KASLR será calculado antes de tentar resolver qualquer simbolo.
		*/
 
    rc = init_from_json_profile(vmi);
 
    if ( VMI_FAILURE == rc && !vmi->init_task )
        rc = linux_symbol_to_address(vmi, "init_task", NULL, &vmi->init_task);
    else
        rc = VMI_SUCCESS;
 
    if ( VMI_FAILURE == rc ) {
        errprint("Failed to determine init_task!\n");
        goto _exit;
    }
 
    /* Save away the claimed init_task addr. It may be needed again for KASLR computation. */
    vmi->init_task = canonical_addr(vmi->init_task);
    linux_instance->init_task_fixed = vmi->init_task;
 
		// KPGD = Kernel Page Global Directory e_e
 
    if ( !vmi->kpgd ) {
#if defined(ARM32) || defined(ARM64)
        rc = driver_get_vcpureg(vmi, &vmi->kpgd, TTBR1, 0);
#elif defined(I386) || defined(X86_64)
        rc = driver_get_vcpureg(vmi, &vmi->kpgd, CR3, 0);
        vmi->kpgd &= ~0x1fffull; // mask PCID and meltdown bits
#endif
    }
 
    /*
     * The driver failed to get us a pagetable.
     * As a fall-back, try to init using heuristics.
     * This path is taken in FILE mode as well.
     */
    if ( VMI_FAILURE == rc && VMI_FAILURE == linux_filemode_init(vmi) )
        goto _exit;
 
    if ( !linux_instance->kaslr_offset ) {
        if ( VMI_FAILURE == init_kaslr(vmi) ) {
            // try without masking Meltdown bit
            vmi->kpgd |= 0x1000ull;
            if ( VMI_FAILURE == init_kaslr(vmi) ) {
                dbprint(VMI_DEBUG_MISC, "**failed to determine KASLR offset\n");
                goto _exit;
            }
        }
    }
 
    dbprint(VMI_DEBUG_MISC, "**set vmi->kpgd (0x%.16"PRIx64").\n", vmi->kpgd);
    dbprint(VMI_DEBUG_MISC, "**set vmi->init_task (0x%.16"PRIx64").\n", vmi->init_task);
 
    os_interface = g_malloc(sizeof(struct os_interface));
    if ( !os_interface )
        goto _exit;
 
    bzero(os_interface, sizeof(struct os_interface));
    os_interface->os_get_offset = linux_get_offset;
    os_interface->os_get_kernel_struct_offset = linux_get_kernel_struct_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_symbol_to_address;
    os_interface->os_usym2rva = NULL;
    os_interface->os_v2sym = NULL;
    os_interface->os_v2ksym = linux_system_map_address_to_symbol;
    os_interface->os_read_unicode_struct = NULL;
    os_interface->os_teardown = linux_teardown;
 
    vmi->os_interface = os_interface;
 
    return VMI_SUCCESS;
 
_exit:
    linux_teardown(vmi);
    return VMI_FAILURE;
}

linux_symbol_to_address()

linux_filemode_init()

init_kaslr()


🌱 Back to Garden

3 items under this folder.