Run any Ring 0 code from a Win32 application on Windows NT

This page last updated July 31, 1997
Copyright (C) 1997 Prasad Dabak, Sandeep Phadke, and Milind Borate


The callgate is a mechanism of controlled ring transfers (privilege level transfers) on Intel microprocessors. There are ways to implement a callgate mechanism under Windows 3.1 and Windows 95 (for Windows 3.1, see Matt Pietrek, "Run Privileged Code from Your Windows-based Programs Using Call Gates," Microsoft Systems Journal, May 1993; for Windows 95, see Pietrek's excellent book, Windows 95 System Programming Secrets).

We are providing here an equivalent mechanism for Windows NT 3.51 and 4.0. We provide the reader with an API, driver and a DLL to directly try out this mechanism.

Get callgate.zip (see instructions below)

This is the best mechanism to execute privileged instructions, without having to write a NT kernel mode device driver. You can directly link with our general-purpose DLL and execute Ring 0 code.

Implementation

There are a lot of undocumented functions in the core NT component NTOSKRNL.EXE. Using some of these functions we have provided a mechanism for creating callgates under Windows NT. The implementation consists of a kernel mode device driver CALLGATE.SYS and a wrapper DLL CALLGATE.DLL. Using the functions from CALLGATE.DLL, one can create a callgate and execute any Ring 0 code from a Win32 application.

The prototypes for the functions exported by CALLGATE.DLL are given in GATE.H header file. We have provided a sample application which uses this DLL to create callgate and get the contents of the CPU control registers like CR0, CR2, CR3 from a Win32 application. It also demonstrates how direct port I/O can be done using this trick. The sample program provided, beeps by outputting data on the sound port.

The function which is called through a callgate is written in assembly language, since the standard 32-bit compiler does not generate the stack frame required for such a function. The function called through a callgate is called by a far call. Therefore the parameters to the functions starts from ESP+8. The standard 32-bit compiler generates the code which expects the parameters to start from ESP+4. Also in this case, you have to make a far return, whereas standard 32-bit compiler generates a near return instruction. You can find the details about this in Matt Pietrek's Windows 95 System Programming Secrets, Chapter 5, pages 301, 302 (cool stuff in the PHYS program).

Note that CALLGATE.SYS and CALLGATE.DLL have to be present in the same directory as that of the application using CALLGATE.DLL, since CALLGATE.DLL forms the complete path of the driver by getting the current directory of the application.

The source code for CALLGATE.DLL and CALLGATE.SYS will be presented in our forthcoming book Undocumented Windows NT to be published by O'Reilly Associates.

NOTE: You have to extremely cautious when writing the function which is to be called through a callgate. A small mistake can easily crash your NT machine. We are NOT responsible for any data loss caused due to the use of this trick.

Currently the function which is called through callgate has a restriction that it can not access any paged data. Therefore one needs to lock the data and code which is executed at ring 0 using VirtualLock. How to overcome this limitation will be described in our forthcoming book.

Using the sample program

  1. Copy CALLGATE.ZIP to your local drive in some directory.
  2. Unzip the file using 'PKUNZIP -d CALLGATE.ZIP'
  3. Change to Release directory.
  4. Run cgateapp.exe which will display the contents of CR0, CR2, CR3 registers and beeps by doing direct port I/O to the sound device.
You must login as administrator to try out the sample, since for installing the driver one needs admin privileges under NT.

Compiling the source code

We have provided the source code for a sample application which uses the CALLGATE.DLL API for creating callgates. The source code is compiled using MSVC 4.0. The function called through callgate is present in RING0.ASM file. The RING0.ASM is assembled using ML.EXE from NT DDK.
Undocumented Bookstore