调用NtCompareTokens函数出现STATUS_ACCESS_VIOLATION的原因及替代方案
NtCompareTokens返回STATUS_ACCESS_VIOLATION的原因及替代方案
错误原因
你代码里的核心问题是输出参数传了NULL:NtCompareTokens的第三个参数是用来接收比较结果的输出参数,需要传入一个有效的BOOLEAN变量地址。但你定义的res是NULL,函数尝试往空地址写入数据,直接触发了访问违例(STATUS_ACCESS_VIOLATION)。
另外还要注意,调用NtCompareTokens要求两个令牌句柄都具备TOKEN_QUERY权限,如果句柄权限不足,也可能引发错误,但这次的访问违例明显是输出参数的问题导致的。
修复后的代码示例
把res换成栈上的有效变量,让函数能正常写入结果:
BOOLEAN compare(PHANDLE token_handle, PHANDLE duplicatetoken_handle) { HMODULE hModule = GetModuleHandle(TEXT("ntdll.dll")); BOOLEAN result = FALSE; if (hModule != NULL) { typedef NTSTATUS(NTAPI* NtCompareTokens_t)(HANDLE Token1, HANDLE Token2, PBOOLEAN Equal); NtCompareTokens_t pNtCompareTokens = (NtCompareTokens_t)GetProcAddress(hModule, "NtCompareTokens"); if (pNtCompareTokens != NULL) { NTSTATUS status = pNtCompareTokens(*token_handle, *duplicatetoken_handle, &result); // 可选:检查调用是否成功,失败则返回默认值 if (!NT_SUCCESS(status)) { result = FALSE; } } } return result; }
替代比较方法
如果不想用NtCompareTokens,可以试试这些方式:
- 对比令牌的核心信息:用
GetTokenInformation分别获取两个令牌的用户SID、组SID、权限列表,逐一对比这些内容是否完全一致。 - 结合登录会话ID判断:获取令牌的登录会话ID,再结合用户SID,能大概率判断是否为同一令牌(同一用户同一登录会话的令牌通常一致)。
- 不推荐直接对比令牌内存:令牌内部结构依赖系统版本,兼容性差,容易出问题。
内容的提问来源于stack exchange,提问作者Suchitra Mahato
相关产品推荐
相关产品推荐

