1. 程式人生 > >管理員許可權程式以普通使用者的許可權執行不需要管理員許可權的程式

管理員許可權程式以普通使用者的許可權執行不需要管理員許可權的程式

工作中碰到這樣的需求,A程式需要管理員許可權(也就是會彈UAC驗證),B程式不需要,現在B程式是通過A程式CreateProcess啟動的,發現其實B程式繼承了A的許可權,解決方法如下:

DWORD GetProcessIL(DWORD u32_PID, DWORD* pu32_ProcessIL)
{
	*pu32_ProcessIL = 0;

	HANDLE h_Process   = 0;
	HANDLE h_Token     = 0;
	DWORD  u32_Size    = 0;
	BYTE*  pu8_Count   = 0;
	DWORD* pu32_ProcIL = 0;
	TOKEN_MANDATORY_LABEL* pk_Label = 0;

	h_Process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, u32_PID);
	if (!h_Process)
		goto _CleanUp;

	if (!OpenProcessToken(h_Process, TOKEN_QUERY, &h_Token))
		goto _CleanUp;

	if (!GetTokenInformation(h_Token, TokenIntegrityLevel, NULL, 0, &u32_Size) &&
		GetLastError() != ERROR_INSUFFICIENT_BUFFER)
		goto _CleanUp;

	pk_Label = (TOKEN_MANDATORY_LABEL*) HeapAlloc(GetProcessHeap(), 0, u32_Size);
	if (!pk_Label)
		goto _CleanUp;

	if (!GetTokenInformation(h_Token, TokenIntegrityLevel, pk_Label, u32_Size, &u32_Size))
		goto _CleanUp;

	pu8_Count = GetSidSubAuthorityCount(pk_Label->Label.Sid);
	if (!pu8_Count)
		goto _CleanUp;

	pu32_ProcIL = GetSidSubAuthority(pk_Label->Label.Sid, *pu8_Count-1);
	if (!pu32_ProcIL)
		goto _CleanUp;

	*pu32_ProcessIL = *pu32_ProcIL;
	SetLastError(ERROR_SUCCESS);

_CleanUp:
	DWORD u32_Error = GetLastError();
	if (pk_Label)  HeapFree(GetProcessHeap(), 0, pk_Label);
	if (h_Token)   CloseHandle(h_Token);
	if (h_Process) CloseHandle(h_Process);
	return u32_Error;
}

DWORD CreateProcessMediumIL(WCHAR* u16_Path, WCHAR* u16_CmdLine, WCHAR* u16_CurrentDirectory, PROCESS_INFORMATION *pProcessInfo)
{
	HANDLE h_Process = 0;
	HANDLE h_Token   = 0;
	HANDLE h_Token2  = 0;
	PROCESS_INFORMATION k_ProcInfo    = {0};
	STARTUPINFOW        k_StartupInfo = {0};

	BOOL b_UseToken = FALSE;

	// Detect Windows Vista, 2008, Windows 7 and higher
	if (GetProcAddress(GetModuleHandleA("Kernel32"), "GetProductInfo"))
	{
		DWORD u32_CurIL;
		DWORD u32_Err = GetProcessIL(GetCurrentProcessId(), &u32_CurIL);
		if (u32_Err)
			return u32_Err;

		if (u32_CurIL > SECURITY_MANDATORY_MEDIUM_RID)
			b_UseToken = TRUE;
	}

	// Create the process normally (before Windows Vista or if current process runs with a medium IL)
	if (!b_UseToken)
	{
		if (!::CreateProcessW(u16_Path, u16_CmdLine, 0, 0, FALSE, 0, 0, u16_CurrentDirectory, &k_StartupInfo, &k_ProcInfo))
		{
			return GetLastError();
		}

		if(pProcessInfo)
		{
			*pProcessInfo = k_ProcInfo;
		}
		else
		{
			CloseHandle(k_ProcInfo.hThread);
			CloseHandle(k_ProcInfo.hProcess); 
		}

		return ERROR_SUCCESS;
	}

	defCreateProcessWithTokenW f_CreateProcessWithTokenW = 
		(defCreateProcessWithTokenW) GetProcAddress(GetModuleHandleA("Advapi32"), "CreateProcessWithTokenW");

	if (!f_CreateProcessWithTokenW) // This will never happen on Vista!
		return ERROR_INVALID_FUNCTION; 

	HWND h_Progman = ::GetShellWindow();

	DWORD u32_ExplorerPID = 0;		
	GetWindowThreadProcessId(h_Progman, &u32_ExplorerPID);

	// ATTENTION:
	// If UAC is turned OFF all processes run with SECURITY_MANDATORY_HIGH_RID, also Explorer!
	// But this does not matter because to start the new process without UAC no elevation is required.
	h_Process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, u32_ExplorerPID);
	if (!h_Process)
		goto _CleanUp;

	if (!OpenProcessToken(h_Process, TOKEN_DUPLICATE, &h_Token))
		goto _CleanUp;

	if (!DuplicateTokenEx(h_Token, TOKEN_ALL_ACCESS, 0, SecurityImpersonation, TokenPrimary, &h_Token2))
		goto _CleanUp;

	if (!f_CreateProcessWithTokenW(h_Token2, 0, u16_Path, u16_CmdLine, 0, 0, u16_CurrentDirectory, &k_StartupInfo, &k_ProcInfo))
	{
		goto _CleanUp;
	}

	if(pProcessInfo)
		*pProcessInfo = k_ProcInfo;

	SetLastError(ERROR_SUCCESS);

_CleanUp:
	DWORD u32_Error = GetLastError();
	if (h_Token)   CloseHandle(h_Token);
	if (h_Token2)  CloseHandle(h_Token2);
	if (h_Process) CloseHandle(h_Process);

	if(!pProcessInfo)
	{
		CloseHandle(k_ProcInfo.hThread);
		CloseHandle(k_ProcInfo.hProcess); 
	}

	return u32_Error;
}
用法和CreateProcess一樣,可以自己擴充套件一下