Kernel Basics

Here we introduce the fundamental concepts of Windows kernel, including the executive layer, kernel layer, and hardware abstraction layer (HAL), providing a foundation which to build upon.

Ring Model

The purpose of processor rings, or protection rings, in x86 architecture is to enforce different levels of privilege and access control within the system. By dividing the system into multiple rings, each with its own set of permissions and restrictions, the rings provide a mechanism for isolating and protecting different components of the system.

This helps prevent unauthorised access and provides a means for implementing security boundaries between different layers of software, such as the kernel and user applications. The rings enable the operating system to execute privileged operations in higher privilege levels (e.g., Ring 0) while restricting user applications to lower privilege levels (e.g., Ring 3). This separation of privileges helps enhance system security and stability.

When we are debugging a user-mode application and we crash that application, the kernel remains stable. If however, we are debugging the kernel, and we crash the kernel, the operating system must be restarted.

The Windows operating system only implements two of the four available protection rings on x86 compatible processors. The kernel resides in ring 0, and userland resides in ring 3.

Kernel Mode versus User Mode

As we have already seen the kernel shares a single address space and this is available to the kernel image (ntoskrnl.exe) and all driver modules loaded in kernel space. This means that a compromised driver can essentially access any memory address space inside the kernel.

Within user-mode each process has its own virtual memory address space and each processor cannot access another processes address space without first making a call to the Win32 APIs, such as WriteProcessMemory. Furthermore, the token associated with the process must have the correct permissions to access the virtual memory in the target process.

When user-mode applications need to interact with the kernel they make requests via Subsystem DLLs, such as kernel32.dll:

Kernel space contains two important layers related to the OS functionality; executive and kernel. The executive is responsible for high-level functions, such as memory management and security, and the kernel layer is responsible for more primitive functions, such as thread scheduling and handling interrupt requests.

Executive Layer

The Executive Layer (higher layer) is a key component of the kernel in the Windows operating system. It provides a set of essential services and functions that enable higher-level components and subsystems to interact with the underlying system resources and manage system operations.

The Executive Layer is responsible for various important tasks, such as process and thread management, memory management, I/O operations, object management, security and access control, synchronisation, and inter-process communication. It acts as an intermediary between user-mode processes and the lower-level components of the operating system, facilitating the execution of system calls and managing system resources on behalf of user applications.

Two example features of the Executive Layer that are familiar to exploit developers are the handling of system service functions that are exported via ntdll.dll, such as NtAllocateVirtualMemory, and interacting with device driver functions that are called via the DeviceIoControl function.

Kernel Layer

The Kernel Layer (lower layer), also referred to as the Kernel Subsystem, is the core component of the operating system's kernel. It is the innermost layer that interacts directly with the hardware and provides low-level functionalities necessary for the operation of the operating system.

It implements mechanisms such as process scheduling, interrupt handling, and system call processing. It serves as the bridge between the hardware and the higher-level components in the Executive Layer, providing a foundation for the operating system's operation and ensuring its stability and security.

In summary, the Executive Layer focuses on higher-level services, management of system objects, and system-wide functionalities, while the Kernel Layer deals with low-level operations, hardware interaction, and core system management. They work together to provide a complete and functional operating system environment.

Hardware Abstraction Layer

The Hardware Abstraction Layer (HAL) is a component in an operating system that provides a uniform interface between the hardware and the rest of the system. Its purpose is to abstract the hardware-specific details and complexities, allowing the operating system and device drivers to work with different hardware configurations without requiring modifications to the higher-level software.

The main purpose of the HAL is to provide a standardised set of functions and services that shield the operating system from the specifics of the underlying hardware. It presents a consistent interface for accessing hardware resources, such as memory, processors, interrupts, I/O ports, and devices, regardless of the specific hardware implementation.

The HAL is implemented by the hal.dll DLL.

Driver developers only have to write to the single interface (the HAL).

User Mode Calling Kernel Mode

In Windows, it is intended that user-mode code should not make direct system calls, but instead, it should utilise the Win32 API (Subsystem DLLs). These higher-level interfaces provide a standardised and convenient way to interact with the operating system. By using the Win32 API, developers can abstract away the complexities of system calls and rely on the established mechanisms provided by the operating system.

From an exploit developer's perspective, there may be situations where bypassing the Win32 API becomes necessary to evade detection and gain deeper access to the underlying system. By directly making system calls or interacting with the kernel, exploit developers can achieve more granular control and exploit vulnerabilities that may not be exposed through higher-level interfaces.

To make syscalls the syscall instruction is moved to the rax register, and the arguments are passed using the x64 Application Binary Interface calling convention; the first four arguments in the registers rcx, rdx, r8, and r9. All subsequent arguments should be pushed to the stack.

Kernel Pools

The kernel pool is a dedicated memory pool used by the Windows operating system to allocate and manage memory for kernel-mode components. It provides a controlled environment for kernel code execution and facilitates efficient memory allocation and deallocation within the kernel.

As of Windows 10 (version 19H1) the kernel uses the Segment Heap; this has been ported from user-mode.

A segment heap is a memory allocation mechanism introduced in Windows 10 that improves memory management efficiency. It divides the heap into segments and employs algorithms to optimise memory usage, reduce fragmentation, and enhance overall performance of memory allocation and deallocation operations.

The heaps are seperated:

  • NonPaged heaps are never paged out to disk; these are assigned to critical data structures.

  • NonPagedNx heaps are never paged out to disk and they are not executable.

  • Paged heaps can be paged out to disk.

  • Special heaps are used for kernel code debugging, such as that used in driver development.

The kernel pools have additional security, implemented through randomisation and encoding.

Last updated