注册表是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