From 0bfeaed44a8d669d4d292bc1a2caf75cdf3d50e9 Mon Sep 17 00:00:00 2001 From: nithax <43627008+nithax@users.noreply.github.com> Date: Fri, 4 Apr 2025 10:01:18 -0400 Subject: [PATCH] XEX2 Loading Fixes (#51) * Fixes loading .xex import table names when a name is not aligned to 4 bytes. * Fixes loading .xex optional headers, adds missing case when the header_key & 0xFF == 1 * Fixes loading .xex base address and entry point to be the XEX2 base/entry to successfully resolve all import thunks. --- XenonUtils/xex.cpp | 20 ++++++++++++++++---- XenonUtils/xex.h | 10 +++++++--- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/XenonUtils/xex.cpp b/XenonUtils/xex.cpp index d1972c0..c12d63c 100644 --- a/XenonUtils/xex.cpp +++ b/XenonUtils/xex.cpp @@ -201,8 +201,17 @@ Image Xex2LoadImage(const uint8_t* data, size_t dataSize) const auto* dosHeader = reinterpret_cast(image.data.get()); const auto* ntHeaders = reinterpret_cast(image.data.get() + dosHeader->e_lfanew); - image.base = ntHeaders->OptionalHeader.ImageBase; - image.entry_point = image.base + ntHeaders->OptionalHeader.AddressOfEntryPoint; + image.base = security->loadAddress; + const void* xex2BaseAddressPtr = getOptHeaderPtr(data, XEX_HEADER_IMAGE_BASE_ADDRESS); + if (xex2BaseAddressPtr != nullptr) + { + image.base = *reinterpret_cast*>(xex2BaseAddressPtr); + } + const void* xex2EntryPointPtr = getOptHeaderPtr(data, XEX_HEADER_ENTRY_POINT); + if (xex2EntryPointPtr != nullptr) + { + image.entry_point = *reinterpret_cast*>(xex2EntryPointPtr); + } const auto numSections = ntHeaders->FileHeader.NumberOfSections; const auto* sections = reinterpret_cast(ntHeaders + 1); @@ -227,10 +236,13 @@ Image Xex2LoadImage(const uint8_t* data, size_t dataSize) std::vector stringTable; auto* pStrTable = reinterpret_cast(imports + 1); + size_t paddedStringOffset = 0; for (size_t i = 0; i < imports->numImports; i++) { - stringTable.emplace_back(pStrTable); - pStrTable += strlen(pStrTable) + 1; + stringTable.emplace_back(pStrTable + paddedStringOffset); + + // pad the offset to the next multiple of 4 + paddedStringOffset += ((stringTable.back().length() + 1) + 3) & ~3; } auto* library = (Xex2ImportLibrary*)(((char*)imports) + sizeof(Xex2ImportHeader) + imports->sizeOfStringTable); diff --git a/XenonUtils/xex.h b/XenonUtils/xex.h index 9ab831e..363efff 100644 --- a/XenonUtils/xex.h +++ b/XenonUtils/xex.h @@ -245,13 +245,17 @@ inline const void* getOptHeaderPtr(const uint8_t* moduleBytes, uint32_t headerKe const Xex2OptHeader& optHeader = ((const Xex2OptHeader*)(xex2Header + 1))[i]; if (optHeader.key == headerKey) { - if ((headerKey & 0xFF) == 0) + if((headerKey & 0xFF) == 0) { - return &optHeader.value; + return reinterpret_cast(&optHeader.value); + } + else if ((headerKey & 0xFF) == 1) + { + return reinterpret_cast(&optHeader.value); } else { - return &moduleBytes[optHeader.offset]; + return reinterpret_cast(reinterpret_cast(moduleBytes) + optHeader.offset); } } }