Steam proxy

This commit is contained in:
momo5502 2016-07-12 18:33:25 +02:00
parent 2ea490382b
commit 245cd533d1
19 changed files with 1544 additions and 1442 deletions

2
deps/fmt vendored

@ -1 +1 @@
Subproject commit 4133e501f3277aeef530b75de2e7bfceca93e5d2 Subproject commit 0d5ef5c2a66026409b0cfbafa1d2f46cdc5aa4d0

2
deps/mongoose vendored

@ -1 +1 @@
Subproject commit 6f7f774080f0c2ec291bfa0a908bc31a923051a1 Subproject commit 36a1927915f966f20486a80070f0428f2606a53a

2
deps/protobuf vendored

@ -1 +1 @@
Subproject commit 790e6afb72ed4ad952d9c74e73ae53a01443fe97 Subproject commit 70c1ac756d3cd8fa04725f82f0ad1a30404c3bb3

View File

@ -1,254 +1,254 @@
#include "STDInclude.hpp" #include "STDInclude.hpp"
namespace Components namespace Components
{ {
Dvar::Var Colors::NewColors; Dvar::Var Colors::NewColors;
std::vector<DWORD> Colors::ColorTable; std::vector<DWORD> Colors::ColorTable;
DWORD Colors::HsvToRgb(Colors::HsvColor hsv) DWORD Colors::HsvToRgb(Colors::HsvColor hsv)
{ {
DWORD rgb; DWORD rgb;
unsigned char region, p, q, t; unsigned char region, p, q, t;
unsigned int h, s, v, remainder; unsigned int h, s, v, remainder;
if (hsv.s == 0) if (hsv.s == 0)
{ {
rgb = RGB(hsv.v, hsv.v, hsv.v); rgb = RGB(hsv.v, hsv.v, hsv.v);
return rgb; return rgb;
} }
// converting to 16 bit to prevent overflow // converting to 16 bit to prevent overflow
h = hsv.h; h = hsv.h;
s = hsv.s; s = hsv.s;
v = hsv.v; v = hsv.v;
region = static_cast<uint8_t>(h / 43); region = static_cast<uint8_t>(h / 43);
remainder = (h - (region * 43)) * 6; remainder = (h - (region * 43)) * 6;
p = static_cast<uint8_t>((v * (255 - s)) >> 8); p = static_cast<uint8_t>((v * (255 - s)) >> 8);
q = static_cast<uint8_t>((v * (255 - ((s * remainder) >> 8))) >> 8); q = static_cast<uint8_t>((v * (255 - ((s * remainder) >> 8))) >> 8);
t = static_cast<uint8_t>((v * (255 - ((s * (255 - remainder)) >> 8))) >> 8); t = static_cast<uint8_t>((v * (255 - ((s * (255 - remainder)) >> 8))) >> 8);
switch (region) switch (region)
{ {
case 0: case 0:
rgb = RGB(v, t, p); rgb = RGB(v, t, p);
break; break;
case 1: case 1:
rgb = RGB(q, v, p); rgb = RGB(q, v, p);
break; break;
case 2: case 2:
rgb = RGB(p, v, t); rgb = RGB(p, v, t);
break; break;
case 3: case 3:
rgb = RGB(p, q, v); rgb = RGB(p, q, v);
break; break;
case 4: case 4:
rgb = RGB(t, p, v); rgb = RGB(t, p, v);
break; break;
default: default:
rgb = RGB(v, p, q); rgb = RGB(v, p, q);
break; break;
} }
return rgb; return rgb;
} }
void Colors::Strip(const char* in, char* out, int max) void Colors::Strip(const char* in, char* out, int max)
{ {
if (!in || !out) return; if (!in || !out) return;
max--; max--;
int current = 0; int current = 0;
while (*in != 0 && current < max) while (*in != 0 && current < max)
{ {
char index = *(in + 1); char index = *(in + 1);
if (*in == '^' && (Colors::ColorIndex(index) != 7 || index == '7')) if (*in == '^' && (Colors::ColorIndex(index) != 7 || index == '7'))
{ {
++in; ++in;
} }
else else
{ {
*out = *in; *out = *in;
++out; ++out;
++current; ++current;
} }
++in; ++in;
} }
*out = '\0'; *out = '\0';
} }
std::string Colors::Strip(std::string in) std::string Colors::Strip(std::string in)
{ {
char buffer[1000] = { 0 }; // Should be more than enough char buffer[1000] = { 0 }; // Should be more than enough
Colors::Strip(in.data(), buffer, sizeof(buffer)); Colors::Strip(in.data(), buffer, sizeof(buffer));
return std::string(buffer); return std::string(buffer);
} }
void __declspec(naked) Colors::ClientUserinfoChanged() void __declspec(naked) Colors::ClientUserinfoChanged()
{ {
__asm __asm
{ {
mov eax, [esp + 4h] // length mov eax, [esp + 4h] // length
sub eax, 1 sub eax, 1
push eax push eax
push ecx // name push ecx // name
push edx // buffer push edx // buffer
call strncpy call strncpy
add esp, 0Ch add esp, 0Ch
retn retn
} }
} }
char* Colors::GetClientName(int localClientNum, int index, char *buf, size_t size) char* Colors::GetClientName(int localClientNum, int index, char *buf, size_t size)
{ {
Game::CL_GetClientName(localClientNum, index, buf, size); Game::CL_GetClientName(localClientNum, index, buf, size);
// Remove the colors // Remove the colors
strncpy(buf, Colors::Strip(buf).data(), size); strncpy_s(buf, size, Colors::Strip(buf).data(), size);
return buf; return buf;
} }
void Colors::PatchColorLimit(char limit) void Colors::PatchColorLimit(char limit)
{ {
Utils::Hook::Set<char>(0x535629, limit); // DrawText2d Utils::Hook::Set<char>(0x535629, limit); // DrawText2d
Utils::Hook::Set<char>(0x4C1BE4, limit); // No idea :P Utils::Hook::Set<char>(0x4C1BE4, limit); // No idea :P
Utils::Hook::Set<char>(0x4863DD, limit); // No idea :P Utils::Hook::Set<char>(0x4863DD, limit); // No idea :P
Utils::Hook::Set<char>(0x486429, limit); // No idea :P Utils::Hook::Set<char>(0x486429, limit); // No idea :P
Utils::Hook::Set<char>(0x49A5A8, limit); // No idea :P Utils::Hook::Set<char>(0x49A5A8, limit); // No idea :P
Utils::Hook::Set<char>(0x505721, limit); // R_TextWidth Utils::Hook::Set<char>(0x505721, limit); // R_TextWidth
Utils::Hook::Set<char>(0x505801, limit); // No idea :P Utils::Hook::Set<char>(0x505801, limit); // No idea :P
Utils::Hook::Set<char>(0x50597F, limit); // No idea :P Utils::Hook::Set<char>(0x50597F, limit); // No idea :P
Utils::Hook::Set<char>(0x5815DB, limit); // No idea :P Utils::Hook::Set<char>(0x5815DB, limit); // No idea :P
Utils::Hook::Set<char>(0x592ED0, limit); // No idea :P Utils::Hook::Set<char>(0x592ED0, limit); // No idea :P
Utils::Hook::Set<char>(0x5A2E2E, limit); // No idea :P Utils::Hook::Set<char>(0x5A2E2E, limit); // No idea :P
Utils::Hook::Set<char>(0x5A2733, limit - '0'); // No idea :P Utils::Hook::Set<char>(0x5A2733, limit - '0'); // No idea :P
} }
char Colors::Add(uint8_t r, uint8_t g, uint8_t b) char Colors::Add(uint8_t r, uint8_t g, uint8_t b)
{ {
char index = '0' + static_cast<char>(Colors::ColorTable.size()); char index = '0' + static_cast<char>(Colors::ColorTable.size());
Colors::ColorTable.push_back(RGB(r, g, b)); Colors::ColorTable.push_back(RGB(r, g, b));
Colors::PatchColorLimit(index); Colors::PatchColorLimit(index);
return index; return index;
} }
unsigned int Colors::ColorIndex(unsigned char index) unsigned int Colors::ColorIndex(unsigned char index)
{ {
unsigned int result = index - '0'; unsigned int result = index - '0';
if (result >= Colors::ColorTable.size() || result < 0) result = 7; if (result >= Colors::ColorTable.size() || result < 0) result = 7;
return result; return result;
} }
void Colors::LookupColor(DWORD* color, char index) void Colors::LookupColor(DWORD* color, char index)
{ {
*color = RGB(255, 255, 255); *color = RGB(255, 255, 255);
if (index == '8') // Color 8 if (index == '8') // Color 8
{ {
*color = *reinterpret_cast<DWORD*>(0x66E5F70); *color = *reinterpret_cast<DWORD*>(0x66E5F70);
} }
else if (index == '9') // Color 9 else if (index == '9') // Color 9
{ {
*color = *reinterpret_cast<DWORD*>(0x66E5F74); *color = *reinterpret_cast<DWORD*>(0x66E5F74);
} }
else if (index == ':') else if (index == ':')
{ {
*color = Colors::HsvToRgb({ static_cast<uint8_t>((Game::Sys_Milliseconds() / 200) % 256), 255,255 }); *color = Colors::HsvToRgb({ static_cast<uint8_t>((Game::Sys_Milliseconds() / 200) % 256), 255,255 });
} }
else if (index == ';') else if (index == ';')
{ {
float fltColor[4]; float fltColor[4];
Game::Dvar_GetUnpackedColorByName("sv_customTextColor", fltColor); Game::Dvar_GetUnpackedColorByName("sv_customTextColor", fltColor);
*color = RGB(fltColor[0] * 255, fltColor[1] * 255, fltColor[2] * 255); *color = RGB(fltColor[0] * 255, fltColor[1] * 255, fltColor[2] * 255);
} }
else else
{ {
int clrIndex = Colors::ColorIndex(index); int clrIndex = Colors::ColorIndex(index);
// Use native colors // Use native colors
if (clrIndex <= 7 && !Colors::NewColors.Get<bool>()) if (clrIndex <= 7 && !Colors::NewColors.Get<bool>())
{ {
*color = reinterpret_cast<DWORD*>(0x78DC70)[index - 48]; *color = reinterpret_cast<DWORD*>(0x78DC70)[index - 48];
} }
else else
{ {
*color = Colors::ColorTable[clrIndex]; *color = Colors::ColorTable[clrIndex];
} }
} }
} }
char* Colors::CleanStrStub(char* string) char* Colors::CleanStrStub(char* string)
{ {
Colors::Strip(string, string, strlen(string) + 1); Colors::Strip(string, string, strlen(string) + 1);
return string; return string;
} }
void __declspec(naked) Colors::LookupColorStub() void __declspec(naked) Colors::LookupColorStub()
{ {
__asm __asm
{ {
push ebx push ebx
push [esp + 8h] // Index push [esp + 8h] // Index
push esi // Color ref push esi // Color ref
call Colors::LookupColor call Colors::LookupColor
add esp, 8h add esp, 8h
pop ebx pop ebx
retn retn
} }
} }
Colors::Colors() Colors::Colors()
{ {
// Disable SV_UpdateUserinfo_f, to block changing the name ingame // Disable SV_UpdateUserinfo_f, to block changing the name ingame
Utils::Hook::Set<BYTE>(0x6258D0, 0xC3); Utils::Hook::Set<BYTE>(0x6258D0, 0xC3);
// Allow colored names ingame // Allow colored names ingame
Utils::Hook(0x5D8B40, Colors::ClientUserinfoChanged, HOOK_JUMP).Install()->Quick(); Utils::Hook(0x5D8B40, Colors::ClientUserinfoChanged, HOOK_JUMP).Install()->Quick();
// Though, don't apply that to overhead names. // Though, don't apply that to overhead names.
Utils::Hook(0x581932, Colors::GetClientName, HOOK_CALL).Install()->Quick(); Utils::Hook(0x581932, Colors::GetClientName, HOOK_CALL).Install()->Quick();
// Patch RB_LookupColor // Patch RB_LookupColor
Utils::Hook(0x534CD0, Colors::LookupColorStub, HOOK_JUMP).Install()->Quick(); Utils::Hook(0x534CD0, Colors::LookupColorStub, HOOK_JUMP).Install()->Quick();
// Patch ColorIndex // Patch ColorIndex
Utils::Hook(0x417770, Colors::ColorIndex, HOOK_JUMP).Install()->Quick(); Utils::Hook(0x417770, Colors::ColorIndex, HOOK_JUMP).Install()->Quick();
// Patch I_CleanStr // Patch I_CleanStr
Utils::Hook(0x4AD470, Colors::CleanStrStub, HOOK_JUMP).Install()->Quick(); Utils::Hook(0x4AD470, Colors::CleanStrStub, HOOK_JUMP).Install()->Quick();
// Register dvar // Register dvar
Colors::NewColors = Dvar::Register<bool>("cg_newColors", true, Game::dvar_flag::DVAR_FLAG_SAVED, "Use Warfare² color code style."); Colors::NewColors = Dvar::Register<bool>("cg_newColors", true, Game::dvar_flag::DVAR_FLAG_SAVED, "Use Warfare² color code style.");
Game::Dvar_RegisterColor("sv_customTextColor", 1, 0.7f, 0, 1, Game::dvar_flag::DVAR_FLAG_REPLICATED, "Color for the extended color code."); Game::Dvar_RegisterColor("sv_customTextColor", 1, 0.7f, 0, 1, Game::dvar_flag::DVAR_FLAG_REPLICATED, "Color for the extended color code.");
// Add our colors // Add our colors
Colors::Add(0, 0, 0); // 0 - Black Colors::Add(0, 0, 0); // 0 - Black
Colors::Add(255, 49, 49); // 1 - Red Colors::Add(255, 49, 49); // 1 - Red
Colors::Add(134, 192, 0); // 2 - Green Colors::Add(134, 192, 0); // 2 - Green
Colors::Add(255, 173, 34); // 3 - Yellow Colors::Add(255, 173, 34); // 3 - Yellow
Colors::Add(0, 135, 193); // 4 - Blue Colors::Add(0, 135, 193); // 4 - Blue
Colors::Add(32, 197, 255); // 5 - Light Blue Colors::Add(32, 197, 255); // 5 - Light Blue
Colors::Add(151, 80, 221); // 6 - Pink Colors::Add(151, 80, 221); // 6 - Pink
Colors::Add(255, 255, 255); // 7 - White Colors::Add(255, 255, 255); // 7 - White
Colors::Add(0, 0, 0); // 8 - Team color (axis?) Colors::Add(0, 0, 0); // 8 - Team color (axis?)
Colors::Add(0, 0, 0); // 9 - Team color (allies?) Colors::Add(0, 0, 0); // 9 - Team color (allies?)
// Custom colors // Custom colors
Colors::Add(0, 0, 0); // 10 - Rainbow (:) Colors::Add(0, 0, 0); // 10 - Rainbow (:)
Colors::Add(0, 0, 0); // 11 - Server color (;) - using that color in infostrings (e.g. your name) fails, ';' is an illegal character! Colors::Add(0, 0, 0); // 11 - Server color (;) - using that color in infostrings (e.g. your name) fails, ';' is an illegal character!
} }
Colors::~Colors() Colors::~Colors()
{ {
Colors::ColorTable.clear(); Colors::ColorTable.clear();
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -13,11 +13,11 @@ namespace Components
{ {
char filename[MAX_PATH]; char filename[MAX_PATH];
__time64_t time; __time64_t time;
tm* ltime; tm ltime;
_time64(&time); _time64(&time);
ltime = _localtime64(&time); _localtime64_s(&ltime, &time);
strftime(filename, sizeof(filename) - 1, "iw4x-" VERSION_STR "-%Y%m%d%H%M%S.dmp", ltime); strftime(filename, sizeof(filename) - 1, "iw4x-" VERSION_STR "-%Y%m%d%H%M%S.dmp", &ltime);
HANDLE hFile = CreateFileA(filename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); HANDLE hFile = CreateFileA(filename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

View File

@ -1,155 +1,155 @@
#include "STDInclude.hpp" #include "STDInclude.hpp"
namespace Components namespace Components
{ {
std::mutex Logger::MessageMutex; std::mutex Logger::MessageMutex;
std::vector<std::string> Logger::MessageQueue; std::vector<std::string> Logger::MessageQueue;
void(*Logger::PipeCallback)(std::string) = nullptr; void(*Logger::PipeCallback)(std::string) = nullptr;
bool Logger::IsConsoleReady() bool Logger::IsConsoleReady()
{ {
return (IsWindow(*reinterpret_cast<HWND*>(0x64A3288)) != FALSE || (Dedicated::IsDedicated() && !Flags::HasFlag("console"))); return (IsWindow(*reinterpret_cast<HWND*>(0x64A3288)) != FALSE || (Dedicated::IsDedicated() && !Flags::HasFlag("console")));
} }
void Logger::Print(const char* message, ...) void Logger::Print(const char* message, ...)
{ {
return Logger::MessagePrint(0, Logger::Format(&message)); return Logger::MessagePrint(0, Logger::Format(&message));
} }
void Logger::Print(int channel, const char* message, ...) void Logger::Print(int channel, const char* message, ...)
{ {
return Logger::MessagePrint(channel, Logger::Format(&message)); return Logger::MessagePrint(channel, Logger::Format(&message));
} }
void Logger::MessagePrint(int channel, std::string message) void Logger::MessagePrint(int channel, std::string message)
{ {
if (Flags::HasFlag("stdout") || Loader::PerformingUnitTests()) if (Flags::HasFlag("stdout") || Loader::PerformingUnitTests())
{ {
printf("%s", message.data()); printf("%s", message.data());
fflush(stdout); fflush(stdout);
return; return;
} }
if (!Logger::IsConsoleReady()) if (!Logger::IsConsoleReady())
{ {
OutputDebugStringA(message.data()); OutputDebugStringA(message.data());
} }
if (!Game::Sys_IsMainThread()) if (!Game::Sys_IsMainThread())
{ {
Logger::EnqueueMessage(message); Logger::EnqueueMessage(message);
} }
else else
{ {
Game::Com_PrintMessage(0, message.data(), 0); Game::Com_PrintMessage(0, message.data(), 0);
} }
} }
void Logger::ErrorPrint(int error, std::string message) void Logger::ErrorPrint(int error, std::string message)
{ {
return Game::Com_Error(error, "%s", message.data()); return Game::Com_Error(error, "%s", message.data());
} }
void Logger::Error(int error, const char* message, ...) void Logger::Error(int error, const char* message, ...)
{ {
return Logger::ErrorPrint(error, Logger::Format(&message)); return Logger::ErrorPrint(error, Logger::Format(&message));
} }
void Logger::Error(const char* message, ...) void Logger::Error(const char* message, ...)
{ {
return Logger::ErrorPrint(0, Logger::Format(&message)); return Logger::ErrorPrint(0, Logger::Format(&message));
} }
void Logger::SoftError(const char* message, ...) void Logger::SoftError(const char* message, ...)
{ {
return Logger::ErrorPrint(2, Logger::Format(&message)); return Logger::ErrorPrint(2, Logger::Format(&message));
} }
std::string Logger::Format(const char** message) std::string Logger::Format(const char** message)
{ {
char buffer[0x1000] = { 0 }; char buffer[0x1000] = { 0 };
va_list ap = reinterpret_cast<char*>(const_cast<char**>(&message[1])); va_list ap = reinterpret_cast<char*>(const_cast<char**>(&message[1]));
//va_start(ap, *message); //va_start(ap, *message);
_vsnprintf(buffer, sizeof(buffer), *message, ap); _vsnprintf_s(buffer, sizeof(buffer), *message, ap);
va_end(ap); va_end(ap);
return buffer; return buffer;
} }
void Logger::Frame() void Logger::Frame()
{ {
Logger::MessageMutex.lock(); Logger::MessageMutex.lock();
for (unsigned int i = 0; i < Logger::MessageQueue.size(); ++i) for (unsigned int i = 0; i < Logger::MessageQueue.size(); ++i)
{ {
Game::Com_PrintMessage(0, Logger::MessageQueue[i].data(), 0); Game::Com_PrintMessage(0, Logger::MessageQueue[i].data(), 0);
if (!Logger::IsConsoleReady()) if (!Logger::IsConsoleReady())
{ {
OutputDebugStringA(Logger::MessageQueue[i].data()); OutputDebugStringA(Logger::MessageQueue[i].data());
} }
} }
Logger::MessageQueue.clear(); Logger::MessageQueue.clear();
Logger::MessageMutex.unlock(); Logger::MessageMutex.unlock();
} }
void Logger::PipeOutput(void(*callback)(std::string)) void Logger::PipeOutput(void(*callback)(std::string))
{ {
Logger::PipeCallback = callback; Logger::PipeCallback = callback;
} }
void Logger::PrintMessagePipe(const char* data) void Logger::PrintMessagePipe(const char* data)
{ {
if (Logger::PipeCallback) if (Logger::PipeCallback)
{ {
Logger::PipeCallback(data); Logger::PipeCallback(data);
} }
} }
void __declspec(naked) Logger::PrintMessageStub() void __declspec(naked) Logger::PrintMessageStub()
{ {
__asm __asm
{ {
mov eax, Logger::PipeCallback mov eax, Logger::PipeCallback
test eax, eax test eax, eax
jz returnPrint jz returnPrint
push [esp + 8h] push [esp + 8h]
call Logger::PrintMessagePipe call Logger::PrintMessagePipe
add esp, 4h add esp, 4h
retn retn
returnPrint: returnPrint:
push esi push esi
mov esi, [esp + 0Ch] mov esi, [esp + 0Ch]
mov eax, 4AA835h mov eax, 4AA835h
jmp eax jmp eax
} }
} }
void Logger::EnqueueMessage(std::string message) void Logger::EnqueueMessage(std::string message)
{ {
Logger::MessageMutex.lock(); Logger::MessageMutex.lock();
Logger::MessageQueue.push_back(message); Logger::MessageQueue.push_back(message);
Logger::MessageMutex.unlock(); Logger::MessageMutex.unlock();
} }
Logger::Logger() Logger::Logger()
{ {
Logger::PipeOutput(nullptr); Logger::PipeOutput(nullptr);
QuickPatch::OnFrame(Logger::Frame); QuickPatch::OnFrame(Logger::Frame);
Utils::Hook(Game::Com_PrintMessage, Logger::PrintMessageStub, HOOK_JUMP).Install()->Quick(); Utils::Hook(Game::Com_PrintMessage, Logger::PrintMessageStub, HOOK_JUMP).Install()->Quick();
} }
Logger::~Logger() Logger::~Logger()
{ {
Logger::MessageMutex.lock(); Logger::MessageMutex.lock();
Logger::MessageQueue.clear(); Logger::MessageQueue.clear();
Logger::MessageMutex.unlock(); Logger::MessageMutex.unlock();
} }
} }

View File

@ -118,7 +118,7 @@ namespace Components
AntiCheat::EmptyHash(); AntiCheat::EmptyHash();
_snprintf(buffer, size, format, mapname); _snprintf_s(buffer, size, size, format, mapname);
} }
void Maps::AddDependency(std::string expression, std::string zone) void Maps::AddDependency(std::string expression, std::string zone)

View File

@ -45,7 +45,7 @@ namespace Components
Game::Script_SetupTokens(script, reinterpret_cast<char*>(0x797F80)); Game::Script_SetupTokens(script, reinterpret_cast<char*>(0x797F80));
script->punctuations = reinterpret_cast<Game::punctuation_t*>(0x797F80); script->punctuations = reinterpret_cast<Game::punctuation_t*>(0x797F80);
strcpy(script->buffer, buffer.data()); memcpy(script->buffer, buffer.data(), script->length + 1);
script->length = Game::Script_CleanString(script->buffer); script->length = Game::Script_CleanString(script->buffer);
@ -75,7 +75,7 @@ namespace Components
return 0; return 0;
} }
strncpy(source->filename, "string", 64); strncpy_s(source->filename, 64, "string", 64);
source->scriptstack = script; source->scriptstack = script;
source->tokens = NULL; source->tokens = NULL;
source->defines = NULL; source->defines = NULL;

View File

@ -305,6 +305,7 @@ namespace Components
Utils::Hook::Nop(0x6830B1, 20); Utils::Hook::Nop(0x6830B1, 20);
Utils::Hook(0x682EBF, QuickPatch::GetStatsID, HOOK_CALL).Install()->Quick(); Utils::Hook(0x682EBF, QuickPatch::GetStatsID, HOOK_CALL).Install()->Quick();
Utils::Hook(0x6830B1, QuickPatch::GetStatsID, HOOK_CALL).Install()->Quick(); Utils::Hook(0x6830B1, QuickPatch::GetStatsID, HOOK_CALL).Install()->Quick();
//Utils::Hook::Set<BYTE>(0x68323A, 0xEB);
// Exploit fixes // Exploit fixes
Utils::Hook(0x414D92, QuickPatch::MsgReadBitsCompressCheckSV, HOOK_CALL).Install()->Quick(); Utils::Hook(0x414D92, QuickPatch::MsgReadBitsCompressCheckSV, HOOK_CALL).Install()->Quick();

View File

@ -144,7 +144,7 @@ namespace Components
char msgbuf[1024] = { 0 }; char msgbuf[1024] = { 0 };
va_list v; va_list v;
va_start(v, message); va_start(v, message);
_vsnprintf(msgbuf, sizeof(msgbuf), message, v); _vsnprintf_s(msgbuf, sizeof(msgbuf), message, v);
va_end(v); va_end(v);
Game::Scr_ShutdownAllocNode(); Game::Scr_ShutdownAllocNode();

View File

@ -271,12 +271,17 @@ namespace Components
Theatre::DemoContainer.CurrentSelection = index; Theatre::DemoContainer.CurrentSelection = index;
Theatre::Container::DemoInfo info = Theatre::DemoContainer.Demos[index]; Theatre::Container::DemoInfo info = Theatre::DemoContainer.Demos[index];
tm time;
char buffer[1000] = { 0 };
localtime_s(&time, &info.TimeStamp);
asctime_s(buffer, sizeof buffer, &time);
Dvar::Var("ui_demo_mapname").Set(info.Mapname); Dvar::Var("ui_demo_mapname").Set(info.Mapname);
Dvar::Var("ui_demo_mapname_localized").Set(Game::UI_LocalizeMapName(info.Mapname.data())); Dvar::Var("ui_demo_mapname_localized").Set(Game::UI_LocalizeMapName(info.Mapname.data()));
Dvar::Var("ui_demo_gametype").Set(Game::UI_LocalizeGameType(info.Gametype.data())); Dvar::Var("ui_demo_gametype").Set(Game::UI_LocalizeGameType(info.Gametype.data()));
Dvar::Var("ui_demo_length").Set(Utils::String::FormatTimeSpan(info.Length)); Dvar::Var("ui_demo_length").Set(Utils::String::FormatTimeSpan(info.Length));
Dvar::Var("ui_demo_author").Set(info.Author); Dvar::Var("ui_demo_author").Set(info.Author);
Dvar::Var("ui_demo_date").Set(std::asctime(std::localtime(&info.TimeStamp))); Dvar::Var("ui_demo_date").Set(buffer);
} }
} }

