简单实现注册表受保护部分的只读

注册表是windows系统十分关键的部分,通过设置注册表项目,可以很好的配置优化计算机,当然也可以给计算机带来无法想象的灾难,我们来看一段关于注册表只读设置的代码……

  最近看wrk,发现注册表操作类函数都有类似下面的代码段:

 

      if (mode == UserMode) {
  return ZwRestoreKey(KeyHandle, FileHandle, Flags);
  } else {
  status = ObReferenceObjectByHandle(
  KeyHandle,
  0,
  CmpKeyObjectType,
  mode,
  (PVOID *)(&KeyBody),
  NULL
  );
  if (NT_SUCCESS(status)) {
  if ( CmIsKcbReadOnly(KeyBody->KeyControlBlock) ) {
  //
  // key is protected
  //
  status = STATUS_ACCESS_DENIED;
  } else {
  BEGIN_LOCK_CHECKPOINT;
  status = CmRestoreKey(
  KeyBody->KeyControlBlock,
  FileHandle,
  Flags
  );
  END_LOCK_CHECKPOINT;
  }
  ObDereferenceObject((PVOID)KeyBody);
  }
  }

 

   其中CmIsKcbReadOnly是实现保护的关键。定义如下:

 

      #define CmIsKcbReadOnly(kcb) ((kcb)->ExtFlags & CM_KCB_READ_ONLY_KEY)
  #define CM_KCB_READ_ONLY_KEY 0x0080 // this kcb is read-only all write operations onto it are denied.

 

  很简单吧,看来实现保护只需要设置一下KeyControlBlock里的ExtFlags就可以了。在win2003下KeyControlBlock类型定义如下:

 

       lkd> dt _CM_KEY_CONTROL_BLOCK
  +0x000 RefCount : Uint4B
  +0x004 ExtFlags : Pos 0, 8 Bits // 设置这里
  +0x004 PrivateAlloc : Pos 8, 1 Bit
  +0x004 Delete : Pos 9, 1 Bit
  +0x004 DelayedCloseIndex : Pos 10, 12 Bits
  +0x004 TotalLevels : Pos 22, 10 Bits
  +0x008 KeyHash : _CM_KEY_HASH
  +0x008 ConvKey : Uint4B
  +0x00c NextHash : Ptr32 _CM_KEY_HASH
  +0x010 KeyHive : Ptr32 _HHIVE
  +0x014 KeyCell : Uint4B
  +0x018 ParentKcb : Ptr32 _CM_KEY_CONTROL_BLOCK
  +0x01c NameBlock : Ptr32 _CM_NAME_CONTROL_BLOCK
  +0x020 CachedSecurity : Ptr32 _CM_KEY_SECURITY_CACHE
  +0x024 ValueCache : _CACHED_CHILD_LIST
  +0x02c IndexHint : Ptr32 _CM_INDEX_HINT_BLOCK
  +0x02c HashKey : Uint4B
  +0x02c SubKeyCount : Uint4B
  +0x030 KeyBodyListHead : _LIST_ENTRY
  +0x030 FreeListEntry : _LIST_ENTRY
  +0x038 KeyBodyArray : [4] Ptr32 _CM_KEY_BODY
  +0x048 DelayCloseEntry : Ptr32 Void
  +0x050 KcbLastWriteTime : _LARGE_INTEGER
  +0x058 KcbMaxNameLen : Uint2B
  +0x05a KcbMaxValueNameLen : Uint2B
  +0x05c KcbMaxValueDataLen : Uint4B
  +0x060 KcbUserFlags : Pos 0, 4 Bits
  +0x060 KcbVirtControlFlags : Pos 4, 4 Bits
  +0x060 KcbDebug : Pos 8, 8 Bits
  +0x060 Flags : Pos 16, 16 Bits

 

  实现的代码片段如下:

 

      #pragma pack(1)
  typedef struct _CM_KEY_BODY {
  ULONG Type; // "ky02"
  PVOID KeyControlBlock;
  PVOID NotifyBlock;
  PEPROCESS Process; // the owner process
  LIST_ENTRY KeyBodyList; // key_nodes using the same kcb
  } CM_KEY_BODY, *PCM_KEY_BODY;
  #pragma pack()
  NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
  {
  NTSTATUS ntStatus;
  UNICODE_STRING keyName;
  OBJECT_ATTRIBUTES objAttr;
  HANDLE hKey;
  PCM_KEY_BODY KeyBody;
  PULONG keyControlBlock;
  PHHIVE keyHive;
  RtlInitUnicodeString(&keyName, L"//Registry//Machine//SYSTEM//CurrentControlSet//Services//BITS");
  InitializeObjectAttributes(&objAttr, &keyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
  ntStatus = ZwOpenKey(&hKey, KEY_READ, &objAttr);
  if(! NT_SUCCESS(ntStatus))
  return STATUS_UNSUCCESSFUL;
  ntStatus = ObReferenceObjectByHandle(hKey, KEY_READ, NULL, KernelMode, &KeyBody, NULL);
  if(! NT_SUCCESS(ntStatus))
  {
  ZwClose(hKey);
  return STATUS_UNSUCCESSFUL;
  }
  keyControlBlock = KeyBody->KeyControlBlock;
  //
  // try to protect the key
  //
  *(PULONG)((ULONG)keyControlBlock + 0x4) |= 0x0080; // 0x14
  ObDereferenceObject(KeyBody);
  ZwClose(hKey);
  return STATUS_SUCCESS;
  }

 

  最后很扫兴的说,这种方法不适用于window2000

你可能感兴趣的:(简单实现注册表受保护部分的只读)