[英]Running Process in system context
Is it possible to launch process in system context from a parent process thats running under administrator account with elevation(say a command prompt).是否可以从在具有提升权限的管理员帐户下运行的父进程在系统上下文中启动进程(比如命令提示符)。 The problem is similar to what psexec does but more of how it actually implements this.
这个问题类似于 psexec 所做的,但更多的是它如何实际实现它。
I was thinking opening the crss.exe/winlogon.exe process duplicating the token and launching a new process using that process token.我正在考虑打开 crss.exe/winlogon.exe 进程复制令牌并使用该进程令牌启动新进程。 But I fail to even open the process handle (Getlasterror return 5).
但我什至无法打开进程句柄(Getlasterror 返回 5)。 Can someone let me know if this is the right approach or the process should be launched differently?
有人可以告诉我这是正确的方法还是应该以不同的方式启动流程?
HANDLE hWinLogonProcess;
for(const auto& ps : running_processes)
{
if(ps.id == GetCurrentProcessId() ||
0 != ps.short_name.CompareNoCase(L"winlogon.exe"))
{
continue;
}
DWORD dwWinLogonSessionId(0);
if(FALSE == ProcessIdToSessionId(GetCurrentProcessId(), &dwWinLogonSessionId))
{
std::wcerr<<"Could not get Winlogon process session id"<<std::endl;
continue;
}
if(dwWinLogonSessionId != dwCurSessionId)
{
continue;
}
hWinLogonProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, ps.id);
if(FALSE == hWinLogonProcess)
{
std::wcerr<<"Failed to get winlogon process handle"<<std::endl;
return;
}
else
{
std::wcout<<"Able to open process "<<ps.short_name.GetString()<<" handle"<<std::endl;
break;
}
}
I am sure its possible as there is a working tool (psexec) but I couldnt find any reference online to do this.我确信这是可能的,因为有一个可用的工具 (psexec),但我无法在网上找到任何参考资料来执行此操作。
Also this is similar to question , but posting separately as there was details on how it had to be achieved.这也类似于问题,但单独发布,因为有关于如何实现它的详细信息。
Yes, this is possible (without any service help). 是的,这是可能的(没有任何服务帮助)。
But I fail to even open the process handle
但是我什至没有打开流程句柄
Does your process have the SE_DEBUG_PRIVILEGE
privilege enabled? 您的进程是否启用了
SE_DEBUG_PRIVILEGE
特权?
With this privilege, you can open a system process with all access if it is not protected (smss.exe, csrss.exe, services.exe), and use that handle in CreateProcessAsUser
(), or with UpdateProcThreadAttribute(PROC_THREAD_ATTRIBUTE_PARENT_PROCESS)
if you also have SE_ASSIGNPRIMARYTOKEN_PRIVILEGE
and SE_TCB_PRIVILEGE
privileges enabled (for setting the token's SessionId
to 0), which you can get in 2 ways: 拥有此特权,如果未受保护(smss.exe,csrss.exe,services.exe),则可以打开具有所有访问权限的系统进程,并在
CreateProcessAsUser
()中使用该句柄,或者在还具有UpdateProcThreadAttribute(PROC_THREAD_ATTRIBUTE_PARENT_PROCESS)
情况下使用启用了SE_ASSIGNPRIMARYTOKEN_PRIVILEGE
和SE_TCB_PRIVILEGE
特权(用于将令牌的SessionId
设置为0),您可以通过两种方式获得特权:
open a thread from an unprotected system process and impersonate it, then open your own thread token and adjust privileges on it. 从不受保护的系统进程中打开线程并进行模拟,然后打开自己的线程令牌并调整其特权。
open a token from any system process (this works even for protected processes), duplicate the token, adjust privileges on it, and then impersonate with this token. 从任何系统进程中打开一个令牌(即使对于受保护的进程也是如此),复制该令牌,调整其特权,然后使用该令牌进行模拟。
To "launch a process in the system context", if you want to run the process: 如果要运行进程,请“在系统上下文中启动进程”:
with the LocalSystem token. 使用LocalSystem令牌。
in the System terminal session (0) 在系统终端会话中(0)
Both, as I say, are possible. 正如我所说,两者都是可能的。 And all you need is
SE_DEBUG_PRIVILEGE
. 您只需要
SE_DEBUG_PRIVILEGE
。
more simply - open some system process with PROCESS_CREATE_PROCESS
access right. 更简单-使用
PROCESS_CREATE_PROCESS
访问权限打开某些系统进程。 Use this handle with UpdateProcThreadAttribute(PROC_THREAD_ATTRIBUTE_PARENT_PROCESS)
. 将此句柄与
UpdateProcThreadAttribute(PROC_THREAD_ATTRIBUTE_PARENT_PROCESS)
。 As a result, your started process inherits a token from the system process. 结果,您启动的进程从系统进程继承了一个令牌。 This will be not work on XP, but there it is possible to hook
NtCreateProcess/Ex()
to replace HANDLE ParentProcess
with your opened handle. 这在XP上将不起作用,但是可以钩住
NtCreateProcess/Ex()
以用打开的句柄替换HANDLE ParentProcess
。
Another way is to use CreateProcessAsUser()
. 另一种方法是使用
CreateProcessAsUser()
。 Before creating the process, you will be need SE_ASSIGNPRIMARYTOKEN_PRIVILEGE
and SE_TCB_PRIVILEGE
privileges to set the token's TokenSessionId
(if you want to run in session 0). 在创建流程之前,您将需要
SE_ASSIGNPRIMARYTOKEN_PRIVILEGE
和SE_TCB_PRIVILEGE
特权来设置令牌的TokenSessionId
(如果要在会话0中运行)。
Thanks to RbMm answer I figured a way to accomplish this task.感谢 RbMm 的回答,我想出了一种方法来完成这项任务。
For any of you who did not succeed, I leave below something that might help:对于任何没有成功的人,我在下面留下一些可能有帮助的东西:
//First we need to add debug privilege to this process
HANDLE hToken;
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hToken))
{
std::cout << "OpenProcessToken failed: " << GetLastError();
return 0;
}
TOKEN_PRIVILEGES tk;
tk.PrivilegeCount = 1;
tk.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if(!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tk.Privileges[0].Luid))
{
std::cout << "LookupPrivilegeValue failed: " << GetLastError();
return 0;
}
AdjustTokenPrivileges(hToken, FALSE, &tk, 0, NULL, 0);
if((DWORD res = GetLastError()) != ERROR_SUCCESS)
{
std::cout << "AdjustTokenPrivileges failed: " << res;
}
CloseHandle(hToken);
//Now we need a handle to a process that already runs as SYSTEM.
//You can choose any process that is not protected (if OpenProcess fails try with other process)
//pid of chosen process (you can get this by opening task manager and go to
//Details tab or by enumerating all processes and extract that one you need)
DWORD pid;
HANDLE hProcess = OpenProcess(PROCESS_CREATE_PROCESS, FALSE, pid);
if (!hProcess)
{
std::cout << "OpenProcess with pid " << pid << "failed: " << GetLastError();
return 0
}
//We need to initialize a list that contains PROC_THREAD_ATTRIBUTE_PARENT_PROCESS
//to specify that parent process of the process we are going to start is the
//process we opened earlier (this will make the child process inherit the system context).
//This list will be specified in a STARTUPINFOEX object that CreateProcess will get
STARTUPINFOEX siex = { sizeof(STARTUPINFOEX) };
siex.StartupInfo.cb = sizeof(STARTUPINFOEXW);
//We need to initialize our list. To do this we call InitializeProcThreadAttributeList
//with a NULL list to get how big our list needs to be to store all attributes
//we want to specify, then we allocate our list with the size we got from first call
//and we call again the function to initialize the list.
SIZE_T cbAttributeListSize = 0;
if(!InitializeProcThreadAttributeList(NULL, 1, 0, &cbAttributeListSize))
{
std::cout << "InitializeProcThreadAttributeList failed: " << GetLastError();
return 0
}
siex.lpAttributeList = reinterpret_cast<PPROC_THREAD_ATTRIBUTE_LIST>(HeapAlloc(GetProcessHeap(), 0, cbAttributeListSize));
if(!InitializeProcThreadAttributeList(siex.lpAttributeList, 1, 0, &cbAttributeListSize))
{
std::cout << "InitializeProcThreadAttributeList failed: " << GetLastError();
return 0
}
if(!UpdateProcThreadAttribute(siex.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &hProcess, sizeof(hProcess), NULL, NULL))
{
std::cout << "UpdateProcThreadAttribute failed: " << GetLastError();
return 0
}
//path to program we want to run in system context
LPWSTR szCmdline = _wcsdup(TEXT("C:\\Windows\\System32\\notepad.exe"));
PROCESS_INFORMATION pi = { 0 };
if(!CreateProcess(NULL, szCmdline, nullptr, nullptr, FALSE, EXTENDED_STARTUPINFO_PRESENT, NULL, NULL, reinterpret_cast<LPSTARTUPINFOW>(&siex), &pi))
{
std::cout << "CreateProcess failed: " << GetLastError();
return 0
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.