コード例 #1
0
ファイル: injector.c プロジェクト: ph0sec/drakvuf
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;
}
コード例 #2
0
int main (int argc, char **argv) {
    vmi_instance_t vmi;
    struct sigaction act;
    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);

    char *name = NULL;

    if(argc < 2){
        fprintf(stderr, "Usage: interrupt_events_example <name of VM>\n");
        exit(1);
    }

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

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

    /* Register event to track INT3 interrupts */
    memset(&interrupt_event, 0, sizeof(vmi_event_t));
    interrupt_event.type = VMI_EVENT_INTERRUPT;
    interrupt_event.interrupt_event.enabled = 1;
    interrupt_event.interrupt_event.reinject = 1;
    interrupt_event.callback = int3_cb;

    vmi_register_event(vmi, &interrupt_event);

    printf("Waiting for events...\n");
    while(!interrupted){
        vmi_events_listen(vmi,500);
    }
    printf("Finished with test.\n");

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

    return 0;
}
コード例 #3
0
ファイル: hvm.c プロジェクト: allewwaly/HI
int main(int argc, char **argv)
{
        vmi_instance_t vmi = NULL;
        status_t status = VMI_SUCCESS;
        if (argc != 2) {
                printf("Usage: %s <vmname>\n", argv[0]);
                return 1;
        }
        char *name=argv[1];
	//vmi_pid_t pid=atoi(argv[3]);
        if (vmi_init(&vmi, VMI_AUTO | VMI_INIT_COMPLETE | VMI_INIT_EVENTS, name) == VMI_FAILURE) {
                printf("Failed to init LibVMI library.\n");
                return 1;
        }
        printf("success to init LibVMI\n");
	int i;
	vmi_pause_vm(vmi);
	for (i = 0; i < num; i++) {
		char *vaddr_str=hypercall_address[i][1];
		char *hypercall_name=hypercall_address[i][0];
	        vaddr[i] =(addr_t) strtoul(vaddr_str, NULL, 16);
		printf("virtual address is:%lx\n",vaddr[i]);
		//printf("pid is: %d\n",pid);
        	paddr[i] = vmi_translate_kv2p(vmi,vaddr[i]);
	        printf("physical address is::%lx\n",paddr[i]);
		mm_event[i].mem_event.gla2 = vaddr[i];//add comparing gla to memory event structure
		mm_event[i].mem_event.hypercall=hypercall_name;
		printf("Preparing memory event to catch HYPERCALL %s at PA 0x%lx, page 0x%lx\n\n",
	            hypercall_name, paddr[i], paddr[i] >> 12);
		SETUP_MEM_EVENT(&mm_event[i], paddr[i], VMI_MEMEVENT_PAGE,
        	            VMI_MEMACCESS_RWX, mm_callback);
		vmi_register_event(vmi,&mm_event[i]);
	}
	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");
        vmi_destroy(vmi);
        return 1;
}
コード例 #4
0
ファイル: step-event-example.c プロジェクト: chonghw/libvmi
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;
}
コード例 #5
0
ファイル: event-example.c プロジェクト: chonghw/libvmi
int main (int argc, char **argv)
{
    vmi_instance_t vmi = NULL;
    status_t status = VMI_SUCCESS;

    struct sigaction act;

    reg_t lstar = 0;
    addr_t phys_lstar = 0;
    reg_t cstar = 0;
    addr_t phys_cstar = 0;
    reg_t sysenter_ip = 0;
    addr_t phys_sysenter_ip = 0;

    addr_t ia32_sysenter_target = 0;
    addr_t phys_ia32_sysenter_target = 0;
    addr_t vsyscall = 0;
    addr_t phys_vsyscall = 0;

    char *name = NULL;
    vmi_pid_t pid = -1;

    if(argc < 2){
        fprintf(stderr, "Usage: events_example <name of VM> <PID of process to track {optional}>\n");
        exit(1);
    }

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

    // Arg 2 is the pid of the process to track.
    if(argc == 3)
        pid = (int) strtoul(argv[2], NULL, 0);

    /* 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");
    }

    // Get the cr3 for this process.
    if(pid != -1) {
        cr3 = vmi_pid_to_dtb(vmi, pid);
        printf("CR3 for process (%d) == %llx\n", pid, (unsigned long long)cr3);
    }

    // Get the value of lstar and cstar for the system.
    // NOTE: all vCPUs have the same value for these registers
    vmi_get_vcpureg(vmi, &lstar, MSR_LSTAR, 0);
    vmi_get_vcpureg(vmi, &cstar, MSR_CSTAR, 0);
    vmi_get_vcpureg(vmi, &sysenter_ip, SYSENTER_EIP, 0);
    printf("vcpu 0 MSR_LSTAR == %llx\n", (unsigned long long)lstar);
    printf("vcpu 0 MSR_CSTAR == %llx\n", (unsigned long long)cstar);
    printf("vcpu 0 MSR_SYSENTER_IP == %llx\n", (unsigned long long)sysenter_ip);

    ia32_sysenter_target = vmi_translate_ksym2v(vmi, "ia32_sysenter_target");
    printf("ksym ia32_sysenter_target == %llx\n", (unsigned long long)ia32_sysenter_target);

    /* Per Linux ABI, this VA represents the start of the vsyscall page 
     *  If vsyscall support is enabled (deprecated or disabled on many newer 
     *  3.0+ kernels), it is accessible at this address in every process.
     */ 
    vsyscall = 0xffffffffff600000;

    // Translate to a physical address.
    phys_lstar= vmi_translate_kv2p(vmi, lstar);
    printf("Physical LSTAR == %llx\n", (unsigned long long)phys_lstar);

    phys_cstar= vmi_translate_kv2p(vmi, cstar);
    printf("Physical CSTAR == %llx\n", (unsigned long long)phys_cstar);

    phys_sysenter_ip= vmi_translate_kv2p(vmi, sysenter_ip);
    printf("Physical SYSENTER_IP == %llx\n", (unsigned long long)phys_sysenter_ip);

    phys_ia32_sysenter_target = vmi_translate_kv2p(vmi,ia32_sysenter_target);
    printf("Physical ia32_sysenter_target == %llx\n", (unsigned long long)ia32_sysenter_target);
    phys_vsyscall = vmi_translate_kv2p(vmi,vsyscall);
    printf("Physical phys_vsyscall == %llx\n", (unsigned long long)phys_vsyscall);


    // Get only the page that the handler starts.
    printf("LSTAR Physical PFN == %llx\n", (unsigned long long)(phys_lstar >> 12));
    printf("CSTAR Physical PFN == %llx\n", (unsigned long long)(phys_cstar >> 12));
    printf("SYSENTER_IP Physical PFN == %llx\n", (unsigned long long)(phys_sysenter_ip >> 12));
    printf("phys_vsyscall Physical PFN == %llx\n", (unsigned long long)(phys_vsyscall >> 12));
    printf("phys_ia32_sysenter_target Physical PFN == %llx\n", (unsigned long long)(phys_ia32_sysenter_target >> 12));

    /* Configure an event to track when the process is running.
     * (The CR3 register is updated on task context switch, allowing
     *  us to follow as various tasks are scheduled and run upon the CPU)
     */
    memset(&cr3_event, 0, sizeof(vmi_event_t));
    cr3_event.type = VMI_EVENT_REGISTER;
    cr3_event.reg_event.reg = CR3;

    /* Observe only write events to the given register. 
     *   NOTE: read events are unsupported at this time.
     */
    cr3_event.reg_event.in_access = VMI_REGACCESS_W;

    /* Optional (default = 0): Trigger on change 
     *  Causes events to be delivered by the hypervisor to this monitoring
     *   program if and only if the register value differs from that previously 
     *   observed.
     *  Usage: cr3_event.reg_event.onchange = 1;
     *
     * Optional (default = 0): Asynchronous event delivery
     *  Causes events to be delivered by the hypervisor to this monitoring
     *   program if and only if the register value differs from that previously
     *   observed.
     *  Usage: cr3_event.reg_event.async =1;
     */

    if(pid == -1){
        cr3_event.callback = cr3_all_tasks_callback;
        vmi_register_event(vmi, &cr3_event);
    } else {
        cr3_event.callback = cr3_one_task_callback;
        /* This acts as a filter: if the CR3 value at time of event == the CR3
         *  we wish to inspect, then the callback will be invoked. Otherwise,
         *  no action is taken.
         */
        cr3_event.reg_event.equal = cr3;
        vmi_register_event(vmi, &cr3_event);
    }

    // Setup a default event for tracking memory at the syscall handler.
    // But don't install it; that will be done by the cr3 handler.
    memset(&msr_syscall_sysenter_event, 0, sizeof(vmi_event_t));
    msr_syscall_sysenter_event.type = VMI_EVENT_MEMORY;
    msr_syscall_sysenter_event.mem_event.physical_address = phys_sysenter_ip;
    msr_syscall_sysenter_event.mem_event.npages = 1;
    msr_syscall_sysenter_event.mem_event.granularity=VMI_MEMEVENT_PAGE;

    memset(&kernel_sysenter_target_event, 0, sizeof(vmi_event_t));
    kernel_sysenter_target_event.type = VMI_EVENT_MEMORY;
    kernel_sysenter_target_event.mem_event.physical_address = phys_ia32_sysenter_target;
    kernel_sysenter_target_event.mem_event.npages = 1;
    kernel_sysenter_target_event.mem_event.granularity=VMI_MEMEVENT_PAGE;

    memset(&kernel_vsyscall_event, 0, sizeof(vmi_event_t));
    kernel_vsyscall_event.type = VMI_EVENT_MEMORY;
    kernel_vsyscall_event.mem_event.physical_address = phys_vsyscall;
    kernel_vsyscall_event.mem_event.npages = 1;
    kernel_vsyscall_event.mem_event.granularity=VMI_MEMEVENT_PAGE;

    while(!interrupted){
        printf("Waiting for events...\n");
        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;
}
コード例 #6
0
ファイル: event-example.c プロジェクト: chinaJack/libvmi
int main (int argc, char **argv)
{
    vmi_instance_t vmi = NULL;
    status_t status = VMI_SUCCESS;

    struct sigaction act;

    reg_t lstar = 0;
    addr_t phys_lstar = 0;
    reg_t cstar = 0;
    addr_t phys_cstar = 0;
    reg_t sysenter_ip = 0;
    addr_t phys_sysenter_ip = 0;

    addr_t ia32_sysenter_target = 0;
    addr_t phys_ia32_sysenter_target = 0;
    addr_t vsyscall = 0;
    addr_t phys_vsyscall = 0;

    char *name = NULL;
    vmi_pid_t pid = -1;

    if(argc < 2){
        fprintf(stderr, "Usage: events_example <name of VM> <PID of process to track {optional}>\n");
        exit(1);
    }

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

    // Arg 2 is the pid of the process to track.
    if(argc == 3)
        pid = (int) strtoul(argv[2], NULL, 0);

    /* 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");
    }

    // Get the cr3 for this process.
    /*
addr_t vmi_pid_to_dtb (vmi_instance_t vmi, vmi_pid_t pid)
Given a pid, this function returns the virtual address of the directory table base for this process' address space. 
This value is effectively what would be in the CR3 register while this process is running.

Parameters

[in] vmi LibVMI instance
[in] pid Desired process id to lookup
Returns

OrderedDict([(u'emphasis', u'pid'), ('#text', u'The directory table base virtual address for')])
    */
    if(pid != -1) {
        cr3 = vmi_pid_to_dtb(vmi, pid);  //虚拟机句柄和进程id  进程基地址
        printf("CR3 for process (%d) == %llx\n", pid, (unsigned long long)cr3);
    }

    // Get the value of lstar and cstar for the system.
    // NOTE: all vCPUs have the same value for these registers
    //status_t vmi_get_vcpureg (vmi_instance_t vmi, reg_t *value, registers_t reg, unsigned long vcpu)
  
  //获取特定寄存器值
    vmi_get_vcpureg(vmi, &lstar, MSR_LSTAR, 0); 
    vmi_get_vcpureg(vmi, &cstar, MSR_CSTAR, 0);
    vmi_get_vcpureg(vmi, &sysenter_ip, SYSENTER_EIP, 0);
  
  //在调用SYSENTER指令前,软件必须通过下面的MSR寄存器,指定0层的代码段和代码指针,0层的堆栈段和堆栈指针:
    printf("vcpu 0 MSR_LSTAR == %llx\n", (unsigned long long)lstar);
    printf("vcpu 0 MSR_CSTAR == %llx\n", (unsigned long long)cstar);
    printf("vcpu 0 MSR_SYSENTER_IP == %llx\n", (unsigned long long)sysenter_ip);

/*
addr_t vmi_translate_ksym2v (vmi_instance_t vmi, const char *symbol)
Performs the translation from a kernel symbol to a virtual address.

Parameters

[in] vmi LibVMI instance
[in] symbol Desired kernel symbol to translate
Returns

Virtual address, or zero on error
*/
    ia32_sysenter_target = vmi_translate_ksym2v(vmi, "ia32_sysenter_target");
    printf("ksym ia32_sysenter_target == %llx\n", (unsigned long long)ia32_sysenter_target);
//??? 返回结果为0 岂不是发生了error


    /* Per Linux ABI, this VA represents the start of the vsyscall page 
     *  If vsyscall support is enabled (deprecated or disabled on many newer 
     *  3.0+ kernels), it is accessible at this address in every process.
     */ 
    vsyscall = 0xffffffffff600000;

    // Translate to a physical address.
    phys_lstar= vmi_translate_kv2p(vmi, lstar);
    printf("Physical LSTAR == %llx0\n", (unsigned long long)phys_lstar);

    phys_cstar= vmi_translate_kv2p(vmi, cstar);
    printf("Physical CSTAR == %llx\n", (unsigned long long)phys_cstar);

    phys_sysenter_ip= vmi_translate_kv2p(vmi, sysenter_ip);
    printf("Physical SYSENTER_IP == %llx\n", (unsigned long long)phys_sysenter_ip);

    phys_ia32_sysenter_target = vmi_translate_kv2p(vmi,ia32_sysenter_target);
    printf("Physical ia32_sysenter_target == %llx\n", (unsigned long long)ia32_sysenter_target);
    /*
http://www.longene.org/forum/viewtopic.php?f=5&t=8851
在x86结构中,较新的CPU都提供了sysenter/sysexit指令,专门用于系统调用的进入和退出,由于去掉了一些不必要的检查,它的速度比以前的int指令要快。
因此在新的Linux系统中,大部分系统调用都采用了sysenter代替原来的int 80。除了一些比较慢的系统调用,如clone、execve等少数几个,因为对于这种系统调用,
进入/退出内核空间所费的时钟周期,相对于其处理时间,几乎可以忽略不计。
考虑到和glibc的对接问题,现在glibc中不直接调用int 80或者sysenter。而是采用vdso方式,在内核中生成一个页面,用于系统调用,
叫做vsyscall,在load_elf_binary时,会将其映射到用户空间,glibc直接调用其中的函数。

关于sysenter的一些资料,可以看这里http://www.cnblogs.com/yangnas/archive/2010/04/28/1723232.html
    */
    phys_vsyscall = vmi_translate_kv2p(vmi,vsyscall);
    printf("Physical phys_vsyscall == %llx\n", (unsigned long long)phys_vsyscall);


    // Get only the page that the handler starts.
    printf("LSTAR Physical PFN == %llx\n", (unsigned long long)(phys_lstar >> 12));
    printf("CSTAR Physical PFN == %llx\n", (unsigned long long)(phys_cstar >> 12));
    printf("SYSENTER_IP Physical PFN == %llx\n", (unsigned long long)(phys_sysenter_ip >> 12));
    printf("phys_vsyscall Physical PFN == %llx\n", (unsigned long long)(phys_vsyscall >> 12));
    printf("phys_ia32_sysenter_target Physical PFN == %llx\n", (unsigned long long)(phys_ia32_sysenter_target >> 12));

    /* Configure an event to track when the process is running.
     * (The CR3 register is updated on task context switch, allowing
     *  us to follow as various tasks are scheduled and run upon the CPU)
     */
    memset(&cr3_event, 0, sizeof(vmi_event_t));
    cr3_event.type = VMI_EVENT_REGISTER;
    cr3_event.reg_event.reg = CR3;

    /* Observe only write events to the given register. 
     *   NOTE: read events are unsupported at this time.
     */
    cr3_event.reg_event.in_access = VMI_REGACCESS_W;

    /* Optional (default = 0): Trigger on change 
     *  Causes events to be delivered by the hypervisor to this monitoring
     *   program if and only if the register value differs from that previously 
     *   observed.
     *  Usage: cr3_event.reg_event.onchange = 1;
     *
     * Optional (default = 0): Asynchronous event delivery
     *  Causes events to be delivered by the hypervisor to this monitoring
     *   program if and only if the register value differs from that previously
     *   observed.
     *  Usage: cr3_event.reg_event.async =1;
     */


//重要 注册事件 回调函数
    if(pid == -1){  //如果没加参数  就为-1
        cr3_event.callback = cr3_all_tasks_callback;
        vmi_register_event(vmi, &cr3_event);
    }
    else {
        cr3_event.callback = cr3_one_task_callback;
        /* This acts as a filter: if the CR3 value at time of event == the CR3
         *  we wish to inspect, then the callback will be invoked. Otherwise,
         *  no action is taken.
         */
         //只有当事件发生时,cr3的值等于我们一开始注册的进程的cr3值,才会调用回调函数
        cr3_event.reg_event.equal = cr3;            //保存原始的cr3的值
        vmi_register_event(vmi, &cr3_event);
    }


//设置内存事件,在cr3的事件处理函数中进行绑定
    // Setup a default event for tracking memory at the syscall handler.
    // But don't install it; that will be done by the cr3 handler.
    memset(&msr_syscall_sysenter_event, 0, sizeof(vmi_event_t));
    msr_syscall_sysenter_event.type = VMI_EVENT_MEMORY; 
    msr_syscall_sysenter_event.mem_event.physical_address = phys_sysenter_ip;
    msr_syscall_sysenter_event.mem_event.npages = 1;
    msr_syscall_sysenter_event.mem_event.granularity=VMI_MEMEVENT_PAGE;

    memset(&kernel_sysenter_target_event, 0, sizeof(vmi_event_t));
    kernel_sysenter_target_event.type = VMI_EVENT_MEMORY;
    kernel_sysenter_target_event.mem_event.physical_address = phys_ia32_sysenter_target;
    kernel_sysenter_target_event.mem_event.npages = 1;
    kernel_sysenter_target_event.mem_event.granularity=VMI_MEMEVENT_PAGE;

    memset(&kernel_vsyscall_event, 0, sizeof(vmi_event_t));
    kernel_vsyscall_event.type = VMI_EVENT_MEMORY;
    kernel_vsyscall_event.mem_event.physical_address = phys_vsyscall;
    kernel_vsyscall_event.mem_event.npages = 1;
    kernel_vsyscall_event.mem_event.granularity=VMI_MEMEVENT_PAGE;

    while(!interrupted){
        printf("Waiting for events...\n");
        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;
}
コード例 #7
0
ファイル: va-pages.c プロジェクト: smaresca/libvmi
event_response_t cr3_callback(vmi_instance_t vmi, vmi_event_t *event) {

    va_pages = vmi_get_va_pages(vmi, event->reg_event.value);

    GSList *loop = va_pages;
    while(loop) {
        page_info_t *page = loop->data;

        // Demonstrate using access_context_t
        access_context_t ctx = {
            .translate_mechanism = VMI_TM_PROCESS_DTB,
            .addr = page->vaddr,
            .dtb = event->reg_event.value,
        };

        uint64_t test;
        if(VMI_FAILURE == vmi_read_64(vmi, &ctx, &test)) {
            printf("Page in virtual address space of DTB 0x%"PRIx64" unaccessible: 0x%"PRIx64".\t"
                   "Size: 0x%"PRIx64"\n",
                   ctx.dtb, page->vaddr, (uint64_t)page->size);
        }

        loop=loop->next;
    }
    free_va_pages();
    return 0;
}

int main (int argc, char **argv)
{
    vmi_instance_t vmi = NULL;
    status_t status = VMI_SUCCESS;

    struct sigaction act;

    char *name = NULL;
    va_pages = NULL;

    if(argc < 2) {
        fprintf(stderr, "Usage: events_example <name of VM>\n");
        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");
    }

    /* Configure an event to track when the process is running.
     * (The CR3 register is updated on task context switch, allowing
     *  us to follow as various tasks are scheduled and run upon the CPU)
     */
    SETUP_REG_EVENT(&cr3_event, CR3, VMI_REGACCESS_W, 0, cr3_callback);
    vmi_register_event(vmi, &cr3_event);

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

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

    return 0;
}
コード例 #8
0
int main (int argc, char **argv)
{
	// local variables
	vmi_instance_t vmi;
	int ret_val = 0; // return code for after goto
	struct sigaction signal_action;

	// process list vars
	vmi_pid_t pid = 0;
	char *procname = NULL;
	addr_t list_head = 0;
	addr_t next_list_entry = 0;
	addr_t current_process = 0;
	addr_t tmp_next = 0;
	status_t status;

	// breakpoint vars
	char*			*sym;
	uint16_t	*off;
	vmi_pid_t *bpid;
	addr_t		*add;
	uint8_t		*byt;

	addr_t lib_map_addr = 0;
	addr_t BN_rand_addr = 0;
	int bnrand_jump_offset = 0;
	addr_t bnrand_addr = 0;

	// this is the VM or file that we are looking at
	if (argc < 2) {
		printf("Usage: %s <vmname>\n", argv[0]);
		return 1;
	}
	
	char *name = argv[1];

	////////////////////
	// Initialization // 
	////////////////////

	// initialize the libvmi library
	printf("Initializing libvmi for VM \"%s\"\n", name);
	if (vmi_init(&vmi, VMI_XEN|VMI_INIT_COMPLETE|VMI_INIT_EVENTS, name) == VMI_FAILURE) {
		printf("Failed to init LibVMI library.\n");
		ret_val = 2;
		goto error_exit;
	}

	// verify OS is Linux
	printf("Verifying the VM is running Linux...");
	// TODO: verify that the VM is running a *supported* Linux kernel
	// if kernel is not one we recognize, don't run because we'll be mucking around in memory we don't understand
	if (VMI_OS_LINUX != vmi_get_ostype(vmi)) { // this only checks if /etc/libvmi.conf says it's "Linux"
		printf("\nVM is running %s, exiting...\n", vmi_get_ostype(vmi));
		ret_val = 3;
		goto error_exit;
	}
	printf(" Yup. Good to go.\n");

	// pause the vm for consistent memory access
	printf("Pausing the VM\n");
	if (vmi_pause_vm(vmi) != VMI_SUCCESS) {
		printf("Failed to pause VM\n");
		ret_val = 4;
		goto error_exit; // don't return directly, do cleanup first
	}

	tasks_offset					= vmi_get_offset(vmi, "linux_tasks");
	name_offset						= vmi_get_offset(vmi, "linux_name");
	pid_offset						= vmi_get_offset(vmi, "linux_pid");
	mm_offset							= vmi_get_offset(vmi, "linux_mm");
	// hardcoded because config_parser doesn't support dynamic config vars
	mmap_offset						= 0x0;
	vm_area_file_offset		= 0xa0;
	vm_area_next_offset		= 0x10;
	vm_area_start_offset	= 0x0;
	file_path_offset			= 0x10;
	dentry_offset					= 0x8;
	iname_offset					= 0x38;
	//mmap_offset = vmi_get_offset(vmi, "linux_mmap");
	//vm_area_file_offset = vmi_get_offset(vmi, "linux_vm_file");
	//vm_area_next_offset = vmi_get_offset(vmi, "linux_vm_next");
	//vm_area_start_offset = vmi_get_offset(vmi, "linux_vm_start");
	//file_path_offset = vmi_get_offset(vmi, "linux_f_path");
	//dentry_offset = vmi_get_offset(vmi, "linux_dentry");
	//iname_offset = vmi_get_offset(vmi, "linux_d_iname");

	if (0 == tasks_offset) {
		printf("Failed to find tasks_offset\n");
		goto error_exit;
	}   
	if (0 == pid_offset) {
		printf("Failed to find pid_offset\n");
		goto error_exit;
	}   
	if (0 == name_offset) {
		printf("Failed to find name_offset\n");
		goto error_exit;
	}   
	if (0 == mm_offset) {
		printf("Failed to find mm_offset\n");
		goto error_exit;
	}   
	//if (0 == mmap_offset) {
	//	printf("Failed to find mmap_offset\n");
	//	goto error_exit;
	//}   
	//if (0 == vm_area_file_offset) {
	//	printf("Failed to find vm_area_file_offset\n");
	//	goto error_exit;
	//}   
	//if (0 == vm_area_next_offset) {
	//	printf("Failed to find vm_area_next_offset\n");
	//	goto error_exit;
	//}   
	//if (0 == vm_area_start_offset) {
	//	printf("Failed to find vm_area_start_offset\n");
	//	goto error_exit;
	//}   
	//if (0 == file_path_offset) {
	//	printf("Failed to find file_path_offset\n");
	//	goto error_exit;
	//}   
	//if (0 == dentry_offset) {
	//	printf("Failed to find dentry_offset\n");
	//	goto error_exit;
	//}   
	//if (0 == iname_offset) {
	//	printf("Failed to find iname_offset\n");
	//	goto error_exit;
	//}   

	// Set up breakpoints
	breakpoints = (breakpoint_t*)calloc(MAX_BREAKPOINTS, sizeof(breakpoint_t)); // allocate space for each breakpoint, zero memory
	//add_breakpoint("extract_entropy_user", 155, 0, 0xe8, before_extract_buf);
	//add_breakpoint("extract_entropy_user", 160, 0, 0x83, after_extract_buf);
	// new breakpoints created below

	//////////////////////////
	// Find apache2 process //
	//////////////////////////

	// find pid of apache2 processes
	// for each process, read symbol table and find BN_rand function
	// at offset +13 bytes from BN_rand, we find an offset from the instruction at BN_rand+17 (probably around -700 bytes)
	// +570 bytes from the offset above, we find the instruction at which we want a breakpoint
	// so, breakpoint at BN_rand+17+[BN_rand+13]+570
	// then, at callback, read r13 for address of buffer, overwrite with TODO bytes

	// find pid of apache2 processes
	list_head = vmi_translate_ksym2v(vmi, "init_task") + tasks_offset; // find init_task struct and move to first linked list entry
	next_list_entry = list_head; // iterator
	do {
		current_process = next_list_entry - tasks_offset; // subtract tasks_offset back off to get to head of struct
		vmi_read_32_va(vmi, current_process + pid_offset, 0, (uint32_t*)&pid); // get pid of this process
		procname = vmi_read_str_va(vmi, current_process + name_offset, 0); // get process name of this process
		if (strncmp(procname,"apache2",sizeof("apache2")) == 0) {
			printf("Finding library address in %s [pid %d]\n",procname,pid);
			lib_map_addr = walk_vmmap_for_lib(vmi, current_process, "libcrypto.so.1.0.2");
			if (lib_map_addr == 0) { // if failed to find lib
				printf("Failed to find library in %s\n",procname);
				ret_val = 9;
				goto error_exit;
			}
			printf("Found library address: 0x%llx\n", lib_map_addr);
			// for each process, read symbol table and find BN_rand function
			BN_rand_addr = lib_map_addr + 0xd5a50; // static offset for BN_rand function
			// at offset +13 bytes from BN_rand, we find an offset from the instruction at BN_rand+17 (probably around -700 bytes)
			vmi_read_32_va(vmi, BN_rand_addr+13, pid, &bnrand_jump_offset); // get jump offset to bnrand function
			//printf("jump offset: %d\n",bnrand_jump_offset);
			bnrand_addr = BN_rand_addr+17+bnrand_jump_offset; // get address of bnrand function
			//printf("bnrand: 0x%llx\n", bnrand_addr);
			// +570 bytes from the offset above, we find the instruction at which we want a breakpoint
			add_breakpoint_addr(bnrand_addr + 570, pid, 0x31, bnrand_callback);
			//printf("Added breakpoint at 0x%llx\n",bnrand_addr+570);
		}
		status = vmi_read_addr_va(vmi, next_list_entry, 0, &next_list_entry); // follow linked-list->next to next element
		if (status == VMI_FAILURE) {
			printf("Failed to read next pointer in loop at %"PRIx64"\n", next_list_entry);
			goto error_exit;
		}

	} while(next_list_entry != list_head);




	for (int i = 0; i < num_breakpoints; i++) { // iterate over breakpoints and find the right addresses for them

		////////////////////////////////////////////
		// Find memory location to put breakpoint //
		////////////////////////////////////////////

		// assign short names (note: modifying these modifies the breakpoint struct)
		sym = &breakpoints[i].symbol;
		off = &breakpoints[i].offset;
		bpid = &breakpoints[i].pid;
		add = &breakpoints[i].addr;
		byt = &breakpoints[i].inst_byte; // remember that if this is not set above, it should be zeroed from calloc

		if (breakpoints[i].addr == 0) { // if don't have address, find symbol
			// find address to break on
			printf("Accessing System Map for %s symbol\n", *sym);
			*add = vmi_translate_ksym2v(vmi, *sym) + *off;
			printf("%s + %u is at 0x%llx\n", *sym, *off, *add);
		}

		// either verify the byte there is correct, or record which byte is there for later replacing
		if (*byt == 0) { // if this byte was not set, we need to get it
			vmi_read_8_va(vmi, *add, *bpid, byt); // read it directly into byt
			printf("[pid %d] Saving byte at address 0x%llx: %x\n", *bpid, *add, *byt);
		} else { // if the byte was set, verify that it's currently set to that value
			uint8_t temp_byte = 0;
			vmi_read_8_va(vmi, *add, *bpid, &temp_byte); // read it temporarily
			printf("[pid %d] Checking byte at address 0x%llx is set to %x: %x\n", *bpid, *add, *byt, temp_byte);
			if (*byt != temp_byte) { // uh oh, we have an error
				ret_val = 8;
				goto error_exit;
			}
		}
	} // end first for loop after breakpoints are constructed properly

	///////////////////
	// Main gameplan //
	//               //
	// https://groups.google.com/forum/#!topic/vmitools/jNGxM0LBEDM
	// Based on the google groups discussion above (which I wish I found earlier, meh), it looks like the way people trap on instructions is to:
	//	1) actually *modify* the memory to have the 0xcc (interrupt 3, aka breakpoint) instruction in place of the instruction it would have executed
	//	2) register an event on receiving the INT3 signal and receive the callback
	//	3) at the end of the callback, fix the memory to its original instruction,
	//	4) single-step one instruction forward, executing the one instruction, then getting another callback
	//	5) replace the previous instruction with to 0xcc, "resetting" the breakpoint, then clearing the event and continuing
	//               //
	///////////////////

	for (int i = 0; i < num_breakpoints; i++) { // iterate over breakpoints and insert them all

		// assign short names (note: modifying these modifies the breakpoint struct)
		add = &breakpoints[i].addr;
		bpid = &breakpoints[i].pid;
		byt = &breakpoints[i].inst_byte;

		// Step 1: modify memory in the VM with an INT3 instruction (0xcc)
		printf("[pid %d] Setting breakpoint at address 0x%llx.\n", *bpid, *add);
		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, *add, *bpid, &int3)) {
			printf("[pid %d] Couldn't write INT3 instruction to memory... exiting.\n", *bpid);
			ret_val = 5;
			goto error_exit;
		}

		// debug: check memory is now an INT3 instruction
		uint8_t temp_byte = 0;
		vmi_read_8_va(vmi, *add, 0, &temp_byte);
		printf("[pid %d] This should be an INT3 instruction (0xcc): 0x%x\n", *bpid, temp_byte);


	} // end second for loop after breakpoints are all inserted and callback is registered

	// Step 2: register an event on receiving INT3 signal
	printf("Creating event for callback when breakpoint is reached.\n");
	memset(&rng_event, 0, sizeof(vmi_event_t)); // clear rng_event so we can set everything fresh
	rng_event.type = VMI_EVENT_INTERRUPT; // interrupt event -- trigger when interrupt occurs
	rng_event.interrupt_event.intr = INT3; // trigger on INT3 instruction
	rng_event.interrupt_event.reinject = 0; // swallow interrupt silently without passing it on to guest
	rng_event.callback = rng_int3_event_callback; // reference to our callback function
	printf("Registering event...\n");
	if (VMI_SUCCESS == vmi_register_event(vmi, &rng_event)) {; // register the event!
		printf("Event Registered!\n");
	} else { // uh oh, event failed
		printf("Problem registering event... exiting.\n");
		ret_val = 6;
		goto error_exit; // don't return directly, do cleanup first
	}

	// resume the VM
	printf("Resuming the VM\n");
	vmi_resume_vm(vmi);

	//////////////////////////////////////
	// Spin and wait for event callback // 
	//////////////////////////////////////

	// for a clean exit, catch signals (from host, not VM), set "interrupted" to non-zero, exit while loop at end of main()
	signal_action.sa_handler = close_handler;
	signal_action.sa_flags = 0;
	sigemptyset(&signal_action.sa_mask);
	sigaction(SIGHUP,  &signal_action, NULL);
	sigaction(SIGTERM, &signal_action, NULL);
	sigaction(SIGINT,  &signal_action, NULL);
	sigaction(SIGALRM, &signal_action, NULL);

	while(!interrupted) { // until an interrupt happens
		printf("Waiting for events...\n");
		if (VMI_SUCCESS != vmi_events_listen(vmi, 500)) { // listen for events for 500ms (no event = VMI_SUCCESS)
			printf("Error waiting for events... exiting.\n");
			interrupted = -1;
		}
	}
	printf("Finished with test.\n");

	//////////////////
	// Exit cleanly // 
	//////////////////

error_exit:
	// attempt to remove breakpoints
	for (int i = 0; i < num_breakpoints; i++) { // iterate over breakpoints and insert them all

		// assign short names (note: modifying these modifies the breakpoint struct)
		add = &breakpoints[i].addr;
		bpid = &breakpoints[i].pid;
		byt = &breakpoints[i].inst_byte;

		printf("[pid %d] Removing breakpoint %d at 0x%llx.\n", *bpid, i, *add);
		if (VMI_SUCCESS != vmi_write_8_va(vmi, *add, *bpid, byt)) {
			printf("Couldn't write to memory... exiting.\n");
			ret_val = 7;
		}
	}

	// resume the vm
	printf("Resuming the VM\n");
	vmi_resume_vm(vmi);

	// cleanup any memory associated with the LibVMI instance
	printf("Cleaning up\n");
	vmi_destroy(vmi);

	return ret_val;
}