【Windows】服务中以管理员\普通权限启动进程

概述:windows 服务中以管理员或普通权限启动进程

0x01 管理员权限启动进程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// 管理员权限启动进程
#ifdef UNICODE
MMSYSSHARED_EXPORT bool CreateProcessWithAdmin(const std::wstring& exe, const std::wstring& param, bool show)
#else
MMSYSSHARED_EXPORT bool CreateProcessWithAdmin(const std::string& exe, const std::string& param, bool show)
#endif // UNICODE
{
HANDLE hToken{ NULL };
HANDLE hTokenDup{ NULL };
LPVOID pEnvironment{ NULL };
bool res{ false };
#ifdef UNICODE
wchar_t* cmd = (wchar_t*)param.c_str();
#else
char* cmd = (wchar_t*)param.c_str();
#endif

do
{
if (exe.empty())
{
LOG_ERROR("exe is null!");
break;
}

if (!GetTokenWithProcessName(L"explorer.exe", hToken))
{
LOG_ERROR("GetTokenWithProcessName Error: %u", GetLastError());
break;
}
// 复制令牌,把调用方有效的所有访问权限给复制后的令牌.
if (!DuplicateTokenEx(hToken, MAXIMUM_ALLOWED/*TOKEN_ALL_ACCESS*/, NULL/*&sa*/, SecurityImpersonation, TokenPrimary, &hTokenDup))
{
LOG_ERROR("DuplicateTokenEx Error: %u", GetLastError());
break;
}
STARTUPINFO si;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
#ifdef UNICODE
wchar_t desk[]{ TEXT("WinSta0\\Default") };
#else
char desk[]{ TEXT("WinSta0\\Default") };
#endif
si.lpDesktop = desk;
if (show)
{
si.wShowWindow = SW_SHOW;
}
else
{
si.wShowWindow = SW_HIDE;
}
si.dwFlags = STARTF_USESHOWWINDOW;
PROCESS_INFORMATION pi;
// 检索指定用户的环境变量。然后,可以将此块传递给 CreateProcessAsUser 函数。
if (!CreateEnvironmentBlock(&pEnvironment, hTokenDup, FALSE))
{
LOG_ERROR("CreateEnvironmentBlock Error: %u", GetLastError());
break;
}
// 缺少环境变量时某些依赖环境变量的程序打不开,或者运行不正常。
if (!CreateProcessAsUser(hTokenDup, exe.c_str(), cmd, NULL, NULL, FALSE
, NORMAL_PRIORITY_CLASS
/*| CREATE_NEW_CONSOLE */
| CREATE_UNICODE_ENVIRONMENT
, pEnvironment, NULL, &si, &pi))
{
LOG_ERROR("CreateProcessAsUser Error: %u", GetLastError());
break;
}
res = true;
} while (0);
// 清理
if (cmd)
{
delete[]cmd;
}
if (pEnvironment)
{
DestroyEnvironmentBlock(pEnvironment);
}
if(hToken)
CloseHandle(hToken);
if (hTokenDup)
CloseHandle(hTokenDup);
return res;
}

