Dr. Memory
Dr. Syscall: System Call Monitoring Extension

The drsyscall DynamoRIO Extension provides system call monitoring features beyond the basics in the DynamoRIO API itself. drsyscall is part of the Dr. Memory Framework.

Setup

To use drsyscall with your client, first locate the Dr. Memory Framework. Then use the standard method of using an Extension with the name drsyscall. The two steps will look like this in your client's CMakeLists.txt file:

find_package(DrMemoryFramework)
use_DynamoRIO_extension(clientname drsyscall)

To point CMake at the framework, set the DrMemoryFramework_DIR variable to point at the drmf subdirectory of the Dr. Memory package that you are using. For example:

cmake -G"Ninja" -DDynamoRIO_DIR=c:/path/to/DynamoRIO-Windows-4.1.0-8/cmake -DDrMemoryFramework_DIR=c:/path/to/DrMemory-Windows-1.6.0-2/drmf ../mysrcs/

That will automatically set up the include path and library dependence.

Your client must call drsys_init() prior to accessing any API routines in drsyscall, and should call drsys_exit() at process exit time.

Event Replacement

drsyscall uses the drmgr Extension to ensure its events occur at the proper order. A user of drsyscall must use the drmgr versions of the basic block and thread events.

Dr. Syscall API

drsyscall provides the following key features:

  1. System call name to number querying
  2. System call number to name querying
  3. System call argument type iteration
  4. System call argument value iteration
  5. Query whether a system call return value indicates success
  6. Iteration over every memory region read or written by a system call
  7. Storage of system call argument values for access in post-syscall events

Many features of drsyscall operate on the current in-progress system call. The client should register for the pre- and post-syscall events through drmgr. In those events, the client can then invoke drsyscall API routines to query the current system call. The client should normally use a default priority for its system call events to ensure that drsyscall's per-system-call initialization is in place prior to invoking drsyscall functions.

If the client wishes to modify the machine context, system call parameters, or system call return value, the client must use a separate system call event that is ordered prior to DRMGR_PRIORITY_PRESYS_DRSYS or DRMGR_PRIORITY_POSTSYS_DRSYS.

The client can statically iterate over the types of the parameters to every system call in its dr_init() routine and decide which system calls it wants to monitor. It should then request that drsyscall filter those system calls. Only filtered system calls can be dynamically queried.

When dealing with system call results and identifying whether a system call succeeded, drsys_cur_syscall_result() distinguishes itself from dr_syscall_get_result_ex() by providing accurate results for all system calls, in particular including Windows win32k.sys graphical (NtGdi) and user (NtUser) system calls. It also knows which system calls return 64-bit results, elminating the need for the caller to specifically request the top 32 bits in such cases. For setting the result value of a system call, currently drsyscall does not provide its own routine and dr_syscall_set_result_ex() should be used.

System Call Numbers

On Linux, the system call number is the standard number exported by the kernel. For SYS_ioctl, a secondary number indicates the request code. drsyscall does not currently split the 32-bit SYS_socketcall or IPC system calls into secondary numbers.

On Windows, drsyscall uses the raw number from the eax register. This includes the WOW64 index stored in the upper 16 bits on Windows 8 and beyond. Secondary numbers are used for NtUserCall* system calls.

For MacOS, whether 32-bit or 64-bit, we normalize the system call number to a positive integer with the top 8 bits set to 0x1 for a Mach system call, 0x3 for Machdep, and 0x0 for BSD (allowing the direct use of SYS_ constants). The user can access the raw eax register in the pre-syscall event to view the unmodified number, whose encoding varies depending on the bitwidth and interrupt vector used.