diff --git a/ExtraMirror.sln b/ExtraMirror.sln index f2320ee..3954afb 100644 --- a/ExtraMirror.sln +++ b/ExtraMirror.sln @@ -1,26 +1,17 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Express 2013 for Windows Desktop -VisualStudioVersion = 12.0.31101.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26430.6 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shel", "MiniBase\MiniBase.vcxproj", "{ED77F24F-5F18-4201-B6B4-EE4E5352EEF2}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ЭкстраМиррор", "MiniBase\MiniBase.vcxproj", "{ED77F24F-5F18-4201-B6B4-EE4E5352EEF2}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 Release|Win32 = Release|Win32 - Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {ED77F24F-5F18-4201-B6B4-EE4E5352EEF2}.Debug|Win32.ActiveCfg = Debug|Win32 - {ED77F24F-5F18-4201-B6B4-EE4E5352EEF2}.Debug|Win32.Build.0 = Debug|Win32 - {ED77F24F-5F18-4201-B6B4-EE4E5352EEF2}.Debug|x64.ActiveCfg = Debug|x64 - {ED77F24F-5F18-4201-B6B4-EE4E5352EEF2}.Debug|x64.Build.0 = Debug|x64 {ED77F24F-5F18-4201-B6B4-EE4E5352EEF2}.Release|Win32.ActiveCfg = Release|Win32 {ED77F24F-5F18-4201-B6B4-EE4E5352EEF2}.Release|Win32.Build.0 = Release|Win32 - {ED77F24F-5F18-4201-B6B4-EE4E5352EEF2}.Release|x64.ActiveCfg = Release|x64 - {ED77F24F-5F18-4201-B6B4-EE4E5352EEF2}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/MiniBase/MiniBase.vcxproj b/MiniBase/MiniBase.vcxproj index e8fd6d9..8fb3727 100644 --- a/MiniBase/MiniBase.vcxproj +++ b/MiniBase/MiniBase.vcxproj @@ -30,7 +30,7 @@ DynamicLibrary true v140_xp - Unicode + MultiByte DynamicLibrary @@ -70,6 +70,7 @@ true + .mix true @@ -169,7 +170,6 @@ - @@ -180,7 +180,6 @@ - @@ -190,6 +189,5 @@ - - + \ No newline at end of file diff --git a/MiniBase/MiniBase.vcxproj.filters b/MiniBase/MiniBase.vcxproj.filters index 5aed8dc..3233a2c 100644 --- a/MiniBase/MiniBase.vcxproj.filters +++ b/MiniBase/MiniBase.vcxproj.filters @@ -26,9 +26,6 @@ Файлы исходного кода - - Файлы исходного кода - Заголовочные файлы\msg @@ -58,9 +55,6 @@ Заголовочные файлы - - Заголовочные файлы - Заголовочные файлы\msg diff --git a/MiniBase/client.cpp b/MiniBase/client.cpp index 0368c62..f92081f 100644 --- a/MiniBase/client.cpp +++ b/MiniBase/client.cpp @@ -9,18 +9,19 @@ #include #pragma warning(disable:4996) - extern TCHAR g_settingsFileName[MAX_PATH]; bool FirstFrame = false; pfnUserMsgHook pMOTD; GameInfo_t BuildInfo; -cvar_t *random; +cvar_t *steamid_r; map g_modelsHashMap; cvar_t *logsfiles; cvar_t *events_block; - cvar_t *ex_thud; cvar_t *motd_block; + +vector Cvars; + void HookEngineMessages(){ pEngineMsgBase = (PEngineMsg)offset.FindSVCMessages(); pSVC_StuffText = HookEngineMsg("svc_stufftext", SVC_StuffText); @@ -28,26 +29,37 @@ void HookEngineMessages(){ pSVC_SendCvarValue2 = HookEngineMsg("svc_sendcvarvalue2", SVC_SendCvarValue2); pSVC_Director = HookEngineMsg("svc_director", SVC_Director); pSVC_VoiceInit = HookEngineMsg("svc_voiceinit", SVC_VoiceInit); -// pSVC_Resourcelist = HookEngineMsg("svc_resourcelist", SVC_Resourcelist); } -void ConsolePrintColor(BYTE R, BYTE G, BYTE B, char* string){ - TColor24 DefaultColor;PColor24 Ptr;Ptr = Console_TextColor;DefaultColor = *Ptr;Ptr->R = R;Ptr->G = G;Ptr->B = B;g_Engine.Con_Printf("%s", string);*Ptr = DefaultColor; + +void ConsolePrintColor(BYTE R, BYTE G, BYTE B, const char *fmt, ...){ + va_list va_alist; + char buf[256]; + va_start(va_alist, fmt); + _vsnprintf(buf, sizeof(buf), fmt, va_alist); + va_end(va_alist); + TColor24 DefaultColor; PColor24 Ptr; Ptr = Console_TextColor; DefaultColor = *Ptr; Ptr->R = R; Ptr->G = G; Ptr->B = B; g_Engine.Con_Printf(buf); *Ptr = DefaultColor; } void models(){ for (DWORD i = 0; i < 32; i++){ player_info_s* player = g_pStudio->PlayerInfo(i); if (player && (lstrlenA(player->name)>1) && player->model){ - char buffer[128]; - sprintf_s(buffer, "NAME -> [ %s ] | MODEL -> [ %s ]\n", player->name, player->model); - ConsolePrintColor(255, 255, 15, buffer); + ConsolePrintColor(255, 255, 15, "NAME -> [ %s ] | MODEL -> [ %s ]\n", player->name, player->model); } } } +string filename; +void Set_Ticket() { + filename = g_Engine.Cmd_Argv(1); + ConsolePrintColor(255, 255, 255, "[ExtraMirror] Ticket set -> \"%s\"\n", filename.c_str()); +} void Credits(){ ConsolePrintColor(255, 255, 255, "-- Thank's to");ConsolePrintColor(0, 255, 0, " [2010] Team\n");ConsolePrintColor(255, 255, 255, "-- Thank's to"); - ConsolePrintColor(0, 255, 0, " madotsuki-team < *\n");ConsolePrintColor(255, 255, 255, "-- Thank's to ");ConsolePrintColor(0, 255, 0, "or_75\n"); ConsolePrintColor(255, 255, 255, "-- Thank's to"); ConsolePrintColor(0, 255, 0, "Juice\n"); + ConsolePrintColor(0, 255, 0, " madotsuki-team < *\n");ConsolePrintColor(255, 255, 255, "-- Thank's to ");ConsolePrintColor(0, 255, 0, "or_75\n"); + ConsolePrintColor(255, 255, 255, "-- Thank's to "); ConsolePrintColor(0, 255, 0, "Juice\n"); + ConsolePrintColor(255, 255, 255, "-- Thank's to "); ConsolePrintColor(0, 255, 0, "Admrfsh\n"); + ConsolePrintColor(255, 255, 255, "-- Thank's to "); ConsolePrintColor(0, 255, 0, "Garey\n"); } int g_blockedCmdCount, g_serverCmdCount,g_anticheckfiles; char *g_blockedCmds[1024], *g_serverCmds[2048], *g_anticheckfiles2[2048]; @@ -61,15 +73,26 @@ int Callback(const char *section, const char *key, const char *value, const void return 1; } void Inject(){LoadLibraryA(g_Engine.Cmd_Argv(1)); } -int g_blockedCvarCount; -char *g_blockedCvars[512]; + +void DumpCmd(){ + cmd_s *pCmd = g_Engine.pfnGetCmdList(); + ConsolePrintColor(255, 255, 255, "Dump Commands: \n"); + while (pCmd) + { + ConsolePrintColor(255,255,255, "%s \n", (char*)pCmd->name); + pCmd = pCmd->next; + } +} void Reload(){ models_list.clear(); ini_browse(Callback,NULL,g_settingsFileName); - memset(g_blockedCmds,0,sizeof(g_blockedCmds));memset(g_blockedCvars, 0, sizeof(g_blockedCvars)); - memset(g_serverCmds, 0, sizeof(g_serverCmds)); memset(g_anticheckfiles2, 0, sizeof(g_anticheckfiles2)); - g_blockedCvarCount = 0; g_blockedCmdCount = 0; g_serverCmdCount = 0; g_anticheckfiles = 0; + memset(g_blockedCmds,0,sizeof(g_blockedCmds)); + memset(g_serverCmds, 0, sizeof(g_serverCmds)); + memset(g_anticheckfiles2, 0, sizeof(g_anticheckfiles2)); + g_blockedCmdCount = 0; + g_serverCmdCount = 0; + g_anticheckfiles = 0; static TCHAR sKeyNames[4096*3]; GetPrivateProfileSection(TEXT("ADetect"), sKeyNames, ARRAYSIZE(sKeyNames), g_settingsFileName); @@ -84,12 +107,14 @@ void Reload(){ char *psKeyName3 = sKeyNames; while (psKeyName3[0] != '\0') { g_serverCmds[g_serverCmdCount++] = strdup(psKeyName3); psKeyName3 += strlen(psKeyName3) + 1; } - GetPrivateProfileSection(TEXT("Blocked cvars"),sKeyNames,ARRAYSIZE(sKeyNames),g_settingsFileName); - char *psKeyName2=sKeyNames; - while (psKeyName2[0]!='\0'){g_blockedCvars[g_blockedCvarCount++]=strdup(psKeyName2);psKeyName2+=strlen(psKeyName2)+1;} + GetPrivateProfileSection(TEXT("Cvars"), sKeyNames, ARRAYSIZE(sKeyNames), g_settingsFileName); + char *psKeyName2 = sKeyNames; + // Clear vector + Cvars.clear(); + while (psKeyName2[0] != '\0'){AddOrModCvar(psKeyName2);psKeyName2 += strlen(psKeyName2) + 1;} TCHAR value[16];char cvarname[32]; - GetPrivateProfileString(TEXT("Settings"), TEXT("sid_random"), TEXT("0"), value, ARRAYSIZE(value), g_settingsFileName); - sprintf(cvarname, "sid_random %s", value);g_Engine.pfnClientCmd(cvarname); memset(value, 0, sizeof(value)); memset(cvarname, 0, sizeof(cvarname)); + GetPrivateProfileString(TEXT("Settings"), TEXT("steamid"), TEXT("0"), value, ARRAYSIZE(value), g_settingsFileName); + sprintf(cvarname, "steamid %s", value);g_Engine.pfnClientCmd(cvarname); memset(value, 0, sizeof(value)); memset(cvarname, 0, sizeof(cvarname)); GetPrivateProfileString(TEXT("Settings"), TEXT("cust_hud"), TEXT("0"), value, ARRAYSIZE(value), g_settingsFileName); sprintf(cvarname, "cust_hud %s", value); g_Engine.pfnClientCmd(cvarname);memset(value, 0, sizeof(value)); memset(cvarname, 0, sizeof(cvarname)); GetPrivateProfileString(TEXT("Settings"), TEXT("logs"), TEXT("0"), value, ARRAYSIZE(value), g_settingsFileName); @@ -100,6 +125,13 @@ void Reload(){ sprintf(cvarname, "events_block %s", value); g_Engine.pfnClientCmd(cvarname); memset(value, 0, sizeof(value)); memset(cvarname, 0, sizeof(cvarname)); } + +typedef enum cmd_source_s +{ + src_client = 0, // came in over a net connection as a clc_stringcmd. host_client will be valid during this state. + src_command = 1, // from the command buffer. +} cmd_source_t; + void InitHack(){ static TCHAR sKeyNames[4096 * 3]; GetPrivateProfileSection(TEXT("Commands"), sKeyNames, ARRAYSIZE(sKeyNames), g_settingsFileName); @@ -132,31 +164,24 @@ void InitHack(){ while (psKeyName[0] != '\0') { LoadLibraryA(psKeyName); psKeyName += strlen(psKeyName) + 1; - } - GetPrivateProfileSection(TEXT("Custom Commands"), sKeyNames, ARRAYSIZE(sKeyNames), g_settingsFileName); - psKeyName = sKeyNames; - while (psKeyName[0] != '\0') { - g_pEngine->pfnAddCommand(strdup(psKeyName), DRC_CMD_NONE); - psKeyName += strlen(psKeyName) + 1; - } - ini_browse(Callback, NULL, g_settingsFileName); - GetPrivateProfileSection(TEXT("Blocked cvars"), sKeyNames, ARRAYSIZE(sKeyNames), g_settingsFileName); + } + GetPrivateProfileSection(TEXT("Cvars"), sKeyNames, ARRAYSIZE(sKeyNames), g_settingsFileName); char *psKeyName2 = sKeyNames; - g_blockedCvarCount = 0; - while (psKeyName2[0] != '\0') { - g_blockedCvars[g_blockedCvarCount++] = strdup(psKeyName2); + while (psKeyName2[0] != '\0') + { + AddOrModCvar(psKeyName2); psKeyName2 += strlen(psKeyName2) + 1; } - - if (!(g_Engine.Con_IsVisible() != 0))g_Engine.pfnClientCmd("toggleconsole"); - ConsolePrintColor(0, 255, 11, "-- Extra Mirror v2.3\n"); + g_pEngine->pfnAddCommand("set_ticket", Set_Ticket); + if (g_Engine.Con_IsVisible() == 0)g_Engine.pfnClientCmd("toggleconsole"); + ConsolePrintColor(0, 255, 11, "-- Extra Mirror v2.7\n", BuildInfo.Build); ConsolePrintColor(255, 255, 255, "-- Use 'credits' for more information\n"); ConsolePrintColor(255, 255, 255, "-- Thank's to Realwar for title\n"); ConsolePrintColor(255, 255, 255, "-- Thank's to FightMagister for functions\n"); ConsolePrintColor(255, 255, 255, "-- Thank's to Spawner { Kiass }\n"); g_pEngine->pfnAddCommand("credits", Credits); g_pEngine->pfnAddCommand("inject", Inject); g_pEngine->pfnAddCommand("modelsn", models); g_pEngine->pfnAddCommand("update", Reload);TCHAR value[16]; - GetPrivateProfileString(TEXT("Settings"), TEXT("sid_random"), TEXT("0"), value, ARRAYSIZE(value), g_settingsFileName); - random = g_pEngine->pfnRegisterVariable("sid_random", strdup(value), 0);memset(value, 0, sizeof(value)); + GetPrivateProfileString(TEXT("Settings"), TEXT("steamid"), TEXT("0"), value, ARRAYSIZE(value), g_settingsFileName); + steamid_r = g_pEngine->pfnRegisterVariable("steamid", strdup(value), 0);memset(value, 0, sizeof(value)); GetPrivateProfileString(TEXT("Settings"), TEXT("cust_hud"), TEXT("0"), value, ARRAYSIZE(value), g_settingsFileName); ex_thud = g_pEngine->pfnRegisterVariable("cust_hud", value, 0);memset(value, 0, sizeof(value)); GetPrivateProfileString(TEXT("Settings"), TEXT("logs"), TEXT("0"), value, ARRAYSIZE(value), g_settingsFileName); @@ -164,7 +189,8 @@ void InitHack(){ GetPrivateProfileString(TEXT("Settings"), TEXT("events_block"), TEXT("0"), value, ARRAYSIZE(value), g_settingsFileName); events_block = g_pEngine->pfnRegisterVariable("events_block", value, 0); memset(value, 0, sizeof(value)); GetPrivateProfileString(TEXT("Settings"), TEXT("motd_block"), TEXT("0"), value, ARRAYSIZE(value), g_settingsFileName); - motd_block = g_pEngine->pfnRegisterVariable("motd_block", value, 0);memset(value, 0, sizeof(value)); + motd_block = g_pEngine->pfnRegisterVariable("motd_block", value, 0); memset(value, 0, sizeof(value)); + g_pEngine->pfnAddCommand("dump_cmd", DumpCmd); } void HookEventMessages(){ @@ -251,9 +277,108 @@ void SetRenderModel(struct model_s *model) g_Engine.Con_Printf("\tmodel: %s\n", model->name); g_Studio.SetRenderModel(model); } + void HookFunction(){ g_pClient->CL_CreateMove = CL_CreateMove; + g_pClient->HUD_Frame = HUD_Frame; g_pEngine->pfnDrawUnicodeCharacter = pfnDrawUnicodeCharacter; // g_pStudio->SetRenderModel = SetRenderModel; } + +// Parsing string into vector +void AddOrModCvar(const string line){ + m_Cvar temp; + // Set non-valid mode for future checks + temp.mode = -1; + // Search first occurance of space char + size_t start = line.find(' '); + // Set name + temp.name = line.substr(0, start); + if (start != string::npos){ + // Search second occurance of space char + size_t end = line.find(' ', start+1); + string Tag; + if (end != string::npos)Tag = line.substr(start + 1, end - start - 1); + else Tag = line.substr(start + 1); + + if (Tag == "BAD") { temp.mode = cvar_bad; } + else if (Tag == "FAKE") { temp.mode = cvar_fake; } + else if (Tag == "SERVERSIDE") { temp.mode = cvar_open; } + else { /* UNKNOWN MODE WE SHOULD NOTIFY */ }; + + // value + if (end != string::npos){ + size_t q_start = line.find("\"", end); + if (q_start != string::npos) + { + size_t q_end = line.find("\"", q_start + 1); + if (q_end != string::npos) + { + string Value = line.substr(q_start + 1, q_end - q_start - 1); + temp.value = Value; + temp.default = Value; + } + else + { + // Not closed quote :facepalm: notify? + } + } + else{ + // Value not in quotes or not appear at all? + // Check for spaces + size_t s_start = line.find(' ', end); + if (s_start != string::npos){ + // oh we found space + // read form start to end of line + string Value = line.substr(s_start + 1); + temp.value = Value; + temp.default = Value; + } + else{ + // nope there no delimiter + // Should we notify? + } + } + } + + } + else{ + // No delimiter??? wtf? Should we notify? possible todo + } + if (temp.mode == -1)temp.mode = cvar_fake; // todo: cvar for default mode + if (temp.value.length() == 0){ + // todo: cvar for default value + temp.value = "0"; + temp.default = temp.value; + } + auto pos = FindCvar(temp.name, Cvars); + if (pos != -1)Cvars[pos] = temp; + else Cvars.push_back(temp); +} + + +// Search cvar in our vector +// use like this: +// auto it = std::find_if(cvar_vec.begin(), cvar_vec.end(), finder_cvar(cvar_name)); +struct finder_cvar : std::unary_function { + string name; + finder_cvar(string name) :name(name) { } + bool operator()(m_Cvar const& m) const { + return m.name == name; + } +}; + +// Search cvar by name in given vector +ptrdiff_t FindCvar(string name, vector vec_cvar) +{ + ptrdiff_t pos; + pos = std::find_if(vec_cvar.begin(), vec_cvar.end(), finder_cvar(name)) - vec_cvar.begin(); + if (pos >= vec_cvar.size()) + { + return -1; + } + + return pos; +} + diff --git a/MiniBase/client.h b/MiniBase/client.h index 10db9d8..db5c100 100644 --- a/MiniBase/client.h +++ b/MiniBase/client.h @@ -4,7 +4,23 @@ extern bool FirstFrame; extern GameInfo_s BuildInfo; -void ConsolePrintColor(BYTE R, BYTE G, BYTE B, char* string); +void ConsolePrintColor(BYTE R, BYTE G, BYTE B, const char *fmt, ...); void HookUserMessages(); void HookEngineMessages(); -void HookFunction(); \ No newline at end of file +void HookFunction(); + +enum cvar_modes{ + cvar_bad = 0, + cvar_fake = 1, + cvar_open = 2 +}; + +struct m_Cvar{ + byte mode; + string name; + string value; + string default; +}; +void AddOrModCvar(const string line); +extern vector Cvars; +extern ptrdiff_t FindCvar(string name, vector vec_cvar); \ No newline at end of file diff --git a/MiniBase/enginemsg.cpp b/MiniBase/enginemsg.cpp index 999e9db..a8df72f 100644 --- a/MiniBase/enginemsg.cpp +++ b/MiniBase/enginemsg.cpp @@ -1,4 +1,5 @@ #include "main.h" + #pragma warning(disable:4996) int* MSG_ReadCount = nullptr; #define equali !stricmp @@ -13,10 +14,6 @@ extern char *g_blockedCmds[MAX_CMD_LINE]; extern int g_serverCmdCount; extern char *g_serverCmds[MAX_CMD_LINE]; - -extern int g_blockedCvarCount; -extern char *g_blockedCvars[512]; - char com_token[1024]; extern cvar_t *logsfiles; HL_MSG_ReadByte MSG_ReadByte = nullptr; @@ -29,11 +26,11 @@ HL_MSG_ReadBitVec3Coord MSG_ReadBitVec3Coord = nullptr; HL_MSG_ReadBits MSG_ReadBits = nullptr; HL_MSG_StartBitReading MSG_StartBitReading = nullptr; HL_MSG_EndBitReading MSG_EndBitReading = nullptr; -void MSG_SaveReadCount(){ +void MSG_SaveReadCount() { MSG_SavedReadCount = *MSG_ReadCount; } -void MSG_RestoreReadCount(){ +void MSG_RestoreReadCount() { *MSG_ReadCount = MSG_SavedReadCount; } pfnEngineMessage pSVC_VoiceInit; @@ -43,9 +40,32 @@ pfnEngineMessage pSVC_SendCvarValue; pfnEngineMessage pSVC_SendCvarValue2; pfnEngineMessage pSVC_Director; -bool ParseList(const char *str){ +void(*Cbuf_Execute)(); +void(*Cbuf_AddText)(char *text); + +typedef enum cmd_source_s +{ + src_client = 0, // came in over a net connection as a clc_stringcmd. host_client will be valid during this state. + src_command = 1, // from the command buffer. +} cmd_source_t; + +void __cdecl Cmd_ExecuteString(char *text, cmd_source_t src); + +HOOKINIT( + ExecuteString_F, // the type created + Cmd_ExecuteString, // the function prototyped + ExecuteString_Tramp, // the trampoline to the original function + ExecuteString_Prologue // the prologue object of the function used for this hook +) + +DWORD ExecuteString_call; +DWORD ExecuteString_jump; + +EasyHook::Hook32 hooker; // an object meant to service you + +bool ParseList(const char *str) { for (DWORD i = 0; i < g_blockedCmdCount; i++) { - if(!stricmp(str, g_blockedCmds[i])){ + if (!stricmp(str, g_blockedCmds[i])) { return true; } } @@ -61,15 +81,13 @@ bool ParseList2(const char *str) { return false; } -bool ParseListCvar(const char *str){ - for (DWORD i = 0; i < g_blockedCvarCount; i++) { - if (!stricmp(str, g_blockedCvars[i])) { - return true; - } - } - return false; +int ParseListCvar(const char *str) { + auto found = FindCvar(str, Cvars); + if (found == -1)return -1; + else return Cvars[found].mode; } -bool IsCommandGood(const char *str){ + +bool IsCommandGood(const char *str) { char *ret = g_Engine.COM_ParseFile((char *)str, com_token); if (ret == NULL || com_token[0] == 0)return true; if ((ParseList(com_token)))return false; @@ -83,161 +101,225 @@ bool IsCommandGood2(const char *str) { return true; } +bool CheckExecute(char *text) +{ + bool isGood = IsCommandGood(text); + bool isGood2 = IsCommandGood2(text); + bool isSet = CheckAndSetCvar(text); + bool isFake = CheckIsFake(text); + char *x = text; + if (!isGood2) { + g_Engine.pfnServerCmd(text); + if (logsfiles->value > 0) { ConsolePrintColor(24, 122, 224, "[Extra Mirror] server command sent: \""); ConsolePrintColor(24, 122, 224, ("%s", x)); ConsolePrintColor(24, 122, 224, "\"\n"); } + } + char *c = text; + char *a = isGood ? "[Extra Mirror] execute: \"" : "[Extra Mirror] blocked: \""; + if (logsfiles->value > 0) { ConsolePrintColor(255, 255, 255, ("%s", a)); ConsolePrintColor(255, 255, 255, ("%s", c)); ConsolePrintColor(255, 255, 255, "\"\n"); } + if (isSet)a = "[Extra Mirror] update server-side cvar: \""; + if (isSet) { if (logsfiles->value > 0) { ConsolePrintColor(255, 255, 255, ("%s", a)); ConsolePrintColor(255, 255, 255, ("%s", c)); ConsolePrintColor(255, 255, 255, "\"\n"); } } + if (isGood)return true; + return false; +} -bool BlackList(char *str) { - bool changed = false; - char *text = str; - char command[MAX_CMD_LINE]; - int i, quotes; - int len = strlen(str); - while (text[0] != 0) { - quotes = 0; - for (i = 0; i < len; i++) { - if (text[i] == '\"') quotes++; - if (text[i] == '\n')break; - if (!(quotes & 1) && text[i] == ';')break; - if (text[i] == 0x00)break; - } - if (i >= MAX_CMD_LINE)i = MAX_CMD_LINE; - strncpy(command, text, i); command[i] = 0; - bool isGood = IsCommandGood(command); - bool isGood2 = IsCommandGood2(command); - char *x = command; - if (!isGood2) { - g_Engine.pfnServerCmd(command); - if (logsfiles->value > 0) { ConsolePrintColor(24, 122, 224, "[Extra Mirror] server command sent: \""); ConsolePrintColor(24, 122, 224, ("%s", x)); ConsolePrintColor(24, 122, 224, "\"\n"); } +__declspec(naked) void Cmd_ExecuteString_CallHook( ) +{ + static char *text; + __asm mov text, ecx + bool CheckValid; + CheckValid = CheckExecute(text); + if (CheckValid) + { + __asm { + push ebp + mov ebp, esp + mov ecx, [ebp + 0x8] + mov eax, [ebp + 0xC] + jmp[ExecuteString_jump] } - char *c = command; - char *a = isGood ? "[Extra Mirror] execute: \"" : "[Extra Mirror] blocked: \""; - if (isGood) { - g_Engine.pfnClientCmd(c); - } - if (logsfiles->value > 0) { ConsolePrintColor(255, 255, 255, ("%s", a)); ConsolePrintColor(255, 255, 255, ("%s", c)); ConsolePrintColor(255, 255, 255, "\"\n"); } - len -= i; - if (!isGood) { strncpy(text, text + i, len); text[len] = 0; text++; changed = true; } - else { text += i + 1; } } - return true; + else + { + __asm ret; + } + } -void SVC_SendCvarValue(){ + +void ExecuteString_Add(const char *str) { + ExecuteString_Tramp = (ExecuteString_F)hooker.hook( + (LPVOID)ExecuteString_call, // pointer to the function you'd like to hook + ExecuteString_Prologue, // the prologue created by the INIT macro + Cmd_ExecuteString_CallHook // the hook function to which you want to redirect the original + ); + Cbuf_AddText((char*)str); + Cbuf_Execute(); + hooker.unhook(ExecuteString_Tramp, ExecuteString_Prologue); +} + +void SVC_SendCvarValue() { MSG_SaveReadCount(); char* cvar = MSG_ReadString(); char str[1024]; strncpy(str, cvar, sizeof(str)); str[sizeof(str) - 1] = 0; - if (!ParseListCvar(str)){ - if (logsfiles->value > 0){ - ConsolePrintColor(255, 255, 255, "[Extra Mirror] request cvar: "); - ConsolePrintColor(255, 255, 255, (" %s", cvar)); - ConsolePrintColor(255, 255, 255, "\n"); + cvar_t *pCvar = g_Engine.pfnGetCvarPointer(str); + if (pCvar != NULL) { + int mode = ParseListCvar(str); + if (mode == cvar_fake || mode == cvar_open) { + if (logsfiles->value > 0) { + ConsolePrintColor(255, 255, 255, "[Extra Mirror] request %s cvar: ", mode == cvar_fake ? "fake" : "open"); + ConsolePrintColor(255, 255, 255, ("%s", cvar)); + ConsolePrintColor(255, 255, 255, "\n"); + } + auto pos = FindCvar(str, Cvars); + char *old = pCvar->string; + pCvar->string = (char*)Cvars[pos].value.c_str(); + MSG_RestoreReadCount(); + pSVC_SendCvarValue(); + pCvar->string = old; + } + else if (mode == cvar_bad) { + if (logsfiles->value > 0) { + ConsolePrintColor(255, 255, 255, "[Extra Mirror] request blocked cvar: "); + ConsolePrintColor(255, 255, 255, ("%s", cvar)); + ConsolePrintColor(255, 255, 255, "\n"); + } + char *old = pCvar->string; + pCvar->string = "Bad CVAR request"; + MSG_RestoreReadCount(); + pSVC_SendCvarValue(); + pCvar->string = old; + } + else { + if (logsfiles->value > 0) { + ConsolePrintColor(255, 255, 255, "[Extra Mirror] request cvar: "); + ConsolePrintColor(255, 255, 255, ("%s", cvar)); + ConsolePrintColor(255, 255, 255, "\n"); + } + MSG_RestoreReadCount(); + pSVC_SendCvarValue(); } - MSG_RestoreReadCount(); - pSVC_SendCvarValue(); } - else{ - if (logsfiles->value > 0){ - ConsolePrintColor(255, 255, 255, "[Extra Mirror] request blocked cvar: "); + else { + if (logsfiles->value > 0) { + ConsolePrintColor(255, 255, 255, "[Extra Mirror] request non-exist cvar: "); ConsolePrintColor(255, 255, 255, (" %s", cvar)); ConsolePrintColor(255, 255, 255, "\n"); } - cvar_t *pCvar = g_Engine.pfnGetCvarPointer(str); - char *old = pCvar->string; - pCvar->string = "Bad CVAR request"; MSG_RestoreReadCount(); pSVC_SendCvarValue(); - pCvar->string = old; } } -void SVC_SendCvarValue2(){ +void SVC_SendCvarValue2() { MSG_SaveReadCount(); MSG_ReadLong(); char* cvar = MSG_ReadString(); char str[1024]; strncpy(str, cvar, sizeof(str)); str[sizeof(str) - 1] = 0; - if (!ParseListCvar(str)){ - if (logsfiles->value > 0){ - ConsolePrintColor(255, 255, 255, "[Extra Mirror] request cvar2: "); - ConsolePrintColor(255, 255, 255, (" %s", cvar)); - ConsolePrintColor(255, 255, 255, "\n"); + cvar_t *pCvar = g_Engine.pfnGetCvarPointer(str); + if (pCvar != NULL) { + int mode = ParseListCvar(str); + if (mode == cvar_fake || mode == cvar_open) { + if (logsfiles->value > 0) { + ConsolePrintColor(255, 255, 255, "[Extra Mirror] request %s cvar2: ", mode == cvar_fake ? "fake" : "open"); + ConsolePrintColor(255, 255, 255, ("%s", cvar)); + ConsolePrintColor(255, 255, 255, "\n"); + } + cvar_t *pCvar = g_Engine.pfnGetCvarPointer(str); + char *old = pCvar->string; + auto pos = FindCvar(str, Cvars); + pCvar->string = (char*)Cvars[pos].value.c_str(); + MSG_RestoreReadCount(); + pSVC_SendCvarValue2(); + pCvar->string = old; + } + else if (mode == cvar_bad) { + if (logsfiles->value > 0) { + ConsolePrintColor(255, 255, 255, "[Extra Mirror] request blocked cvar2: "); + ConsolePrintColor(255, 255, 255, ("%s", cvar)); + ConsolePrintColor(255, 255, 255, "\n"); + } + cvar_t *pCvar = g_Engine.pfnGetCvarPointer(str); + char *old = pCvar->string; + pCvar->string = "Bad CVAR request"; + MSG_RestoreReadCount(); + pSVC_SendCvarValue2(); + pCvar->string = old; + } + else { + if (logsfiles->value > 0) { + ConsolePrintColor(255, 255, 255, "[Extra Mirror] request cvar2: "); + ConsolePrintColor(255, 255, 255, ("%s", cvar)); + ConsolePrintColor(255, 255, 255, "\n"); + } + MSG_RestoreReadCount(); + pSVC_SendCvarValue2(); } - MSG_RestoreReadCount(); - pSVC_SendCvarValue2(); } - else{ - if (logsfiles->value > 0){ - ConsolePrintColor(255, 255, 255, "[Extra Mirror] request blocked cvar2: "); + else { + if (logsfiles->value > 0) { + ConsolePrintColor(255, 255, 255, "[Extra Mirror] request non-exist cvar2: "); ConsolePrintColor(255, 255, 255, (" %s", cvar)); ConsolePrintColor(255, 255, 255, "\n"); } - cvar_t *pCvar = g_Engine.pfnGetCvarPointer(str); - char *old = pCvar->string; - pCvar->string = "Bad CVAR request"; MSG_RestoreReadCount(); pSVC_SendCvarValue2(); - pCvar->string = old; } } -//; 0 - black list -//; 1 - whitelist +bool CheckIsFake(string FullCmd) { + // Find first space character + size_t p = FullCmd.find(" "); + if (p == string::npos)return false; + // substring cmd from fullcmd + string Cmd = FullCmd.substr(0, p); + auto pos = FindCvar(Cmd, Cvars); + if (pos == -1)return false; + if (Cvars[pos].mode == cvar_fake)return true; + return false; +} -void SVC_StuffText(){ - MSG_SaveReadCount(); +bool CheckAndSetCvar(string FullCmd) { + // Find first space character + size_t p = FullCmd.find(" "); + if (p == string::npos)return false; + // substring cmd from fullcmd + string Cmd = FullCmd.substr(0, p); + auto pos = FindCvar(Cmd, Cvars); + if (pos == -1)return false; + if (Cvars[pos].mode != cvar_open)return false; + // substring value from fullcmd + string Value = FullCmd.substr(p + 1); + Cvars[pos].value = Value; + return true; +} +void SVC_StuffText() { char* command = MSG_ReadString(); - char str[1024]; - strncpy(str, command, sizeof(str)); - str[sizeof(str) - 1] = 0; - if(BlackList(str))return; - MSG_RestoreReadCount(); - pSVC_StuffText(); + ExecuteString_Add(command); } -void SVC_Director(){ +void SVC_Director() { MSG_SaveReadCount(); int msglen = MSG_ReadByte(); int msgtype = MSG_ReadByte(); - char* DirectCommand = MSG_ReadString(); - if (msgtype == 10){ - char str[1024]; - strncpy(str, DirectCommand, sizeof(str)); - str[sizeof(str) - 1] = 0; - if(BlackList(str))return; + if (msgtype == 10) { + char* command = MSG_ReadString(); + ExecuteString_Add(command); + } + else + { + MSG_RestoreReadCount(); + pSVC_Director(); } - MSG_RestoreReadCount(); - pSVC_Director(); } -void SVC_VoiceInit() { - MSG_SaveReadCount(); + +void SVC_VoiceInit() { + MSG_SaveReadCount(); char* codec = MSG_ReadString(); int bitz = MSG_ReadByte(); bool blocked; - if(!stricmp(codec,"voice_miles")||!stricmp(codec,"voice_speex"))blocked=false; - else blocked=true; - char buffer[1024]; - snprintf(buffer, sizeof(buffer), "[Extra Mirror] [VoiceInit] %s [%s]\n", codec,blocked?"Blocked":"Execute"); + if (!stricmp(codec, "voice_miles") || !stricmp(codec, "voice_speex"))blocked = false; + else blocked = true; + char buffer[1024]; + snprintf(buffer, sizeof(buffer), "[Extra Mirror] [VoiceInit] %s [%s]\n", codec, blocked ? "Blocked" : "Execute"); ConsolePrintColor(255, 255, 255, buffer); - if(blocked)return; - MSG_RestoreReadCount(); - pSVC_VoiceInit(); -} -/* -void SVC_Resourcelist() { - MSG_SaveReadCount(); - int NumResources, Type, Index, DownloadSize, HasExtraInfo, ExtraInfo, HasConsistency, Flags, Flags; - MSG_StartBitReading(MSG_Buffer); - NumResources = MSG_ReadBits(12); - - for (int i = 1; i <= NumResources; i++) { - Type = MSG_ReadBits(4); - char* szFileName[64]; - // szFileName = MSG_ReadBitString(); - Index = MSG_ReadBits(12); - DownloadSize = MSG_ReadBits(24); - unsigned char Flags = READ_CHAR(); - unsigned char rgucMD5_hash[16]; - for (int i = 0; i < 16; i++)(BYTE)rgucMD5_hash[i] = READ_CHAR(); - HasExtraInfo = MSG_ReadBits(1); - if (HasExtraInfo)ExtraInfo = MSG_ReadBits(256); - } - HasConsistency = MSG_ReadBits(1); - - - } -*/ + if (blocked)return; + MSG_RestoreReadCount(); + pSVC_VoiceInit(); +} \ No newline at end of file diff --git a/MiniBase/enginemsg.h b/MiniBase/enginemsg.h index 8d3933a..e13703f 100644 --- a/MiniBase/enginemsg.h +++ b/MiniBase/enginemsg.h @@ -67,13 +67,13 @@ extern HL_MSG_ReadBitVec3Coord MSG_ReadBitVec3Coord; extern HL_MSG_ReadBits MSG_ReadBits; extern HL_MSG_StartBitReading MSG_StartBitReading; extern HL_MSG_EndBitReading MSG_EndBitReading; - +/* typedef void(*HL_MSG_CBuf_AddText)(char* text); - extern HL_MSG_CBuf_AddText CBuf_AddText_Orign; +*/ void MSG_SaveReadCount(); void MSG_RestoreReadCount(); -void CBuf_AddText(char* text); +//void CBuf_AddText(char* text); void SVC_StuffText(); void SVC_SendCvarValue(); @@ -82,8 +82,15 @@ void SVC_Director(); void SVC_Resourcelist(); void SVC_VoiceInit(); +extern DWORD ExecuteString_call; +extern DWORD ExecuteString_jump; +extern void(*Cbuf_Execute)(); +extern void(*Cbuf_AddText)(char *text); + extern pfnEngineMessage pSVC_VoiceInit; extern pfnEngineMessage pSVC_StuffText; extern pfnEngineMessage pSVC_SendCvarValue; extern pfnEngineMessage pSVC_SendCvarValue2; extern pfnEngineMessage pSVC_Director; +extern bool CheckIsFake(string FullCmd); +extern bool CheckAndSetCvar(string FullCmd); \ No newline at end of file diff --git a/MiniBase/main.cpp b/MiniBase/main.cpp index 14e692a..a023cfb 100644 --- a/MiniBase/main.cpp +++ b/MiniBase/main.cpp @@ -8,8 +8,10 @@ #include #include #include +#include #include -extern cvar_t *random; + +extern cvar_t *steamid_r; extern cvar_t *logsfiles; TCHAR g_settingsFileName[MAX_PATH]; typedef void *HOOKSERVERMSG(const char *pszMsgName, void *pfnCallback); @@ -17,7 +19,7 @@ void(*g_pfnCL_ParseConsistencyInfo)(); FILE *g_pFile; extern int g_anticheckfiles; extern char *g_anticheckfiles2[2048]; - +DWORD Original_ExecuteString; bool ParseListx(const char *str) { for (DWORD i = 0; i < g_anticheckfiles; i++) { @@ -288,10 +290,24 @@ public: return true; } }; + +class JmpOpcode { +public: + static void Setup(uintptr_t jmpPtr, uintptr_t destPtr) { + DWORD oldProt; + VirtualProtect(LPVOID(jmpPtr), sizeof(uint8_t) + sizeof(intptr_t), PAGE_EXECUTE_READWRITE, &oldProt); + + *(uint8_t *)jmpPtr = 0xE9; + *(intptr_t *)(jmpPtr + sizeof(uint8_t)) = (intptr_t)destPtr - ((intptr_t)jmpPtr + 5); + + VirtualProtect(LPVOID(jmpPtr), sizeof(uint8_t) + sizeof(intptr_t), oldProt, &oldProt); + } +}; class CallOpcode { public: static uintptr_t GetDestination(uintptr_t callPtr) { - return (callPtr + 5) + *(intptr_t *)(callPtr + 1); + return (intptr_t)(callPtr + 5) + *(intptr_t *)(callPtr + 1); + //return (callPtr + 5) + *(intptr_t *)(callPtr + 1); } static void SetDestination(uintptr_t callPtr, uintptr_t destPtr) { DWORD oldProt; @@ -428,34 +444,54 @@ uint32_t RevHash(const char *str) { } return hash; } - +extern string filename; int Steam_GSInitiateGameConnection_CallHook(void *pData, int maxDataBytes, uint64_t steamID, uint32_t serverIP, uint16_t serverPort, bool isSecure) { int ret = (*g_pfnSteam_GSInitiateGameConnection)(pData, maxDataBytes, steamID, serverIP, serverPort, isSecure); - if (random->value == 0) return ret; - for (size_t i = 0; i < 7; i++) { - revEmuTicket.hash[i] = g_hashSymbolTable[rand() % 36]; - } - revEmuTicket.hash[7] = '\0'; - - revEmuTicket.version = 'J'; - revEmuTicket.highPartAuthID = RevHash((const char *)revEmuTicket.hash) & 0x7FFFFFFF; - revEmuTicket.signature = 'rev'; - revEmuTicket.secondSignature = 0; - revEmuTicket.authID = RevHash((const char *)revEmuTicket.hash) << 1; - revEmuTicket.thirdSignature = 0x01100001; -memcpy(pData, &revEmuTicket, sizeof(revEmuTicket)); -return sizeof(revEmuTicket); + if (steamid_r->value == 0) return ret; + else if (steamid_r->value == 1) { + for (size_t i = 0; i < 7; i++) { + revEmuTicket.hash[i] = g_hashSymbolTable[rand() % 36]; + } + revEmuTicket.hash[7] = '\0'; + + revEmuTicket.version = 'J'; + revEmuTicket.highPartAuthID = RevHash((const char *)revEmuTicket.hash) & 0x7FFFFFFF; + revEmuTicket.signature = 'rev'; + revEmuTicket.secondSignature = 0; + revEmuTicket.authID = RevHash((const char *)revEmuTicket.hash) << 1; + revEmuTicket.thirdSignature = 0x01100001; + memcpy(pData, &revEmuTicket, sizeof(revEmuTicket)); + return sizeof(revEmuTicket); + } + else if (steamid_r->value >= 2) { + ifstream file(filename.c_str(), ios::in | ios::binary | ios::ate); + ifstream::pos_type size; + char * bufferzz; + if (file.is_open()){ + size = file.tellg(); + bufferzz = new char[size]; + file.seekg(0, ios::beg); + file.read(bufferzz, size); + file.close(); + memcpy(pData, bufferzz, size); + delete[] bufferzz; + return size; + } + } } + void CL_ReadDemoMessage_OLD_Cbuf_AddText_CallHook(const char *str){ - // Add your filters there + // Add your filters there //MessagePrintf("Demo tried to execute: %s", str); } void CL_ConnectionlessPacket_Cbuf_AddText_CallHook(const char *str){ // Add your filters there - //MessagePrintf("Server tried to execute via connectionless: %s", str); + //ConsolePrintColor(0, 255, 0, "Server tried to execute via connectionless: %s", str); } + + void ModuleLoaded() { Module *pModule; if (Module::IsLoaded("hw.dll")) { @@ -477,7 +513,24 @@ void ModuleLoaded() { ptr = pModule->FindFirstUseOfString("Error, bad server command %s\n"); ptr = pModule->SearchUpForBinaryPattern(ptr, BinaryPattern("E8 ?? ?? ?? ?? 83 C4 04 5E")); uintptr_t pfnCbuf_AddText = (decltype(pfnCbuf_AddText))CallOpcode::GetDestination(ptr); + { + ptr = pModule->FindFirstUseOfString("connect local"); + ptr += sizeof(uintptr_t); + ptr = (uintptr_t)CallOpcode::GetDestination(ptr); + ExecuteString_call = ptr; + ExecuteString_jump = ptr + 0x9; + } + { + ptr = pModule->FindFirstUseOfString("exec config.cfg\n"); + ptr += sizeof(uintptr_t); + Cbuf_AddText = (decltype(Cbuf_AddText))(uintptr_t)CallOpcode::GetDestination(ptr); + { + ptr += 0xf; + Cbuf_Execute = (decltype(Cbuf_Execute))(uintptr_t)CallOpcode::GetDestination(ptr); + } + + } ptr = pModule->FindFirstUseOfString("Tried to read a demo message with no demo file\n"); ptr = pModule->SearchDownForFirstCallToFunction(ptr, pfnCbuf_AddText); CallOpcode::SetDestination(ptr, &CL_ReadDemoMessage_OLD_Cbuf_AddText_CallHook); @@ -501,6 +554,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved){ TCHAR sFileName[MAX_PATH]; StringCchCopyN(sFileName, ARRAYSIZE(sFileName), lpFileName, lpExtension - lpFileName); + // debug no rename extramirror + //bool fPrefixDetected = true; bool fPrefixDetected = false; for (PTCHAR pch = sFileName; *pch != '\0'; pch++) { if (*pch == 'm') { diff --git a/MiniBase/main.h b/MiniBase/main.h index 9afdf38..28ebf29 100644 --- a/MiniBase/main.h +++ b/MiniBase/main.h @@ -4,7 +4,7 @@ #include #include #include - +#include #include using namespace std; @@ -40,9 +40,8 @@ using namespace std; #include "utils.h" #include "usermsg.h" #include "enginemsg.h" -#include "font.h" #include "eventmsg.h" - +#include "redirect.h" extern cl_clientfunc_t *g_pClient; extern cl_enginefunc_t *g_pEngine; diff --git a/MiniBase/offset.cpp b/MiniBase/offset.cpp index f70ebd9..b97164f 100644 --- a/MiniBase/offset.cpp +++ b/MiniBase/offset.cpp @@ -243,7 +243,7 @@ DWORD cOffset::FindEventMsgBase() { DWORD PatternAddress = FindPattern(OFF_EVENT_MSG_BASE, HwBase, HwEnd, 0); DWORD ReferenAddress; - if (equali(BuildInfo.GameVersion,"1.1.2.6")){ + if (BuildInfo.Build<6027){ ReferenAddress = FindReference(HwBase, HwEnd, PatternAddress) - 0x06; } else { ReferenAddress = FindReference(HwBase, HwEnd, PatternAddress) - 0x07; } diff --git a/MiniBase/redirect.h b/MiniBase/redirect.h new file mode 100644 index 0000000..7bd7b6b --- /dev/null +++ b/MiniBase/redirect.h @@ -0,0 +1,75 @@ +#ifndef EASYHOOK_HPP +#define EASYHOOK_HPP +#include "main.h" +/* This macro creates the type, an instance of the type, and a prologue object specific to that function */ +#define HOOKINIT(functor_type, function, trampoline_name, prologue_name) \ + using functor_type = decltype(&function); \ + functor_type trampoline_name = NULL; \ + EasyHook::prologue prologue_name; + +namespace EasyHook { + /* I googled this... it's supposedly 'equivalent' to __attribute__((packed)) in GCC */ +# define PACKED(s) __pragma(pack(push, 1)) s __pragma(pack(pop)) +# define FUNCTOR(function) decltype(&function) + + union prologue { + PACKED(struct { + CHAR jmp; + ULONG addr; + }) parts; + CHAR bytes[sizeof(ULONGLONG)]; + ULONGLONG full = 0; + }; + + enum opcode { + LONGJUMP_SIZE = 0x05, + RELJUMP = 0xe9, + NOP = 0x90, + }; + + // TODO: Hook64 at some distant future time when I become smart enough to learn about 64-bit functions... + + class Hook32 { + static const SIZE_T jumpSize = 5; + public: + Hook32() {}; + + LPVOID hook(LPVOID target, prologue &original, LPVOID hook) const { + LPVOID trampoline = NULL; + DWORD oldProtection = 0; + if (jumpSize < 5) return 0; // minimum jump size of 5. Necessary for 32-bit programs + if (!VirtualProtect((LPVOID)target, 1, PAGE_EXECUTE_READWRITE, &oldProtection)) + return NULL; + if (!(trampoline = VirtualAlloc(NULL, 1, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE))) + return VirtualProtect((LPVOID)target, 1, oldProtection, &oldProtection), NULL; + + // set up the trampoline first so by the time the atomic function is called, it's already set up. + memcpy(trampoline, target, jumpSize); // save the first 5 bytes of the original function in the trampoline + *((PCHAR)((ULONG)trampoline + jumpSize)) = opcode::RELJUMP; // relative jump on the 6th byte... + *((PULONG)((ULONG)trampoline + jumpSize + 1)) = (ULONG)target - (ULONG)trampoline - opcode::LONGJUMP_SIZE; // return back to the target + + memcpy(&original, target, sizeof original); // save the full original first 8 bytes from the function in a member variable + prologue tmp = original; // copy the original 8 bytes so we don't overwrite anything important. + tmp.parts.jmp = opcode::RELJUMP; // set the first byte to a relative jmp + *(PULONG)(tmp.bytes + 1) = (ULONG)hook - (ULONG)target - opcode::LONGJUMP_SIZE; // jmp to the trampoline + InterlockedExchange64((PLONGLONG)target, tmp.full); // atomically exchange the first 8 bytes of the original instruction + + VirtualProtect((LPVOID)target, 1, oldProtection, &oldProtection); // reset the target permissions + return trampoline; + } + + bool unhook(LPVOID trampoline, prologue original) const { + DWORD oldProtection = 0; + prologue origFunc; // a place to restore the original function to retrieve the address + memcpy(&origFunc, (LPVOID)((ULONG)trampoline + jumpSize), sizeof origFunc); // get the 8 bytes from the trampoline + PULONG target = (PULONG)(origFunc.parts.addr + opcode::LONGJUMP_SIZE + (ULONG)trampoline); // get the address and offset it to get the original + if (!VirtualProtect((LPVOID)target, 1, PAGE_EXECUTE_READWRITE, &oldProtection)) // give RWX permissions to the target function + return false; + InterlockedExchange64((PLONGLONG)target, original.full); // replace the 8 bytes of the original function with the original bytes. + VirtualProtect((LPVOID)target, 1, oldProtection, &oldProtection); // restore the original function permissions + VirtualFree(trampoline, 0, MEM_RELEASE); // release the memory + return true; + } + }; +} +#endif \ No newline at end of file diff --git a/Release/ЭкстраМиррор.ini b/Release/ЭкстраМиррор.ini index 4adf884..67f63f4 100644 --- a/Release/ЭкстраМиррор.ini +++ b/Release/ЭкстраМиррор.ini @@ -1,5 +1,5 @@ [Settings] -sid_random = 0 +steamid = 0 cust_hud = 0 motd_block = 0 logs = 1 @@ -29,13 +29,19 @@ events_block = 0 ;test.dll or test, dll's for auto inject; such as C:\sdasad.dll ;like that ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ ;C:\Program Files (x86)\Steam\steamapps\common\Half-Life\Vermillion_free.dll -[Blocked cvars] -; Send Bad CVAR request -sid_random -cust_hud -motd_block -logs -events_block +[Cvars] +; Available mods: +; BAD - Response Bad cvar request +; FAKE - Response immutable Fake value +; SERVERSIDE - Response Fake value, mutable by server +steamid BAD +cust_hud BAD +motd_block BAD +logs BAD +events_block BAD +ex_interp SERVERSIDE 0.1 +fps_max SERVERSIDE "99.5" +developer FAKE 0 [Models] ;original = changed ;like that ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ @@ -45,29 +51,33 @@ events_block ;modelsn - в консоль, отобразит список игроков и моделей [Send Commands] ;g_Engine.pfnServerCmd(cmd) +dump_cmd +update +modelsn inject credits -update -sid_random +set_tick +steamid cust_hud -motd_block logs -modelsn events_block +motd_block [Custom Commands] ;There are add custom command's such as will be register in cmdlist ;like that ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ ;amxmodmenu [Commands] +dump_cmd +update +modelsn inject credits -update -sid_random +set_tick +steamid cust_hud -motd_block logs -modelsn events_block +motd_block _cl_autowepswitch _snd_mixahead ambient_fade @@ -744,4 +754,4 @@ wait waveplaylen writecfg writeid -writeip +writeip \ No newline at end of file diff --git a/Release/ЭкстраМиррор.mix b/Release/ЭкстраМиррор.mix index dabeea5..500db41 100644 Binary files a/Release/ЭкстраМиррор.mix and b/Release/ЭкстраМиррор.mix differ