⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 createprocessasuser.cpp

📁 这是一本学习 window编程的很好的参考教材
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	// for some reason, the service process hangs around for 20 seconds
	// before exiting, which causes the deletion to lag for the same amount of time.
}

SERVICE_STATUS_HANDLE g_hss;
SERVICE_STATUS g_ss;

void WINAPI Handler( DWORD )
{
	SetServiceStatus( g_hss, &g_ss );
}

void WINAPI ServiceMain( DWORD argc, wchar_t* argv[] )
{
	g_ss.dwCurrentState = SERVICE_RUNNING;
	g_ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS;

	g_hss = RegisterServiceCtrlHandler( L"AsPrincipal", Handler );
	SetServiceStatus( g_hss, &g_ss );
	bool fAsSystem = false;
	bool fAsAppID = false;
	bool fAsInteractive = false;
	bool fEqualToInteractive = false;
	if (_wcsnicmp(argv[1], L"-s",2)==0) fAsSystem = true;

	HANDLE hptoken = INVALID_HANDLE_VALUE;
	DWORD dwErr = 0;
	LPCWSTR szwDescr = NULL;
	do {
		if (!fAsSystem) {
			LPWSTR szcwUser = NULL;
			LPWSTR szcwDomain = NULL;
			LPWSTR szcwPassword = NULL;
			LPWSTR szcwAppID = NULL;
			WCHAR szwPassword[MAX_PATH], szwUserName[MAX_PATH], szwUserDomain[MAX_PATH];
			memset(szwPassword,0,sizeof(szwPassword));
			memset(szwUserName,0,sizeof(szwUserName));
			memset(szwUserDomain,0,sizeof(szwUserDomain));
			for (DWORD i = 1; i < argc; i++) {
				if (_wcsnicmp(argv[i], L"-d",2)==0) szcwDomain = argv[i]+2;
				else if (_wcsnicmp(argv[i], L"-u",2)==0) szcwUser = argv[i]+2;
				else if (_wcsnicmp(argv[i], L"-p",2)==0) szcwPassword = argv[i]+2;
				else if (_wcsnicmp(argv[i], L"-a",2)==0) szcwAppID = argv[i]+2;
				else if (_wcsnicmp(argv[i], L"-i",2)==0) fAsInteractive = true;
				if (i == 3) break;
				if (szcwAppID) break;
				if (fAsInteractive) break;
			}
			if (szcwAppID) {
				fAsAppID = true;
				if (FAILED(dwErr = GetRunAsPassword(szcwAppID, MAX_PATH, szwPassword, MAX_PATH, szwUserName, MAX_PATH, szwUserDomain))) {
					if (E_RUN_AS_INTERACTIVE == dwErr) {
						fAsAppID = false;
						fAsInteractive = true;
					} else {szwDescr = L"Failed to retrieve AppID data"; break;}
				} else {
					szcwUser = szwUserName;
					szcwDomain = szwUserDomain;
					szcwPassword = szwPassword;
				}
			}
			if (!fAsInteractive && !fAsAppID) {
				wcscpy(szwUserName,szcwUser);
				wcscpy(szwUserDomain, szcwDomain);
				wcscpy(szwPassword, szcwPassword);
			}
			if (fAsInteractive) {
				if (FAILED(dwErr = GetInteractiveUserToken(&hptoken, MAX_PATH, szwUserName, MAX_PATH, szwUserDomain))) {
					szwDescr = L"Failed to retrieve token of shell process"; break;}
			} else {
				if (!LogonUser(szcwUser,szcwDomain,szcwPassword, 
					LOGON32_LOGON_BATCH, LOGON32_PROVIDER_DEFAULT, &hptoken)) {
					dwErr = GetLastError(), szwDescr = L"LogonUser failed"; break; }
				HANDLE htmp;
				memset(szwPassword, 0, sizeof(szwPassword));
				szcwUser = szwPassword;
				szcwDomain = szwPassword + MAX_PATH/2;
				if (FAILED(dwErr = GetInteractiveUserToken(&htmp, MAX_PATH/2, szcwUser, MAX_PATH/2, szcwDomain))) {
					szwDescr = L"Failed to retrieve token of shell process"; break;}
				CloseHandle(htmp);
				fEqualToInteractive = (_wcsicmp(szcwUser, szwUserName) == 0 && _wcsicmp(szcwDomain, szwUserDomain) == 0);
			}
		}

		wchar_t cmd[MAX_CMD_LEN];
		wchar_t* dst = cmd;
		wchar_t* dstEnd = cmd + sizeof cmd / sizeof *cmd;
		wchar_t** it = argv + ((fAsSystem ||fAsAppID||fAsInteractive)?2:4);
		wchar_t** const end = it + argc - 1;
		while ( end != it )
		{
			// add whitespace between args
			if ( dst != cmd )
				*dst++ = L' ';

			// watch for overflow
			const int cch = lstrlen( *it );
			if ( dst + cch + 2 > dstEnd )
				break;

			// concatenate args
			lstrcpy( dst, *it );
			dst += cch;
			++it;
		}
		*dst = '\0';

		STARTUPINFO si;
		memset(&si, 0, sizeof(si));
		si.cb = sizeof(si);
		si.lpDesktop = (fAsInteractive || fEqualToInteractive || fAsSystem)?NULL:
			(hptoken!=INVALID_HANDLE_VALUE && (dwErr = GrantDesktopAccess(hptoken))==S_OK)?NULL:L"";
		if (dwErr) szwDescr = L"GrantDesktopAccess failed";
		PROCESS_INFORMATION pi;
		if (INVALID_HANDLE_VALUE != hptoken) {
			if (CreateProcessAsUser(hptoken, 0, cmd, 0, 0, FALSE, 0, 0, 0, &si, &pi ) ) {
				CloseHandle( pi.hThread );
				CloseHandle( pi.hProcess );
			} else dwErr = GetLastError(), szwDescr = L"CreateProcessAsUser failed";
			hptoken = (CloseHandle(hptoken), INVALID_HANDLE_VALUE);
		} else if ( CreateProcess( 0, cmd, 0, 0, FALSE, 0, 0, 0, &si, &pi ) ) {
			CloseHandle( pi.hThread );
			CloseHandle( pi.hProcess );
		} else dwErr = GetLastError(), szwDescr = L"CreateProcess failed";
	} while(false);

	if (dwErr) {
	    HANDLE h;
		if (hptoken != INVALID_HANDLE_VALUE) hptoken = (CloseHandle(hptoken), INVALID_HANDLE_VALUE);
		h = RegisterEventSource(NULL, L"AsPrincipal");
		if (h != NULL)  {
			ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, dwErr, NULL, (szwDescr)?1:0, 0, (szwDescr)?&szwDescr:NULL,NULL);
			DeregisterEventSource(h); 
		}
	}
	g_ss.dwCurrentState = SERVICE_STOPPED;
	SetServiceStatus( g_hss, &g_ss );
}

