如何从Windows服务启动具有提升的管理员帐户权限的应用程序,即使该帐户尚未登录也是如此 [英] How to launch an application with elevated administrator account privilege from windows service even if the account has not yet logon

查看:164
本文介绍了如何从Windows服务启动具有提升的管理员帐户权限的应用程序,即使该帐户尚未登录也是如此的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是这种情况:

操作系统环境:Windows 7

我的系统中有两个用户帐户,标准用户S和管理员帐户A,并且有一个运行本地系统权限的Windows服务。

现在我使用帐户S登录,并且我想从该服务启动具有提升的管理员帐户A的应用程序程序,所以这里是代码片段:



Here is the case:
OS environment: Windows 7
There are two user accounts in my system, standard user "S" and administrator account "A", and there is a windows service running with "Local System" privilege.
Now i logged-in with account "S", and i want to launch an application with elevated administrator account "A" from that service program, so here is the code snippet:

int LaunchAppWithElevatedPrivilege (
	LPTSTR lpszUsername,    // client to log on
	LPTSTR lpszDomain,      // domain of client's account
	LPTSTR lpszPassword,    // client's password
	LPTSTR lpCommandLine    // command line to execute e.g. L"C:\\windows\\regedit.exe"
	)
{
	DWORD dwExitCode = 0;	

	HANDLE hToken = NULL;
	HANDLE hFullToken = NULL;
	HANDLE hPrimaryFullToken = NULL;
	HANDLE lsa = NULL;
	BOOL bResult = FALSE;

	LUID luid;
	MSV1_0_INTERACTIVE_PROFILE* profile = NULL;
	DWORD err;
	PTOKEN_GROUPS LocalGroups = NULL;
	DWORD dwLength = 0;
	DWORD dwSessionId = 0;
	LPVOID pEnv = NULL;
	DWORD dwCreationFlags = 0;
	PROCESS_INFORMATION pi = {0};
	STARTUPINFO si = {0};

	__try
	{
		if (!LogonUser( lpszUsername,
				lpszDomain,
				lpszPassword,
				LOGON32_LOGON_INTERACTIVE,
				LOGON32_PROVIDER_DEFAULT,
				&hToken))
                {
			LOG_FAILED(L"GetTokenInformation failed!");
                        __leave;
                }

		if( !GetTokenInformation(hToken, (TOKEN_INFORMATION_CLASS)19, (VOID*)&hFullToken, 
			sizeof(HANDLE), &dwLength))
		{
			LOG_FAILED(L"GetTokenInformation failed!");
			__leave;
		}

		if(!DuplicateTokenEx(hFullToken, MAXIMUM_ALLOWED, NULL,
			SecurityIdentification, TokenPrimary, &hPrimaryFullToken))
		{
			LOG_FAILED(L"DuplicateTokenEx failed!");
			__leave;		
		}

		DWORD dwSessionId = 0;
		WTS_SESSION_INFO* sessionInfo = NULL;
		DWORD ndSessionInfoCount;

		bResult = WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &sessionInfo, &ndSessionInfoCount);
		if (!bResult)
		{
		        dwSessionId = WTSGetActiveConsoleSessionId();
		}
		else
		{
			for(unsigned int i=0; i<ndSessionInfoCount; i++)
			{
				if( sessionInfo[i].State == WTSActive )
				{
					dwSessionId = sessionInfo[i].SessionId;
				}
			}
		}

		if(0 == dwSessionId)
		{
			LOG_FAILED(L"Get active session id failed!");
			__leave;
		}

		if(!SetTokenInformation(hPrimaryFullToken, TokenSessionId, &dwSessionId, sizeof(DWORD)))
		{
			LOG_FAILED(L"SetTokenInformation failed!");
			__leave;
		}

		if(CreateEnvironmentBlock(&pEnv, hPrimaryFullToken, FALSE))
		{
			dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
		}
		else
			pEnv=NULL;


		if (! ImpersonateLoggedOnUser(hPrimaryFullToken) ) 
		{
			LOG_FAILED(L"ImpersonateLoggedOnUser failed!");
			__leave;
		}

		si.cb= sizeof(STARTUPINFO);
		si.lpDesktop = L"winsta0\\default";
        
		bResult = CreateProcessAsUser(
			hPrimaryFullToken,            // client's access token
			NULL,              // file to execute
			lpCommandLine,     // command line
			NULL,              // pointer to process SECURITY_ATTRIBUTES
			NULL,              // pointer to thread SECURITY_ATTRIBUTES
			FALSE,             // handles are not inheritable
			dwCreationFlags,   // creation flags
			pEnv,              // pointer to new environment block 
			NULL,              // name of current directory 
			&si,               // pointer to STARTUPINFO structure
			&pi                // receives information about new process
			);

		RevertToSelf();

		if (bResult && pi.hProcess != INVALID_HANDLE_VALUE) 
		{
			WaitForSingleObject(pi.hProcess, INFINITE);
			GetExitCodeProcess(pi.hProcess, &dwExitCode);
		} 
		else
		{
			LOG_FAILED(L"CreateProcessAsUser failed!");
		}
	}
	__finally
	{
		if (pi.hProcess != INVALID_HANDLE_VALUE)
			CloseHandle(pi.hProcess);  
		if (pi.hThread != INVALID_HANDLE_VALUE)
			CloseHandle(pi.hThread); 

		if(LocalGroups)
			LocalFree(LocalGroups);
		if(pEnv)
			DestroyEnvironmentBlock(pEnv);
		if(hToken)
			CloseHandle(hToken);
		if(hFullToken)
			CloseHandle(hFullToken);
		if(hPrimaryFullToken)
			CloseHandle(hPrimaryFullToken);
	}

	return dwExitCode;
}





我将帐户A的用户名和密码传递给方法LaunchAppWithElevatedPrivilege,以及应用程序i想要发射,例如C:\windows\regedit.exe,但是当我运行服务程序时,我发现它确实使用提升的帐户A启动regedit.exe,但regedit.exe的内容是纯粹的。屏幕截图如下:



http:// social。 msdn.microsoft.com/Forums/getfile/463206

http:/ /social.msdn.microsoft.com/Forums/getfile/463207

推荐答案

如果您搜索了更多而不是在codeproject上发布了3次,则stackoverflow或者msdn。比你发现危险的黑客堆栈溢出



最好的解决方案是互动服务
If you had searched more instead of posting it 3 times at codeproject, stackoverflow or msdn. Than you had found the dangerous hack Stack overflow

The best solution is with interactive services


这篇关于如何从Windows服务启动具有提升的管理员帐户权限的应用程序,即使该帐户尚未登录也是如此的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