VirtualBox

Changeset 106239 in vbox


Ignore:
Timestamp:
Oct 8, 2024 2:47:35 PM (4 months ago)
Author:
vboxsync
Message:

Additions/NT/Installer: Check that what installer selector is about to launch looks like an installer and is correctly signed with the build certificate. This needs more testing. bugref:10771

Location:
trunk/src/VBox/Additions/WINNT/Installer/Loader
Files:
2 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/Installer/Loader/Makefile.kmk

    r106061 r106239  
    6969
    7070
     71# Signing certificate.
     72ifdef VBOX_SIGNING_MODE
     73 if1of ($(VBOX_SIGNING_MODE), test)
     74  # If signing the installer, the loader stub must be signed as well.
     75  # Hack alert! Using POST_CMDS.win to place the signing after VBoxPeSetVersion.
     76  VBoxWindowsAdditions_POST_CMDS.win = $(call VBOX_SIGN_IMAGE_FN,$(out),,2)
     77  VBoxWindowsAdditions_ORDERDEPS     = $(VBOX_SIGN_IMAGE_ORDERDEPS)
     78 endif
     79 VBoxWindowsAdditions_DEFS         += VBOX_SIGNING_MODE
     80 VBoxWindowsAdditions_INCS         += $(VBoxWindowsAdditions_0_OUTDIR)
     81 VBoxWindowsAdditions_INTERMEDIATES = $(VBoxWindowsAdditions_0_OUTDIR)/BuildCert.h
     82
     83 # Dummy signed program that we can extract the signature from.
     84 BLDPROGS += bldAddSignedDummy
     85 bldAddSignedDummy_TEMPLATE := VBoxBldProg
     86 bldAddSignedDummy_SOURCES  := bldAddSignedDummy.cpp
     87 bldAddSignedDummy_ORDERDEPS = $(VBOX_SIGN_IMAGE_ORDERDEPS)
     88 bldAddSignedDummy_POST_CMDS = $(call VBOX_SIGN_IMAGE_FN,$(out),,2)
     89
     90 # The certificate include file.
     91 $$(VBoxWindowsAdditions_0_OUTDIR)/BuildCert.h: \
     92                $(VBOX_BIN2C) \
     93                $(VBOX_RTSIGNTOOL) \
     94                $$(bldAddSignedDummy_1_TARGET) \
     95                | $$(dir $$@)
     96        $(QUIET)$(RM) -f -- "$@" "[email protected]"
     97        $(VBOX_RTSIGNTOOL) extract-exe-signer-cert --exe "$(bldAddSignedDummy_1_TARGET)" --output "[email protected]" --der
     98        $(VBOX_BIN2C) -ascii --append BuildCert "[email protected]" "$@"
     99        $(QUIET)$(RM) -f -- [email protected]
     100
     101 OTHER_CLEAN += $(VBOX_SUP_WIN_CERTS_FILE)
     102
     103endif # VBOX_SIGNING_MODE
     104
     105
    71106include $(FILE_KBUILD_SUB_FOOTER)
    72107
  • trunk/src/VBox/Additions/WINNT/Installer/Loader/VBoxWindowsAdditions.cpp

    r106061 r106239  
    3232*   Header Files                                                                                                                 *
    3333*********************************************************************************************************************************/
     34#define UNICODE                     /* For resource related macros. */
    3435#include <iprt/cdefs.h>
    3536#include <iprt/win/windows.h>
     37#include <Wintrust.h>
     38#include <Softpub.h>
    3639#ifndef ERROR_ELEVATION_REQUIRED    /* Windows Vista and later. */
    3740# define ERROR_ELEVATION_REQUIRED  740
     
    4346#include "NoCrtOutput.h"
    4447
     48#ifdef VBOX_SIGNING_MODE
     49# include "BuildCert.h"
     50#endif
     51
     52
     53#ifdef VBOX_SIGNING_MODE
     54
     55/**
     56 * Checks the file signatures of both this stub program and the actual installer
     57 * binary, making sure they use the same certificate as at build time and that
     58 * the signature verifies correctly.
     59 *
     60 * @returns 0 on success, non-zero exit code on failure.
     61 */
     62static int CheckFileSignatures(wchar_t const *pwszExePath, HANDLE hFileExe, wchar_t const *pwszSelfPath, HANDLE hFileSelf)
     63{
     64    /*
     65     * Check the OS version (bypassing shims).
     66     *
     67     * The RtlGetVersion API was added in windows 2000, so it's precense is a
     68     * provides a minimum OS version indicator already.
     69     */
     70    LONG (__stdcall *pfnRtlGetVersion)(OSVERSIONINFOEXW *);
     71    *(FARPROC *)&pfnRtlGetVersion = GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlGetVersion");
     72    if (!pfnRtlGetVersion)
     73    {
     74        /* double check it. */
     75        DWORD const dwVersion = GetVersion();
     76        if ((dwVersion & 0xff) < 5)
     77            return 0;
     78        return ErrorMsgRcSUS(40, "RtlGetVersion not present while Windows version is 5.0 or higher (", dwVersion, ")");
     79    }
     80    OSVERSIONINFOEXW WinOsInfoEx = { sizeof(WinOsInfoEx) };
     81    NTSTATUS const   rcNt        = pfnRtlGetVersion(&WinOsInfoEx);
     82    if (!RT_SUCCESS(rcNt))
     83        return ErrorMsgRcSU(41, "RtlGetVersion failed: ", rcNt);
     84
     85    /* Skip both of these checks if pre-XP. */
     86    if (   (WinOsInfoEx.dwMajorVersion == 5 && WinOsInfoEx.dwMinorVersion < 1)
     87        || WinOsInfoEx.dwMajorVersion < 4)
     88        return 0;
     89
     90    /*
     91     * We need to find the system32 directory to load the WinVerifyTrust API.
     92     */
     93    static wchar_t const s_wszSlashWinTrustDll[] = L"\\Wintrust.dll";
     94
     95    /* Call GetSystemWindowsDirectoryW/GetSystemDirectoryW. */
     96    wchar_t wszSysDll[MAX_PATH + sizeof(s_wszSlashWinTrustDll)] = { 0 };
     97    UINT const cwcSystem32 = GetSystemDirectoryW(wszSysDll, MAX_PATH);
     98    if (!cwcSystem32 || cwcSystem32 >= MAX_PATH)
     99        return ErrorMsgRc(42, "GetSystemDirectoryW failed");
     100
     101    /* Load it: */
     102    memcpy(&wszSysDll[cwcSystem32], s_wszSlashWinTrustDll, sizeof(s_wszSlashWinTrustDll));
     103    DWORD   fLoadFlags      = LOAD_LIBRARY_SEARCH_SYSTEM32;
     104    HMODULE hModWinTrustDll = LoadLibraryExW(wszSysDll, NULL, fLoadFlags);
     105    if (!hModWinTrustDll && GetLastError() == ERROR_INVALID_PARAMETER)
     106    {
     107        fLoadFlags = 0;
     108        hModWinTrustDll = LoadLibraryExW(wszSysDll, NULL, fLoadFlags);
     109    }
     110    if (!hModWinTrustDll)
     111        return ErrorMsgRcSWSU(43, "Failed to load '", wszSysDll, "': ", GetLastError());
     112
     113    /* Resolve API: */
     114    decltype(WinVerifyTrust) * const pfnWinVerifyTrust
     115        = (decltype(WinVerifyTrust) *)GetProcAddress(hModWinTrustDll, "WinVerifyTrust");
     116    if (!pfnWinVerifyTrust)
     117        return ErrorMsgRc(44, "WinVerifyTrust not found");
     118
     119    /*
     120     * We also need the Crypt32.dll for CryptQueryObject and CryptMsgGetParam.
     121     */
     122    /* Load it: */
     123    static wchar_t const s_wszSlashCrypt32Dll[] = L"\\Crypt32.dll";
     124    AssertCompile(sizeof(s_wszSlashCrypt32Dll) <= sizeof(s_wszSlashWinTrustDll));
     125    memcpy(&wszSysDll[cwcSystem32], s_wszSlashCrypt32Dll, sizeof(s_wszSlashCrypt32Dll));
     126    HMODULE const hModCrypt32Dll = LoadLibraryExW(wszSysDll, NULL, fLoadFlags);
     127    if (!hModCrypt32Dll)
     128        return ErrorMsgRcSWSU(45, "Failed to load '", wszSysDll, "': ", GetLastError());
     129
     130    /* Resolve APIs: */
     131    decltype(CryptQueryObject) * const pfnCryptQueryObject
     132        = (decltype(CryptQueryObject) *)GetProcAddress(hModCrypt32Dll, "CryptQueryObject");
     133    if (!pfnCryptQueryObject)
     134        return ErrorMsgRc(46, "CryptQueryObject not found");
     135
     136    decltype(CryptMsgClose) * const    pfnCryptMsgClose
     137        = (decltype(CryptMsgClose) *)GetProcAddress(hModCrypt32Dll, "CryptMsgClose");
     138    if (!pfnCryptQueryObject)
     139        return ErrorMsgRc(47, "CryptMsgClose not found");
     140
     141    decltype(CryptMsgGetParam) * const pfnCryptMsgGetParam
     142        = (decltype(CryptMsgGetParam) *)GetProcAddress(hModCrypt32Dll, "CryptMsgGetParam");
     143    if (!pfnCryptQueryObject)
     144        return ErrorMsgRc(48, "CryptMsgGetParam not found");
     145
     146    /*
     147     * We'll verify the primary signer certificate first as that's something that
     148     * should work even if SHA-256 isn't supported by the Windows crypto code.
     149     */
     150    struct
     151    {
     152        HANDLE          hFile;
     153        wchar_t const  *pwszFile;
     154
     155        DWORD           fEncoding;
     156        DWORD           dwContentType;
     157        DWORD           dwFormatType;
     158        HCERTSTORE      hCertStore;
     159        HCRYPTMSG       hMsg;
     160
     161        DWORD           cbCert;
     162        uint8_t        *pbCert;
     163    } aExes[] =
     164    {
     165        { hFileSelf, pwszSelfPath,   0, 0, 0, NULL, NULL,   0, NULL },
     166        { hFileExe,  pwszExePath,    0, 0, 0, NULL, NULL,   0, NULL },
     167    };
     168
     169    HANDLE const hHeap  = GetProcessHeap();
     170    int          rcExit = 0;
     171    for (unsigned i = 0; i < RT_ELEMENTS(aExes) && rcExit == 0; i++)
     172    {
     173        if (!pfnCryptQueryObject(CERT_QUERY_OBJECT_FILE,
     174                                 aExes[i].pwszFile,
     175                                 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
     176                                 CERT_QUERY_FORMAT_FLAG_BINARY,
     177                                 0 /*fFlags*/,
     178                                 &aExes[i].fEncoding,
     179                                 &aExes[i].dwContentType,
     180                                 &aExes[i].dwFormatType,
     181                                 &aExes[i].hCertStore,
     182                                 &aExes[i].hMsg,
     183                                 NULL /*ppvContext*/))
     184            rcExit = ErrorMsgRcSWSU(50 + i*4, "CryptQueryObject/FILE on '", aExes[i].pwszFile, "': ", GetLastError());
     185        else if (!pfnCryptMsgGetParam(aExes[i].hMsg, CMSG_CERT_PARAM, 0, NULL, &aExes[i].cbCert))
     186            rcExit = ErrorMsgRcSWSU(51 + i*4, "CryptMsgGetParam/CMSG_CERT_PARAM/size failed on '",
     187                                    aExes[i].pwszFile, "': ", GetLastError());
     188        else
     189        {
     190            DWORD const cbCert = aExes[i].cbCert;
     191            aExes[i].pbCert = (uint8_t *)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, cbCert);
     192            if (!aExes[i].pbCert)
     193                rcExit = ErrorMsgRcSUS(52 + i*4, "Out of memory (", cbCert, " bytes) for signing certificate information");
     194            else if (!pfnCryptMsgGetParam(aExes[i].hMsg, CMSG_CERT_PARAM, 0, aExes[i].pbCert, &aExes[i].cbCert))
     195                rcExit = ErrorMsgRcSWSU(53 + i*4, "CryptMsgGetParam/CMSG_CERT_PARAM failed on '", aExes[i].pwszFile, "': ",
     196                                        GetLastError());
     197        }
     198    }
     199
     200    if (rcExit == 0)
     201    {
     202        /* Do the two match? */
     203        if (   aExes[0].cbCert != aExes[1].cbCert
     204            || memcmp(aExes[0].pbCert, aExes[1].pbCert, aExes[0].cbCert) != 0)
     205            rcExit = ErrorMsgRcSWS(58, "The certificate on '", pwszExePath, "' does not match.");
     206        /* The two match, now do they match the one we're expecting to use? */
     207        else if (   aExes[0].cbCert != g_cbBuildCert
     208                 || memcmp(aExes[0].pbCert, g_abBuildCert, g_cbBuildCert) != 0)
     209            rcExit = ErrorMsgRcSWS(59, "The signing certificate of '", pwszExePath, "' differs from the build certificate");
     210        /* else: it all looks fine */
     211    }
     212
     213    /* cleanup */
     214    for (unsigned i = 0; i < RT_ELEMENTS(aExes); i++)
     215    {
     216        if (aExes[i].pbCert)
     217        {
     218            HeapFree(hHeap, 0, aExes[i].pbCert);
     219            aExes[i].pbCert = NULL;
     220        }
     221        if (aExes[i].hMsg)
     222        {
     223            pfnCryptMsgClose(aExes[i].hMsg);
     224            aExes[i].hMsg = NULL;
     225        }
     226    }
     227    if (rcExit != 0)
     228        return rcExit;
     229
     230    /*
     231     * ASSUMING we're using SHA-256 for signing, we do a windows OS cutoff at Windows 7.
     232     * For Windows Vista and older we skip this step.
     233     */
     234    if (   (WinOsInfoEx.dwMajorVersion == 6 && WinOsInfoEx.dwMinorVersion == 0)
     235        || WinOsInfoEx.dwMajorVersion < 6)
     236        return 0;
     237
     238    /*
     239     * Construct input WinVerifyTrust parameters and call it on each of the executables in turn.
     240     * This code was borrowed from SUPHardNt.
     241     */
     242    for (unsigned i = 0; i < RT_ELEMENTS(aExes); i++)
     243    {
     244        WINTRUST_FILE_INFO FileInfo = { 0 };
     245        FileInfo.cbStruct      = sizeof(FileInfo);
     246        FileInfo.pcwszFilePath = aExes[i].pwszFile;
     247        FileInfo.hFile         = aExes[i].hFile;
     248
     249        GUID PolicyActionGuid = WINTRUST_ACTION_GENERIC_VERIFY_V2;
     250
     251        WINTRUST_DATA TrustData = { 0 };
     252        TrustData.cbStruct            = sizeof(TrustData);
     253        TrustData.fdwRevocationChecks = WTD_REVOKE_NONE;  /* Keep simple for now. */
     254        TrustData.dwStateAction       = WTD_STATEACTION_VERIFY;
     255        TrustData.dwUIChoice          = WTD_UI_NONE;
     256        TrustData.dwProvFlags         = 0;
     257        if (WinOsInfoEx.dwMajorVersion >= 6)
     258            TrustData.dwProvFlags     = WTD_CACHE_ONLY_URL_RETRIEVAL;
     259        else
     260            TrustData.dwProvFlags     = WTD_REVOCATION_CHECK_NONE;
     261        TrustData.dwUnionChoice       = WTD_CHOICE_FILE;
     262        TrustData.pFile               = &FileInfo;
     263
     264        HRESULT hrc = pfnWinVerifyTrust(NULL /*hwnd*/, &PolicyActionGuid, &TrustData);
     265        if (hrc != S_OK)
     266        {
     267            /* Translate the eror constant */
     268            const char *pszErrConst = NULL;
     269            switch (hrc)
     270            {
     271                case TRUST_E_SYSTEM_ERROR:            pszErrConst = "TRUST_E_SYSTEM_ERROR";         break;
     272                case TRUST_E_NO_SIGNER_CERT:          pszErrConst = "TRUST_E_NO_SIGNER_CERT";       break;
     273                case TRUST_E_COUNTER_SIGNER:          pszErrConst = "TRUST_E_COUNTER_SIGNER";       break;
     274                case TRUST_E_CERT_SIGNATURE:          pszErrConst = "TRUST_E_CERT_SIGNATURE";       break;
     275                case TRUST_E_TIME_STAMP:              pszErrConst = "TRUST_E_TIME_STAMP";           break;
     276                case TRUST_E_BAD_DIGEST:              pszErrConst = "TRUST_E_BAD_DIGEST";           break;
     277                case TRUST_E_BASIC_CONSTRAINTS:       pszErrConst = "TRUST_E_BASIC_CONSTRAINTS";    break;
     278                case TRUST_E_FINANCIAL_CRITERIA:      pszErrConst = "TRUST_E_FINANCIAL_CRITERIA";   break;
     279                case TRUST_E_PROVIDER_UNKNOWN:        pszErrConst = "TRUST_E_PROVIDER_UNKNOWN";     break;
     280                case TRUST_E_ACTION_UNKNOWN:          pszErrConst = "TRUST_E_ACTION_UNKNOWN";       break;
     281                case TRUST_E_SUBJECT_FORM_UNKNOWN:    pszErrConst = "TRUST_E_SUBJECT_FORM_UNKNOWN"; break;
     282                case TRUST_E_SUBJECT_NOT_TRUSTED:     pszErrConst = "TRUST_E_SUBJECT_NOT_TRUSTED";  break;
     283                case TRUST_E_NOSIGNATURE:             pszErrConst = "TRUST_E_NOSIGNATURE";          break;
     284                case TRUST_E_FAIL:                    pszErrConst = "TRUST_E_FAIL";                 break;
     285                case TRUST_E_EXPLICIT_DISTRUST:       pszErrConst = "TRUST_E_EXPLICIT_DISTRUST";    break;
     286                case CERT_E_EXPIRED:                  pszErrConst = "CERT_E_EXPIRED";               break;
     287                case CERT_E_VALIDITYPERIODNESTING:    pszErrConst = "CERT_E_VALIDITYPERIODNESTING"; break;
     288                case CERT_E_ROLE:                     pszErrConst = "CERT_E_ROLE";                  break;
     289                case CERT_E_PATHLENCONST:             pszErrConst = "CERT_E_PATHLENCONST";          break;
     290                case CERT_E_CRITICAL:                 pszErrConst = "CERT_E_CRITICAL";              break;
     291                case CERT_E_PURPOSE:                  pszErrConst = "CERT_E_PURPOSE";               break;
     292                case CERT_E_ISSUERCHAINING:           pszErrConst = "CERT_E_ISSUERCHAINING";        break;
     293                case CERT_E_MALFORMED:                pszErrConst = "CERT_E_MALFORMED";             break;
     294                case CERT_E_UNTRUSTEDROOT:            pszErrConst = "CERT_E_UNTRUSTEDROOT";         break;
     295                case CERT_E_CHAINING:                 pszErrConst = "CERT_E_CHAINING";              break;
     296                case CERT_E_REVOKED:                  pszErrConst = "CERT_E_REVOKED";               break;
     297                case CERT_E_UNTRUSTEDTESTROOT:        pszErrConst = "CERT_E_UNTRUSTEDTESTROOT";     break;
     298                case CERT_E_REVOCATION_FAILURE:       pszErrConst = "CERT_E_REVOCATION_FAILURE";    break;
     299                case CERT_E_CN_NO_MATCH:              pszErrConst = "CERT_E_CN_NO_MATCH";           break;
     300                case CERT_E_WRONG_USAGE:              pszErrConst = "CERT_E_WRONG_USAGE";           break;
     301                case CERT_E_UNTRUSTEDCA:              pszErrConst = "CERT_E_UNTRUSTEDCA";           break;
     302                case CERT_E_INVALID_POLICY:           pszErrConst = "CERT_E_INVALID_POLICY";        break;
     303                case CERT_E_INVALID_NAME:             pszErrConst = "CERT_E_INVALID_NAME";          break;
     304                case CRYPT_E_FILE_ERROR:              pszErrConst = "CRYPT_E_FILE_ERROR";           break;
     305                case CRYPT_E_REVOKED:                 pszErrConst = "CRYPT_E_REVOKED";              break;
     306            }
     307            if (pszErrConst)
     308                rcExit = ErrorMsgRcSWSS(60 + i, "WinVerifyTrust failed on '", pwszExePath, "': ", pszErrConst);
     309            else
     310                rcExit = ErrorMsgRcSWSX(60 + i, "WinVerifyTrust failed on '", pwszExePath, "': ", hrc);
     311        }
     312
     313        /* clean up state data. */
     314        TrustData.dwStateAction = WTD_STATEACTION_CLOSE;
     315        FileInfo.hFile          = NULL;
     316        hrc = pfnWinVerifyTrust(NULL /*hwnd*/, &PolicyActionGuid, &TrustData);
     317    }
     318
     319    return rcExit;
     320}
     321
     322#endif /* VBOX_SIGNING_MODE */
     323
     324/**
     325 * strstr for haystacks w/o null termination.
     326 */
     327static const char *MyStrStrN(const char *pchHaystack, size_t cbHaystack, const char *pszNeedle)
     328{
     329    size_t const cchNeedle = strlen(pszNeedle);
     330    char const   chFirst   = *pszNeedle;
     331    if (cbHaystack >= cchNeedle)
     332    {
     333        cbHaystack -= cchNeedle - 1;
     334        while (cbHaystack > 0)
     335        {
     336            const char *pchHit = (const char *)memchr(pchHaystack, chFirst, cbHaystack);
     337            if (pchHit)
     338            {
     339                if (memcmp(pchHit, pszNeedle, cchNeedle) == 0)
     340                    return pchHit;
     341                pchHit++;
     342                cbHaystack -= pchHit - pchHaystack;
     343                pchHaystack = pchHit;
     344            }
     345            else
     346                break;
     347        }
     348    }
     349    return NULL;
     350}
     351
     352/**
     353 * Check that the executable file is "related" the one for the current process.
     354 */
     355static int CheckThatFileIsRelated(wchar_t const *pwszExePath, wchar_t const *pwszSelfPath)
     356{
     357    /*
     358     * Start by checking version info.
     359     */
     360    /*
     361     * Query the version info for the files:
     362     */
     363    DWORD const cbExeVerInfo  = GetFileVersionInfoSizeW(pwszExePath, NULL);
     364    if (!cbExeVerInfo)
     365        return ErrorMsgRcSWSU(20, "GetFileVersionInfoSizeW failed on '", pwszExePath, "': ", GetLastError());
     366
     367    DWORD const cbSelfVerInfo = GetFileVersionInfoSizeW(pwszSelfPath, NULL);
     368    if (!cbSelfVerInfo)
     369        return ErrorMsgRcSWSU(21, "GetFileVersionInfoSizeW failed on '", pwszSelfPath, "': ", GetLastError());
     370
     371    HANDLE const hHeap         = GetProcessHeap();
     372    DWORD const  cbBothVerInfo = RT_ALIGN_32(cbExeVerInfo, 64) + RT_ALIGN_32(cbSelfVerInfo, 64);
     373    void * const pvExeVerInfo  = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, cbBothVerInfo);
     374    void * const pvSelfVerInfo = (uint8_t *)pvExeVerInfo + RT_ALIGN_32(cbExeVerInfo, 64);
     375    if (!pvExeVerInfo)
     376        return ErrorMsgRcSUS(22, "Out of memory (", cbBothVerInfo, " bytes) for version info");
     377
     378    int rcExit = 0;
     379    if (!GetFileVersionInfoW(pwszExePath, 0, cbExeVerInfo, pvExeVerInfo))
     380        rcExit = ErrorMsgRcSWSU(23, "GetFileVersionInfoW failed on '", pwszExePath, "': ", GetLastError());
     381    else if (!GetFileVersionInfoW(pwszSelfPath, 0, cbSelfVerInfo, pvSelfVerInfo))
     382        rcExit = ErrorMsgRcSWSU(24, "GetFileVersionInfoW failed on '", pwszSelfPath, "': ", GetLastError());
     383
     384    /*
     385     * Compare the product and company strings, which should be identical.
     386     */
     387    static struct
     388    {
     389        wchar_t const *pwszQueryItem;
     390        const char    *pszQueryErrorMsg1;
     391        const char    *pszCompareErrorMsg1;
     392    } const s_aIdenticalItems[] =
     393    {
     394        { L"\\StringFileInfo\\040904b0\\ProductName", "VerQueryValueW/ProductName failed on '", "Product string of '" },
     395        { L"\\StringFileInfo\\040904b0\\CompanyName", "VerQueryValueW/CompanyName failed on '", "Company string of '" },
     396    };
     397
     398    for (unsigned i = 0; i < RT_ELEMENTS(s_aIdenticalItems) && rcExit == 0; i++)
     399    {
     400        void *pvExeInfoItem  = NULL;
     401        UINT  cbExeInfoItem  = 0;
     402        void *pvSelfInfoItem = NULL;
     403        UINT  cbSelfInfoItem = 0;
     404        if (!VerQueryValueW(pvExeVerInfo, s_aIdenticalItems[i].pwszQueryItem, &pvExeInfoItem, &cbExeInfoItem))
     405            rcExit = ErrorMsgRcSWSU(25 + i*3, s_aIdenticalItems[i].pszQueryErrorMsg1 , pwszExePath, "': ", GetLastError());
     406        else  if (!VerQueryValueW(pvSelfVerInfo, s_aIdenticalItems[i].pwszQueryItem, &pvSelfInfoItem, &cbSelfInfoItem))
     407            rcExit = ErrorMsgRcSWSU(26 + i*3, s_aIdenticalItems[i].pszQueryErrorMsg1, pwszSelfPath, "': ", GetLastError());
     408        else if (   cbExeInfoItem != cbSelfInfoItem
     409                 || memcmp(pvExeInfoItem, pvSelfInfoItem, cbSelfInfoItem) != 0)
     410            rcExit = ErrorMsgRcSWS(27 + i*3, s_aIdenticalItems[i].pszCompareErrorMsg1, pwszExePath, "' does not match");
     411    }
     412                 
     413    HeapFree(hHeap, 0, pvExeVerInfo);
     414
     415    /*
     416     * Check that the file has a manifest that looks like it may belong to
     417     * an NSIS installer.
     418     */
     419    if (rcExit == 0)
     420    {
     421        HMODULE hMod = LoadLibraryExW(pwszExePath, NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE);
     422        if (!hMod && GetLastError() == ERROR_INVALID_PARAMETER)
     423            hMod     = LoadLibraryExW(pwszExePath, NULL, LOAD_LIBRARY_AS_DATAFILE);
     424        if (hMod)
     425        {
     426            HRSRC const hRsrcMt = FindResourceExW(hMod, RT_MANIFEST, MAKEINTRESOURCEW(1),
     427                                                  MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL));
     428            if (hRsrcMt)
     429            {
     430                DWORD const   cbManifest = SizeofResource(hMod, hRsrcMt);
     431                HGLOBAL const hGlobalMt  = LoadResource(hMod, hRsrcMt);
     432                if (hGlobalMt)
     433                {
     434                    const char * const pchManifest = (const char *)LockResource(hGlobalMt);
     435                    if (pchManifest)
     436                    {
     437                        /* Just look for a few strings we expect to always find the manifest. */
     438                        if (!MyStrStrN(pchManifest, cbManifest, "Nullsoft.NSIS.exehead"))
     439                            rcExit = 36;
     440                        else if (!MyStrStrN(pchManifest, cbManifest, "requestedPrivileges"))
     441                            rcExit = 37;
     442                        else if (!MyStrStrN(pchManifest, cbManifest, "highestAvailable"))
     443                            rcExit = 38;
     444                        if (rcExit)
     445                            rcExit = ErrorMsgRcSWSU(rcExit, "Manifest check of '", pwszExePath, "' failed: ", rcExit);
     446                    }
     447                    else
     448                        rcExit = ErrorMsgRc(35, "LockResource/Manifest failed");
     449                }
     450                else
     451                    rcExit = ErrorMsgRcSU(34, "LoadResource/Manifest failed: ", GetLastError());
     452            }
     453            else
     454                rcExit = ErrorMsgRcSU(33, "FindResourceExW/Manifest failed: ", GetLastError());
     455        }
     456        else
     457            rcExit = ErrorMsgRcSWSU(32, "LoadLibraryExW of '", pwszExePath, "' as datafile failed: ", GetLastError());
     458    }
     459
     460    return rcExit;
     461}
    45462
    46463static BOOL IsWow64(void)
     
    137554    if (cwcExePath == 0 || cwcExePath >= sizeof(wszExePath))
    138555        return ErrorMsgRcLastErrSUR(13, "GetModuleFileNameW failed: ", cwcExePath);
     556
     557    WCHAR wszSelfPath[MAX_PATH];
     558    memcpy(wszSelfPath, wszExePath, sizeof(wszSelfPath));
    139559
    140560    /*
     
    221641
    222642    /*
     643     * Open the executable for this process.
     644     */
     645    HANDLE hFileSelf = CreateFileW(wszSelfPath, GENERIC_READ, FILE_SHARE_READ, NULL /*pSecAttr*/, OPEN_EXISTING,
     646                                   FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
     647    if (hFileSelf == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_PARAMETER)
     648        hFileSelf    = CreateFileW(wszSelfPath, GENERIC_READ, FILE_SHARE_READ, NULL /*pSecAttr*/, OPEN_EXISTING,
     649                                   FILE_ATTRIBUTE_NORMAL, NULL);
     650    if (hFileSelf == INVALID_HANDLE_VALUE)
     651    {
     652        if (GetLastError() == ERROR_FILE_NOT_FOUND)
     653            return ErrorMsgRcSW(17, "File not found: ", wszSelfPath);
     654        return ErrorMsgRcSWSU(17, "Error opening '", wszSelfPath, "' for reading: ", GetLastError());
     655    }
     656
     657
     658    /*
     659     * Open the file we're about to execute.
     660     */
     661    HANDLE hFileExe = CreateFileW(wszExePath, GENERIC_READ, FILE_SHARE_READ, NULL /*pSecAttr*/, OPEN_EXISTING,
     662                                  FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
     663    if (hFileExe == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_PARAMETER)
     664        hFileExe    = CreateFileW(wszExePath, GENERIC_READ, FILE_SHARE_READ, NULL /*pSecAttr*/, OPEN_EXISTING,
     665                                  FILE_ATTRIBUTE_NORMAL, NULL);
     666    if (hFileExe == INVALID_HANDLE_VALUE)
     667    {
     668        if (GetLastError() == ERROR_FILE_NOT_FOUND)
     669            return ErrorMsgRcSW(18, "File not found: ", wszExePath);
     670        return ErrorMsgRcSWSU(18, "Error opening '", wszExePath, "' for reading: ", GetLastError());
     671    }
     672
     673    /*
     674     * Check that the file we're about to launch is related to us and safe to start.
     675     */
     676    int rcExit = CheckThatFileIsRelated(wszExePath, wszSelfPath);
     677    if (rcExit != 0)
     678        return rcExit;
     679
     680#ifdef VBOX_SIGNING_MODE
     681    rcExit = CheckFileSignatures(wszExePath, hFileExe, wszSelfPath, hFileSelf);
     682    if (rcExit != 0)
     683        return rcExit;
     684#endif
     685
     686    /*
    223687     * Start the process.
    224688     */
    225     int                 rcExit      = 0;
    226689    STARTUPINFOW        StartupInfo = { sizeof(StartupInfo), 0 };
    227690    PROCESS_INFORMATION ProcInfo    = { 0 };
  • trunk/src/VBox/Additions/WINNT/Installer/Loader/bldAddSignedDummy.cpp

    r106221 r106239  
    11/* $Id$ */
    22/** @file
    3  * VirtualBox Support Library - Dummy program for extracting signing certificate.
     3 * VBoxWindowsAdditions - Dummy program for extracting signing certificate.
    44 */
    55
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette