Optimize crash procedure

This commit is contained in:
momo5502 2016-02-29 20:38:14 +01:00
parent 90e389ecdd
commit b3fbc045a9
4 changed files with 78 additions and 14 deletions

2
deps/protobuf vendored

@ -1 +1 @@
Subproject commit 60a0d41a2988a40cf3a94a4cb602f5f1c94135e9
Subproject commit 52f62e3652ce80ab14593331f4277539e7fa29c8

View File

@ -5,10 +5,35 @@ namespace Components
int AntiCheat::LastCheck;
std::string AntiCheat::Hash;
// This function does nothing, it only adds the two passed variables and returns the value
// The only important thing it does is to clean the first parameter, and then return
// By returning, the crash procedure will be called, as it hasn't been cleaned from the stack
void __declspec(naked) AntiCheat::NullSub()
{
__asm
{
push ebp
push ecx
mov ebp, esp
xor eax, eax
mov eax, [ebp + 8h]
mov ecx, [ebp + 0Ch]
add eax, ecx
pop ecx
pop ebp
retn 4
}
}
void __declspec(naked) AntiCheat::CrashClient()
{
static uint8_t crashProcedure[] =
{
// Variable space
0xDC, 0xC1, 0xDC, 0x05,
// Uninstall minidump handler
0xB8, 0x63, 0xE7, 0x2F, 0x00, // mov eax, 2FE763h
0x05, 0xAD, 0xAD, 0x3C, 0x00, // add eax, 3CADADh
@ -21,19 +46,47 @@ namespace Components
0x05, 0xDD, 0x28, 0x1A, 0x00, // add eax, 1A28DDh
0x80, 0x00, 0x68, // add byte ptr [eax], 68h
0xC3, // retn
// Random stuff
0xBE, 0xFF, 0xC2, 0xF4, 0x3A,
};
__asm
{
// This does absolutely nothing :P
// TODO: Obfuscate even more
xor eax, eax
mov ebx, [esp + 4h]
shl ebx, 4h
setz bl
// Call our crash procedure
push offset crashProcedure
retn
// Push the fake var onto the stack
push ebx
// Get address to VirtualProtect
mov eax, 6567h
shl eax, 0Ch
or eax, 70000A50h
// Move the address into ebx
push eax
pop ebx
// Save the address to our crash procedure
mov eax, offset crashProcedure
push eax
// Unprotect the .text segment
push eax
push 40h
push 2D5FFFh
push 401001h
call ebx
// Increment to our crash procedure
add dword ptr [esp], 4h
// This basically removes the pushed ebx value from the stack, so returning results in a call to the procedure
jmp AntiCheat::NullSub
}
}
@ -44,14 +97,13 @@ namespace Components
AntiCheat::Hash.clear();
}
void AntiCheat::Frame()
void AntiCheat::PerformCheck()
{
// Perform check only every 30 seconds
if (AntiCheat::LastCheck && (Game::Com_Milliseconds() - AntiCheat::LastCheck) < 1000 * 30) return;
AntiCheat::LastCheck = Game::Com_Milliseconds();
// Get base module
std::string hash = Utils::Cryptography::SHA512::Compute(reinterpret_cast<uint8_t*>(GetModuleHandle(NULL)) + 0x1000, 0x2D6000, false);
// Hash .text segment
// Add 1 to each value, so searching in memory doesn't reveal anything
size_t textSize = 0x2D6001;
uint8_t* textBase = reinterpret_cast<uint8_t*>(0x401001);
std::string hash = Utils::Cryptography::SHA512::Compute(textBase - 1, textSize - 1, false);
// Set the hash, if none is set
if (AntiCheat::Hash.empty())
@ -59,12 +111,21 @@ namespace Components
AntiCheat::Hash = hash;
}
// Crash if the hashes don't match
else if(AntiCheat::Hash != hash)
else if (AntiCheat::Hash != hash)
{
AntiCheat::CrashClient();
}
}
void AntiCheat::Frame()
{
// Perform check only every 30 seconds
if (AntiCheat::LastCheck && (Game::Com_Milliseconds() - AntiCheat::LastCheck) < 1000 * 30) return;
AntiCheat::LastCheck = Game::Com_Milliseconds();
AntiCheat::PerformCheck();
}
AntiCheat::AntiCheat()
{
AntiCheat::EmptyHash();

View File

@ -15,5 +15,8 @@ namespace Components
static std::string Hash;
static void Frame();
static void PerformCheck();
static void NullSub();
};
}

View File

@ -44,7 +44,7 @@ namespace Components
for (int j = 0; j < 10; ++j)
{
int progress = atoi(Game::TabeLookup(challengeTable, i, 6 + j * 2));
if (!progress )break;
if (!progress) break;
maxState = j + 2;
maxProgress = progress;