View File

@ -8,7 +8,7 @@
// Disable irrelevant warnings // Disable irrelevant warnings
#pragma warning(disable: 4100) // Unreferenced parameter (steam has to have them and other stubs as well, due to their calling convention) #pragma warning(disable: 4100) // Unreferenced parameter (steam has to have them and other stubs as well, due to their calling convention)
#define _CRT_SECURE_NO_WARNINGS #define VC_EXTRALEAN
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>

View File

@ -1,105 +1,97 @@
#include "STDInclude.hpp" #include "STDInclude.hpp"
namespace Steam namespace Steam
{ {
unsigned int Utils::GetSecondsSinceAppActive() unsigned int Utils::GetSecondsSinceAppActive()
{ {
return 0; return 0;
} }
unsigned int Utils::GetSecondsSinceComputerActive() unsigned int Utils::GetSecondsSinceComputerActive()
{ {
return 0; return 0;
} }
int Utils::GetConnectedUniverse() int Utils::GetConnectedUniverse()
{ {
return 1; return 1;
} }
unsigned int Utils::GetServerRealTime() unsigned int Utils::GetServerRealTime()
{ {
return 0; return 0;
} }
const char* Utils::GetIPCountry() const char* Utils::GetIPCountry()
{ {
return "US"; return "US";
} }
bool Utils::GetImageSize(int iImage, unsigned int *pnWidth, unsigned int *pnHeight) bool Utils::GetImageSize(int iImage, unsigned int *pnWidth, unsigned int *pnHeight)
{ {
return false; return false;
} }
bool Utils::GetImageRGBA(int iImage, unsigned char *pubDest, int nDestBufferSize) bool Utils::GetImageRGBA(int iImage, unsigned char *pubDest, int nDestBufferSize)
{ {
return false; return false;
} }
bool Utils::GetCSERIPPort(unsigned int *unIP, unsigned short *usPort) bool Utils::GetCSERIPPort(unsigned int *unIP, unsigned short *usPort)
{ {
return false; return false;
} }
unsigned char Utils::GetCurrentBatteryPower() unsigned char Utils::GetCurrentBatteryPower()
{ {
return 255; return 255;
} }
unsigned int Utils::GetAppID() unsigned int Utils::GetAppID()
{ {
return 10190; return 10190;
} }
void Utils::SetOverlayNotificationPosition(int eNotificationPosition) void Utils::SetOverlayNotificationPosition(int eNotificationPosition)
{ {
if (Steam::Overlay) Proxy::SetOverlayNotificationPosition(eNotificationPosition);
{ }
FARPROC setPosition = GetProcAddress(Steam::Overlay, "SetNotificationPosition");
bool Utils::IsAPICallCompleted(unsigned __int64 hSteamAPICall, bool *pbFailed)
if (setPosition) {
{ return false;
::Utils::Hook::Call<void(int)>(setPosition)(eNotificationPosition); }
}
} int Utils::GetAPICallFailureReason(unsigned __int64 hSteamAPICall)
} {
return -1;
bool Utils::IsAPICallCompleted(unsigned __int64 hSteamAPICall, bool *pbFailed) }
{
return false; bool Utils::GetAPICallResult(unsigned __int64 hSteamAPICall, void *pCallback, int cubCallback, int iCallbackExpected, bool *pbFailed)
} {
return false;
int Utils::GetAPICallFailureReason(unsigned __int64 hSteamAPICall) }
{
return -1; void Utils::RunFrame()
} {
}
bool Utils::GetAPICallResult(unsigned __int64 hSteamAPICall, void *pCallback, int cubCallback, int iCallbackExpected, bool *pbFailed)
{ unsigned int Utils::GetIPCCallCount()
return false; {
} return 0;
}
void Utils::RunFrame()
{ void Utils::SetWarningMessageHook(void(*pFunction)(int hpipe, const char *message))
} {
}
unsigned int Utils::GetIPCCallCount()
{ bool Utils::IsOverlayEnabled()
return 0; {
} return false;
}
void Utils::SetWarningMessageHook(void(*pFunction)(int hpipe, const char *message))
{ bool Utils::BOverlayNeedsPresent()
} {
return false;
bool Utils::IsOverlayEnabled() }
{ }
return false;
}
bool Utils::BOverlayNeedsPresent()
{
return false;
}
}

