Changeset 96722 in vbox for trunk/src/VBox/Additions
- Timestamp:
- Sep 14, 2022 1:17:09 AM (2 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/Installer/VBoxDrvInst.cpp
r96605 r96722 41 41 #include <devguid.h> 42 42 #include <RegStr.h> 43 #ifdef RT_ARCH_X86 44 # include <wintrust.h> 45 # include <softpub.h> 46 #endif 43 47 44 48 #include <iprt/asm.h> … … 111 115 } DIFXAPI_LOG; 112 116 113 typedef void (__cdecl * DIFXAPILOGCALLBACK_W)(DIFXAPI_LOG Event, DWORD Error, PCWSTR EventDescription, PVOID CallbackContext); 114 115 typedef DWORD (WINAPI *fnDriverPackageInstall)(PCTSTR DriverPackageInfPath, DWORD Flags, PCINSTALLERINFO pInstallerInfo, BOOL *pNeedReboot); 116 fnDriverPackageInstall g_pfnDriverPackageInstall = NULL; 117 118 typedef DWORD (WINAPI *fnDriverPackageUninstall)(PCTSTR DriverPackageInfPath, DWORD Flags, PCINSTALLERINFO pInstallerInfo, BOOL *pNeedReboot); 119 fnDriverPackageUninstall g_pfnDriverPackageUninstall = NULL; 120 121 typedef VOID (WINAPI *fnDIFXAPISetLogCallback)(DIFXAPILOGCALLBACK_W LogCallback, PVOID CallbackContext); 122 fnDIFXAPISetLogCallback g_pfnDIFXAPISetLogCallback = NULL; 117 typedef void (__cdecl *DIFXAPILOGCALLBACK_W)(DIFXAPI_LOG Event, DWORD Error, PCWSTR EventDescription, PVOID CallbackContext); 118 typedef DWORD (WINAPI *PFN_DriverPackageInstall_T)(PCTSTR DriverPackageInfPath, DWORD Flags, PCINSTALLERINFO pInstallerInfo, BOOL *pNeedReboot); 119 typedef DWORD (WINAPI *PFN_DriverPackageUninstall_T)(PCTSTR DriverPackageInfPath, DWORD Flags, PCINSTALLERINFO pInstallerInfo, BOOL *pNeedReboot); 120 typedef VOID (WINAPI *PFN_DIFXAPISetLogCallback_T)(DIFXAPILOGCALLBACK_W LogCallback, PVOID CallbackContext); 121 122 123 /********************************************************************************************************************************* 124 * Global Variables * 125 *********************************************************************************************************************************/ 126 static PFN_DriverPackageInstall_T g_pfnDriverPackageInstall = NULL; 127 static PFN_DriverPackageUninstall_T g_pfnDriverPackageUninstall = NULL; 128 static PFN_DIFXAPISetLogCallback_T g_pfnDIFXAPISetLogCallback = NULL; 123 129 124 130 … … 229 235 230 236 /* 231 * Write to the log file if we have one (wide char format ).237 * Write to the log file if we have one (wide char format, used to be ansi). 232 238 */ 233 239 HANDLE const hLogFile = (HANDLE)pvCtx; … … 250 256 } 251 257 258 259 /** 260 * Writes a header to the DIFx log file. 261 */ 262 static void VBoxDIFxWriteLogHeader(HANDLE hLogFile, char const *pszOperation, wchar_t const *pwszInfFile) 263 { 264 /* Don't want to use RTUtf16Printf here as it drags in a lot of code, thus this tedium... */ 265 wchar_t wszBuf[168]; 266 RTUtf16CopyAscii(wszBuf, RT_ELEMENTS(wszBuf), "\r\n"); 267 268 SYSTEMTIME SysTime = {0}; 269 GetSystemTime(&SysTime); 270 271 char szVal[128]; 272 RTStrFormatU32(szVal, sizeof(szVal), SysTime.wYear, 10, 4, 0, RTSTR_F_ZEROPAD | RTSTR_F_WIDTH); 273 RTUtf16CatAscii(wszBuf, RT_ELEMENTS(wszBuf), szVal); 274 RTUtf16CatAscii(wszBuf, RT_ELEMENTS(wszBuf), "-"); 275 276 RTStrFormatU32(szVal, sizeof(szVal), SysTime.wMonth, 10, 2, 0, RTSTR_F_ZEROPAD | RTSTR_F_WIDTH); 277 RTUtf16CatAscii(wszBuf, RT_ELEMENTS(wszBuf), szVal); 278 RTUtf16CatAscii(wszBuf, RT_ELEMENTS(wszBuf), "-"); 279 280 RTStrFormatU32(szVal, sizeof(szVal), SysTime.wDay, 10, 2, 0, RTSTR_F_ZEROPAD | RTSTR_F_WIDTH); 281 RTUtf16CatAscii(wszBuf, RT_ELEMENTS(wszBuf), szVal); 282 RTUtf16CatAscii(wszBuf, RT_ELEMENTS(wszBuf), "T"); 283 284 RTStrFormatU32(szVal, sizeof(szVal), SysTime.wHour, 10, 2, 0, RTSTR_F_ZEROPAD | RTSTR_F_WIDTH); 285 RTUtf16CatAscii(wszBuf, RT_ELEMENTS(wszBuf), szVal); 286 RTUtf16CatAscii(wszBuf, RT_ELEMENTS(wszBuf), ":"); 287 288 RTStrFormatU32(szVal, sizeof(szVal), SysTime.wMinute, 10, 2, 0, RTSTR_F_ZEROPAD | RTSTR_F_WIDTH); 289 RTUtf16CatAscii(wszBuf, RT_ELEMENTS(wszBuf), szVal); 290 RTUtf16CatAscii(wszBuf, RT_ELEMENTS(wszBuf), ":"); 291 292 RTStrFormatU32(szVal, sizeof(szVal), SysTime.wSecond, 10, 2, 0, RTSTR_F_ZEROPAD | RTSTR_F_WIDTH); 293 RTUtf16CatAscii(wszBuf, RT_ELEMENTS(wszBuf), szVal); 294 RTUtf16CatAscii(wszBuf, RT_ELEMENTS(wszBuf), "."); 295 296 RTStrFormatU32(szVal, sizeof(szVal), SysTime.wMilliseconds, 10, 3, 0, RTSTR_F_ZEROPAD | RTSTR_F_WIDTH); 297 RTUtf16CatAscii(wszBuf, RT_ELEMENTS(wszBuf), szVal); 298 RTUtf16CatAscii(wszBuf, RT_ELEMENTS(wszBuf), "Z: Opened log file for "); 299 300 RTUtf16CatAscii(wszBuf, RT_ELEMENTS(wszBuf), pszOperation); 301 RTUtf16CatAscii(wszBuf, RT_ELEMENTS(wszBuf), " of '"); 302 303 DWORD dwIgn; 304 WriteFile(hLogFile, wszBuf, (DWORD)(RTUtf16Len(wszBuf) * sizeof(wchar_t)), &dwIgn, NULL); 305 WriteFile(hLogFile, pwszInfFile, (DWORD)(RTUtf16Len(pwszInfFile) * sizeof(wchar_t)), &dwIgn, NULL); 306 WriteFile(hLogFile, L"'\r\n", 3 * sizeof(wchar_t), &dwIgn, NULL); 307 } 308 309 #ifdef RT_ARCH_X86 310 311 /** 312 * Interceptor WinVerifyTrust function for SetupApi.dll on Windows 2000, XP, 313 * W2K3 and XP64. 314 * 315 * This crudely modifies the driver verification request from a WHQL/logo driver 316 * check to a simple Authenticode check. 317 */ 318 static LONG WINAPI InterceptedWinVerifyTrust(HWND hwnd, GUID *pActionId, void *pvData) 319 { 320 /* 321 * Resolve the real WinVerifyTrust function. 322 */ 323 static decltype(WinVerifyTrust) * volatile s_pfnRealWinVerifyTrust = NULL; 324 decltype(WinVerifyTrust) *pfnRealWinVerifyTrust = s_pfnRealWinVerifyTrust; 325 if (!pfnRealWinVerifyTrust) 326 { 327 HMODULE hmod = GetModuleHandleW(L"WINTRUST.DLL"); 328 if (!hmod) 329 hmod = LoadLibraryW(L"WINTRUST.DLL"); 330 if (!hmod) 331 { 332 ErrorMsgLastErr("InterceptedWinVerifyTrust: Failed to load wintrust.dll"); 333 return TRUST_E_SYSTEM_ERROR; 334 } 335 pfnRealWinVerifyTrust = (decltype(WinVerifyTrust) *)GetProcAddress(hmod, "WinVerifyTrust"); 336 if (!pfnRealWinVerifyTrust) 337 { 338 ErrorMsg("InterceptedWinVerifyTrust: Failed to locate WinVerifyTrust in wintrust.dll"); 339 return TRUST_E_SYSTEM_ERROR; 340 } 341 s_pfnRealWinVerifyTrust = pfnRealWinVerifyTrust; 342 } 343 344 /* 345 * Modify the ID if appropriate. 346 */ 347 static const GUID s_GuidDriverActionVerify = DRIVER_ACTION_VERIFY; 348 static const GUID s_GuidActionGenericChainVerify = WINTRUST_ACTION_GENERIC_CHAIN_VERIFY; 349 static const GUID s_GuidActionGenericVerify2 = WINTRUST_ACTION_GENERIC_VERIFY_V2; 350 if (pActionId) 351 { 352 if (memcmp(pActionId, &s_GuidDriverActionVerify, sizeof(*pActionId)) == 0) 353 { 354 /** @todo don't apply to obvious NT components... */ 355 PrintStr("DRIVER_ACTION_VERIFY: Changing it to WINTRUST_ACTION_GENERIC_VERIFY_V2\r\n"); 356 pActionId = (GUID *)&s_GuidActionGenericVerify2; 357 } 358 else if (memcmp(pActionId, &s_GuidActionGenericChainVerify, sizeof(*pActionId)) == 0) 359 PrintStr("WINTRUST_ACTION_GENERIC_CHAIN_VERIFY\r\n"); 360 else if (memcmp(pActionId, &s_GuidActionGenericVerify2, sizeof(*pActionId)) == 0) 361 PrintStr("WINTRUST_ACTION_GENERIC_VERIFY_V2\r\n"); 362 else 363 PrintStr("WINTRUST_ACTION_UNKNOWN\r\n"); 364 } 365 366 /* 367 * Log the data. 368 */ 369 if (pvData) 370 { 371 WINTRUST_DATA *pData = (WINTRUST_DATA *)pvData; 372 PrintSXS(" cbStruct = ", pData->cbStruct, "\r\n"); 373 # ifdef DEBUG 374 PrintSXS(" dwUIChoice = ", pData->dwUIChoice, "\r\n"); 375 PrintSXS(" fdwRevocationChecks = ", pData->fdwRevocationChecks, "\r\n"); 376 PrintSXS(" dwStateAction = ", pData->dwStateAction, "\r\n"); 377 PrintSXS(" hWVTStateData = ", (uintptr_t)pData->hWVTStateData, "\r\n"); 378 # endif 379 if (pData->cbStruct >= 7*sizeof(uint32_t)) 380 { 381 switch (pData->dwUnionChoice) 382 { 383 case WTD_CHOICE_FILE: 384 PrintSXS(" pFile = ", (uintptr_t)pData->pFile, "\r\n"); 385 if (RT_VALID_PTR(pData->pFile)) 386 { 387 PrintSXS(" pFile->cbStruct = ", pData->pFile->cbStruct, "\r\n"); 388 # ifndef DEBUG 389 if (pData->pFile->hFile) 390 # endif 391 PrintSXS(" pFile->hFile = ", (uintptr_t)pData->pFile->hFile, "\r\n"); 392 if (RT_VALID_PTR(pData->pFile->pcwszFilePath)) 393 PrintSWS(" pFile->pcwszFilePath = '", pData->pFile->pcwszFilePath, "'\r\n"); 394 # ifdef DEBUG 395 else 396 PrintSXS(" pFile->pcwszFilePath = ", (uintptr_t)pData->pFile->pcwszFilePath, "\r\n"); 397 PrintSXS(" pFile->pgKnownSubject = ", (uintptr_t)pData->pFile->pgKnownSubject, "\r\n"); 398 # endif 399 } 400 break; 401 402 case WTD_CHOICE_CATALOG: 403 PrintSXS(" pCatalog = ", (uintptr_t)pData->pCatalog, "\r\n"); 404 if (RT_VALID_PTR(pData->pCatalog)) 405 { 406 PrintSXS(" pCat->cbStruct = ", pData->pCatalog->cbStruct, "\r\n"); 407 # ifdef DEBUG 408 PrintSXS(" pCat->dwCatalogVersion = ", pData->pCatalog->dwCatalogVersion, "\r\n"); 409 # endif 410 if (RT_VALID_PTR(pData->pCatalog->pcwszCatalogFilePath)) 411 PrintSWS("pCat->pcwszCatalogFilePath = '", pData->pCatalog->pcwszCatalogFilePath, "'\r\n"); 412 # ifdef DEBUG 413 else 414 PrintSXS("pCat->pcwszCatalogFilePath = ", (uintptr_t)pData->pCatalog->pcwszCatalogFilePath, "\r\n"); 415 # endif 416 if (RT_VALID_PTR(pData->pCatalog->pcwszMemberTag)) 417 PrintSWS(" pCat->pcwszMemberTag = '", pData->pCatalog->pcwszMemberTag, "'\r\n"); 418 # ifdef DEBUG 419 else 420 PrintSXS(" pCat->pcwszMemberTag = ", (uintptr_t)pData->pCatalog->pcwszMemberTag, "\r\n"); 421 # endif 422 if (RT_VALID_PTR(pData->pCatalog->pcwszMemberFilePath)) 423 PrintSWS(" pCat->pcwszMemberFilePath = '", pData->pCatalog->pcwszMemberFilePath, "'\r\n"); 424 # ifdef DEBUG 425 else 426 PrintSXS(" pCat->pcwszMemberFilePath = ", (uintptr_t)pData->pCatalog->pcwszMemberFilePath, "\r\n"); 427 # else 428 if (pData->pCatalog->hMemberFile) 429 # endif 430 PrintSXS(" pCat->hMemberFile = ", (uintptr_t)pData->pCatalog->hMemberFile, "\r\n"); 431 # ifdef DEBUG 432 PrintSXS("pCat->pbCalculatedFileHash = ", (uintptr_t)pData->pCatalog->pbCalculatedFileHash, "\r\n"); 433 PrintSXS("pCat->cbCalculatedFileHash = ", pData->pCatalog->cbCalculatedFileHash, "\r\n"); 434 PrintSXS(" pCat->pcCatalogContext = ", (uintptr_t)pData->pCatalog->pcCatalogContext, "\r\n"); 435 # endif 436 } 437 break; 438 439 case WTD_CHOICE_BLOB: 440 PrintSXS(" pBlob = ", (uintptr_t)pData->pBlob, "\r\n"); 441 break; 442 443 case WTD_CHOICE_SIGNER: 444 PrintSXS(" pSgnr = ", (uintptr_t)pData->pSgnr, "\r\n"); 445 break; 446 447 case WTD_CHOICE_CERT: 448 PrintSXS(" pCert = ", (uintptr_t)pData->pCert, "\r\n"); 449 break; 450 451 default: 452 PrintSXS(" dwUnionChoice = ", pData->dwUnionChoice, "\r\n"); 453 break; 454 } 455 } 456 } 457 458 /* 459 * Make the call. 460 */ 461 PrintStr("Calling WinVerifyTrust ...\r\n"); 462 LONG iRet = pfnRealWinVerifyTrust(hwnd, pActionId, pvData); 463 PrintSXS("WinVerifyTrust returns ", (ULONG)iRet, "\r\n"); 464 465 return iRet; 466 } 467 468 469 /** 470 * Installs an WinVerifyTrust interceptor in setupapi.dll on Windows 2000, XP, 471 * W2K3 and XP64. 472 * 473 * This is a very crude hack to lower the WHQL check to just require a valid 474 * Authenticode signature by intercepting the verification call. 475 * 476 * @return Ignored, just a convenience for saving space in error paths. 477 */ 478 static int InstallWinVerifyTrustInterceptorInSetupApi(void) 479 { 480 /* Check the version: */ 481 OSVERSIONINFOW VerInfo = { sizeof(VerInfo) }; 482 GetVersionExW(&VerInfo); 483 if (VerInfo.dwMajorVersion != 5) 484 return 1; 485 486 /* The the target module: */ 487 HMODULE hModSetupApi = GetModuleHandleW(L"SETUPAPI.DLL"); 488 if (!hModSetupApi) 489 return ErrorMsgLastErr("Failed to locate SETUPAPI.DLL in the process"); 490 491 /* 492 * Find the delayed import table (at least that's how it's done in the RTM). 493 */ 494 IMAGE_DOS_HEADER const *pDosHdr = (IMAGE_DOS_HEADER const *)hModSetupApi; 495 IMAGE_NT_HEADERS const *pNtHdrs = (IMAGE_NT_HEADERS const *)( (uintptr_t)hModSetupApi 496 + ( pDosHdr->e_magic == IMAGE_DOS_SIGNATURE 497 ? pDosHdr->e_lfanew : 0)); 498 if (pNtHdrs->Signature != IMAGE_NT_SIGNATURE) 499 return ErrorMsgSU("Failed to parse SETUPAPI.DLL for WinVerifyTrust interception: #", 1); 500 if (pNtHdrs->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC) 501 return ErrorMsgSU("Failed to parse SETUPAPI.DLL for WinVerifyTrust interception: #", 2); 502 if (pNtHdrs->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT) 503 return ErrorMsgSU("Failed to parse SETUPAPI.DLL for WinVerifyTrust interception: #", 3); 504 505 uint32_t const cbDir = pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].Size; 506 if (cbDir < sizeof(IMAGE_DELAYLOAD_DESCRIPTOR)) 507 return ErrorMsgSU("Failed to parse SETUPAPI.DLL for WinVerifyTrust interception: #", 4); 508 uint32_t const cbImages = pNtHdrs->OptionalHeader.SizeOfImage; 509 if (cbDir >= cbImages) 510 return ErrorMsgSU("Failed to parse SETUPAPI.DLL for WinVerifyTrust interception: #", 5); 511 uint32_t const offDir = pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress; 512 if (offDir > cbImages - cbDir) 513 return ErrorMsgSU("Failed to parse SETUPAPI.DLL for WinVerifyTrust interception: #", 6); 514 515 /* 516 * Scan the entries looking for wintrust.dll. 517 */ 518 IMAGE_DELAYLOAD_DESCRIPTOR const * const paEntries = (IMAGE_DELAYLOAD_DESCRIPTOR const *)((uintptr_t)hModSetupApi + offDir); 519 uint32_t const cEntries = cbDir / sizeof(paEntries[0]); 520 for (uint32_t iImp = 0; iImp < cEntries; iImp++) 521 { 522 const char * const pchRva2Ptr = paEntries[iImp].Attributes.RvaBased ? (const char *)hModSetupApi : (const char *)0; 523 const char * const pszDllName = &pchRva2Ptr[paEntries[iImp].DllNameRVA]; 524 if (RTStrICmpAscii(pszDllName, "WINTRUST.DLL") == 0) 525 { 526 /* 527 * Scan the symbol names. 528 */ 529 uint32_t const cbHdrs = pNtHdrs->OptionalHeader.SizeOfHeaders; 530 uint32_t * const pauNameRvas = (uint32_t *)&pchRva2Ptr[paEntries[iImp].ImportNameTableRVA]; 531 uintptr_t * const paIat = (uintptr_t *)&pchRva2Ptr[paEntries[iImp].ImportAddressTableRVA]; 532 for (uint32_t iSym = 0; pauNameRvas[iSym] != NULL; iSym++) 533 { 534 IMAGE_IMPORT_BY_NAME const * const pName = (IMAGE_IMPORT_BY_NAME const *)&pchRva2Ptr[pauNameRvas[iSym]]; 535 if (RTStrCmp(pName->Name, "WinVerifyTrust") == 0) 536 { 537 PrintSXS("Intercepting WinVerifyTrust for SETUPAPI.DLL (old: ", paIat[iSym], ")\r\n"); 538 paIat[iSym] = (uintptr_t)InterceptedWinVerifyTrust; 539 return 0; 540 } 541 } 542 return ErrorMsgSU("Failed to parse SETUPAPI.DLL for WinVerifyTrust interception: #", 9); 543 } 544 } 545 return ErrorMsgSU("Failed to parse SETUPAPI.DLL for WinVerifyTrust interception: #", 10); 546 } 547 548 #endif /* RT_ARCH_X86 */ 252 549 253 550 /** … … 323 620 * Windows 2000 and later. 324 621 */ 325 OSVERSIONINFO VerInfo = { sizeof(VerInfo) };326 GetVersionEx (&VerInfo);622 OSVERSIONINFOW VerInfo = { sizeof(VerInfo) }; 623 GetVersionExW(&VerInfo); 327 624 if (VerInfo.dwPlatformId != VER_PLATFORM_WIN32_NT) 328 625 return ErrorMsg("Platform not supported for driver (un)installation!"); … … 367 664 hLogFile = CreateFileW(pwszLogFile, FILE_GENERIC_WRITE & ~FILE_WRITE_DATA /* append mode */, FILE_SHARE_READ, 368 665 NULL /*pSecAttr*/, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL /*hTemplateFile*/); 369 if (hLogFile == INVALID_HANDLE_VALUE) 666 if (hLogFile != INVALID_HANDLE_VALUE) 667 VBoxDIFxWriteLogHeader(hLogFile, fInstall ? "install" : "uninstall", pwszDriverPath); 668 else 370 669 ErrorMsgLastErrSWS("Failed to open/create log file '", pwszLogFile, "'"); 371 670 g_pfnDIFXAPISetLogCallback(VBoxDIFxLogCallback, (void *)hLogFile); … … 374 673 PrintStr(fInstall ? "Installing driver ...\r\n" : "Uninstalling driver ...\r\n"); 375 674 PrintSWS("INF-File: '", wszFullDriverInf, "'\r\n"); 675 #ifdef RT_ARCH_X86 676 InstallWinVerifyTrustInterceptorInSetupApi(); 677 #endif 376 678 377 679 INSTALLERINFO InstInfo = … … 589 891 { 590 892 PrintSWSWS("Installing from INF-File: '", pwszInf, "', Section: '", pwszSection, "' ...\r\n"); 893 #ifdef RT_ARCH_X86 894 InstallWinVerifyTrustInterceptorInSetupApi(); 895 #endif 591 896 592 897 UINT uErrorLine = 0; … … 985 1290 986 1291 /* Make sure we're on NT4 before continuing: */ 987 OSVERSIONINFO VerInfo = { sizeof(VerInfo) };988 GetVersionEx (&VerInfo);1292 OSVERSIONINFOW VerInfo = { sizeof(VerInfo) }; 1293 GetVersionExW(&VerInfo); 989 1294 if ( VerInfo.dwPlatformId != VER_PLATFORM_WIN32_NT 990 1295 || VerInfo.dwMajorVersion != 4) 991 return ErrorMsgSUSUS("This command is only for NT 4. GetVersionEx reports ", VerInfo.dwMajorVersion, ".",1296 return ErrorMsgSUSUS("This command is only for NT 4. GetVersionExW reports ", VerInfo.dwMajorVersion, ".", 992 1297 VerInfo.dwMinorVersion, "."); 993 1298
Note:
See TracChangeset
for help on using the changeset viewer.