Anticheat fixes and aimbot detection

This commit is contained in:
momo5502 2016-08-08 01:57:00 +02:00
parent 4fc7de502a
commit b0df3e0e21
19 changed files with 710 additions and 695 deletions

View File

@ -9,7 +9,7 @@ namespace Components
// 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
void __declspec(naked) AntiCheat::NullSub() __declspec(naked) void AntiCheat::NullSub()
{ {
__asm __asm
{ {
@ -28,7 +28,8 @@ namespace Components
} }
} }
void __declspec(naked) AntiCheat::CrashClient() #if 0
__declspec(naked) void AntiCheat::CrashClient()
{ {
static uint8_t crashProcedure[] = static uint8_t crashProcedure[] =
{ {
@ -83,26 +84,20 @@ namespace Components
jmp AntiCheat::NullSub jmp AntiCheat::NullSub
} }
} }
#endif
void AntiCheat::AssertLibraryCall(void* callee) void AntiCheat::CrashClient()
{ {
HMODULE hModuleSelf = nullptr; Utils::Hook::Set<BYTE>(0x41BA2C, 0xEB);
GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, reinterpret_cast<char*>(AntiCheat::AssertLibraryCall), &hModuleSelf);
AntiCheat::AssertModuleCall(hModuleSelf, callee);
} }
void AntiCheat::AssertProcessCall(void* callee) void AntiCheat::AssertCalleeModule(void* callee)
{ {
AntiCheat::AssertModuleCall(GetModuleHandle(NULL), callee); HMODULE hModuleSelf = nullptr, hModuleTarget = nullptr, hModuleProcess = GetModuleHandleA(NULL);
}
void AntiCheat::AssertModuleCall(HMODULE module, void* callee)
{
HMODULE hModuleTarget = nullptr;
GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, reinterpret_cast<char*>(callee), &hModuleTarget); GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, reinterpret_cast<char*>(callee), &hModuleTarget);
GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, reinterpret_cast<char*>(AntiCheat::AssertCalleeModule), &hModuleSelf);
if (!module || !hModuleTarget || module != hModuleTarget) if (!hModuleSelf || !hModuleTarget || !hModuleProcess || (hModuleTarget != hModuleSelf &&hModuleTarget != hModuleProcess))
{ {
//AntiCheat::CrashClient(); //AntiCheat::CrashClient();
AntiCheat::Hash.append("\0", 1); AntiCheat::Hash.append("\0", 1);
@ -110,12 +105,12 @@ namespace Components
} }
// This has to be called when doing .text changes during runtime // This has to be called when doing .text changes during runtime
void AntiCheat::EmptyHash() __declspec(noinline) void AntiCheat::EmptyHash()
{ {
AntiCheat::LastCheck = 0; AntiCheat::LastCheck = 0;
AntiCheat::Hash.clear(); AntiCheat::Hash.clear();
AntiCheat::AssertLibraryCall(_ReturnAddress()); AntiCheat::AssertCalleeModule(_ReturnAddress());
} }
void AntiCheat::InitLoadLibHook() void AntiCheat::InitLoadLibHook()
@ -255,7 +250,7 @@ namespace Components
AntiCheat::InstallLibHook(); AntiCheat::InstallLibHook();
} }
void __declspec(naked) AntiCheat::CinematicStub() __declspec(naked) void AntiCheat::CinematicStub()
{ {
__asm __asm
{ {
@ -273,14 +268,34 @@ namespace Components
} }
} }
void __declspec(naked) AntiCheat::AimTargetGetTagPosStub() __declspec(naked) void AntiCheat::DObjGetWorldTagPosStub()
{
__asm
{
pushad
push[esp + 20h]
call AntiCheat::AssertCalleeModule
pop esi
popad
push ecx
mov ecx, [esp + 10h]
push 426585h
retn
}
}
__declspec(naked) void AntiCheat::AimTargetGetTagPosStub()
{ {
__asm __asm
{ {
pushad pushad
push [esp + 20h] push [esp + 20h]
call AntiCheat::AssertProcessCall call AntiCheat::AssertCalleeModule
pop esi pop esi
popad popad
@ -311,8 +326,9 @@ namespace Components
Utils::Hook(0x418204, AntiCheat::SoundInitDriverStub, HOOK_CALL).Install()->Quick(); Utils::Hook(0x418204, AntiCheat::SoundInitDriverStub, HOOK_CALL).Install()->Quick();
QuickPatch::OnFrame(AntiCheat::Frame); QuickPatch::OnFrame(AntiCheat::Frame);
// Check AimTarget_GetTagPos // Detect aimbots
//Utils::Hook(0x56AC60, AntiCheat::AimTargetGetTagPosStub, HOOK_JUMP).Install()->Quick(); Utils::Hook(0x426580, AntiCheat::DObjGetWorldTagPosStub, HOOK_JUMP).Install()->Quick();
Utils::Hook(0x56AC60, AntiCheat::AimTargetGetTagPosStub, HOOK_JUMP).Install()->Quick();
// TODO: Probably move that :P // TODO: Probably move that :P
AntiCheat::InitLoadLibHook(); AntiCheat::InitLoadLibHook();

View File

@ -27,9 +27,7 @@ namespace Components
static void NullSub(); static void NullSub();
static void AssertLibraryCall(void* callee); static void AssertCalleeModule(void* callee);
static void AssertProcessCall(void* callee);
static void AssertModuleCall(HMODULE module, void* callee);
static void UninstallLibHook(); static void UninstallLibHook();
static void InstallLibHook(); static void InstallLibHook();
@ -44,6 +42,7 @@ namespace Components
static void SoundInitStub(int a1, int a2, int a3); static void SoundInitStub(int a1, int a2, int a3);
static void SoundInitDriverStub(); static void SoundInitDriverStub();
static void DObjGetWorldTagPosStub();
static void AimTargetGetTagPosStub(); static void AimTargetGetTagPosStub();
static Utils::Hook LoadLibHook[4]; static Utils::Hook LoadLibHook[4];

View File

@ -64,7 +64,7 @@ namespace Components
return header; return header;
} }
void __declspec(naked) AssetHandler::FindAssetStub() __declspec(naked) void AssetHandler::FindAssetStub()
{ {
__asm __asm
{ {
@ -122,7 +122,7 @@ namespace Components
return (!restrict); return (!restrict);
} }
void __declspec(naked) AssetHandler::AddAssetStub() __declspec(naked) void AssetHandler::AddAssetStub()
{ {
__asm __asm
{ {

View File

@ -152,7 +152,7 @@ namespace Components
} }
} }
void __declspec(naked) Auth::DirectConnectStub() __declspec(naked) void Auth::DirectConnectStub()
{ {
__asm __asm
{ {

View File

@ -86,7 +86,7 @@ namespace Components
return std::string(buffer); return std::string(buffer);
} }
void __declspec(naked) Colors::ClientUserinfoChanged() __declspec(naked) void Colors::ClientUserinfoChanged()
{ {
__asm __asm
{ {
@ -190,7 +190,7 @@ namespace Components
return string; return string;
} }
void __declspec(naked) Colors::LookupColorStub() __declspec(naked) void Colors::LookupColorStub()
{ {
__asm __asm
{ {

View File

@ -433,7 +433,7 @@ namespace Components
ExitProcess(1); ExitProcess(1);
} }
void __declspec(naked) Console::DrawSolidConsoleStub() __declspec(naked) void Console::DrawSolidConsoleStub()
{ {
__asm __asm
{ {

View File

@ -48,7 +48,7 @@ namespace Components
Utils::Hook::Call<void()>(0x60C3D0)(); Utils::Hook::Call<void()>(0x60C3D0)();
} }
void __declspec(naked) Dedicated::PostInitializationStub() __declspec(naked) void Dedicated::PostInitializationStub()
{ {
__asm __asm
{ {
@ -74,7 +74,7 @@ namespace Components
return text; return text;
} }
void __declspec(naked) Dedicated::PreSayStub() __declspec(naked) void Dedicated::PreSayStub()
{ {
__asm __asm
{ {
@ -90,7 +90,7 @@ namespace Components
} }
} }
void __declspec(naked) Dedicated::PostSayStub() __declspec(naked) void Dedicated::PostSayStub()
{ {
__asm __asm
{ {

View File

@ -113,7 +113,7 @@ namespace Components
FileSystem::RegisterFolder("userraw"); FileSystem::RegisterFolder("userraw");
} }
void __declspec(naked) FileSystem::StartupStub() __declspec(naked) void FileSystem::StartupStub()
{ {
__asm __asm
{ {

View File

@ -108,7 +108,7 @@ namespace Components
} }
} }
void __declspec(naked) Logger::PrintMessageStub() __declspec(naked) void Logger::PrintMessageStub()
{ {
__asm __asm
{ {

View File

@ -1,59 +1,59 @@
#include "STDInclude.hpp" #include "STDInclude.hpp"
namespace Components namespace Components
{ {
Utils::Hook Materials::ImageVersionCheckHook; Utils::Hook Materials::ImageVersionCheckHook;
void __declspec(naked) Materials::ImageVersionCheck() __declspec(naked) void Materials::ImageVersionCheck()
{ {
__asm __asm
{ {
cmp eax, 9 cmp eax, 9
je returnSafely je returnSafely
jmp Materials::ImageVersionCheckHook.Original jmp Materials::ImageVersionCheckHook.Original
returnSafely: returnSafely:
mov al, 1 mov al, 1
add esp, 18h add esp, 18h
retn retn
} }
} }
Game::Material* Materials::VerifyMaterial(Game::Material* material) Game::Material* Materials::VerifyMaterial(Game::Material* material)
{ {
if (!IsBadReadPtr(material, 4) && !IsBadReadPtr(material->name, 1)) if (!IsBadReadPtr(material, 4) && !IsBadReadPtr(material->name, 1))
{ {
return material; return material;
} }
return Game::DB_FindXAssetHeader(Game::XAssetType::ASSET_TYPE_MATERIAL, "default").material; return Game::DB_FindXAssetHeader(Game::XAssetType::ASSET_TYPE_MATERIAL, "default").material;
} }
void __declspec(naked) Materials::DrawMaterialStub() __declspec(naked) void Materials::DrawMaterialStub()
{ {
__asm __asm
{ {
push eax push eax
call Materials::VerifyMaterial call Materials::VerifyMaterial
add esp, 4h add esp, 4h
mov edx, 5310F0h mov edx, 5310F0h
jmp edx jmp edx
} }
} }
Materials::Materials() Materials::Materials()
{ {
// Allow codo images // Allow codo images
Materials::ImageVersionCheckHook.Initialize(0x53A456, Materials::ImageVersionCheck, HOOK_CALL)->Install(); Materials::ImageVersionCheckHook.Initialize(0x53A456, Materials::ImageVersionCheck, HOOK_CALL)->Install();
// Fix material pointer exploit // Fix material pointer exploit
Utils::Hook(0x534E0C, Materials::DrawMaterialStub, HOOK_CALL).Install()->Quick(); Utils::Hook(0x534E0C, Materials::DrawMaterialStub, HOOK_CALL).Install()->Quick();
} }
Materials::~Materials() Materials::~Materials()
{ {
Materials::ImageVersionCheckHook.Uninstall(); Materials::ImageVersionCheckHook.Uninstall();
} }
} }

View File

@ -278,7 +278,7 @@ namespace Components
Network::StartupSignal(); Network::StartupSignal();
} }
void __declspec(naked) Network::NetworkStartStub() __declspec(naked) void Network::NetworkStartStub()
{ {
__asm __asm
{ {
@ -288,7 +288,7 @@ namespace Components
} }
} }
void __declspec(naked) Network::DeployPacketStub() __declspec(naked) void Network::DeployPacketStub()
{ {
__asm __asm
{ {

View File

@ -7,7 +7,7 @@ namespace Components
wink::signal<wink::slot<Renderer::Callback>> Renderer::FrameOnceSignal; wink::signal<wink::slot<Renderer::Callback>> Renderer::FrameOnceSignal;
wink::signal<wink::slot<Renderer::BackendCallback>> Renderer::BackendFrameSignal; wink::signal<wink::slot<Renderer::BackendCallback>> Renderer::BackendFrameSignal;
void __declspec(naked) Renderer::FrameStub() __declspec(naked) void Renderer::FrameStub()
{ {
__asm __asm
{ {
@ -23,7 +23,7 @@ namespace Components
Renderer::FrameOnceSignal.clear(); Renderer::FrameOnceSignal.clear();
} }
void __declspec(naked) Renderer::BackendFrameStub() __declspec(naked) void Renderer::BackendFrameStub()
{ {
__asm __asm
{ {

View File

@ -21,7 +21,7 @@ namespace Components
Logger::Error(5, "script compile error\nunknown function %s\n%s\n\n", funcName.data(), Script::ScriptName.data()); Logger::Error(5, "script compile error\nunknown function %s\n%s\n\n", funcName.data(), Script::ScriptName.data());
} }
void __declspec(naked) Script::StoreFunctionNameStub() __declspec(naked) void Script::StoreFunctionNameStub()
{ {
__asm __asm
{ {
@ -48,7 +48,7 @@ namespace Components
} }
} }
void __declspec(naked) Script::StoreScriptNameStub() __declspec(naked) void Script::StoreScriptNameStub()
{ {
__asm __asm
{ {
@ -71,7 +71,7 @@ namespace Components
Script::ScriptNameStack.pop_back(); Script::ScriptNameStack.pop_back();
} }
void __declspec(naked) Script::RestoreScriptNameStub() __declspec(naked) void Script::RestoreScriptNameStub()
{ {
__asm __asm
{ {

View File

@ -88,7 +88,7 @@ namespace Components
Game::UI_DrawText(cxt, addressText.data(), 0x7FFFFFFF, font, x2 - Game::UI_TextWidth(addressText.data(), 0, font, fontSize), y, 0, 0, fontSize, reinterpret_cast<float*>(0x747F34), 3); Game::UI_DrawText(cxt, addressText.data(), 0x7FFFFFFF, font, x2 - Game::UI_TextWidth(addressText.data(), 0, font, fontSize), y, 0, 0, fontSize, reinterpret_cast<float*>(0x747F34), 3);
} }
void __declspec(naked) ServerInfo::DrawScoreboardStub() __declspec(naked) void ServerInfo::DrawScoreboardStub()
{ {
__asm __asm
{ {

View File

@ -30,7 +30,7 @@ namespace Components
std::memcpy(Theatre::BaselineSnapshot, *reinterpret_cast<DWORD**>(snapshotMsg + 8), *reinterpret_cast<DWORD*>(snapshotMsg + 20)); std::memcpy(Theatre::BaselineSnapshot, *reinterpret_cast<DWORD**>(snapshotMsg + 8), *reinterpret_cast<DWORD*>(snapshotMsg + 20));
} }
void __declspec(naked) Theatre::BaselineStoreStub() __declspec(naked) void Theatre::BaselineStoreStub()
{ {
_asm _asm
{ {
@ -79,7 +79,7 @@ namespace Components
} }
} }
void __declspec(naked) Theatre::BaselineToFileStub() __declspec(naked) void Theatre::BaselineToFileStub()
{ {
__asm __asm
{ {
@ -95,7 +95,7 @@ namespace Components
} }
} }
void __declspec(naked) Theatre::AdjustTimeDeltaStub() __declspec(naked) void Theatre::AdjustTimeDeltaStub()
{ {
__asm __asm
{ {
@ -113,7 +113,7 @@ namespace Components
} }
} }
void __declspec(naked) Theatre::ServerTimedOutStub() __declspec(naked) void Theatre::ServerTimedOutStub()
{ {
__asm __asm
{ {
@ -132,7 +132,7 @@ namespace Components
} }
} }
void __declspec(naked) Theatre::UISetActiveMenuStub() __declspec(naked) void Theatre::UISetActiveMenuStub()
{ {
__asm __asm
{ {

View File

@ -1,285 +1,285 @@
#include "STDInclude.hpp" #include "STDInclude.hpp"
namespace Components namespace Components
{ {
UIFeeder::Container UIFeeder::Current; UIFeeder::Container UIFeeder::Current;
std::map<float, UIFeeder::Callbacks> UIFeeder::Feeders; std::map<float, UIFeeder::Callbacks> UIFeeder::Feeders;
void UIFeeder::Add(float feeder, UIFeeder::GetItemCount_t itemCountCb, UIFeeder::GetItemText_t itemTextCb, UIFeeder::Select_t selectCb) void UIFeeder::Add(float feeder, UIFeeder::GetItemCount_t itemCountCb, UIFeeder::GetItemText_t itemTextCb, UIFeeder::Select_t selectCb)
{ {
UIFeeder::Feeders[feeder] = { itemCountCb, itemTextCb, selectCb }; UIFeeder::Feeders[feeder] = { itemCountCb, itemTextCb, selectCb };
} }
const char* UIFeeder::GetItemText() const char* UIFeeder::GetItemText()
{ {
if (UIFeeder::Feeders.find(UIFeeder::Current.Feeder) != UIFeeder::Feeders.end()) if (UIFeeder::Feeders.find(UIFeeder::Current.Feeder) != UIFeeder::Feeders.end())
{ {
return UIFeeder::Feeders[UIFeeder::Current.Feeder].GetItemText(UIFeeder::Current.Index, UIFeeder::Current.Column); return UIFeeder::Feeders[UIFeeder::Current.Feeder].GetItemText(UIFeeder::Current.Index, UIFeeder::Current.Column);
} }
return nullptr; return nullptr;
} }
unsigned int UIFeeder::GetItemCount() unsigned int UIFeeder::GetItemCount()
{ {
if (UIFeeder::Feeders.find(UIFeeder::Current.Feeder) != UIFeeder::Feeders.end()) if (UIFeeder::Feeders.find(UIFeeder::Current.Feeder) != UIFeeder::Feeders.end())
{ {
return UIFeeder::Feeders[UIFeeder::Current.Feeder].GetItemCount(); return UIFeeder::Feeders[UIFeeder::Current.Feeder].GetItemCount();
} }
return 0; return 0;
} }
bool UIFeeder::SetItemSelection() bool UIFeeder::SetItemSelection()
{ {
if (UIFeeder::Feeders.find(UIFeeder::Current.Feeder) != UIFeeder::Feeders.end()) if (UIFeeder::Feeders.find(UIFeeder::Current.Feeder) != UIFeeder::Feeders.end())
{ {
UIFeeder::Feeders[UIFeeder::Current.Feeder].Select(UIFeeder::Current.Index); UIFeeder::Feeders[UIFeeder::Current.Feeder].Select(UIFeeder::Current.Index);
return true; return true;
} }
return false; return false;
} }
bool UIFeeder::CheckFeeder() bool UIFeeder::CheckFeeder()
{ {
if (UIFeeder::Current.Feeder == 15.0f) return false; if (UIFeeder::Current.Feeder == 15.0f) return false;
return (UIFeeder::Feeders.find(UIFeeder::Current.Feeder) != UIFeeder::Feeders.end()); return (UIFeeder::Feeders.find(UIFeeder::Current.Feeder) != UIFeeder::Feeders.end());
} }
void __declspec(naked) UIFeeder::SetItemSelectionStub() __declspec(naked) void UIFeeder::SetItemSelectionStub()
{ {
__asm __asm
{ {
mov eax, [esp + 08h] mov eax, [esp + 08h]
mov UIFeeder::Current.Feeder, eax mov UIFeeder::Current.Feeder, eax
mov eax, [esp + 0Ch] mov eax, [esp + 0Ch]
mov UIFeeder::Current.Index, eax mov UIFeeder::Current.Index, eax
call UIFeeder::SetItemSelection call UIFeeder::SetItemSelection
test al, al test al, al
jz continue jz continue
retn retn
continue: continue:
fld ds:739FD0h fld ds:739FD0h
mov eax, 4C25D6h mov eax, 4C25D6h
jmp eax jmp eax
} }
} }
void __declspec(naked) UIFeeder::GetItemTextStub() __declspec(naked) void UIFeeder::GetItemTextStub()
{ {
__asm __asm
{ {
mov eax, [esp + 0Ch] mov eax, [esp + 0Ch]
mov UIFeeder::Current.Feeder, eax mov UIFeeder::Current.Feeder, eax
mov eax, [esp + 10h] mov eax, [esp + 10h]
mov UIFeeder::Current.Index, eax mov UIFeeder::Current.Index, eax
mov eax, [esp + 14h] mov eax, [esp + 14h]
mov UIFeeder::Current.Column, eax mov UIFeeder::Current.Column, eax
call UIFeeder::GetItemText call UIFeeder::GetItemText
test eax, eax test eax, eax
jz continue jz continue
push ebx push ebx
mov ebx, [esp + 4 + 28h] mov ebx, [esp + 4 + 28h]
mov dword ptr[ebx], 0 mov dword ptr[ebx], 0
pop ebx pop ebx
retn retn
continue: continue:
push ecx push ecx
fld ds:739FD0h fld ds:739FD0h
mov eax, 4CE9E7h mov eax, 4CE9E7h
jmp eax jmp eax
} }
} }
void __declspec(naked) UIFeeder::GetItemCountStub() __declspec(naked) void UIFeeder::GetItemCountStub()
{ {
__asm __asm
{ {
mov eax, [esp + 8h] mov eax, [esp + 8h]
mov UIFeeder::Current.Feeder, eax mov UIFeeder::Current.Feeder, eax
call UIFeeder::GetItemCount call UIFeeder::GetItemCount
test eax, eax test eax, eax
jz continue jz continue
retn retn
continue: continue:
push ecx push ecx
fld ds:739FD0h fld ds:739FD0h
mov eax, 41A0D7h mov eax, 41A0D7h
jmp eax; jmp eax;
} }
} }
void __declspec(naked) UIFeeder::HandleKeyStub() __declspec(naked) void UIFeeder::HandleKeyStub()
{ {
static int NextClickTime = 0; static int NextClickTime = 0;
__asm __asm
{ {
mov ebx, ebp mov ebx, ebp
mov eax, [ebp + 12Ch] mov eax, [ebp + 12Ch]
mov UIFeeder::Current.Feeder, eax mov UIFeeder::Current.Feeder, eax
push ebx push ebx
call UIFeeder::CheckFeeder call UIFeeder::CheckFeeder
pop ebx pop ebx
test al, al test al, al
jz continueOriginal jz continueOriginal
// Get current milliseconds // Get current milliseconds
call Game::Sys_Milliseconds call Game::Sys_Milliseconds
// Check if allowed to click // Check if allowed to click
cmp eax, NextClickTime cmp eax, NextClickTime
jl continueOriginal jl continueOriginal
// Set next allowed click time to current time + 300ms // Set next allowed click time to current time + 300ms
add eax, 300 add eax, 300
mov NextClickTime, eax mov NextClickTime, eax
// Get item cursor position ptr // Get item cursor position ptr
mov ecx, ebx mov ecx, ebx
add ecx, Game::itemDef_t::cursorPos add ecx, Game::itemDef_t::cursorPos
// Get item listbox ptr // Get item listbox ptr
mov edx, ebx mov edx, ebx
add edx, Game::itemDef_t::typeData add edx, Game::itemDef_t::typeData
// Get listbox cursor pos // Get listbox cursor pos
mov edx, [edx] mov edx, [edx]
add edx, Game::listBoxDef_s::startPos add edx, Game::listBoxDef_s::startPos
mov edx, [edx] mov edx, [edx]
// Resolve item cursor pos pointer // Resolve item cursor pos pointer
mov ebx, [ecx] mov ebx, [ecx]
// Check if item cursor pos equals listbox cursor pos // Check if item cursor pos equals listbox cursor pos
cmp ebx, edx cmp ebx, edx
je returnSafe je returnSafe
// Update indices if not // Update indices if not
mov [ecx], edx mov [ecx], edx
mov UIFeeder::Current.Index, edx mov UIFeeder::Current.Index, edx
call UIFeeder::SetItemSelection call UIFeeder::SetItemSelection
returnSafe: returnSafe:
retn retn
continueOriginal: continueOriginal:
mov eax, 635570h mov eax, 635570h
jmp eax jmp eax
} }
} }
void __declspec(naked) UIFeeder::MouseEnterStub() __declspec(naked) void UIFeeder::MouseEnterStub()
{ {
__asm __asm
{ {
mov eax, [edi + 12Ch] mov eax, [edi + 12Ch]
mov UIFeeder::Current.Feeder, eax mov UIFeeder::Current.Feeder, eax
call UIFeeder::CheckFeeder call UIFeeder::CheckFeeder
test al, al test al, al
jnz continue jnz continue
mov[edi + 130h], esi mov[edi + 130h], esi
continue: continue:
mov eax, 639D75h mov eax, 639D75h
jmp eax jmp eax
} }
} }
void __declspec(naked) UIFeeder::MouseSelectStub() __declspec(naked) void UIFeeder::MouseSelectStub()
{ {
__asm __asm
{ {
mov eax, [esp + 08h] mov eax, [esp + 08h]
mov UIFeeder::Current.Feeder, eax mov UIFeeder::Current.Feeder, eax
call UIFeeder::CheckFeeder call UIFeeder::CheckFeeder
test al, al test al, al
jnz continue jnz continue
mov eax, 4C25D0h mov eax, 4C25D0h
jmp eax jmp eax
continue: continue:
retn retn
} }
} }
void __declspec(naked) UIFeeder::PlaySoundStub() __declspec(naked) void UIFeeder::PlaySoundStub()
{ {
__asm __asm
{ {
mov eax, [edi + 12Ch] mov eax, [edi + 12Ch]
mov UIFeeder::Current.Feeder, eax mov UIFeeder::Current.Feeder, eax
call UIFeeder::CheckFeeder call UIFeeder::CheckFeeder
test al, al test al, al
jnz continue jnz continue
mov eax, 685E10h mov eax, 685E10h
jmp eax jmp eax
continue: continue:
retn retn
} }
} }
UIFeeder::UIFeeder() UIFeeder::UIFeeder()
{ {
// Get feeder item count // Get feeder item count
Utils::Hook(0x41A0D0, UIFeeder::GetItemCountStub, HOOK_JUMP).Install()->Quick(); Utils::Hook(0x41A0D0, UIFeeder::GetItemCountStub, HOOK_JUMP).Install()->Quick();
// Get feeder item text // Get feeder item text
Utils::Hook(0x4CE9E0, UIFeeder::GetItemTextStub, HOOK_JUMP).Install()->Quick(); Utils::Hook(0x4CE9E0, UIFeeder::GetItemTextStub, HOOK_JUMP).Install()->Quick();
// Select feeder item // Select feeder item
Utils::Hook(0x4C25D0, UIFeeder::SetItemSelectionStub, HOOK_JUMP).Install()->Quick(); Utils::Hook(0x4C25D0, UIFeeder::SetItemSelectionStub, HOOK_JUMP).Install()->Quick();
// Mouse enter check // Mouse enter check
Utils::Hook(0x639D6E, UIFeeder::MouseEnterStub, HOOK_JUMP).Install()->Quick(); Utils::Hook(0x639D6E, UIFeeder::MouseEnterStub, HOOK_JUMP).Install()->Quick();
// Handle key event // Handle key event
Utils::Hook(0x63C5BC, UIFeeder::HandleKeyStub, HOOK_CALL).Install()->Quick(); Utils::Hook(0x63C5BC, UIFeeder::HandleKeyStub, HOOK_CALL).Install()->Quick();
// Mouse select check // Mouse select check
Utils::Hook(0x639D31, UIFeeder::MouseSelectStub, HOOK_CALL).Install()->Quick(); Utils::Hook(0x639D31, UIFeeder::MouseSelectStub, HOOK_CALL).Install()->Quick();
// Play mouse over sound check // Play mouse over sound check
Utils::Hook(0x639D66, UIFeeder::PlaySoundStub, HOOK_CALL).Install()->Quick(); Utils::Hook(0x639D66, UIFeeder::PlaySoundStub, HOOK_CALL).Install()->Quick();
// some thing overwriting feeder 2's data // some thing overwriting feeder 2's data
Utils::Hook::Set<BYTE>(0x4A06A9, 0xEB); Utils::Hook::Set<BYTE>(0x4A06A9, 0xEB);
} }
UIFeeder::~UIFeeder() UIFeeder::~UIFeeder()
{ {
UIFeeder::Feeders.clear(); UIFeeder::Feeders.clear();
} }
} }

View File

@ -1,136 +1,136 @@
#include "STDInclude.hpp" #include "STDInclude.hpp"
namespace Components namespace Components
{ {
std::map<std::string, wink::slot<UIScript::Callback>> UIScript::UIScripts; std::map<std::string, wink::slot<UIScript::Callback>> UIScript::UIScripts;
std::map<int, wink::slot<UIScript::CallbackRaw>> UIScript::UIOwnerDraws; std::map<int, wink::slot<UIScript::CallbackRaw>> UIScript::UIOwnerDraws;
template<> int UIScript::Token::Get() template<> int UIScript::Token::Get()
{ {
if (this->IsValid()) if (this->IsValid())
{ {
return atoi(this->token); return atoi(this->token);
} }
return 0; return 0;
} }
template<> char* UIScript::Token::Get() template<> char* UIScript::Token::Get()
{ {
if (this->IsValid()) if (this->IsValid())
{ {
return this->token; return this->token;
} }
return ""; return "";
} }
template<> const char* UIScript::Token::Get() template<> const char* UIScript::Token::Get()
{ {
return this->Get<char*>(); return this->Get<char*>();
} }
template<> std::string UIScript::Token::Get() template<> std::string UIScript::Token::Get()
{ {
return this->Get<const char*>(); return this->Get<const char*>();
} }
bool UIScript::Token::IsValid() bool UIScript::Token::IsValid()
{ {
return (token && token[0]); return (token && token[0]);
} }
void UIScript::Token::Parse(const char** args) void UIScript::Token::Parse(const char** args)
{ {
if (args) if (args)
{ {
this->token = Game::Com_ParseExt(args); this->token = Game::Com_ParseExt(args);
} }
} }
void UIScript::Add(std::string name, UIScript::Callback* callback) void UIScript::Add(std::string name, UIScript::Callback* callback)
{ {
UIScript::UIScripts[name] = callback; UIScript::UIScripts[name] = callback;
} }
void UIScript::Add(std::string name, UIScript::CallbackRaw* callback) void UIScript::Add(std::string name, UIScript::CallbackRaw* callback)
{ {
UIScript::Add(name, reinterpret_cast<UIScript::Callback*>(callback)); UIScript::Add(name, reinterpret_cast<UIScript::Callback*>(callback));
} }
void UIScript::AddOwnerDraw(int ownerdraw, UIScript::CallbackRaw* callback) void UIScript::AddOwnerDraw(int ownerdraw, UIScript::CallbackRaw* callback)
{ {
UIScript::UIOwnerDraws[ownerdraw] = callback; UIScript::UIOwnerDraws[ownerdraw] = callback;
} }
bool UIScript::RunMenuScript(const char* name, const char** args) bool UIScript::RunMenuScript(const char* name, const char** args)
{ {
if (UIScript::UIScripts.find(name) != UIScript::UIScripts.end()) if (UIScript::UIScripts.find(name) != UIScript::UIScripts.end())
{ {
UIScript::UIScripts[name](UIScript::Token(args)); UIScript::UIScripts[name](UIScript::Token(args));
return true; return true;
} }
return false; return false;
} }
void UIScript::OwnerDrawHandleKeyStub(int ownerDraw, int flags, float *special, int key) void UIScript::OwnerDrawHandleKeyStub(int ownerDraw, int flags, float *special, int key)
{ {
if (key == 200 || key == 201) //mouse buttons if (key == 200 || key == 201) //mouse buttons
{ {
for (auto i = UIScript::UIOwnerDraws.begin(); i != UIScript::UIOwnerDraws.end(); ++i) for (auto i = UIScript::UIOwnerDraws.begin(); i != UIScript::UIOwnerDraws.end(); ++i)
{ {
if (i->first == ownerDraw) if (i->first == ownerDraw)
{ {
i->second(); i->second();
} }
} }
} }
Utils::Hook::Call<void(int, int, float*, int)>(0x4F58A0)(ownerDraw, flags, special, key); Utils::Hook::Call<void(int, int, float*, int)>(0x4F58A0)(ownerDraw, flags, special, key);
} }
void __declspec(naked) UIScript::RunMenuScriptStub() __declspec(naked) void UIScript::RunMenuScriptStub()
{ {
__asm __asm
{ {
mov eax, esp mov eax, esp
add eax, 8h add eax, 8h
mov edx, eax // UIScript name mov edx, eax // UIScript name
mov eax, [esp + 0C10h] // UIScript args mov eax, [esp + 0C10h] // UIScript args
push eax push eax
push edx push edx
call UIScript::RunMenuScript call UIScript::RunMenuScript
add esp, 8h add esp, 8h
test al, al test al, al
jz continue jz continue
// if returned // if returned
pop edi pop edi
pop esi pop esi
add esp, 0C00h add esp, 0C00h
retn retn
continue: continue:
mov eax, 45ED00h mov eax, 45ED00h
jmp eax jmp eax
} }
} }
UIScript::UIScript() UIScript::UIScript()
{ {
// Install handler // Install handler
Utils::Hook::RedirectJump(0x45EC59, UIScript::RunMenuScriptStub); Utils::Hook::RedirectJump(0x45EC59, UIScript::RunMenuScriptStub);
// Install ownerdraw handler // Install ownerdraw handler
Utils::Hook(0x63D233, UIScript::OwnerDrawHandleKeyStub, HOOK_CALL).Install()->Quick(); Utils::Hook(0x63D233, UIScript::OwnerDrawHandleKeyStub, HOOK_CALL).Install()->Quick();
} }
UIScript::~UIScript() UIScript::~UIScript()
{ {
UIScript::UIScripts.clear(); UIScript::UIScripts.clear();
UIScript::UIOwnerDraws.clear(); UIScript::UIOwnerDraws.clear();
} }
} }

View File

@ -1,165 +1,165 @@
#include "STDInclude.hpp" #include "STDInclude.hpp"
namespace Components namespace Components
{ {
Dvar::Var Window::NoBorder; Dvar::Var Window::NoBorder;
Dvar::Var Window::NativeCursor; Dvar::Var Window::NativeCursor;
HWND Window::MainWindow = 0; HWND Window::MainWindow = 0;
BOOL Window::CursorVisible = TRUE; BOOL Window::CursorVisible = TRUE;
int Window::Width() int Window::Width()
{ {
return Window::Width(Window::MainWindow); return Window::Width(Window::MainWindow);
} }
int Window::Height() int Window::Height()
{ {
return Window::Height(Window::MainWindow); return Window::Height(Window::MainWindow);
} }
int Window::Width(HWND window) int Window::Width(HWND window)
{ {
RECT rect; RECT rect;
Window::Dimension(window, &rect); Window::Dimension(window, &rect);
return (rect.right - rect.left); return (rect.right - rect.left);
} }
int Window::Height(HWND window) int Window::Height(HWND window)
{ {
RECT rect; RECT rect;
Window::Dimension(window, &rect); Window::Dimension(window, &rect);
return (rect.bottom - rect.top); return (rect.bottom - rect.top);
} }
void Window::Dimension(RECT* rect) void Window::Dimension(RECT* rect)
{ {
Window::Dimension(Window::MainWindow, rect); Window::Dimension(Window::MainWindow, rect);
} }
void Window::Dimension(HWND window, RECT* rect) void Window::Dimension(HWND window, RECT* rect)
{ {
if (rect) if (rect)
{ {
ZeroMemory(rect, sizeof(RECT)); ZeroMemory(rect, sizeof(RECT));
if (window && IsWindow(window)) if (window && IsWindow(window))
{ {
GetWindowRect(window, rect); GetWindowRect(window, rect);
} }
} }
} }
bool Window::IsCursorWithin(HWND window) bool Window::IsCursorWithin(HWND window)
{ {
RECT rect; RECT rect;
POINT point; POINT point;
Window::Dimension(window, &rect); Window::Dimension(window, &rect);
GetCursorPos(&point); GetCursorPos(&point);
return ((point.x - rect.left) > 0 && (point.y - rect.top) > 0 && (rect.right - point.x) > 0 && (rect.bottom - point.y) > 0); return ((point.x - rect.left) > 0 && (point.y - rect.top) > 0 && (rect.right - point.x) > 0 && (rect.bottom - point.y) > 0);
} }
int Window::IsNoBorder() int Window::IsNoBorder()
{ {
return Window::NoBorder.Get<bool>(); return Window::NoBorder.Get<bool>();
} }
void __declspec(naked) Window::StyleHookStub() __declspec(naked) void Window::StyleHookStub()
{ {
__asm __asm
{ {
call Window::IsNoBorder call Window::IsNoBorder
test al, al test al, al
jz setBorder jz setBorder
mov ebp, WS_VISIBLE | WS_POPUP mov ebp, WS_VISIBLE | WS_POPUP
retn retn
setBorder: setBorder:
mov ebp, WS_VISIBLE | WS_SYSMENU | WS_CAPTION mov ebp, WS_VISIBLE | WS_SYSMENU | WS_CAPTION
retn retn
} }
} }
void Window::DrawCursorStub(void *scrPlace, float x, float y, float w, float h, int horzAlign, int vertAlign, const float *color, Game::Material *material) void Window::DrawCursorStub(void *scrPlace, float x, float y, float w, float h, int horzAlign, int vertAlign, const float *color, Game::Material *material)
{ {
if (Window::NativeCursor.Get<bool>()) if (Window::NativeCursor.Get<bool>())
{ {
Window::CursorVisible = TRUE; Window::CursorVisible = TRUE;
} }
else else
{ {
Game::UI_DrawHandlePic(scrPlace, x, y, w, h, horzAlign, vertAlign, color, material); Game::UI_DrawHandlePic(scrPlace, x, y, w, h, horzAlign, vertAlign, color, material);
} }
} }
int WINAPI Window::ShowCursorHook(BOOL show) int WINAPI Window::ShowCursorHook(BOOL show)
{ {
if (Window::NativeCursor.Get<bool>() && IsWindow(Window::MainWindow) && GetForegroundWindow() == Window::MainWindow && Window::IsCursorWithin(Window::MainWindow)) if (Window::NativeCursor.Get<bool>() && IsWindow(Window::MainWindow) && GetForegroundWindow() == Window::MainWindow && Window::IsCursorWithin(Window::MainWindow))
{ {
static int count = 0; static int count = 0;
(show ? ++count : --count); (show ? ++count : --count);
if (count >= 0) if (count >= 0)
{ {
Window::CursorVisible = TRUE; Window::CursorVisible = TRUE;
} }
return count; return count;
} }
return ShowCursor(show); return ShowCursor(show);
} }
HWND WINAPI Window::CreateMainWindow(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam) HWND WINAPI Window::CreateMainWindow(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
{ {
Window::MainWindow = CreateWindowExA(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); Window::MainWindow = CreateWindowExA(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
return Window::MainWindow; return Window::MainWindow;
} }
Window::Window() Window::Window()
{ {
// Borderless window // Borderless window
Window::NoBorder = Dvar::Register<bool>("r_noborder", true, Game::dvar_flag::DVAR_FLAG_SAVED, "Do not use a border in windowed mode"); Window::NoBorder = Dvar::Register<bool>("r_noborder", true, Game::dvar_flag::DVAR_FLAG_SAVED, "Do not use a border in windowed mode");
Window::NativeCursor = Dvar::Register<bool>("ui_nativeCursor", false, Game::dvar_flag::DVAR_FLAG_SAVED, "Display native cursor"); Window::NativeCursor = Dvar::Register<bool>("ui_nativeCursor", false, Game::dvar_flag::DVAR_FLAG_SAVED, "Display native cursor");
Utils::Hook(0x507643, Window::StyleHookStub, HOOK_CALL).Install()->Quick(); Utils::Hook(0x507643, Window::StyleHookStub, HOOK_CALL).Install()->Quick();
// Main window creation // Main window creation
Utils::Hook::Nop(0x5076AA, 1); Utils::Hook::Nop(0x5076AA, 1);
Utils::Hook(0x5076AB, Window::CreateMainWindow, HOOK_CALL).Install()->Quick(); Utils::Hook(0x5076AB, Window::CreateMainWindow, HOOK_CALL).Install()->Quick();
// Mark the cursor as visible // Mark the cursor as visible
Utils::Hook(0x48E5D3, Window::DrawCursorStub, HOOK_CALL).Install()->Quick(); Utils::Hook(0x48E5D3, Window::DrawCursorStub, HOOK_CALL).Install()->Quick();
// Draw the cursor if necessary // Draw the cursor if necessary
Renderer::OnFrame([] () Renderer::OnFrame([] ()
{ {
if (Window::NativeCursor.Get<bool>() && IsWindow(Window::MainWindow) && GetForegroundWindow() == Window::MainWindow && Window::IsCursorWithin(Window::MainWindow)) if (Window::NativeCursor.Get<bool>() && IsWindow(Window::MainWindow) && GetForegroundWindow() == Window::MainWindow && Window::IsCursorWithin(Window::MainWindow))
{ {
int value = 0; int value = 0;
if (Window::CursorVisible) if (Window::CursorVisible)
{ {
// TODO: Apply custom cursor // TODO: Apply custom cursor
SetCursor(LoadCursor(NULL, IDC_ARROW)); SetCursor(LoadCursor(NULL, IDC_ARROW));
while ((value = ShowCursor(TRUE)) < 0); while ((value = ShowCursor(TRUE)) < 0);
while (value > 0) { value = ShowCursor(FALSE); } // Set display counter to 0 while (value > 0) { value = ShowCursor(FALSE); } // Set display counter to 0
} }
else else
{ {
while ((value = ShowCursor(FALSE)) >= 0); while ((value = ShowCursor(FALSE)) >= 0);
while (value < -1) { value = ShowCursor(TRUE); } // Set display counter to -1 while (value < -1) { value = ShowCursor(TRUE); } // Set display counter to -1
} }
Window::CursorVisible = FALSE; Window::CursorVisible = FALSE;
} }
}); });
// Don't let the game interact with the native cursor // Don't let the game interact with the native cursor
Utils::Hook::Set(0x6D7348, Window::ShowCursorHook); Utils::Hook::Set(0x6D7348, Window::ShowCursorHook);
} }
} }

View File

@ -56,7 +56,7 @@ namespace Utils
*place = Hook::Interceptor::InterceptionStub; *place = Hook::Interceptor::InterceptionStub;
} }
void __declspec(naked) Hook::Interceptor::InterceptionStub() __declspec(naked) void Hook::Interceptor::InterceptionStub()
{ {
__asm __asm
{ {