Exemplo n.º 1
30
// create the child process with command line "-runas session -parent [parent process id]"
// the child process will run in the specified session
HANDLE CWinRobotService::CreateChildProcess(ULONG sid)
{
	TrackDebugOut;

	WCHAR szComd[MAX_PATH*2];
	WCHAR curpath[MAX_PATH];
	GetModuleFileNameW( 0, curpath, MAX_PATH );
	PathRemoveFileSpec(curpath);
	DWORD dwProcessId = 0;
	HANDLE hNewToken = NULL;
	HRESULT hr = S_OK;
	HWINSTA  hwinsta = NULL;
	HANDLE hToken= NULL;
	void* pEnvBlock = NULL;
	PROCESS_INFORMATION pi;
	ZeroMemory(&pi,sizeof(pi));
	DWORD errcode=0;

	try
	{
		DebugOutF(filelog::log_info,"attempt to CreateChildProcess %d",sid);
// 		HANDLE hCurProcess = 0;
// 
// 		DuplicateHandle(GetCurrentProcess(),GetCurrentProcess(), GetCurrentProcess(), &hCurProcess, 
// 			0, TRUE, DUPLICATE_SAME_ACCESS);
#ifdef _WIN64
		swprintf(szComd,L"\"%s\\WinRobotHostx64.exe\" -runas session -parent %d",curpath,GetProcessId(GetCurrentProcess()));
#else
		swprintf(szComd,L"\"%s\\WinRobotHostx86.exe\" -runas session -parent %d",curpath,GetProcessId(GetCurrentProcess()));
#endif
		STARTUPINFOW si;
		ZeroMemory(&si, sizeof(STARTUPINFOW));
		si.cb= sizeof(STARTUPINFOW);

		DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS;

		si.lpDesktop = L"winsta0\\default";;

		INT  *pState = NULL;
		DWORD buflen = 0;
		ConnectActiveSession();

		if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hToken)){
			DebugOutF(filelog::log_error,"OpenProcessToken failed , error code = %d",GetLastError());
			throw E_UNEXPECTED;
		}
		// Duplicate the token because we need modify it
		if(!DuplicateTokenEx(hToken,MAXIMUM_ALLOWED,0,SecurityAnonymous ,TokenPrimary ,&hNewToken)){
			errcode = GetLastError();
			DebugOutF(filelog::log_error,"DuplicateTokenEx failed , error code = %d",GetLastError());
			throw HRESULT_FROM_WIN32(errcode);
		}
		// change the token so that the process will be create in the new session
		if(!SetTokenInformation(hNewToken,TokenSessionId,&sid,sizeof(DWORD)))
		{
			errcode = GetLastError();
			DebugOutF(filelog::log_error,"SetTokenInformation failed , error code = %d",GetLastError());
			throw HRESULT_FROM_WIN32(errcode);
		}
 		if(!CreateEnvironmentBlock( &pEnvBlock, hToken, TRUE)){
 			DebugOutF(filelog::log_error,"CreateEnvironmentBlock Failed, error code = %d",GetLastError());
 		}else{
 			dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
 		}
		BOOL bCreate = FALSE;
		for(int i=0;i<5;i++)
		{
			if(!(bCreate = CreateProcessAsUserW(hNewToken,
				0,szComd,0,0,FALSE,dwCreationFlags ,pEnvBlock,curpath,&si,&pi )))
			{
				if(GetLastError() == 233){
					// change the token so that the process will be create in the new session
					sid = 0;
					if(!SetTokenInformation(hNewToken,TokenSessionId,&sid,sizeof(DWORD)))
					{
						errcode = GetLastError();
						DebugOutF(filelog::log_error,"SetTokenInformation failed , error code = %d",GetLastError());
						throw HRESULT_FROM_WIN32(errcode);
					}
					continue;
				}
				Sleep(300);
				continue;
			}
			else
			{
				break;
			}
		}
		if(bCreate)
		{
			DebugOutF(filelog::log_info,"CreateChildProcess on session %d ok",sid);
		}
		else
		{
			DebugOutF(filelog::log_error,"CreateProcessAsUser on session %d %s,%s,failed error code = %d"
				,sid,(char*)CW2A(szComd),(char*)CW2A(curpath),GetLastError());
		}
	}
	catch (HRESULT hr1)
	{
		hr = hr1;
	}

	if(hToken) CloseHandle(hToken);
	if(hNewToken)CloseHandle(hNewToken);
	if(pi.hThread){CloseHandle(pi.hThread);pi.hThread = 0;}
	if(pEnvBlock)DestroyEnvironmentBlock(pEnvBlock);
	return pi.hProcess;
}
Exemplo n.º 2
0
Arquivo: win.c Projeto: 0xe/win-sshd
/*
  Execute a command as a "user". The command is run as cmd.exe /c <command>
  The command is executed from the user's HOME (as determined by the user profile)
  Input, Output & Err streams are redirected. 
*/
void *win_execute_command(wchar_t *shell, wchar_t *command, wchar_t *user, wchar_t *password, wchar_t *domain, wchar_t *root, int pty_mode) {
    SECURITY_ATTRIBUTES sa;
    STARTUPINFOW si;
    HANDLE out_rd_tmp, in_wr_tmp, out_wr, in_rd, in_wr, err_wr;
    exec_ctx *ctx;
    HANDLE ttok, ntok;
	int ret;

    ZeroMemory(&sa, sizeof(sa));
    sa.nLength = sizeof(sa);
    sa.bInheritHandle = TRUE;

    ctx = malloc(sizeof(*ctx));
    ZeroMemory(ctx, sizeof(*ctx));
    ctx->pty_mode = pty_mode;
 
    /* setup the parent child plumbing */
    if (!CreatePipe(&in_rd, &in_wr_tmp, &sa, 0)) {
        printf("Couldn't set up in pipe to child %s", get_error_msg(GetLastError()));
        free(ctx);
        return NULL;
    }

    if (!CreatePipe(&out_rd_tmp, &out_wr, &sa, 0)) {
        printf("Couldn't set up stdout pipe to child %s", get_error_msg(GetLastError()));
		free(ctx);
        return NULL;
    }

    if (!DuplicateHandle(GetCurrentProcess(), out_wr, GetCurrentProcess(), &err_wr, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
		printf("Couldn't set up stderr pipe to child %s", get_error_msg(GetLastError()));
		free(ctx);
		return NULL;
    }

    if (!DuplicateHandle(GetCurrentProcess(), out_rd_tmp, GetCurrentProcess(), &ctx->out_rd, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
		return NULL;
    }
    if (!DuplicateHandle(GetCurrentProcess(), in_wr_tmp, GetCurrentProcess(), &in_wr, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
		return NULL;
    }
    CloseHandle(out_rd_tmp);
    CloseHandle(in_wr_tmp);

    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    si.wShowWindow = SW_HIDE;
    si.hStdInput = in_rd;
    si.hStdOutput = out_wr; 
    si.hStdError = err_wr;
/*
    if (!CreateProcessWithLogonW(user, domain, password, LOGON_WITH_PROFILE, shell, command, 0, NULL, root, &si, &ctx->pi)) {
	*/
	ret = LogonUserW(user, domain, password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &ttok);
	if (!ret) {
		CloseHandle(ttok);
		INFO(GetLastError(), "Login failed for user");
		return NULL;
	}
	ret = DuplicateTokenEx(ttok, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenPrimary, &ntok);
	if (!ret) {
		CloseHandle(ttok);
		INFO(GetLastError(), "Can't impersonate user");
		return NULL;
	}
	CloseHandle(ttok);
	if (!CreateProcessAsUserW(ntok, shell, command, NULL, NULL, TRUE, 0, NULL, root, &si, &ctx->pi)) {
		int ecode = GetLastError();
		INFO(GetLastError(), "CreateProcess failed");
        free(ctx);
		CloseHandle(ntok);
        return NULL;
    }
	CloseHandle(ntok);
    CloseHandle(out_wr);
    CloseHandle(err_wr);
    CloseHandle(in_rd);
    return ctx;
}
Exemplo n.º 3
0
/**
 * Launch the post update application as the specified user (helper.exe).
 * It takes in the path of the callback application to calculate the path
 * of helper.exe.  For service updates this is called from both the system
 * account and the current user account.
 *
 * @param  installationDir The path to the callback application binary.
 * @param  updateInfoDir   The directory where update info is stored.
 * @param  forceSync       If true even if the ini file specifies async, the
 *                         process will wait for termination of PostUpdate.
 * @param  userToken       The user token to run as, if NULL the current user
 *                         will be used.
 * @return TRUE if there was no error starting the process.
 */
BOOL
LaunchWinPostProcess(const WCHAR *installationDir,
                     const WCHAR *updateInfoDir,
                     bool forceSync,
                     HANDLE userToken)
{
  WCHAR workingDirectory[MAX_PATH + 1];
  wcscpy(workingDirectory, installationDir);

  // Launch helper.exe to perform post processing (e.g. registry and log file
  // modifications) for the update.
  WCHAR inifile[MAX_PATH + 1];
  wcscpy(inifile, installationDir);
  if (!PathAppendSafe(inifile, L"updater.ini")) {
    return FALSE;
  }

  WCHAR exefile[MAX_PATH + 1];
  WCHAR exearg[MAX_PATH + 1];
  WCHAR exeasync[10];
  bool async = true;
  if (!GetPrivateProfileStringW(L"PostUpdateWin", L"ExeRelPath", NULL, exefile,
                                MAX_PATH + 1, inifile)) {
    return FALSE;
  }

  if (!GetPrivateProfileStringW(L"PostUpdateWin", L"ExeArg", NULL, exearg,
                                MAX_PATH + 1, inifile)) {
    return FALSE;
  }

  if (!GetPrivateProfileStringW(L"PostUpdateWin", L"ExeAsync", L"TRUE", 
                                exeasync,
                                sizeof(exeasync)/sizeof(exeasync[0]), 
                                inifile)) {
    return FALSE;
  }

  WCHAR exefullpath[MAX_PATH + 1];
  wcscpy(exefullpath, installationDir);
  if (!PathAppendSafe(exefullpath, exefile)) {
    return false;
  }

  WCHAR dlogFile[MAX_PATH + 1];
  if (!PathGetSiblingFilePath(dlogFile, exefullpath, L"uninstall.update")) {
    return FALSE;
  }

  WCHAR slogFile[MAX_PATH + 1];
  wcscpy(slogFile, updateInfoDir);
  if (!PathAppendSafe(slogFile, L"update.log")) {
    return FALSE;
  }

  WCHAR dummyArg[14];
  wcscpy(dummyArg, L"argv0ignored ");

  size_t len = wcslen(exearg) + wcslen(dummyArg);
  WCHAR *cmdline = (WCHAR *) malloc((len + 1) * sizeof(WCHAR));
  if (!cmdline) {
    return FALSE;
  }

  wcscpy(cmdline, dummyArg);
  wcscat(cmdline, exearg);

  if (forceSync ||
      !_wcsnicmp(exeasync, L"false", 6) || 
      !_wcsnicmp(exeasync, L"0", 2)) {
    async = false;
  }
  
  // We want to launch the post update helper app to update the Windows
  // registry even if there is a failure with removing the uninstall.update
  // file or copying the update.log file.
  CopyFileW(slogFile, dlogFile, false);

  STARTUPINFOW si = {sizeof(si), 0};
  si.lpDesktop = L"";
  PROCESS_INFORMATION pi = {0};

  bool ok;
  if (userToken) {
    ok = CreateProcessAsUserW(userToken,
                              exefullpath,
                              cmdline,
                              NULL,  // no special security attributes
                              NULL,  // no special thread attributes
                              false, // don't inherit filehandles
                              0,     // No special process creation flags
                              NULL,  // inherit my environment
                              workingDirectory,
                              &si,
                              &pi);
  } else {
    ok = CreateProcessW(exefullpath,
                        cmdline,
                        NULL,  // no special security attributes
                        NULL,  // no special thread attributes
                        false, // don't inherit filehandles
                        0,     // No special process creation flags
                        NULL,  // inherit my environment
                        workingDirectory,
                        &si,
                        &pi);
  }
  free(cmdline);
  if (ok) {
    if (!async)
      WaitForSingleObject(pi.hProcess, INFINITE);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
  }
  return ok;
}
int _tmain(int argc, _TCHAR* argv[])
{
    bool parentprocess = false;
    DWORD createflags = 0;
    WCHAR* cmdline = nullptr;
    int pid = 0;
    int illevel = -1;

    if (!ParseArgs(argc, argv, &pid, &parentprocess, &createflags, &cmdline, &illevel))
    {
        printf("NewProcessFromToken: [options] pid cmdline\n");
        printf("Options:\n");
        printf("-p : Use parent process technique to create the new process\n");
        printf("-j : Try and break away from the current process job\n");
        printf("-c : Create a new console for the process\n");
        printf("-il level: Set the process IL level\n");
        printf("* level:\n");
        printf("  u - Untrusted\n");
        printf("  l - Low\n");
        printf("  m - Medium\n");
        printf("  h - High\n");
        printf("  s - System\n");
        printf("  0xXXXX - Arbitrary IL\n");
    }
    else
    {
        if (pid == 0)
        {
            pid = GetCurrentProcessId();
        }

        EnableDebugPrivilege();
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,
                                      FALSE, pid);
        if (hProcess)
        {
            if (!parentprocess)
            {
                HANDLE hToken;

                if (OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &hToken))
                {
                    HANDLE hDupToken;

                    if (DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, nullptr, SecurityImpersonation, TokenPrimary, &hDupToken))
                    {
                        if (illevel >= 0)
                        {
                            SetTokenIL(hDupToken, illevel);
                        }

                        STARTUPINFO startInfo = { 0 };
                        PROCESS_INFORMATION procInfo = { 0 };

                        startInfo.cb = sizeof(startInfo);

                        if (CreateProcessAsUserW(hDupToken, nullptr, cmdline, nullptr, nullptr, FALSE, createflags, nullptr, nullptr, &startInfo, &procInfo))
                        {
                            printf("Created process %d\n", procInfo.dwProcessId);
                        }
                        else
                        {
                            printf("Error CreateProcessAsUser: %ls\n", GetErrorMessage().c_str());
                            if (CreateProcessWithTokenW(hDupToken, 0, nullptr, cmdline, createflags, nullptr, nullptr, &startInfo, &procInfo))
                            {
                                printf("Created process %d\n", procInfo.dwProcessId);
                            }
                            else
                            {
                                printf("Error CreateProcessWithToken: %ls\n", GetErrorMessage().c_str());
                            }
                        }
                    }
                    else
                    {
                        printf("Error Duplicating Token: %ls\n", GetErrorMessage().c_str());
                    }
                }
                else
                {
                    printf("Error OpenProcessToken: %ls\n", GetErrorMessage().c_str());
                }
            }
            else
            {
                SIZE_T size = 0;

                InitializeProcThreadAttributeList(nullptr, 1, 0, &size);

                std::vector<BYTE> attrlist(size);
                LPPROC_THREAD_ATTRIBUTE_LIST pattrlist = (LPPROC_THREAD_ATTRIBUTE_LIST)&attrlist[0];

                InitializeProcThreadAttributeList(pattrlist, 1, 0, &size);

                if (UpdateProcThreadAttribute(pattrlist, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &hProcess, sizeof(hProcess), nullptr, nullptr))
                {
                    STARTUPINFOEX startInfo = { 0 };
                    PROCESS_INFORMATION procInfo = { 0 };

                    startInfo.StartupInfo.cb = sizeof(startInfo);
                    startInfo.lpAttributeList = pattrlist;

                    if (CreateProcess(nullptr, cmdline, nullptr, nullptr, FALSE, CREATE_SUSPENDED | EXTENDED_STARTUPINFO_PRESENT | createflags,
                                      nullptr, nullptr, &startInfo.StartupInfo, &procInfo))
                    {
                        printf("Created process %d\n", procInfo.dwProcessId);
                        if (illevel >= 0)
                        {
                            HANDLE hToken;

                            if (OpenProcessToken(procInfo.hProcess, TOKEN_ALL_ACCESS, &hToken))
                            {
                                SetTokenIL(hToken, illevel);
                            }
                        }

                        ResumeThread(procInfo.hThread);
                    }
                    else
                    {
                        printf("Error: CreateProcess %ls\n", GetErrorMessage().c_str());
                    }
                }

                DeleteProcThreadAttributeList(pattrlist);
            }

        }
        else
        {
            printf("Error OpenProcess: %ls\n", GetErrorMessage().c_str());
        }
    }

    return 0;
}