You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++内核调用ZwQuerySystemInformation报类型不兼容错误排查

内核BigPool查询代码类型转换报错修复

核心错误点

  • 自定义的ZwQuerySystemInformation函数签名完全不符合原生定义:第二个参数被错误定义为PSYSTEM_BIGPOOL_INFORMATION强类型指针,实际应为通用无类型指针PVOID;长度参数、返回长度参数被错误定义为ULONG64类型,实际原生为ULONG类型,这是触发编译报错、甚至后续运行时栈崩溃的核心原因。
  • 首次探测缓冲区长度的调用传参逻辑错误:第一次调用函数获取所需缓冲区大小时,不需要传入有效信息结构体指针,直接传NULL即可,你传入&infoLen(长度变量的地址)和错误的函数签名共同触发了类型不匹配报错。
  • 附加逻辑问题:一是自定义的SystemBigPoolInformation枚举值默认取0,和Windows原生系统的枚举值不匹配,编译通过后调用也会返回参数错误;二是打印SizeInBytes(SIZE_T类型数值)时误用了指针格式符%p,会导致打印值异常。

修正后的代码

修正后的结构体与函数声明

typedef struct _SYSTEM_BIGPOOL_ENTRY {
    union {
        PVOID VirtualAddress;
        ULONG_PTR NonPaged : 1;
    };
    ULONG_PTR SizeInBytes;
    union {
        UCHAR Tag[4];
        ULONG64 TagULong;
    };
} SYSTEM_BIGPOOL_ENTRY, *PSYSTEM_BIGPOOL_ENTRY;

typedef struct _SYSTEM_BIGPOOL_INFORMATION {
    ULONG64 Count;
    SYSTEM_BIGPOOL_ENTRY AllocatedInfo[ANYSIZE_ARRAY];
} SYSTEM_BIGPOOL_INFORMATION, *PSYSTEM_BIGPOOL_INFORMATION;

typedef enum _SYSTEM_INFORMATION_CLASS {
    SystemBigPoolInformation = 66 // 补全原生系统对应枚举值,默认0会导致调用失败
} SYSTEM_INFORMATION_CLASS;

// 修正为符合原生定义的函数签名
typedef NTSTATUS(WINAPI* fNtQuerySystemInformation)(
    SYSTEM_INFORMATION_CLASS SystemInformationClass, 
    PVOID SystemInformation,
    ULONG SystemInformationLength, 
    PULONG ReturnLength
    );

NTSTATUS ZwQuerySystemInformation(
    SYSTEM_INFORMATION_CLASS SystemInformationClass,
    PVOID SystemInformation,
    ULONG SystemInformationLength,
    PULONG ReturnLength);

注意:内核函数声明必须和系统导出的原生函数签名完全一致,参数类型、参数顺序不匹配会直接导致栈错位、调用崩溃。

修正后的业务实现代码

PVOID ExPool() {
    ULONG infoLen = 0;
    NTSTATUS status = ZwQuerySystemInformation(SystemBigPoolInformation, NULL, 0, &infoLen);
    PSYSTEM_BIGPOOL_INFORMATION pPoolInfo = NULL;

    while (status == STATUS_INFO_LENGTH_MISMATCH)
    {
        DbgPrintEx(0, 0, "Required Length : %lX\n", infoLen);

        if (pPoolInfo) {
            ExFreePool(pPoolInfo);
            pPoolInfo = NULL;
        }

        pPoolInfo = (PSYSTEM_BIGPOOL_INFORMATION)ExAllocatePool(NonPagedPool, infoLen);
        if (!pPoolInfo) {
            return NULL;
        }
        status = ZwQuerySystemInformation(SystemBigPoolInformation, pPoolInfo, infoLen, &infoLen);
    }

    if (NT_SUCCESS(status) && pPoolInfo)
    {
        DbgPrintEx(0, 0, "Call status : %lX\n", status);
        DbgPrintEx(0, 0, "BigPool Entry Count : %lu\n", pPoolInfo->Count);

        for (ULONG64 i = 0; i < pPoolInfo->Count; i++)
        {
            SYSTEM_BIGPOOL_ENTRY* Entry = &pPoolInfo->AllocatedInfo[i];
            PVOID VirtualAddress = (PVOID)((uintptr_t)Entry->VirtualAddress & ~1ull);
            SIZE_T SizeInBytes = Entry->SizeInBytes;
            BOOLEAN NonPaged = (BOOLEAN)(Entry->NonPaged);

            if (NonPaged && SizeInBytes == 0x200000)
            {
                // 修正数值类型的打印格式符,不要用%p打印非地址数值
                DbgPrintEx(0, 0, "NonPagedPool Address: %p, Size: %llX\n", VirtualAddress, SizeInBytes);
            }
        }

        ExFreePool(pPoolInfo);
        pPoolInfo = NULL;
    }
    return NULL;
}

补充说明

你之前尝试把变量转成ULONG64解决不了问题,因为报错根本不是业务逻辑里的结构体字段类型不匹配,是函数原型定义错误+首次调用传参错误两个基础问题,和结构体里的ULONG/ULONG64字段定义没有关系。

内容的提问来源于stack exchange,提问作者Maurice Moss

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 06:24:25