试图了解进程特权属性
Trying to understand process privilege attributes
我正在编写一个可以收集进程权限的日志记录服务,并且我正在尝试了解每个进程权限的属性。让我用这段代码解释一下:
HANDLE hToken;
if(OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &hToken))
{
DWORD dwSize = 0;
if(!GetTokenInformation(hToken, TokenPrivileges, NULL, dwSize, &dwSize) &&
::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
BYTE* pb = new (std::nothrow) BYTE[dwSize];
if(pb)
{
TOKEN_PRIVILEGES* pTPs = (TOKEN_PRIVILEGES*)pb;
DWORD dwSize2;
if(GetTokenInformation(hToken, TokenPrivileges, pTPs, dwSize, &dwSize2) &&
dwSize2 <= dwSize)
{
for(UINT i = 0; i < pTPs->PrivilegeCount; i++)
{
//Analyze privilege attributes to understand if it's enabled or disabled?
DWORD dwPrivAttr = pTPs->Privileges[i].Attributes;
//...
}
}
delete[] pb;
}
}
CloseHandle(hToken);
}
所以让我们看看 TOKEN_PRIVILEGES 和 LUID_AND_ATTRIBUTES
的结构:
#define SE_PRIVILEGE_ENABLED_BY_DEFAULT (0x00000001L)
#define SE_PRIVILEGE_ENABLED (0x00000002L)
#define SE_PRIVILEGE_REMOVED (0X00000004L)
#define SE_PRIVILEGE_USED_FOR_ACCESS (0x80000000L)
看起来它被定义为一个位掩码,但这带来了以下解释这些标志的问题:
ENABLED
和ENABLED_BY_DEFAULT
有什么区别?
什么是SE_PRIVILEGE_USED_FOR_ACCESS
以及如何使用它?
如果SE_PRIVILEGE_ENABLED
和SE_PRIVILEGE_REMOVED
都设置了怎么办?或者,重置?
我只是 运行 一个简单的测试,对于我的过程,SeShutdownPrivilege
权限将这些属性设置为 0
。那么这是什么意思呢?
我对这个结构比较困惑,但我暂时只说这些。
谢谢!
按顺序回答您的问题:
ENABLED_BY_DEFAULT
表示该权限是进程启动时启用的权限之一。如果您有 ENABLED
但没有 ENABLED_BY_DEFAULT
,则该进程已明确启用该权限。如果您有 ENABLED_BY_DEFAULT
但没有 ENABLED
,则该进程已明确禁用该权限。
根据文档,只要实际使用特权,就会设置 SE_PRIVILEGE_USED_FOR_ACCESS
。您可以使用它来进行故障排除,例如,检测您正在设置您实际上没有使用的特权,或者通过实验确定特定系统调用需要哪些特权。 (我从来没有检查过这是否真的像记录的那样运行,尽管我没有理由不这么认为。)
如果 SE_PRIVILEGE_ENABLED
和 SE_PRIVILEGE_REMOVED
都已设置,则您在 Windows 中发现了错误。 :-)
如果 SE_PRIVILEGE_ENABLED
和 SE_PRIVILEGE_REMOVED
均未设置,则权限存在于令牌中,未被删除,但当前未启用。您可以使用 AdjustTokenPrivileges().
启用它(或删除它)
如果该属性为零,则权限存在于令牌中但当前未启用、未被删除、默认情况下未启用且进程从未使用过。
我们中的一些人可能需要被明确告知的是,特权有三种可能的状态,而不仅仅是两种。当我开始研究这些东西时,我认为进程要么拥有特权,要么没有特权。但事实证明,即使进程有特权,它也可以处于禁用状态。换句话说,disabled != 没有。
接下来顺理成章。如果进程的访问令牌中不存在特权,则进程不具有该特权。反之亦然,如果进程没有特权,则特权不会出现在令牌中。
如果进程有权限,进程可以随意启用或禁用它,对吧?为什么这有用?好吧,我猜这允许你在不完全了解它们做什么的情况下调用库函数,如果它们做的比你想象的要多,就让它们失败……不过很奇怪。
我正在编写一个可以收集进程权限的日志记录服务,并且我正在尝试了解每个进程权限的属性。让我用这段代码解释一下:
HANDLE hToken;
if(OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &hToken))
{
DWORD dwSize = 0;
if(!GetTokenInformation(hToken, TokenPrivileges, NULL, dwSize, &dwSize) &&
::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
BYTE* pb = new (std::nothrow) BYTE[dwSize];
if(pb)
{
TOKEN_PRIVILEGES* pTPs = (TOKEN_PRIVILEGES*)pb;
DWORD dwSize2;
if(GetTokenInformation(hToken, TokenPrivileges, pTPs, dwSize, &dwSize2) &&
dwSize2 <= dwSize)
{
for(UINT i = 0; i < pTPs->PrivilegeCount; i++)
{
//Analyze privilege attributes to understand if it's enabled or disabled?
DWORD dwPrivAttr = pTPs->Privileges[i].Attributes;
//...
}
}
delete[] pb;
}
}
CloseHandle(hToken);
}
所以让我们看看 TOKEN_PRIVILEGES 和 LUID_AND_ATTRIBUTES
的结构:
#define SE_PRIVILEGE_ENABLED_BY_DEFAULT (0x00000001L)
#define SE_PRIVILEGE_ENABLED (0x00000002L)
#define SE_PRIVILEGE_REMOVED (0X00000004L)
#define SE_PRIVILEGE_USED_FOR_ACCESS (0x80000000L)
看起来它被定义为一个位掩码,但这带来了以下解释这些标志的问题:
ENABLED
和ENABLED_BY_DEFAULT
有什么区别?什么是
SE_PRIVILEGE_USED_FOR_ACCESS
以及如何使用它?如果
SE_PRIVILEGE_ENABLED
和SE_PRIVILEGE_REMOVED
都设置了怎么办?或者,重置?我只是 运行 一个简单的测试,对于我的过程,
SeShutdownPrivilege
权限将这些属性设置为0
。那么这是什么意思呢?
我对这个结构比较困惑,但我暂时只说这些。
谢谢!
按顺序回答您的问题:
ENABLED_BY_DEFAULT
表示该权限是进程启动时启用的权限之一。如果您有ENABLED
但没有ENABLED_BY_DEFAULT
,则该进程已明确启用该权限。如果您有ENABLED_BY_DEFAULT
但没有ENABLED
,则该进程已明确禁用该权限。根据文档,只要实际使用特权,就会设置
SE_PRIVILEGE_USED_FOR_ACCESS
。您可以使用它来进行故障排除,例如,检测您正在设置您实际上没有使用的特权,或者通过实验确定特定系统调用需要哪些特权。 (我从来没有检查过这是否真的像记录的那样运行,尽管我没有理由不这么认为。)如果
SE_PRIVILEGE_ENABLED
和SE_PRIVILEGE_REMOVED
都已设置,则您在 Windows 中发现了错误。 :-)如果
SE_PRIVILEGE_ENABLED
和SE_PRIVILEGE_REMOVED
均未设置,则权限存在于令牌中,未被删除,但当前未启用。您可以使用 AdjustTokenPrivileges(). 启用它(或删除它)
如果该属性为零,则权限存在于令牌中但当前未启用、未被删除、默认情况下未启用且进程从未使用过。
我们中的一些人可能需要被明确告知的是,特权有三种可能的状态,而不仅仅是两种。当我开始研究这些东西时,我认为进程要么拥有特权,要么没有特权。但事实证明,即使进程有特权,它也可以处于禁用状态。换句话说,disabled != 没有。
接下来顺理成章。如果进程的访问令牌中不存在特权,则进程不具有该特权。反之亦然,如果进程没有特权,则特权不会出现在令牌中。
如果进程有权限,进程可以随意启用或禁用它,对吧?为什么这有用?好吧,我猜这允许你在不完全了解它们做什么的情况下调用库函数,如果它们做的比你想象的要多,就让它们失败……不过很奇怪。