从进程中删除管理员权限 [英] Removing Administrator Privilages from Process

查看:40
本文介绍了从进程中删除管理员权限的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在这篇很棒的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.

顺便说一句,有一个更简单的 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