The kernel hook implemented in Chapter 3 was a good example of system call table hooking, but most rootkits contain more than one kernel hook. To give a more complete example, the next three sections will add kernel hooks for registry key hiding, directory hiding, and process hiding. Combined, these additional hooks should provide a better understanding of the absolute control available to rootkit designers.
Keep in mind that system call table hooks can easily be detected by a growing number of rootkit detectors, so implementing this design requires a deployment environment in which both system administrators and end users are either aware of the rootkit, or completely unaware of rootkit detection and removal methods. Another option is to use the trampoline hooking method detailed in Chapter 4 in lieu of system call table hooking. The number of detectors that can spot trampoline hooking is much lower than the number that can spot system call table hooking. In addition, the technology required to extract a rootkit that’s using kernel-level trampoline hooking is much more difficult to implement.
As you read through the following example, you might notice that registry value hiding and file hiding haven’t been included. The reason for this discrepancy can be applied to all rootkit design: Don’t do any more than you have to. Because registry values can be placed inside registry keys, and files can be placed inside directories, it is possible to implement registry value and file hiding functionality without the need for additional hooks. In the case of registry value hiding, the additional overhead required to re-index registry values more than doubles the processing time; and processing time is at a premium when hooking kernel functions. In the case of file hiding, a single, obscure hook, ZwQueryDirectoryFile, can be used to hide directories, minimizing the possibility of detection; and minimizing the possibility of detection is always a consideration when designing a rootkit.
The functionality required to hide registry keys has been implemented by creating two new files and modifying four existing files.
The new files are as follows:
Following are the four modified files:
Ghost.c hookManager.c hookManager.h SOURCES
The code follows.