diff options
Diffstat (limited to 'NorthstarDedicatedTest/ExploitFixes.cpp')
-rw-r--r-- | NorthstarDedicatedTest/ExploitFixes.cpp | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/NorthstarDedicatedTest/ExploitFixes.cpp b/NorthstarDedicatedTest/ExploitFixes.cpp index af7d48ac..84ccc997 100644 --- a/NorthstarDedicatedTest/ExploitFixes.cpp +++ b/NorthstarDedicatedTest/ExploitFixes.cpp @@ -365,6 +365,83 @@ static void* GetEntByIndexHook(int idx) return GetEntByIndex(idx); } +// RELOCATED FROM https://github.com/R2Northstar/NorthstarLauncher/commit/25dbf729cfc75107a0fcf0186924b58ecc05214b +// Rewrite of CLZSS::SafeUncompress to fix a vulnerability where malicious compressed payloads could cause the decompressor to try to read +// out of the bounds of the output buffer. +KHOOK( + LZSS_SafeUncompress, + ("engine.dll", "48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 33 ED 41 8B F9"), + uint32_t, + __fastcall, + (void* self, const unsigned char* pInput, unsigned char* pOutput, unsigned int unBufSize)) +{ + static constexpr int LZSS_LOOKSHIFT = 4; + + uint32_t totalBytes = 0; + int getCmdByte = 0, cmdByte = 0; + + struct lzss_header_t + { + uint32_t id, actualSize; + }; + + lzss_header_t header = *(lzss_header_t*)pInput; + + if (pInput == NULL || header.id != 'SSZL' || header.actualSize == 0 || header.actualSize > unBufSize) + return 0; + + pInput += sizeof(lzss_header_t); + + for (;;) + { + if (!getCmdByte) + cmdByte = *pInput++; + + getCmdByte = (getCmdByte + 1) & 0x07; + + if (cmdByte & 0x01) + { + int position = *pInput++ << LZSS_LOOKSHIFT; + position |= (*pInput >> LZSS_LOOKSHIFT); + position += 1; + + int count = (*pInput++ & 0x0F) + 1; + if (count == 1) + break; + + // Ensure reference chunk exists entirely within our buffer + if (position > totalBytes) + return 0; + + totalBytes += count; + if (totalBytes > unBufSize) + return 0; + + unsigned char* pSource = pOutput - position; + for (int i = 0; i < count; i++) + *pOutput++ = *pSource++; + } + else + { + totalBytes++; + if (totalBytes > unBufSize) + return 0; + + *pOutput++ = *pInput++; + } + cmdByte = cmdByte >> 1; + } + + if (totalBytes == header.actualSize) + { + return totalBytes; + } + else + { + return 0; + } +} + ////////////////////////////////////////////////// void DoBytePatches() |