tklengyel / drakvuf

DRAKVUF Black-box Binary Analysis
https://drakvuf.com
Other
1.07k stars 255 forks source link

Bug MEMACCESS event not working on page with BREAKPOINT #180

Closed masthoon closed 8 years ago

masthoon commented 8 years ago

When you register a BREAKPOINT then a MEMACCESS on the same page, the MEMACCESS event won't work.

POC :

this->trap_test.breakpoint.addr = exAllocatePoolWithTag; // addr_type is ADDR_VA

if ( !drakvuf_add_trap(drakvuf, &this->trap_test) ) {
    throw -1;
}

vmi_get_vcpureg(vmi, &cr3, CR3, 0);
kernel_page = vmi_pagetable_lookup(vmi, cr3, exAllocatePoolWithTag);
assert(kernel_page != NULL);
this->trap_pagetest.memaccess.gfn = kernel_page >> 12;

if ( !drakvuf_add_trap(drakvuf, &this->trap_pagetest) ) { // access = VMI_MEMACCESS_X
    throw -1;
}
assert(vmi_get_mem_event(vmi, kernel_page) != NULL); // FAIL

Drakvuf uses vmi_swap_events to replace old event (Breakpoint guard RW) to new event with according rights (_mem_event.inaccess). Then, it deletes the old event using vmi_clear_event.

I think the problem is the current implementation of _vmi_clearevent, it calls _clear_memevent who resets page access rights and removes the page from vmi->mem_events.

So, both events are removed (from _vmi->memevents) and the page right is reset however the breakpoint will still trigger thanks to the interrupt.

tklengyel commented 8 years ago

Good catch. I've updated the LibVMI vmi_swap_events API to take the free routine pointer directly so we don't have to call vmi_clear_event afterwards.