KB131065演示了如何激活SeDebugPrivilege以打开任何进程的句柄。它有一个名为SetPrivilege
的函数调用AdjustTokenPrivileges
,但有两个实现,没有提到原因。
第一个实现在两次传递中调用ATP:
//
// first pass. get current privilege setting
//
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = 0;
AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
&tpPrevious,
&cbPrevious
);
if (GetLastError() != ERROR_SUCCESS) return FALSE;
//
// second pass. set privilege based on previous setting
//
tpPrevious.PrivilegeCount = 1;
tpPrevious.Privileges[0].Luid = luid;
if(bEnablePrivilege) {
tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
}
else {
tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED &
tpPrevious.Privileges[0].Attributes);
}
AdjustTokenPrivileges(
hToken,
FALSE,
&tpPrevious,
cbPrevious,
NULL,
NULL
);
这看起来有点矫枉过正。我没有在文档中看到任何内容,表明previous-state参数的Attributes
字段接收到需要保留的任何其他标志。看起来更像是代码从禁用特权开始,然后它返回并重新启用它或再次禁用它。我有正确的解释吗?别人推荐这种技术吗?
SetPrivilege
的第二个实现看起来更像我期望的那样:
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if(bEnablePrivilege) {
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
} else {
tp.Privileges[0].Attributes = 0;
}
AdjustTokenPrivileges( hToken, FALSE, &tp, cb, NULL, NULL );
第二个版本是否过于简化?我注意到它与Enabling and Disabling Privileges in C++中演示的内容基本相同,只是KB文章忽略了API的返回值并直接转到GetLastError
来检测成功和失败。
答案 0 :(得分:1)
我一直使用第二个例子。
在第一个例子中我完全看不到任何意义。例如,GetWindowLong\SetWindowLong
函数是有意义的,但对于特权,根本没有可以组合的持久设置,因此需要检索以前的状态。
是的,他们实际上是为了获得当前状态而禁用该权限,这是错误的 然而,遗憾的是,MSDN上有许多可怕的代码。