Ejemplo n.º 1
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);
}
Ejemplo n.º 2
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);
    }
}
Ejemplo n.º 3
0
void carve_file_from_memory(drakvuf_t *drakvuf, addr_t ph_base,
        addr_t block_size) {

    addr_t aligned_file_size = struct_sizes[FILE_OBJECT];
    if(PM2BIT(drakvuf->pm) == BIT32) {
        // 8-byte alignment on 32-bit mode
        if(struct_sizes[FILE_OBJECT] % 8) {
            aligned_file_size += 8 - (struct_sizes[FILE_OBJECT] % 8);
        }
    } else {
        // 16-byte alignment on 64-bit mode
        if(struct_sizes[FILE_OBJECT] % 16) {
            aligned_file_size += 16 - (struct_sizes[FILE_OBJECT] % 16);
        }
    }

    addr_t file_base = ph_base + block_size - aligned_file_size;
    addr_t file_name = file_base + offsets[FILE_OBJECT_FILENAME];

    addr_t file_name_str = 0;
    uint16_t length = 0;

    vmi_read_addr_pa(drakvuf->vmi, file_name + offsets[UNICODE_STRING_BUFFER], &file_name_str);
    vmi_read_16_pa(drakvuf->vmi, file_name + offsets[UNICODE_STRING_LENGTH], &length);

    if (file_name_str && length) {
        unicode_string_t str = { .contents = NULL };
        str.length = length;
        str.encoding = "UTF-16";
        str.contents = malloc(length);
        vmi_read_va(drakvuf->vmi, file_name, 0, str.contents, length);
        unicode_string_t str2 = { .contents = NULL };
        status_t rc = vmi_convert_str_encoding(&str, &str2, "UTF-8");

        if (VMI_SUCCESS == rc) {
            PRINT_DEBUG("\tFile closing: %s.\n", str2.contents);
            volatility_extract_file(drakvuf, file_base);
            g_free(str2.contents);
        }

        free(str.contents);
    }
Ejemplo n.º 4
0
void volatility_extract_file(drakvuf_t *drakvuf, addr_t file_object) {

    char* profile = NULL;
    if (PM2BIT(drakvuf->pm) == BIT32) {
        profile = PROFILE32;
    } else {
        profile = PROFILE64;
    }

    char *command = g_malloc0(
            snprintf(NULL, 0, VOL_DUMPFILES, PYTHON, VOLATILITY, drakvuf->domID,
                     profile, file_object,
                    (drakvuf->dump_folder ? drakvuf->dump_folder : "/tmp")
                    ) + 1);
    sprintf(command, VOL_DUMPFILES, PYTHON, VOLATILITY, drakvuf->domID, profile,
            file_object,
            (drakvuf->dump_folder ? drakvuf->dump_folder : "/tmp"));

    PRINT_DEBUG("** RUNNING COMMAND: %s\n", command);
    g_spawn_command_line_sync(command, NULL, NULL, NULL, NULL);
    free(command);
}
Ejemplo n.º 5
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;
    }
}
Ejemplo n.º 6
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;
        }
    }
}