Skip to content
/ wix Public
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/burn/engine/engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,8 @@ static HRESULT InitializeEngineState(
BurnPipeConnectionInitialize(&pEngineState->embeddedConnection);

// Retain whether bundle was initially run elevated.
ProcElevated(::GetCurrentProcess(), &pEngineState->internalCommand.fInitiallyElevated);
hr = ProcIsHighIntegrity(::GetCurrentProcess(), &pEngineState->internalCommand.fInitiallyElevated);
ExitOnFailure(hr, "Failed to determine if process is running elevated.");

// Parse command line.
hr = CoreParseCommandLine(&pEngineState->internalCommand, &pEngineState->command, &pEngineState->companionConnection, &pEngineState->embeddedConnection, &hSectionFile, &hSourceEngineFile);
Expand Down
1 change: 1 addition & 0 deletions src/burn/stub/precomp.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <strutil.h>
#include <fileutil.h>
#include <pathutil.h>
#include <polcutil.h>
#include <logutil.h>

#include "engine.h"
2 changes: 2 additions & 0 deletions src/burn/stub/stub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ int WINAPI wWinMain(
L"feclient.dll", // unsafely loaded by DecryptFile().
};

AppSetDefaultProcessMitigationPolicy(POLICY_BURN_REGISTRY_PATH);

// Best effort attempt to get our file handle as soon as possible.
hr = PathForCurrentProcess(&sczPath, NULL);
if (SUCCEEDED(hr))
Expand Down
93 changes: 73 additions & 20 deletions src/dtf/SfxCA/SfxUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,24 +163,70 @@ static HRESULT CreateGuid(
return hr;
}

static HRESULT ProcessElevated()
static HRESULT LogLastError(__in MSIHANDLE hSession, __in_z const wchar_t* wzMessage)
{
HRESULT hr = S_OK;
HANDLE hToken = NULL;
TOKEN_ELEVATION tokenElevated = {};
DWORD cbToken = 0;
HRESULT hr = HRESULT_FROM_WIN32(::GetLastError());

if (::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &hToken) &&
::GetTokenInformation(hToken, TokenElevation, &tokenElevated, sizeof(TOKEN_ELEVATION), &cbToken))
{
hr = (0 != tokenElevated.TokenIsElevated) ? S_OK : S_FALSE;
}
else
Log(hSession, L"%ls. Error code 0x%08X", wzMessage, hr);

return hr;
}

static HRESULT HighIntegrityProcess(__in MSIHANDLE hSession, __out BOOL* pfHighIntegrity)
{
HRESULT hr = S_OK;
HANDLE hToken = NULL;
DWORD dwTokenLength = 0;
DWORD cbToken = 0;
PTOKEN_MANDATORY_LABEL pTokenMandatoryLabel = NULL;
DWORD rid = 0;

*pfHighIntegrity = FALSE;

if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &hToken))
{
hr = LogLastError(hSession, L"Failed to open process token");
goto LExit;
}

if (!::GetTokenInformation(hToken, TokenIntegrityLevel, NULL, 0, &dwTokenLength))
{
DWORD er = ::GetLastError();
if (er != ERROR_INSUFFICIENT_BUFFER)
{
hr = HRESULT_FROM_WIN32(::GetLastError());
hr = LogLastError(hSession, L"Failed to get token integrity information length");
goto LExit;
}
}

return hr;
pTokenMandatoryLabel = reinterpret_cast<PTOKEN_MANDATORY_LABEL>(::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, dwTokenLength));
if (!pTokenMandatoryLabel)
{
hr = LogLastError(hSession, L"Failed to allocate memory for token integrity information");
goto LExit;
}

if (!::GetTokenInformation(hToken, TokenIntegrityLevel, pTokenMandatoryLabel, dwTokenLength, &cbToken))
{
hr = LogLastError(hSession, L"Failed to get token integrity information");
goto LExit;
}

rid = *::GetSidSubAuthority(pTokenMandatoryLabel->Label.Sid, *::GetSidSubAuthorityCount(pTokenMandatoryLabel->Label.Sid) - 1);
*pfHighIntegrity = (SECURITY_MANDATORY_HIGH_RID <= rid);

