The System Service Descriptor Table (SSDT) in kernel space contains the pointers to the system service routines (kernel functions) exported by the kernel executive (ntoskrnl.exe, ntkrnlpa.exe and so on). When an application calls an API such as WriteFile(), ReadFile(), or CreateProcess(), it calls the stub in the ntdll.dll which switches the thread to the kernel mode. The thread running in the kernel mode consults the SSDT to determine the address of the kernel function to invoke. The following screenshot illustrates this concept with an example of WriteFile() (the concept is similar for other APIs):

In general, ntoskrnl.exe exports core kernel API functions such as NtReadFile(), NtWrite()File, and so on. In the x86 platform, the pointers to these kernel functions are stored directly in the SSDT, whereas on the x64 platforms, SSDT does not contain the pointers. Instead, it stores an encoded integer that is decoded to determine the address of the kernel function. Irrespective of the implementation, the concept remains the same and the SSDT is consulted to determine the address of a specific kernel function. The following WinDbg command on the Windows7 x86 platform displays the contents of the SSDT. The entries in the table contain the pointers to the functions implemented by ntoskrnl.exe (nt). The order and the number of entries vary across operating system versions:
kd> dps nt!KiServiceTable
82a8f5fc 82c8f06a nt!NtAcceptConnectPort
82a8f600 82ad2739 nt!NtAccessCheck
82a8f604 82c1e065 nt!NtAccessCheckAndAuditAlarm
82a8f608 82a35a1c nt!NtAccessCheckByType
82a8f60c 82c9093d nt!NtAccessCheckByTypeAndAuditAlarm
82a8f610 82b0f7a4 nt!NtAccessCheckByTypeResultList
82a8f614 82d02611 nt!NtAccessCheckByTypeResultListAndAuditAlarm
[REMOVED]
There is a second table, similar to the SSDT, known as SSDT shadow. This table stores the pointers to the GUI-related functions exported by win32k.sys. To display the entries of both the tables, you can use the ssdt volatility plugin, as shown here. SSDT[0] refers to the native SSDT table and SSDT[1] refers to SSDT shadow:
$ python vol.py -f win7_x86.vmem --profile=Win7SP1x86 ssdt
Volatility Foundation Volatility Framework 2.6
[x86] Gathering all referenced SSDTs from KTHREADs...
Finding appropriate address space for tables...
SSDT[0] at 82a8f5fc with 401 entries
Entry 0x0000: 0x82c8f06a (NtAcceptConnectPort) owned by ntoskrnl.exe
Entry 0x0001: 0x82ad2739 (NtAccessCheck) owned by ntoskrnl.exe
Entry 0x0002: 0x82c1e065 (NtAccessCheckAndAuditAlarm) owned by ntoskrnl.exe
Entry 0x0003: 0x82a35a1c (NtAccessCheckByType) owned by ntoskrnl.exe
[REMOVED]
SSDT[1] at 96c37000 with 825 entries
Entry 0x1000: 0x96bc0e6d (NtGdiAbortDoc) owned by win32k.sys
Entry 0x1001: 0x96bd9497 (NtGdiAbortPath) owned by win32k.sys
Entry 0x1002: 0x96a272c1 (NtGdiAddFontResourceW) owned by win32k.sys
Entry 0x1003: 0x96bcff67 (NtGdiAddRemoteFontToDC) owned by win32k.sys
In the case of SSDT hooking, an attacker replaces the pointer of a specific function with the address of the malicious function. For instance, if an attacker wishes to intercept the data that is written to a file, the pointer to NtWriteFile() can be changed to point to the address of the malicious function of an attacker's choice. This is illustrated in the following diagram:

To detect SSDT hooking, you can look for the entries in the SSDT table that do not point to addresses in ntoskrnl.exe or win32k.sys. The following code is an example of the Mader rootkit, which hooks various-registry related functions and points them to the malicious driver core.sys. At this stage, you can determine the base address of core.sys using modules, modscan, or driverscan and then dump it to disk for further analysis using the moddump plugin:
$ python vol.py -f mader.vmem --profile=WinXPSP3x86 ssdt | egrep -v "(ntoskrnl|win32k)"
Volatility Foundation Volatility Framework 2.6
[x86] Gathering all referenced SSDTs from KTHREADs...
Finding appropriate address space for tables...
SSDT[0] at 80501b8c with 284 entries
Entry 0x0019: 0xf66eb74e (NtClose) owned by core.sys
Entry 0x0029: 0xf66eb604 (NtCreateKey) owned by core.sys
Entry 0x003f: 0xf66eb6a6 (NtDeleteKey) owned by core.sys
Entry 0x0041: 0xf66eb6ce (NtDeleteValueKey) owned by core.sys
Entry 0x0062: 0xf66eb748 (NtLoadKey) owned by core.sys
Entry 0x0077: 0xf66eb4a7 (NtOpenKey) owned by core.sys
Entry 0x00c1: 0xf66eb6f8 (NtReplaceKey) owned by core.sys
Entry 0x00cc: 0xf66eb720 (NtRestoreKey) owned by core.sys
Entry 0x00f7: 0xf66eb654 (NtSetValueKey) owned by core.sys
The disadvantage of using SSDT hooking for an attacker is that it is easy to detect, and the 64-bit release of Windows prevents SSDT hooking due to the Kernel Patch Protection (KPP) mechanism, also known as PatchGuard (https://en.wikipedia.org/wiki/Kernel_Patch_Protection). Since the entries in the SSDT vary across different versions of Windows and are subject to change in newer versions, it becomes difficult for a malware author to write a rootkit that is reliable.