Howto: Implementation of new system service calls (II)

By Michael Schöbel

In this post we describe a very simple, but complete example of the implementation of a new system service call with the WRK. The system service prints a debug message from within the kernel and can be called from user mode.

You can download the application and a WRK patch for the necessary kernel modifications.

Kernel modifications

Our new system service call is called NtHelloKernel. It takes one integer value as argument and prints as many debug messages. As explained in the last post, we need to modify the system service dispatch table and generate some stubs for the new system service call. Listing 1 and listing 2 show the necessary modifications.

..
TABLE_ENTRY  QueryPortInformationProcess, 0, 0
TABLE_ENTRY  GetCurrentProcessorNumber, 0, 0
TABLE_ENTRY  WaitForMultipleObjects32, 1, 5
TABLE_ENTRY  HelloKernel, 1, 1
 
TABLE_END 296
 
..

Listing 1: /base/ntos/ke/i386/systable.asm

..
SYSSTUBS_ENTRY8  295, WaitForMultipleObjects32, 5
SYSSTUBS_ENTRY1  296, HelloKernel, 1
SYSSTUBS_ENTRY2  296, HelloKernel, 1
SYSSTUBS_ENTRY3  296, HelloKernel, 1
SYSSTUBS_ENTRY4  296, HelloKernel, 1
SYSSTUBS_ENTRY5  296, HelloKernel, 1
SYSSTUBS_ENTRY6  296, HelloKernel, 1
SYSSTUBS_ENTRY7  296, HelloKernel, 1
 
SYSSTUBS_ENTRY8  296, HelloKernel, 1
 
STUBS_END

Listing 2: /base/ntos/ke/i386/sysstubs.asm

Finally, we need the implementation of the new system service routine. Listing 3 shows the implementation for our example.

NTSTATUS
NtHelloKernel(
	int count
	)
{
	int i;
 
	PAGED_CODE();
 
	if (count > 0) {
 
		for (i=0; i<count; ++i) {
			DbgPrint("Hello User! [%d]",i);
		}
	}
 
	return STATUS_SUCCESS;
}

Listing 3: NtHelloKernel implementation

The debug message is printed via DbgPrint and appears in the kernel debugger or in applications like DebugView.Now compile the modified Windows kernel and boot your (virtual) machine using this new kernel. The next section describes the development of a simple test application.User mode application

We develop the application in two parts: a wrapper dynamic link library to call the new system service and the application program.

System service call wrapper DLL

Listing 4 and listing 5 show the header and the implementation file for the wrapper DLL. We define a HelloKernel(int count) function which passes the count argument to the newly created system service.

#ifndef _MYNTDLL_H_
#define _MYNTDLL_H_
 
#ifdef MYNTDLL_EXPORT
    #define MYNTDLL_API __declspec(dllexport) NTSTATUS
 
    #define _X86_
    #include <nt.h>
 
#else
    #define MYNTDLL_API __declspec(dllimport) DWORD
    #pragma comment("lib","myntdll.lib")
 
    #include <windows.h>
#endif
 
MYNTDLL_API HelloKernel(int count);
 
#endif // _MYNTDLL_H_
</windows.h></nt.h>

Listing 4: Header file: myntdll.h

#define MYNTDLL_EXPORT
#include "myntdll.h"
 
NTSTATUS
CallNtHelloKernel(
	int count
	)
{
	void** stackFrame = (void*)(&amp;count);
 
	// call NtHelloKernel
 
	__asm {
		mov eax, 0x0128		// EE - modified WRK kernel
		mov edx, stackFrame
		int 0x2E
	}
}
 
MYNTDLL_API HelloKernel(int count) {
 
	return CallNtHelloKernel(count);
}

Listing 5: Implementation file: myntdll.c
Application implementationFinally, we implement the test application. We call our new defined HelloKernel in the main function. The code is listed in listing 6.

#include <windows.h>
#include <stdio.h>
 
#include "myntdll.h"
 
int main(int argc, char* argv[]) {
 
    printf("calling HelloKerneln");
 
    // use new system service call
    HelloKernel(5);
 
}
</stdio.h></windows.h>

Listing 6: Application: hellokernel.c
Building the exampleTo build the example application and the wrapper DLL, open a command prompt windows (cmd.exe) and initialize your build environment as shown in listing 7. The adaptation of the include path is necessary to make sure that the wrapper DLL and the application is built using the SDK definitions from the WRK source tree. The WRKPATH environment variable must be set to your WRK directory.

set ARCH=x86
set WRKPATH=X:WRK-v1.2
set PATH=%WRKPATH%toolsx86;%PATH%
set INCLUDE=%WRKPATH%publicsdkinc;%WRKPATH%basentosinc;%WRKPATH%publicinternalbaseinc;%INCLUDE%

Listing 7: Build environment
Afterwards, you can build the application by simply typing nmake into command window. The makefile is shown in listing 8.

all: myntdll.dll hellokernel.exe
 
hellokernel.exe: myntdll.dll hellokernel.c myntdll.h
	cl /Zi hellokernel.c myntdll.lib
 
myntdll.dll: myntdll.c myntdll.h
	cl /LD myntdll.c

Listing 8: Makefile
Running the test applicationFor testing the new system service call run the hellokernel.exe application. The next figure shows the result for a successful run using DebugView.


hellokernel.exe result
If you try to execute the test application with an unmodified Windows kernel (or a “normal” Windows XP system) you should receive a “An invalid system service was specified in a system service call.”-message as result.Downloads

You can download and test the code of this article: kernelpatch and test application.

Comments

2 Responses to “Howto: Implementation of new system service calls (II)”

  1. Thompson on January 15th, 2009 22:55

    “An invalid system service was specified in a system service call.”

    Ah I know to well. Thanks for you have given me the solution to the problem that has been bugging me for far to long.

  2. Chelsea M Heffner on February 22nd, 2009 03:58

    The code is nice and short too so there is less text for you to look over when checking for bugs and spelling mistakes. I once spent 2 hours figuring out the bug to a software I wrote and it turns out I misspelled one of the variables.