博客园:https://www.cnblogs.com/ndyxb/p/12734717.html
要对一个任意进程(包括系统安全进程和服务进程)进行指定了写相关的访问权的OpenProcess操作,需要当前进程具有SeDeDebug权限。
实现原理:
获取进程的访问令牌,然后将访问令牌的权限修改为指定权限。但是系统内部并不直接识别权限名称,而是识别LUID值,所以需要根据权限名称获取对应的LUID值,之后传递给系统,实现进程访问令牌权限的修改。
实现过程:
1.获取指定进程的访问令牌(需要获取TOKEN_ADJUST_PRIVILEGES权限的令牌句柄)
2.获取本地系统指定特权名称的LUID值(LUID值相当于该特权的身份标号)
3.创建一个新的进程令牌特权结构体,并对其进行赋值(新特权的数量,特权对应的LUID值以及特权的属性状态)
4.调用 AdjustTokenPrivileges 函数对进程令牌的特权进行修改
注意点:
AdjustTokenPrivileges返回TRUE,并不代表特权设置成功,还需要使用GetLastError来判断错误码返回值。
若错误码返回值为ERROR_SUCCESS,则表示所有特权设置成功;若为ERROR_NOT_ALL_ASSIGNED,
则表示并不是所有特权都设置成功
换句话说,如果在程序中只提升了一个访问令牌特权,
且错误码为ERROR_NOT_ALL_ASSIGNED,则提升失败。如果程序运行在 Windows 7或者以上版本的操作系统,
可以尝试以管理员身份运行程序然后再测试
//************************************ // 函数名: CPrivilgeEscalationDlg::EnableDebugPrivilege // 返回类型: BOOL // 功能: 提升进程访问令牌权限 // 参数1: 需要提升权限的进程句柄 // 参数2: 特权名称 //************************************ BOOL CPrivilgeEscalationDlg::EnableDebugPrivilege(HANDLE hProcess, char* pszPrivilegesName) { HANDLE hToken = NULL; //令牌权限结构体 TOKEN_PRIVILEGES tp; //打开进程令牌并获取进程令牌句柄 BOOL bRet = OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken); if (FALSE == bRet) { MessageBox(L"打开进程令牌失败!"); return FALSE; } //获取本地系统的 pszPrivilegesName 特权的LUID值 bRet = LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid); if (FALSE == bRet) { MessageBox(L"获取LUID值失败!"); CloseHandle(hToken); hToken = INVALID_HANDLE_VALUE; return FALSE; } //设置提升权限信息 //设置新提权的数量 tp.PrivilegeCount = 1; //启用该特权 tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; //提升进程令牌访问权限 bRet = AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL); if (FALSE == bRet) { MessageBox(L"提升进程令牌访问权限失败!"); CloseHandle(hToken); hToken = INVALID_HANDLE_VALUE; return FALSE; } else { //根据错误码判断是否是特权都设置成功 DWORD dwRet = GetLastError(); if (ERROR_SUCCESS == dwRet) { CloseHandle(hToken); hToken = INVALID_HANDLE_VALUE; return TRUE; } else if (ERROR_NOT_ALL_ASSIGNED == dwRet) { MessageBox(L"提升权限失败!,请以管理员身份运行"); CloseHandle(hToken); hToken = INVALID_HANDLE_VALUE; return FALSE; } } CloseHandle(hToken); hToken = INVALID_HANDLE_VALUE; return FALSE; }