vbox的更動 51770 路徑 trunk/src/VBox/Runtime/common/ldr/ldrPE.cpp
圖例:
- 未更動
- 新增
- 刪除
-
trunk
- 屬性 svn:mergeinfo 變動
/branches/bird/hardenedwindows (已新增) 已合併: 92692-94610
- 屬性 svn:mergeinfo 變動
-
trunk/src/VBox
- 屬性 svn:mergeinfo 變動
/branches/bird/hardenedwindows/src/VBox (已新增) 已合併: 92692-94610
- 屬性 svn:mergeinfo 變動
-
trunk/src/VBox/Runtime/common/ldr/ldrPE.cpp
r49044 r51770 33 33 #include "internal/iprt.h" 34 34 35 #include <iprt/alloc.h>36 35 #include <iprt/assert.h> 36 #include <iprt/asm.h> 37 #include <iprt/err.h> 37 38 #include <iprt/log.h> 39 #include <iprt/md5.h> 40 #include <iprt/mem.h> 38 41 #include <iprt/path.h> 42 #include <iprt/sha.h> 39 43 #include <iprt/string.h> 40 #include <iprt/err.h> 44 #ifndef IPRT_WITHOUT_LDR_VERIFY 45 # include <iprt/crypto/pkcs7.h> 46 # include <iprt/crypto/spc.h> 47 # include <iprt/crypto/x509.h> 48 #endif 41 49 #include <iprt/formats/codeview.h> 42 50 #include "internal/ldrPE.h" … … 53 61 */ 54 62 #define PE_RVA2TYPE(pvBits, rva, type) ((type) ((uintptr_t)pvBits + (uintptr_t)(rva)) ) 63 64 /** The max size of the security directory. */ 65 #ifdef IN_RING3 66 # define RTLDRMODPE_MAX_SECURITY_DIR_SIZE _4M 67 #else 68 # define RTLDRMODPE_MAX_SECURITY_DIR_SIZE _1M 69 #endif 55 70 56 71 … … 92 107 /** The image timestamp. */ 93 108 uint32_t uTimestamp; 109 /** Set if the image is 64-bit, clear if 32-bit. */ 110 bool f64Bit; 94 111 /** The import data directory entry. */ 95 112 IMAGE_DATA_DIRECTORY ImportDir; … … 100 117 /** The debug directory entry. */ 101 118 IMAGE_DATA_DIRECTORY DebugDir; 102 } RTLDRMODPE, *PRTLDRMODPE; 119 /** The security directory entry. */ 120 IMAGE_DATA_DIRECTORY SecurityDir; 121 122 /** Offset of the first PKCS \#7 SignedData signature if present. */ 123 uint32_t offPkcs7SignedData; 124 /** Size of the first PKCS \#7 SignedData. */ 125 uint32_t cbPkcs7SignedData; 126 127 /** Copy of the optional header field DllCharacteristics. */ 128 uint16_t fDllCharacteristics; 129 } RTLDRMODPE; 130 /** Pointer to the instance data for a PE loader module. */ 131 typedef RTLDRMODPE *PRTLDRMODPE; 132 103 133 104 134 /** … … 132 162 133 163 164 /** 165 * PE hash context union. 166 */ 167 typedef union RTLDRPEHASHCTXUNION 168 { 169 RTSHA512CONTEXT Sha512; 170 RTSHA256CONTEXT Sha256; 171 RTSHA1CONTEXT Sha1; 172 RTMD5CONTEXT Md5; 173 } RTLDRPEHASHCTXUNION; 174 /** Pointer to a PE hash context union. */ 175 typedef RTLDRPEHASHCTXUNION *PRTLDRPEHASHCTXUNION; 176 177 178 /** 179 * PE hash digests 180 */ 181 typedef union RTLDRPEHASHRESUNION 182 { 183 uint8_t abSha512[RTSHA512_HASH_SIZE]; 184 uint8_t abSha256[RTSHA256_HASH_SIZE]; 185 uint8_t abSha1[RTSHA1_HASH_SIZE]; 186 uint8_t abMd5[RTMD5_HASH_SIZE]; 187 } RTLDRPEHASHRESUNION; 188 /** Pointer to a PE hash work set. */ 189 typedef RTLDRPEHASHRESUNION *PRTLDRPEHASHRESUNION; 190 191 /** 192 * Special places to watch out for when hashing a PE image. 193 */ 194 typedef struct RTLDRPEHASHSPECIALS 195 { 196 uint32_t cbToHash; 197 uint32_t offCksum; 198 uint32_t cbCksum; 199 uint32_t offSecDir; 200 uint32_t cbSecDir; 201 uint32_t offEndSpecial; 202 } RTLDRPEHASHSPECIALS; 203 /** Pointer to the structure with the special hash places. */ 204 typedef RTLDRPEHASHSPECIALS *PRTLDRPEHASHSPECIALS; 205 206 207 #ifndef IPRT_WITHOUT_LDR_VERIFY 208 /** 209 * Parsed signature data. 210 */ 211 typedef struct RTLDRPESIGNATURE 212 { 213 /** The outer content info wrapper. */ 214 RTCRPKCS7CONTENTINFO ContentInfo; 215 /** Pointer to the decoded SignedData inside the ContentInfo member. */ 216 PRTCRPKCS7SIGNEDDATA pSignedData; 217 /** Pointer to the indirect data content. */ 218 PRTCRSPCINDIRECTDATACONTENT pIndData; 219 /** The digest type employed by the signature. */ 220 RTDIGESTTYPE enmDigest; 221 222 /** Pointer to the raw signatures. This is allocated in the continuation of 223 * this structure to keep things simple. The size is given by the security 224 * export directory. */ 225 WIN_CERTIFICATE const *pRawData; 226 227 /** Hash scratch data. */ 228 RTLDRPEHASHCTXUNION HashCtx; 229 /** Hash result. */ 230 RTLDRPEHASHRESUNION HashRes; 231 } RTLDRPESIGNATURE; 232 /** Pointed to SigneData parsing stat and output. */ 233 typedef RTLDRPESIGNATURE *PRTLDRPESIGNATURE; 234 #endif 235 236 134 237 /******************************************************************************* 135 238 * Internal Functions * … … 251 354 { 252 355 if ((RTFOFF)offFile + cbToRead > cbFile) 253 cbToRead = cbFile - (RTFOFF)offFile;356 cbToRead = (uint32_t)(cbFile - (RTFOFF)offFile); 254 357 int rc = pThis->Core.pReader->pfnRead(pThis->Core.pReader, pbMem, cbToRead, offFile); 255 358 if (RT_FAILURE(rc)) … … 331 434 if (uRva == NIL_RTLDRADDR || uRva > pThis->cbImage) 332 435 { 333 if (offFile < 0 )436 if (offFile < 0 || offFile >= UINT32_MAX) 334 437 return VERR_INVALID_PARAMETER; 335 return rtldrPEReadPartFromFile(pThis, offFile, cbMem, ppvMem);336 } 337 return rtldrPEReadPartByRva(pThis, pvBits, uRva, cbMem, ppvMem);438 return rtldrPEReadPartFromFile(pThis, (uint32_t)offFile, cbMem, ppvMem); 439 } 440 return rtldrPEReadPartByRva(pThis, pvBits, (uint32_t)uRva, cbMem, ppvMem); 338 441 } 339 442 … … 549 652 rc = VERR_BAD_EXE_FORMAT; 550 653 } 551 pFirstThunk->u1.Function = Value;654 pFirstThunk->u1.Function = (uint32_t)Value; 552 655 if (pFirstThunk->u1.Function != Value) 553 656 { … … 664 767 /* Some bound checking just to be sure it works... */ 665 768 if ((uintptr_t)pbr - (uintptr_t)pBaseRelocs + pbr->SizeOfBlock > cbBaseRelocs) 666 cRelocations = (((uintptr_t)pBaseRelocs + cbBaseRelocs) - (uintptr_t)pbr - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(uint16_t); 769 cRelocations = (uint32_t)( (((uintptr_t)pBaseRelocs + cbBaseRelocs) - (uintptr_t)pbr - sizeof(IMAGE_BASE_RELOCATION)) 770 / sizeof(uint16_t) ); 667 771 668 772 /* … … 692 796 { 693 797 case IMAGE_REL_BASED_HIGHLOW: /* 32-bit, add delta. */ 694 *u.pu32 += uDelta;798 *u.pu32 += (uint32_t)uDelta; 695 799 break; 696 800 case IMAGE_REL_BASED_DIR64: /* 64-bit, add delta. */ … … 717 821 pwoffFixup++; 718 822 int32_t i32 = (uint32_t)(*u.pu16 << 16) | *pwoffFixup; 719 i32 += uDelta;823 i32 += (uint32_t)uDelta; 720 824 i32 += 0x8000; //?? 721 825 *u.pu16 = (uint16_t)(i32 >> 16); … … 760 864 761 865 /** @copydoc RTLDROPS::pfnRelocate. */ 762 static int rtldrPERelocate(PRTLDRMODINTERNAL pMod, void *pvBits, RTUINTPTR NewBaseAddress, RTUINTPTR OldBaseAddress, PFNRTLDRIMPORT pfnGetImport, void *pvUser) 866 static DECLCALLBACK(int) rtldrPERelocate(PRTLDRMODINTERNAL pMod, void *pvBits, RTUINTPTR NewBaseAddress, RTUINTPTR OldBaseAddress, 867 PFNRTLDRIMPORT pfnGetImport, void *pvUser) 763 868 { 764 869 PRTLDRMODPE pModPe = (PRTLDRMODPE)pMod; … … 926 1031 if (RT_SUCCESS(rc)) 927 1032 { 928 uint ptr_tuNamePrev = 0;1033 uint32_t uNamePrev = 0; 929 1034 for (uint32_t uOrdinal = 0; uOrdinal < cOrdinals; uOrdinal++) 930 1035 { … … 1063 1168 uint32_t *paRVANames = PE_RVA2TYPE(pvBits, pExpDir->AddressOfNames, uint32_t *); 1064 1169 uint16_t *paOrdinals = PE_RVA2TYPE(pvBits, pExpDir->AddressOfNameOrdinals, uint16_t *); 1065 uint ptr_tuNamePrev = 0;1170 uint32_t uNamePrev = 0; 1066 1171 unsigned cOrdinals = RT_MAX(pExpDir->NumberOfNames, pExpDir->NumberOfFunctions); 1067 1172 for (unsigned uOrdinal = 0; uOrdinal < cOrdinals; uOrdinal++) … … 1074 1179 const char *pszName = NULL; 1075 1180 /* Search from previous + 1 to the end. */ 1076 u nsigneduName = uNamePrev + 1;1181 uint32_t uName = uNamePrev + 1; 1077 1182 while (uName < pExpDir->NumberOfNames) 1078 1183 { … … 1147 1252 1148 1253 /* 1254 * Allocate temporary memory for a path buffer (this code is also compiled 1255 * and maybe even used in stack starved environments). 1256 */ 1257 char *pszPath = (char *)RTMemTmpAlloc(RTPATH_MAX); 1258 if (!pszPath) 1259 return VERR_NO_TMP_MEMORY; 1260 1261 /* 1149 1262 * Get the debug directory. 1150 1263 */ … … 1156 1269 (void const **)&paDbgDir); 1157 1270 if (RT_FAILURE(rcRet)) 1271 { 1272 RTMemTmpFree(pszPath); 1158 1273 return rcRet; 1274 } 1159 1275 1160 1276 /* … … 1170 1286 1171 1287 void const *pvPart = NULL; 1172 char szPath[RTPATH_MAX];1173 1288 RTLDRDBGINFO DbgInfo; 1174 1289 RT_ZERO(DbgInfo.u); … … 1190 1305 DbgInfo.u.Cv.uMinorVer = paDbgDir[i].MinorVersion; 1191 1306 DbgInfo.u.Cv.uTimestamp = paDbgDir[i].TimeDateStamp; 1192 if ( paDbgDir[i].SizeOfData < sizeof(szPath)1307 if ( paDbgDir[i].SizeOfData < RTPATH_MAX 1193 1308 && paDbgDir[i].SizeOfData > 16 1194 1309 && ( DbgInfo.LinkAddress != NIL_RTLDRADDR … … 1228 1343 case IMAGE_DEBUG_TYPE_MISC: 1229 1344 DbgInfo.enmType = RTLDRDBGINFOTYPE_UNKNOWN; 1230 if ( paDbgDir[i].SizeOfData < sizeof(szPath)1345 if ( paDbgDir[i].SizeOfData < RTPATH_MAX 1231 1346 && paDbgDir[i].SizeOfData > RT_UOFFSETOF(IMAGE_DEBUG_MISC, Data)) 1232 1347 { … … 1249 1364 else 1250 1365 { 1251 char *pszPath = szPath;1252 1366 rc = RTUtf16ToUtf8Ex((PCRTUTF16)&pMisc->Data[0], 1253 1367 (pMisc->Length - RT_OFFSETOF(IMAGE_DEBUG_MISC, Data)) / sizeof(RTUTF16), 1254 &pszPath, sizeof(szPath), NULL);1368 &pszPath, RTPATH_MAX, NULL); 1255 1369 if (RT_SUCCESS(rc)) 1256 DbgInfo.pszExtFile = szPath;1370 DbgInfo.pszExtFile = pszPath; 1257 1371 else 1258 1372 rcRet = rc; /* continue without a filename. */ … … 1283 1397 it's probably the current ANSI/Windows code page for the process 1284 1398 generating the image anyways.) */ 1285 if (DbgInfo.pszExtFile && DbgInfo.pszExtFile != szPath) 1286 { 1287 char *pszPath = szPath; 1399 if (DbgInfo.pszExtFile && DbgInfo.pszExtFile != pszPath) 1400 { 1288 1401 rc = RTLatin1ToUtf8Ex(DbgInfo.pszExtFile, 1289 1402 paDbgDir[i].SizeOfData - ((uintptr_t)DbgInfo.pszExtFile - (uintptr_t)pvBits), 1290 &pszPath, sizeof(szPath), NULL);1403 &pszPath, RTPATH_MAX, NULL); 1291 1404 if (RT_FAILURE(rc)) 1292 1405 { … … 1296 1409 } 1297 1410 if (DbgInfo.pszExtFile) 1298 RTPathChangeToUnixSlashes( szPath, true /*fForce*/);1411 RTPathChangeToUnixSlashes(pszPath, true /*fForce*/); 1299 1412 1300 1413 rc = pfnCallback(pMod, &DbgInfo, pvUser); … … 1308 1421 1309 1422 rtldrPEFreePart(pModPe, pvBits, paDbgDir); 1423 RTMemTmpFree(pszPath); 1310 1424 return rcRet; 1311 1425 } … … 1491 1605 1492 1606 /** @interface_method_impl{RTLDROPS,pfnQueryProp} */ 1493 static DECLCALLBACK(int) rtldrPE_QueryProp(PRTLDRMODINTERNAL pMod, RTLDRPROP enmProp, void *pvBuf, size_t cbBuf )1607 static DECLCALLBACK(int) rtldrPE_QueryProp(PRTLDRMODINTERNAL pMod, RTLDRPROP enmProp, void *pvBuf, size_t cbBuf, size_t *pcbRet) 1494 1608 { 1495 1609 PRTLDRMODPE pModPe = (PRTLDRMODPE)pMod; … … 1497 1611 { 1498 1612 case RTLDRPROP_TIMESTAMP_SECONDS: 1613 Assert(*pcbRet == cbBuf); 1499 1614 if (cbBuf == sizeof(int32_t)) 1500 1615 *(int32_t *)pvBuf = pModPe->uTimestamp; … … 1502 1617 *(int64_t *)pvBuf = pModPe->uTimestamp; 1503 1618 else 1504 return VERR_INVALID_PARAMETER; 1619 AssertFailedReturn(VERR_INTERNAL_ERROR_3); 1620 break; 1621 1622 case RTLDRPROP_IS_SIGNED: 1623 Assert(cbBuf == sizeof(bool)); 1624 Assert(*pcbRet == cbBuf); 1625 *(bool *)pvBuf = pModPe->offPkcs7SignedData != 0; 1626 break; 1627 1628 case RTLDRPROP_PKCS7_SIGNED_DATA: 1629 { 1630 if (pModPe->cbPkcs7SignedData == 0) 1631 return VERR_NOT_FOUND; 1632 Assert(pModPe->offPkcs7SignedData > pModPe->SecurityDir.VirtualAddress); 1633 1634 *pcbRet = pModPe->cbPkcs7SignedData; 1635 if (cbBuf < pModPe->cbPkcs7SignedData) 1636 return VERR_BUFFER_OVERFLOW; 1637 return pModPe->Core.pReader->pfnRead(pModPe->Core.pReader, pvBuf, pModPe->cbPkcs7SignedData, 1638 pModPe->offPkcs7SignedData); 1639 } 1640 1641 case RTLDRPROP_SIGNATURE_CHECKS_ENFORCED: 1642 Assert(cbBuf == sizeof(bool)); 1643 Assert(*pcbRet == cbBuf); 1644 *(bool *)pvBuf = pModPe->offPkcs7SignedData > 0 1645 && (pModPe->fDllCharacteristics & IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY); 1505 1646 break; 1506 1647 … … 1512 1653 1513 1654 1655 1656 /* 1657 * Lots of Authenticode fun ahead. 1658 */ 1659 1660 1661 /** 1662 * Initializes the hash context. 1663 * 1664 * @returns VINF_SUCCESS or VERR_NOT_SUPPORTED. 1665 * @param pHashCtx The hash context union. 1666 * @param enmDigest The hash type we're calculating.. 1667 */ 1668 static int rtLdrPE_HashInit(PRTLDRPEHASHCTXUNION pHashCtx, RTDIGESTTYPE enmDigest) 1669 { 1670 switch (enmDigest) 1671 { 1672 case RTDIGESTTYPE_SHA512: RTSha512Init(&pHashCtx->Sha512); break; 1673 case RTDIGESTTYPE_SHA256: RTSha256Init(&pHashCtx->Sha256); break; 1674 case RTDIGESTTYPE_SHA1: RTSha1Init(&pHashCtx->Sha1); break; 1675 case RTDIGESTTYPE_MD5: RTMd5Init(&pHashCtx->Md5); break; 1676 default: AssertFailedReturn(VERR_NOT_SUPPORTED); 1677 } 1678 return VINF_SUCCESS; 1679 } 1680 1681 1682 /** 1683 * Updates the hash with more data. 1684 * 1685 * @param pHashCtx The hash context union. 1686 * @param enmDigest The hash type we're calculating.. 1687 * @param pvBuf Pointer to a buffer with bytes to add to thash. 1688 * @param cbBuf How many bytes to add from @a pvBuf. 1689 */ 1690 static void rtLdrPE_HashUpdate(PRTLDRPEHASHCTXUNION pHashCtx, RTDIGESTTYPE enmDigest, void const *pvBuf, size_t cbBuf) 1691 { 1692 switch (enmDigest) 1693 { 1694 case RTDIGESTTYPE_SHA512: RTSha512Update(&pHashCtx->Sha512, pvBuf, cbBuf); break; 1695 case RTDIGESTTYPE_SHA256: RTSha256Update(&pHashCtx->Sha256, pvBuf, cbBuf); break; 1696 case RTDIGESTTYPE_SHA1: RTSha1Update(&pHashCtx->Sha1, pvBuf, cbBuf); break; 1697 case RTDIGESTTYPE_MD5: RTMd5Update(&pHashCtx->Md5, pvBuf, cbBuf); break; 1698 default: AssertReleaseFailed(); 1699 } 1700 } 1701 1702 1703 /** 1704 * Finalizes the hash calculations. 1705 * 1706 * @param pHashCtx The hash context union. 1707 * @param enmDigest The hash type we're calculating.. 1708 * @param pHashRes The hash result union. 1709 */ 1710 static void rtLdrPE_HashFinalize(PRTLDRPEHASHCTXUNION pHashCtx, RTDIGESTTYPE enmDigest, PRTLDRPEHASHRESUNION pHashRes) 1711 { 1712 switch (enmDigest) 1713 { 1714 case RTDIGESTTYPE_SHA512: RTSha512Final(&pHashCtx->Sha512, pHashRes->abSha512); break; 1715 case RTDIGESTTYPE_SHA256: RTSha256Final(&pHashCtx->Sha256, pHashRes->abSha256); break; 1716 case RTDIGESTTYPE_SHA1: RTSha1Final(&pHashCtx->Sha1, pHashRes->abSha1); break; 1717 case RTDIGESTTYPE_MD5: RTMd5Final(pHashRes->abMd5, &pHashCtx->Md5); break; 1718 default: AssertReleaseFailed(); 1719 } 1720 } 1721 1722 1723 /** 1724 * Returns the digest size for the given digest type. 1725 * 1726 * @returns Size in bytes. 1727 * @param enmDigest The hash type in question. 1728 */ 1729 static uint32_t rtLdrPE_HashGetHashSize(RTDIGESTTYPE enmDigest) 1730 { 1731 switch (enmDigest) 1732 { 1733 case RTDIGESTTYPE_SHA512: return RTSHA512_HASH_SIZE; 1734 case RTDIGESTTYPE_SHA256: return RTSHA256_HASH_SIZE; 1735 case RTDIGESTTYPE_SHA1: return RTSHA1_HASH_SIZE; 1736 case RTDIGESTTYPE_MD5: return RTMD5_HASH_SIZE; 1737 default: AssertReleaseFailedReturn(0); 1738 } 1739 } 1740 1741 1742 /** 1743 * Calculate the special too watch out for when hashing the image. 1744 * 1745 * @returns IPRT status code. 1746 * @param pModPe The PE module. 1747 * @param pPlaces The structure where to store the special places. 1748 * @param pErrInfo Optional error info. 1749 */ 1750 static int rtldrPe_CalcSpecialHashPlaces(PRTLDRMODPE pModPe, PRTLDRPEHASHSPECIALS pPlaces, PRTERRINFO pErrInfo) 1751 { 1752 /* 1753 * If we're here despite a missing signature, we need to get the file size. 1754 */ 1755 pPlaces->cbToHash = pModPe->SecurityDir.VirtualAddress; 1756 if (pPlaces->cbToHash == 0) 1757 { 1758 RTFOFF cbFile = pModPe->Core.pReader->pfnSize(pModPe->Core.pReader); 1759 pPlaces->cbToHash = (uint32_t)cbFile; 1760 if (pPlaces->cbToHash != (RTFOFF)cbFile) 1761 return RTErrInfoSetF(pErrInfo, VERR_LDRVI_FILE_LENGTH_ERROR, "File is too large: %RTfoff", cbFile); 1762 } 1763 1764 /* 1765 * Calculate the special places. 1766 */ 1767 pPlaces->offCksum = (uint32_t)pModPe->offNtHdrs 1768 + (pModPe->f64Bit 1769 ? RT_OFFSETOF(IMAGE_NT_HEADERS64, OptionalHeader.CheckSum) 1770 : RT_OFFSETOF(IMAGE_NT_HEADERS32, OptionalHeader.CheckSum)); 1771 pPlaces->cbCksum = RT_SIZEOFMEMB(IMAGE_NT_HEADERS32, OptionalHeader.CheckSum); 1772 pPlaces->offSecDir = (uint32_t)pModPe->offNtHdrs 1773 + (pModPe->f64Bit 1774 ? RT_OFFSETOF(IMAGE_NT_HEADERS64, OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY]) 1775 : RT_OFFSETOF(IMAGE_NT_HEADERS32, OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY])); 1776 pPlaces->cbSecDir = sizeof(IMAGE_DATA_DIRECTORY); 1777 pPlaces->offEndSpecial = pPlaces->offSecDir + pPlaces->cbSecDir; 1778 return VINF_SUCCESS; 1779 } 1780 1781 1782 /** 1783 * Calculates the whole image hash. 1784 * 1785 * The Authenticode_PE.docx version 1.0 explains how the hash is calculated, 1786 * points 8 thru 14 are bogus. If you study them a little carefully, it is 1787 * clear that the algorithm will only work if the raw data for the section have 1788 * no gaps between them or in front of them. So, this elaborate section sorting 1789 * by PointerToRawData and working them section by section could simply be 1790 * replaced by one point: 1791 * 1792 * 8. Add all the file content between SizeOfHeaders and the 1793 * attribute certificate table to the hash. Then finalize 1794 * the hash. 1795 * 1796 * Not sure if Microsoft is screwing with us on purpose here or whether they 1797 * assigned some of this work to less talented engineers and tech writers. I 1798 * love fact that they say it's "simplified" and should yield the correct hash 1799 * for "almost all" files. Stupid, Stupid, Microsofties!! 1800 * 1801 * My simplified implementation that just hashes the entire file up to the 1802 * signature or end of the file produces the same SHA1 values as "signtool 1803 * verify /v" does both for edited executables with gaps between/before/after 1804 * sections raw data and normal executables without any gaps. 1805 * 1806 * @returns IPRT status code. 1807 * @param pModPe The PE module. 1808 * @param pvScratch Scratch buffer. 1809 * @param cbScratch Size of the scratch buffer. 1810 * @param enmDigest The hash digest type we're calculating. 1811 * @param pHashCtx Hash context scratch area. 1812 * @param pHashRes Hash result buffer. 1813 * @param pErrInfo Optional error info buffer. 1814 */ 1815 static int rtldrPE_HashImageCommon(PRTLDRMODPE pModPe, void *pvScratch, uint32_t cbScratch, RTDIGESTTYPE enmDigest, 1816 PRTLDRPEHASHCTXUNION pHashCtx, PRTLDRPEHASHRESUNION pHashRes, PRTERRINFO pErrInfo) 1817 { 1818 int rc = rtLdrPE_HashInit(pHashCtx, enmDigest); 1819 if (RT_FAILURE(rc)) 1820 return rc; 1821 1822 /* 1823 * Calculate the special places. 1824 */ 1825 RTLDRPEHASHSPECIALS SpecialPlaces; 1826 rc = rtldrPe_CalcSpecialHashPlaces(pModPe, &SpecialPlaces, pErrInfo); 1827 if (RT_FAILURE(rc)) 1828 return rc; 1829 1830 /* 1831 * Work our way thru the image data. 1832 */ 1833 uint32_t off = 0; 1834 while (off < SpecialPlaces.cbToHash) 1835 { 1836 uint32_t cbRead = RT_MIN(SpecialPlaces.cbToHash - off, cbScratch); 1837 uint8_t *pbCur = (uint8_t *)pvScratch; 1838 rc = pModPe->Core.pReader->pfnRead(pModPe->Core.pReader, pbCur, cbRead, off); 1839 if (RT_FAILURE(rc)) 1840 return RTErrInfoSetF(pErrInfo, VERR_LDRVI_READ_ERROR_HASH, "Hash read error at %#x: %Rrc (cbRead=%#zx)", 1841 off, rc, cbRead); 1842 1843 if (off < SpecialPlaces.offEndSpecial) 1844 { 1845 if (off < SpecialPlaces.offCksum) 1846 { 1847 /* Hash everything up to the checksum. */ 1848 uint32_t cbChunk = RT_MIN(SpecialPlaces.offCksum - off, cbRead); 1849 rtLdrPE_HashUpdate(pHashCtx, enmDigest, pbCur, cbChunk); 1850 pbCur += cbChunk; 1851 cbRead -= cbChunk; 1852 off += cbChunk; 1853 } 1854 1855 if (off < SpecialPlaces.offCksum + SpecialPlaces.cbCksum && off >= SpecialPlaces.offCksum) 1856 { 1857 /* Skip the checksum */ 1858 uint32_t cbChunk = RT_MIN(SpecialPlaces.offCksum + SpecialPlaces.cbCksum - off, cbRead); 1859 pbCur += cbChunk; 1860 cbRead -= cbChunk; 1861 off += cbChunk; 1862 } 1863 1864 if (off < SpecialPlaces.offSecDir && off >= SpecialPlaces.offCksum + SpecialPlaces.cbCksum) 1865 { 1866 /* Hash everything between the checksum and the data dir entry. */ 1867 uint32_t cbChunk = RT_MIN(SpecialPlaces.offSecDir - off, cbRead); 1868 rtLdrPE_HashUpdate(pHashCtx, enmDigest, pbCur, cbChunk); 1869 pbCur += cbChunk; 1870 cbRead -= cbChunk; 1871 off += cbChunk; 1872 } 1873 1874 if (off < SpecialPlaces.offSecDir + SpecialPlaces.cbSecDir && off >= SpecialPlaces.offSecDir) 1875 { 1876 /* Skip the security data directory entry. */ 1877 uint32_t cbChunk = RT_MIN(SpecialPlaces.offSecDir + SpecialPlaces.cbSecDir - off, cbRead); 1878 pbCur += cbChunk; 1879 cbRead -= cbChunk; 1880 off += cbChunk; 1881 } 1882 } 1883 1884 rtLdrPE_HashUpdate(pHashCtx, enmDigest, pbCur, cbRead); 1885 1886 /* Advance */ 1887 off += cbRead; 1888 } 1889 1890 /* 1891 * If there isn't a signature, experiments with signtool indicates that we 1892 * have to zero padd the file size until it's a multiple of 8. (This is 1893 * most likely to give 64-bit values in the certificate a natural alignment 1894 * when memory mapped.) 1895 */ 1896 if ( pModPe->SecurityDir.Size != SpecialPlaces.cbToHash 1897 && SpecialPlaces.cbToHash != RT_ALIGN_32(SpecialPlaces.cbToHash, WIN_CERTIFICATE_ALIGNMENT)) 1898 { 1899 static const uint8_t s_abZeros[WIN_CERTIFICATE_ALIGNMENT] = { 0,0,0,0, 0,0,0,0 }; 1900 rtLdrPE_HashUpdate(pHashCtx, enmDigest, s_abZeros, 1901 RT_ALIGN_32(SpecialPlaces.cbToHash, WIN_CERTIFICATE_ALIGNMENT) - SpecialPlaces.cbToHash); 1902 } 1903 1904 /* 1905 * Done. Finalize the hashes. 1906 */ 1907 rtLdrPE_HashFinalize(pHashCtx, enmDigest, pHashRes); 1908 return VINF_SUCCESS; 1909 } 1910 1911 #ifndef IPRT_WITHOUT_LDR_VERIFY 1912 1913 /** 1914 * Verifies image preconditions not checked by the open validation code. 1915 * 1916 * @returns IPRT status code. 1917 * @param pModPe The PE module. 1918 * @param pErrInfo Optional error info buffer. 1919 */ 1920 static int rtldrPE_VerifySignatureImagePrecoditions(PRTLDRMODPE pModPe, PRTERRINFO pErrInfo) 1921 { 1922 /* 1923 * Validate the sections. While doing so, track the amount of section raw 1924 * section data in the file so we can use this to validate the signature 1925 * table location later. 1926 */ 1927 uint32_t offNext = pModPe->cbHeaders; /* same */ 1928 for (uint32_t i = 0; i < pModPe->cSections; i++) 1929 if (pModPe->paSections[i].SizeOfRawData > 0) 1930 { 1931 uint64_t offEnd = (uint64_t)pModPe->paSections[i].PointerToRawData + pModPe->paSections[i].SizeOfRawData; 1932 if (offEnd > offNext) 1933 { 1934 if (offEnd >= _2G) 1935 return RTErrInfoSetF(pErrInfo, VERR_LDRVI_SECTION_RAW_DATA_VALUES, 1936 "Section %#u specifies file data after 2GB: PointerToRawData=%#x SizeOfRawData=%#x", 1937 i, pModPe->paSections[i].PointerToRawData, pModPe->paSections[i].SizeOfRawData); 1938 offNext = (uint32_t)offEnd; 1939 } 1940 } 1941 uint32_t offEndOfSectionData = offNext; 1942 1943 /* 1944 * Validate the signature. 1945 */ 1946 if (!pModPe->SecurityDir.Size) 1947 return RTErrInfoSet(pErrInfo, VERR_LDRVI_NOT_SIGNED, "Not signed."); 1948 1949 uint32_t const offSignature = pModPe->SecurityDir.VirtualAddress; 1950 uint32_t const cbSignature = pModPe->SecurityDir.Size; 1951 if ( cbSignature <= sizeof(WIN_CERTIFICATE) 1952 || cbSignature >= RTLDRMODPE_MAX_SECURITY_DIR_SIZE 1953 || offSignature >= _2G) 1954 return RTErrInfoSetF(pErrInfo, VERR_LDRVI_INVALID_SECURITY_DIR_ENTRY, 1955 "Invalid security data dir entry: cb=%#x off=%#x", cbSignature, offSignature); 1956 1957 if (offSignature < offEndOfSectionData) 1958 return RTErrInfoSetF(pErrInfo, VERR_LDRVI_INVALID_SECURITY_DIR_ENTRY, 1959 "Invalid security data dir entry offset: %#x offEndOfSectionData=%#x", 1960 offSignature, offEndOfSectionData); 1961 1962 if (RT_ALIGN_32(offSignature, WIN_CERTIFICATE_ALIGNMENT) != offSignature) 1963 return RTErrInfoSetF(pErrInfo, VERR_LDRVI_INVALID_SECURITY_DIR_ENTRY, 1964 "Misaligned security dir entry offset: %#x (alignment=%#x)", 1965 offSignature, WIN_CERTIFICATE_ALIGNMENT); 1966 1967 1968 return VINF_SUCCESS; 1969 } 1970 1971 1972 /** 1973 * Reads and checks the raw signature data. 1974 * 1975 * @returns IPRT status code. 1976 * @param pModPe The PE module. 1977 * @param ppSignature Where to return the pointer to the parsed 1978 * signature data. Pass to 1979 * rtldrPE_VerifySignatureDestroy when done. 1980 * @param pErrInfo Optional error info buffer. 1981 */ 1982 static int rtldrPE_VerifySignatureRead(PRTLDRMODPE pModPe, PRTLDRPESIGNATURE *ppSignature, PRTERRINFO pErrInfo) 1983 { 1984 *ppSignature = NULL; 1985 AssertReturn(pModPe->SecurityDir.Size > 0, VERR_INTERNAL_ERROR_2); 1986 1987 /* 1988 * Allocate memory for reading and parsing it. 1989 */ 1990 if (pModPe->SecurityDir.Size >= RTLDRMODPE_MAX_SECURITY_DIR_SIZE) 1991 return RTErrInfoSetF(pErrInfo, VERR_LDRVI_INVALID_SECURITY_DIR_ENTRY, 1992 "Signature directory is to large: %#x", pModPe->SecurityDir.Size); 1993 1994 PRTLDRPESIGNATURE pSignature = (PRTLDRPESIGNATURE)RTMemTmpAllocZ(sizeof(*pSignature) + 64 + pModPe->SecurityDir.Size); 1995 if (!pSignature) 1996 return RTErrInfoSetF(pErrInfo, VERR_LDRVI_NO_MEMORY_SIGNATURE, "Failed to allocate %zu bytes", 1997 sizeof(*pSignature) + 64 + pModPe->SecurityDir.Size); 1998 pSignature->pRawData = RT_ALIGN_PT(pSignature + 1, 64, WIN_CERTIFICATE const *); 1999 2000 2001 /* 2002 * Read it. 2003 */ 2004 int rc = pModPe->Core.pReader->pfnRead(pModPe->Core.pReader, (void *)pSignature->pRawData, 2005 pModPe->SecurityDir.Size, pModPe->SecurityDir.VirtualAddress); 2006 if (RT_SUCCESS(rc)) 2007 { 2008 /* 2009 * Check the table we've read in. 2010 */ 2011 uint32_t cbLeft = pModPe->SecurityDir.Size; 2012 WIN_CERTIFICATE const *pEntry = pSignature->pRawData; 2013 for (;;) 2014 { 2015 if ( cbLeft < sizeof(*pEntry) 2016 || pEntry->dwLength > cbLeft 2017 || pEntry->dwLength < sizeof(*pEntry)) 2018 rc = RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_HDR_LENGTH, 2019 "Bad WIN_CERTIFICATE length: %#x (max %#x, signature=%u)", 2020 pEntry->dwLength, cbLeft, 0); 2021 else if (pEntry->wRevision != WIN_CERT_REVISION_2_0) 2022 rc = RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_HDR_REVISION, 2023 "Unsupported WIN_CERTIFICATE revision value: %#x (signature=%u)", 2024 pEntry->wRevision, 0); 2025 else if (pEntry->wCertificateType != WIN_CERT_TYPE_PKCS_SIGNED_DATA) 2026 rc = RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_HDR_TYPE, 2027 "Unsupported WIN_CERTIFICATE certificate type: %#x (signature=%u)", 2028 pEntry->wCertificateType, 0); 2029 else 2030 { 2031 /* advance */ 2032 uint32_t cbEntry = RT_ALIGN(pEntry->dwLength, WIN_CERTIFICATE_ALIGNMENT); 2033 if (cbEntry >= cbLeft) 2034 break; 2035 cbLeft -= cbEntry; 2036 pEntry = (WIN_CERTIFICATE *)((uintptr_t)pEntry + cbEntry); 2037 2038 /* For now, only one entry is supported. */ 2039 rc = RTErrInfoSet(pErrInfo, VERR_LDRVI_BAD_CERT_MULTIPLE, "Multiple WIN_CERTIFICATE entries are not supported."); 2040 } 2041 break; 2042 } 2043 if (RT_SUCCESS(rc)) 2044 { 2045 *ppSignature = pSignature; 2046 return VINF_SUCCESS; 2047 } 2048 } 2049 else 2050 rc = RTErrInfoSetF(pErrInfo, VERR_LDRVI_READ_ERROR_SIGNATURE, "Signature read error: %Rrc", rc); 2051 RTMemTmpFree(pSignature); 2052 return rc; 2053 } 2054 2055 2056 /** 2057 * Destroys the parsed signature. 2058 * 2059 * @param pModPe The PE module. 2060 * @param pSignature The signature data to destroy. 2061 */ 2062 static void rtldrPE_VerifySignatureDestroy(PRTLDRMODPE pModPe, PRTLDRPESIGNATURE pSignature) 2063 { 2064 RTCrPkcs7ContentInfo_Delete(&pSignature->ContentInfo); 2065 RTMemTmpFree(pSignature); 2066 } 2067 2068 2069 /** 2070 * Decodes the raw signature. 2071 * 2072 * @returns IPRT status code. 2073 * @param pModPe The PE module. 2074 * @param pSignature The signature data. 2075 * @param pErrInfo Optional error info buffer. 2076 */ 2077 static int rtldrPE_VerifySignatureDecode(PRTLDRMODPE pModPe, PRTLDRPESIGNATURE pSignature, PRTERRINFO pErrInfo) 2078 { 2079 WIN_CERTIFICATE const *pEntry = pSignature->pRawData; 2080 AssertReturn(pEntry->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA, VERR_INTERNAL_ERROR_2); 2081 AssertReturn(pEntry->wRevision == WIN_CERT_REVISION_2_0, VERR_INTERNAL_ERROR_2); 2082 2083 RTASN1CURSORPRIMARY PrimaryCursor; 2084 RTAsn1CursorInitPrimary(&PrimaryCursor, 2085 &pEntry->bCertificate[0], 2086 pEntry->dwLength - RT_OFFSETOF(WIN_CERTIFICATE, bCertificate), 2087 pErrInfo, 2088 &g_RTAsn1DefaultAllocator, 2089 0, 2090 "WinCert"); 2091 2092 int rc = RTCrPkcs7ContentInfo_DecodeAsn1(&PrimaryCursor.Cursor, 0, &pSignature->ContentInfo, "CI"); 2093 if (RT_SUCCESS(rc)) 2094 { 2095 if (RTCrPkcs7ContentInfo_IsSignedData(&pSignature->ContentInfo)) 2096 { 2097 pSignature->pSignedData = pSignature->ContentInfo.u.pSignedData; 2098 2099 /* 2100 * Decode the authenticode bits. 2101 */ 2102 if (!strcmp(pSignature->pSignedData->ContentInfo.ContentType.szObjId, RTCRSPCINDIRECTDATACONTENT_OID)) 2103 { 2104 pSignature->pIndData = pSignature->pSignedData->ContentInfo.u.pIndirectDataContent; 2105 Assert(pSignature->pIndData); 2106 2107 /* 2108 * Check that things add up. 2109 */ 2110 if (RT_SUCCESS(rc)) 2111 rc = RTCrPkcs7SignedData_CheckSanity(pSignature->pSignedData, 2112 RTCRPKCS7SIGNEDDATA_SANITY_F_AUTHENTICODE 2113 | RTCRPKCS7SIGNEDDATA_SANITY_F_ONLY_KNOWN_HASH 2114 | RTCRPKCS7SIGNEDDATA_SANITY_F_SIGNING_CERT_PRESENT, 2115 pErrInfo, "SD"); 2116 if (RT_SUCCESS(rc)) 2117 rc = RTCrSpcIndirectDataContent_CheckSanityEx(pSignature->pIndData, 2118 pSignature->pSignedData, 2119 RTCRSPCINDIRECTDATACONTENT_SANITY_F_ONLY_KNOWN_HASH, 2120 pErrInfo); 2121 if (RT_SUCCESS(rc)) 2122 { 2123 PCRTCRX509ALGORITHMIDENTIFIER pDigestAlgorithm = &pSignature->pIndData->DigestInfo.DigestAlgorithm; 2124 pSignature->enmDigest = RTCrX509AlgorithmIdentifier_QueryDigestType(pDigestAlgorithm); 2125 AssertReturn(pSignature->enmDigest != RTDIGESTTYPE_INVALID, VERR_INTERNAL_ERROR_4); /* Checked above! */ 2126 } 2127 } 2128 else 2129 rc = RTErrInfoSetF(pErrInfo, VERR_LDRVI_EXPECTED_INDIRECT_DATA_CONTENT_OID, 2130 "Unknown pSignedData.ContentInfo.ContentType.szObjId value: %s (expected %s)", 2131 pSignature->pSignedData->ContentInfo.ContentType.szObjId, RTCRSPCINDIRECTDATACONTENT_OID); 2132 } 2133 } 2134 return rc; 2135 } 2136 2137 2138 static int rtldrPE_VerifyAllPageHashesV2(PRTLDRMODPE pModPe, PCRTCRSPCSERIALIZEDOBJECTATTRIBUTE pAttrib, RTDIGESTTYPE enmDigest, 2139 void *pvScratch, size_t cbScratch, PRTERRINFO pErrInfo) 2140 { 2141 AssertReturn(cbScratch >= _4K, VERR_INTERNAL_ERROR_3); 2142 2143 /* 2144 * Calculate the special places. 2145 */ 2146 RTLDRPEHASHSPECIALS SpecialPlaces; 2147 int rc = rtldrPe_CalcSpecialHashPlaces(pModPe, &SpecialPlaces, pErrInfo); 2148 if (RT_FAILURE(rc)) 2149 return rc; 2150 2151 uint32_t const cbHash = rtLdrPE_HashGetHashSize(enmDigest); 2152 uint32_t const cPages = pAttrib->u.pPageHashesV2->RawData.Asn1Core.cb / (cbHash + 4); 2153 if (cPages * (cbHash + 4) != pAttrib->u.pPageHashesV2->RawData.Asn1Core.cb) 2154 return RTErrInfoSetF(pErrInfo, VERR_LDRVI_PAGE_HASH_TAB_SIZE_OVERFLOW, 2155 "Page Hashes V2 size issue: cb=%#x cbHash=%#x", 2156 pAttrib->u.pPageHashesV2->RawData.Asn1Core.cb, cbHash); 2157 2158 /* 2159 * Walk the table. 2160 */ 2161 uint32_t const cbScratchReadMax = cbScratch & ~(uint32_t)(_4K - 1); 2162 uint32_t cbScratchRead = 0; 2163 uint32_t offScratchRead = 0; 2164 2165 uint32_t offPrev = 0; 2166 uint32_t offSectEnd = pModPe->cbHeaders; 2167 uint32_t iSh = UINT32_MAX; 2168 uint8_t const *pbHashTab = pAttrib->u.pPageHashesV2->RawData.Asn1Core.uData.pu8; 2169 for (uint32_t iPage = 0; iPage < cPages; iPage++) 2170 { 2171 /* Decode the page offset. */ 2172 uint32_t const offFile = RT_MAKE_U32_FROM_U8(pbHashTab[0], pbHashTab[1], pbHashTab[2], pbHashTab[3]); 2173 if (offFile >= SpecialPlaces.cbToHash) 2174 { 2175 /* The last entry is zero. */ 2176 if ( offFile == SpecialPlaces.cbToHash 2177 && iPage + 1 == cPages 2178 && ASMMemIsAll8(pbHashTab + 4, cbHash, 0) == NULL) 2179 return VINF_SUCCESS; 2180 return RTErrInfoSetF(pErrInfo, VERR_LDRVI_PAGE_HASH_TAB_TOO_LONG, 2181 "Page hash entry #%u is beyond the signature table start: %#x, %#x", 2182 iPage, offFile, SpecialPlaces.cbToHash); 2183 } 2184 if (offFile < offPrev) 2185 return RTErrInfoSetF(pErrInfo, VERR_LDRVI_PAGE_HASH_TAB_NOT_STRICTLY_SORTED, 2186 "Page hash table is not strictly sorted: entry #%u @%#x, previous @%#x\n", 2187 iPage, offFile, offPrev); 2188 2189 /* Figure out how much to read and how much to zero. Need keep track 2190 of the on-disk section boundraries. */ 2191 if (offFile >= offSectEnd) 2192 { 2193 iSh++; 2194 if ( iSh < pModPe->cSections 2195 && offFile - pModPe->paSections[iSh].PointerToRawData < pModPe->paSections[iSh].SizeOfRawData) 2196 offSectEnd = pModPe->paSections[iSh].PointerToRawData + pModPe->paSections[iSh].SizeOfRawData; 2197 else 2198 { 2199 iSh = 0; 2200 while ( iSh < pModPe->cSections 2201 && offFile - pModPe->paSections[iSh].PointerToRawData >= pModPe->paSections[iSh].SizeOfRawData) 2202 iSh++; 2203 if (iSh < pModPe->cSections) 2204 offSectEnd = pModPe->paSections[iSh].PointerToRawData + pModPe->paSections[iSh].SizeOfRawData; 2205 else 2206 return RTErrInfoSetF(pErrInfo, VERR_PAGE_HASH_TAB_HASHES_NON_SECTION_DATA, 2207 "Page hash entry #%u isn't in any section: %#x", iPage, offFile); 2208 } 2209 } 2210 2211 uint32_t cbRead = _4K; 2212 if (offFile + cbRead > offSectEnd) 2213 cbRead = offSectEnd - offFile; 2214 2215 if (offFile + cbRead > SpecialPlaces.cbToHash) 2216 cbRead = SpecialPlaces.cbToHash - offFile; 2217 2218 /* Did we get a cache hit? */ 2219 uint8_t *pbCur = (uint8_t *)pvScratch; 2220 if ( offFile + cbRead <= offScratchRead + cbScratchRead 2221 && offFile >= offScratchRead) 2222 pbCur += offFile - offScratchRead; 2223 /* Missed, read more. */ 2224 else 2225 { 2226 offScratchRead = offFile; 2227 cbScratchRead = offSectEnd - offFile; 2228 if (cbScratchRead > cbScratchReadMax) 2229 cbScratchRead = cbScratchReadMax; 2230 rc = pModPe->Core.pReader->pfnRead(pModPe->Core.pReader, pbCur, cbScratchRead, offScratchRead); 2231 if (RT_FAILURE(rc)) 2232 return RTErrInfoSetF(pErrInfo, VERR_LDRVI_READ_ERROR_HASH, 2233 "Page hash read error at %#x: %Rrc (cbScratchRead=%#zx)", 2234 offScratchRead, rc, cbScratchRead); 2235 } 2236 2237 /* Zero any additional bytes in the page. */ 2238 if (cbRead != _4K) 2239 memset(pbCur + cbRead, 0, _4K - cbRead); 2240 2241 /* 2242 * Hash it. 2243 */ 2244 RTLDRPEHASHCTXUNION HashCtx; 2245 rc = rtLdrPE_HashInit(&HashCtx, enmDigest); 2246 AssertRCReturn(rc, rc); 2247 2248 /* Deal with special places. */ 2249 uint32_t cbLeft = _4K; 2250 if (offFile < SpecialPlaces.offEndSpecial) 2251 { 2252 uint32_t off = offFile; 2253 if (off < SpecialPlaces.offCksum) 2254 { 2255 /* Hash everything up to the checksum. */ 2256 uint32_t cbChunk = RT_MIN(SpecialPlaces.offCksum - off, cbLeft); 2257 rtLdrPE_HashUpdate(&HashCtx, enmDigest, pbCur, cbChunk); 2258 pbCur += cbChunk; 2259 cbLeft -= cbChunk; 2260 off += cbChunk; 2261 } 2262 2263 if (off < SpecialPlaces.offCksum + SpecialPlaces.cbCksum && off >= SpecialPlaces.offCksum) 2264 { 2265 /* Skip the checksum */ 2266 uint32_t cbChunk = RT_MIN(SpecialPlaces.offCksum + SpecialPlaces.cbCksum - off, cbLeft); 2267 pbCur += cbChunk; 2268 cbLeft -= cbChunk; 2269 off += cbChunk; 2270 } 2271 2272 if (off < SpecialPlaces.offSecDir && off >= SpecialPlaces.offCksum + SpecialPlaces.cbCksum) 2273 { 2274 /* Hash everything between the checksum and the data dir entry. */ 2275 uint32_t cbChunk = RT_MIN(SpecialPlaces.offSecDir - off, cbLeft); 2276 rtLdrPE_HashUpdate(&HashCtx, enmDigest, pbCur, cbChunk); 2277 pbCur += cbChunk; 2278 cbLeft -= cbChunk; 2279 off += cbChunk; 2280 } 2281 2282 if (off < SpecialPlaces.offSecDir + SpecialPlaces.cbSecDir && off >= SpecialPlaces.offSecDir) 2283 { 2284 /* Skip the security data directory entry. */ 2285 uint32_t cbChunk = RT_MIN(SpecialPlaces.offSecDir + SpecialPlaces.cbSecDir - off, cbLeft); 2286 pbCur += cbChunk; 2287 cbLeft -= cbChunk; 2288 off += cbChunk; 2289 } 2290 } 2291 2292 rtLdrPE_HashUpdate(&HashCtx, enmDigest, pbCur, cbLeft); 2293 2294 /* 2295 * Finish the hash calculation and compare the result. 2296 */ 2297 RTLDRPEHASHRESUNION HashRes; 2298 rtLdrPE_HashFinalize(&HashCtx, enmDigest, &HashRes); 2299 2300 pbHashTab += 4; 2301 if (memcmp(pbHashTab, &HashRes, cbHash) != 0) 2302 return RTErrInfoSetF(pErrInfo, VERR_LDRVI_PAGE_HASH_MISMATCH, 2303 "Page hash v2 failed for page #%u, @%#x, %#x bytes: %.*Rhxs != %.*Rhxs", 2304 iPage, offFile, cbRead, (size_t)cbHash, pbHashTab, (size_t)cbHash, &HashRes); 2305 pbHashTab += cbHash; 2306 offPrev = offFile; 2307 } 2308 2309 return VINF_SUCCESS; 2310 } 2311 2312 2313 /** 2314 * Validates the image hash, including page hashes if present. 2315 * 2316 * @returns IPRT status code. 2317 * @param pModPe The PE module. 2318 * @param pSignature The decoded signature data. 2319 * @param pErrInfo Optional error info buffer. 2320 */ 2321 static int rtldrPE_VerifySignatureValidateHash(PRTLDRMODPE pModPe, PRTLDRPESIGNATURE pSignature, PRTERRINFO pErrInfo) 2322 { 2323 AssertReturn(pSignature->enmDigest > RTDIGESTTYPE_INVALID && pSignature->enmDigest < RTDIGESTTYPE_END, VERR_INTERNAL_ERROR_4); 2324 AssertPtrReturn(pSignature->pIndData, VERR_INTERNAL_ERROR_5); 2325 AssertReturn(RTASN1CORE_IS_PRESENT(&pSignature->pIndData->DigestInfo.Digest.Asn1Core), VERR_INTERNAL_ERROR_5); 2326 AssertPtrReturn(pSignature->pIndData->DigestInfo.Digest.Asn1Core.uData.pv, VERR_INTERNAL_ERROR_5); 2327 2328 uint32_t const cbHash = rtLdrPE_HashGetHashSize(pSignature->enmDigest); 2329 AssertReturn(pSignature->pIndData->DigestInfo.Digest.Asn1Core.cb == cbHash, VERR_INTERNAL_ERROR_5); 2330 2331 /* 2332 * Allocate a temporary memory buffer. 2333 */ 2334 #ifdef IN_RING0 2335 uint32_t cbScratch = _256K; 2336 #else 2337 uint32_t cbScratch = _1M; 2338 #endif 2339 void *pvScratch = RTMemTmpAlloc(cbScratch); 2340 if (!pvScratch) 2341 { 2342 cbScratch = _4K; 2343 pvScratch = RTMemTmpAlloc(cbScratch); 2344 if (!pvScratch) 2345 return RTErrInfoSet(pErrInfo, VERR_NO_TMP_MEMORY, "Failed to allocate 4KB of scratch space for hashing image."); 2346 } 2347 2348 /* 2349 * Calculate and compare the full image hash. 2350 */ 2351 int rc = rtldrPE_HashImageCommon(pModPe, pvScratch, cbScratch, pSignature->enmDigest, 2352 &pSignature->HashCtx, &pSignature->HashRes, pErrInfo); 2353 if (RT_SUCCESS(rc)) 2354 { 2355 if (!memcmp(&pSignature->HashRes, pSignature->pIndData->DigestInfo.Digest.Asn1Core.uData.pv, cbHash)) 2356 { 2357 /* 2358 * Compare the page hashes if present. 2359 */ 2360 PCRTCRSPCSERIALIZEDOBJECTATTRIBUTE pAttrib = RTCrSpcIndirectDataContent_GetPeImageHashesV2(pSignature->pIndData); 2361 if (pAttrib) 2362 rc = rtldrPE_VerifyAllPageHashesV2(pModPe, pAttrib, pSignature->enmDigest, pvScratch, cbScratch, pErrInfo); 2363 2364 return rc; 2365 } 2366 rc = RTErrInfoSetF(pErrInfo, VERR_LDRVI_IMAGE_HASH_MISMATCH, 2367 "Full image signature mismatch: %.*Rhxs, expected %.*Rhxs", 2368 cbHash, &pSignature->HashRes, 2369 cbHash, pSignature->pIndData->DigestInfo.Digest.Asn1Core.uData.pv); 2370 } 2371 2372 RTMemTmpFree(pvScratch); 2373 return rc; 2374 } 2375 2376 #endif /* !IPRT_WITHOUT_LDR_VERIFY */ 2377 2378 2379 /** @interface_method_impl{RTLDROPS,pfnVerifySignature} */ 2380 static DECLCALLBACK(int) rtldrPE_VerifySignature(PRTLDRMODINTERNAL pMod, PFNRTLDRVALIDATESIGNEDDATA pfnCallback, void *pvUser, 2381 PRTERRINFO pErrInfo) 2382 { 2383 #ifndef IPRT_WITHOUT_LDR_VERIFY 2384 PRTLDRMODPE pModPe = (PRTLDRMODPE)pMod; 2385 2386 int rc = rtldrPE_VerifySignatureImagePrecoditions(pModPe, pErrInfo); 2387 if (RT_SUCCESS(rc)) 2388 { 2389 PRTLDRPESIGNATURE pSignature = NULL; 2390 rc = rtldrPE_VerifySignatureRead(pModPe, &pSignature, pErrInfo); 2391 if (RT_SUCCESS(rc)) 2392 { 2393 rc = rtldrPE_VerifySignatureDecode(pModPe, pSignature, pErrInfo); 2394 if (RT_SUCCESS(rc)) 2395 rc = rtldrPE_VerifySignatureValidateHash(pModPe, pSignature, pErrInfo); 2396 if (RT_SUCCESS(rc)) 2397 { 2398 rc = pfnCallback(&pModPe->Core, RTLDRSIGNATURETYPE_PKCS7_SIGNED_DATA, 2399 &pSignature->ContentInfo, sizeof(pSignature->ContentInfo), 2400 pErrInfo, pvUser); 2401 } 2402 rtldrPE_VerifySignatureDestroy(pModPe, pSignature); 2403 } 2404 } 2405 return rc; 2406 #else 2407 return VERR_NOT_SUPPORTED; 2408 #endif 2409 } 2410 2411 2412 2413 /** @interface_method_impl{RTLDROPS,pfnHashImage} */ 2414 static DECLCALLBACK(int) rtldrPE_HashImage(PRTLDRMODINTERNAL pMod, RTDIGESTTYPE enmDigest, char *pszDigest, size_t cbDigest) 2415 { 2416 PRTLDRMODPE pModPe = (PRTLDRMODPE)pMod; 2417 2418 /* 2419 * Allocate a temporary memory buffer. 2420 */ 2421 uint32_t cbScratch = _16K; 2422 void *pvScratch = RTMemTmpAlloc(cbScratch); 2423 if (!pvScratch) 2424 { 2425 cbScratch = _4K; 2426 pvScratch = RTMemTmpAlloc(cbScratch); 2427 if (!pvScratch) 2428 return VERR_NO_TMP_MEMORY; 2429 } 2430 2431 /* 2432 * Do the hashing. 2433 */ 2434 RTLDRPEHASHCTXUNION HashCtx; 2435 RTLDRPEHASHRESUNION HashRes; 2436 int rc = rtldrPE_HashImageCommon(pModPe, pvScratch, cbScratch, enmDigest, &HashCtx, &HashRes, NULL); 2437 if (RT_SUCCESS(rc)) 2438 { 2439 /* 2440 * Format the digest into as human readable hash string. 2441 */ 2442 switch (enmDigest) 2443 { 2444 case RTDIGESTTYPE_SHA512: rc = RTSha512ToString(HashRes.abSha512, pszDigest, cbDigest); break; 2445 case RTDIGESTTYPE_SHA256: rc = RTSha256ToString(HashRes.abSha256, pszDigest, cbDigest); break; 2446 case RTDIGESTTYPE_SHA1: rc = RTSha1ToString(HashRes.abSha1, pszDigest, cbDigest); break; 2447 case RTDIGESTTYPE_MD5: rc = RTMd5ToString(HashRes.abMd5, pszDigest, cbDigest); break; 2448 default: AssertFailedReturn(VERR_INTERNAL_ERROR_3); 2449 } 2450 } 2451 return rc; 2452 } 2453 2454 1514 2455 /** @copydoc RTLDROPS::pfnDone */ 1515 2456 static DECLCALLBACK(int) rtldrPEDone(PRTLDRMODINTERNAL pMod) … … 1523 2464 return VINF_SUCCESS; 1524 2465 } 2466 1525 2467 1526 2468 /** @copydoc RTLDROPS::pfnClose */ … … 1566 2508 NULL, 1567 2509 rtldrPE_QueryProp, 2510 rtldrPE_VerifySignature, 2511 rtldrPE_HashImage, 1568 2512 42 1569 2513 }, … … 1597 2541 NULL, 1598 2542 rtldrPE_QueryProp, 2543 rtldrPE_VerifySignature, 2544 rtldrPE_HashImage, 1599 2545 42 1600 2546 }, … … 1660 2606 * volatile everywhere! Trying to prevent the compiler being a smarta$$ and reorder stuff. 1661 2607 */ 1662 IMAGE_LOAD_CONFIG_DIRECTORY32 volatile *pLoadCfg32 = (IMAGE_LOAD_CONFIG_DIRECTORY32 volatile *)pLoadCfg; 1663 IMAGE_LOAD_CONFIG_DIRECTORY64 volatile *pLoadCfg64 = pLoadCfg; 1664 1665 pLoadCfg64->SEHandlerCount = pLoadCfg32->SEHandlerCount; 1666 pLoadCfg64->SEHandlerTable = pLoadCfg32->SEHandlerTable; 1667 pLoadCfg64->SecurityCookie = pLoadCfg32->SecurityCookie; 1668 pLoadCfg64->EditList = pLoadCfg32->EditList; 1669 pLoadCfg64->Reserved1 = pLoadCfg32->Reserved1; 1670 pLoadCfg64->CSDVersion = pLoadCfg32->CSDVersion; 1671 pLoadCfg64->ProcessHeapFlags = pLoadCfg32->ProcessHeapFlags; /* switched place with ProcessAffinityMask, but we're more than 16 byte off by now so it doesn't matter. */ 1672 pLoadCfg64->ProcessAffinityMask = pLoadCfg32->ProcessAffinityMask; 1673 pLoadCfg64->VirtualMemoryThreshold = pLoadCfg32->VirtualMemoryThreshold; 1674 pLoadCfg64->MaximumAllocationSize = pLoadCfg32->MaximumAllocationSize; 1675 pLoadCfg64->LockPrefixTable = pLoadCfg32->LockPrefixTable; 1676 pLoadCfg64->DeCommitTotalFreeThreshold = pLoadCfg32->DeCommitTotalFreeThreshold; 1677 uint32_t u32DeCommitFreeBlockThreshold = pLoadCfg32->DeCommitFreeBlockThreshold; 1678 pLoadCfg64->DeCommitFreeBlockThreshold = u32DeCommitFreeBlockThreshold; 2608 IMAGE_LOAD_CONFIG_DIRECTORY32_V3 volatile *pLoadCfg32 = (IMAGE_LOAD_CONFIG_DIRECTORY32_V3 volatile *)pLoadCfg; 2609 IMAGE_LOAD_CONFIG_DIRECTORY64_V3 volatile *pLoadCfg64 = pLoadCfg; 2610 2611 pLoadCfg64->GuardFlags = pLoadCfg32->GuardFlags; 2612 pLoadCfg64->GuardCFFunctionCount = pLoadCfg32->GuardCFFunctionCount; 2613 pLoadCfg64->GuardCFFunctionTable = pLoadCfg32->GuardCFFunctionTable; 2614 pLoadCfg64->Reserved2 = pLoadCfg32->Reserved2; 2615 pLoadCfg64->GuardCFCCheckFunctionPointer= pLoadCfg32->GuardCFCCheckFunctionPointer; 2616 pLoadCfg64->SEHandlerCount = pLoadCfg32->SEHandlerCount; 2617 pLoadCfg64->SEHandlerTable = pLoadCfg32->SEHandlerTable; 2618 pLoadCfg64->SecurityCookie = pLoadCfg32->SecurityCookie; 2619 pLoadCfg64->EditList = pLoadCfg32->EditList; 2620 pLoadCfg64->Reserved1 = pLoadCfg32->Reserved1; 2621 pLoadCfg64->CSDVersion = pLoadCfg32->CSDVersion; 2622 pLoadCfg64->ProcessHeapFlags = pLoadCfg32->ProcessHeapFlags; /* switched place with ProcessAffinityMask, but we're more than 16 byte off by now so it doesn't matter. */ 2623 pLoadCfg64->ProcessAffinityMask = pLoadCfg32->ProcessAffinityMask; 2624 pLoadCfg64->VirtualMemoryThreshold = pLoadCfg32->VirtualMemoryThreshold; 2625 pLoadCfg64->MaximumAllocationSize = pLoadCfg32->MaximumAllocationSize; 2626 pLoadCfg64->LockPrefixTable = pLoadCfg32->LockPrefixTable; 2627 pLoadCfg64->DeCommitTotalFreeThreshold = pLoadCfg32->DeCommitTotalFreeThreshold; 2628 uint32_t u32DeCommitFreeBlockThreshold = pLoadCfg32->DeCommitFreeBlockThreshold; 2629 pLoadCfg64->DeCommitFreeBlockThreshold = u32DeCommitFreeBlockThreshold; 1679 2630 /* the rest is equal. */ 1680 2631 Assert( RT_OFFSETOF(IMAGE_LOAD_CONFIG_DIRECTORY32, DeCommitFreeBlockThreshold) … … 1720 2671 /* This restriction needs to be implemented elsewhere. */ 1721 2672 if ( (pFileHdr->Characteristics & IMAGE_FILE_RELOCS_STRIPPED) 1722 && !(fFlags & RTLDR_O_FOR_DEBUG))2673 && !(fFlags & (RTLDR_O_FOR_DEBUG | RTLDR_O_FOR_VALIDATION))) 1723 2674 { 1724 2675 Log(("rtldrPEOpen: %s: IMAGE_FILE_RELOCS_STRIPPED\n", pszLogName)); … … 1856 2807 1857 2808 case IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT: // 13 2809 if (fFlags & (RTLDR_O_FOR_DEBUG | RTLDR_O_FOR_VALIDATION)) 2810 break; 1858 2811 Log(("rtldrPEOpen: %s: dir no. %d (DELAY_IMPORT) VirtualAddress=%#x Size=%#x is not supported!!!\n", 1859 2812 pszLogName, i, pDir->VirtualAddress, pDir->Size)); … … 1870 2823 return VERR_LDRPE_CERT_MALFORMED; 1871 2824 } 1872 if (pDir->Size >= _1M)2825 if (pDir->Size >= RTLDRMODPE_MAX_SECURITY_DIR_SIZE) 1873 2826 { 1874 2827 Log(("rtldrPEOpen: %s: Security directory is too large: %#x bytes\n", pszLogName, i, pDir->Size)); … … 1894 2847 1895 2848 case IMAGE_DIRECTORY_ENTRY_TLS: // 9 2849 if (fFlags & (RTLDR_O_FOR_DEBUG | RTLDR_O_FOR_VALIDATION)) 2850 break; 1896 2851 Log(("rtldrPEOpen: %s: dir no. %d (TLS) VirtualAddress=%#x Size=%#x is not supported!!!\n", 1897 2852 pszLogName, i, pDir->VirtualAddress, pDir->Size)); … … 1899 2854 1900 2855 case IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR:// 14 2856 if (fFlags & (RTLDR_O_FOR_DEBUG | RTLDR_O_FOR_VALIDATION)) 2857 break; 1901 2858 Log(("rtldrPEOpen: %s: dir no. %d (COM_DESCRIPTOR) VirtualAddress=%#x Size=%#x is not supported!!!\n", 1902 2859 pszLogName, i, pDir->VirtualAddress, pDir->Size)); … … 1945 2902 for (unsigned cSHdrsLeft = cSections; cSHdrsLeft > 0; cSHdrsLeft--, pSH++) 1946 2903 { 1947 const unsigned iSH = pSH - &paSections[0]; NOREF(iSH);2904 const unsigned iSH = (unsigned)(pSH - &paSections[0]); NOREF(iSH); 1948 2905 Log3(("RTLdrPE: #%d '%-8.8s' Characteristics: %08RX32\n" 1949 2906 "RTLdrPE: VirtAddr: %08RX32 VirtSize: %08RX32\n" … … 2110 3067 2111 3068 /** 2112 * Validates the data of some selected data directories entries. 2113 * 2114 * This requires a valid section table and thus has to wait 2115 * till after we've read and validated it. 3069 * Validates the data of some selected data directories entries and remember 3070 * important bits for later. 3071 * 3072 * This requires a valid section table and thus has to wait till after we've 3073 * read and validated it. 2116 3074 * 2117 3075 * @returns iprt status code. … … 2120 3078 * @param fFlags Loader flags, RTLDR_O_XXX. 2121 3079 */ 2122 static int rtldrPEValidateDirectories (PRTLDRMODPE pModPe, const IMAGE_OPTIONAL_HEADER64 *pOptHdr, uint32_t fFlags)3080 static int rtldrPEValidateDirectoriesAndRememberStuff(PRTLDRMODPE pModPe, const IMAGE_OPTIONAL_HEADER64 *pOptHdr, uint32_t fFlags) 2123 3081 { 2124 3082 const char *pszLogName = pModPe->Core.pReader->pfnLogName(pModPe->Core.pReader); NOREF(pszLogName); … … 2136 3094 if (Dir.Size) 2137 3095 { 2138 const size_t cbExpect = pOptHdr->Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC 2139 ? sizeof(IMAGE_LOAD_CONFIG_DIRECTORY32) 2140 : sizeof(IMAGE_LOAD_CONFIG_DIRECTORY64); 2141 if ( Dir.Size != cbExpect 2142 && ( cbExpect == sizeof(IMAGE_LOAD_CONFIG_DIRECTORY32) 2143 && Dir.Size != (uint32_t)RT_OFFSETOF(IMAGE_LOAD_CONFIG_DIRECTORY32, SEHandlerTable)) 2144 ) 2145 { 2146 Log(("rtldrPEOpen: %s: load cfg dir: unexpected dir size of %d bytes, expected %d.\n", 2147 pszLogName, Dir.Size, cbExpect)); 3096 const size_t cbExpectV3 = !pModPe->f64Bit 3097 ? sizeof(IMAGE_LOAD_CONFIG_DIRECTORY32_V3) 3098 : sizeof(IMAGE_LOAD_CONFIG_DIRECTORY64_V3); 3099 const size_t cbExpectV2 = !pModPe->f64Bit 3100 ? sizeof(IMAGE_LOAD_CONFIG_DIRECTORY32_V2) 3101 : sizeof(IMAGE_LOAD_CONFIG_DIRECTORY64_V2); 3102 const size_t cbExpectV1 = !pModPe->f64Bit 3103 ? sizeof(IMAGE_LOAD_CONFIG_DIRECTORY32_V1) 3104 : sizeof(IMAGE_LOAD_CONFIG_DIRECTORY64_V2) /*No V1*/; 3105 3106 if ( Dir.Size != cbExpectV3 3107 && Dir.Size != cbExpectV2 3108 && Dir.Size != cbExpectV1) 3109 { 3110 Log(("rtldrPEOpen: %s: load cfg dir: unexpected dir size of %d bytes, expected %d, %d, or %d.\n", 3111 pszLogName, Dir.Size, cbExpectV3, cbExpectV2, cbExpectV1)); 2148 3112 return VERR_LDRPE_LOAD_CONFIG_SIZE; 2149 3113 } … … 2158 3122 rtldrPEConvert32BitLoadConfigTo64Bit(&u.Cfg64); 2159 3123 2160 if (u.Cfg64.Size != cbExpect) 2161 { 2162 Log(("rtldrPEOpen: %s: load cfg dir: unexpected header size of %d bytes, expected %d.\n", 2163 pszLogName, u.Cfg64.Size, cbExpect)); 2164 return VERR_LDRPE_LOAD_CONFIG_SIZE; 2165 } 2166 if (u.Cfg64.LockPrefixTable) 3124 if (u.Cfg64.Size != Dir.Size) 3125 { 3126 /* Kludge, seen ati shipping 32-bit DLLs and EXEs with Dir.Size=0x40 3127 and Cfg64.Size=0x5c or 0x48. Windows seems to deal with it, so 3128 lets do so as well. */ 3129 if ( Dir.Size < u.Cfg64.Size 3130 && ( u.Cfg64.Size == cbExpectV3 3131 || u.Cfg64.Size == cbExpectV2) ) 3132 { 3133 Log(("rtldrPEOpen: %s: load cfg dir: Header (%d) and directory (%d) size mismatch, applying the ATI kludge\n", 3134 pszLogName, u.Cfg64.Size, Dir.Size)); 3135 Dir.Size = u.Cfg64.Size; 3136 memset(&u.Cfg64, 0, sizeof(u.Cfg64)); 3137 rc = rtldrPEReadRVA(pModPe, &u.Cfg64, Dir.Size, Dir.VirtualAddress); 3138 if (RT_FAILURE(rc)) 3139 return rc; 3140 rtldrPEConvert32BitLoadConfigTo64Bit(&u.Cfg64); 3141 } 3142 if (u.Cfg64.Size != Dir.Size) 3143 { 3144 Log(("rtldrPEOpen: %s: load cfg dir: unexpected header size of %d bytes, expected %d.\n", 3145 pszLogName, u.Cfg64.Size, Dir.Size)); 3146 return VERR_LDRPE_LOAD_CONFIG_SIZE; 3147 } 3148 } 3149 if (u.Cfg64.LockPrefixTable && !(fFlags & (RTLDR_O_FOR_DEBUG | RTLDR_O_FOR_VALIDATION))) 2167 3150 { 2168 3151 Log(("rtldrPEOpen: %s: load cfg dir: lock prefix table at %RX64. We don't support lock prefix tables!\n", … … 2179 3162 } 2180 3163 #endif 2181 if (u.Cfg64.EditList )3164 if (u.Cfg64.EditList && !(fFlags & (RTLDR_O_FOR_DEBUG | RTLDR_O_FOR_VALIDATION))) 2182 3165 { 2183 3166 Log(("rtldrPEOpen: %s: load cfg dir: EditList=%RX64 is unsupported!\n", … … 2185 3168 return VERR_BAD_EXE_FORMAT; 2186 3169 } 3170 /** @todo GuardCFC? Possibly related to: 3171 * http://research.microsoft.com/pubs/69217/ccs05-cfi.pdf 3172 * Not trusting something designed by bakas who don't know how to modify a 3173 * structure without messing up its natural alignment. */ 3174 if ( ( u.Cfg64.GuardCFCCheckFunctionPointer 3175 || u.Cfg64.Reserved2 3176 || u.Cfg64.GuardCFFunctionTable 3177 || u.Cfg64.GuardCFFunctionCount 3178 || u.Cfg64.GuardFlags) 3179 && !(fFlags & (RTLDR_O_FOR_DEBUG | RTLDR_O_FOR_VALIDATION))) 3180 { 3181 Log(("rtldrPEOpen: %s: load cfg dir: Guard stuff: %RX64,%RX64,%RX64,%RX64,%RX32!\n", 3182 pszLogName, u.Cfg64.GuardCFCCheckFunctionPointer, u.Cfg64.Reserved2, 3183 u.Cfg64.GuardCFFunctionTable, u.Cfg64.GuardCFFunctionCount, u.Cfg64.GuardFlags)); 3184 return VERR_BAD_EXE_FORMAT; 3185 } 2187 3186 } 2188 3187 … … 2192 3191 */ 2193 3192 Dir = pOptHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY]; 2194 if (Dir.Size && !(fFlags & RTLDR_O_FOR_DEBUG))3193 if (Dir.Size) 2195 3194 { 2196 3195 PWIN_CERTIFICATE pFirst = (PWIN_CERTIFICATE)RTMemTmpAlloc(Dir.Size); … … 2200 3199 if (RT_SUCCESS(rc)) 2201 3200 { 2202 uint32_t off = 0; 2203 PWIN_CERTIFICATE pCur = pFirst; 3201 uint32_t off = 0; 2204 3202 do 2205 3203 { 3204 PWIN_CERTIFICATE pCur = (PWIN_CERTIFICATE)((uint8_t *)pFirst + off); 3205 2206 3206 /* validate the members. */ 2207 uint32_t const cbCur = RT_ALIGN_32(pCur->dwLength, 8); 2208 if ( cbCur < sizeof(WIN_CERTIFICATE) 2209 || cbCur + off > RT_ALIGN_32(Dir.Size, 8)) 3207 if ( pCur->dwLength < sizeof(WIN_CERTIFICATE) 3208 || pCur->dwLength + off > Dir.Size) 2210 3209 { 2211 3210 Log(("rtldrPEOpen: %s: cert at %#x/%#x: dwLength=%#x\n", pszLogName, off, Dir.Size, pCur->dwLength)); … … 2233 3232 } 2234 3233 2235 /** @todo Rainy Day: Implement further verification using openssl. */ 3234 /* Remember the first signed data certificate. */ 3235 if ( pCur->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA 3236 && pModPe->offPkcs7SignedData == 0) 3237 { 3238 pModPe->offPkcs7SignedData = Dir.VirtualAddress 3239 + (uint32_t)((uintptr_t)&pCur->bCertificate[0] - (uintptr_t)pFirst); 3240 pModPe->cbPkcs7SignedData = pCur->dwLength - RT_OFFSETOF(WIN_CERTIFICATE, bCertificate); 3241 } 2236 3242 2237 3243 /* next */ 2238 off += cbCur; 2239 pCur = (PWIN_CERTIFICATE)((uint8_t *)pCur + cbCur); 3244 off += RT_ALIGN(pCur->dwLength, WIN_CERTIFICATE_ALIGNMENT); 2240 3245 } while (off < Dir.Size); 2241 3246 } … … 2259 3264 * @param offNtHdrs The offset of the NT headers (where you find "PE\0\0"). 2260 3265 * @param phLdrMod Where to store the handle. 2261 */ 2262 int rtldrPEOpen(PRTLDRREADER pReader, uint32_t fFlags, RTLDRARCH enmArch, RTFOFF offNtHdrs, PRTLDRMOD phLdrMod) 3266 * @param pErrInfo Where to return extended error information. Optional. 3267 */ 3268 int rtldrPEOpen(PRTLDRREADER pReader, uint32_t fFlags, RTLDRARCH enmArch, RTFOFF offNtHdrs, 3269 PRTLDRMOD phLdrMod, PRTERRINFO pErrInfo) 2263 3270 { 2264 3271 /* … … 2349 3356 pModPe->cbHeaders = OptHdr.SizeOfHeaders; 2350 3357 pModPe->uTimestamp = FileHdr.TimeDateStamp; 3358 pModPe->f64Bit = FileHdr.SizeOfOptionalHeader == sizeof(OptHdr); 2351 3359 pModPe->ImportDir = OptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; 2352 3360 pModPe->RelocDir = OptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; 2353 3361 pModPe->ExportDir = OptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; 2354 3362 pModPe->DebugDir = OptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG]; 3363 pModPe->SecurityDir = OptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY]; 3364 pModPe->fDllCharacteristics = OptHdr.DllCharacteristics; 2355 3365 2356 3366 /* 2357 3367 * Perform validation of some selected data directories which requires 2358 * inspection of the actual data. 3368 * inspection of the actual data. This also saves some certificate 3369 * information. 2359 3370 */ 2360 rc = rtldrPEValidateDirectories (pModPe, &OptHdr, fFlags);3371 rc = rtldrPEValidateDirectoriesAndRememberStuff(pModPe, &OptHdr, fFlags); 2361 3372 if (RT_SUCCESS(rc)) 2362 3373 {
注意:
瀏覽 TracChangeset
來幫助您使用更動檢視器