Skip to content

API Documentation

Topic intended for developers

This topic is intended for developers who'd like to build upon the capabilities of HidHide and alter driver configuration. As an end-user you can simply use the client UI application shipped along with the driver setup.

This article describes how an application can interact with the driver to influence which device instances get blocked and which processes get granted access. The steps outlined here are the only supported and safe way (besides the control application shipped along the driver) to interact with the driver and should be read carefully and thoroughly.

Control Device

The filter driver uses the common concept of exposing a Control Device which can be opened from any user-land process and used to send I/O Control Commands to. No elevated privileges are required (and thus should be avoided) to access the control device.

Use the CreateFile Windows API within the language/framework of your choice and open the path \\.\HidHide. See examples below for .NET or good ol' C/C++:

Obtain Control Device handle

// Use e.g. https://github.com/dotnet/pinvoke/
// Install-Package PInvoke.Kernel32
using (var handle = Kernel32.CreateFile("\\\\.\\HidHide",
    Kernel32.ACCESS_MASK.GenericRight.GENERIC_READ,
    Kernel32.FileShare.FILE_SHARE_READ | Kernel32.FileShare.FILE_SHARE_WRITE,
    IntPtr.Zero, Kernel32.CreationDisposition.OPEN_EXISTING,
    Kernel32.CreateFileFlags.FILE_ATTRIBUTE_NORMAL,
    Kernel32.SafeObjectHandle.Null
))
{
    // call DeviceIoControl here
}
#include <Windows.h>

HANDLE handle = CreateFile(
    "\\\\.\\HidHide", 
    GENERIC_READ, 
    (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE), 
    NULL, 
    OPEN_EXISTING, 
    FILE_ATTRIBUTE_NORMAL, 
    NULL);

// call DeviceIoControl here

CloseHandle(handle);

For other frameworks and languages please consult the appropriate documentation.

Exclusive handle access enforced

Reading and altering the lists of denied/allowed entities is not an atomic operation, therefore only one handle (process) is allowed to open the control device and issue requests at a time. Make sure to close the handle shortly after your operations are done to not block other processes which may want to talk to the driver.

I/O Control Commands

Driver behavior is altered entirely through the DeviceIoControl Windows API and outlined below. Arrays of strings are exchanged as a double-null-terminated wide-character-string literal so make sure to apply proper conversion and specify the correct buffer lengths (include all NULL-characters and multiply times sizeof(wchar_t)).

Get Blacklist

Retrieves the current blacklist/block-list/deny-list of Device Instance IDs which are currently blocked access to.

Parameter
Description
dwIoControlCode IOCTL_GET_BLACKLIST
lpInBuffer NULL
nInBufferSize 0
lpOutBuffer Pre-allocated buffer receiving the current list of blocked (hidden) device instance identifiers as a double-null-terminated wide-character-string literal.
nOutBufferSize The size of the buffer in bytes.
lpBytesReturned The required buffer size in bytes.

Set Blacklist

Submits a new blacklist/block-list/deny-list of Device Instance IDs which are then blocked access to.

Parameter
Description
dwIoControlCode IOCTL_SET_BLACKLIST
lpInBuffer Buffer containing the new list of blocked (hidden) device instance identifiers as a double-null-terminated wide-character-string literal.
nInBufferSize The size of the buffer in bytes.
lpOutBuffer NULL
nOutBufferSize 0

Get Whitelist

Retrieves the current whitelist/allow-list of absolute DOS device paths to applications which are currently allowed to see blocked devices.

Parameter
Description
dwIoControlCode IOCTL_GET_WHITELIST
lpInBuffer NULL
nInBufferSize 0
lpOutBuffer Pre-allocated buffer receiving the current list of whitelisted (allowed) file paths to processes in DOS device notation as a double-null-terminated wide-character-string literal.
nOutBufferSize The size of the buffer in bytes.
lpBytesReturned The required buffer size in bytes.

Set Whitelist

Submits a new whitelist/allow-list of absolute DOS device paths to applications which will then be allowed to see blocked devices.

Parameter
Description
dwIoControlCode IOCTL_SET_WHITELIST
lpInBuffer Buffer containing the new list of whitelisted (allowed) file paths to processes in DOS device notation as a double-null-terminated wide-character-string literal.
nInBufferSize The size of the buffer in bytes.
lpOutBuffer NULL
nOutBufferSize 0

Get Status

Retrieves the current global status of blocking capabilities. Returns a boolean value if the the driver is currently blocking configured devices (true) or on pass-through (false).

Parameter
Description
dwIoControlCode IOCTL_GET_ACTIVE
lpInBuffer NULL
nInBufferSize 0
lpOutBuffer Gets the current state of the hiding capabilities (1 = device hiding active, 0 = device hiding inactive).
nOutBufferSize sizeof(BOOLEAN) (1 byte)

Set Status

Submits the new global status of blocking capabilities. Sets a boolean value if the the driver is currently blocking configured devices (true) or on pass-through (false).

Parameter
Description
dwIoControlCode IOCTL_SET_ACTIVE
lpInBuffer Sets the new state of the hiding capabilities (1 = device hiding active, 0 = device hiding inactive).
nInBufferSize sizeof(BOOLEAN) (1 byte)
lpOutBuffer NULL
nOutBufferSize 0

Usage examples

The API usage should be fairly self-explanatory to anyone experienced with the basic Windows API, if in doubt, consult the Microsoft documentation for usage details 😉 For other high-level languages like C#/.NET wrapper libraries exist for the few required functions. A sample implementation is provided below (C#).

Preparation

First, since .NET doesn't really offer any convenience methods to deal with double-null-terminated wide-character-string literals I've thrown together this simple helper class:

Dealing with the application list requires translating the native executable file path to the DOS device path the driver works with. This is a tricky task as it involves quite a few native API calls and logic taking NTFS mount points (junctions) into account. Feel free to utilise yet another helper class:

With that out of the way we need the IOCTL definitions for the DeviceIoControl call. The values are simply computed from the helper macros which are not available in managed code:

IOCTL code definitions

private const uint IOCTL_GET_WHITELIST = 0x80016000;
private const uint IOCTL_SET_WHITELIST = 0x80016004;
private const uint IOCTL_GET_BLACKLIST = 0x80016008;
private const uint IOCTL_SET_BLACKLIST = 0x8001600C;
private const uint IOCTL_GET_ACTIVE = 0x80016010;
private const uint IOCTL_SET_ACTIVE = 0x80016014;

Retrieve, alter and submit deny-list

Retrieve, alter and submit allow-list