void wmain( int argc, wchar_t* argv[] )
{
	if (1 < argc) {
		int fCheckParams = 0;
		for (int i = 1; i < argc; i++) {
			if (_wcsnicmp(argv[i], L"-s",2)==0) fCheckParams |= 0x8;
			else if (_wcsnicmp(argv[i], L"-d",2)==0) fCheckParams |= 0x1;
			else if (_wcsnicmp(argv[i], L"-u",2)==0) fCheckParams |= 0x2;
			else if (_wcsnicmp(argv[i], L"-p",2)==0) fCheckParams |= 0x4;
			else if (_wcsnicmp(argv[i], L"-a",2)==0) fCheckParams |= 0x10;
			else if (_wcsnicmp(argv[i], L"-i",2)==0) fCheckParams |= 0x20;
			if ( fCheckParams==0x8 && i > 1) break; //if second param is not any of -d -u -p than break;
			else if (fCheckParams==0x10 && i > 1) break;
			else if (fCheckParams==0x20 && i > 1) break;
			else if (fCheckParams == 0x7) break;
			else if (i > 3) break;
		}
		if (fCheckParams != 0x8 && fCheckParams != 0x7 && fCheckParams != 0x10 && fCheckParams!=0x20) PrintUsageAndQuit();
	} else if ( 1 == argc )	{
		// try to detect whether we are being launched by the SCM
		// or by the interactive user, who should have passed cmd line args
		if ( !IsLocalSystem() )
			PrintUsageAndQuit();

		SERVICE_TABLE_ENTRY ste[] = { 
			{ L"AsPrincipal", ServiceMain },
			{ 0, 0 }
		};
		StartServiceCtrlDispatcher( ste );
		return;
	}
	if ( !IsAdmin() )
		Quit( L"You must be a member of the local Administrator's group to run this program" );

	StartAsService( argc - 1, (const wchar_t**)argv + 1 );
}

