Windows内核:用内核APIo&HIVE文件格式管理注册表
字数 1835 2025-08-20 18:18:05

Windows内核注册表管理与HIVE文件解析

1. 注册表基础概念

注册表是Windows操作系统中的核心数据库,用于存储系统和应用程序的配置信息。它具有层次结构,包含键(Key)和值(Value)。

1.1 主要根键

  • HKEY_LOCAL_MACHINE (HKLM)
  • HKEY_CURRENT_USER (HKCU)
  • HKEY_CLASSES_ROOT (HKCR)
  • HKEY_USERS (HKU)
  • HKEY_CURRENT_CONFIG (HKCC)

1.2 恶意软件常见注册表操作

  1. 持久化:通过Run键实现自启动
    • HKLM\Software\Microsoft\Windows\CurrentVersion\Run
    • HKCU\Software\Microsoft\Windows\CurrentVersion\Run
  2. 隐藏自身:修改Explorer设置隐藏文件/进程
  3. 修改系统配置:禁用任务管理器、安全中心等
  4. 应用程序劫持:修改文件关联
  5. 信息收集:窃取用户凭据和系统配置

2. 内核API注册表操作

2.1 常用内核API函数

2.1.1 创建/打开注册表项

NTSTATUS ZwCreateKey(
    PHANDLE KeyHandle,
    ACCESS_MASK DesiredAccess,
    POBJECT_ATTRIBUTES ObjectAttributes,
    ULONG TitleIndex,
    PUNICODE_STRING Class,
    ULONG CreateOptions,
    PULONG Disposition
);

NTSTATUS ZwOpenKey(
    PHANDLE KeyHandle,
    ACCESS_MASK DesiredAccess,
    POBJECT_ATTRIBUTES ObjectAttributes
);

示例代码:

