作者:小 琛
欢迎转载,请标明出处
应用场景:运行的程序本身为管理员权限,此时需要启动一个新的程序,该程序需要以普通权限启动。
思路:
-
使用
CreateProcessAsUser
或CreateProcessWithLogonW
等函数创建一个新的进程。这些函数可以指定一个不同权限的用户账户来启动进程,从而实现进程的降权启动。注意,这些函数需要当前程序拥有 SeAssignPrimaryTokenPrivilege 权限,可以通过调用AdjustTokenPrivileges
函数获取该权限。 -
获取新进程的安全标识符(SID),并使用
SetTokenInformation
函数将新进程的安全性设置为普通权限。具体来说,可以使用以下步骤实现:- 通过
OpenProcessToken
函数获取当前进程的令牌句柄; - 使用
GetTokenInformation
函数获取当前进程令牌的安全标识符; - 使用
DuplicateTokenEx
函数创建一个新的安全令牌; - 使用
SetTokenInformation
函数将新令牌的安全级别设置为普通权限。
- 通过
-
使用新令牌启动进程。在
CreateProcessAsUser
或CreateProcessWithLogonW
函数中指定新令牌即可。
BOOL CreateProcessAsUser(std::wstring command_line)
{LOG_INFO << "_CreateProcessAsUser command_line:" << command_line;BOOL ret = FALSE;DWORD u_ExplorerPID;HANDLE hTokenUser = 0;HANDLE h_Token = 0;HANDLE h_Process = 0;STARTUPINFO si;PROCESS_INFORMATION pi;ZeroMemory(&si, sizeof(STARTUPINFO));ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));si.dwFlags = STARTF_USESHOWWINDOW;si.wShowWindow = SW_SHOWNORMAL;HWND h_Progman = GetShellWindow();GetWindowThreadProcessId(h_Progman, &u_ExplorerPID);h_Process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, u_ExplorerPID);OpenProcessToken(h_Process, TOKEN_DUPLICATE, &h_Token);DuplicateTokenEx(h_Token, TOKEN_ALL_ACCESS, 0, SecurityImpersonation, TokenPrimary, &hTokenUser);ret = CreateProcessWithTokenW(hTokenUser, NULL, NULL, (WCHAR*)command_line.c_str(), NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);if (h_Token) {CloseHandle(h_Token);}if (hTokenUser) {CloseHandle(hTokenUser);}if (h_Process) {CloseHandle(h_Process);}if (!ret) {LOG_INFO << "_CreateProcessAsUser GetLastError:" << GetLastError();}return ret;
}