MFC-修改本进程权限为调试

发布时间 2023-05-28 15:45:27作者: 天子骄龙

 

    
    HANDLE hToken;     //存放获得的令牌
    TOKEN_PRIVILEGES tp;   //令牌权限结构体
    /*
    一个LUID_AND_ATTRIBUTES结构体. 每个结构体包括LUID和特权的属性
    typedef struct _TOKEN_PRIVILEGES
{
    ULONG PrivilegeCount; //数组元素的个数
    LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY]; //数组.类型为LUID_AND_ATTRIBUTES
} TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES;

    一个LUID_AND_ATTRIBUTES结构体. 每个结构体包括LUID和特权的属性. 特权的属性可以是下列值的组合:
        SE_PRIVILEGE_ENABLED_BY_DEFAULT    特权默认启用
        SE_PRIVILEGE_ENABLED               特权启用
        SE_PRIVILEGE_USED_FOR_ACCESS       特权被用来访问一个对象或服务



    typedef struct _LUID_AND_ATTRIBUTES {
        LUID  Luid;
         DWORD Attributes;
    } LUID_AND_ATTRIBUTES, *PLUID_AND_ATTRIBUTES;
    Luid    指定 LUID 值
    Attributes   指定 LUID 的属性。 此值最多包含 32 个一位标志。 其含义取决于 LUID 的定义和使用



    typedef struct _LUID {
     DWORD LowPart;
     LONG  HighPart;
    } LUID, *PLUID;

    */



    BOOL b = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);//获取当前进程的令牌
    /*

    参数1:HANDLE ProcessHandle   要修改访问权限的进程句柄
    参数2:DWORD DesiredAccess    进程对获得的令牌有哪些操作权限
            TOKEN_ADJUST_PRIVILEGES = 0x0020H    要修改访问令牌的特权
            TOKEN_ADJUST_GROUPS
            TOKEN_ADJUST_DEFAULT
            TOKEN_EXECUTE
            TOKEN_QUERY=0x0008H                  查询
            TOKEN_READ
            TOKEN_WRITE
            TOKEN_ALL_ACCESS
    参数3:PHANDLE TokenHandle    存放令牌的句柄的地址

    返回值:非零表示成功,零表示失败
    */

    if (!b) {
        AfxMessageBox(_T("获取进程的令牌句柄失败"));
    }

    BOOL b1 = LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);//获取本地系统的指定权限
    /*
    LUID存储在tp结构体里
    参数1:LPCTSTR lpSystemName   表示所要查看的系统,本地系统直接用NULL
    参数2:LPCTSTR lpName         指向一个以零结尾的字符串,指定权限的名称
            SE_DEBUG_NAME        调试权限,这个权限应该是进程所能具有的最大权限
            其他:https://learn.microsoft.com/zh-cn/windows/win32/secauthz/privilege-constants
    参数3:PLUID  lpLuid   指向接收 LUID 的变量的指针【LUID保存权限值】
    返回值:如果函数成功,该函数将返回非零
            如果函数失败,它将返回零

    */

    if (!b1) {
        AfxMessageBox(_T("获取系统权限的特权值失败"));
    }


    //下面开始激活当前令牌的调试权限,调试权限一般是不开通的,因为权限太大了
    //一定要用完了就关掉
    tp.PrivilegeCount = 1;  //只启动调试权限,所以权限的个数是一个
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;  //属性设置
    /*
    当Attributes = SE_PRIVILEGE_ENABLE   时,激活权限
    当Attributes = 0      时,关闭权限
    权限是LookupPrivilegeValue函数获得的
    */

    BOOL b2 = AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);//修改访问令牌的权限
    /*
    【必须以管理员身份运行程序】
    参数1:HANDLE TokenHandle   包含特权的令牌句柄
    参数2:BOOL     是否禁用所有令牌的权限
            FALSE   则不禁用,以NewState参数指针的信息为基础来修改特权
            TRUE    禁用所有特权,NewState参数无效
    参数3:PTOKEN_PRIVILEGES NewState   新特权信息的指针(结构体)【令牌指针】
    参数4:DWORD BufferLength   缓冲数据大小,以字节为单位 【令牌占用字节数】
    参数5:PTOKEN_PRIVILEGES PreviousState  接收被改变特权当前状态的Buffer
    参数6:PDWORD ReturnLength   接收PreviousState缓存区要求的大小
                如果PreviousState为NULL,这个参数可以为NULL
    返回值:如果这个函数成功,返回非0.为了确定这个函数是否修改了所有指定的特权,
        可以调用GetLastError函数,当这个函数返回下面的值之一时就代表函数成功:
        ERROR_SUCCESS              这个函数修改了所有指定的特权。
        ERROR_NOT_ALL_ASSIGNED     这个令牌没有参数NewState里指定一个或多个的权限。(一个或多个没有修改成功)
        如果这个函数失败,返回0
    */

    DWORD d = GetLastError();

    if (d != ERROR_SUCCESS) {
        AfxMessageBox(_T("权限修改失败"));
    }

    if (d == ERROR_SUCCESS) {
        AfxMessageBox(_T("权限修改成功"));
    }


    CloseHandle(hToken);

 

【本进程必须以管理员身份启动,否则修改进程权限失败】