HRESULT RetrieveLogonSid(HANDLE hToken,PSID *pLogonSid)
{
	PTOKEN_GROUPS	ptgGroups = NULL;
	DWORD			cbBuffer  = 0;
	DWORD			dwSidLength;
	UINT			i;
	HRESULT			hr=S_OK;

	__try {
		*pLogonSid = NULL;

		GetTokenInformation(hToken, TokenGroups, ptgGroups, cbBuffer, &cbBuffer);
		if (cbBuffer && !(ptgGroups = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbBuffer))) return hr = E_OUTOFMEMORY;
		if (!GetTokenInformation(hToken,TokenGroups,ptgGroups,cbBuffer,&cbBuffer)) return hr = GetLastError();
		// Get the logon Sid by looping through the Sids in the token
		for(i = 0 ; i < ptgGroups->GroupCount ; i++) {
			if (ptgGroups->Groups[i].Attributes & SE_GROUP_LOGON_ID) {
				if (!IsValidSid(ptgGroups->Groups[i].Sid)) return hr = E_FAIL;
				dwSidLength=GetLengthSid(ptgGroups->Groups[i].Sid);

				if((*pLogonSid = (PSID)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSidLength)) == NULL) return hr = E_OUTOFMEMORY;
				if (!CopySid(dwSidLength,*pLogonSid,ptgGroups->Groups[i].Sid)) return hr = GetLastError();
				return S_OK;
			}
		}
		return hr = E_INVALIDARG;
	} __finally {
		if (hr != S_OK) {
			if(*pLogonSid != NULL) {
				HeapFree(GetProcessHeap(), 0, *pLogonSid);
				*pLogonSid = NULL;
			}
		}
		if (ptgGroups != NULL) HeapFree(GetProcessHeap(), 0, ptgGroups);
	}
	return E_UNEXPECTED;
}
 
 
HRESULT InsertSidInAcl(PSID pSid,PACL pAclSource,PACL *pAclDestination,DWORD AccessMask,bool bAddSid,bool bFreeOldAcl)
{
	ACL_SIZE_INFORMATION	AclInfo;
	DWORD					dwNewAclSize;
	LPVOID					pAce;
	DWORD					AceCounter;
	HRESULT					hr=S_OK;

	__try {
		if (pAclSource == NULL) {
			*pAclDestination = NULL;
			return S_OK;
		}

		if (!IsValidSid(pSid)) return hr = E_FAIL;

		if (!GetAclInformation(pAclSource,&AclInfo,sizeof(ACL_SIZE_INFORMATION),AclSizeInformation)) return hr = GetLastError();

		//	Compute size for new ACL, based on addition or subtraction of ACE 
		if (bAddSid) dwNewAclSize = AclInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pSid) - sizeof(DWORD);
		else dwNewAclSize = AclInfo.AclBytesInUse - sizeof(ACCESS_ALLOWED_ACE) - GetLengthSid(pSid) + sizeof(DWORD);

		*pAclDestination = (PACL) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwNewAclSize);
		if (*pAclDestination == NULL) return hr = E_OUTOFMEMORY;

		if (!InitializeAcl(*pAclDestination, dwNewAclSize, ACL_REVISION)) return hr = GetLastError();

		// copy existing ACEs to new ACL
		for(AceCounter = 0 ; AceCounter < AclInfo.AceCount ; AceCounter++) {
			if (!GetAce(pAclSource, AceCounter, &pAce)) return hr = GetLastError();
			if (!bAddSid) {
				// we only care about ACCESS_ALLOWED ACEs
				if ((((PACE_HEADER)pAce)->AceType) == ACCESS_ALLOWED_ACE_TYPE) {
					PSID pTempSid=(PSID)&((PACCESS_ALLOWED_ACE)pAce)->SidStart;
					if (EqualSid(pSid, pTempSid)) continue;
				}
			}

			if (!AddAce(*pAclDestination,ACL_REVISION,0,pAce,((PACE_HEADER)pAce)->AceSize)) return hr = GetLastError();
		}

		if (bAddSid && !AddAccessAllowedAce(*pAclDestination,ACL_REVISION,AccessMask,pSid)) return hr = GetLastError();
		return S_OK;
	} __finally {
		if (hr != S_OK) {
			if(*pAclDestination != NULL) HeapFree(GetProcessHeap(), 0, *pAclDestination);
		} else if (bFreeOldAcl)	HeapFree(GetProcessHeap(), 0, pAclSource);
	}

	return E_UNEXPECTED;
}

