From b13aaed6d0a940934dcb26aa3cb28ffc0dd06c48 Mon Sep 17 00:00:00 2001 From: Ladislav Zezula Date: Wed, 18 Nov 2020 19:12:53 +0100 Subject: Fixed some variants of NP_Protect-ed maps --- src/SBaseFileTable.cpp | 97 +++++++++++++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 40 deletions(-) (limited to 'src/SBaseFileTable.cpp') diff --git a/src/SBaseFileTable.cpp b/src/SBaseFileTable.cpp index e08daef..af8d290 100644 --- a/src/SBaseFileTable.cpp +++ b/src/SBaseFileTable.cpp @@ -57,11 +57,11 @@ static DWORD GetNecessaryBitCount(ULONGLONG MaxValue) } //----------------------------------------------------------------------------- -// Implementation of the TStormBits struc +// Implementation of the TMPQBits struct -struct TStormBits +struct TMPQBits { - static TStormBits * Create(DWORD NumberOfBits, BYTE FillValue); + static TMPQBits * Create(DWORD NumberOfBits, BYTE FillValue); void GetBits(unsigned int nBitPosition, unsigned int nBitLength, void * pvBuffer, int nResultSize); void SetBits(unsigned int nBitPosition, unsigned int nBitLength, void * pvBuffer, int nResultSize); @@ -73,17 +73,17 @@ struct TStormBits BYTE Elements[1]; // Array of elements (variable length) }; -const USHORT TStormBits::SetBitsMask[] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF}; +const USHORT TMPQBits::SetBitsMask[] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF}; -TStormBits * TStormBits::Create( +TMPQBits * TMPQBits::Create( DWORD NumberOfBits, BYTE FillValue) { - TStormBits * pBitArray; - size_t nSize = sizeof(TStormBits) + (NumberOfBits + 7) / 8; + TMPQBits * pBitArray; + size_t nSize = sizeof(TMPQBits) + (NumberOfBits + 7) / 8; // Allocate the bit array - pBitArray = (TStormBits *)STORM_ALLOC(BYTE, nSize); + pBitArray = (TMPQBits *)STORM_ALLOC(BYTE, nSize); if(pBitArray != NULL) { memset(pBitArray, FillValue, nSize); @@ -94,7 +94,7 @@ TStormBits * TStormBits::Create( return pBitArray; } -void TStormBits::GetBits( +void TMPQBits::GetBits( unsigned int nBitPosition, unsigned int nBitLength, void * pvBuffer, @@ -159,7 +159,7 @@ void TStormBits::GetBits( } } -void TStormBits::SetBits( +void TMPQBits::SetBits( unsigned int nBitPosition, unsigned int nBitLength, void * pvBuffer, @@ -225,6 +225,11 @@ void TStormBits::SetBits( } } +void GetMPQBits(TMPQBits * pBits, unsigned int nBitPosition, unsigned int nBitLength, void * pvBuffer, int nResultByteSize) +{ + pBits->GetBits(nBitPosition, nBitLength, pvBuffer, nResultByteSize); +} + //----------------------------------------------------------------------------- // Support for MPQ header @@ -234,19 +239,22 @@ static bool VerifyTablePosition64( ULONGLONG TableSize, // Size of the MPQ table, in bytes ULONGLONG FileSize) // Size of the entire file, in bytes { - // Verify overflows - if((MpqOffset + TableOffset) < MpqOffset) - return false; - if((MpqOffset + TableOffset + TableSize) < MpqOffset) - return false; - - // Verify sizes - if(TableOffset >= FileSize || TableSize >= FileSize) - return false; - if((MpqOffset + TableOffset) >= FileSize) - return false; - if((MpqOffset + TableOffset + TableSize) >= FileSize) - return false; + if(TableOffset != 0) + { + // Verify overflows + if((MpqOffset + TableOffset) < MpqOffset) + return false; + if((MpqOffset + TableOffset + TableSize) < MpqOffset) + return false; + + // Verify sizes + if(TableOffset >= FileSize || TableSize >= FileSize) + return false; + if((MpqOffset + TableOffset) >= FileSize) + return false; + if((MpqOffset + TableOffset + TableSize) >= FileSize) + return false; + } return true; } @@ -333,10 +341,21 @@ static ULONGLONG DetermineArchiveSize_V4( // This could only be called for MPQs version 4 assert(pHeader->wFormatVersion == MPQ_FORMAT_VERSION_4); - // Determine the archive size as the greatest of all valid values - EndOfTable = pHeader->BetTablePos64 + pHeader->BetTableSize64; - if(EndOfTable > ArchiveSize) - ArchiveSize = EndOfTable; + // Check position of BET table, if correct + if((pHeader->BetTablePos64 >> 0x20) == 0 && (pHeader->BetTableSize64 >> 0x20) == 0) + { + EndOfTable = pHeader->BetTablePos64 + pHeader->BetTableSize64; + if(EndOfTable > ArchiveSize) + ArchiveSize = EndOfTable; + } + + // Check position of HET table, if correct + if((pHeader->HetTablePos64 >> 0x20) == 0 && (pHeader->HetTableSize64 >> 0x20) == 0) + { + EndOfTable = pHeader->HetTablePos64 + pHeader->HetTableSize64; + if(EndOfTable > ArchiveSize) + ArchiveSize = EndOfTable; + } EndOfTable = pHeader->dwHashTablePos + pHeader->dwHashTableSize * sizeof(TMPQHash); if(EndOfTable > ArchiveSize) @@ -346,10 +365,6 @@ static ULONGLONG DetermineArchiveSize_V4( if(EndOfTable > ArchiveSize) ArchiveSize = EndOfTable; - EndOfTable = pHeader->HetTablePos64 + pHeader->HetTableSize64; - if(EndOfTable > ArchiveSize) - ArchiveSize = EndOfTable; - // Return the calculated archive size return ArchiveSize; } @@ -628,6 +643,8 @@ int ConvertMpqHeaderToFormat4( return ERROR_FAKE_MPQ_HEADER; if(!VerifyTablePosition64(MpqOffset, pHeader->HiBlockTablePos64, pHeader->HiBlockTableSize64, FileSize)) return ERROR_FAKE_MPQ_HEADER; + if(!VerifyTablePosition64(MpqOffset, pHeader->HetTablePos64, pHeader->HetTableSize64, FileSize)) + return ERROR_FAKE_MPQ_HEADER; // Check for malformed MPQs if(pHeader->wFormatVersion != MPQ_FORMAT_VERSION_4 || (ha->MpqPos + pHeader->ArchiveSize64) != FileSize || (ha->MpqPos + pHeader->HiBlockTablePos64) >= FileSize) @@ -1332,7 +1349,7 @@ TMPQHetTable * CreateHetTable(DWORD dwEntryCount, DWORD dwTotalCount, DWORD dwNa memset(pHetTable->pNameHashes, 0, dwTotalCount); // Allocate the bit array for file indexes - pHetTable->pBetIndexes = TStormBits::Create(dwTotalCount * pHetTable->dwIndexSizeTotal, 0xFF); + pHetTable->pBetIndexes = TMPQBits::Create(dwTotalCount * pHetTable->dwIndexSizeTotal, 0xFF); if(pHetTable->pBetIndexes != NULL) { // Initialize the HET table from the source data (if given) @@ -1732,7 +1749,7 @@ static TMPQBetTable * TranslateBetTable( } // Load the bit-based file table - pBetTable->pFileTable = TStormBits::Create(pBetTable->dwTableEntrySize * pBetHeader->dwEntryCount, 0); + pBetTable->pFileTable = TMPQBits::Create(pBetTable->dwTableEntrySize * pBetHeader->dwEntryCount, 0); if(pBetTable->pFileTable != NULL) { LengthInBytes = (pBetTable->pFileTable->NumberOfBits + 7) / 8; @@ -1746,7 +1763,7 @@ static TMPQBetTable * TranslateBetTable( pBetTable->dwBitCount_NameHash2 = pBetHeader->dwBitCount_NameHash2; // Create and load the array of BET hashes - pBetTable->pNameHashes = TStormBits::Create(pBetTable->dwBitTotal_NameHash2 * pBetHeader->dwEntryCount, 0); + pBetTable->pNameHashes = TMPQBits::Create(pBetTable->dwBitTotal_NameHash2 * pBetHeader->dwEntryCount, 0); if(pBetTable->pNameHashes != NULL) { LengthInBytes = (pBetTable->pNameHashes->NumberOfBits + 7) / 8; @@ -1771,7 +1788,7 @@ TMPQExtHeader * TranslateBetTable( TMPQBetHeader BetHeader; TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize; TFileEntry * pFileEntry; - TStormBits * pBitArray = NULL; + TMPQBits * pBitArray = NULL; LPBYTE pbLinearTable = NULL; LPBYTE pbTrgData; DWORD LengthInBytes; @@ -1791,7 +1808,7 @@ TMPQExtHeader * TranslateBetTable( pbTrgData = (LPBYTE)(pBetHeader + 1); // Save the bit-based block table - pBitArray = TStormBits::Create(BetHeader.dwEntryCount * BetHeader.dwTableEntrySize, 0); + pBitArray = TMPQBits::Create(BetHeader.dwEntryCount * BetHeader.dwTableEntrySize, 0); if(pBitArray != NULL) { DWORD dwFlagIndex = 0; @@ -1846,7 +1863,7 @@ TMPQExtHeader * TranslateBetTable( } // Create bit array for name hashes - pBitArray = TStormBits::Create(BetHeader.dwBitTotal_NameHash2 * BetHeader.dwEntryCount, 0); + pBitArray = TMPQBits::Create(BetHeader.dwBitTotal_NameHash2 * BetHeader.dwEntryCount, 0); if(pBitArray != NULL) { DWORD dwFileIndex = 0; @@ -2376,7 +2393,7 @@ TMPQHetTable * LoadHetTable(TMPQArchive * ha) TMPQHeader * pHeader = ha->pHeader; // If the HET table position is not 0, we expect the table to be present - if(pHeader->HetTablePos64 != 0 && pHeader->HetTableSize64 != 0) + if(pHeader->HetTablePos64 && pHeader->HetTableSize64) { // Attempt to load the HET table (Hash Extended Table) pExtTable = LoadExtTable(ha, pHeader->HetTablePos64, (size_t)pHeader->HetTableSize64, HET_TABLE_SIGNATURE, MPQ_KEY_HASH_TABLE); @@ -2398,7 +2415,7 @@ TMPQBetTable * LoadBetTable(TMPQArchive * ha) TMPQHeader * pHeader = ha->pHeader; // If the BET table position is not 0, we expect the table to be present - if(pHeader->BetTablePos64 != 0 && pHeader->BetTableSize64 != 0) + if(pHeader->BetTablePos64 && pHeader->BetTableSize64) { // Attempt to load the HET table (Hash Extended Table) pExtTable = LoadExtTable(ha, pHeader->BetTablePos64, (size_t)pHeader->BetTableSize64, BET_TABLE_SIGNATURE, MPQ_KEY_BLOCK_TABLE); @@ -2518,7 +2535,7 @@ static int BuildFileTable_HetBet(TMPQArchive * ha) TMPQHetTable * pHetTable = ha->pHetTable; TMPQBetTable * pBetTable; TFileEntry * pFileEntry = ha->pFileTable; - TStormBits * pBitArray; + TMPQBits * pBitArray; DWORD dwBitPosition = 0; DWORD i; int nError = ERROR_FILE_CORRUPT; -- cgit v1.2.3