HANDLE hKey;
UNICODE_STRING regPath;
RtlInitUnicodeString(&regPath, L"\\Registry\\Machine\\Software\\MyKey");
OBJECT_ATTRIBUTES objAttr;
InitializeObjectAttributes(&objAttr, &regPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
NTSTATUS status = ZwCreateKey(&hKey, KEY_ALL_ACCESS, &objAttr, 0, NULL, 0, NULL);

2.1.2 删除注册表项/值

NTSTATUS ZwDeleteKey(HANDLE KeyHandle);
NTSTATUS ZwDeleteValueKey(HANDLE KeyHandle, PUNICODE_STRING ValueName);

2.1.3 设置注册表值

NTSTATUS ZwSetValueKey(
    HANDLE KeyHandle,
    PUNICODE_STRING ValueName,
    ULONG TitleIndex,
    ULONG Type,
    PVOID Data,
    ULONG DataSize
);

示例代码:

UNICODE_STRING valueName;
RtlInitUnicodeString(&valueName, L"MyValue");
DWORD data = 1;
NTSTATUS status = ZwSetValueKey(hKey, &valueName, 0, REG_DWORD, &data, sizeof(data));

2.1.4 查询注册表值

NTSTATUS ZwQueryValueKey(
    HANDLE KeyHandle,
    PUNICODE_STRING ValueName,
    KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
    PVOID KeyValueInformation,
    ULONG Length,
    PULONG ResultLength
);

2.2 实现注册表持久化

完整示例代码:

#include <ntddk.h>

VOID ShowError(PUCHAR pszText, NTSTATUS ntStatus) {
    DbgPrint("%s Error[0x%X]\n", pszText, ntStatus);
}

BOOLEAN SetRegistryAutoRun(PUNICODE_STRING ustrExecutablePath) {
    HANDLE hKey = NULL;
    OBJECT_ATTRIBUTES objectAttributes;
    UNICODE_STRING ustrKeyPath, ustrValueName;
    NTSTATUS status;
    
    RtlInitUnicodeString(&ustrKeyPath, L"\\Registry\\Machine\\Software\\Microsoft\\Windows\\CurrentVersion\\Run");
    InitializeObjectAttributes(&objectAttributes, &ustrKeyPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
    
    status = ZwOpenKey(&hKey, KEY_ALL_ACCESS, &objectAttributes);
    if (!NT_SUCCESS(status)) {
        ShowError("ZwOpenKey", status);
        return FALSE;
    }
    
    RtlInitUnicodeString(&ustrValueName, L"MyPersistentApp");
    status = ZwSetValueKey(hKey, &ustrValueName, 0, REG_SZ, ustrExecutablePath->Buffer, ustrExecutablePath->Length);
    
    if (!NT_SUCCESS(status)) {
        ZwClose(hKey);
        ShowError("ZwSetValueKey", status);
        return FALSE;
    }
    
    ZwClose(hKey);
    DbgPrint("Successfully set auto-run entry.\n");
    return TRUE;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath) {
    UNICODE_STRING ustrExecutablePath;
    RtlInitUnicodeString(&ustrExecutablePath, L"C:\\Path\\To\\YourApp.exe");
    SetRegistryAutoRun(&ustrExecutablePath);
    return STATUS_SUCCESS;
}

3. HIVE文件格式解析

3.1 HIVE文件基础

HIVE文件是注册表在磁盘上的存储形式,位于%SystemRoot%\System32\Config目录下。每个HIVE文件代表一棵注册表树。

3.2 HIVE文件结构

3.2.1 Header结构

  • Signature(0x0): "regf"标识
  • 主/次序列号(0x4,0x8): 校验完整性
  • 最后写入时间(0xC): 8字节Windows文件时间
  • 主/次版本号(0x14,0x18)
  • 文件类型(0x1C): 0x0标准类型,0x1事务日志
  • 根键偏移量(0x24): RootCell的相对偏移
  • 文件长度(0x28): 不包括Header的大小
  • 文件名(0x30): Unicode字符串

3.2.2 HBIN块

  • Signature(0x0): "hbin"标识
  • 文件偏移(0x4): 相对于第一个HBIN块的偏移
  • 数据大小(0x8): HBIN块大小(通常4096字节)

3.2.3 Cell单元

包含在HBIN块内,由以下记录组成:

  1. nk记录: 描述注册表项
  2. vk记录: 描述注册表值
  3. sk记录: 描述安全权限数据

3.3 记录类型详解

3.3.1 nk记录(注册表项)

  • 签名(0x4): "nk"(0x6B6E)
  • 最后修改时间(0x8): 8字节
  • 父项偏移量(0x14): 0xFFFFFFFF表示无父项
  • 子项数量(0x18)
  • 子项列表偏移量(0x20)
  • vk数量(0x28)
  • vk列表偏移量(0x2C)
  • sk索引(0x30)
  • 名称长度(0x4C)
  • 键名称(0x50): ASCII字符串

3.3.2 vk记录(注册表值)

  • 签名(0x4): "vk"(0x6B76)
  • 名称长度(0x6)
  • 数据长度(0x8)
  • 数据(0xC)
  • 数据类型(0x10):
    • REG_SZ(0x1)
    • REG_EXPAND_SZ(0x2)
    • REG_BINARY(0x3)
    • REG_DWORD(0x4)
    • REG_MULTI_SZ(0x7)
  • 名称(0x18): ASCII字符串

3.3.3 sk记录(安全信息)

  • Flink(0x8): 下一条sk记录偏移
  • Blink(0xC): 上一条sk记录偏移

3.3.4 List记录

  1. lf/lh: 子项集合(lf按字母序,lh哈希表)
  2. li/ri: 子项存储(li简单,ri分块)
  3. db: 已删除项记录

3.4 HIVE文件解析实践

3.4.1 驱动框架

#include <ntddk.h>

VOID DriverUnload(_In_ PDRIVER_OBJECT DriverObject) {
    UNREFERENCED_PARAMETER(DriverObject);
    DbgPrint("HIVE解析驱动卸载!\n");
}

NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath) {
    UNREFERENCED_PARAMETER(RegistryPath);
    DriverObject->DriverUnload = DriverUnload;
    DbgPrint("HIVE解析驱动加载成功!\n");
    return STATUS_SUCCESS;
}

3.4.2 文件读取功能

NTSTATUS ReadFile(_In_ PUNICODE_STRING FileName, _Out_ PVOID* Buffer, _Out_ ULONG* FileSize) {
    HANDLE fileHandle;
    IO_STATUS_BLOCK ioStatusBlock;
    OBJECT_ATTRIBUTES objectAttributes;
    NTSTATUS status;
    FILE_STANDARD_INFORMATION fileInfo;
    
    InitializeObjectAttributes(&objectAttributes, FileName, OBJ_KERNEL_HANDLE, NULL, NULL);
    status = ZwCreateFile(&fileHandle, GENERIC_READ, &objectAttributes, &ioStatusBlock, NULL, 
                         FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, 
                         FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
    
    if (!NT_SUCCESS(status)) {
        DbgPrint("打开文件失败,状态码: 0x%08x\n", status);
        return status;
    }
    
    status = ZwQueryInformationFile(fileHandle, &ioStatusBlock, &fileInfo, sizeof(fileInfo), FileStandardInformation);
    if (!NT_SUCCESS(status)) {
        ZwClose(fileHandle);
        return status;
    }
    
    *FileSize = fileInfo.EndOfFile.LowPart;
    *Buffer = ExAllocatePoolWithTag(NonPagedPool, *FileSize, 'Hive');
    
    if (*Buffer == NULL) {
        ZwClose(fileHandle);
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    
    status = ZwReadFile(fileHandle, NULL, NULL, NULL, &ioStatusBlock, *Buffer, *FileSize, NULL, NULL);
    if (!NT_SUCCESS(status)) {
        ExFreePoolWithTag(*Buffer, 'Hive');
        ZwClose(fileHandle);
        return status;
    }
    
    ZwClose(fileHandle);
    return status;
}

3.4.3 HIVE头部解析

typedef struct _HIVE_HEADER {
    CHAR Signature[4];        // "regf"
    ULONG Sequence1;         // 序列号
    ULONG Sequence2;         // 序列号
    ULONG RootCellOffset;    // RootCell的偏移
    ULONG HiveBinsDataSize;  // hbin数据的大小
    ULONG ClusteringFactor;
    // 其他字段...
} HIVE_HEADER, *PHIVE_HEADER;

NTSTATUS ParseHiveHeader(_In_ PVOID Buffer, _Out_ ULONG* RootCellOffset) {
    PHIVE_HEADER hiveHeader = (PHIVE_HEADER)Buffer;
    
    if (RtlCompareMemory(hiveHeader->Signature, "regf", 4) != 4) {
        DbgPrint("HIVE文件签名错误!\n");
        return STATUS_INVALID_PARAMETER;
    }
    
    *RootCellOffset = hiveHeader->RootCellOffset;
    DbgPrint("RootCell Offset: 0x%08x\n", *RootCellOffset);
    return STATUS_SUCCESS;
}

3.4.4 nk记录解析

NTSTATUS ParseNkRecord(_In_ PVOID Buffer, _In_ ULONG Offset) {
    PNK_RECORD nkRecord = (PNK_RECORD)((PUCHAR)Buffer + Offset);
    
    if (nkRecord->Signature != 0x6B6E) { // "nk"
        DbgPrint("NK记录签名错误!\n");
        return STATUS_INVALID_PARAMETER;
    }
    
    DbgPrint("NK记录解析成功!子键数量: %u, 键值数量: %u\n", 
             nkRecord->SubkeyCount, nkRecord->ValueCount);
    return STATUS_SUCCESS;
}

4. 总结

本文详细介绍了Windows内核中注册表操作的两种方式:

  1. 通过内核API函数直接操作注册表
  2. 通过解析底层的HIVE文件格式间接操作注册表

对于安全研究而言,理解HIVE文件格式尤为重要,因为它比API操作更难被检测和监控。通过分析HIVE文件结构,可以深入理解注册表的存储机制,为注册表取证和安全分析提供基础。

Windows内核注册表管理与HIVE文件解析 1. 注册表基础概念 注册表是Windows操作系统中的核心数据库,用于存储系统和应用程序的配置信息。它具有层次结构,包含键(Key)和值(Value)。 1.1 主要根键 HKEY_ LOCAL_ MACHINE (HKLM) HKEY_ CURRENT_ USER (HKCU) HKEY_ CLASSES_ ROOT (HKCR) HKEY_ USERS (HKU) HKEY_ CURRENT_ CONFIG (HKCC) 1.2 恶意软件常见注册表操作 持久化 :通过Run键实现自启动 HKLM\Software\Microsoft\Windows\CurrentVersion\Run HKCU\Software\Microsoft\Windows\CurrentVersion\Run 隐藏自身 :修改Explorer设置隐藏文件/进程 修改系统配置 :禁用任务管理器、安全中心等 应用程序劫持 :修改文件关联 信息收集 :窃取用户凭据和系统配置 2. 内核API注册表操作 2.1 常用内核API函数 2.1.1 创建/打开注册表项 示例代码: 2.1.2 删除注册表项/值 2.1.3 设置注册表值 示例代码: 2.1.4 查询注册表值 2.2 实现注册表持久化 完整示例代码: 3. HIVE文件格式解析 3.1 HIVE文件基础 HIVE文件是注册表在磁盘上的存储形式,位于 %SystemRoot%\System32\Config 目录下。每个HIVE文件代表一棵注册表树。 3.2 HIVE文件结构 3.2.1 Header结构 Signature (0x0): "regf"标识 主/次序列号 (0x4,0x8): 校验完整性 最后写入时间 (0xC): 8字节Windows文件时间 主/次版本号 (0x14,0x18) 文件类型 (0x1C): 0x0标准类型,0x1事务日志 根键偏移量 (0x24): RootCell的相对偏移 文件长度 (0x28): 不包括Header的大小 文件名 (0x30): Unicode字符串 3.2.2 HBIN块 Signature (0x0): "hbin"标识 文件偏移 (0x4): 相对于第一个HBIN块的偏移 数据大小 (0x8): HBIN块大小(通常4096字节) 3.2.3 Cell单元 包含在HBIN块内,由以下记录组成: nk记录 : 描述注册表项 vk记录 : 描述注册表值 sk记录 : 描述安全权限数据 3.3 记录类型详解 3.3.1 nk记录(注册表项) 签名 (0x4): "nk"(0x6B6E) 最后修改时间 (0x8): 8字节 父项偏移量 (0x14): 0xFFFFFFFF表示无父项 子项数量 (0x18) 子项列表偏移量 (0x20) vk数量 (0x28) vk列表偏移量 (0x2C) sk索引 (0x30) 名称长度 (0x4C) 键名称 (0x50): ASCII字符串 3.3.2 vk记录(注册表值) 签名 (0x4): "vk"(0x6B76) 名称长度 (0x6) 数据长度 (0x8) 数据 (0xC) 数据类型 (0x10): REG_ SZ(0x1) REG_ EXPAND_ SZ(0x2) REG_ BINARY(0x3) REG_ DWORD(0x4) REG_ MULTI_ SZ(0x7) 名称 (0x18): ASCII字符串 3.3.3 sk记录(安全信息) Flink (0x8): 下一条sk记录偏移 Blink (0xC): 上一条sk记录偏移 3.3.4 List记录 lf/lh : 子项集合(lf按字母序,lh哈希表) li/ri : 子项存储(li简单,ri分块) db : 已删除项记录 3.4 HIVE文件解析实践 3.4.1 驱动框架 3.4.2 文件读取功能 3.4.3 HIVE头部解析 3.4.4 nk记录解析 4. 总结 本文详细介绍了Windows内核中注册表操作的两种方式: 通过内核API函数直接操作注册表 通过解析底层的HIVE文件格式间接操作注册表 对于安全研究而言,理解HIVE文件格式尤为重要,因为它比API操作更难被检测和监控。通过分析HIVE文件结构,可以深入理解注册表的存储机制,为注册表取证和安全分析提供基础。