From 303631f9d7f753dacffb1e038dd273dc204e1ea9 Mon Sep 17 00:00:00 2001 From: Ladislav Zezula Date: Sat, 18 Jun 2016 20:32:15 +0200 Subject: + Updated for protectors fiddling with too big block table index --- src/SBaseFileTable.cpp | 46 ++++++++++++++++++---------------------------- 1 file changed, 18 insertions(+), 28 deletions(-) (limited to 'src/SBaseFileTable.cpp') diff --git a/src/SBaseFileTable.cpp b/src/SBaseFileTable.cpp index 9d37ff1..981328b 100644 --- a/src/SBaseFileTable.cpp +++ b/src/SBaseFileTable.cpp @@ -581,11 +581,9 @@ int ConvertMpqHeaderToFormat4( // Hash entry verification when the file table does not exist yet bool IsValidHashEntry(TMPQArchive * ha, TMPQHash * pHash) { - TFileEntry * pFileEntry = ha->pFileTable + MPQ_BLOCK_INDEX(pHash->dwBlockIndex); - DWORD dwBlockIndex = MPQ_BLOCK_INDEX(pHash->dwBlockIndex); + TFileEntry * pFileEntry = ha->pFileTable + MPQ_BLOCK_INDEX(pHash); - pFileEntry = ha->pFileTable + dwBlockIndex; - return ((dwBlockIndex < ha->dwFileTableSize) && (pFileEntry->dwFlags & MPQ_FILE_EXISTS)) ? true : false; + return ((MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize) && (pFileEntry->dwFlags & MPQ_FILE_EXISTS)) ? true : false; } // Hash entry verification when the file table does not exist yet @@ -593,20 +591,12 @@ static bool IsValidHashEntry1(TMPQArchive * ha, TMPQHash * pHash, TMPQBlock * pB { ULONGLONG ByteOffset; TMPQBlock * pBlock; - DWORD dwBlockIndex; - - // We need to mask out the upper 4 bits of the block table index. - // This is because it gets shifted out when calculating block table offset - // BlockTableOffset = pHash->dwBlockIndex * 0x10 - // Malformed MPQ maps may contain invalid entries - // Note that Storm.dll does not perfom this check - dwBlockIndex = MPQ_BLOCK_INDEX(pHash->dwBlockIndex); // The block index is considered valid if it's less than block table size - if(dwBlockIndex < ha->pHeader->dwBlockTableSize) + if(MPQ_BLOCK_INDEX(pHash) < ha->pHeader->dwBlockTableSize) { // Calculate the block table position - pBlock = pBlockTable + dwBlockIndex; + pBlock = pBlockTable + MPQ_BLOCK_INDEX(pHash); // Check whether this is an existing file // Also we do not allow to be file size greater than 2GB @@ -787,28 +777,28 @@ static int BuildFileTableFromBlockTable( // - Multiple hash entries (different file name) point to the same block entry // // Ignore all hash table entries where: - // - dwBlockIndex >= BlockTableSize + // - Block Index >= BlockTableSize // - Flags of the appropriate block table entry // if(IsValidHashEntry1(ha, pHash, pBlockTable)) { - DWORD dwBlockIndex = MPQ_BLOCK_INDEX(pHash->dwBlockIndex); - DWORD dwNewIndex = MPQ_BLOCK_INDEX(pHash->dwBlockIndex); + DWORD dwOldIndex = MPQ_BLOCK_INDEX(pHash); + DWORD dwNewIndex = MPQ_BLOCK_INDEX(pHash); // Determine the new block index if(DefragmentTable != NULL) { // Need to handle case when multiple hash // entries point to the same block entry - if(DefragmentTable[dwBlockIndex] == HASH_ENTRY_FREE) + if(DefragmentTable[dwOldIndex] == HASH_ENTRY_FREE) { - DefragmentTable[dwBlockIndex] = dwItemCount; + DefragmentTable[dwOldIndex] = dwItemCount; dwNewIndex = dwItemCount++; } else { - dwNewIndex = DefragmentTable[dwBlockIndex]; + dwNewIndex = DefragmentTable[dwOldIndex]; } // Fix the pointer in the hash entry @@ -820,7 +810,7 @@ static int BuildFileTableFromBlockTable( // Get the pointer to the file entry and the block entry pFileEntry = ha->pFileTable + dwNewIndex; - pBlock = pBlockTable + dwBlockIndex; + pBlock = pBlockTable + dwOldIndex; // ByteOffset is only valid if file size is not zero pFileEntry->ByteOffset = pBlock->dwFilePos; @@ -1814,11 +1804,11 @@ TFileEntry * GetFileEntryLocale2(TMPQArchive * ha, const char * szFileName, LCID if(ha->pHashTable != NULL) { pHash = GetHashEntryLocale(ha, szFileName, lcLocale); - if(pHash != NULL && pHash->dwBlockIndex < ha->dwFileTableSize) + if(pHash != NULL && MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize) { if(PtrHashIndex != NULL) PtrHashIndex[0] = (DWORD)(pHash - ha->pHashTable); - return ha->pFileTable + pHash->dwBlockIndex; + return ha->pFileTable + MPQ_BLOCK_INDEX(pHash); } } @@ -1848,11 +1838,11 @@ TFileEntry * GetFileEntryExact(TMPQArchive * ha, const char * szFileName, LCID l if(ha->pHashTable != NULL) { pHash = GetHashEntryExact(ha, szFileName, lcLocale); - if(pHash != NULL && pHash->dwBlockIndex < ha->dwFileTableSize) + if(pHash != NULL && MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize) { if(PtrHashIndex != NULL) PtrHashIndex[0] = (DWORD)(pHash - ha->pHashTable); - return ha->pFileTable + pHash->dwBlockIndex; + return ha->pFileTable + MPQ_BLOCK_INDEX(pHash); } } @@ -2640,11 +2630,11 @@ int DefragmentFileTable(TMPQArchive * ha) for(pHash = ha->pHashTable; pHash < pHashTableEnd; pHash++) { - if(pHash->dwBlockIndex < ha->dwFileTableSize) + if(MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize) { // If that block entry is there, set it to the hash entry // If not, set it as DELETED - dwNewBlockIndex = DefragmentTable[pHash->dwBlockIndex]; + dwNewBlockIndex = DefragmentTable[MPQ_BLOCK_INDEX(pHash)]; pHash->dwBlockIndex = (dwNewBlockIndex != HASH_ENTRY_FREE) ? dwNewBlockIndex : HASH_ENTRY_DELETED; } } @@ -2753,7 +2743,7 @@ int RebuildFileTable(TMPQArchive * ha, DWORD dwNewHashTableSize) { if(IsValidHashEntry(ha, pHash)) { - pFileEntry = ha->pFileTable + pHash->dwBlockIndex; + pFileEntry = ha->pFileTable + MPQ_BLOCK_INDEX(pHash); AllocateHashEntry(ha, pFileEntry, pHash->lcLocale); } } -- cgit v1.2.3