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