Saj*_*rim 5 winapi uac privilege-elevation access-token elevated-privileges
在这篇伟大的MSDN文章的帮助下,我的第一个想法是简单地检查进程是否使用提升的Administrator组,并使用AdjustTokenGroups()我将Administrator组设置为SE_GROUP_USE_FOR_DENY_ONLY.不幸的是,我们无法修改当前正在运行的进程的管理员组,因为它还具有该SE_GROUP_MANDATORY属性,这使得它无法进行更改.
MSDN文档有这样的说法:
该AdjustTokenGroups函数无法禁用具有结构中SE_GROUP_MANDATORY属性的组TOKEN_GROUPS.请CreateRestrictedToken改用.
所以,我完成了以下代码来实现这一目标;
bool _IsNewProcessLaunched()
{
HANDLE hToken = NULL;
bool hasRestarted = false;
if (!OpenProcessToken( GetCurrentProcess(),
TOKEN_ASSIGN_PRIMARY | TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ADJUST_GROUPS,
&hToken ))
{
return hasRestarted;
}
PSECURITY_DESCRIPTOR pSID = NULL;
SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
if(! AllocateAndInitializeSid( &SIDAuth, 2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&pSID) )
{
CloseHandle(hToken);
hToken = NULL;
return hasRestarted;
}
BOOL isAdmin = FALSE;
BOOL ok = CheckTokenMembership(NULL, pSID, &isAdmin);
// Create the SID structure for the administrator SID
SID_AND_ATTRIBUTES adminSID = {0};
adminSID.Sid = pSID;
// Create a restricted token which denies the administrator group
HANDLE restrictedToken;
CreateRestrictedToken(hToken,RESTR,DISABLE_MAX_PRIVILEGE,&adminSID,NULL,NULL,NULL,NULL,&restrictedToken);
//Create startup info
STARTUPINFO si = {0};
PROCESS_INFORMATION pi = {0};
si.lpDesktop = L"winsta0\\default";
si.cb = sizeof( si );
// Get the current executables name
TCHAR exePath[MAX_PATH];
GetModuleFileName(NULL,exePath,MAX_PATH);
// Start the new (non-administrator elevated) restricted process
if( CreateProcessAsUser(restrictedToken,exePath,NULL,NULL,NULL,TRUE,NORMAL_PRIORITY_CLASS,NULL,NULL,&si,&pi) == 0)
hasRestarted = false;
else
hasRestarted = true;
return hasRestarted;
}
Run Code Online (Sandbox Code Playgroud)
但新进程仍以管理员身份运行,而不是以普通用户身份运行.
我该如何做到这一点?
由于您要限制调用进程的令牌,因此启动的进程将使用与调用进程相同的用户帐户运行,只需使用受限制的权限.请记住,在UAC下,管理员没有提升就没有完整的管理员权限. CreateRestrictedToken()创建具有受限权限的令牌.因此,即使用户可能是管理员,也不意味着启动的进程将以管理权限运行.
顺便说一句,有一个简化的API,称为Safer API,您可以使用它代替CreateRestrictedToken():
#include <WinSafer.h>
bool _IsNewProcessLaunched()
{
// Create the restricted token.
SAFER_LEVEL_HANDLE hLevel = NULL;
if (!SaferCreateLevel(SAFER_SCOPEID_USER, SAFER_LEVELID_NORMALUSER, SAFER_LEVEL_OPEN, &hLevel, NULL))
{
return false;
}
HANDLE hRestrictedToken = NULL;
if (!SaferComputeTokenFromLevel(hLevel, NULL, &hRestrictedToken, 0, NULL))
{
SaferCloseLevel(hLevel);
return false;
}
SaferCloseLevel(hLevel);
// Set the token to medium integrity.
TOKEN_MANDATORY_LABEL tml = {0};
tml.Label.Attributes = SE_GROUP_INTEGRITY;
// alternatively, use CreateWellKnownSid(WinMediumLabelSid) instead...
if (!ConvertStringSidToSid(TEXT("S-1-16-8192"), &(tml.Label.Sid)))
{
CloseHandle(hRestrictedToken);
return false;
}
if (!SetTokenInformation(hRestrictedToken, TokenIntegrityLevel, &tml, sizeof(tml) + GetLengthSid(tml.Label.Sid))))
{
LocalFree(tml.Label.Sid);
CloseHandle(hRestrictedToken);
return false;
}
LocalFree(tml.Label.Sid);
// Create startup info
STARTUPINFO si = {0};
si.cb = sizeof( si );
si.lpDesktop = L"winsta0\\default";
PROCESS_INFORMATION pi = {0};
// Get the current executable's name
TCHAR exePath[MAX_PATH+1] = {0};
GetModuleFileName(NULL, exePath, MAX_PATH);
// Start the new (non-elevated) restricted process
if (!CreateProcessAsUser(hRestrictedToken, exePath, NULL, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi))
{
CloseHandle(hRestrictedToken);
return false;
}
CloseHandle(hRestrictedToken);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return true;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2702 次 |
| 最近记录: |