在服务中用管理员权限创建一个可弹出UI的进程

时间:2021-08-13 01:15:24
do
	{
// 		if (!OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hThisToken ))
// 		{
// 			PrintfDbgStr(TEXT("OpenProcessToken error !error code:%d\n"),GetLastError());
// 			bSuccess = FALSE;
// 			break;
// 		}
// 		if(!SetPrivilege(hThisToken,SE_TCB_NAME,TRUE))
// 		{
// 			PrintfDbgStr(TEXT("SetPrivilege error !error code:%d\n"),GetLastError());
// 			bSuccess = FALSE;
// 			break;
// 		}
		DWORD dwSessionId = WTSGetActiveConsoleSessionId();
		if(!WTSQueryUserToken(dwSessionId,&hToken))
		{
			PrintfDbgStr(TEXT("WTSQueryUserToken error !error code:%d\n"),GetLastError());
			bSuccess = FALSE;
			break;
		}

		STARTUPINFO si;
		PROCESS_INFORMATION pi;
		ZeroMemory(&si,sizeof(STARTUPINFO));
		ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));
		si.cb = sizeof(STARTUPINFO);
		si.lpDesktop = _T("WinSta0\\Default");
		si.wShowWindow = TRUE;
		si.dwFlags     = STARTF_USESHOWWINDOW;

		LPVOID pEnv = NULL;
		DWORD dwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
		if(!CreateProcessAsUser(hToken,NULL,pBuf,NULL,NULL,FALSE,dwCreationFlag,pEnv,NULL,&si,&pi))
		{
			PrintfDbgStr(TEXT("CreateProcessAsUser error !error code:%d\n"),GetLastError());
			bSuccess = FALSE;
			break;
		}
		
	}while(0);

这种方法创建的进程不是管理员权限的,因为是调用了用户的令牌创建的进程。不过,确实能顺利弹出UI。

HANDLE hToken = NULL;
	HANDLE hTokenDup = NULL;
	do 
	{
		if(OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hToken))
		{
			if(DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS,NULL, SecurityIdentification, TokenPrimary, &hTokenDup))
			{
				DWORD dwSessionId = WTSGetActiveConsoleSessionId();
				if(!SetTokenInformation(hTokenDup,TokenSessionId,&dwSessionId,sizeof(DWORD)))
				{
					PrintfDbgStr(TEXT("SetTokenInformation error !error code:%d\n"),GetLastError());
					bSuccess = FALSE;
					break;
				}

				STARTUPINFO si;
				PROCESS_INFORMATION pi;
				ZeroMemory(&si,sizeof(STARTUPINFO));
				ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));
				si.cb = sizeof(STARTUPINFO);
				si.lpDesktop = _T("WinSta0\\Default");
				si.wShowWindow = SW_SHOW;
				si.dwFlags     =   STARTF_USESHOWWINDOW /*|STARTF_USESTDHANDLES*/;

				LPVOID pEnv = NULL;
				DWORD dwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT;
				if(!CreateEnvironmentBlock(&pEnv,hTokenDup,FALSE))
				{
					PrintfDbgStr(TEXT("CreateEnvironmentBlock error !error code:%d\n"),GetLastError());
					bSuccess = FALSE;
					break;
				}

				if(!CreateProcessAsUser(hTokenDup,NULL,pBuf,NULL,NULL,FALSE,dwCreationFlag,pEnv,NULL,&si,&pi))
				{
					PrintfDbgStr(TEXT("CreateProcessAsUser error !error code:%d\n"),GetLastError());
					bSuccess = FALSE;
					break;
				}

				if(pEnv)
				{
					DestroyEnvironmentBlock(pEnv);
				}
			}
			else
			{
				PrintfDbgStr(TEXT("DuplicateTokenEx error !error code:%d\n"),GetLastError());
				bSuccess = FALSE;
				break;
			}

				
		}
		else
		{
			PrintfDbgStr(TEXT("cannot get administror!error code:%d\n"),GetLastError());
			bSuccess = FALSE;
			break;
		}
	}while(0);

	if(hTokenDup != NULL && hTokenDup != INVALID_HANDLE_VALUE)
		CloseHandle(hTokenDup);
	if(hToken != NULL && hToken != INVALID_HANDLE_VALUE)
		CloseHandle(hToken);
这里就能用管理员权限打开一个进程并,弹出UI了,注意dwCreationFlag和si的参数设定,我是经过多次试验得出的,错了的话,可能就弹不出来了哦。这种方法是打开用户的令牌但是把服务的所有权限都给这个令牌,所以用户令牌就有足够的权限用管理员打开进程了。