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

View File

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

View File

@ -80,6 +80,11 @@ namespace Components
ServerList::InsertRequest(address, true); ServerList::InsertRequest(address, true);
} }
}); });
// This is placed here in case the anticheat has been disabled!
#ifndef DEBUG
Renderer::OnFrame(AntiCheat::ScanIntegrityCheck);
#endif
} }
Discovery::~Discovery() 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*>(0x5BAE91, Maps::EntryPool.data() + 1);
Utils::Hook::Set<Game::XAssetEntry*>(0x5BAEA2, 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() Maps::Maps()

View File

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

View File

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