Skip to content

Inserting Protection Macros in Device Drivers

To mark code blocks for protection, link your driver with the dummy driver VirtualizerDDK.sys. This driver is required only before protection. Code Virtualizer removes the dependency from the protected driver, so you do not need to distribute VirtualizerDDK.sys.

C/C++ Example

VIRTUALIZER_TIGER_BLACK_START

// your code goes here

VIRTUALIZER_TIGER_BLACK_END

To test the unprotected driver, place VirtualizerDDK.sys in the %system32%\drivers folder, then register and start it. You can use OSR Driver Loader to register and load the driver. Starting VirtualizerDDK.sys at system startup (BOOT, SYSTEM, or AUTOMATIC) keeps it available for testing.

Note: VirtualizerDDK.sys is a dummy driver and consumes no significant system resources.

Example of real device driver with Code Virtualizer

The following example marks two sensitive areas inside a real driver's DriverEntry routine.

Device Driver Example

#include <ntddk.h>
#include "VirtualizerDDK.h"

NTSTATUS
DriverEntry(
   IN PDRIVER_OBJECT  DriverObject,
   IN PUNICODE_STRING RegistryPath
   )
{

   PDEVICE_OBJECT      deviceObject;
   PDEVICE_EXTENSION   deviceExtension;
   UNICODE_STRING      ntDeviceName;
   UNICODE_STRING      symbolicLinkName;
   NTSTATUS            status;

   DebugPrint(("==>DriverEntry %d\n", i));

    VIRTUALIZER_LION_RED_START     // area to protect starts here!

   //
   // Create the device object
   //
   RtlInitUnicodeString( &ntDeviceName, NTDEVICE_NAME_STRING );

   status = IoCreateDevice(
               DriverObject,               // DriverObject
               sizeof( DEVICE_EXTENSION ), // DeviceExtensionSize
               &ntDeviceName,              // DeviceName
               FILE_DEVICE_UNKNOWN,        // DeviceType
               FILE_DEVICE_SECURE_OPEN,    // DeviceCharacteristics
               FALSE,                      // Not Exclusive
               &deviceObject               // DeviceObject
               );

   if ( !NT_SUCCESS(status) ) {
       DebugPrint(("\tIoCreateDevice returned 0x%x\n", status));
       return( status );
   }

 VIRTUALIZER_LION_RED_END           // area to protect finishes here!

   //
   // Set up dispatch entry points for the driver.
   //
   DriverObject->MajorFunction[IRP_MJ_CREATE]          =
   DriverObject->MajorFunction[IRP_MJ_CLOSE]           = EventCreateClose;
   DriverObject->MajorFunction[IRP_MJ_CLEANUP]         = EventCleanup;
   DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = EventDispatchIoControl;
   DriverObject->DriverUnload                          = EventUnload;

   //
   // Create a symbolic link for userapp to interact with the driver.
   //
   RtlInitUnicodeString( &symbolicLinkName, SYMBOLIC_NAME_STRING );
   status = IoCreateSymbolicLink( &symbolicLinkName, &ntDeviceName );

   if ( !NT_SUCCESS(status) ) {

       IoDeleteDevice( deviceObject );
       DebugPrint(("\tIoCreateSymbolicLink returned 0x%x\n", status));
       return( status );
   }

  VIRTUALIZER_TIGER_BLACK_START      // area to protect starts here!

   //
   // Initialize the device extension.
   //
   deviceExtension = deviceObject->DeviceExtension;

   InitializeListHead(&deviceExtension->EventQueueHead);

   KeInitializeSpinLock(&deviceExtension->QueueLock);

   deviceExtension->Self = deviceObject;

   //
   // Establish user-buffer access method.
   //
   deviceObject->Flags |= DO_BUFFERED_IO;

   DebugPrint(("<==DriverEntry\n"));

   return( status );

  VIRTUALIZER_TIGER_BLACK_END        // area to protect finishes here!
}