2015-12-21 3 views
3

Я пытаюсь выполнить проект, который переводит двоичный файл ELF в виртуальную машину, чтобы обеспечить процесс собственной среды выполнения, аналогичный http://dune.scs.stanford.edu/. Многие работы говорят «мы обнаруживаем системный вызов ....», но не указали подробности обнаружения, кроме этой статьи, код которой обнаруживает syscall в vmx non root ring 0. (поскольку процесс будет выполняться в этом кольце). Но я недостаточно некомпетентен, чтобы понять его метод из-за отсутствия документации и намеков в его статье. Соответствующий фрагмент кода, как показано ниже

/* 
* macro to switch to G0 fs.base 
* 
* NOTE: clobbers %rax, %rdx, and %rcx 
*/ 
    .macro SET_G0_FS_BASE 
    movq $0, %gs:IN_USERMODE 
    movq %gs:KFS_BASE, %rax 
    movq %gs:UFS_BASE, %rdx 
    cmp %rax, %rdx 
    je 1f 
#if USE_RDWRGSFS 
    wrfsbase %rax 
#else 
    movq %rax, %rdx 
    shrq $32, %rdx 
    movl $MSR_FS_BASE, %ecx 
    wrmsr 
#endif /* USE_RDWRGSFS */ 
1: 
    .endm 


__dune_syscall: 
    /* handle system calls from G0 */ 
    testq $1, %gs:IN_USERMODE 
    jnz 1f 
    pushq %r11 
    popfq 
    vmcall 
    jmp *%rcx 

1: 
    /* first switch to the kernel stack */ 
    movq %rsp, %gs:TMP 
    movq %gs:TRAP_STACK, %rsp 

    /* now push the trap frame onto the stack */ 
    subq $TF_END, %rsp 
    movq %rcx, RIP(%rsp) 
    movq %r11, RFLAGS(%rsp) 
    movq %r10, RCX(%rsp) /* fixup to standard 64-bit calling ABI */ 
    SAVE_REGS 0, 1 
    movq %gs:TMP, %rax 
    movq %rax, RSP(%rsp) 

    /* then restore the CPL0 FS base address */ 
    SET_G0_FS_BASE 

    /* then finally re-enable interrupts and jump to the handler */ 
    sti 
    movq %rsp, %rdi /* argument 0 */ 
    lea dune_syscall_handler, %rax 
    call *%rax 

    /* next restore the CPL3 FS base address */ 
    SET_G3_FS_BASE 

    /* then pop the trap frame off the stack */ 
    RESTORE_REGS 0, 1 
    movq RCX(%rsp), %r10 
    movq RFLAGS(%rsp), %r11 
    movq RIP(%rsp), %rcx 

    /* switch to the user stack and return to ring 3 */ 
    movq RSP(%rsp), %rsp 
    sysretq 

.globl __dune_syscall_end 
__dune_syscall_end: 
    nop 

Моими вопросов являются

1) Как выше кусок коды работает? Любое объяснение, указатель или ссылка будут полезны

2) Можно ли использовать любой другой способ обнаружения системного вызова в этом сценарии? Я думаю, что настройка с vdso будет другим решением. Что я могу сказать, чтобы заставить syscall в vmx non root использовать int 80h и перехватить это прерывание. Пожалуйста, поделитесь любым предложением для этого взлома.

+0

I гавань» t еще не прочитал весь вопрос, но да, построение ядра для экспорта заглушки 'int 0x80' в' vdso', а не 'sysenter', должно быть полностью прозрачным для glibc. Вы изучали механизм 'strace (1)' использует для отслеживания системных вызовов? Я не уверен, как он работает под капотом, но я знаю, что он основан на системном вызове 'ptrace (2)', который позволяет 'gdb' управлять другим процессом для одношаговой. Существует также 'ltrace (1)', который использует взломы shared-lib для отслеживания всех вызовов функций в shared libs. –

ответ

0

Я не собираюсь объяснять вам этот кусок кода (нужно будет иметь больше, но я не могу, потому что репозиторий не все еще доступен)

Но обнаружение системного вызова в VMX, не корень полагаться на некоторых трюках вы можете найти в этой paper, страница 6 и 7. в основном, для обнаружения

  • /SYSRET системного вызова: вы должны отключить CSE бит в вашем EFER так, что любая попытка использовать системный вызов/SYSRET приведет недопустимое исключение opcode, которое вы перехватите
  • SYSENTER/SYSEXIT: вы должны сохранить SYSENTER_CS_MSR где-то в гипервизора, а затем загрузить его с нулевым значением, так что любое использование SYSENTER/SYSEXIT приведет общее исключение защиты, что вы поймаете