[ZoneBuilder] Better FastFile obfuscation
This commit is contained in:
parent
745f27429a
commit
3e20ca366a
@ -9,6 +9,8 @@ namespace Components
|
|||||||
bool FastFiles::IsIW4xZone = false;
|
bool FastFiles::IsIW4xZone = false;
|
||||||
bool FastFiles::StreamRead = false;
|
bool FastFiles::StreamRead = false;
|
||||||
|
|
||||||
|
char FastFiles::LastByteRead = 0;
|
||||||
|
|
||||||
unsigned int FastFiles::CurrentZone;
|
unsigned int FastFiles::CurrentZone;
|
||||||
unsigned int FastFiles::MaxZones;
|
unsigned int FastFiles::MaxZones;
|
||||||
|
|
||||||
@ -332,6 +334,7 @@ namespace Components
|
|||||||
void FastFiles::ReadHeaderStub(unsigned int* header, int size)
|
void FastFiles::ReadHeaderStub(unsigned int* header, int size)
|
||||||
{
|
{
|
||||||
FastFiles::IsIW4xZone = false;
|
FastFiles::IsIW4xZone = false;
|
||||||
|
FastFiles::LastByteRead = 0;
|
||||||
Game::DB_ReadXFileUncompressed(header, size);
|
Game::DB_ReadXFileUncompressed(header, size);
|
||||||
|
|
||||||
if (header[0] == XFILE_HEADER_IW4X)
|
if (header[0] == XFILE_HEADER_IW4X)
|
||||||
@ -439,6 +442,36 @@ namespace Components
|
|||||||
Utils::Hook::Call<void(Game::XZoneInfo*, unsigned int)>(0x5BBAC0)(zoneInfo, zoneCount);
|
Utils::Hook::Call<void(Game::XZoneInfo*, unsigned int)>(0x5BBAC0)(zoneInfo, zoneCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__declspec(naked) void FastFiles::ReadXFile(void* /*buffer*/, int /*size*/)
|
||||||
|
{
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
mov eax, [esp + 4]
|
||||||
|
mov ecx, [esp + 8]
|
||||||
|
|
||||||
|
push 445468h
|
||||||
|
retn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FastFiles::ReadXFileStub(char* buffer, int size)
|
||||||
|
{
|
||||||
|
FastFiles::ReadXFile(buffer, size);
|
||||||
|
|
||||||
|
if(FastFiles::IsIW4xZone)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < size; ++i)
|
||||||
|
{
|
||||||
|
buffer[i] ^= FastFiles::LastByteRead;
|
||||||
|
Utils::RotLeft(buffer[i], 4);
|
||||||
|
buffer[i] ^= -1;
|
||||||
|
Utils::RotRight(buffer[i], 6);
|
||||||
|
|
||||||
|
FastFiles::LastByteRead = buffer[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void FastFiles::LogStreamRead(int len)
|
void FastFiles::LogStreamRead(int len)
|
||||||
{
|
{
|
||||||
@ -466,6 +499,9 @@ namespace Components
|
|||||||
// Allow loading IW4x zones
|
// Allow loading IW4x zones
|
||||||
Utils::Hook(0x4157B8, FastFiles::ReadHeaderStub, HOOK_CALL).install()->quick();
|
Utils::Hook(0x4157B8, FastFiles::ReadHeaderStub, HOOK_CALL).install()->quick();
|
||||||
|
|
||||||
|
// Obfuscate zone data
|
||||||
|
Utils::Hook(Game::DB_ReadXFile, FastFiles::ReadXFileStub, HOOK_JUMP).install()->quick();
|
||||||
|
|
||||||
// Allow custom zone loading
|
// Allow custom zone loading
|
||||||
if (!ZoneBuilder::IsEnabled())
|
if (!ZoneBuilder::IsEnabled())
|
||||||
{
|
{
|
||||||
|
@ -41,6 +41,8 @@ namespace Components
|
|||||||
static bool IsIW4xZone;
|
static bool IsIW4xZone;
|
||||||
static bool StreamRead;
|
static bool StreamRead;
|
||||||
|
|
||||||
|
static char LastByteRead;
|
||||||
|
|
||||||
static Key CurrentKey;
|
static Key CurrentKey;
|
||||||
static symmetric_CTR CurrentCTR;
|
static symmetric_CTR CurrentCTR;
|
||||||
static std::vector<std::string> ZonePaths;
|
static std::vector<std::string> ZonePaths;
|
||||||
@ -62,6 +64,9 @@ namespace Components
|
|||||||
|
|
||||||
static void LoadZonesStub(Game::XZoneInfo *zoneInfo, unsigned int zoneCount);
|
static void LoadZonesStub(Game::XZoneInfo *zoneInfo, unsigned int zoneCount);
|
||||||
|
|
||||||
|
static void ReadXFile(void* buffer, int size);
|
||||||
|
static void ReadXFileStub(char* buffer, int size);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
static void LogStreamRead(int len);
|
static void LogStreamRead(int len);
|
||||||
#endif
|
#endif
|
||||||
|
@ -445,6 +445,18 @@ namespace Components
|
|||||||
#ifndef DEBUG
|
#ifndef DEBUG
|
||||||
// Insert a random byte, this will destroy the whole alignment and result in a crash, if not handled
|
// Insert a random byte, this will destroy the whole alignment and result in a crash, if not handled
|
||||||
zoneBuffer.insert(zoneBuffer.begin(), static_cast<char>(Utils::Cryptography::Rand::GenerateInt()));
|
zoneBuffer.insert(zoneBuffer.begin(), static_cast<char>(Utils::Cryptography::Rand::GenerateInt()));
|
||||||
|
|
||||||
|
char lastByte = 0;
|
||||||
|
for(unsigned int i = 0; i < zoneBuffer.size(); ++i )
|
||||||
|
{
|
||||||
|
char oldLastByte = lastByte;
|
||||||
|
lastByte = zoneBuffer[i];
|
||||||
|
|
||||||
|
Utils::RotLeft(zoneBuffer[i], 6);
|
||||||
|
zoneBuffer[i] ^= -1;
|
||||||
|
Utils::RotRight(zoneBuffer[i], 4);
|
||||||
|
zoneBuffer[i] ^= oldLastByte;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
zoneBuffer = Utils::Compression::ZLib::Compress(zoneBuffer);
|
zoneBuffer = Utils::Compression::ZLib::Compress(zoneBuffer);
|
||||||
@ -988,4 +1000,37 @@ namespace Components
|
|||||||
assert(ZoneBuilder::MemAllocator.empty());
|
assert(ZoneBuilder::MemAllocator.empty());
|
||||||
ZoneBuilder::CommonAssets.clear();
|
ZoneBuilder::CommonAssets.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||||
|
bool ZoneBuilder::unitTest()
|
||||||
|
{
|
||||||
|
printf("Testing circular bit shifting (left)...");
|
||||||
|
|
||||||
|
unsigned int integer = 0x80000000;
|
||||||
|
Utils::RotLeft(integer, 1);
|
||||||
|
|
||||||
|
if(integer != 1)
|
||||||
|
{
|
||||||
|
printf("Error\n");
|
||||||
|
printf("Bit shifting failed: %X\n", integer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Success\n");
|
||||||
|
printf("Testing circular bit shifting (right)...");
|
||||||
|
|
||||||
|
unsigned char byte = 0b00000011;
|
||||||
|
Utils::RotRight(byte, 2);
|
||||||
|
|
||||||
|
if (byte != 0b11000000)
|
||||||
|
{
|
||||||
|
printf("Error\n");
|
||||||
|
printf("Bit shifting failed %X\n", byte & 0xFF);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Success\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#define XFILE_VERSION 276
|
#define XFILE_VERSION 276
|
||||||
|
|
||||||
#define XFILE_HEADER_IW4X 0x78345749 // 'IW4x'
|
#define XFILE_HEADER_IW4X 0x78345749 // 'IW4x'
|
||||||
#define XFILE_VERSION_IW4X 1
|
#define XFILE_VERSION_IW4X 2
|
||||||
|
|
||||||
namespace Components
|
namespace Components
|
||||||
{
|
{
|
||||||
@ -97,6 +97,7 @@ namespace Components
|
|||||||
|
|
||||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||||
const char* getName() override { return "ZoneBuilder"; };
|
const char* getName() override { return "ZoneBuilder"; };
|
||||||
|
bool unitTest() override;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool IsEnabled();
|
static bool IsEnabled();
|
||||||
|
@ -15,6 +15,25 @@ namespace Utils
|
|||||||
|
|
||||||
bool HasIntercection(unsigned int base1, unsigned int len1, unsigned int base2, unsigned int len2);
|
bool HasIntercection(unsigned int base1, unsigned int len1, unsigned int base2, unsigned int len2);
|
||||||
|
|
||||||
|
template <typename T> inline void RotLeft(T& object, size_t bits)
|
||||||
|
{
|
||||||
|
bits %= sizeof(T) * 8;
|
||||||
|
|
||||||
|
T sign = 1;
|
||||||
|
sign = sign << (sizeof(T) * 8 - 1);
|
||||||
|
|
||||||
|
bool negative = (object & sign) != 0;
|
||||||
|
object &= ~sign;
|
||||||
|
object = (object << bits) | (object >> (sizeof(T) * 8 - bits));
|
||||||
|
object |= T(negative) << ((sizeof(T) * 8 - 1 + bits) % (sizeof(T) * 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> inline void RotRight(T& object, size_t bits)
|
||||||
|
{
|
||||||
|
bits %= (sizeof(T) * 8);
|
||||||
|
RotLeft<T>(object, ((sizeof(T) * 8) - bits));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T> inline void Merge(std::vector<T>* target, T* source, size_t length)
|
template <typename T> inline void Merge(std::vector<T>* target, T* source, size_t length)
|
||||||
{
|
{
|
||||||
if (source)
|
if (source)
|
||||||
|
Loading…
Reference in New Issue
Block a user