VeraCrypt
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMounir IDRASSI <mounir.idrassi@idrix.fr>2023-10-08 01:55:07 +0200
committerMounir IDRASSI <mounir.idrassi@idrix.fr>2023-10-08 01:55:07 +0200
commitc91e5792ef7361a06ed959b47cbe97da97e7a037 (patch)
tree144b5f051dc878ff10756788a63ef6c471a69b12
parent22ac25dde7b80ffd15ac1bf513d6c8578f3832cf (diff)
downloadVeraCrypt-c91e5792ef7361a06ed959b47cbe97da97e7a037.tar.gz
VeraCrypt-c91e5792ef7361a06ed959b47cbe97da97e7a037.zip
Windows: Modified implementation for Secure Desktop handling to overcome Windows 11 issues
We use only alphanumeric characters for the name in addition to the '_' character We ensure the random desktop name doesn't already exist We create the random desktop on the Secure Desktop thread and we look over SwitchDesktop until it works. We call SetThreadDesktop (hOriginalDesk) in main thread once we finish
-rw-r--r--src/Common/Dlgcode.c136
1 files changed, 82 insertions, 54 deletions
diff --git a/src/Common/Dlgcode.c b/src/Common/Dlgcode.c
index e0307cde..e0ff2b2c 100644
--- a/src/Common/Dlgcode.c
+++ b/src/Common/Dlgcode.c
@@ -13782,7 +13782,7 @@ static BOOL GenerateRandomString (HWND hwndDlg, LPTSTR szName, DWORD maxCharsCou
bRet = RandgetBytesFull (hwndDlg, indexes, maxCharsCount + 1, TRUE, TRUE);
if (bRet)
{
- static LPCTSTR chars = _T("0123456789@#$%^&_-*abcdefghijklmnopqrstuvwxyz");
+ static LPCTSTR chars = _T("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_");
DWORD i, charsLen = (DWORD) _tcslen (chars);
DWORD effectiveLen = (indexes[0] % (64 - 16)) + 16; // random length between 16 to 64
effectiveLen = (effectiveLen > maxCharsCount)? maxCharsCount : effectiveLen;
@@ -13864,7 +13864,9 @@ static unsigned int __stdcall SecureDesktopMonitoringThread( LPVOID lpThreadPara
{
if (GetUserObjectInformation (currentDesk, UOI_NAME, szName, dwLen, &dwLen))
{
- if (0 != _wcsicmp (szName, szVCDesktopName))
+ if (0 == _wcsicmp(szName, L"Default")) // default input desktop for the interactive window station
+ bPerformSwitch = TRUE;
+ else if (0 != _wcsicmp (szName, szVCDesktopName))
bPerformSwitch = TRUE;
}
free (szName);
@@ -13888,18 +13890,29 @@ static unsigned int __stdcall SecureDesktopThread( LPVOID lpThreadParameter )
SecureDesktopThreadParam* pParam = (SecureDesktopThreadParam*) lpThreadParameter;
SecureDesktopMonitoringThreadParam monitorParam;
BOOL bNewDesktopSet = FALSE;
+ HDESK hSecureDesk;
+ DWORD desktopAccess = DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_READOBJECTS | DESKTOP_SWITCHDESKTOP | DESKTOP_WRITEOBJECTS;
+
+ hSecureDesk = CreateDesktop (pParam->szDesktopName, NULL, NULL, 0, desktopAccess, NULL);
+ if (!hSecureDesk)
+ {
+ return 0;
+ }
+
+ StringCbCopy(SecureDesktopName, sizeof (SecureDesktopName), pParam->szDesktopName);
+ pParam->hDesk = hSecureDesk;
// wait for SwitchDesktop to succeed before using it for current thread
while (true)
{
- if (SwitchDesktop (pParam->hDesk))
+ if (SwitchDesktop (hSecureDesk))
{
break;
}
Sleep (SECUREDESKTOP_MONOTIR_PERIOD);
}
- bNewDesktopSet = SetThreadDesktop (pParam->hDesk);
+ bNewDesktopSet = SetThreadDesktop (hSecureDesk);
if (bNewDesktopSet)
{
@@ -13909,7 +13922,7 @@ static unsigned int __stdcall SecureDesktopThread( LPVOID lpThreadParameter )
if (hStopEvent)
{
monitorParam.szVCDesktopName = pParam->szDesktopName;
- monitorParam.hVcDesktop = pParam->hDesk;
+ monitorParam.hVcDesktop = hSecureDesk;
monitorParam.hStopEvent = hStopEvent;
hMonitoringThread = (HANDLE) _beginthreadex (NULL, 0, SecureDesktopMonitoringThread, (LPVOID) &monitorParam, 0, &monitoringThreadID);
}
@@ -13986,18 +13999,36 @@ INT_PTR SecureDesktopDialogBoxParam(
if (bEffectiveUseSecureDesktop && !IsThreadInSecureDesktop(GetCurrentThreadId()))
{
+ BOOL bRandomNameGenerated = FALSE;
+ HDESK existedDesk = NULL;
EnterCriticalSection (&csSecureDesktop);
bSecureDesktopOngoing = TRUE;
finally_do ({ bSecureDesktopOngoing = FALSE; LeaveCriticalSection (&csSecureDesktop); });
- if (GenerateRandomString (hWndParent, szDesktopName, 64))
+ // ensure that the randomly generated name is not already used
+ do
+ {
+ if (existedDesk)
+ {
+ CloseDesktop (existedDesk);
+ existedDesk = NULL;
+ }
+ if (GenerateRandomString (hWndParent, szDesktopName, 64))
+ {
+ existedDesk = OpenDesktop (szDesktopName, 0, FALSE, GENERIC_READ);
+ if (!existedDesk)
+ {
+ bRandomNameGenerated = TRUE;
+ }
+ }
+ } while (existedDesk);
+
+ if (bRandomNameGenerated)
{
map<DWORD, BOOL> ctfmonBeforeList, ctfmonAfterList;
- DWORD desktopAccess = DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_READOBJECTS | DESKTOP_SWITCHDESKTOP | DESKTOP_WRITEOBJECTS;
- HDESK hSecureDesk;
- HDESK hOriginalDesk = GetThreadDesktop (GetCurrentThreadId());
+ HDESK hOriginalDesk = NULL;
+ SecureDesktopThreadParam param;
- HDESK hInputDesk = NULL;
// wait for the input desktop to be available before switching to
// secure desktop. Under Windows 10, the user session can be started
@@ -14005,65 +14036,62 @@ INT_PTR SecureDesktopDialogBoxParam(
// case, we wait for the user to be really authenticated before starting
// secure desktop mechanism
- while (!(hInputDesk = OpenInputDesktop (0, TRUE, GENERIC_READ)))
+ while (!(hOriginalDesk = OpenInputDesktop (0, TRUE, GENERIC_ALL)))
{
Sleep (SECUREDESKTOP_MONOTIR_PERIOD);
}
-
- CloseDesktop (hInputDesk);
// get the initial list of ctfmon.exe processes before creating new desktop
GetCtfMonProcessIdList (ctfmonBeforeList);
- hSecureDesk = CreateDesktop (szDesktopName, NULL, NULL, 0, desktopAccess, NULL);
- if (hSecureDesk)
- {
- SecureDesktopThreadParam param;
-
- param.hDesk = hSecureDesk;
- param.szDesktopName = szDesktopName;
- param.hInstance = hInstance;
- param.lpTemplateName = lpTemplateName;
- param.lpDialogFunc = lpDialogFunc;
- param.dwInitParam = dwInitParam;
- param.retValue = 0;
- param.bDlgDisplayed = FALSE;
-
- // 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)
- {
- StringCbCopy(SecureDesktopName, sizeof (SecureDesktopName), szDesktopName);
+ param.hDesk = NULL;
+ param.szDesktopName = szDesktopName;
+ param.hInstance = hInstance;
+ param.lpTemplateName = lpTemplateName;
+ param.lpDialogFunc = lpDialogFunc;
+ param.dwInitParam = dwInitParam;
+ param.retValue = 0;
+ param.bDlgDisplayed = FALSE;
- WaitForSingleObject (hThread, INFINITE);
- CloseHandle (hThread);
+ // 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)
+ {
+ WaitForSingleObject (hThread, INFINITE);
+ CloseHandle (hThread);
- if (param.bDlgDisplayed)
- {
- // dialog box was indeed displayed in Secure Desktop
- retValue = param.retValue;
- bSuccess = TRUE;
- }
+ if (param.bDlgDisplayed)
+ {
+ // dialog box was indeed displayed in Secure Desktop
+ retValue = param.retValue;
+ bSuccess = TRUE;
+ }
+ }
- // switch back to original desktop
- SwitchDesktop (hOriginalDesk);
+ if (param.hDesk)
+ {
+ while (!SwitchDesktop (hOriginalDesk))
+ {
+ Sleep (SECUREDESKTOP_MONOTIR_PERIOD);
}
- CloseDesktop (hSecureDesk);
+ SetThreadDesktop (hOriginalDesk);
+
+ CloseDesktop (param.hDesk);
+ }
- // get the new list of ctfmon.exe processes in order to find the ID of the
- // ctfmon.exe instance that corresponds to the desktop we create so that
- // we can kill it, otherwise it would remain running
- GetCtfMonProcessIdList (ctfmonAfterList);
+ // get the new list of ctfmon.exe processes in order to find the ID of the
+ // ctfmon.exe instance that corresponds to the desktop we create so that
+ // we can kill it, otherwise it would remain running
+ GetCtfMonProcessIdList (ctfmonAfterList);
- for (map<DWORD, BOOL>::iterator It = ctfmonAfterList.begin();
- It != ctfmonAfterList.end(); It++)
+ for (map<DWORD, BOOL>::iterator It = ctfmonAfterList.begin();
+ It != ctfmonAfterList.end(); It++)
+ {
+ if (ctfmonBeforeList[It->first] != TRUE)
{
- if (ctfmonBeforeList[It->first] != TRUE)
- {
- // Kill process
- KillProcess (It->first);
- }
+ // Kill process
+ KillProcess (It->first);
}
}