windows内核安全(五)

注册表操作

Posted by volcanohatred on June 20, 2018

注册表操作

REG_MULTI_SZ 多字符类型
UNC 局域网共享路径
HIVE存储,注册表数据存储
操作注册表相关函数:

ZwCreateKey :打开注册表句柄
ZwOpenKey:打开注册表
ZwSetValueKey :在添加和修改注册表键值的时候,要分类进行添加和修改
ZwQueryValueKey :对注册表的项进行查询,从而获取注册表的键值
ZwQueryKey:获得某注册表项究竟有多少个子项
ZwEnumerateKey :针对第几个子项获取该子项的具体信息
ZwDeleteKey :删除子项

注册表操作C代码:

#include <ntddk.h>
#include <ntstrsafe.h>
#include <windef.h>

NTSTATUS ntCreateKey(WCHAR *szKey);

NTSTATUS ntOpenKey(WCHAR *szKey);
NTSTATUS ntEnumerateSubKey(WCHAR *szKey);

NTSTATUS ntSetValueKey(WCHAR *szKey);
NTSTATUS ntQueryValueKey(WCHAR *szKey);
NTSTATUS ntEnumerateSubValueKey(WCHAR *szKey);
NTSTATUS ntDeleteValueKey(WCHAR *szKey);

NTSTATUS ntDeleteKey(WCHAR *szKey);

VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
   NTSTATUS ntStatus = ntDeleteValueKey(L"\\Registry\\Machine\\SoftWare\\Mallocfree");
   if (!NT_SUCCESS(ntStatus))
   {
      DbgPrint("ntSetValueKey() failed:%x\n", ntStatus);
      return;
   }
   ntDeleteKey(L"\\Registry\\Machine\\SoftWare\\Mallocfree");
   DbgPrint("Driver Unloaded\n");
}

NTSTATUS RegOper(WCHAR *szKey);

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
{
   DbgPrint("Driver begin\n");
   pDriverObject->DriverUnload = DriverUnload;

   RegOper(L"\\Registry\\Machine\\SoftWare\\Mallocfree");

   return STATUS_SUCCESS;
}

NTSTATUS RegOper(WCHAR *szKey)
{
   NTSTATUS      ntStatus = STATUS_UNSUCCESSFUL;
   WCHAR        szDeleteSubKey[MAX_PATH] = { 0 };

   if (szKey == NULL)
   {
      return ntStatus;
   }

   ntStatus = ntCreateKey(szKey);
   if (!NT_SUCCESS(ntStatus))
   {
      DbgPrint("ntCreateKey() failed:%x\n", ntStatus);
      return ntStatus;
   }

   ntStatus = ntSetValueKey(szKey);

   if (!NT_SUCCESS(ntStatus))
   {
      DbgPrint("ntSetValueKey() failed:%x\n", ntStatus);
      return ntStatus;
   }

   ntStatus = ntQueryValueKey(szKey);

   if (!NT_SUCCESS(ntStatus))
   {
      DbgPrint("ntQueryValueKey() failed:%x\n", ntStatus);
      return ntStatus;
   }

   ntStatus = ntEnumerateSubValueKey(szKey);

   if (!NT_SUCCESS(ntStatus))
   {
      DbgPrint("ntEnumerateSubValueKey() failed:%x\n", ntStatus);
      return ntStatus;
   }


   //     ntStatus =  ntDeleteValueKey(szKey);
   //     if (!NT_SUCCESS(ntStatus))
   //     {
   //        DbgPrint("ntSetValueKey() failed:%x\n", ntStatus);
   //        return ntStatus;
   //     }


   ntStatus = ntOpenKey(szKey);
   if (!NT_SUCCESS(ntStatus))
   {
      DbgPrint("ntOpenKey() failed:%x\n", ntStatus);
      return ntStatus;
   }

   ntStatus = ntEnumerateSubKey(szKey);
   if (!NT_SUCCESS(ntStatus))
   {
      DbgPrint("ntEnumerateSubItem() failed:%x\n", ntStatus);
      return ntStatus;
   }


   //     RtlStringCbCopyW(szDeleteSubKey, sizeof(szDeleteSubKey), szKey);
   //     RtlStringCbCatW(szDeleteSubKey, sizeof(szDeleteSubKey), L"\\KernelDriver");
   //     ntStatus = ntDeleteKey(szDeleteSubKey);
   //     if (!NT_SUCCESS(ntStatus))
   //     {
   //        DbgPrint("ntDeleteKey() failed:%x\n", ntStatus);
   //        return ntStatus;
   //     }

   return ntStatus;

}

