如何强制使用int $ 0x80而不是sysenter进行系统调用检测

时间:2015-12-21 18:35:32

标签: linux kernel x86-64 virtualization system-calls

我正在尝试完成将ELF二进制文件转换为虚拟机的项目,以便为进程提供类似于http://dune.scs.stanford.edu/的自己的执行环境。许多论文说"我们检测到系统调用...."但没有提供检测的细节,除了本文的代码检测vmx非根环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进行调整将是其他解决方案。我能想到的是强制vmx non root中的syscall使用int 80h并挂钩此中断。请分享任何关于此黑客的建议。

1 个答案:

答案 0 :(得分:0)

我不打算向你解释这段代码(需要的不仅仅是那些,但我可以因为git存储库仍然无法使用)

但是检测vmx non root中的系统调用依赖于你可以在paper,第6页和第7页中找到的一些技巧。 基本上,要检测

  • syscall / sysret:你必须在你的EFER中禁用CSE位,这样任何使用syscall / sysret的尝试都会导致你将拦截无效的操作码异常
  • sysenter / sysexit:您必须将SYSENTER_CS_MSR保存在虚拟机管理程序中的某个位置,然后使用空值加载它,以便任何使用sysenter / sysexit都会导致您将捕获的常规保护异常