Windows-管理员权限程序以普通用户的权限运行不需要管理员权限的程序

工作中碰到这样的需求,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一样,可以自己扩展一下

 

 


 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值