//创建KEY和SUBKEY示例
NTSTATUS ntCreateKey(WCHAR *szKey)
{

   UNICODE_STRING        uRegKey = { 0 };
   HANDLE              hRegister = NULL;
   ULONG           ulResult = 0;
   OBJECT_ATTRIBUTES  objectAttributes = { 0 };
   UNICODE_STRING        subRegKey = { 0 };
   HANDLE              hSubRegister = NULL;
   OBJECT_ATTRIBUTES  subObjectAttributes = { 0 };
   NTSTATUS         ntStatus = STATUS_SUCCESS;


   RtlInitUnicodeString(&uRegKey, szKey);
   InitializeObjectAttributes(&objectAttributes,
      &uRegKey,
      OBJ_CASE_INSENSITIVE,
      NULL,
      NULL);
   ntStatus = ZwCreateKey(&hRegister,
      KEY_ALL_ACCESS,
      &objectAttributes,
      0,
      NULL,
      REG_OPTION_NON_VOLATILE,    //非变化,即永久
      &ulResult);

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

   //开始创建SUBKEY

   RtlInitUnicodeString(&subRegKey, L"KernelDriver");

   InitializeObjectAttributes(&subObjectAttributes,
      &subRegKey,
      OBJ_CASE_INSENSITIVE,
      hRegister,
      NULL);
   ntStatus = ZwCreateKey(&hSubRegister,
      KEY_ALL_ACCESS,
      &subObjectAttributes,
      0,
      NULL,
      REG_OPTION_NON_VOLATILE,
      &ulResult);

   if (!NT_SUCCESS(ntStatus))
   {
      ZwClose(hRegister);
      return ntStatus;
   }

   ZwClose(hRegister);
   ZwClose(hSubRegister);

   return ntStatus;
}

//打开注册表
NTSTATUS ntOpenKey(WCHAR *szKey)
{
   UNICODE_STRING        RegUnicodeString = { 0 };
   HANDLE              hRegister = NULL;
   OBJECT_ATTRIBUTES  objectAttributes = { 0 };
   NTSTATUS         ntStatus = STATUS_SUCCESS;

   RtlInitUnicodeString(&RegUnicodeString, szKey);

   InitializeObjectAttributes(&objectAttributes,
      &RegUnicodeString,
      OBJ_CASE_INSENSITIVE,
      NULL,
      NULL);
   ntStatus = ZwOpenKey(&hRegister,
      KEY_ALL_ACCESS,
      &objectAttributes);

   if (NT_SUCCESS(ntStatus))
   {
      return ntStatus;
   }

   ZwClose(hRegister);
   return ntStatus;
}

