void mm_callback(vmi_instance_t vmi, vmi_event_t *event) { struct injector *injector = event->data; reg_t rip, cr3, rsp; vmi_get_vcpureg(vmi, &rip, RIP, event->vcpu_id); vmi_get_vcpureg(vmi, &cr3, CR3, event->vcpu_id); vmi_get_vcpureg(vmi, &rsp, RSP, event->vcpu_id); vmi_pid_t pid = vmi_dtb_to_pid(vmi, cr3); printf("----- Memevent: PID %u executing RIP 0x%lx. Target PID: %u. Target RIP: 0x%lx. My event count: %u\n", pid, ((event->mem_event.gfn<<12) + event->mem_event.offset), injector->target_pid, injector->target_rip, injector->mm_count); if ((PM2BIT(injector->pm) == BIT32 && rip < KERNEL32) || (PM2BIT(injector->pm) == BIT64 && rip < KERNEL64)) { injector->target_pid = pid; injector->target_rip = (event->mem_event.gfn << 12) + event->mem_event.offset; hijack_thread(injector, vmi, event->vcpu_id, pid); vmi_clear_event(vmi, event); vmi_clear_event(vmi, &injector->cr3_event); injector->mm_count++; uint8_t trap = 0xCC; vmi_read_8_pa(vmi, injector->target_rip, &injector->backup); vmi_write_8_pa(vmi, injector->target_rip, &trap); return; } vmi_clear_event(vmi, event); vmi_step_event(vmi, event, event->vcpu_id, 1, NULL); }
//callback function void mm_callback(vmi_instance_t vmi, vmi_event_t *event) { print_event(event); vmi_get_vcpureg(vmi,&rax,RAX,0); vmi_get_vcpureg(vmi,&rbx,RBX,0); vmi_get_vcpureg(vmi,&rcx,RCX,0); vmi_get_vcpureg(vmi,&rdx,RDX,0); vmi_get_vcpureg(vmi,&rsi,RSI,0); vmi_get_vcpureg(vmi,&rdi,RDI,0); printf("HYPERCALL is: %s\n RAX value is: %lx\n RBX value is: %lx\n RCX value is: %lx\n RDX value is: %lx\n RSI value is: %lx\n RDI value is: %lx\n", event->mem_event.hypercall,rax,rbx,rcx,rdx,rsi,rdi); if(event->mem_event.gla == event->mem_event.gla2) { printf("\tCought the original hypercall executing again!"); vmi_clear_event(vmi, event); interrupted = 1; } else { printf("\tEvent on same page, but not the hypercall: %s",event->mem_event.hypercall); vmi_clear_event(vmi, event); /* These two calls are equivalent */ //vmi_step_event(vmi, event, event->vcpu_id, 1, NULL); vmi_step_event(vmi, event, event->vcpu_id, 1, NULL); } printf("\n}\n"); }
void ss_callback(vmi_instance_t vmi, vmi_event_t *event) { reg_t rip, cr3; vmi_get_vcpureg(vmi, &rip, RIP, event->vcpu_id); vmi_get_vcpureg(vmi, &cr3, CR3, event->vcpu_id); page_mode_t pm = vmi_get_page_mode(vmi); vmi_pid_t pid = vmi_dtb_to_pid(vmi, cr3); printf("----- Singlestep: CR3 0x%lx PID %u executing RIP 0x%lx\n", cr3, pid, rip); if ((PM2BIT(pm) == BIT32 && rip < KERNEL32) || (PM2BIT(pm) == BIT64 && rip < KERNEL64)) { printf("Good RIP: 0x%lx\n", rip); struct injector *injector = event->data; injector->ss_enabled = 0; injector->target_pid = pid; injector->target_rip = vmi_pagetable_lookup(vmi, cr3, rip); hijack_thread(injector, vmi, event->vcpu_id, pid); vmi_clear_event(vmi, event); vmi_clear_event(vmi, &injector->cr3_event); injector->mm_count++; uint8_t trap = 0xCC; vmi_read_8_pa(vmi, injector->target_rip, &injector->backup); vmi_write_8_pa(vmi, injector->target_rip, &trap); } }
event_response_t mm_callback(vmi_instance_t vmi, vmi_event_t *event) { vmi_get_vcpureg(vmi, &cr3, CR3, 0); vmi_pid_t current_pid = vmi_dtb_to_pid(vmi, cr3); reg_t rip_test; vmi_get_vcpureg(vmi, &rip_test, RIP, 0); printf("Memevent: {\n\tPID %u. RIP 0x%lx:\n", current_pid, rip_test); print_event(event); if( current_pid == pid && event->mem_event.gla == rip) { printf("\tCought the original RIP executing again!"); vmi_clear_event(vmi, event, NULL); interrupted = 1; } else { printf("\tEvent on same page, but not the same RIP"); vmi_clear_event(vmi, event, NULL); /* These two calls are equivalent */ //vmi_step_event(vmi, event, event->vcpu_id, 1, NULL); vmi_step_event(vmi, event, event->vcpu_id, 1, step_callback); } printf("\n}\n"); return 0; }
int start_app(honeymon_clone_t *clone, vmi_pid_t pid, const char *app) { vmi_pause_vm(clone->vmi); struct injector injector = { .clone = clone, .target_cr3 = vmi_pid_to_dtb(clone->vmi, pid), .target_pid = pid, .target_proc = app, .winver = clone->winver, .pm = vmi_get_page_mode(clone->vmi) }; if (!injector.target_cr3) return 0; printf("Target PID %u with DTB 0x%lx to start '%s'\n", pid, injector.target_cr3, app); injector.cr3_event.type = VMI_EVENT_REGISTER; injector.cr3_event.reg_event.reg = CR3; injector.cr3_event.reg_event.in_access = VMI_REGACCESS_W; injector.cr3_event.callback = cr3_callback; injector.cr3_event.data = &injector; vmi_register_event(clone->vmi, &injector.cr3_event); vmi_event_t interrupt_event; memset(&interrupt_event, 0, sizeof(vmi_event_t)); interrupt_event.type = VMI_EVENT_INTERRUPT; interrupt_event.interrupt_event.intr = INT3; interrupt_event.callback = injector_int3_cb; interrupt_event.data = &injector; vmi_register_event(clone->vmi, &interrupt_event); printf("Starting injection loop\n"); vmi_resume_vm(clone->vmi); status_t status = VMI_FAILURE; while (!clone->interrupted) { //printf("Waiting for events...\n"); status = vmi_events_listen(clone->vmi, 500); if (status != VMI_SUCCESS) { printf("Error waiting for events, quitting...\n"); clone->interrupted = -1; } } vmi_clear_event(clone->vmi, &injector.cr3_event); vmi_clear_event(clone->vmi, &injector.mm_event); vmi_clear_event(clone->vmi, &injector.ss_event); vmi_clear_event(clone->vmi, &interrupt_event); printf("Finished with injection.\n"); return injector.ret; }
gboolean event_entry_free (gpointer key, gpointer value, gpointer data) { vmi_instance_t vmi=(vmi_instance_t)data; vmi_event_t *event = (vmi_event_t*)value; vmi_clear_event(vmi, event); return TRUE; }
event_response_t cr3_one_task_callback(vmi_instance_t vmi, vmi_event_t *event){ vmi_pid_t pid = vmi_dtb_to_pid(vmi, event->reg_event.value); printf("one_task callback\n"); if(event->reg_event.value == cr3){ printf("My process with PID %"PRIi32", CR3=%"PRIx64" is executing on vcpu %"PRIu32". Previous CR3=%"PRIx64"\n", pid, event->reg_event.value, event->vcpu_id, event->reg_event.previous); msr_syscall_sysenter_event.mem_event.in_access = VMI_MEMACCESS_X; msr_syscall_sysenter_event.callback=msr_syscall_sysenter_cb; kernel_sysenter_target_event.mem_event.in_access = VMI_MEMACCESS_X; kernel_sysenter_target_event.callback=ia32_sysenter_target_cb; kernel_vsyscall_event.mem_event.in_access = VMI_MEMACCESS_X; kernel_vsyscall_event.callback=vsyscall_cb; if(vmi_register_event(vmi, &msr_syscall_sysenter_event) == VMI_FAILURE) fprintf(stderr, "Could not install sysenter syscall handler.\n"); if(vmi_register_event(vmi, &kernel_sysenter_target_event) == VMI_FAILURE) fprintf(stderr, "Could not install sysenter syscall handler.\n"); if(vmi_register_event(vmi, &kernel_vsyscall_event) == VMI_FAILURE) fprintf(stderr, "Could not install sysenter syscall handler.\n"); } else{ printf("PID %i is executing, not my process!\n", pid); vmi_clear_event(vmi, &msr_syscall_sysenter_event, NULL); } return 0; }
void waitfor_cr3_callback(vmi_instance_t vmi, vmi_event_t *event) { struct injector *injector = event->data; injector->clone->interrupted = 1; printf("Injected process is scheduled to execute\n"); vmi_pause_vm(vmi); vmi_clear_event(vmi, event); }
void cr3_one_task_callback(vmi_instance_t vmi, vmi_event_t *event){ vmi_pid_t pid = vmi_dtb_to_pid(vmi, event->reg_event.value); printf("one_task callback\n"); if(event->reg_event.value == cr3){ printf("My process (PID %i) is executing on vcpu %ud\n", pid, event->vcpu_id); msr_syscall_sysenter_event.mem_event.in_access = VMI_MEMACCESS_X; msr_syscall_sysenter_event.callback=msr_syscall_sysenter_cb; kernel_sysenter_target_event.mem_event.in_access = VMI_MEMACCESS_X; kernel_sysenter_target_event.callback=ia32_sysenter_target_cb; kernel_vsyscall_event.mem_event.in_access = VMI_MEMACCESS_X; kernel_vsyscall_event.callback=vsyscall_cb; if(vmi_register_event(vmi, &msr_syscall_sysenter_event) == VMI_FAILURE) fprintf(stderr, "Could not install sysenter syscall handler.\n"); if(vmi_register_event(vmi, &kernel_sysenter_target_event) == VMI_FAILURE) fprintf(stderr, "Could not install sysenter syscall handler.\n"); if(vmi_register_event(vmi, &kernel_vsyscall_event) == VMI_FAILURE) fprintf(stderr, "Could not install sysenter syscall handler.\n"); } else{ printf("PID %i is executing, not my process!\n", pid); vmi_clear_event(vmi, &msr_syscall_sysenter_event); } }
//callback function void mm_callback(vmi_instance_t vmi, vmi_event_t *event) { print_event(event); if(event->mem_event.gla == vaddr) { printf("\tCought the original hypercall executing again!"); vmi_clear_event(vmi, event); interrupted = 1; } else { printf("\tEvent on same page, but not the hypercall"); vmi_clear_event(vmi, event); /* These two calls are equivalent */ //vmi_step_event(vmi, event, event->vcpu_id, 1, NULL); vmi_step_event(vmi, event, event->vcpu_id, 1, NULL); } printf("\n}\n"); }
void cr3_all_tasks_callback(vmi_instance_t vmi, vmi_event_t *event){ vmi_pid_t pid = vmi_dtb_to_pid(vmi, event->reg_event.value); printf("PID %i with CR3=%"PRIx64" executing on vcpu %u.\n", pid, event->reg_event.value, event->vcpu_id); msr_syscall_sysenter_event.mem_event.in_access = VMI_MEMACCESS_X; msr_syscall_sysenter_event.callback=msr_syscall_sysenter_cb; if(vmi_register_event(vmi, &msr_syscall_sysenter_event) == VMI_FAILURE) fprintf(stderr, "Could not install sysenter syscall handler.\n"); vmi_clear_event(vmi, &msr_syscall_sysenter_event); }
void syscall_compat_cb(vmi_instance_t vmi, vmi_event_t *event){ reg_t rdi, rax; vmi_get_vcpureg(vmi, &rax, RAX, event->vcpu_id); vmi_get_vcpureg(vmi, &rdi, RDI, event->vcpu_id); printf("Syscall happened: RAX(syscall#)=%u RDI(1st argument)=%u\n", (unsigned int)rax, (unsigned int)rdi); print_event(*event); vmi_clear_event(vmi, &msr_syscall_compat_event); }
event_response_t msr_syscall_sysenter_cb(vmi_instance_t vmi, vmi_event_t *event){ reg_t rdi, rax; vmi_get_vcpureg(vmi, &rax, RAX, event->vcpu_id); vmi_get_vcpureg(vmi, &rdi, RDI, event->vcpu_id); printf("Syscall happened: RAX(syscall#)=%u RDI(1st argument)=%u\n", (unsigned int)rax, (unsigned int)rdi); print_event(*event); vmi_clear_event(vmi, &msr_syscall_sysenter_event, NULL); return 0; }
event_response_t rng_single_step_callback(vmi_instance_t vmi, vmi_event_t *event) { //printf("Got a single-step callback!\n"); // gameplan step 5 //printf("Re-adding breakpoint before instruction.\n"); uint8_t int3 = INT3_INST; // create temporary variable because we can't use an address to a static #defined int if (VMI_SUCCESS != vmi_write_8_va(vmi, breakpoints[break_idx].addr, 0, &int3)) { //printf("Couldn't write to memory... exiting.\n"); return VMI_FAILURE; } // clear break_idx now that we've reinserted the interrupt break_idx = -1; vmi_clear_event(vmi, event, NULL); return VMI_SUCCESS; }
event_response_t cr3_callback(vmi_instance_t vmi, vmi_event_t *event){ vmi_pid_t current_pid = vmi_dtb_to_pid(vmi, event->reg_event.value); printf("PID %i with CR3=%"PRIx64" executing on vcpu %u.\n", current_pid, event->reg_event.value, event->vcpu_id); if(current_pid == pid) { if(!mm_enabled) { mm_enabled = 1; printf(" -- Enabling mem-event\n"); vmi_register_event(vmi, &mm_event); } } else { if(mm_enabled) { mm_enabled = 0; printf(" -- Disabling mem-event\n"); vmi_clear_event(vmi, &mm_event, NULL); } } return 0; }
void injector_int3_cb(vmi_instance_t vmi, vmi_event_t *event) { struct injector *injector = event->data; addr_t pa = (event->interrupt_event.gfn << 12) + event->interrupt_event.offset; reg_t cr3; vmi_get_vcpureg(vmi, &cr3, CR3, event->vcpu_id); vmi_pid_t pid = vmi_dtb_to_pid(vmi, cr3); printf("INT3 @ 0x%lx. PID %u\n", pa, pid); if (pa == injector->userspace_return) { event->interrupt_event.reinject = 0; if (pid != injector->target_pid) { printf("Userspace return trap hit by another PID, not the target (%u)\n", injector->target_pid); vmi_write_8_pa(vmi, pa, &injector->userspace_return_backup); vmi_step_event(vmi, event, event->vcpu_id, 1, reset_return_trap); return; } injector->target_pid = pid; injector->target_rip = pa; injector->backup = injector->userspace_return_backup; injector->userspace_return = 0; hijack_thread(injector, vmi, event->vcpu_id, pid); /* injector->ss_enabled = 1; memset(&injector->ss_event, 0, sizeof(vmi_event_t)); injector->ss_event.type = VMI_EVENT_SINGLESTEP; injector->ss_event.callback = ss_callback; injector->ss_event.data = injector; SET_VCPU_SINGLESTEP(injector->ss_event.ss_event, event->vcpu_id); vmi_register_event(vmi, &injector->ss_event); */ vmi_clear_event(vmi, &injector->cr3_event); injector->mm_count++; return; } if (pa == injector->target_rip) { event->interrupt_event.reinject = 0; if (pid != injector->target_pid) { printf("Return trap hit by another PID, not the target (%u)\n", injector->target_pid); vmi_write_8_pa(vmi, pa, &injector->backup); vmi_step_event(vmi, event, event->vcpu_id, 1, reset_return_trap); return; } reg_t rax; vmi_get_vcpureg(vmi, &rax, RAX, event->vcpu_id); vmi_pid_t pid = vmi_dtb_to_pid(vmi, cr3); printf("RAX: 0x%lx\n", rax); printf("Restoring RSP to 0x%lx\n", injector->saved_rsp); printf("Restoring RAX to 0x%lx\n", injector->saved_rax); printf("Restoring RCX to 0x%lx\n", injector->saved_rcx); printf("Restoring RDX to 0x%lx\n", injector->saved_rdx); printf("Restoring R8 to 0x%lx\n", injector->saved_r8); printf("Restoring R9 to 0x%lx\n", injector->saved_r9); vmi_set_vcpureg(vmi, injector->saved_rsp, RSP, event->vcpu_id); vmi_set_vcpureg(vmi, injector->saved_rax, RAX, event->vcpu_id); vmi_set_vcpureg(vmi, injector->saved_rcx, RCX, event->vcpu_id); vmi_set_vcpureg(vmi, injector->saved_rdx, RDX, event->vcpu_id); vmi_set_vcpureg(vmi, injector->saved_r8, R8, event->vcpu_id); vmi_set_vcpureg(vmi, injector->saved_r9, R9, event->vcpu_id); if (rax) { printf("-- CreateProcessA SUCCESS --\n"); if (PM2BIT(injector->pm) == BIT32) { struct process_information_32 pip; vmi_read_va(vmi, injector->process_info, pid, &pip, sizeof(struct process_information_32)); printf("\tProcess handle: 0x%x. Thread handle: 0x%x\n", pip.hProcess, pip.hThread); printf("\tPID: %u. TID: %u\n", pip.dwProcessId, pip.dwThreadId); injector->pid = pip.dwProcessId; injector->tid = pip.dwThreadId; injector->hProc = pip.hProcess; injector->hThr = pip.hThread; } else { struct process_information_64 pip; vmi_read_va(vmi, injector->process_info, pid, &pip, sizeof(struct process_information_64)); printf("\tProcess handle: 0x%lx. Thread handle: 0x%lx\n", pip.hProcess, pip.hThread); printf("\tPID: %u. TID: %u\n", pip.dwProcessId, pip.dwThreadId); injector->pid = pip.dwProcessId; injector->tid = pip.dwThreadId; injector->hProc = pip.hProcess; injector->hThr = pip.hThread; } if (injector->pid && injector->tid) { injector->ret = rax; injector->cr3_event.callback = waitfor_cr3_callback; injector->cr3_event.reg_event.equal = vmi_pid_to_dtb(vmi, injector->pid); injector->cr3_event.data = injector; vmi_register_event(vmi, &injector->cr3_event); printf("\tInjected process CR3: 0x%lx\n", injector->cr3_event.reg_event.equal); } } else { injector->clone->interrupted = 1; } vmi_write_8_pa(vmi, pa, &injector->backup); vmi_clear_event(vmi, event); } else { event->interrupt_event.reinject = 1; } }
void cr3_callback(vmi_instance_t vmi, vmi_event_t *event) { //printf("CR3 changed to 0x%lx\n", event->reg_event.value); struct injector *injector = event->data; addr_t thread = 0, kpcrb_offset = 0, trapframe = 0; addr_t userspace_return_va = 0, userspace_return_pa = 0; reg_t fsgs = 0; if (event->reg_event.value == injector->target_cr3) { if (!injector->target_rip) { /* TODO: Trap frame approach only works on 64-bit */ if (PM2BIT(injector->pm) == BIT32) { if(!injector->mm_enabled) { vmi_pid_t pid = vmi_dtb_to_pid(vmi, event->reg_event.value); addr_t waitfor = sym2va(vmi, pid, "kernel32.dll", "WaitForMultipleObjects"); //printf("PID %u waitfor 0x%lx\n", pid, waitfor); if (!waitfor) { //injector->clone->interrupted = 1; printf("Target process doesn't have kernel32.dll mapped!\n"); return; } injector->mm_enabled=1; memset(&injector->mm_event, 0, sizeof(vmi_event_t)); injector->mm_event.type = VMI_EVENT_MEMORY; injector->mm_event.mem_event.physical_address = vmi_translate_uv2p(vmi, waitfor, pid); injector->mm_event.mem_event.npages = 1; injector->mm_event.mem_event.granularity=VMI_MEMEVENT_PAGE; injector->mm_event.mem_event.in_access = VMI_MEMACCESS_X; injector->mm_event.callback=mm_callback; injector->mm_event.data = injector; vmi_register_event(vmi, &injector->mm_event); } return; } /* Read return to userspace RIP out of the stack trap frame. */ if (PM2BIT(injector->pm) == BIT32) { vmi_get_vcpureg(vmi, &fsgs, FS_BASE, event->vcpu_id); kpcrb_offset = offsets[KPCR_PRCBDATA]; } else { vmi_get_vcpureg(vmi, &fsgs, GS_BASE, event->vcpu_id); kpcrb_offset = offsets[KPCR_PRCB]; } vmi_read_addr_va(vmi, fsgs + kpcrb_offset + offsets[KPRCB_CURRENTTHREAD], 0, &thread); vmi_read_addr_va(vmi, thread + offsets[KTHREAD_TRAPFRAME], 0, &trapframe); //printf("Trap frame @ 0x%lx\n", trapframe); if (PM2BIT(injector->pm) == BIT32) { vmi_read_addr_va(vmi, trapframe + offsets[KTRAP_FRAME_EIP], 0, &userspace_return_va); } else { vmi_read_addr_va(vmi, trapframe + offsets[KTRAP_FRAME_RIP], 0, &userspace_return_va); } injector->userspace_return = vmi_pagetable_lookup(vmi, event->reg_event.value, userspace_return_va); //printf("Userspace return @ VA 0x%lx -> PA 0x%lx\n", userspace_return_va, injector->userspace_return); uint8_t trap = 0xCC; vmi_read_8_pa(vmi, injector->userspace_return, &injector->userspace_return_backup); vmi_write_8_pa(vmi, injector->userspace_return, &trap); /*if (!injector->ss_enabled) { printf("My target process is executing, registering singlestep\n"); injector->ss_enabled = 1; memset(&injector->ss_event, 0, sizeof(vmi_event_t)); injector->ss_event.type = VMI_EVENT_SINGLESTEP; injector->ss_event.callback = ss_callback; injector->ss_event.data = injector; SET_VCPU_SINGLESTEP(injector->ss_event.ss_event, event->vcpu_id); vmi_register_event(vmi, &injector->ss_event); }*/ } } else { //printf("CR3 0x%lx is executing, not my process!\n", // event->reg_event.value); if (injector->mm_enabled) { injector->mm_enabled = 0; vmi_clear_event(vmi, &injector->mm_event); } if (injector->ss_enabled) { //printf("\tDisabling singlestep\n"); injector->ss_enabled = 0; vmi_clear_event(vmi, &injector->ss_event); } if (injector->userspace_return) { vmi_write_8_pa(vmi, injector->userspace_return, &injector->userspace_return_backup); injector->userspace_return_backup = 0; injector->userspace_return = 0; } } }