Exemplo n.º 1
0
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);
    }
}
Exemplo n.º 2
0
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);
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
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);
    }
}
Exemplo n.º 6
0
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);
}
Exemplo n.º 7
0
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;
}
Exemplo n.º 8
0
event_response_t bnrand_callback(vmi_instance_t vmi, vmi_event_t *event) {

	uint64_t nbytes;
	addr_t buf_addr;
	uint8_t* buffer;
	vmi_pid_t pid = vmi_dtb_to_pid(vmi, event->regs.x86->cr3);
	printf("Called bnrand_callback from pid %d!\n");

	// look at args
	printf("Reading RDI register (*buf):    0x%llx\n", event->regs.x86->rdi);
	printf("Reading RSI register (bytes):    0x%llx\n", event->regs.x86->rsi);
	printf("Reading RDX register (*rnd):    0x%llx\n", event->regs.x86->rdx);

	// read in all the bytes at buf
	nbytes = event->regs.x86->rsi;
	buf_addr = event->regs.x86->rdi;
	buffer = malloc(nbytes); // allocate buffer

	vmi_read_va(vmi, buf_addr, pid, buffer, nbytes);
	printf("old buf: ");
	for (unsigned int i = 0; i < nbytes; i++) {
		printf("%02x ",buffer[i]);
	}
	printf("\n");

	// modify rng buffer!
	vmi_write_va(vmi, buf_addr, pid, RNG_VALUE, nbytes);

	// read in all the bytes at buf again (sanity check)
	vmi_read_va(vmi, buf_addr, pid, buffer, nbytes);
	printf("new buf: ");
	for (unsigned int i = 0; i < nbytes; i++) {
		printf("%02x ",buffer[i]);
	}
	printf("\n");

	return VMI_SUCCESS;
}
Exemplo n.º 9
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;
    }
}
Exemplo n.º 10
0
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;
        }
    }
}
Exemplo n.º 11
0
int main (int argc, char **argv)
{
    vmi_instance_t vmi = NULL;
    status_t status = VMI_SUCCESS;

    struct sigaction act;

    mm_enabled=0;

    char *name = NULL;

    if(argc < 2){
        fprintf(stderr, "Usage: %s <name of VM>\n", argv[0]);
        exit(1);
    }

    // Arg 1 is the VM name.
    name = argv[1];

    /* for a clean exit */
    act.sa_handler = close_handler;
    act.sa_flags = 0;
    sigemptyset(&act.sa_mask);
    sigaction(SIGHUP,  &act, NULL);
    sigaction(SIGTERM, &act, NULL);
    sigaction(SIGINT,  &act, NULL);
    sigaction(SIGALRM, &act, NULL);

    // Initialize the libvmi library.
    if (vmi_init(&vmi, VMI_XEN | VMI_INIT_COMPLETE | VMI_INIT_EVENTS, name) == VMI_FAILURE){
        printf("Failed to init LibVMI library.\n");
        if (vmi != NULL ) {
            vmi_destroy(vmi);
        }
        return 1;
    }
    else{
        printf("LibVMI init succeeded!\n");
    }

    vmi_pause_vm(vmi);

    SETUP_REG_EVENT(&cr3_event, CR3, VMI_REGACCESS_W, 0, cr3_callback);
    vmi_register_event(vmi, &cr3_event);

    // Setup a mem event for tracking memory at the current instruction's page
    // But don't install it; that will be done by the cr3 handler.

    vmi_get_vcpureg(vmi, &rip, RIP, 0);
    vmi_get_vcpureg(vmi, &cr3, CR3, 0);

    printf("Current value of RIP is 0x%lx\n", rip);
    rip -= 0x1;

    pid = vmi_dtb_to_pid(vmi, cr3);
    if(pid==4) {
        rip_pa = vmi_translate_uv2p(vmi, rip, pid);
    } else {
        rip_pa = vmi_translate_kv2p(vmi, rip);
    }

    printf("Preparing memory event to catch next RIP 0x%lx, PA 0x%lx, page 0x%lx for PID %u\n",
            rip, rip_pa, rip_pa >> 12, pid);
    SETUP_MEM_EVENT(&mm_event, rip_pa, VMI_MEMEVENT_PAGE, VMI_MEMACCESS_X, mm_callback);

    vmi_resume_vm(vmi);

    while(!interrupted){
        status = vmi_events_listen(vmi,500);
        if (status != VMI_SUCCESS) {
            printf("Error waiting for events, quitting...\n");
            interrupted = -1;
        }
    }
    printf("Finished with test.\n");

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

    return 0;
}