IOCTL Cng Random
Proof-of-concept initially developed by Grzegorz Tworek
#include <Windows.h>
#define OBJ_CASE_INSENSITIVE 0x00000040L
#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020
#define NT_SUCCESS(Status)(((NTSTATUS)(Status)) >= 0)
#define IOCTL_KSEC_RNG CTL_CODE(FILE_DEVICE_KSEC, 1, METHOD_BUFFERED, FILE_ANY_ACCESS)
typedef struct _IO_STATUS_BLOCK {
union {
NTSTATUS Status;
PVOID Pointer;
};
ULONG_PTR Information;
} IO_STATUS_BLOCK, * PIO_STATUS_BLOCK;
typedef struct _LSA_UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, * PUNICODE_STRING;
typedef struct _OBJECT_ATTRIBUTES {
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES;
SIZE_T StringLengthW(_In_ LPCWSTR String)
{
LPCWSTR String2;
for (String2 = String; *String2; ++String2);
return (String2 - String);
}
#define InitializeObjectAttributes(p, n, a, r, s) { \
(p)->Length = sizeof(OBJECT_ATTRIBUTES); \
(p)->RootDirectory = r; \
(p)->Attributes = a; \
(p)->ObjectName = n; \
(p)->SecurityDescriptor = s; \
(p)->SecurityQualityOfService = NULL; \
}
VOID ImplZeroMemory1(_Inout_ PVOID Destination, _In_ SIZE_T Size)
{
PBYTE Dest = (PBYTE)Destination;
while (Size--)
{
*Dest++ = 0;
}
}
VOID RtlInitUnicodeString(_Inout_ PUNICODE_STRING DestinationString, _In_ PCWSTR SourceString)
{
SIZE_T DestSize;
if (SourceString)
{
DestSize = StringLengthW(SourceString) * sizeof(WCHAR);
DestinationString->Length = (USHORT)DestSize;
DestinationString->MaximumLength = (USHORT)DestSize + sizeof(WCHAR);
}
else
{
DestinationString->Length = 0;
DestinationString->MaximumLength = 0;
}
DestinationString->Buffer = (PWCHAR)SourceString;
}
BOOL GetRandomIntegerCryptoNextGenDeviceObject(PUINT32 RandomInteger)
{
typedef NTSTATUS(NTAPI* NTOPENFILE)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, ULONG, ULONG);
typedef NTSTATUS(NTAPI* NTDEVICEIOCONTROLFILE)(HANDLE, HANDLE, PVOID, PVOID, PIO_STATUS_BLOCK, ULONG, PVOID, ULONG, PVOID, ULONG);
typedef NTSTATUS(NTAPI* NTCLOSE)(HANDLE);
NTOPENFILE NtOpenFile = NULL;
NTDEVICEIOCONTROLFILE NtDeviceIoControlFile = NULL;
NTCLOSE NtClose = NULL;
NTSTATUS Status = 0;
HMODULE Module = NULL;
UNICODE_STRING DriverName = { 0 };
OBJECT_ATTRIBUTES ObjectAttributes = { 0 };
IO_STATUS_BLOCK Io = { 0 };
HANDLE Handle = NULL;
BYTE Buffer[16] = { 0 };
BOOL Flag = FALSE;
Module = GetModuleHandleA("ntdll.dll");
if (Module == NULL)
goto EXIT_ROUTINE;
NtOpenFile = (NTOPENFILE)GetProcAddress(Module, "NtOpenFile");
NtDeviceIoControlFile = (NTDEVICEIOCONTROLFILE)GetProcAddress(Module, "NtDeviceIoControlFile");
NtClose = (NTCLOSE)GetProcAddress(Module, "NtClose");
if (!NtOpenFile || !NtDeviceIoControlFile || !NtClose)
goto EXIT_ROUTINE;
RtlInitUnicodeString(&DriverName, L"\\Device\\CNG");
InitializeObjectAttributes(&ObjectAttributes, &DriverName, OBJ_CASE_INSENSITIVE, 0, 0);
Status = NtOpenFile(&Handle, SYNCHRONIZE | FILE_READ_DATA, &ObjectAttributes, &Io, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_SYNCHRONOUS_IO_NONALERT);
if (!NT_SUCCESS(Status))
goto EXIT_ROUTINE;
ImplZeroMemory1(&Io, sizeof(IO_STATUS_BLOCK));
Status = NtDeviceIoControlFile(Handle, NULL, NULL, NULL, &Io, IOCTL_KSEC_RNG, NULL, 0, Buffer, sizeof(Buffer));
if (!NT_SUCCESS(Status))
goto EXIT_ROUTINE;
*RandomInteger = ((UINT32)Buffer[0]) | ((UINT32)Buffer[1] << 8) | ((UINT32)Buffer[2] << 16) | ((UINT32)Buffer[3] << 24);
Flag = TRUE;
EXIT_ROUTINE:
if (NtClose && Handle)
NtClose(Handle);
return Flag;
}
INT main(VOID)
{
UINT32 Value = 0;
GetRandomIntegerCryptoNextGenDeviceObject(&Value);
return ERROR_SUCCESS;
}Last updated