ethical.blue Magazine

// Cybersecurity clarified.

Windows Internals: APIs, Rings and System Calls

2022-06-13   Dawid Farbaniec
...
The application programming interface (API for short) in Windows is simply a set of functions contained in libraries, which are usually part of the system. They are exposed to developers so that they can use them in their programs. The old Windows API (also called Win32 API) consists of layers (similar to onion) and often some functions are "wrappers" on the lower (level of abstraction) calls. Basic functions are available in the libraries kernel32.dll and user32.dll. For example: Someone creates a program that uses the Win32 API and needs to create a file. One can use the CreateFile function for this purpose. But what happens inside the function? One will find there, among others different processor instructions, the call NtCreateFile. The NtCreateFile function is in the ntdll.dll library and is abstractly lower than the Win32 API, and the set of functions prefixed with Nt contained therein are named Native API. This interface is the bridge between the user's applications and the guts of Windows. The Native API also contains kernel mode (ring 0) elements such as the Zw prefix function versions (for example: ZwCreateFile). They are used when developing kernel mode programs.



It is worth noting that for some time the old Win32 API, programmed mainly in C language, is slowly replaced by the new interface called Windows Runtime (WinRT for short).

Privilege Levels (Rings)

The architecture of the Windows system isolates user programs from those running in the kernel mode. This is possible thanks to the security features implemented in the processor, which provide four levels of privilege (rings) for the executed code.



The most privileged level is the zero level in which the components critical for the operating system, such as drivers, work. The next two levels (ring 1 and ring 2) are of moderate privileges. On the other hand, the user level (ring 3) is a mode in which standard programs run that do not have direct access to critical system or hardware resources. In the documentation for AMD64 and Intel 64 processors, the current privilege level is abbreviated as CPL (Current Privilege Level). It can be read from the code segment (CS) register.



Hardware Abstraction Layer (HAL)

HAL's task is, inter alia, hiding details of the implementation of hardware and device support, which increases code portability and provides an interface for communication with the hardware and services of the Windows kernel.



The hardware abstraction layer library is named HAL.DLL and is located in the directory:
%WINDOWS%\System32\hal.dll

The functions provided by this library have the prefix Hal, for example: HalExamineMBR.

It is worth taking an interest in this library if one want to program drivers and create or analyze code running in the kernel mode.

System Calls (SYSCALL)

As the Native API is a bridge between user mode (ring 3) and kernel mode (ring 0), it should include some mechanism for forwarding calls to the kernel.

This is done with the SYSCALL processor instruction. And the best explanation is to look to the inside of the selected Native API function. The sample program may be the system calculator.



With command u ntdll!NtCreateFile it is possible to display the internals of the NtCreateFile function in the Assembly language. The disassembly is shown below.



The u command in the WinDbg tool allows one to disassemble, receive a listing in the Assembly language of the selected code fragment (for example: a function or an address in memory). Inside the function NtCreateFile one can notice, among others:
  • passing the argument from the RCX register to R10 (the SYSCALL instruction destroys the contents of the RCX register),
  • passing the call number to the EAX register (here 55h),
  • checking instructions (TEST, JNE),
  • system call via SYSCALL instruction,
  • (...)

For comparison, one can display the internals of another function, for example: NtQuerySystemInformation. Here, the SYSCALL call number in the EAX register is 36h.



The previous figures show what the system call looks like.

Please note that the system call numbers (the value passed via the EAX register) may change with Windows versions, as they are internal mechanisms and compatibility is not required here. For application developers, there is a Win32 API, while the Native API and SYSCALL mechanism are used by specialized programs that require it or computer viruses.

Hope you like this small tutorial.

Bibliography

Chris Anley, John Heasman, Felix FX Linder, Gerardo Richarte, 2007 – The Shellcoder’s Handbook, ISBN: 9780470080238
https://docs.microsoft.com/en-us/windows/uwp/get-started/universal-application-platform-guide#how-the-universal-windows-platform-relates-to-windows-runtime-apis [access: 2020-08-23]
https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/u--unassemble- [access: 2020-08-31]