0

The purpose is to create a new process in session 0 from a process in non 0 console session. I know some methods that fulfill the purpose, but I want to know why the method described below does not, despite msdn says it should work.

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));
    }
}

During testing on my pc,GetTokenInformation successfully output SessionId=0 and CreateProcessWithTokenW created a new process in SYSTEM username, with all privileges from smss.exe. but the new process still ran in whatever session the calling process was in. msdn on CreateProcessWithTokenW notes

Terminal Services: The process is run in the session specified in the token. By default, this is the same session that called LogonUser. To change the session, use the SetTokenInformation function.

Apparantly the secondary logon service CreateProcessWithTokenW relies on not does not follow the documentation

elflyao
  • 367
  • 3
  • 9
  • this is because `CreateProcessWithTokenW` internal change TokenSessionId of the token. set it to caller *SessionId*. https://stackoverflow.com/questions/38427094/createprocessasuser-works-createprocesswithtokenw-does-not/38442543#38442543 – RbMm Feb 16 '21 at 14:38
  • "*create a new process in session 0 from a process in non 0 console session*" - why would you ever want to do that? What is the use-case here? Session 0 is reserved for services. If you want a process to run in session 0, it should itself be a service, or be launched by a service. – Remy Lebeau Feb 16 '21 at 17:25

1 Answers1

2

CreateProcessWithTokenW get SessionId of caller and set this SessionId in token (as side effect - token was modified after CreateProcessWithTokenW. you can call GetTokenInformation again after CreateProcessWithTokenW and view that now already not 0 here. so - CreateProcessWithTokenW can not be used for run process in another session. need use CreateProcessAsUserW. more research here

RbMm
  • 31,280
  • 3
  • 35
  • 56