Uninformed: Informative Information for the Uninformed

Vol 8» 2007.Sep


SSDT

The System Service Descriptor Table (SSDT) is used by the Windows kernel when dispatching system calls. The SSDT itself is exported in kernel-mode through the nt!KeServiceDescriptorTable global variable. This variable contains information relating to system call tables that have been registered with the operating. In contrast to other operating systems, the Windows kernel supports the dynamic registration (nt!KeAddSystemServiceTable) of new system call tables at runtime. The two most common system call tables are those used for native and GDI system calls.

In the context of a local kernel-mode backdoor, system calls represent an obvious target due to the fact that they are implicitly tied to the privilege boundary that exists between user-mode and kernel-mode. The act of hooking a system call handler in kernel-mode makes it possible to expose a privileged backdoor into the kernel using the operating system's well-defined system call interface. Furthermore, hooking system calls makes it possible for the backdoor to alter data that is seen by user-mode and thus potentially hide its presence to some degree.

In practice, system calls can be hooked on Windows using two distinct strategies. The first strategy involves using generic function hooking techniques which are described in 2.1.1. The second strategy involves using the function pointer hooking technique which is described in 2.5. Using the function pointer hooking involves simply altering the function pointer associated with a specific system call index by accessed the system call table which contains the system call that is to be hooked.

The following code shows a very simple illustration of how one might go about hooking a system call in the native system call table on 32-bit versions of Windows2:

PVOID HookSystemCall(
  PVOID SystemCallFunction,
  PVOID HookFunction)
{
  ULONG SystemCallIndex =
    *(ULONG *)((PCHAR)SystemCallFunction+1);
  PVOID *NativeSystemCallTable =
    KeServiceDescriptorTable[0];
  PVOID OriginalSystemCall =
    NativeSystemCallTable[SystemCallIndex];

  NativeSystemCallTable[SystemCallIndex] = HookFunction;

  return OriginalSystemCall;
}

Category: Type I if prologue hook is used. Type IIa if the function pointer hook is used. The SSDT (both native and GDI) should effectively be considered write-once.

Origin: System call hooking has been used extensively for quite some time. Since this technique has become so well-known, its actual origins are unclear. The earliest description the authors could find was from M. B. Jones in a paper from 1993 entitled Interposition agents: Transparently interposing user code at the system interface[27]. Jones explains in his section on related work that he was unable to find any explicit research on the subject prior of agent-based interposition prior to his writing. However, it seems clear that system calls were being hooked in an ad-hoc fashion far in advance of this point. The authors were unable to find many of the papers cited by Jones. Plaguez appears to be one of the first (Jan, 1998) to publicly illustrate the usefulness of system call hooking in Linux with a specific eye toward security in Phrack 52[30].

Capabilities: Kernel-mode code execution.

Considerations: On certain versions of Windows XP, the SSDT is marked as read-only. This must be taken into account when attempting to write to the SSDT across multiple versions of Windows.

Covertness: System call hooks on Windows are very easy to detect. Comparing the in-memory SSDTs with the on-disk versions is one of the most common strategies employed.