aboutsummaryrefslogtreecommitdiff
path: root/NorthstarDedicatedTest/ExploitFixes.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'NorthstarDedicatedTest/ExploitFixes.cpp')
-rw-r--r--NorthstarDedicatedTest/ExploitFixes.cpp77
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()