Link to home
Start Free TrialLog in
Avatar of msgolez
msgolez

asked on

Help query values from the registry using zwqueryvaluekey

Hello All

I'm trying to querry a value from the registry using zwqueryvaluekey from a kernel driver. In particular i'm trying to query the start value of driver. My question is, once i get the structure the contains the information, how do i compare the value of the Start key with values such as 0, 1, 2, 3 or 4.

Here is my code:

#include <ntddk.h>

VOID ReadUnload(PDRIVER_OBJECT  pDriverObject);

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING RegistryPath)
{
UNICODE_STRING uPath, uName, uResult;
ANSI_STRING aResult;
HANDLE hFolder = NULL;
OBJECT_ATTRIBUTES objAttribs;
NTSTATUS status = STATUS_SUCCESS;
ULONG dataLength = 0x80;
ULONG structLength = sizeof(KEY_VALUE_BASIC_INFORMATION) + dataLength + sizeof(UNICODE_NULL);
PKEY_VALUE_BASIC_INFORMATION pBasicValue = NULL;
PKEY_VALUE_PARTIAL_INFORMATION pPartialValue = NULL;
PKEY_VALUE_FULL_INFORMATION pFullValue = NULL;
pBasicValue = (PKEY_VALUE_BASIC_INFORMATION) ExAllocatePool(PagedPool, structLength);
pPartialValue = (PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePool(PagedPool, structLength);
pFullValue = (PKEY_VALUE_FULL_INFORMATION) ExAllocatePool(PagedPool, structLength);

RtlInitUnicodeString(&uPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\ultra" );
RtlInitUnicodeString(&uName, L"Type");

InitializeObjectAttributes(&objAttribs, &uPath, OBJ_CASE_INSENSITIVE, NULL, NULL);

status = ZwOpenKey(&hFolder, KEY_READ, &objAttribs);

if(status != STATUS_SUCCESS)
{
      DbgPrint("Couldn't open key. Ending function.\n");
      return status;
}

//Try to read the value, using the PKEY_VALUE_PARTIAL_INFORMATION.
memset(pPartialValue, 0, structLength);
status = ZwQueryValueKey(hFolder, &uName, KeyValuePartialInformation, pPartialValue, structLength, &dataLength);

switch(status)
{
case STATUS_INVALID_HANDLE: //Always end up here.
      DbgPrint("ZwQueryValueKey(Partial) says the handle is bogus.\n");
      break;
case STATUS_BUFFER_OVERFLOW:
      DbgPrint("Buffer overflow error");
      //Since it failed because of insufficient storage, allocate enough.
      ExFreePool(pPartialValue);
      structLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + dataLength + sizeof(UNICODE_NULL);
      pPartialValue = (PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePool(PagedPool, structLength);
      status = ZwQueryValueKey(hFolder, &uName, KeyValuePartialInformation, pPartialValue, structLength, &dataLength);

      if(status != STATUS_SUCCESS)
      {
            //Just give it up.  Shouldn't get here, either.
            DbgPrint("ZwQueryValueKey(Partial): Still didn't get it."\
                        " Status: %X\n", status);
            break;
      }
      //Fall Through
case STATUS_SUCCESS:
      DbgPrint("Success");
//      my_data =  (PCANSI_STRING)pPartialValue->Data;
//  RtlAnsiStringToUnicodeString( &uResult, my_data, TRUE);
//      RtlInitUnicodeString(&uResult, pPartialValue->Data);
//      DbgPrint(pPartialValue->Data[7]);
      DbgPrint(pPartialValue->Data);
}
ExFreePool(pPartialValue);

Basically when i get pPartialValue->Data, how do i compare it to 0,1,2,3 or 4?

Thanks
Avatar of Axter
Axter
Flag of United States of America image

>>RtlInitUnicodeString(&uPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\ultra" );

Instead of using a string literal, you could use the path that is passed in to the DriverEntry function.
NTSTATUS
DriverEntry(IN PDRIVER_OBJECT DriverObject,
                  IN PUNICODE_STRING RegistryPath) // ***** use this value ******
{
   
    GetRegistrySettings(RegistryPath);
}

This value will change according to your driver, so it makes it a little more portable.
Example reg path:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MY_DRIVER_NAME\DEBUG_LOGGING_ON


In my GetRegistrySettings function, I have a static variable that stores the RegistryPath value, so that the function can be called again from outside of DriverEntry without knowning the path value.
Example:

VOID GetRegistrySettings (IN PUNICODE_STRING RegistryPath_Input)
{
      OBJECT_ATTRIBUTES attributes;
      HANDLE driverRegKey;
      NTSTATUS status;
      ULONG resultLength;
      UNICODE_STRING valueName;
      UCHAR bufferPath[MAX_PATH * sizeof(WCHAR)] = {0};
      WCHAR *buffer = (WCHAR *)bufferPath;

      static UNICODE_STRING RegistryPath = {0, 0, 0}; // ****** Make sure this is STATIC *****

      if (RegistryPath_Input == NULL && RegistryPath.Buffer == NULL)
            return; //Should never reach this point unless NULL value passed first time called

      if (RegistryPath.Buffer == NULL)
      {
            RegistryPath.Buffer = ExAllocatePoolWithTag(NonPagedPool,  (RegistryPath_Input->MaximumLength + 2) * sizeof(WCHAR), '6_H');
            if (RegistryPath.Buffer == NULL)
                  return;
            RegistryPath.Length                        = RegistryPath_Input->Length;
            RegistryPath.MaximumLength            = RegistryPath_Input->MaximumLength;
            wcsncpy(RegistryPath.Buffer,RegistryPath_Input->Buffer, RegistryPath.Length      / 2 );
            RegistryPath.Buffer[RegistryPath_Input->Length / 2] = 0;
      }

      InitializeObjectAttributes( &attributes,
            &RegistryPath,
            OBJ_CASE_INSENSITIVE,
            NULL,
            NULL );

      status = ZwOpenKey( &driverRegKey,
            KEY_READ,
            &attributes );

      if (!NT_SUCCESS( status )) {
            return;
      }

      // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MY_DRIVER_NAME\DEBUG_LOGGING_ON
      RtlInitUnicodeString( &valueName, L"DEBUG_LOGGING_ON" );
      status = ZwQueryValueKey( driverRegKey,
            &valueName,
            KeyValuePartialInformation,
            bufferPath,
            sizeof(bufferPath),
            &resultLength );


      if (NT_SUCCESS( status ))
      {
            if (((PKEY_VALUE_PARTIAL_INFORMATION) bufferPath)->Data[0] == 'Y')
            {
                  GXHSM_DIAG_MODE_ON = TRUE;
                  DbgPrint("Turning on DiagMode\n");
            }
            else
            {
                  GXHSM_DIAG_MODE_ON = FALSE;
                  DbgPrint("DiagMode is OFF\n");
            }
      }

You could easily change the above function so as to take a second argument that would specify the specific registry field to retrieve.
Avatar of msgolez
msgolez

ASKER

Im sorry, im not really that familiar with driver writing, can you pleas show me the necessary changes that i have to make that will allow me to compare the value at key with 0,1,2,3 or 4?

im retrieveing a REG_DWORD and i wanna know how to type cast the value that i got to compare it againsts 0,1,2,3 or 4.

Thanks for your response :)
Example:

if (((PKEY_VALUE_PARTIAL_INFORMATION) pPartialValue)->Data[0] == 0)
{
}
else if (((PKEY_VALUE_PARTIAL_INFORMATION) pPartialValue)->Data[0] == 1)
{
}
else if (((PKEY_VALUE_PARTIAL_INFORMATION) pPartialValue)->Data[0] == 2)
{
}
else if (((PKEY_VALUE_PARTIAL_INFORMATION) pPartialValue)->Data[0] == 3)
{
}
else if (((PKEY_VALUE_PARTIAL_INFORMATION) pPartialValue)->Data[0] == 4)
{
}

Avatar of msgolez

ASKER

So Data[0] should have the value even if in the registry its 0x00000001?

Thanks :)
>>So Data[0] should have the value even if in the registry its 0x00000001?

Yes.
ASKER CERTIFIED SOLUTION
Avatar of Axter
Axter
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of msgolez

ASKER

thank you :)