88
src/Steam/Proxy.cpp Normal file
View File

@ -0,0 +1,88 @@
#include "STDInclude.hpp"
namespace Steam
{
HMODULE Proxy::Client = nullptr;
HMODULE Proxy::Overlay = nullptr;
bool Proxy::Inititalize()
{
std::string directoy = Proxy::GetSteamDirectory();
if (directoy.empty()) return false;
SetDllDirectoryA(Proxy::GetSteamDirectory().data());
Proxy::Client = LoadLibraryA(STEAMCLIENT_LIB);
Proxy::Overlay = LoadLibraryA(GAMEOVERLAY_LIB);
return (Proxy::Client && Proxy::Overlay);
}
void Proxy::Uninititalize()
{
if (Proxy::Client) FreeLibrary(Proxy::Client);
Proxy::Client = nullptr;
if (Proxy::Overlay) FreeLibrary(Proxy::Overlay);
Proxy::Overlay = nullptr;
}
std::string Proxy::GetSteamDirectory()
{
HKEY hRegKey;
char SteamPath[MAX_PATH];
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, STEAM_REGISTRY_PATH, 0, KEY_QUERY_VALUE, &hRegKey) == ERROR_SUCCESS)
{
DWORD dwLength = sizeof(SteamPath);
RegQueryValueExA(hRegKey, "InstallPath", NULL, NULL, reinterpret_cast<BYTE*>(SteamPath), &dwLength);
RegCloseKey(hRegKey);
return SteamPath;
}
return "";
}
void Proxy::SetOverlayNotificationPosition(uint32_t eNotificationPosition)
{
if (Proxy::Overlay)
{
FARPROC SetNotificationPositionFn = GetProcAddress(Proxy::Overlay, "SetNotificationPosition");
if (SetNotificationPositionFn)
{
::Utils::Hook::Call<void(uint32_t)>(SetNotificationPositionFn)(eNotificationPosition);
}
}
}
bool Proxy::IsOverlayEnabled()
{
if (Proxy::Overlay)
{
FARPROC IsOverlayEnabledFn = GetProcAddress(Proxy::Overlay, "IsOverlayEnabled");
if (IsOverlayEnabledFn)
{
return ::Utils::Hook::Call<bool()>(IsOverlayEnabledFn)();
}
}
return false;
}
bool Proxy::BOverlayNeedsPresent()
{
if (Proxy::Overlay)
{
FARPROC BOverlayNeedsPresentFn = GetProcAddress(Proxy::Overlay, "BOverlayNeedsPresent");
if (BOverlayNeedsPresentFn)
{
return ::Utils::Hook::Call<bool()>(BOverlayNeedsPresentFn)();
}
}
return false;
}
}

