使用 RtlHashUnicodeString 的 BaseDllName 哈希与现有 BaseNameHashValue 不匹配

问题描述 投票:0回答:1

BaseNameHashValue 是 LDR_DATA_TABLE_ENTRY 中的加载器数据表条目, 使用 RtlHashUnicodeString 存储 BaseDllName 的哈希值。 (参考:Windows 内部原理第七版第 1 部分系统架构、进程、线程、内存管理等。)

运行下面的 x86 程序会输出这些值

Name:       peb2.exe
Hash:       0x29413AE9 Calculated: 0x264362E9
Address:    0x00F10000
---------------------------------------------
Name:       ntdll.dll
Hash:       0xF46857D4 Calculated: 0xD22E2014
Address:    0x77AD0000
---------------------------------------------
Name:       KERNEL32.DLL
Hash:       0x536CD652 Calculated: 0x536CD652
Address:    0x75C80000
---------------------------------------------
Name:       KERNELBASE.dll
Hash:       0x0235BEC4 Calculated: 0x1217B6E4
Address:    0x77160000
---------------------------------------------
Name:       ucrtbase.dll
Hash:       0xAEF34AF7 Calculated: 0x2E1D6317
Address:    0x77430000
---------------------------------------------
Name:       VCRUNTIME140.dll
Hash:       0xB61775F8 Calculated: 0xC5F96E18
Address:    0x75710000
---------------------------------------------

但是,请注意,与使用 RtlHashUnicodeString 计算出的值匹配的唯一哈希值是

Name:       KERNEL32.DLL
Hash:       0x536CD652 Calculated: 0x536CD652
Address:    0x75C80000

为什么 KERNEL32.DLL 具有相同的哈希值,但其他模块却没有?

peb2.cpp

#include <stdio.h>
#include <stdint.h>
#include <windows.h>
#include <ntstatus.h>
#include <winternl.h>

#define HASH_STRING_ALGORITHM_DEFAULT 0

typedef struct {
    PVOID Reserved1[2];
    LIST_ENTRY InMemoryOrderLinks;
    PVOID Reserved2[2];
    PVOID DllBase;
    PVOID EntryPoint;
    ULONG SizeOfImage;
    UNICODE_STRING FullDllName;
    UNICODE_STRING BaseDllName;
    uint8_t pad[92];
    /*
    union _union_9066 field_0x24;
    ushort ObsoleteLoadCount;
    ushort TlsIndex;
    struct _LIST_ENTRY HashLinks;
    ulong TimeDateStamp;
    struct _ACTIVATION_CONTEXT* EntryPointActivationContext;
    void* Lock;
    struct _LDR_DDAG_NODE* DdagNode;
    struct _LIST_ENTRY NodeModuleLink;
    struct _LDRP_LOAD_CONTEXT* LoadContext;
    void* ParentDllBase;
    void* SwitchBackContext;
    struct _RTL_BALANCED_NODE BaseAddressIndexNode;
    struct _RTL_BALANCED_NODE MappingInfoIndexNode;
    ulong OriginalBase;
    long Padding_84;
    union _LARGE_INTEGER LoadTime;
    */
    ULONG BaseNameHashValue;
    /*
    enum _LDR_DLL_LOAD_REASON LoadReason;
    ulong ImplicitPathOptions;
    ulong ReferenceCount;
    ulong DependentLoadFlags;
    uchar SigningLevel;
    char __PADDING__[3];    
    */
} MY_LDR_DATA_TABLE_ENTRY;

typedef VOID(NTAPI* pRtlInitUnicodeString)(PUNICODE_STRING, PCWSTR);
typedef NTSTATUS(NTAPI* pRtlHashUnicodeString)(const UNICODE_STRING*, BOOLEAN, ULONG, PULONG);

ULONG GetHashFromBaseName(PCWSTR BaseName) {
    ULONG hash = 0;
    HMODULE hNtdll = GetModuleHandle(L"ntdll.dll");
    pRtlInitUnicodeString RtlInitUnicodeString = (pRtlInitUnicodeString)GetProcAddress(hNtdll, "RtlInitUnicodeString");
    pRtlHashUnicodeString RtlHashUnicodeString = (pRtlHashUnicodeString)GetProcAddress(hNtdll, "RtlHashUnicodeString");
    UNICODE_STRING uStr;
    RtlInitUnicodeString(&uStr, BaseName);
    RtlHashUnicodeString(&uStr, FALSE, HASH_STRING_ALGORITHM_DEFAULT, &hash);
    return hash;
}

int main()
{
    PPEB peb = (PPEB)__readfsdword(0x30);
    PLIST_ENTRY ptr = peb->Ldr->InMemoryOrderModuleList.Flink;

    while (ptr != &peb->Ldr->InMemoryOrderModuleList)
    {
        MY_LDR_DATA_TABLE_ENTRY* e = CONTAINING_RECORD(ptr, MY_LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);

        if (e->BaseDllName.Buffer != NULL) {
            int len = e->BaseDllName.Length / sizeof(wchar_t);
            wchar_t BaseName[256];
            wcsncpy_s(BaseName, sizeof(BaseName) / sizeof(wchar_t), e->BaseDllName.Buffer, len);
            BaseName[len] = L'\0';
            // BaseDllName - The name of the module itself, without the full path.
            wprintf(L"Name:       %s\n", BaseName);
            // BaseNameHashValue - Hash of BaseDllName using RtlHashUnicodeString.
            wprintf(L"Hash:       0x%08X Calculated: 0x%08X\n", e->BaseNameHashValue, GetHashFromBaseName(BaseName));
            // Holds the base address at which the module was loaded.
            wprintf(L"Address:    0x%p\n", (void*)e->DllBase);
            wprintf(L"---------------------------------------------\n");
        }

        ptr = ptr->Flink;
    }

    return 0;
}
windows dll kernel-module
1个回答
0
投票

更改此调用中的第二个参数

RtlHashUnicodeString(&uStr, FALSE, HASH_STRING_ALGORITHM_DEFAULT, &hash);

为真:

RtlHashUnicodeString(&uStr, TRUE, HASH_STRING_ALGORITHM_DEFAULT, &hash);

查看 ntdll.dll,加载器子系统用私有函数

RtlHashUnicodeString
包装
LdrpHashUnicodeString
。该函数始终使用不区分大小写的哈希生成。

© www.soinside.com 2019 - 2024. All rights reserved.