//\\registry\\machine\\SYSTEM\\CurrentControlSet\\services\\LanmanServer
//枚举键
NTSTATUS ntEnumerateSubKey(WCHAR *szKey)
{
   UNICODE_STRING           RegUnicodeString = { 0 };
   HANDLE                 hRegister = NULL;
   ULONG              ulSize = 0;
   OBJECT_ATTRIBUTES     objectAttributes = { 0 };
   NTSTATUS            ntStatus = STATUS_SUCCESS;
   UNICODE_STRING       uniKeyName = { 0 };
   PKEY_FULL_INFORMATION  pfi = NULL;
   ULONG              i = 0;
   PKEY_BASIC_INFORMATION  pbi = NULL;


   RtlInitUnicodeString(&RegUnicodeString, szKey);
   InitializeObjectAttributes(&objectAttributes,
      &RegUnicodeString,
      OBJ_CASE_INSENSITIVE,
      NULL,
      NULL);

   ntStatus = ZwOpenKey(&hRegister,
      KEY_ALL_ACCESS,
      &objectAttributes);

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


   //第一次调用ZwQueryKey为了获取KEY_FULL_INFORMATION数据的长度
   ntStatus = ZwQueryKey(hRegister,
      KeyFullInformation,
      NULL,
      0,
      &ulSize);
   if (STATUS_BUFFER_OVERFLOW != ntStatus &&
      STATUS_BUFFER_TOO_SMALL != ntStatus)
   {
      return ntStatus;
   }

   pfi =
      (PKEY_FULL_INFORMATION)
      ExAllocatePoolWithTag(PagedPool, ulSize, 'SGER');
   if (pfi == NULL)
   {
      ZwClose(hRegister);
      return STATUS_INSUFFICIENT_RESOURCES;
   }

   //第二次调用ZwQueryKey为了获取KEY_FULL_INFORMATION数据的数据
   ntStatus = ZwQueryKey(hRegister,
      KeyFullInformation,
      pfi,
      ulSize,
      &ulSize);
   if (!NT_SUCCESS(ntStatus))
   {
      ExFreePool(pfi);
      ZwClose(hRegister);
      return ntStatus;
   }

   for (i = 0; i<pfi->SubKeys; i++)
   {
      //第一次调用ZwEnumerateKey为了获取KEY_BASIC_INFORMATION数据的长度
      ntStatus = ZwEnumerateKey(hRegister,
         i,
         KeyBasicInformation,
         NULL,
         0,
         &ulSize);
      if (STATUS_BUFFER_OVERFLOW != ntStatus &&
         STATUS_BUFFER_TOO_SMALL != ntStatus)
      {
         ZwClose(hRegister);
         ExFreePool(pfi);
         return ntStatus;
      }

      pbi = (PKEY_BASIC_INFORMATION)
         ExAllocatePoolWithTag(PagedPool, ulSize, 'SGER');
      if (pbi == NULL)
      {
         ZwClose(hRegister);
         return STATUS_INSUFFICIENT_RESOURCES;
      }

      //第二次调用ZwEnumerateKey为了获取KEY_BASIC_INFORMATION数据的数据
      ntStatus = ZwEnumerateKey(hRegister,
         i,
         KeyBasicInformation,
         pbi,
         ulSize,
         &ulSize);

      if (!NT_SUCCESS(ntStatus))
      {
         ZwClose(hRegister);
         ExFreePool(pfi);
         ExFreePool(pbi);
         return ntStatus;
      }

      uniKeyName.Length =
         uniKeyName.MaximumLength =
         (USHORT)pbi->NameLength;

      uniKeyName.Buffer = pbi->Name;

      DbgPrint("The %d sub item name is:%wZ\n", i, &uniKeyName);

      ExFreePool(pbi);
   }

   ExFreePool(pfi);
   ZwClose(hRegister);

   return ntStatus;
}

//删除键
NTSTATUS ntDeleteKey(WCHAR *szKey)
{
   UNICODE_STRING        RegUnicodeString = { 0 };
   HANDLE              hRegister = NULL;
   OBJECT_ATTRIBUTES  objectAttributes = { 0 };
   NTSTATUS         ntStatus = STATUS_SUCCESS;

   RtlInitUnicodeString(&RegUnicodeString, szKey);

   InitializeObjectAttributes(&objectAttributes,
      &RegUnicodeString,
      OBJ_CASE_INSENSITIVE,
      NULL,
      NULL);

   ntStatus = ZwOpenKey(&hRegister,
      KEY_ALL_ACCESS,
      &objectAttributes);

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

   ntStatus = ZwDeleteKey(hRegister);

   ZwClose(hRegister);
   return ntStatus;
}
//\\registry\\machine\SYSTEM\CurrentControlSet\services\LanmanServer

NTSTATUS ntSetValueKey(WCHAR *szKey)
{
   UNICODE_STRING        RegUnicodeString = { 0 };
   HANDLE              hRegister = NULL;
   OBJECT_ATTRIBUTES  objectAttributes = { 0 };
   UNICODE_STRING        ValueName = { 0 };
   NTSTATUS         ntStatus = STATUS_SUCCESS;
   ULONG           ulValue = 0;
   WCHAR           *strValue = L"hello world";
   CHAR            buffer[1024] = { 0 };

   RtlInitUnicodeString(&RegUnicodeString, szKey);

   InitializeObjectAttributes(
      &objectAttributes,
      &RegUnicodeString,
      OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
      NULL,
      NULL
   );

   ntStatus = ZwOpenKey(&hRegister,
      KEY_ALL_ACCESS,
      &objectAttributes);

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

   RtlInitUnicodeString(&ValueName, L"Mallocfree1");
   ulValue = 1000;
   ZwSetValueKey(hRegister,
      &ValueName,
      0,
      REG_DWORD,
      &ulValue,
      sizeof(ulValue));


   RtlInitUnicodeString(&ValueName, L"Mallocfree2");

   ZwSetValueKey(hRegister,
      &ValueName,
      0,
      REG_SZ,
      strValue,
      wcslen(strValue) * sizeof(WCHAR) + sizeof(WCHAR));


   RtlInitUnicodeString(&ValueName, L"Mallocfree3");

   RtlFillMemory(buffer, sizeof(buffer), 0xFF);
   ZwSetValueKey(hRegister,
      &ValueName,
      0,
      REG_BINARY,
      buffer,
      sizeof(buffer));

   //todo:add a multisz valuekey

   ZwClose(hRegister);
   return ntStatus;
}