HRESULT AdjustWinstaDesktopSecurity(HWINSTA hWinsta, HDESK hDesktop, PSID pLogonSid, bool bGrant, HANDLE hToken)
{
	SECURITY_INFORMATION	si = DACL_SECURITY_INFORMATION;
	PSECURITY_DESCRIPTOR	sdDesktop = NULL;
	PSECURITY_DESCRIPTOR	sdWinsta = NULL;
	SECURITY_DESCRIPTOR		sdNewDesktop;
	SECURITY_DESCRIPTOR		sdNewWinsta;
	DWORD					sdDesktopLength	= 0;	/* allocation size */
	DWORD					sdWinstaLength	= 0;	/* allocation size */
	PACL					pDesktopDacl;		/* previous Dacl on Desktop */
	PACL					pWinstaDacl;        /* previous Dacl on Winsta */
	PACL					pNewDesktopDacl	= NULL;	/* new Dacl for Desktop */
	PACL					pNewWinstaDacl	= NULL;	/* new Dacl for Winsta */
	BOOL 					bDesktopDaclPresent;
	BOOL 					bWinstaDaclPresent;
	BOOL 					bDaclDefaultDesktop;
	BOOL 					bDaclDefaultWinsta;
	HRESULT  				hr = S_OK;
	PSID					pUserSid = NULL;

	__try {
		GetUserObjectSecurity(hDesktop,	&si, sdDesktop, sdDesktopLength, &sdDesktopLength);

		if (sdDesktopLength) sdDesktop = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sdDesktopLength);

		if (!GetUserObjectSecurity(hDesktop,&si,sdDesktop,sdDesktopLength,&sdDesktopLength)) return GetLastError();

		GetUserObjectSecurity(hWinsta,&si,sdWinsta,sdWinstaLength,&sdWinstaLength);

		if (sdWinstaLength)	sdWinsta = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sdWinstaLength);

		if (!GetUserObjectSecurity(hWinsta,&si,sdWinsta,sdWinstaLength,&sdWinstaLength)) return GetLastError();

		if (!GetSecurityDescriptorDacl(sdDesktop,&bDesktopDaclPresent, &pDesktopDacl, &bDaclDefaultDesktop)) return GetLastError();

		if (!GetSecurityDescriptorDacl(sdWinsta,&bWinstaDaclPresent,&pWinstaDacl,&bDaclDefaultWinsta)) return GetLastError();

		// Create new DACL with Logon and User Sid for Desktop
		if(bDesktopDaclPresent && (hr = InsertSidInAcl(pLogonSid,pDesktopDacl,&pNewDesktopDacl,
				GENERIC_READ | GENERIC_WRITE | READ_CONTROL | DESKTOP_READOBJECTS | DESKTOP_CREATEWINDOW | 
				DESKTOP_CREATEMENU | DESKTOP_SWITCHDESKTOP | DESKTOP_ENUMERATE, bGrant,false)) != S_OK) return hr;

		// Create new DACL with Logon and User Sid for Window station
		if(bWinstaDaclPresent && (hr = InsertSidInAcl(pLogonSid,pWinstaDacl,&pNewWinstaDacl,
							GENERIC_READ | GENERIC_WRITE | READ_CONTROL
							| WINSTA_ACCESSGLOBALATOMS | WINSTA_ENUMDESKTOPS | WINSTA_READATTRIBUTES | 
							WINSTA_ACCESSCLIPBOARD | WINSTA_ENUMERATE | WINSTA_EXITWINDOWS, bGrant, false)) != S_OK) return hr;
 
		// Initialize the target security descriptor for Desktop
		if (bDesktopDaclPresent && !InitializeSecurityDescriptor(&sdNewDesktop, SECURITY_DESCRIPTOR_REVISION)) return GetLastError();

		// Initialize the target security descriptor for Window station
		if(bWinstaDaclPresent && !InitializeSecurityDescriptor(&sdNewWinsta,SECURITY_DESCRIPTOR_REVISION)) return GetLastError();

		// Apply new ACL to the Desktop security descriptor
		if(bDesktopDaclPresent && !SetSecurityDescriptorDacl(&sdNewDesktop,TRUE,pNewDesktopDacl,bDaclDefaultDesktop)) return GetLastError();

		// Apply new ACL to the Window station security descriptor
		if(bWinstaDaclPresent && !SetSecurityDescriptorDacl(&sdNewWinsta, TRUE, pNewWinstaDacl, bDaclDefaultWinsta)) return GetLastError();

		// Apply security descriptors with new DACLs to Desktop and Window station
		if (bDesktopDaclPresent && !SetUserObjectSecurity(hDesktop, &si,&sdNewDesktop)) return GetLastError();

		if(bWinstaDaclPresent && !SetUserObjectSecurity(hWinsta,&si,&sdNewWinsta)) return GetLastError();
		return S_OK;
	}__finally{
		if (sdDesktop != NULL) HeapFree(GetProcessHeap(), 0, sdDesktop);
		if (sdWinsta != NULL) HeapFree(GetProcessHeap(), 0, sdWinsta);
		if (pNewDesktopDacl != NULL) HeapFree(GetProcessHeap(), 0, pNewDesktopDacl);
		if (pNewWinstaDacl != NULL) HeapFree(GetProcessHeap(), 0, pNewWinstaDacl);
	}
	return E_UNEXPECTED;
}

HRESULT GrantDesktopAccess(HANDLE hToken)
{
	HWINSTA	hWinsta = NULL;
	HDESK	hDesktop = NULL;
	PSID	pLogonSid = NULL;
	HRESULT hr = E_FAIL;

	__try {
		if ((hr = RetrieveLogonSid(hToken, &pLogonSid))!=S_OK) return hr;

		hWinsta=GetProcessWindowStation();
		hDesktop=GetThreadDesktop(GetCurrentThreadId());
		 
		if (!SetHandleInformation(hDesktop, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) return GetLastError();

		if (!SetHandleInformation(hWinsta, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) return GetLastError();
		return AdjustWinstaDesktopSecurity(hWinsta, hDesktop, pLogonSid, true, hToken);
	} __finally {
		if(pLogonSid != NULL)
			HeapFree(GetProcessHeap(), 0, pLogonSid);
	}
	return E_UNEXPECTED;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -