AntiCheat refactoring part 7

?
This commit is contained in:
momo5502 2016-11-05 12:56:12 +01:00
parent b1f283a066
commit d32d58cc6f
8 changed files with 80 additions and 56 deletions

View File

@ -2,11 +2,13 @@
namespace Components
{
int AntiCheat::LastCheck;
Utils::Time::Interval AntiCheat::LastCheck;
std::string AntiCheat::Hash;
Utils::Hook AntiCheat::LoadLibHook[4];
unsigned long AntiCheat::Flags = NO_FLAG;
bool AntiCheat::ScanIntegrityIsInOrder;
// 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
@ -125,16 +127,6 @@ namespace Components
}
}
// This has to be called when doing .text changes during runtime
[[deprecated]]
__declspec(noinline) void AntiCheat::EmptyHash()
{
AntiCheat::LastCheck = 0;
AntiCheat::Hash.clear();
AntiCheat::AssertCalleeModule(_ReturnAddress());
}
void AntiCheat::InitLoadLibHook()
{
static uint8_t loadLibStub[] = { 0x33, 0xC0, 0xC2, 0x04, 0x00 }; // xor eax, eax; retn 04h
@ -168,11 +160,11 @@ namespace Components
void AntiCheat::ReadIntegrityCheck()
{
static int lastCheck = Game::Sys_Milliseconds();
if ((Game::Sys_Milliseconds() - lastCheck) > 1000 * 20)
static Utils::Time::Interval check;
if(check.Elapsed(20s))
{
lastCheck = Game::Sys_Milliseconds();
check.Set();
if (HANDLE h = OpenProcess(PROCESS_VM_READ, TRUE, GetCurrentProcessId()))
{
@ -191,11 +183,11 @@ namespace Components
void AntiCheat::FlagIntegrityCheck()
{
static int lastCheck = Game::Sys_Milliseconds();
static Utils::Time::Interval check;
if ((Game::Sys_Milliseconds() - lastCheck) > 1000 * 30)
if (check.Elapsed(30s))
{
lastCheck = Game::Sys_Milliseconds();
check.Set();
unsigned long flags = ((AntiCheat::IntergrityFlag::MAX_FLAG - 1) << 1) - 1;
@ -212,15 +204,19 @@ namespace Components
void AntiCheat::ScanIntegrityCheck()
{
static int count = 0;
int lastCheck = AntiCheat::LastCheck;
int milliseconds = Game::Sys_Milliseconds();
if (!AntiCheat::ScanIntegrityIsInOrder)
{
#ifdef DEBUG_DETECTIONS
Logger::Print("AntiCheat: Integrity order check failed");
#endif
if (lastCheck) count = 0;
else ++count;
AntiCheat::CrashClient();
}
AntiCheat::ScanIntegrityIsInOrder = false;
// If there was no check within the last 40 seconds, crash!
if ((milliseconds > 1000 * 40) && ((lastCheck && (milliseconds - lastCheck) > 1000 * 40) || count > 1))
if (AntiCheat::LastCheck.Elapsed(40s))
{
#ifdef DEBUG_DETECTIONS
Logger::Print("AntiCheat: Integrity check failed");
@ -233,8 +229,14 @@ namespace Components
AntiCheat::Flags |= AntiCheat::IntergrityFlag::SCAN_INTEGRITY_CHECK;
}
void AntiCheat::PerformCheck()
void AntiCheat::PerformScan()
{
AntiCheat::ScanIntegrityIsInOrder = true;
// Perform check only every 10 seconds
if (!AntiCheat::LastCheck.Elapsed(10s)) return;
AntiCheat::LastCheck.Set();
// Hash .text segment
// Add 1 to each value, so searching in memory doesn't reveal anything
size_t textSize = 0x2D6001;
@ -260,15 +262,6 @@ namespace Components
AntiCheat::Flags |= AntiCheat::IntergrityFlag::MEMORY_SCAN;
}
void AntiCheat::Frame()
{
// Perform check only every 10 seconds
if (AntiCheat::LastCheck && (Game::Sys_Milliseconds() - AntiCheat::LastCheck) < 1000 * 10) return;
AntiCheat::LastCheck = Game::Sys_Milliseconds();
AntiCheat::PerformCheck();
}
#ifdef DEBUG_LOAD_LIBRARY
HANDLE AntiCheat::LoadLibary(std::wstring library, void* callee)
{
@ -545,12 +538,8 @@ namespace Components
AntiCheat::AntiCheat()
{
AntiCheat::Flags = NO_FLAG;
AntiCheat::LastCheck = 0;
#pragma warning(push)
#pragma warning(disable: 4996)
AntiCheat::EmptyHash();
#pragma warning(pop)
AntiCheat::Hash.clear();
AntiCheat::ScanIntegrityIsInOrder = false;
#ifdef DEBUG
Command::Add("penis", [] (Command::Params)
@ -566,7 +555,7 @@ namespace Components
Utils::Hook(0x60BE9D, AntiCheat::SoundInitStub, HOOK_CALL).Install()->Quick();
Utils::Hook(0x60BE8E, AntiCheat::SoundInitDriverStub, HOOK_CALL).Install()->Quick();
Utils::Hook(0x418204, AntiCheat::SoundInitDriverStub, HOOK_CALL).Install()->Quick();
QuickPatch::OnFrame(AntiCheat::Frame);
Renderer::OnFrame(AntiCheat::PerformScan);
// Detect aimbots
Utils::Hook(0x426580, AntiCheat::DObjGetWorldTagPosStub, HOOK_JUMP).Install()->Quick();
@ -580,6 +569,10 @@ namespace Components
// Prevent external processes from accessing our memory
AntiCheat::ProtectProcess();
Renderer::OnDeviceRecoveryEnd([] ()
{
AntiCheat::ProtectProcess();
});
// Set the integrity flag
AntiCheat::Flags |= AntiCheat::IntergrityFlag::INITIALIZATION;
@ -589,11 +582,7 @@ namespace Components
AntiCheat::~AntiCheat()
{
AntiCheat::Flags = NO_FLAG;
#pragma warning(push)
#pragma warning(disable: 4996)
AntiCheat::EmptyHash();
#pragma warning(pop)
AntiCheat::Hash.clear();
for (int i = 0; i < ARRAYSIZE(AntiCheat::LoadLibHook); ++i)
{

View File

@ -16,7 +16,6 @@ namespace Components
#endif
static void CrashClient();
static void EmptyHash();
static void InitLoadLibHook();
@ -36,12 +35,13 @@ namespace Components
MAX_FLAG,
};
static int LastCheck;
static Utils::Time::Interval LastCheck;
static std::string Hash;
static unsigned long Flags;
static void Frame();
static void PerformCheck();
static bool ScanIntegrityIsInOrder;
static void PerformScan();
static void PatchWinAPI();
static unsigned long ProtectProcess();

View File

@ -80,6 +80,11 @@ namespace Components
ServerList::InsertRequest(address, true);
}
});
// This is placed here in case the anticheat has been disabled!
#ifndef DEBUG
Renderer::OnFrame(AntiCheat::ScanIntegrityCheck);
#endif
}
Discovery::~Discovery()

View File

@ -484,11 +484,6 @@ namespace Components
Utils::Hook::Set<Game::XAssetEntry*>(0x5BAE91, Maps::EntryPool.data() + 1);
Utils::Hook::Set<Game::XAssetEntry*>(0x5BAEA2, Maps::EntryPool.data() + 1);
// This is placed here in case the anticheat has been disabled!
#ifndef DEBUG
QuickPatch::OnFrame(AntiCheat::ScanIntegrityCheck);
#endif
}
Maps::Maps()

View File

@ -724,7 +724,7 @@ namespace Components
// This is placed here in case the anticheat has been disabled!
#ifndef DEBUG
QuickPatch::OnFrame(AntiCheat::ReadIntegrityCheck);
Renderer::OnFrame(AntiCheat::ReadIntegrityCheck);
#endif
}

View File

@ -97,6 +97,7 @@ template <size_t S> class Sizer { };
#include "Utils\IO.hpp"
#include "Utils\CSV.hpp"
#include "Utils\Time.hpp"
#include "Utils\Chain.hpp"
#include "Utils\Utils.hpp"
#include "Utils\WebIO.hpp"

17
src/Utils/Time.cpp Normal file
View File

@ -0,0 +1,17 @@
#include "STDInclude.hpp"
namespace Utils
{
namespace Time
{
void Interval::Set()
{
this->LastPoint = std::chrono::high_resolution_clock::now();
}
bool Interval::Elapsed(std::chrono::nanoseconds nsecs)
{
return ((std::chrono::high_resolution_clock::now() - this->LastPoint) >= nsecs);
}
}
}

17
src/Utils/Time.hpp Normal file
View File

@ -0,0 +1,17 @@
namespace Utils
{
namespace Time
{
class Interval
{
private:
std::chrono::high_resolution_clock::time_point LastPoint;
public:
Interval() : LastPoint(std::chrono::high_resolution_clock::now()) {}
void Set();
bool Elapsed(std::chrono::nanoseconds nsecs);
};
}
}