NTSTATUS ntDeleteValueKey(WCHAR *szKey)
{
   UNICODE_STRING        RegUnicodeString = { 0 };
   HANDLE              hRegister = NULL;
   OBJECT_ATTRIBUTES  objectAttributes = { 0 };
   UNICODE_STRING        ValueName = { 0 };
   ULONG           ulSize = 0;
   NTSTATUS         ntStatus = STATUS_SUCCESS;

   RtlInitUnicodeString(&RegUnicodeString, szKey);

   InitializeObjectAttributes(&objectAttributes,
      &RegUnicodeString,
      OBJ_CASE_INSENSITIVE,
      NULL,
      NULL);
   ntStatus = ZwOpenKey(&hRegister,
      KEY_ALL_ACCESS,
      &objectAttributes);
   if (!NT_SUCCESS(ntStatus))
   {
      return ntStatus;
   }

   RtlInitUnicodeString(&ValueName, L"REG_DWORD");
   ntStatus = ZwDeleteValueKey(hRegister, &ValueName);

   ZwClose(hRegister);
   return ntStatus;
}

NTSTATUS ntQueryValueKey(WCHAR *szKey)
{
   UNICODE_STRING                 RegUnicodeString = { 0 };
   HANDLE                       hRegister = 0;
   OBJECT_ATTRIBUTES           objectAttributes = { 0 };
   UNICODE_STRING                 ValueName = { 0 };
   ULONG                    ulSize = 0;
   NTSTATUS                  ntStatus = STATUS_SUCCESS;
   PKEY_VALUE_PARTIAL_INFORMATION pvpi = NULL;

   RtlInitUnicodeString(&RegUnicodeString, szKey);

   InitializeObjectAttributes(&objectAttributes,
      &RegUnicodeString,
      OBJ_CASE_INSENSITIVE,
      NULL,
      NULL);
   ntStatus = ZwOpenKey(&hRegister,
      KEY_ALL_ACCESS,
      &objectAttributes);
   if (!NT_SUCCESS(ntStatus))
   {
      return ntStatus;
   }


   RtlInitUnicodeString(&ValueName, L"Mallocfree1");

   ntStatus = ZwQueryValueKey(hRegister,
      &ValueName,
      KeyValuePartialInformation,
      NULL,
      0,
      &ulSize);

   if (ntStatus != STATUS_BUFFER_OVERFLOW &&
      ntStatus != STATUS_BUFFER_TOO_SMALL)
   {
      ZwClose(hRegister);
      return ntStatus;
   }


   pvpi =
      (PKEY_VALUE_PARTIAL_INFORMATION)
      ExAllocatePoolWithTag(PagedPool, ulSize, 'SGER');
   if (pvpi == NULL)
   {
      return STATUS_INSUFFICIENT_RESOURCES;
   }

   ntStatus = ZwQueryValueKey(hRegister,
      &ValueName,
      KeyValuePartialInformation,
      pvpi,
      ulSize,
      &ulSize);
   if (!NT_SUCCESS(ntStatus))
   {
      ExFreePool(pvpi);
      ZwClose(hRegister);
      return ntStatus;
   }

   if (pvpi->Type == REG_DWORD && pvpi->DataLength == sizeof(ULONG))
   {
      PULONG pulValue = (PULONG)pvpi->Data;
   }

   ExFreePool(pvpi);

   RtlInitUnicodeString(&ValueName, L"Mallocfree2");

   ntStatus = ZwQueryValueKey(hRegister,
      &ValueName,
      KeyValuePartialInformation,
      NULL,
      0,
      &ulSize);

   if (ntStatus == STATUS_OBJECT_NAME_NOT_FOUND || ulSize == 0)
   {
      ZwClose(hRegister);
      return ntStatus;
   }
   pvpi =
      (PKEY_VALUE_PARTIAL_INFORMATION)
      ExAllocatePoolWithTag(PagedPool, ulSize, 'SGER');
   if (pvpi == NULL)
   {
      return STATUS_INSUFFICIENT_RESOURCES;
   }

   ntStatus = ZwQueryValueKey(hRegister,
      &ValueName,
      KeyValuePartialInformation,
      pvpi,
      ulSize,
      &ulSize);
   if (!NT_SUCCESS(ntStatus))
   {
      ExFreePool(pvpi);
      ZwClose(hRegister);
      return ntStatus;
   }

   if (pvpi->Type == REG_SZ)
   {
      UNICODE_STRING uStr;
      uStr.Length = pvpi->DataLength;
      uStr.MaximumLength = pvpi->DataLength;

      uStr.Buffer = pvpi->Data;

      DbgPrint("Value:%S\n", pvpi->Data);
      DbgPrint("Value:%wZ\n", &uStr);
   }
   ExFreePool(pvpi);
   ZwClose(hRegister);
   return ntStatus;
}

