我正在努力完成一个项目,该项目将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非root中的syscall使用int 80h
并挂接这个中断。请分享关于这次黑客攻击的任何建议。
我不会向您解释这段代码(需要更多,但我不能,因为git存储库仍然不可用)
但是,在vmx非root中检测系统调用依赖于本文第6页和第7页中的一些技巧。基本上,检测
- syscall/sysret:您必须在EFER中禁用CSE位,这样任何使用syscall/ssysret的尝试都会导致您将截获的无效操作码异常
- sysenter/sysexit:您必须将sysenter_CS_MSR保存在系统管理程序中的某个位置,然后用null值加载它,这样任何使用sysenter/ssysexit的操作都会导致您将捕获的一般保护异常