作者:小 琛
欢迎转载,请标明出处
应用场景:运行的程序本身为管理员权限,此时需要启动一个新的程序,该程序需要以普通权限启动。
思路:
-
使用
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;
}