LExit:
if (pTokenMandatoryLabel)
{
::HeapFree(::GetProcessHeap(), 0, pTokenMandatoryLabel);
}

if (hToken)
{
::CloseHandle(hToken);
}

return hr;
}

/// <summary>
Expand All @@ -203,6 +249,7 @@ bool ExtractToTempDirectory(__in MSIHANDLE hSession, __in HMODULE hModule,
HRESULT hr = S_OK;
wchar_t szModule[MAX_PATH] = {};
wchar_t szGuid[GUID_STRING_LENGTH] = {};
BOOL fHighIntegrity = FALSE;

DWORD cchCopied = ::GetModuleFileName(hModule, szModule, MAX_PATH - 1);
if (cchCopied == 0 || cchCopied == MAX_PATH - 1)
Expand All @@ -224,9 +271,15 @@ bool ExtractToTempDirectory(__in MSIHANDLE hSession, __in HMODULE hModule,
goto LExit;
}

// Unelevated we use the user's temp directory.
hr = ProcessElevated();
if (S_FALSE == hr)
// Non-high-integrity we use the user's temp directory.
hr = HighIntegrityProcess(hSession, &fHighIntegrity);
if (FAILED(hr))
{
Log(hSession, L"Failed to determine if process is high integrity. Assuming high integrity. Error code 0x%x", hr);
fHighIntegrity = TRUE;
}

if (!fHighIntegrity)
{
// Temp path is documented to be returned with a trailing backslash.
cchCopied = ::GetTempPath(cchTempDirBuf, szTempDir);
Expand All @@ -242,7 +295,7 @@ bool ExtractToTempDirectory(__in MSIHANDLE hSession, __in HMODULE hModule,
goto LExit;
}
}
else // elevated or we couldn't check (in the latter case, assume we're elevated since it's safer to use)
else // high integrity or we couldn't check (in the latter case, assume high integrity since it's safer to use because if we're not elevated we'll fail safely).
{
// Windows directory will not contain a trailing backslash, so we add it next.
cchCopied = ::GetWindowsDirectoryW(szTempDir, cchTempDirBuf);
Expand All @@ -261,22 +314,22 @@ bool ExtractToTempDirectory(__in MSIHANDLE hSession, __in HMODULE hModule,
hr = ::StringCchCat(szTempDir, cchTempDirBuf, L"\\Installer\\");
if (FAILED(hr))
{
Log(hSession, L"Failed append 'Installer' to Windows directory. Error code 0x%x", hr);
Log(hSession, L"Failed to append 'Installer' to Windows directory '%ls'. Error code 0x%x", szTempDir, hr);
goto LExit;
}
}

hr = ::StringCchCat(szTempDir, cchTempDirBuf, szGuid);
if (FAILED(hr))
{
Log(hSession, L"Failed append GUID to temp path. Error code 0x%x", hr);
Log(hSession, L"Failed append GUID to temp path '%ls'. Error code 0x%x", szTempDir, hr);
goto LExit;
}

if (!::CreateDirectory(szTempDir, NULL))
{
hr = HRESULT_FROM_WIN32(::GetLastError());
Log(hSession, L"Failed to create temp directory. Error code 0x%x", hr);
Log(hSession, L"Failed to create temp directory '%ls'. Error code 0x%x", szTempDir, hr);
goto LExit;
}

Expand Down
100 changes: 100 additions & 0 deletions src/libs/dutil/WixToolset.DUtil/apputil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,15 @@

typedef BOOL(WINAPI *LPFN_SETDEFAULTDLLDIRECTORIES)(DWORD);
typedef BOOL(WINAPI *LPFN_SETDLLDIRECTORYW)(LPCWSTR);
typedef BOOL(WINAPI *LPFN_SETPROCESSMITIGATIONPOLICY)(PROCESS_MITIGATION_POLICY, PVOID, SIZE_T);

static BOOL vfInitialized = FALSE;
static LPFN_SETDEFAULTDLLDIRECTORIES vpfnSetDefaultDllDirectories = NULL;
static LPFN_SETDLLDIRECTORYW vpfnSetDllDirectory = NULL;
static LPFN_SETPROCESSMITIGATIONPOLICY vpfnSetProcessMitigationPolicy = NULL;

static const DWORD APP_MITIGATION_POLICY_DISABLED = 0;
static const DWORD APP_MITIGATION_POLICY_ENABLED = 1;

/********************************************************************
EscapeCommandLineArgument - encodes wzArgument such that
Expand Down Expand Up @@ -50,6 +55,7 @@ static void Initialize()

vpfnSetDefaultDllDirectories = (LPFN_SETDEFAULTDLLDIRECTORIES)::GetProcAddress(hKernel32, "SetDefaultDllDirectories");
vpfnSetDllDirectory = (LPFN_SETDLLDIRECTORYW)::GetProcAddress(hKernel32, "SetDllDirectoryW");
vpfnSetProcessMitigationPolicy = (LPFN_SETPROCESSMITIGATIONPOLICY)::GetProcAddress(hKernel32, "SetProcessMitigationPolicy");

vfInitialized = TRUE;

Expand Down Expand Up @@ -190,6 +196,100 @@ DAPI_(void) AppInitializeUnsafe()
::HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
}

DAPI_(HRESULT) AppSetDefaultProcessMitigationPolicy(
__in_z LPCWSTR wzPolicyPath
)
{
HRESULT hr = S_OK;
HRESULT hrPolicy = S_OK;
DWORD dwPolicy = APP_MITIGATION_POLICY_DISABLED;
BOOL fApplied = FALSE;
PROCESS_MITIGATION_REDIRECTION_TRUST_POLICY redirectionTrustPolicy = { };
PROCESS_MITIGATION_DYNAMIC_CODE_POLICY dynamicCodePolicy = { };
PROCESS_MITIGATION_FONT_DISABLE_POLICY fontDisablePolicy = { };

Initialize();

if (!vpfnSetProcessMitigationPolicy)
{
ExitFunction1(hr = S_FALSE);
}

hrPolicy = PolcReadNumber(wzPolicyPath, L"RedirectionGuard", APP_MITIGATION_POLICY_ENABLED, &dwPolicy);
if (FAILED(hrPolicy))
{
TraceError(hrPolicy, "Failed to read mitigation policy setting: RedirectionGuard.");
dwPolicy = APP_MITIGATION_POLICY_ENABLED;
}

if (APP_MITIGATION_POLICY_ENABLED == dwPolicy)
{
redirectionTrustPolicy.EnforceRedirectionTrust = 1;

if (!vpfnSetProcessMitigationPolicy(ProcessRedirectionTrustPolicy, &redirectionTrustPolicy, sizeof(redirectionTrustPolicy)))
{
hr = HRESULT_FROM_WIN32(::GetLastError());
TraceError(hr, "Failed to set RedirectionGuard mitigation policy.");
}
else
{
fApplied = TRUE;
}
}

hrPolicy = PolcReadNumber(wzPolicyPath, L"DynamicCode", APP_MITIGATION_POLICY_DISABLED, &dwPolicy);
if (FAILED(hrPolicy))
{
TraceError(hrPolicy, "Failed to read mitigation policy setting: DynamicCode.");
dwPolicy = APP_MITIGATION_POLICY_DISABLED;
}

if (APP_MITIGATION_POLICY_ENABLED == dwPolicy)
{
dynamicCodePolicy.ProhibitDynamicCode = 1;

if (!vpfnSetProcessMitigationPolicy(ProcessDynamicCodePolicy, &dynamicCodePolicy, sizeof(dynamicCodePolicy)))
{
hr = HRESULT_FROM_WIN32(::GetLastError());
TraceError(hr, "Failed to set DynamicCode mitigation policy.");
}
else
{
fApplied = TRUE;
}
}

hrPolicy = PolcReadNumber(wzPolicyPath, L"FontDisable", APP_MITIGATION_POLICY_DISABLED, &dwPolicy);
if (FAILED(hrPolicy))
{
TraceError(hrPolicy, "Failed to read mitigation policy setting: FontDisable.");
dwPolicy = APP_MITIGATION_POLICY_DISABLED;
}

if (APP_MITIGATION_POLICY_ENABLED == dwPolicy)
{
fontDisablePolicy.DisableNonSystemFonts = 1;

if (!vpfnSetProcessMitigationPolicy(ProcessFontDisablePolicy, &fontDisablePolicy, sizeof(fontDisablePolicy)))
{
hr = HRESULT_FROM_WIN32(::GetLastError());
TraceError(hr, "Failed to set FontDisable mitigation policy.");
}
else
{
fApplied = TRUE;
}
}

LExit:
if (SUCCEEDED(hr) && !fApplied)
{
hr = S_FALSE;
}

return hr;
}

DAPI_(HRESULT) AppAppendCommandLineArgument(
__deref_inout_z LPWSTR* psczCommandLine,
__in_z LPCWSTR wzArgument
Expand Down
10 changes: 10 additions & 0 deletions src/libs/dutil/WixToolset.DUtil/inc/apputil.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ AppInitializeUnsafe - initializes without the full standard safety
********************************************************************/
void DAPI AppInitializeUnsafe();

/********************************************************************
AppSetDefaultProcessMitigationPolicy - enables default process
mitigations, with per-mitigation policy overrides.

NOTE: Best effort. S_FALSE indicates not supported or disabled.
********************************************************************/
HRESULT DAPI AppSetDefaultProcessMitigationPolicy(
__in_z LPCWSTR wzPolicyPath
);

/********************************************************************
AppParseCommandLine - parses the command line using CommandLineToArgvW.
The caller must free the value of pArgv on success
Expand Down
5 changes: 4 additions & 1 deletion src/libs/dutil/WixToolset.DUtil/inc/procutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ HRESULT DAPI ProcGetTokenInformation(
__in TOKEN_INFORMATION_CLASS tokenInformationClass,
__out LPVOID* ppvTokenInformation
);

HRESULT DAPI ProcIsHighIntegrity(
__in HANDLE hProcess,
__out BOOL* pfHighIntegrity
);
HRESULT DAPI ProcHasPrivilege(
__in HANDLE hProcess,
__in LPCWSTR wzPrivilegeName,
Expand Down
25 changes: 24 additions & 1 deletion src/libs/dutil/WixToolset.DUtil/procutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ static BOOL CALLBACK CloseWindowEnumCallback(
__in LPARAM lParam
);


extern "C" HRESULT DAPI ProcElevated(
__in HANDLE hProcess,
__out BOOL* pfElevated
Expand Down Expand Up @@ -141,6 +140,30 @@ extern "C" HRESULT DAPI ProcGetTokenInformation(
return hr;
}

extern "C" HRESULT DAPI ProcIsHighIntegrity(
__in HANDLE hProcess,
__out BOOL* pfHighIntegrity
)
{
HRESULT hr = S_OK;
TOKEN_MANDATORY_LABEL* pTokenMandatoryLabel = NULL;
DWORD integrityRid = 0;

*pfHighIntegrity = FALSE;

hr = ProcGetTokenInformation(hProcess, TokenIntegrityLevel, reinterpret_cast<LPVOID*>(&pTokenMandatoryLabel));
ProcExitOnFailure(hr, "Failed to get token mandatory label.");

integrityRid = *::GetSidSubAuthority(pTokenMandatoryLabel->Label.Sid, *::GetSidSubAuthorityCount(pTokenMandatoryLabel->Label.Sid) - 1);

*pfHighIntegrity = (SECURITY_MANDATORY_HIGH_RID <= integrityRid);

LExit:
ReleaseMem(pTokenMandatoryLabel);

return hr;
}

extern "C" HRESULT DAPI ProcHasPrivilege(
__in HANDLE hProcess,
__in LPCWSTR wzPrivilegeName,
Expand Down
Loading