1
0
mirror of https://github.com/veracrypt/VeraCrypt.git synced 2025-11-11 19:08:26 -06:00

Windows: enhance secure desktop handling to try to workaround Windows 11 issue

Several enhancements implemented:
 - replace CreateThread by _beginthreadex to avoid potential issues when using C runtime
 - use an event to notify monitoring thread to stop instead of a volatile boolean
 - perform switch to the regular desktop in the main thread and not in the secure desktop thread
This commit is contained in:
Mounir IDRASSI
2023-07-15 02:59:13 +02:00
parent 49fff71d0a
commit 7ada94d36b

View File

@@ -14085,13 +14085,14 @@ typedef struct
DLGPROC lpDialogFunc; DLGPROC lpDialogFunc;
LPARAM dwInitParam; LPARAM dwInitParam;
INT_PTR retValue; INT_PTR retValue;
BOOL bDlgDisplayed; // set to TRUE if the dialog was displayed on secure desktop
} SecureDesktopThreadParam; } SecureDesktopThreadParam;
typedef struct typedef struct
{ {
LPCWSTR szVCDesktopName; LPCWSTR szVCDesktopName;
HDESK hVcDesktop; HDESK hVcDesktop;
volatile BOOL* pbStopMonitoring; HANDLE hStopEvent; // event to signal when to stop monitoring
} SecureDesktopMonitoringThreadParam; } SecureDesktopMonitoringThreadParam;
#define SECUREDESKTOP_MONOTIR_PERIOD 500 #define SECUREDESKTOP_MONOTIR_PERIOD 500
@@ -14103,11 +14104,12 @@ static unsigned int __stdcall SecureDesktopMonitoringThread( LPVOID lpThreadPara
SecureDesktopMonitoringThreadParam* pMonitorParam = (SecureDesktopMonitoringThreadParam*) lpThreadParameter; SecureDesktopMonitoringThreadParam* pMonitorParam = (SecureDesktopMonitoringThreadParam*) lpThreadParameter;
if (pMonitorParam) if (pMonitorParam)
{ {
volatile BOOL* pbStopMonitoring = pMonitorParam->pbStopMonitoring; HANDLE hStopEvent = pMonitorParam->hStopEvent;
LPCWSTR szVCDesktopName = pMonitorParam->szVCDesktopName; LPCWSTR szVCDesktopName = pMonitorParam->szVCDesktopName;
HDESK hVcDesktop = pMonitorParam->hVcDesktop; HDESK hVcDesktop = pMonitorParam->hVcDesktop;
while (!*pbStopMonitoring) // loop until the stop event is signaled
while (WaitForSingleObject (hStopEvent, SECUREDESKTOP_MONOTIR_PERIOD) == WAIT_TIMEOUT)
{ {
// check that our secure desktop is still the input desktop // check that our secure desktop is still the input desktop
// otherwise, switch to it // otherwise, switch to it
@@ -14135,22 +14137,18 @@ static unsigned int __stdcall SecureDesktopMonitoringThread( LPVOID lpThreadPara
if (bPerformSwitch) if (bPerformSwitch)
SwitchDesktop (hVcDesktop); SwitchDesktop (hVcDesktop);
Sleep (SECUREDESKTOP_MONOTIR_PERIOD);
} }
} }
return 0; return 0;
} }
static DWORD WINAPI SecureDesktopThread(LPVOID lpThreadParameter) static unsigned int __stdcall SecureDesktopThread( LPVOID lpThreadParameter )
{ {
volatile BOOL bStopMonitoring = FALSE;
HANDLE hMonitoringThread = NULL; HANDLE hMonitoringThread = NULL;
unsigned int monitoringThreadID = 0; unsigned int monitoringThreadID = 0;
SecureDesktopThreadParam* pParam = (SecureDesktopThreadParam*) lpThreadParameter; SecureDesktopThreadParam* pParam = (SecureDesktopThreadParam*) lpThreadParameter;
SecureDesktopMonitoringThreadParam monitorParam; SecureDesktopMonitoringThreadParam monitorParam;
HDESK hOriginalDesk = GetThreadDesktop (GetCurrentThreadId ());
BOOL bNewDesktopSet = FALSE; BOOL bNewDesktopSet = FALSE;
// wait for SwitchDesktop to succeed before using it for current thread // wait for SwitchDesktop to succeed before using it for current thread
@@ -14158,20 +14156,23 @@ static DWORD WINAPI SecureDesktopThread(LPVOID lpThreadParameter)
{ {
if (SwitchDesktop (pParam->hDesk)) if (SwitchDesktop (pParam->hDesk))
{ {
bNewDesktopSet = TRUE;
break; break;
} }
Sleep (SECUREDESKTOP_MONOTIR_PERIOD); Sleep (SECUREDESKTOP_MONOTIR_PERIOD);
} }
bNewDesktopSet = SetThreadDesktop (pParam->hDesk);
if (bNewDesktopSet) if (bNewDesktopSet)
{ {
SetThreadDesktop (pParam->hDesk);
// create the thread that will ensure that VeraCrypt secure desktop has always user input // create the thread that will ensure that VeraCrypt secure desktop has always user input
// this is done only if the stop event is created successfully
HANDLE hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (hStopEvent)
{
monitorParam.szVCDesktopName = pParam->szDesktopName; monitorParam.szVCDesktopName = pParam->szDesktopName;
monitorParam.hVcDesktop = pParam->hDesk; monitorParam.hVcDesktop = pParam->hDesk;
monitorParam.pbStopMonitoring = &bStopMonitoring; monitorParam.hStopEvent = hStopEvent;
hMonitoringThread = (HANDLE) _beginthreadex (NULL, 0, SecureDesktopMonitoringThread, (LPVOID) &monitorParam, 0, &monitoringThreadID); hMonitoringThread = (HANDLE) _beginthreadex (NULL, 0, SecureDesktopMonitoringThread, (LPVOID) &monitorParam, 0, &monitoringThreadID);
} }
@@ -14180,16 +14181,23 @@ static DWORD WINAPI SecureDesktopThread(LPVOID lpThreadParameter)
if (hMonitoringThread) if (hMonitoringThread)
{ {
bStopMonitoring = TRUE; // notify the monitoring thread to stop
SetEvent(hStopEvent);
WaitForSingleObject (hMonitoringThread, INFINITE); WaitForSingleObject (hMonitoringThread, INFINITE);
CloseHandle (hMonitoringThread); CloseHandle (hMonitoringThread);
} }
if (bNewDesktopSet) if (hStopEvent)
{ {
SetThreadDesktop (hOriginalDesk); CloseHandle (hStopEvent);
SwitchDesktop (hOriginalDesk); }
pParam->bDlgDisplayed = TRUE;
}
else
{
pParam->bDlgDisplayed = FALSE;
} }
return 0; return 0;
@@ -14249,6 +14257,7 @@ INT_PTR SecureDesktopDialogBoxParam(
map<DWORD, BOOL> ctfmonBeforeList, ctfmonAfterList; map<DWORD, BOOL> ctfmonBeforeList, ctfmonAfterList;
DWORD desktopAccess = DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_READOBJECTS | DESKTOP_SWITCHDESKTOP | DESKTOP_WRITEOBJECTS; DWORD desktopAccess = DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_READOBJECTS | DESKTOP_SWITCHDESKTOP | DESKTOP_WRITEOBJECTS;
HDESK hSecureDesk; HDESK hSecureDesk;
HDESK hOriginalDesk = GetThreadDesktop (GetCurrentThreadId());
HDESK hInputDesk = NULL; HDESK hInputDesk = NULL;
@@ -14280,8 +14289,10 @@ INT_PTR SecureDesktopDialogBoxParam(
param.lpDialogFunc = lpDialogFunc; param.lpDialogFunc = lpDialogFunc;
param.dwInitParam = dwInitParam; param.dwInitParam = dwInitParam;
param.retValue = 0; param.retValue = 0;
param.bDlgDisplayed = FALSE;
HANDLE hThread = ::CreateThread (NULL, 0, SecureDesktopThread, (LPVOID) &param, 0, NULL); // use _beginthreadex instead of CreateThread because lpDialogFunc may be using the C runtime library
HANDLE hThread = (HANDLE) _beginthreadex (NULL, 0, SecureDesktopThread, (LPVOID) &param, 0, NULL);
if (hThread) if (hThread)
{ {
StringCbCopy(SecureDesktopName, sizeof (SecureDesktopName), szDesktopName); StringCbCopy(SecureDesktopName, sizeof (SecureDesktopName), szDesktopName);
@@ -14289,10 +14300,17 @@ INT_PTR SecureDesktopDialogBoxParam(
WaitForSingleObject (hThread, INFINITE); WaitForSingleObject (hThread, INFINITE);
CloseHandle (hThread); CloseHandle (hThread);
if (param.bDlgDisplayed)
{
// dialog box was indeed displayed in Secure Desktop
retValue = param.retValue; retValue = param.retValue;
bSuccess = TRUE; bSuccess = TRUE;
} }
// switch back to original desktop
SwitchDesktop (hOriginalDesk);
}
CloseDesktop (hSecureDesk); CloseDesktop (hSecureDesk);
// get the new list of ctfmon.exe processes in order to find the ID of the // get the new list of ctfmon.exe processes in order to find the ID of the
@@ -14311,6 +14329,7 @@ INT_PTR SecureDesktopDialogBoxParam(
} }
} }
CloseDesktop(hOriginalDesk);
burn (szDesktopName, sizeof (szDesktopName)); burn (szDesktopName, sizeof (szDesktopName));
} }
} }