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

我正在尝试完成将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调整将是其他解决scheme。 我能想到的是强制在vmx非root的系统调用中使用int 80h并挂接此中断。 请分享这个黑客的任何build议。

我不会解释你这段代码(需要比这更多,但我不能,因为git存储库不可用)

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

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