//\\registry\\machine\SYSTEM\CurrentControlSet\services\LanmanServer
NTSTATUS ntEnumerateSubValueKey(WCHAR *szKey)
{
   UNICODE_STRING                 RegUnicodeString = { 0 };
   HANDLE                       hRegister = NULL;
   OBJECT_ATTRIBUTES           objectAttributes = { 0 };
   ULONG                    ulSize = 0;
   UNICODE_STRING             uniKeyName = { 0 };
   ULONG                    i = 0;
   NTSTATUS                  ntStatus = 0;
   PKEY_VALUE_BASIC_INFORMATION   pvbi = NULL;
   PKEY_FULL_INFORMATION        pfi = NULL;

   RtlInitUnicodeString(&RegUnicodeString, szKey);

   InitializeObjectAttributes(&objectAttributes,
      &RegUnicodeString,
      OBJ_CASE_INSENSITIVE,
      NULL,
      NULL);
   ntStatus = ZwOpenKey(&hRegister,
      KEY_ALL_ACCESS,
      &objectAttributes);

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

   ntStatus = ZwQueryKey(hRegister,
      KeyFullInformation,
      NULL,
      0,
      &ulSize);
   if (STATUS_BUFFER_OVERFLOW != ntStatus &&
      STATUS_BUFFER_TOO_SMALL != ntStatus)
   {
      ZwClose(hRegister);
      return ntStatus;
   }


   pfi =
      (PKEY_FULL_INFORMATION)
      ExAllocatePoolWithTag(PagedPool, ulSize, 'SGER');
   if (pfi == NULL)
   {
      ZwClose(hRegister);
      return STATUS_INSUFFICIENT_RESOURCES;
   }

   ntStatus = ZwQueryKey(hRegister,
      KeyFullInformation,
      pfi,
      ulSize,
      &ulSize);
   if (!NT_SUCCESS(ntStatus))
   {
      ZwClose(hRegister);
      ExFreePool(pfi);
      return ntStatus;
   }

   for (i = 0; i<pfi->Values; i++)
   {
      ntStatus = ZwEnumerateValueKey(hRegister,
         i,
         KeyValueBasicInformation,
         NULL,
         0,
         &ulSize);

      if (STATUS_BUFFER_OVERFLOW != ntStatus &&
         STATUS_BUFFER_TOO_SMALL != ntStatus)
      {
         ZwClose(hRegister);
         ExFreePool(pfi);
         return ntStatus;
      }

      pvbi =
         (PKEY_VALUE_BASIC_INFORMATION)
         ExAllocatePoolWithTag(PagedPool, ulSize, 'SGER');
      if (pvbi == NULL)
      {
         ZwClose(hRegister);
         ExFreePool(pfi);
         return ntStatus;
      }

      ntStatus = ZwEnumerateValueKey(hRegister,
         i,
         KeyValueBasicInformation,
         pvbi,
         ulSize,
         &ulSize);
      if (!NT_SUCCESS(ntStatus))
      {
         ZwClose(hRegister);
         ExFreePool(pfi);
         ExFreePool(pvbi);
         return ntStatus;
      }


      uniKeyName.Length =
         uniKeyName.MaximumLength =
         (USHORT)pvbi->NameLength;

      uniKeyName.Buffer = pvbi->Name;

      DbgPrint("The %d sub value name:%wZ\n", i, &uniKeyName);

      if (pvbi->Type == REG_SZ)
      {
         DbgPrint("type:REG_SZ\n");
      }
      else if (pvbi->Type == REG_MULTI_SZ)
      {
         DbgPrint("type:REG_MULTI_SZ\n");

      }
      else if (pvbi->Type == REG_DWORD)
      {
         DbgPrint("type:REG_DWORD\n");
      }
      else if (pvbi->Type == REG_BINARY)
      {
         DbgPrint("type:REG_BINARY\n");
      }

      ExFreePool(pvbi);
   }

   ExFreePool(pfi);
   ZwClose(hRegister);

   return ntStatus;
}

>