30
src/Steam/Proxy.hpp Normal file
View File

@ -0,0 +1,30 @@
#ifdef _WIN64
#define GAMEOVERLAY_LIB "gameoverlayrenderer64.dll"
#define STEAMCLIENT_LIB "steamclient64.dll"
#define STEAM_REGISTRY_PATH "Software\\Wow6432Node\\Valve\\Steam"
#else
#define GAMEOVERLAY_LIB "gameoverlayrenderer.dll"
#define STEAMCLIENT_LIB "steamclient.dll"
#define STEAM_REGISTRY_PATH "Software\\Valve\\Steam"
#endif
namespace Steam
{
class Proxy
{
public:
static bool Inititalize();
static void Uninititalize();
//Overlay related proxies
static void SetOverlayNotificationPosition(uint32_t eNotificationPosition);
static bool IsOverlayEnabled();
static bool BOverlayNeedsPresent();
private:
static HMODULE Client;
static HMODULE Overlay;
static std::string GetSteamDirectory();
};
}

View File

@ -2,8 +2,6 @@
namespace Steam namespace Steam
{ {
HMODULE Overlay = 0;
uint64_t Callbacks::CallID = 0; uint64_t Callbacks::CallID = 0;
std::map<uint64_t, bool> Callbacks::Calls; std::map<uint64_t, bool> Callbacks::Calls;
std::map<uint64_t, Callbacks::Base*> Callbacks::ResultHandlers; std::map<uint64_t, Callbacks::Base*> Callbacks::ResultHandlers;
@ -71,22 +69,9 @@ namespace Steam
{ {
bool SteamAPI_Init() bool SteamAPI_Init()
{ {
Overlay = GetModuleHandleA("gameoverlayrenderer.dll"); if (!Proxy::Inititalize())
if (!Overlay)
{ {
HKEY hRegKey; OutputDebugStringA("Steamproxy not initialized properly");
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Valve\\Steam", 0, KEY_QUERY_VALUE, &hRegKey) == ERROR_SUCCESS)
{
char steamPath[MAX_PATH] = { 0 };
DWORD dwLength = sizeof(steamPath);
RegQueryValueExA(hRegKey, "InstallPath", NULL, NULL, reinterpret_cast<BYTE*>(steamPath), &dwLength);
RegCloseKey(hRegKey);
SetDllDirectoryA(steamPath);
Overlay = LoadLibraryA(::Utils::String::VA("%s\\%s", steamPath, "gameoverlayrenderer.dll"));
}
} }
return true; return true;
@ -109,6 +94,7 @@ namespace Steam
void SteamAPI_Shutdown() void SteamAPI_Shutdown()
{ {
Proxy::Uninititalize();
} }
void SteamAPI_UnregisterCallResult() void SteamAPI_UnregisterCallResult()

View File

@ -1,93 +1,93 @@
#pragma once #pragma once
#define STEAM_EXPORT extern "C" __declspec(dllexport) #define STEAM_EXPORT extern "C" __declspec(dllexport)
typedef union typedef union
{ {
struct struct
{ {
unsigned int AccountID : 32; unsigned int AccountID : 32;
unsigned int AccountInstance : 20; unsigned int AccountInstance : 20;
unsigned int AccountType : 4; unsigned int AccountType : 4;
int Universe : 8; int Universe : 8;
}; };
unsigned long long Bits; unsigned long long Bits;
} SteamID; } SteamID;
#include "Interfaces\SteamUser.hpp" #include "Interfaces\SteamUser.hpp"
#include "Interfaces\SteamUtils.hpp" #include "Interfaces\SteamUtils.hpp"
#include "Interfaces\SteamFriends.hpp" #include "Interfaces\SteamFriends.hpp"
#include "Interfaces\SteamGameServer.hpp" #include "Interfaces\SteamGameServer.hpp"
#include "Interfaces\SteamNetworking.hpp" #include "Interfaces\SteamNetworking.hpp"
#include "Interfaces\SteamMatchmaking.hpp" #include "Interfaces\SteamMatchmaking.hpp"
#include "Interfaces\SteamRemoteStorage.hpp" #include "Interfaces\SteamRemoteStorage.hpp"
#include "Interfaces\SteamMasterServerUpdater.hpp" #include "Interfaces\SteamMasterServerUpdater.hpp"
namespace Steam #include "Proxy.hpp"
{
class Callbacks namespace Steam
{ {
public: class Callbacks
class Base {
{ public:
public: class Base
Base() : Flags(0), Callback(0) {}; {
public:
virtual void Run(void *pvParam) = 0; Base() : Flags(0), Callback(0) {};
virtual void Run(void *pvParam, bool bIOFailure, uint64_t hSteamAPICall) = 0;
virtual int GetCallbackSizeBytes() = 0; virtual void Run(void *pvParam) = 0;
virtual void Run(void *pvParam, bool bIOFailure, uint64_t hSteamAPICall) = 0;
int GetICallback() { return Callback; } virtual int GetCallbackSizeBytes() = 0;
void SetICallback(int iCallback) { Callback = iCallback; }
int GetICallback() { return Callback; }
protected: void SetICallback(int iCallback) { Callback = iCallback; }
unsigned char Flags;
int Callback; protected:
}; unsigned char Flags;
int Callback;
struct Result };
{
void* data; struct Result
int size; {
int type; void* data;
uint64_t call; int size;
}; int type;
uint64_t call;
static uint64_t RegisterCall(); };
static void RegisterCallback(Base* handler, int callback);
static void RegisterCallResult(uint64_t call, Base* result); static uint64_t RegisterCall();
static void ReturnCall(void* data, int size, int type, uint64_t call); static void RegisterCallback(Base* handler, int callback);
static void RunCallbacks(); static void RegisterCallResult(uint64_t call, Base* result);
static void ReturnCall(void* data, int size, int type, uint64_t call);
private: static void RunCallbacks();
static uint64_t CallID;
static std::map<uint64_t, bool> Calls; private:
static std::map<uint64_t, Base*> ResultHandlers; static uint64_t CallID;
static std::vector<Result> Results; static std::map<uint64_t, bool> Calls;
static std::vector<Base*> CallbackList; static std::map<uint64_t, Base*> ResultHandlers;
}; static std::vector<Result> Results;
static std::vector<Base*> CallbackList;
STEAM_EXPORT bool SteamAPI_Init(); };
STEAM_EXPORT void SteamAPI_RegisterCallResult(Callbacks::Base* result, uint64_t call);
STEAM_EXPORT void SteamAPI_RegisterCallback(Callbacks::Base* handler, int callback); STEAM_EXPORT bool SteamAPI_Init();
STEAM_EXPORT void SteamAPI_RunCallbacks(); STEAM_EXPORT void SteamAPI_RegisterCallResult(Callbacks::Base* result, uint64_t call);
STEAM_EXPORT void SteamAPI_Shutdown(); STEAM_EXPORT void SteamAPI_RegisterCallback(Callbacks::Base* handler, int callback);
STEAM_EXPORT void SteamAPI_UnregisterCallResult(); STEAM_EXPORT void SteamAPI_RunCallbacks();
STEAM_EXPORT void SteamAPI_UnregisterCallback(); STEAM_EXPORT void SteamAPI_Shutdown();
STEAM_EXPORT void SteamAPI_UnregisterCallResult();
STEAM_EXPORT bool SteamGameServer_Init(); STEAM_EXPORT void SteamAPI_UnregisterCallback();
STEAM_EXPORT void SteamGameServer_RunCallbacks();
STEAM_EXPORT void SteamGameServer_Shutdown(); STEAM_EXPORT bool SteamGameServer_Init();
STEAM_EXPORT void SteamGameServer_RunCallbacks();
STEAM_EXPORT Steam::Friends* SteamFriends(); STEAM_EXPORT void SteamGameServer_Shutdown();
STEAM_EXPORT Steam::Matchmaking* SteamMatchmaking();
STEAM_EXPORT Steam::GameServer* SteamGameServer(); STEAM_EXPORT Steam::Friends* SteamFriends();
STEAM_EXPORT Steam::MasterServerUpdater* SteamMasterServerUpdater(); STEAM_EXPORT Steam::Matchmaking* SteamMatchmaking();
STEAM_EXPORT Steam::Networking* SteamNetworking(); STEAM_EXPORT Steam::GameServer* SteamGameServer();
STEAM_EXPORT Steam::RemoteStorage* SteamRemoteStorage(); STEAM_EXPORT Steam::MasterServerUpdater* SteamMasterServerUpdater();
STEAM_EXPORT Steam::User* SteamUser(); STEAM_EXPORT Steam::Networking* SteamNetworking();
STEAM_EXPORT Steam::Utils* SteamUtils(); STEAM_EXPORT Steam::RemoteStorage* SteamRemoteStorage();
STEAM_EXPORT Steam::User* SteamUser();
extern HMODULE Overlay; STEAM_EXPORT Steam::Utils* SteamUtils();
} }

View File

@ -1,257 +1,257 @@
#include "STDInclude.hpp" #include "STDInclude.hpp"
namespace Utils namespace Utils
{ {
std::map<void*, void*> Hook::Interceptor::IReturn; std::map<void*, void*> Hook::Interceptor::IReturn;
std::map<void*, void(*)()> Hook::Interceptor::ICallbacks; std::map<void*, void(*)()> Hook::Interceptor::ICallbacks;
void Hook::Signature::Process() void Hook::Signature::Process()
{ {
if (Hook::Signature::Signatures.empty()) return; if (Hook::Signature::Signatures.empty()) return;
char* start = reinterpret_cast<char*>(Hook::Signature::Start); char* start = reinterpret_cast<char*>(Hook::Signature::Start);
unsigned int sigCount = Hook::Signature::Signatures.size(); unsigned int sigCount = Hook::Signature::Signatures.size();
Hook::Signature::Container* containers = Hook::Signature::Signatures.data(); Hook::Signature::Container* containers = Hook::Signature::Signatures.data();
for (size_t i = 0; i < Hook::Signature::Length; ++i) for (size_t i = 0; i < Hook::Signature::Length; ++i)
{ {
char* address = start + i; char* address = start + i;
for (unsigned int k = 0; k < sigCount; ++k) for (unsigned int k = 0; k < sigCount; ++k)
{ {
Hook::Signature::Container* container = &containers[k]; Hook::Signature::Container* container = &containers[k];
unsigned int j = 0; unsigned int j = 0;
for (j = 0; j < strlen(container->Mask); ++j) for (j = 0; j < strlen(container->Mask); ++j)
{ {
if (container->Mask[j] != '?' &&container->Signature[j] != address[j]) if (container->Mask[j] != '?' &&container->Signature[j] != address[j])
{ {
break; break;
} }
} }
if (j == strlen(container->Mask)) if (j == strlen(container->Mask))
{ {
container->Callback(address); container->Callback(address);
} }
} }
} }
} }
void Hook::Signature::Add(Hook::Signature::Container& container) void Hook::Signature::Add(Hook::Signature::Container& container)
{ {
Hook::Signature::Signatures.push_back(container); Hook::Signature::Signatures.push_back(container);
} }
void Hook::Interceptor::Install(void* place, void(*stub)()) void Hook::Interceptor::Install(void* place, void(*stub)())
{ {
return Hook::Interceptor::Install(reinterpret_cast<void**>(place), stub); return Hook::Interceptor::Install(reinterpret_cast<void**>(place), stub);
} }
void Hook::Interceptor::Install(void** place, void(*stub)()) void Hook::Interceptor::Install(void** place, void(*stub)())
{ {
Hook::Interceptor::IReturn[place] = *place; Hook::Interceptor::IReturn[place] = *place;
Hook::Interceptor::ICallbacks[place] = stub; Hook::Interceptor::ICallbacks[place] = stub;
*place = Hook::Interceptor::InterceptionStub; *place = Hook::Interceptor::InterceptionStub;
} }
void __declspec(naked) Hook::Interceptor::InterceptionStub() void __declspec(naked) Hook::Interceptor::InterceptionStub()
{ {
__asm __asm
{ {
sub esp, 4h // Reserve space on the stack for the return address sub esp, 4h // Reserve space on the stack for the return address
pushad // Store registers pushad // Store registers
lea eax, [esp + 20h] // Load initial stack pointer lea eax, [esp + 20h] // Load initial stack pointer
push eax // Push it onto the stack push eax // Push it onto the stack
call RunCallback // Run the callback based on the given stack pointer call RunCallback // Run the callback based on the given stack pointer
call PopReturn // Get the initial return address according to the stack pointer call PopReturn // Get the initial return address according to the stack pointer
add esp, 4h // Clear the stack add esp, 4h // Clear the stack
mov [esp + 20h], eax // Store the return address at the reserved space mov [esp + 20h], eax // Store the return address at the reserved space
popad // Restore the registers popad // Restore the registers
retn // Return (jump to our return address) retn // Return (jump to our return address)
} }
} }
void Hook::Interceptor::RunCallback(void* place) void Hook::Interceptor::RunCallback(void* place)
{ {
auto iCallback = Hook::Interceptor::ICallbacks.find(place); auto iCallback = Hook::Interceptor::ICallbacks.find(place);
if (iCallback != Hook::Interceptor::ICallbacks.end()) if (iCallback != Hook::Interceptor::ICallbacks.end())
{ {
iCallback->second(); iCallback->second();
Hook::Interceptor::ICallbacks.erase(iCallback); Hook::Interceptor::ICallbacks.erase(iCallback);
} }
} }
void* Hook::Interceptor::PopReturn(void* place) void* Hook::Interceptor::PopReturn(void* place)
{ {
void* retVal = nullptr; void* retVal = nullptr;
auto iReturn = Hook::Interceptor::IReturn.find(place); auto iReturn = Hook::Interceptor::IReturn.find(place);
if (iReturn != Hook::Interceptor::IReturn.end()) if (iReturn != Hook::Interceptor::IReturn.end())
{ {
retVal = iReturn->second; retVal = iReturn->second;
Hook::Interceptor::IReturn.erase(iReturn); Hook::Interceptor::IReturn.erase(iReturn);
} }
return retVal; return retVal;
} }
Hook::~Hook() Hook::~Hook()
{ {
if (Hook::Initialized) if (Hook::Initialized)
{ {
Hook::Uninstall(); Hook::Uninstall();
} }
} }
Hook* Hook::Initialize(DWORD place, void(*stub)(), bool useJump) Hook* Hook::Initialize(DWORD place, void(*stub)(), bool useJump)
{ {
return Hook::Initialize(place, reinterpret_cast<void*>(stub), useJump); return Hook::Initialize(place, reinterpret_cast<void*>(stub), useJump);
} }
Hook* Hook::Initialize(DWORD place, void* stub, bool useJump) Hook* Hook::Initialize(DWORD place, void* stub, bool useJump)
{ {
return Hook::Initialize(reinterpret_cast<void*>(place), stub, useJump); return Hook::Initialize(reinterpret_cast<void*>(place), stub, useJump);
} }
Hook* Hook::Initialize(void* place, void* stub, bool useJump) Hook* Hook::Initialize(void* place, void* stub, bool useJump)
{ {
if (Hook::Initialized) return this; if (Hook::Initialized) return this;
Hook::Initialized = true; Hook::Initialized = true;
Hook::UseJump = useJump; Hook::UseJump = useJump;
Hook::Place = place; Hook::Place = place;
Hook::Stub = stub; Hook::Stub = stub;
Hook::Original = static_cast<char*>(Hook::Place) + 5 + *reinterpret_cast<DWORD*>((static_cast<char*>(Hook::Place) + 1)); Hook::Original = static_cast<char*>(Hook::Place) + 5 + *reinterpret_cast<DWORD*>((static_cast<char*>(Hook::Place) + 1));
return this; return this;
} }
Hook* Hook::Install(bool unprotect, bool keepUnportected) Hook* Hook::Install(bool unprotect, bool keepUnportected)
{ {
Hook::StateMutex.lock(); Hook::StateMutex.lock();
if (!Hook::Initialized || Hook::Installed) if (!Hook::Initialized || Hook::Installed)
{ {
Hook::StateMutex.unlock(); Hook::StateMutex.unlock();
return this; return this;
} }
Hook::Installed = true; Hook::Installed = true;
if (unprotect) VirtualProtect(Hook::Place, sizeof(Hook::Buffer), PAGE_EXECUTE_READWRITE, &this->Protection); if (unprotect) VirtualProtect(Hook::Place, sizeof(Hook::Buffer), PAGE_EXECUTE_READWRITE, &this->Protection);
std::memcpy(Hook::Buffer, Hook::Place, sizeof(Hook::Buffer)); std::memcpy(Hook::Buffer, Hook::Place, sizeof(Hook::Buffer));
char* code = static_cast<char*>(Hook::Place); char* code = static_cast<char*>(Hook::Place);
*code = static_cast<char>(Hook::UseJump ? 0xE9 : 0xE8); *code = static_cast<char>(Hook::UseJump ? 0xE9 : 0xE8);
*reinterpret_cast<size_t*>(code + 1) = reinterpret_cast<size_t>(Hook::Stub) - (reinterpret_cast<size_t>(Hook::Place) + 5); *reinterpret_cast<size_t*>(code + 1) = reinterpret_cast<size_t>(Hook::Stub) - (reinterpret_cast<size_t>(Hook::Place) + 5);
if (unprotect && !keepUnportected) VirtualProtect(Hook::Place, sizeof(Hook::Buffer), Hook::Protection, &this->Protection); if (unprotect && !keepUnportected) VirtualProtect(Hook::Place, sizeof(Hook::Buffer), Hook::Protection, &this->Protection);
FlushInstructionCache(GetCurrentProcess(), Hook::Place, sizeof(Hook::Buffer)); FlushInstructionCache(GetCurrentProcess(), Hook::Place, sizeof(Hook::Buffer));
Hook::StateMutex.unlock(); Hook::StateMutex.unlock();
return this; return this;
} }
void Hook::Quick() void Hook::Quick()
{ {
if (Hook::Installed) if (Hook::Installed)
{ {
Hook::Installed = false; Hook::Installed = false;
} }
} }
Hook* Hook::Uninstall(bool unprotect) Hook* Hook::Uninstall(bool unprotect)
{ {
Hook::StateMutex.lock(); Hook::StateMutex.lock();
if (!Hook::Initialized || !Hook::Installed) if (!Hook::Initialized || !Hook::Installed)
{ {
Hook::StateMutex.unlock(); Hook::StateMutex.unlock();
return this; return this;
} }
Hook::Installed = false; Hook::Installed = false;
if(unprotect) VirtualProtect(Hook::Place, sizeof(Hook::Buffer), PAGE_EXECUTE_READWRITE, &this->Protection); if(unprotect) VirtualProtect(Hook::Place, sizeof(Hook::Buffer), PAGE_EXECUTE_READWRITE, &this->Protection);
std::memcpy(Hook::Place, Hook::Buffer, sizeof(Hook::Buffer)); std::memcpy(Hook::Place, Hook::Buffer, sizeof(Hook::Buffer));
if (unprotect) VirtualProtect(Hook::Place, sizeof(Hook::Buffer), Hook::Protection, &this->Protection); if (unprotect) VirtualProtect(Hook::Place, sizeof(Hook::Buffer), Hook::Protection, &this->Protection);
FlushInstructionCache(GetCurrentProcess(), Hook::Place, sizeof(Hook::Buffer)); FlushInstructionCache(GetCurrentProcess(), Hook::Place, sizeof(Hook::Buffer));
Hook::StateMutex.unlock(); Hook::StateMutex.unlock();
return this; return this;
} }
void* Hook::GetAddress() void* Hook::GetAddress()
{ {
return Hook::Place; return Hook::Place;
} }
void Hook::Nop(void* place, size_t length) void Hook::Nop(void* place, size_t length)
{ {
DWORD oldProtect; DWORD oldProtect;
VirtualProtect(place, length, PAGE_EXECUTE_READWRITE, &oldProtect); VirtualProtect(place, length, PAGE_EXECUTE_READWRITE, &oldProtect);
memset(place, 0x90, length); memset(place, 0x90, length);
VirtualProtect(place, length, oldProtect, &oldProtect); VirtualProtect(place, length, oldProtect, &oldProtect);
FlushInstructionCache(GetCurrentProcess(), place, length); FlushInstructionCache(GetCurrentProcess(), place, length);
} }
void Hook::Nop(DWORD place, size_t length) void Hook::Nop(DWORD place, size_t length)
{ {
Nop(reinterpret_cast<void*>(place), length); Nop(reinterpret_cast<void*>(place), length);
} }
void Hook::SetString(void* place, const char* string, size_t length) void Hook::SetString(void* place, const char* string, size_t length)
{ {
DWORD oldProtect; DWORD oldProtect;
VirtualProtect(place, length + 1, PAGE_EXECUTE_READWRITE, &oldProtect); VirtualProtect(place, length + 1, PAGE_EXECUTE_READWRITE, &oldProtect);
strncpy(static_cast<char*>(place), string, length); strncpy_s(static_cast<char*>(place), length, string, length);
VirtualProtect(place, length + 1, oldProtect, &oldProtect); VirtualProtect(place, length + 1, oldProtect, &oldProtect);
} }
void Hook::SetString(DWORD place, const char* string, size_t length) void Hook::SetString(DWORD place, const char* string, size_t length)
{ {
Hook::SetString(reinterpret_cast<void*>(place), string, length); Hook::SetString(reinterpret_cast<void*>(place), string, length);
} }
void Hook::SetString(void* place, const char* string) void Hook::SetString(void* place, const char* string)
{ {
Hook::SetString(place, string, strlen(static_cast<char*>(place))); Hook::SetString(place, string, strlen(static_cast<char*>(place)));
} }
void Hook::SetString(DWORD place, const char* string) void Hook::SetString(DWORD place, const char* string)
{ {
Hook::SetString(reinterpret_cast<void*>(place), string); Hook::SetString(reinterpret_cast<void*>(place), string);
} }
void Hook::RedirectJump(void* place, void* stub) void Hook::RedirectJump(void* place, void* stub)
{ {
char* operandPtr = static_cast<char*>(place) + 2; char* operandPtr = static_cast<char*>(place) + 2;
int newOperand = reinterpret_cast<int>(stub) - (reinterpret_cast<int>(place) + 6); int newOperand = reinterpret_cast<int>(stub) - (reinterpret_cast<int>(place) + 6);
Utils::Hook::Set<int>(operandPtr, newOperand); Utils::Hook::Set<int>(operandPtr, newOperand);
} }
void Hook::RedirectJump(DWORD place, void* stub) void Hook::RedirectJump(DWORD place, void* stub)
{ {
Hook::RedirectJump(reinterpret_cast<void*>(place), stub); Hook::RedirectJump(reinterpret_cast<void*>(place), stub);
} }
} }