Windows - 使用 CreateProcessWithTokenW 在会话 0 中创建进程
Windows - Create a process in session 0 using CreateProcessWithTokenW
目的是从非 0 控制台会话中的进程在会话 0 中创建新进程。
我知道一些方法可以达到目的,但我想知道为什么下面描述的方法没有,尽管 msdn 说它应该有效。
unsigned FindProcessInSession(unsigned SessionId,const wchar_t*ProcessName)
{
PWTS_PROCESS_INFOW pinfo;DWORD Count,Result=0;
if(WTSEnumerateProcessesW(WTS_CURRENT_SERVER_HANDLE,0,1,&pinfo,&Count)){
for(unsigned i=0;i<Count;++i)if(pinfo[i].SessionId==SessionId&&_wcsicmp(pinfo[i].pProcessName,ProcessName)==0){
Result=pinfo[i].ProcessId;break;
}
WTSFreeMemory(pinfo);
}
return Result;
}
int main()
{
HANDLE hProcess=OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION,0,FindProcessInSession(0,L"smss.exe")),ProcessToken,NewToken;
if(hProcess&&OpenProcessToken(hProcess,TOKEN_DUPLICATE,&ProcessToken)&&DuplicateTokenEx(ProcessToken,MAXIMUM_ALLOWED,0,SecurityImpersonation,TokenImpersonation,&NewToken)){
static STARTUPINFOW si={sizeof(STARTUPINFOW)};PROCESS_INFORMATION pi;DWORD SessionId,l;
printf("GetTokenInformation %d\n",GetTokenInformation(NewToken,TokenSessionId,&SessionId,sizeof SessionId,&l));
printf("SessionId %d\n",SessionId);
printf("CreateProcessWithTokenW %d\n",CreateProcessWithTokenW(NewToken,0,L"c:\windows\system32\cmd.exe",0,0,0,0,&si,&pi));
}
}
在我的电脑上测试期间,GetTokenInformation 成功输出 SessionId=0 并且 CreateProcessWithTokenW 在 SYSTEM 用户名中创建了一个新进程,具有来自 smss.exe 的所有权限。但是新进程仍然 运行 在调用进程所在的任何会话中。
msdn on CreateProcessWithTokenW 注释
终端服务:进程在令牌中指定的会话中 运行。默认情况下,这是调用 LogonUser 的同一会话。要更改会话,请使用 SetTokenInformation 函数。
Appa运行tly 辅助登录服务CreateProcessWithTokenW 依赖不不遵循文档
CreateProcessWithTokenW
获取调用者的 SessionId 并在令牌中设置此 SessionId (作为副作用 - 令牌在 CreateProcessWithTokenW
。你可以在 CreateProcessWithTokenW
之后再次调用 GetTokenInformation
并查看现在这里已经不是 0。所以 - CreateProcessWithTokenW
不能用于另一个会话中的 运行 进程. 需要使用 CreateProcessAsUserW
。更多研究 here
目的是从非 0 控制台会话中的进程在会话 0 中创建新进程。 我知道一些方法可以达到目的,但我想知道为什么下面描述的方法没有,尽管 msdn 说它应该有效。
unsigned FindProcessInSession(unsigned SessionId,const wchar_t*ProcessName)
{
PWTS_PROCESS_INFOW pinfo;DWORD Count,Result=0;
if(WTSEnumerateProcessesW(WTS_CURRENT_SERVER_HANDLE,0,1,&pinfo,&Count)){
for(unsigned i=0;i<Count;++i)if(pinfo[i].SessionId==SessionId&&_wcsicmp(pinfo[i].pProcessName,ProcessName)==0){
Result=pinfo[i].ProcessId;break;
}
WTSFreeMemory(pinfo);
}
return Result;
}
int main()
{
HANDLE hProcess=OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION,0,FindProcessInSession(0,L"smss.exe")),ProcessToken,NewToken;
if(hProcess&&OpenProcessToken(hProcess,TOKEN_DUPLICATE,&ProcessToken)&&DuplicateTokenEx(ProcessToken,MAXIMUM_ALLOWED,0,SecurityImpersonation,TokenImpersonation,&NewToken)){
static STARTUPINFOW si={sizeof(STARTUPINFOW)};PROCESS_INFORMATION pi;DWORD SessionId,l;
printf("GetTokenInformation %d\n",GetTokenInformation(NewToken,TokenSessionId,&SessionId,sizeof SessionId,&l));
printf("SessionId %d\n",SessionId);
printf("CreateProcessWithTokenW %d\n",CreateProcessWithTokenW(NewToken,0,L"c:\windows\system32\cmd.exe",0,0,0,0,&si,&pi));
}
}
在我的电脑上测试期间,GetTokenInformation 成功输出 SessionId=0 并且 CreateProcessWithTokenW 在 SYSTEM 用户名中创建了一个新进程,具有来自 smss.exe 的所有权限。但是新进程仍然 运行 在调用进程所在的任何会话中。 msdn on CreateProcessWithTokenW 注释
终端服务:进程在令牌中指定的会话中 运行。默认情况下,这是调用 LogonUser 的同一会话。要更改会话,请使用 SetTokenInformation 函数。
Appa运行tly 辅助登录服务CreateProcessWithTokenW 依赖不不遵循文档
CreateProcessWithTokenW
获取调用者的 SessionId 并在令牌中设置此 SessionId (作为副作用 - 令牌在 CreateProcessWithTokenW
。你可以在 CreateProcessWithTokenW
之后再次调用 GetTokenInformation
并查看现在这里已经不是 0。所以 - CreateProcessWithTokenW
不能用于另一个会话中的 运行 进程. 需要使用 CreateProcessAsUserW
。更多研究 here