From 0a737c8c87fded05a74cad5232c9c973b3037d61 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Mon, 16 Apr 2018 00:23:05 +0200 Subject: Windows: implement internal verification of Authenticode digital signature for all modules to protect against simple binaries tampering. --- src/Common/Dlgcode.c | 169 ++++++++++++++++++++++++++++++++++++++++++++---- src/Common/Dlgcode.h | 2 +- src/Mount/Mount.c | 62 +++++++++++++++--- src/Setup/SelfExtract.c | 9 +++ src/Setup/Setup.c | 15 ++++- 5 files changed, 231 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/Common/Dlgcode.c b/src/Common/Dlgcode.c index 2e37a6a3..fdff1f07 100644 --- a/src/Common/Dlgcode.c +++ b/src/Common/Dlgcode.c @@ -75,6 +75,8 @@ #endif #include +#include +#include #include #pragma comment( lib, "setupapi.lib" ) @@ -266,6 +268,8 @@ HMODULE hbcryptprimitivesdll = NULL; HMODULE hMsls31 = NULL; HMODULE hntmartadll = NULL; HMODULE hwinscarddll = NULL; +HMODULE hmsvcrtdll = NULL; +HMODULE hWinTrustLib = NULL; #define FREE_DLL(h) if (h) { FreeLibrary (h); h = NULL;} @@ -317,6 +321,29 @@ SHDeleteKeyWPtr SHDeleteKeyWFn = NULL; SHStrDupWPtr SHStrDupWFn = NULL; ChangeWindowMessageFilterPtr ChangeWindowMessageFilterFn = NULL; +typedef LONG (WINAPI *WINVERIFYTRUST)(HWND hwnd, GUID *pgActionID, LPVOID pWVTData); +typedef CRYPT_PROVIDER_DATA* (WINAPI *WTHELPERPROVDATAFROMSTATEDATA)(HANDLE hStateData); +typedef CRYPT_PROVIDER_SGNR* (WINAPI *WTHELPERGETPROVSIGNERFROMCHAIN)(CRYPT_PROVIDER_DATA *pProvData, + DWORD idxSigner, + BOOL fCounterSigner, + DWORD idxCounterSigner); +typedef CRYPT_PROVIDER_CERT* (WINAPI *WTHELPERGETPROVCERTFROMCHAIN)(CRYPT_PROVIDER_SGNR *pSgnr, + DWORD idxCert); + +static WINVERIFYTRUST WinVerifyTrustFn = NULL; +static WTHELPERPROVDATAFROMSTATEDATA WTHelperProvDataFromStateDataFn = NULL; +static WTHELPERGETPROVSIGNERFROMCHAIN WTHelperGetProvSignerFromChainFn = NULL; +static WTHELPERGETPROVCERTFROMCHAIN WTHelperGetProvCertFromChainFn = NULL; + +static unsigned char gpbSha1CodeSignCertFingerprint[64] = { + 0xCD, 0xF3, 0x05, 0xAD, 0xAE, 0xD3, 0x91, 0xF2, 0x0D, 0x95, 0x95, 0xAC, + 0x76, 0x09, 0x35, 0x53, 0x11, 0x00, 0x4D, 0xDD, 0x56, 0x02, 0xBD, 0x09, + 0x76, 0x57, 0xE1, 0xFA, 0xFA, 0xF4, 0x86, 0x09, 0x28, 0xA4, 0x0D, 0x1C, + 0x68, 0xE7, 0x68, 0x31, 0xD3, 0xB6, 0x62, 0x9C, 0x75, 0x91, 0xAB, 0xB5, + 0x6F, 0x1A, 0x75, 0xE7, 0x13, 0x2F, 0xF1, 0xB1, 0x14, 0xBF, 0x5F, 0x00, + 0x40, 0xCE, 0x17, 0x6C +}; + /* Windows dialog class */ #define WINDOWS_DIALOG_CLASS L"#32770" @@ -691,6 +718,7 @@ void AbortProcessDirect (wchar_t *abortMsg) FREE_DLL (hMsls31); FREE_DLL (hntmartadll); FREE_DLL (hwinscarddll); + FREE_DLL (hmsvcrtdll); exit (1); } @@ -740,6 +768,7 @@ void AbortProcessSilent (void) FREE_DLL (hMsls31); FREE_DLL (hntmartadll); FREE_DLL (hwinscarddll); + FREE_DLL (hmsvcrtdll); // Note that this function also causes localcleanup() to be called (see atexit()) exit (1); @@ -2701,6 +2730,9 @@ void InitApp (HINSTANCE hInstance, wchar_t *lpszCommandLine) WNDCLASSW wc; char langId[6]; InitCommonControlsPtr InitCommonControlsFn = NULL; + wchar_t modPath[MAX_PATH]; + + GetModuleFileNameW (NULL, modPath, ARRAYSIZE (modPath)); /* remove current directory from dll search path */ SetDllDirectoryFn = (SetDllDirectoryPtr) GetProcAddress (GetModuleHandle(L"kernel32.dll"), "SetDllDirectoryW"); @@ -2720,6 +2752,7 @@ void InitApp (HINSTANCE hInstance, wchar_t *lpszCommandLine) InitGlobalLocks (); + LoadSystemDll (L"msvcrt.dll", &hmsvcrtdll, TRUE, SRC_POS); LoadSystemDll (L"ntmarta.dll", &hntmartadll, TRUE, SRC_POS); LoadSystemDll (L"MPR.DLL", &hmprdll, TRUE, SRC_POS); #ifdef SETUP @@ -2770,22 +2803,24 @@ void InitApp (HINSTANCE hInstance, wchar_t *lpszCommandLine) LoadSystemDll (L"vsstrace.dll", &hvsstracedll, TRUE, SRC_POS); LoadSystemDll (L"vssapi.dll", &vssapidll, TRUE, SRC_POS); LoadSystemDll (L"spp.dll", &hsppdll, TRUE, SRC_POS); + } +#endif - if (IsOSAtLeast (WIN_7)) - { - LoadSystemDll (L"CryptSP.dll", &hCryptSpDll, TRUE, SRC_POS); - - LoadSystemDll (L"cfgmgr32.dll", &hcfgmgr32dll, TRUE, SRC_POS); - LoadSystemDll (L"devobj.dll", &hdevobjdll, TRUE, SRC_POS); - LoadSystemDll (L"powrprof.dll", &hpowrprofdll, TRUE, SRC_POS); + LoadSystemDll (L"crypt32.dll", &hcrypt32dll, TRUE, SRC_POS); + + if (IsOSAtLeast (WIN_7)) + { + LoadSystemDll (L"CryptSP.dll", &hCryptSpDll, TRUE, SRC_POS); - LoadSystemDll (L"crypt32.dll", &hcrypt32dll, TRUE, SRC_POS); + LoadSystemDll (L"cfgmgr32.dll", &hcfgmgr32dll, TRUE, SRC_POS); + LoadSystemDll (L"devobj.dll", &hdevobjdll, TRUE, SRC_POS); + LoadSystemDll (L"powrprof.dll", &hpowrprofdll, TRUE, SRC_POS); - LoadSystemDll (L"bcrypt.dll", &hbcryptdll, TRUE, SRC_POS); - LoadSystemDll (L"bcryptprimitives.dll", &hbcryptprimitivesdll, TRUE, SRC_POS); - } + LoadSystemDll (L"bcrypt.dll", &hbcryptdll, TRUE, SRC_POS); + LoadSystemDll (L"bcryptprimitives.dll", &hbcryptprimitivesdll, TRUE, SRC_POS); } -#else + +#ifndef SETUP LoadSystemDll (L"WINSCARD.DLL", &hwinscarddll, TRUE, SRC_POS); #endif @@ -2805,6 +2840,10 @@ void InitApp (HINSTANCE hInstance, wchar_t *lpszCommandLine) LoadSystemDll (L"Riched20.dll", &hRichEditDll, FALSE, SRC_POS); +#if defined(NDEBUG) && !defined(SETUP) + if (!VerifyModuleSignature (modPath)) + AbortProcess ("DIST_PACKAGE_CORRUPTED"); +#endif // Get SetupAPI functions pointers SetupCloseInfFileFn = (SetupCloseInfFilePtr) GetProcAddress (hSetupDll, "SetupCloseInfFile"); SetupDiOpenClassRegKeyFn = (SetupDiOpenClassRegKeyPtr) GetProcAddress (hSetupDll, "SetupDiOpenClassRegKey"); @@ -2876,7 +2915,6 @@ void InitApp (HINSTANCE hInstance, wchar_t *lpszCommandLine) // A new instance of the application must be created with elevated privileges. if (IsNonInstallMode () && !IsAdmin () && IsUacSupported ()) { - wchar_t modPath[MAX_PATH]; if (wcsstr (lpszCommandLine, L"/q UAC ") == lpszCommandLine) { @@ -2884,7 +2922,6 @@ void InitApp (HINSTANCE hInstance, wchar_t *lpszCommandLine) exit (1); } - GetModuleFileNameW (NULL, modPath, ARRAYSIZE (modPath)); if (LaunchElevatedProcess (NULL, modPath, lpszCommandLine)) exit (0); @@ -3027,6 +3064,7 @@ void InitApp (HINSTANCE hInstance, wchar_t *lpszCommandLine) FREE_DLL (hMsls31); FREE_DLL (hntmartadll); FREE_DLL (hwinscarddll); + FREE_DLL (hmsvcrtdll); exit (1); } #endif @@ -3071,6 +3109,7 @@ void FinalizeApp (void) FREE_DLL (hMsls31); FREE_DLL (hntmartadll); FREE_DLL (hwinscarddll); + FREE_DLL (hmsvcrtdll); } void InitHelpFileName (void) @@ -13364,3 +13403,105 @@ INT_PTR SecureDesktopDialogBoxParam( } #endif + +static BOOL InitializeWintrust() +{ + if (!hWinTrustLib) + { + wchar_t szPath[MAX_PATH] = {0}; + + if (GetSystemDirectory(szPath, MAX_PATH)) + StringCchCatW (szPath, MAX_PATH, L"\\Wintrust.dll"); + else + StringCchCopyW (szPath, MAX_PATH, L"C:\\Windows\\System32\\Wintrust.dll"); + + hWinTrustLib = LoadLibrary (szPath); + if (hWinTrustLib) + { + WinVerifyTrustFn = (WINVERIFYTRUST) GetProcAddress (hWinTrustLib, "WinVerifyTrust"); + WTHelperProvDataFromStateDataFn = (WTHELPERPROVDATAFROMSTATEDATA) GetProcAddress (hWinTrustLib, "WTHelperProvDataFromStateData"); + WTHelperGetProvSignerFromChainFn = (WTHELPERGETPROVSIGNERFROMCHAIN) GetProcAddress (hWinTrustLib, "WTHelperGetProvSignerFromChain"); + WTHelperGetProvCertFromChainFn = (WTHELPERGETPROVCERTFROMCHAIN) GetProcAddress (hWinTrustLib, "WTHelperGetProvCertFromChain"); + + if ( !WinVerifyTrustFn + || !WTHelperProvDataFromStateDataFn + || !WTHelperGetProvSignerFromChainFn + || !WTHelperGetProvCertFromChainFn) + { + FreeLibrary (hWinTrustLib); + hWinTrustLib = NULL; + } + + } + } + + if (hWinTrustLib) + return TRUE; + else + return FALSE; +} + +static void FinalizeWintrust() +{ + if (hWinTrustLib) + { + FreeLibrary (hWinTrustLib); + hWinTrustLib = NULL; + } +} + +BOOL VerifyModuleSignature (const wchar_t* path) +{ + BOOL bResult = FALSE; + HRESULT hResult; + GUID gActionID = WINTRUST_ACTION_GENERIC_VERIFY_V2; + WINTRUST_FILE_INFO fileInfo = {0}; + WINTRUST_DATA WVTData = {0}; + + if (!InitializeWintrust ()) + return FALSE; + + fileInfo.cbStruct = sizeof(WINTRUST_FILE_INFO); + fileInfo.pcwszFilePath = path; + fileInfo.hFile = NULL; + + WVTData.cbStruct = sizeof(WINTRUST_DATA); + WVTData.dwUIChoice = WTD_UI_NONE; + WVTData.fdwRevocationChecks = WTD_REVOKE_NONE; + WVTData.dwUnionChoice = WTD_CHOICE_FILE; + WVTData.pFile = &fileInfo; + WVTData.dwStateAction = WTD_STATEACTION_VERIFY; + WVTData.dwProvFlags = WTD_REVOCATION_CHECK_NONE | WTD_CACHE_ONLY_URL_RETRIEVAL; + + hResult = WinVerifyTrustFn(0, &gActionID, &WVTData); + if (SUCCEEDED (hResult)) + { + PCRYPT_PROVIDER_DATA pProviderData = WTHelperProvDataFromStateDataFn (WVTData.hWVTStateData); + if (pProviderData) + { + PCRYPT_PROVIDER_SGNR pProviderSigner = WTHelperGetProvSignerFromChainFn (pProviderData, 0, FALSE, 0); + if (pProviderSigner) + { + PCRYPT_PROVIDER_CERT pProviderCert = WTHelperGetProvCertFromChainFn (pProviderSigner, 0); + if (pProviderCert && (pProviderCert->pCert)) + { + BYTE hashVal[64]; + sha512 (hashVal, pProviderCert->pCert->pbCertEncoded, pProviderCert->pCert->cbCertEncoded); + + if (0 == memcmp (hashVal, gpbSha1CodeSignCertFingerprint, 64)) + { + bResult = TRUE; + } + } + } + } + } + + WVTData.dwUIChoice = WTD_UI_NONE; + WVTData.dwStateAction = WTD_STATEACTION_CLOSE; + WinVerifyTrustFn(0, &gActionID, &WVTData); + + FinalizeWintrust (); + + return bResult; +} diff --git a/src/Common/Dlgcode.h b/src/Common/Dlgcode.h index 309ceac5..5d10db35 100644 --- a/src/Common/Dlgcode.h +++ b/src/Common/Dlgcode.h @@ -528,7 +528,7 @@ BOOL GetFreeDriveLetter(WCHAR* pCh); BOOL RaisePrivileges(void); BOOL DeleteDirectory (const wchar_t* szDirName); INT_PTR SecureDesktopDialogBoxParam (HINSTANCE, LPCWSTR, HWND, DLGPROC, LPARAM); - +BOOL VerifyModuleSignature (const wchar_t* path); #ifdef __cplusplus } diff --git a/src/Mount/Mount.c b/src/Mount/Mount.c index b3ad6f6d..3f508d14 100644 --- a/src/Mount/Mount.c +++ b/src/Mount/Mount.c @@ -1507,6 +1507,10 @@ static void LaunchVolCreationWizard (HWND hwndDlg, const wchar_t *arg, BOOL bEle if (!FileExists(t)) Error ("VOL_CREATION_WIZARD_NOT_FOUND", hwndDlg); // Display a user-friendly error message and advise what to do + else if (!VerifyModuleSignature (t)) + { + Error ("DIST_PACKAGE_CORRUPTED", hwndDlg); + } else { @@ -4425,13 +4429,18 @@ BOOL CALLBACK TravelerDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa goto stop; } - // Main app 32-bit + // Main app 32-bit if (Is64BitOs () && !IsNonInstallMode ()) StringCbPrintfW (srcPath, sizeof(srcPath), L"%s\\VeraCrypt-x86.exe", appDir); else StringCbPrintfW (srcPath, sizeof(srcPath), L"%s\\VeraCrypt.exe", appDir); StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCrypt.exe", dstDir); - if (!TCCopyFile (srcPath, dstPath)) + if (!VerifyModuleSignature (srcPath)) + { + Error ("DIST_PACKAGE_CORRUPTED", hwndDlg); + goto stop; + } + else if (!TCCopyFile (srcPath, dstPath)) { handleWin32Error (hwndDlg, SRC_POS); goto stop; @@ -4443,7 +4452,12 @@ BOOL CALLBACK TravelerDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa else StringCbPrintfW (srcPath, sizeof(srcPath), L"%s\\VeraCrypt-x64.exe", appDir); StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCrypt-x64.exe", dstDir); - if (!TCCopyFile (srcPath, dstPath)) + if (!VerifyModuleSignature (srcPath)) + { + Error ("DIST_PACKAGE_CORRUPTED", hwndDlg); + goto stop; + } + else if (!TCCopyFile (srcPath, dstPath)) { handleWin32Error (hwndDlg, SRC_POS); goto stop; @@ -4458,7 +4472,12 @@ BOOL CALLBACK TravelerDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa else StringCbPrintfW (srcPath, sizeof(srcPath), L"%s\\VeraCrypt Format.exe", appDir); StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCrypt Format.exe", dstDir); - if (!TCCopyFile (srcPath, dstPath)) + if (!VerifyModuleSignature (srcPath)) + { + Error ("DIST_PACKAGE_CORRUPTED", hwndDlg); + goto stop; + } + else if (!TCCopyFile (srcPath, dstPath)) { handleWin32Error (hwndDlg, SRC_POS); goto stop; @@ -4470,7 +4489,12 @@ BOOL CALLBACK TravelerDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa else StringCbPrintfW (srcPath, sizeof(srcPath), L"%s\\VeraCrypt Format-x64.exe", appDir); StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCrypt Format-x64.exe", dstDir); - if (!TCCopyFile (srcPath, dstPath)) + if (!VerifyModuleSignature (srcPath)) + { + Error ("DIST_PACKAGE_CORRUPTED", hwndDlg); + goto stop; + } + else if (!TCCopyFile (srcPath, dstPath)) { handleWin32Error (hwndDlg, SRC_POS); goto stop; @@ -4486,7 +4510,12 @@ BOOL CALLBACK TravelerDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa else StringCbPrintfW (srcPath, sizeof(srcPath), L"%s\\VeraCryptExpander.exe", appDir); StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCryptExpander.exe", dstDir); - if (!TCCopyFile (srcPath, dstPath)) + if (!VerifyModuleSignature (srcPath)) + { + Error ("DIST_PACKAGE_CORRUPTED", hwndDlg); + goto stop; + } + else if (!TCCopyFile (srcPath, dstPath)) { handleWin32Error (hwndDlg, SRC_POS); goto stop; @@ -4498,7 +4527,12 @@ BOOL CALLBACK TravelerDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa else StringCbPrintfW (srcPath, sizeof(srcPath), L"%s\\VeraCryptExpander-x64.exe", appDir); StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCryptExpander-x64.exe", dstDir); - if (!TCCopyFile (srcPath, dstPath)) + if (!VerifyModuleSignature (srcPath)) + { + Error ("DIST_PACKAGE_CORRUPTED", hwndDlg); + goto stop; + } + else if (!TCCopyFile (srcPath, dstPath)) { handleWin32Error (hwndDlg, SRC_POS); goto stop; @@ -4508,7 +4542,12 @@ BOOL CALLBACK TravelerDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa // Driver StringCbPrintfW (srcPath, sizeof(srcPath), L"%s\\veracrypt.sys", appDir); StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\veracrypt.sys", dstDir); - if (!TCCopyFile (srcPath, dstPath)) + if (!VerifyModuleSignature (srcPath)) + { + Error ("DIST_PACKAGE_CORRUPTED", hwndDlg); + goto stop; + } + else if (!TCCopyFile (srcPath, dstPath)) { handleWin32Error (hwndDlg, SRC_POS); goto stop; @@ -4517,7 +4556,12 @@ BOOL CALLBACK TravelerDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa // Driver x64 StringCbPrintfW (srcPath, sizeof(srcPath), L"%s\\veracrypt-x64.sys", appDir); StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\veracrypt-x64.sys", dstDir); - if (!TCCopyFile (srcPath, dstPath)) + if (!VerifyModuleSignature (srcPath)) + { + Error ("DIST_PACKAGE_CORRUPTED", hwndDlg); + goto stop; + } + else if (!TCCopyFile (srcPath, dstPath)) { handleWin32Error (hwndDlg, SRC_POS); goto stop; diff --git a/src/Setup/SelfExtract.c b/src/Setup/SelfExtract.c index 9bae2119..7b3fb4fe 100644 --- a/src/Setup/SelfExtract.c +++ b/src/Setup/SelfExtract.c @@ -396,6 +396,15 @@ BOOL VerifyPackageIntegrity (void) GetModuleFileName (NULL, path, ARRAYSIZE (path)); +#ifdef NDEBUG + // verify Authenticode digital signature of the exe file + if (!VerifyModuleSignature (path)) + { + Error ("DIST_PACKAGE_CORRUPTED", NULL); + return FALSE; + } +#endif + fileDataEndPos = (int) FindStringInFile (path, MagEndMarker, strlen (MagEndMarker)); if (fileDataEndPos < 0) { diff --git a/src/Setup/Setup.c b/src/Setup/Setup.c index a1f27f41..cedd9f61 100644 --- a/src/Setup/Setup.c +++ b/src/Setup/Setup.c @@ -1051,7 +1051,7 @@ err: FindClose (h); } - + SetCurrentDirectory (SetupFilesDir); } @@ -2571,7 +2571,18 @@ int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, wchar_t *lpsz #ifndef PORTABLE SetInstallationPath (NULL); #endif - if (!bUninstall) + if (bUninstall) + { + wchar_t path [TC_MAX_PATH]; + + GetModuleFileName (NULL, path, ARRAYSIZE (path)); + if (!VerifyModuleSignature (path)) + { + Error ("DIST_PACKAGE_CORRUPTED", NULL); + exit (1); + } + } + else { if (IsSelfExtractingPackage()) { -- cgit v1.2.3