从流程中删除管理员特权 [英] Removing Administrator Privilages from Process
问题描述
借助这篇出色的 MSDN文章,我的第一个想法只是简单地检查该进程是否使用提升的管理员组,并使用 AdjustTokenGroups()
将管理员组设置为 SE_GROUP_USE_FOR_DENY_ONLY
。但是不幸的是,我们不能在当前运行的进程上修改管理员组,因为它还具有 SE_GROUP_MANDATORY
属性,这使得更改时难以理解。
With the help of this great MSDN article, my first idea was to simply check if the process is using an elevated Administrator group, and using AdjustTokenGroups()
I would set the Administrator group to SE_GROUP_USE_FOR_DENY_ONLY
. Unfortunately though, we can't modify the administrator group on the currently running process as it also has the SE_GROUP_MANDATORY
attribute, which makes it inelligable for changing.
MSDN文档对此有以下说法:
The MSDN document has this to say about it:
AdjustTokenGroups
函数无法禁用 TOKEN_GROUPS
结构中具有 SE_GROUP_MANDATORY
属性的组。使用 CreateRestrictedToken
代替。
The AdjustTokenGroups
function cannot disable groups with the SE_GROUP_MANDATORY
attribute in the TOKEN_GROUPS
structure. Use CreateRestrictedToken
instead.
因此,我完成了以下代码来实现这一点;
So, I am done the following code to achieve this;
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;
}
但是新流程仍以管理员的身份运行比作为普通用户。
But new process is still running as administrator rather than as the normal user.
我该怎么做?
推荐答案
调用进程的令牌,则启动的进程将使用与调用进程相同的用户帐户来运行,只是具有受限的权限。请记住,在UAC下,管理员没有提升权限就没有完整的管理员权限。 CreateRestrictedToken()
创建具有受限权限的令牌。因此,即使用户可能是管理员,并不意味着启动的进程将具有管理权限。
Since you are restricting the calling process's token, the launched process will be run with the same user account as the calling process, just with restricted permissions. Remember, under UAC, administrators do not have full admin rights without elevation. CreateRestrictedToken()
creates a token with restricted permissions. So even though the user may be administrator does not mean the launched process will run with administrative rights.
BTW,有一个更简单的API,被称为更安全的API ,您可以使用而不是 CreateRestrictedToken()
:
BTW, there is a simplier API, known as the Safer API, that you can use instead of 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;
}
这篇关于从流程中删除管理员特权的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!