简单的活着

a API to read/write syscall's arguments

Posted on By Mista Cai

#可读写syscall参数的API

1. 读取syscall参数

我们需要在根据nitro事件构建的sycall对象之上设计一个API,提供透明的方式来获取跨不同操作系统的syscall参数。

以NtOpenFile MSDN定义为例:

NTSTATUS NtOpenFile(
  _Out_ PHANDLE            FileHandle,
  _In_  ACCESS_MASK        DesiredAccess,
  _In_  POBJECT_ATTRIBUTES ObjectAttributes,
  _Out_ PIO_STATUS_BLOCK   IoStatusBlock,
  _In_  ULONG              ShareAccess,
  _In_  ULONG              OpenOptions
);

系统调用将参数传给内核的方式取决于:

  • 操作系统调用协议
  • 系统调用类型(syscall/sysenter)
  Windows sysenter Windows syscall Linux sysenter Linux syscall
arg 1 edx rcx ebx rdi
arg 2 edx + 4 rdx ecx rsi
arg 3 edx + 8 r8 edx rdx
arg 4 edx + 12 r9 esi r10
arg 5 edx + 16 rsp + ? edi r8
arg 6 edx + 20 rsp + ? + 8 ebp r9
arg 7 edx + 24 rsp + ? + 16 no no

关键点

  • Linux系统调用最多具有6个参数
  • Linux始终将寄存器用于syscall参数传递
  • Windows使用寄存器和内存。

修改系统调用参数

由上述描述可知,为了即时修改系统调用参数以改变虚拟机的行为,必须应对两种情况:

  • 参数存储在寄存器中,可以通过nitro_set_regs ioctl替换寄存器值;
  • 参数存储在内存中,利用libvmi的vmi_write_va API写入内存。

以NtOpenFile MSDN定义为例:

def enter_NtCreateFile(syscall):
            KeyHandle, DesiredAccess, object_attributes = syscall.collect_args(3)
            obj = ObjectAttributes(object_attributes, syscall.process)
            buffer = obj.ObjectName.Buffer
            access = FileAccessMask(DesiredAccess)
            syscall.hook = {
                'object_name': buffer,
                'access': access.rights
            }

注意

  • collect_args仅限于Windows/syscall