0x02 普通用户权限启动进程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
// 普通用户权限启动进程
#ifdef UNICODE
bool CreateProcessWithUser(const std::wstring& exePath, const std::wstring& param, bool show)
#else
bool CreateProcessWithUser(const std::string& exePath, const std::string& param, bool show)
#endif // UNICODE
{
HANDLE hToken = 0;
HANDLE hNewToken = 0;
LPVOID pEnvironment{ NULL };
bool res{ false };
int l = param.length();
#ifdef UNICODE
wchar_t* cmd = new wchar_t[l + 1];
memcpy(cmd, param.c_str(), l * sizeof(wchar_t));
cmd[l] = 0;
#else
char* cmd = new char[l + 1];
memcpy(cmd, param.c_str(), l * sizeof(char));
cmd[l] = 0;
#endif // UNICODE

do
{
if (!GetTokenWithProcessName(L"explorer.exe", hToken))
{
LOG_ERROR("GetTokenWithProcessName Error: %u", GetLastError());
break;
}
if (!DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, NULL/*&sa*/, SECURITY_MAX_IMPERSONATION_LEVEL, TokenPrimary, &hNewToken))
{
LOG_ERROR("DuplicateTokenEx Error: %u", GetLastError());
break;
}
DWORD dwCreationFlag = NORMAL_PRIORITY_CLASS /*| CREATE_NEW_CONSOLE*/ | CREATE_UNICODE_ENVIRONMENT;
// 检索指定用户的环境变量。然后,可以将此块传递给 CreateProcessAsUser 函数。
if (!CreateEnvironmentBlock(&pEnvironment, hNewToken, FALSE))
{
LOG_ERROR("CreateEnvironmentBlock Error: %u", GetLastError());
break;
}
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
#ifdef UNICODE
wchar_t desktop[] = L"winsta0\\default";
#else
char desktop[] = "winsta0\\default";
#endif
si.lpDesktop = desktop;
si.dwFlags = STARTF_USESHOWWINDOW;
if (show)
{
si.wShowWindow = SW_SHOW;
}
else
{
si.wShowWindow = SW_HIDE;
}
if (!CreateProcessAsUser(hNewToken, exePath.c_str(), cmd, 0, 0, FALSE, dwCreationFlag, pEnvironment, 0, &si, &pi))
{
#ifdef UNICODE
std::string ansicmd = mm::Charset::UnicodeToANSI(cmd);
std::string ansibat = mm::Charset::UnicodeToANSI(exePath.c_str());
LOG_ERROR("CreateProcessAsUser error! LastError=%ld, %s, %s", GetLastError(), ansibat.c_str(), ansicmd.c_str());
#else
LOG_ERROR("CreateProcessAsUser error! LastError=%ld, %s, %s", GetLastError(), exePath.c_str(), cmd.c_str());
#endif // UNICODE
break;
}
res = true;
} while (0);
// 清理
delete[] cmd;
if (hToken)
{
CloseHandle(hToken);
}
if (hNewToken)
{
CloseHandle(hNewToken);
}
if (pEnvironment)
{
DestroyEnvironmentBlock(pEnvironment);
}
return res;
}

0x03 根据进程名获取进程句柄

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#ifdef UNICODE
bool GetTokenWithProcessName(const wchar_t* szName, HANDLE& hToken)
#else
bool GetTokenWithProcessName(const char* szName, HANDLE& hToken)
#endif // _DEBUG
{
// HANDLE hToken{ NULL };
HANDLE hProcessSnap{ NULL };
PROCESSENTRY32 pe32{ NULL };
HANDLE hProcess{ NULL };
bool res{ false };
do
{
// 多用户模式时任务管理器里可能出现多个explorer
// 需要先获取当前会话ID,再通过枚举进程,通过比较sessionID进而得到token。
//DWORD dwSessionId = WTSGetActiveConsoleSessionId();
//PWTS_PROCESS_INFO ppi = NULL;
//DWORD dwProcessCount = 0;
//if (WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, 0, 1, &ppi, &dwProcessCount))
//{
// for (int i = 0; i < dwProcessCount; i++)
// {
// if (_wcsicmp(ppi[i].pProcessName, L"explorer.exe") == 0)
// {
// if (ppi[i].SessionId == dwSessionId)
// {
// break;
// }
// }
// }
// WTSFreeMemory(ppi);
//}
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (!hProcessSnap)
{
LOG_ERROR("CreateToolhelp32Snapshot error! %d", GetLastError());
break;
}
pe32.dwSize = sizeof(PROCESSENTRY32);
for (Process32First(hProcessSnap, &pe32); Process32Next(hProcessSnap, &pe32);)
{
#ifdef UNICODE
if (_wcsicmp((pe32.szExeFile), szName))
#else
if (_stricmp((pe32.szExeFile), szName))
#endif // _DEBUG
continue;
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pe32.th32ProcessID);
if (!hProcess)
{
LOG_ERROR("OpenProcess error! %d", GetLastError());
break;
}
BOOL ret = OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &hToken);
if(!ret)
{
LOG_ERROR("OpenProcess error! %d", GetLastError());
break;
}
res = true;
break;
}
} while (0);

if (hProcessSnap)
{
CloseHandle(hProcessSnap);
}
if (hProcess)
{
CloseHandle(hProcess);
}
return res;
}

【Windows】服务中以管理员\普通权限启动进程
https://hodlyounger.github.io/A_OS/Windows/权限与会话/【权限与会话】 Service降权启动进程/
作者
mingming
发布于
2023年10月27日
许可协议