mirror of
https://github.com/r4sas/ExtraMirror
synced 2025-02-03 18:35:05 +00:00
Небольшая реконструкция
This commit is contained in:
parent
b42c64eb7b
commit
484c827a3b
@ -30,7 +30,7 @@
|
|||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140_xp</PlatformToolset>
|
<PlatformToolset>v140_xp</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
@ -70,6 +70,7 @@
|
|||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<LinkIncremental>true</LinkIncremental>
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<TargetExt>.mix</TargetExt>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<LinkIncremental>true</LinkIncremental>
|
<LinkIncremental>true</LinkIncremental>
|
||||||
@ -190,6 +191,5 @@
|
|||||||
<ClInclude Include="ValveSDK\misc\parsemsg.h" />
|
<ClInclude Include="ValveSDK\misc\parsemsg.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets" />
|
||||||
</ImportGroup>
|
|
||||||
</Project>
|
</Project>
|
@ -18,9 +18,11 @@ cvar_t *random;
|
|||||||
map<string, string> g_modelsHashMap;
|
map<string, string> g_modelsHashMap;
|
||||||
cvar_t *logsfiles;
|
cvar_t *logsfiles;
|
||||||
cvar_t *events_block;
|
cvar_t *events_block;
|
||||||
|
|
||||||
cvar_t *ex_thud;
|
cvar_t *ex_thud;
|
||||||
cvar_t *motd_block;
|
cvar_t *motd_block;
|
||||||
|
|
||||||
|
vector<m_Cvar> Cvars;
|
||||||
|
|
||||||
void HookEngineMessages(){
|
void HookEngineMessages(){
|
||||||
pEngineMsgBase = (PEngineMsg)offset.FindSVCMessages();
|
pEngineMsgBase = (PEngineMsg)offset.FindSVCMessages();
|
||||||
pSVC_StuffText = HookEngineMsg("svc_stufftext", SVC_StuffText);
|
pSVC_StuffText = HookEngineMsg("svc_stufftext", SVC_StuffText);
|
||||||
@ -31,8 +33,14 @@ void HookEngineMessages(){
|
|||||||
// pSVC_Resourcelist = HookEngineMsg("svc_resourcelist", SVC_Resourcelist);
|
// 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(){
|
void models(){
|
||||||
@ -47,7 +55,10 @@ void models(){
|
|||||||
}
|
}
|
||||||
void Credits(){
|
void Credits(){
|
||||||
ConsolePrintColor(255, 255, 255, "-- Thank's to");ConsolePrintColor(0, 255, 0, " [2010] Team\n");ConsolePrintColor(255, 255, 255, "-- Thank's to");
|
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;
|
int g_blockedCmdCount, g_serverCmdCount,g_anticheckfiles;
|
||||||
char *g_blockedCmds[1024], *g_serverCmds[2048], *g_anticheckfiles2[2048];
|
char *g_blockedCmds[1024], *g_serverCmds[2048], *g_anticheckfiles2[2048];
|
||||||
@ -61,15 +72,26 @@ int Callback(const char *section, const char *key, const char *value, const void
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
void Inject(){LoadLibraryA(g_Engine.Cmd_Argv(1)); }
|
void Inject(){LoadLibraryA(g_Engine.Cmd_Argv(1)); }
|
||||||
int g_blockedCvarCount;
|
/*int g_blockedCvarCount;
|
||||||
char *g_blockedCvars[512];
|
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(){
|
void Reload(){
|
||||||
models_list.clear();
|
models_list.clear();
|
||||||
ini_browse(Callback,NULL,g_settingsFileName);
|
ini_browse(Callback,NULL,g_settingsFileName);
|
||||||
memset(g_blockedCmds,0,sizeof(g_blockedCmds));memset(g_blockedCvars, 0, sizeof(g_blockedCvars));
|
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));
|
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;
|
g_blockedCmdCount = 0; g_serverCmdCount = 0; g_anticheckfiles = 0;
|
||||||
static TCHAR sKeyNames[4096*3];
|
static TCHAR sKeyNames[4096*3];
|
||||||
|
|
||||||
GetPrivateProfileSection(TEXT("ADetect"), sKeyNames, ARRAYSIZE(sKeyNames), g_settingsFileName);
|
GetPrivateProfileSection(TEXT("ADetect"), sKeyNames, ARRAYSIZE(sKeyNames), g_settingsFileName);
|
||||||
@ -84,9 +106,17 @@ void Reload(){
|
|||||||
char *psKeyName3 = sKeyNames;
|
char *psKeyName3 = sKeyNames;
|
||||||
while (psKeyName3[0] != '\0') { g_serverCmds[g_serverCmdCount++] = strdup(psKeyName3); psKeyName3 += strlen(psKeyName3) + 1; }
|
while (psKeyName3[0] != '\0') { g_serverCmds[g_serverCmdCount++] = strdup(psKeyName3); psKeyName3 += strlen(psKeyName3) + 1; }
|
||||||
|
|
||||||
GetPrivateProfileSection(TEXT("Blocked cvars"),sKeyNames,ARRAYSIZE(sKeyNames),g_settingsFileName);
|
/*GetPrivateProfileSection(TEXT("Blocked cvars"),sKeyNames,ARRAYSIZE(sKeyNames),g_settingsFileName);
|
||||||
char *psKeyName2=sKeyNames;
|
char *psKeyName2=sKeyNames;
|
||||||
while (psKeyName2[0]!='\0'){g_blockedCvars[g_blockedCvarCount++]=strdup(psKeyName2);psKeyName2+=strlen(psKeyName2)+1;}
|
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];
|
TCHAR value[16];char cvarname[32];
|
||||||
GetPrivateProfileString(TEXT("Settings"), TEXT("sid_random"), TEXT("0"), value, ARRAYSIZE(value), g_settingsFileName);
|
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));
|
sprintf(cvarname, "sid_random %s", value);g_Engine.pfnClientCmd(cvarname); memset(value, 0, sizeof(value)); memset(cvarname, 0, sizeof(cvarname));
|
||||||
@ -100,6 +130,13 @@ void Reload(){
|
|||||||
sprintf(cvarname, "events_block %s", value); g_Engine.pfnClientCmd(cvarname); memset(value, 0, sizeof(value)); memset(cvarname, 0, sizeof(cvarname));
|
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(){
|
void InitHack(){
|
||||||
static TCHAR sKeyNames[4096 * 3];
|
static TCHAR sKeyNames[4096 * 3];
|
||||||
GetPrivateProfileSection(TEXT("Commands"), sKeyNames, ARRAYSIZE(sKeyNames), g_settingsFileName);
|
GetPrivateProfileSection(TEXT("Commands"), sKeyNames, ARRAYSIZE(sKeyNames), g_settingsFileName);
|
||||||
@ -132,24 +169,16 @@ void InitHack(){
|
|||||||
while (psKeyName[0] != '\0') {
|
while (psKeyName[0] != '\0') {
|
||||||
LoadLibraryA(psKeyName);
|
LoadLibraryA(psKeyName);
|
||||||
psKeyName += strlen(psKeyName) + 1;
|
psKeyName += strlen(psKeyName) + 1;
|
||||||
}
|
}
|
||||||
GetPrivateProfileSection(TEXT("Custom Commands"), sKeyNames, ARRAYSIZE(sKeyNames), g_settingsFileName);
|
GetPrivateProfileSection(TEXT("Cvars"), 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);
|
|
||||||
char *psKeyName2 = sKeyNames;
|
char *psKeyName2 = sKeyNames;
|
||||||
g_blockedCvarCount = 0;
|
while (psKeyName2[0] != '\0')
|
||||||
while (psKeyName2[0] != '\0') {
|
{
|
||||||
g_blockedCvars[g_blockedCvarCount++] = strdup(psKeyName2);
|
AddOrModCvar(psKeyName2);
|
||||||
psKeyName2 += strlen(psKeyName2) + 1;
|
psKeyName2 += strlen(psKeyName2) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(g_Engine.Con_IsVisible() != 0))g_Engine.pfnClientCmd("toggleconsole");
|
if (!(g_Engine.Con_IsVisible() != 0))g_Engine.pfnClientCmd("toggleconsole");
|
||||||
ConsolePrintColor(0, 255, 11, "-- Extra Mirror v2.3\n");
|
ConsolePrintColor(0, 255, 11, "-- Extra Mirror v2.6\n");
|
||||||
ConsolePrintColor(255, 255, 255, "-- Use 'credits' for more information\n");
|
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 Realwar for title\n");
|
||||||
ConsolePrintColor(255, 255, 255, "-- Thank's to FightMagister for functions\n");
|
ConsolePrintColor(255, 255, 255, "-- Thank's to FightMagister for functions\n");
|
||||||
@ -164,7 +193,8 @@ void InitHack(){
|
|||||||
GetPrivateProfileString(TEXT("Settings"), TEXT("events_block"), TEXT("0"), value, ARRAYSIZE(value), g_settingsFileName);
|
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));
|
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);
|
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(){
|
void HookEventMessages(){
|
||||||
@ -257,3 +287,100 @@ void HookFunction(){
|
|||||||
g_pEngine->pfnDrawUnicodeCharacter = pfnDrawUnicodeCharacter;
|
g_pEngine->pfnDrawUnicodeCharacter = pfnDrawUnicodeCharacter;
|
||||||
// g_pStudio->SetRenderModel = SetRenderModel;
|
// 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<m_Cvar, bool> {
|
||||||
|
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<m_Cvar> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,23 @@
|
|||||||
|
|
||||||
extern bool FirstFrame;
|
extern bool FirstFrame;
|
||||||
extern GameInfo_s BuildInfo;
|
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 HookUserMessages();
|
||||||
void HookEngineMessages();
|
void HookEngineMessages();
|
||||||
void HookFunction();
|
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<m_Cvar> Cvars;
|
||||||
|
extern ptrdiff_t FindCvar(string name, vector<m_Cvar> vec_cvar);
|
@ -1,4 +1,5 @@
|
|||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
#pragma warning(disable:4996)
|
#pragma warning(disable:4996)
|
||||||
int* MSG_ReadCount = nullptr;
|
int* MSG_ReadCount = nullptr;
|
||||||
#define equali !stricmp
|
#define equali !stricmp
|
||||||
@ -13,10 +14,6 @@ extern char *g_blockedCmds[MAX_CMD_LINE];
|
|||||||
|
|
||||||
extern int g_serverCmdCount;
|
extern int g_serverCmdCount;
|
||||||
extern char *g_serverCmds[MAX_CMD_LINE];
|
extern char *g_serverCmds[MAX_CMD_LINE];
|
||||||
|
|
||||||
extern int g_blockedCvarCount;
|
|
||||||
extern char *g_blockedCvars[512];
|
|
||||||
|
|
||||||
char com_token[1024];
|
char com_token[1024];
|
||||||
extern cvar_t *logsfiles;
|
extern cvar_t *logsfiles;
|
||||||
HL_MSG_ReadByte MSG_ReadByte = nullptr;
|
HL_MSG_ReadByte MSG_ReadByte = nullptr;
|
||||||
@ -29,11 +26,11 @@ HL_MSG_ReadBitVec3Coord MSG_ReadBitVec3Coord = nullptr;
|
|||||||
HL_MSG_ReadBits MSG_ReadBits = nullptr;
|
HL_MSG_ReadBits MSG_ReadBits = nullptr;
|
||||||
HL_MSG_StartBitReading MSG_StartBitReading = nullptr;
|
HL_MSG_StartBitReading MSG_StartBitReading = nullptr;
|
||||||
HL_MSG_EndBitReading MSG_EndBitReading = nullptr;
|
HL_MSG_EndBitReading MSG_EndBitReading = nullptr;
|
||||||
void MSG_SaveReadCount(){
|
void MSG_SaveReadCount() {
|
||||||
MSG_SavedReadCount = *MSG_ReadCount;
|
MSG_SavedReadCount = *MSG_ReadCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MSG_RestoreReadCount(){
|
void MSG_RestoreReadCount() {
|
||||||
*MSG_ReadCount = MSG_SavedReadCount;
|
*MSG_ReadCount = MSG_SavedReadCount;
|
||||||
}
|
}
|
||||||
pfnEngineMessage pSVC_VoiceInit;
|
pfnEngineMessage pSVC_VoiceInit;
|
||||||
@ -43,9 +40,34 @@ pfnEngineMessage pSVC_SendCvarValue;
|
|||||||
pfnEngineMessage pSVC_SendCvarValue2;
|
pfnEngineMessage pSVC_SendCvarValue2;
|
||||||
pfnEngineMessage pSVC_Director;
|
pfnEngineMessage pSVC_Director;
|
||||||
|
|
||||||
bool ParseList(const char *str){
|
|
||||||
|
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 ExecuteString(char *text, cmd_source_t src);
|
||||||
|
|
||||||
|
HOOKINIT(
|
||||||
|
ExecuteString_F, // the type created
|
||||||
|
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;
|
||||||
|
DWORD Cbuf_Addtext_call;
|
||||||
|
DWORD Cbuf_Addtext_jump;
|
||||||
|
DWORD Cbuf_Execute_call;
|
||||||
|
DWORD Cbuf_Execute_jump;
|
||||||
|
|
||||||
|
EasyHook::Hook32 hooker; // an object meant to service you
|
||||||
|
|
||||||
|
bool ParseList(const char *str) {
|
||||||
for (DWORD i = 0; i < g_blockedCmdCount; i++) {
|
for (DWORD i = 0; i < g_blockedCmdCount; i++) {
|
||||||
if(!stricmp(str, g_blockedCmds[i])){
|
if (!stricmp(str, g_blockedCmds[i])) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -61,15 +83,13 @@ bool ParseList2(const char *str) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ParseListCvar(const char *str){
|
int ParseListCvar(const char *str) {
|
||||||
for (DWORD i = 0; i < g_blockedCvarCount; i++) {
|
auto found = FindCvar(str, Cvars);
|
||||||
if (!stricmp(str, g_blockedCvars[i])) {
|
if (found == -1)return -1;
|
||||||
return true;
|
else return Cvars[found].mode;
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
bool IsCommandGood(const char *str){
|
|
||||||
|
bool IsCommandGood(const char *str) {
|
||||||
char *ret = g_Engine.COM_ParseFile((char *)str, com_token);
|
char *ret = g_Engine.COM_ParseFile((char *)str, com_token);
|
||||||
if (ret == NULL || com_token[0] == 0)return true;
|
if (ret == NULL || com_token[0] == 0)return true;
|
||||||
if ((ParseList(com_token)))return false;
|
if ((ParseList(com_token)))return false;
|
||||||
@ -83,6 +103,127 @@ bool IsCommandGood2(const char *str) {
|
|||||||
return true;
|
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"); }
|
||||||
|
/*else*/if (isSet)a = "[Extra Mirror] update server-side cvar: \"";
|
||||||
|
|
||||||
|
if (isGood)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// experimental
|
||||||
|
__declspec(naked) void Cmd_ExecuteString_CallHook( )
|
||||||
|
{
|
||||||
|
static char *text;
|
||||||
|
__asm MOV text, ECX
|
||||||
|
bool Test;
|
||||||
|
Test = CheckExecute(text);
|
||||||
|
if (Test)
|
||||||
|
{
|
||||||
|
__asm PUSH EBP
|
||||||
|
__asm MOV EBP, ESP
|
||||||
|
__asm MOV ECX, [EBP + 0x8]
|
||||||
|
__asm MOV EAX, [EBP + 0xC]
|
||||||
|
__asm JMP[ExecuteString_jump]
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__asm ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
}/*
|
||||||
|
__declspec(naked) void Cmd_ExecuteString_CallHook()
|
||||||
|
{
|
||||||
|
char *text;
|
||||||
|
cmd_source_t src;
|
||||||
|
__asm {
|
||||||
|
PUSH EBP
|
||||||
|
MOV EBP, ESP
|
||||||
|
MOV ECX, [EBP + 0x8]
|
||||||
|
MOV EAX, [EBP + 0xC]
|
||||||
|
PUSH EAX
|
||||||
|
PUSH ECX
|
||||||
|
MOV text, ECX
|
||||||
|
MOV src, EAX
|
||||||
|
POP ECX
|
||||||
|
POP EAX
|
||||||
|
POP EBP
|
||||||
|
}
|
||||||
|
__asm {
|
||||||
|
PUSH EBP
|
||||||
|
MOV EBP, ESP
|
||||||
|
MOV ECX, [EBP + 0x8]
|
||||||
|
MOV EAX, [EBP + 0xC]
|
||||||
|
jmp[ExecuteString_jump]
|
||||||
|
}
|
||||||
|
ConsolePrintColor(0, 255, 255, "%s", text);
|
||||||
|
hooker.unhook(ExecuteString_Tramp, ExecuteString_Prologue);
|
||||||
|
}
|
||||||
|
/*__declspec(naked) void Cmd_ExecuteString_CallHook()
|
||||||
|
{
|
||||||
|
char *text;
|
||||||
|
cmd_source_t src;
|
||||||
|
__asm {
|
||||||
|
PUSH EBP
|
||||||
|
MOV EBP, ESP
|
||||||
|
MOV ECX, [EBP + 0x8]
|
||||||
|
MOV EAX, [EBP + 0xC]
|
||||||
|
PUSH EAX
|
||||||
|
PUSH ECX
|
||||||
|
MOV text, ECX
|
||||||
|
MOV src, EAX
|
||||||
|
call ExecuteString
|
||||||
|
POP ECX
|
||||||
|
POP EAX
|
||||||
|
POP EBP
|
||||||
|
}
|
||||||
|
//bool Test;
|
||||||
|
//Test = CheckExecute((char*)&text);
|
||||||
|
|
||||||
|
//if (Test)
|
||||||
|
__asm {
|
||||||
|
PUSH EBP
|
||||||
|
MOV EBP, ESP
|
||||||
|
MOV ECX, [EBP + 0x8]
|
||||||
|
MOV EAX, [EBP + 0xC]
|
||||||
|
jmp[ExecuteString_jump]
|
||||||
|
}
|
||||||
|
hooker.unhook(ExecuteString_Tramp, ExecuteString_Prologue);
|
||||||
|
}*/
|
||||||
|
/*
|
||||||
|
void __cdecl ExecuteString(char *text, cmd_source_t src)
|
||||||
|
{
|
||||||
|
if (FirstFrame)
|
||||||
|
ConsolePrintColor(0, 255, 0, "%s %d \n", text, src);
|
||||||
|
|
||||||
|
//MessageBox(NULL, text, NULL, MB_OK);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
void ExecuteString_Test(const char *str, pfnEngineMessage Func) {
|
||||||
|
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_CallHook_Ext((char*)str);
|
||||||
|
Cbuf_Execute_CallHook_Ext();
|
||||||
|
hooker.unhook(ExecuteString_Tramp, ExecuteString_Prologue);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool BlackList(char *str) {
|
bool BlackList(char *str) {
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
@ -96,12 +237,14 @@ bool BlackList(char *str) {
|
|||||||
if (text[i] == '\"') quotes++;
|
if (text[i] == '\"') quotes++;
|
||||||
if (text[i] == '\n')break;
|
if (text[i] == '\n')break;
|
||||||
if (!(quotes & 1) && text[i] == ';')break;
|
if (!(quotes & 1) && text[i] == ';')break;
|
||||||
if (text[i] == 0x00)break;
|
if (text[i] == 0x00 || text[i] == ' ' )break;
|
||||||
}
|
}
|
||||||
if (i >= MAX_CMD_LINE)i = MAX_CMD_LINE;
|
if (i >= MAX_CMD_LINE)i = MAX_CMD_LINE;
|
||||||
strncpy(command, text, i); command[i] = 0;
|
strncpy(command, text, i); command[i] = 0;
|
||||||
bool isGood = IsCommandGood(command);
|
bool isGood = IsCommandGood(command);
|
||||||
bool isGood2 = IsCommandGood2(command);
|
bool isGood2 = IsCommandGood2(command);
|
||||||
|
bool isSet = CheckAndSetCvar(command);
|
||||||
|
bool isFake = CheckIsFake(command);
|
||||||
char *x = command;
|
char *x = command;
|
||||||
if (!isGood2) {
|
if (!isGood2) {
|
||||||
g_Engine.pfnServerCmd(command);
|
g_Engine.pfnServerCmd(command);
|
||||||
@ -109,135 +252,214 @@ bool BlackList(char *str) {
|
|||||||
}
|
}
|
||||||
char *c = command;
|
char *c = command;
|
||||||
char *a = isGood ? "[Extra Mirror] execute: \"" : "[Extra Mirror] blocked: \"";
|
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"); }
|
if (logsfiles->value > 0) { ConsolePrintColor(255, 255, 255, ("%s", a)); ConsolePrintColor(255, 255, 255, ("%s", c)); ConsolePrintColor(255, 255, 255, "\"\n"); }
|
||||||
|
// if (isFake) a = isGood ? "[Extra Mirror] set fake cvar: \"" : "[Extra Mirror] block fake cvar: \"";
|
||||||
|
/*else*/if (isSet)a = "[Extra Mirror] update server-side cvar: \"";
|
||||||
|
if (isGood)g_Engine.pfnClientCmd(c);
|
||||||
|
if (isSet) { if (logsfiles->value > 0) { ConsolePrintColor(255, 255, 255, ("%s", a)); ConsolePrintColor(255, 255, 255, ("%s", c)); ConsolePrintColor(255, 255, 255, "\"\n"); } }
|
||||||
len -= i;
|
len -= i;
|
||||||
if (!isGood) { strncpy(text, text + i, len); text[len] = 0; text++; changed = true; }
|
if (!isGood) { strncpy(text, text + i, len); text[len] = 0; text++; changed = true; }
|
||||||
else { text += i + 1; }
|
else { text += i + 1; }
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
void SVC_SendCvarValue(){
|
|
||||||
|
void SVC_SendCvarValue() {
|
||||||
MSG_SaveReadCount();
|
MSG_SaveReadCount();
|
||||||
char* cvar = MSG_ReadString();
|
char* cvar = MSG_ReadString();
|
||||||
char str[1024];
|
char str[1024];
|
||||||
strncpy(str, cvar, sizeof(str));
|
strncpy(str, cvar, sizeof(str));
|
||||||
str[sizeof(str) - 1] = 0;
|
str[sizeof(str) - 1] = 0;
|
||||||
if (!ParseListCvar(str)){
|
cvar_t *pCvar = g_Engine.pfnGetCvarPointer(str);
|
||||||
if (logsfiles->value > 0){
|
if (pCvar != NULL) {
|
||||||
ConsolePrintColor(255, 255, 255, "[Extra Mirror] request cvar: ");
|
int mode = ParseListCvar(str);
|
||||||
ConsolePrintColor(255, 255, 255, (" %s", cvar));
|
if (mode == cvar_fake || mode == cvar_open) {
|
||||||
ConsolePrintColor(255, 255, 255, "\n");
|
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{
|
else {
|
||||||
if (logsfiles->value > 0){
|
if (logsfiles->value > 0) {
|
||||||
ConsolePrintColor(255, 255, 255, "[Extra Mirror] request blocked cvar: ");
|
ConsolePrintColor(255, 255, 255, "[Extra Mirror] request non-exist cvar: ");
|
||||||
ConsolePrintColor(255, 255, 255, (" %s", cvar));
|
ConsolePrintColor(255, 255, 255, (" %s", cvar));
|
||||||
ConsolePrintColor(255, 255, 255, "\n");
|
ConsolePrintColor(255, 255, 255, "\n");
|
||||||
}
|
}
|
||||||
cvar_t *pCvar = g_Engine.pfnGetCvarPointer(str);
|
|
||||||
char *old = pCvar->string;
|
|
||||||
pCvar->string = "Bad CVAR request";
|
|
||||||
MSG_RestoreReadCount();
|
MSG_RestoreReadCount();
|
||||||
pSVC_SendCvarValue();
|
pSVC_SendCvarValue();
|
||||||
pCvar->string = old;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void SVC_SendCvarValue2(){
|
void SVC_SendCvarValue2() {
|
||||||
MSG_SaveReadCount();
|
MSG_SaveReadCount();
|
||||||
MSG_ReadLong();
|
MSG_ReadLong();
|
||||||
char* cvar = MSG_ReadString();
|
char* cvar = MSG_ReadString();
|
||||||
char str[1024];
|
char str[1024];
|
||||||
strncpy(str, cvar, sizeof(str));
|
strncpy(str, cvar, sizeof(str));
|
||||||
str[sizeof(str) - 1] = 0;
|
str[sizeof(str) - 1] = 0;
|
||||||
if (!ParseListCvar(str)){
|
cvar_t *pCvar = g_Engine.pfnGetCvarPointer(str);
|
||||||
if (logsfiles->value > 0){
|
if (pCvar != NULL) {
|
||||||
ConsolePrintColor(255, 255, 255, "[Extra Mirror] request cvar2: ");
|
int mode = ParseListCvar(str);
|
||||||
ConsolePrintColor(255, 255, 255, (" %s", cvar));
|
if (mode == cvar_fake || mode == cvar_open) {
|
||||||
ConsolePrintColor(255, 255, 255, "\n");
|
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{
|
else {
|
||||||
if (logsfiles->value > 0){
|
if (logsfiles->value > 0) {
|
||||||
ConsolePrintColor(255, 255, 255, "[Extra Mirror] request blocked cvar2: ");
|
ConsolePrintColor(255, 255, 255, "[Extra Mirror] request non-exist cvar2: ");
|
||||||
ConsolePrintColor(255, 255, 255, (" %s", cvar));
|
ConsolePrintColor(255, 255, 255, (" %s", cvar));
|
||||||
ConsolePrintColor(255, 255, 255, "\n");
|
ConsolePrintColor(255, 255, 255, "\n");
|
||||||
}
|
}
|
||||||
cvar_t *pCvar = g_Engine.pfnGetCvarPointer(str);
|
|
||||||
char *old = pCvar->string;
|
|
||||||
pCvar->string = "Bad CVAR request";
|
|
||||||
MSG_RestoreReadCount();
|
MSG_RestoreReadCount();
|
||||||
pSVC_SendCvarValue2();
|
pSVC_SendCvarValue2();
|
||||||
pCvar->string = old;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//; 0 - black list
|
bool CheckIsFake(string FullCmd) {
|
||||||
//; 1 - whitelist
|
// 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(){
|
bool CheckAndSetCvar(string FullCmd) {
|
||||||
MSG_SaveReadCount();
|
// 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() {
|
||||||
|
//MSG_SaveReadCount();
|
||||||
char* command = MSG_ReadString();
|
char* command = MSG_ReadString();
|
||||||
char str[1024];
|
//MSG_RestoreReadCount();
|
||||||
|
ExecuteString_Test(command, pSVC_StuffText);
|
||||||
|
/*char str[1024];
|
||||||
strncpy(str, command, sizeof(str));
|
strncpy(str, command, sizeof(str));
|
||||||
str[sizeof(str) - 1] = 0;
|
str[sizeof(str) - 1] = 0;
|
||||||
if(BlackList(str))return;
|
if (BlackList(str))return;
|
||||||
MSG_RestoreReadCount();
|
MSG_RestoreReadCount();*/
|
||||||
pSVC_StuffText();
|
//ConsolePrintColor(0, 255, 0, "%s", command);
|
||||||
}
|
}
|
||||||
void SVC_Director(){
|
void SVC_Director() {
|
||||||
MSG_SaveReadCount();
|
/*MSG_SaveReadCount();
|
||||||
int msglen = MSG_ReadByte();
|
int msglen = MSG_ReadByte();
|
||||||
int msgtype = MSG_ReadByte();
|
int msgtype = MSG_ReadByte();
|
||||||
char* DirectCommand = MSG_ReadString();
|
char* DirectCommand = MSG_ReadString();
|
||||||
if (msgtype == 10){
|
if (msgtype == 10) {
|
||||||
char str[1024];
|
char str[1024];
|
||||||
strncpy(str, DirectCommand, sizeof(str));
|
strncpy(str, DirectCommand, sizeof(str));
|
||||||
str[sizeof(str) - 1] = 0;
|
str[sizeof(str) - 1] = 0;
|
||||||
if(BlackList(str))return;
|
if (BlackList(str))return;
|
||||||
}
|
}
|
||||||
MSG_RestoreReadCount();
|
MSG_RestoreReadCount();
|
||||||
pSVC_Director();
|
pSVC_Director();*/
|
||||||
}
|
}
|
||||||
void SVC_VoiceInit() {
|
void SVC_VoiceInit() {
|
||||||
MSG_SaveReadCount();
|
MSG_SaveReadCount();
|
||||||
char* codec = MSG_ReadString(); int bitz = MSG_ReadByte(); bool blocked;
|
char* codec = MSG_ReadString(); int bitz = MSG_ReadByte(); bool blocked;
|
||||||
if(!stricmp(codec,"voice_miles")||!stricmp(codec,"voice_speex"))blocked=false;
|
if (!stricmp(codec, "voice_miles") || !stricmp(codec, "voice_speex"))blocked = false;
|
||||||
else blocked=true;
|
else blocked = true;
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
snprintf(buffer, sizeof(buffer), "[Extra Mirror] [VoiceInit] %s [%s]\n", codec,blocked?"Blocked":"Execute");
|
snprintf(buffer, sizeof(buffer), "[Extra Mirror] [VoiceInit] %s [%s]\n", codec, blocked ? "Blocked" : "Execute");
|
||||||
ConsolePrintColor(255, 255, 255, buffer);
|
ConsolePrintColor(255, 255, 255, buffer);
|
||||||
if(blocked)return;
|
if (blocked)return;
|
||||||
MSG_RestoreReadCount();
|
MSG_RestoreReadCount();
|
||||||
pSVC_VoiceInit();
|
pSVC_VoiceInit();
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
void SVC_Resourcelist() {
|
void SVC_Resourcelist() {
|
||||||
MSG_SaveReadCount();
|
MSG_SaveReadCount();
|
||||||
int NumResources, Type, Index, DownloadSize, HasExtraInfo, ExtraInfo, HasConsistency, Flags, Flags;
|
int NumResources, Type, Index, DownloadSize, HasExtraInfo, ExtraInfo, HasConsistency, Flags, Flags;
|
||||||
MSG_StartBitReading(MSG_Buffer);
|
MSG_StartBitReading(MSG_Buffer);
|
||||||
NumResources = MSG_ReadBits(12);
|
NumResources = MSG_ReadBits(12);
|
||||||
|
|
||||||
for (int i = 1; i <= NumResources; i++) {
|
for (int i = 1; i <= NumResources; i++) {
|
||||||
Type = MSG_ReadBits(4);
|
Type = MSG_ReadBits(4);
|
||||||
char* szFileName[64];
|
char* szFileName[64];
|
||||||
// szFileName = MSG_ReadBitString();
|
// szFileName = MSG_ReadBitString();
|
||||||
Index = MSG_ReadBits(12);
|
Index = MSG_ReadBits(12);
|
||||||
DownloadSize = MSG_ReadBits(24);
|
DownloadSize = MSG_ReadBits(24);
|
||||||
unsigned char Flags = READ_CHAR();
|
unsigned char Flags = READ_CHAR();
|
||||||
unsigned char rgucMD5_hash[16];
|
unsigned char rgucMD5_hash[16];
|
||||||
for (int i = 0; i < 16; i++)(BYTE)rgucMD5_hash[i] = READ_CHAR();
|
for (int i = 0; i < 16; i++)(BYTE)rgucMD5_hash[i] = READ_CHAR();
|
||||||
HasExtraInfo = MSG_ReadBits(1);
|
HasExtraInfo = MSG_ReadBits(1);
|
||||||
if (HasExtraInfo)ExtraInfo = MSG_ReadBits(256);
|
if (HasExtraInfo)ExtraInfo = MSG_ReadBits(256);
|
||||||
}
|
}
|
||||||
HasConsistency = MSG_ReadBits(1);
|
HasConsistency = MSG_ReadBits(1);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
@ -82,8 +82,19 @@ void SVC_Director();
|
|||||||
void SVC_Resourcelist();
|
void SVC_Resourcelist();
|
||||||
void SVC_VoiceInit();
|
void SVC_VoiceInit();
|
||||||
|
|
||||||
|
extern DWORD Cbuf_Addtext_call;
|
||||||
|
extern DWORD Cbuf_Addtext_jump;
|
||||||
|
extern DWORD Cbuf_Execute_call;
|
||||||
|
extern DWORD Cbuf_Execute_jump;
|
||||||
|
extern DWORD ExecuteString_call;
|
||||||
|
extern DWORD ExecuteString_jump;
|
||||||
|
extern void Cbuf_AddText_CallHook_Ext(char *text);
|
||||||
|
extern void Cbuf_Execute_CallHook_Ext();
|
||||||
|
|
||||||
extern pfnEngineMessage pSVC_VoiceInit;
|
extern pfnEngineMessage pSVC_VoiceInit;
|
||||||
extern pfnEngineMessage pSVC_StuffText;
|
extern pfnEngineMessage pSVC_StuffText;
|
||||||
extern pfnEngineMessage pSVC_SendCvarValue;
|
extern pfnEngineMessage pSVC_SendCvarValue;
|
||||||
extern pfnEngineMessage pSVC_SendCvarValue2;
|
extern pfnEngineMessage pSVC_SendCvarValue2;
|
||||||
extern pfnEngineMessage pSVC_Director;
|
extern pfnEngineMessage pSVC_Director;
|
||||||
|
extern bool CheckIsFake(string FullCmd);
|
||||||
|
extern bool CheckAndSetCvar(string FullCmd);
|
@ -8,7 +8,9 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
extern cvar_t *random;
|
extern cvar_t *random;
|
||||||
extern cvar_t *logsfiles;
|
extern cvar_t *logsfiles;
|
||||||
TCHAR g_settingsFileName[MAX_PATH];
|
TCHAR g_settingsFileName[MAX_PATH];
|
||||||
@ -17,7 +19,7 @@ void(*g_pfnCL_ParseConsistencyInfo)();
|
|||||||
FILE *g_pFile;
|
FILE *g_pFile;
|
||||||
extern int g_anticheckfiles;
|
extern int g_anticheckfiles;
|
||||||
extern char *g_anticheckfiles2[2048];
|
extern char *g_anticheckfiles2[2048];
|
||||||
|
DWORD Original_ExecuteString;
|
||||||
|
|
||||||
bool ParseListx(const char *str) {
|
bool ParseListx(const char *str) {
|
||||||
for (DWORD i = 0; i < g_anticheckfiles; i++) {
|
for (DWORD i = 0; i < g_anticheckfiles; i++) {
|
||||||
@ -288,10 +290,24 @@ public:
|
|||||||
return true;
|
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 {
|
class CallOpcode {
|
||||||
public:
|
public:
|
||||||
static uintptr_t GetDestination(uintptr_t callPtr) {
|
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) {
|
static void SetDestination(uintptr_t callPtr, uintptr_t destPtr) {
|
||||||
DWORD oldProt;
|
DWORD oldProt;
|
||||||
@ -446,16 +462,132 @@ int Steam_GSInitiateGameConnection_CallHook(void *pData, int maxDataBytes, uint6
|
|||||||
memcpy(pData, &revEmuTicket, sizeof(revEmuTicket));
|
memcpy(pData, &revEmuTicket, sizeof(revEmuTicket));
|
||||||
return sizeof(revEmuTicket);
|
return sizeof(revEmuTicket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__declspec(naked) void Cbuf_Execute_CallHook()
|
||||||
|
{
|
||||||
|
__asm PUSH EBP
|
||||||
|
__asm MOV EBP, ESP
|
||||||
|
__asm SUB ESP, 400h
|
||||||
|
__asm JMP[Cbuf_Execute_jump]
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cbuf_Execute_CallHook_Ext()
|
||||||
|
{
|
||||||
|
Cbuf_Execute_CallHook();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__declspec(naked) void Cbuf_AddText_CallHook(char *text)
|
||||||
|
{
|
||||||
|
//MessageBox(NULL, text, NULL, MB_OK);
|
||||||
|
__asm PUSH EBP
|
||||||
|
__asm MOV EBP, ESP
|
||||||
|
__asm PUSH ESI
|
||||||
|
__asm MOV ESI, [EBP + 0x8]
|
||||||
|
__asm JMP[Cbuf_Addtext_jump]
|
||||||
|
/*MessageBox(NULL, text, NULL, MB_OK);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cbuf_AddText_CallHook_Ext(char *text)
|
||||||
|
{
|
||||||
|
Cbuf_AddText_CallHook(text);
|
||||||
|
}
|
||||||
|
|
||||||
void CL_ReadDemoMessage_OLD_Cbuf_AddText_CallHook(const char *str){
|
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);
|
//MessagePrintf("Demo tried to execute: %s", str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//void (*Original_ExecuteString)(char *text, cmd_source_t src);
|
||||||
|
/*
|
||||||
|
void __cdecl Cmd_ExecuteString_CallHook(char *text, cmd_source_t src)
|
||||||
|
{
|
||||||
|
__asm PUSH EBP
|
||||||
|
__asm MOV EBP, ESP
|
||||||
|
__asm MOV ECX, [EBP + 8]
|
||||||
|
__asm MOV EAX, [EBP + 0Ch]
|
||||||
|
__asm PUSH ESI
|
||||||
|
__asm JMP [Original_ExecuteString]
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
void Cmd_ExecuteString_CallHook(char *text, cmd_source_t src)
|
||||||
|
{
|
||||||
|
char * lox;
|
||||||
|
__asm PUSH EBP
|
||||||
|
__asm MOV EBP, ESP
|
||||||
|
//__asm MOV ECX, DWORD PTR SS : [EBP + 0x8]
|
||||||
|
__asm MOV ECX, [EBP + 0x8]
|
||||||
|
__asm MOV EAX, [EBP + 0xC]
|
||||||
|
__asm { MOV ECX, lox }
|
||||||
|
{
|
||||||
|
std::stringstream stream;
|
||||||
|
stream << "1 " << lox;
|
||||||
|
MessageBox(0, stream.str().c_str(), 0, MB_OK);
|
||||||
|
}
|
||||||
|
__asm PUSH ESI
|
||||||
|
__asm JMP[Original_ExecuteString]
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
//void Cmd_ExecuteString_CallHook(char *text, cmd_source_t src)
|
||||||
|
//__declspec(naked) void WINAPI Cmd_ExecuteString_CallHook()
|
||||||
|
/*__declspec(naked) void Cmd_ExecuteString_CallHook()
|
||||||
|
{
|
||||||
|
__asm PUSH EBP
|
||||||
|
__asm call ExecuteString
|
||||||
|
__asm MOV EBP, ESP
|
||||||
|
__asm MOV ECX, [EBP + 0x8]
|
||||||
|
__asm MOV EAX, [EBP + 0xC]
|
||||||
|
__asm JMP[Original_ExecuteString]
|
||||||
|
}*/
|
||||||
|
/*
|
||||||
|
__declspec(naked) void Cmd_ExecuteString_CallHook()
|
||||||
|
{
|
||||||
|
static char *text; cmd_source_t src;
|
||||||
|
__asm MOV text, ECX
|
||||||
|
__asm MOV src, EAX
|
||||||
|
ExecuteString(text, src);
|
||||||
|
__asm PUSH EBP
|
||||||
|
__asm MOV EBP, ESP
|
||||||
|
__asm MOV ECX, [EBP + 0x8]
|
||||||
|
__asm MOV EAX, [EBP + 0xC]
|
||||||
|
__asm JMP[Original_ExecuteString]
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
// good func #2
|
||||||
|
__declspec(naked) void Cmd_ExecuteString_CallHook()
|
||||||
|
{
|
||||||
|
__asm {
|
||||||
|
PUSH EBP
|
||||||
|
MOV EBP, ESP
|
||||||
|
MOV ECX, [EBP + 0x8]
|
||||||
|
MOV EAX, [EBP + 0xC]
|
||||||
|
PUSH EAX
|
||||||
|
PUSH ECX
|
||||||
|
call ExecuteString
|
||||||
|
POP ECX
|
||||||
|
POP EAX
|
||||||
|
POP EBP
|
||||||
|
}
|
||||||
|
__asm {
|
||||||
|
PUSH EBP
|
||||||
|
MOV EBP, ESP
|
||||||
|
MOV ECX, [EBP + 0x8]
|
||||||
|
MOV EAX, [EBP + 0xC]
|
||||||
|
jmp[Original_ExecuteString]
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
void CL_ConnectionlessPacket_Cbuf_AddText_CallHook(const char *str){
|
void CL_ConnectionlessPacket_Cbuf_AddText_CallHook(const char *str){
|
||||||
// Add your filters there
|
// 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() {
|
void ModuleLoaded() {
|
||||||
Module *pModule;
|
Module *pModule;
|
||||||
if (Module::IsLoaded("hw.dll")) {
|
if (Module::IsLoaded("hw.dll")) {
|
||||||
@ -477,7 +609,33 @@ void ModuleLoaded() {
|
|||||||
ptr = pModule->FindFirstUseOfString("Error, bad server command %s\n");
|
ptr = pModule->FindFirstUseOfString("Error, bad server command %s\n");
|
||||||
ptr = pModule->SearchUpForBinaryPattern(ptr, BinaryPattern("E8 ?? ?? ?? ?? 83 C4 04 5E"));
|
ptr = pModule->SearchUpForBinaryPattern(ptr, BinaryPattern("E8 ?? ?? ?? ?? 83 C4 04 5E"));
|
||||||
uintptr_t pfnCbuf_AddText = (decltype(pfnCbuf_AddText))CallOpcode::GetDestination(ptr);
|
uintptr_t pfnCbuf_AddText = (decltype(pfnCbuf_AddText))CallOpcode::GetDestination(ptr);
|
||||||
|
//.data:01E55198 00000006 C quit\n
|
||||||
|
{
|
||||||
|
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_call = (uintptr_t)CallOpcode::GetDestination(ptr);
|
||||||
|
{
|
||||||
|
std::stringstream stream;
|
||||||
|
ptr += 0xf;
|
||||||
|
Cbuf_Execute_call = (uintptr_t)CallOpcode::GetDestination(ptr);
|
||||||
|
stream << " LEL " << std::hex << Cbuf_Execute_call << " \n";
|
||||||
|
Cbuf_Execute_jump = Cbuf_Execute_call + 0x9;
|
||||||
|
//MessageBox(NULL, stream.str().c_str(), NULL, MB_OK);
|
||||||
|
JmpOpcode::Setup(Cbuf_Execute_call, (DWORD)&Cbuf_Execute_CallHook);
|
||||||
|
}
|
||||||
|
Cbuf_Addtext_jump = Cbuf_Addtext_call + 0x7;
|
||||||
|
JmpOpcode::Setup(Cbuf_Addtext_call, (DWORD)&Cbuf_AddText_CallHook);
|
||||||
|
}
|
||||||
|
//CallOpcode::SetDestination(ptr, &Cmd_ExecuteString_CallHook);
|
||||||
|
//PlaceJMP((BYTE*)ptr, (DWORD)&Cmd_ExecuteString_CallHook, 0x9);
|
||||||
|
//JmpOpcode::Setup(ptr, (DWORD)&Cmd_ExecuteString_CallHook);
|
||||||
ptr = pModule->FindFirstUseOfString("Tried to read a demo message with no demo file\n");
|
ptr = pModule->FindFirstUseOfString("Tried to read a demo message with no demo file\n");
|
||||||
ptr = pModule->SearchDownForFirstCallToFunction(ptr, pfnCbuf_AddText);
|
ptr = pModule->SearchDownForFirstCallToFunction(ptr, pfnCbuf_AddText);
|
||||||
CallOpcode::SetDestination(ptr, &CL_ReadDemoMessage_OLD_Cbuf_AddText_CallHook);
|
CallOpcode::SetDestination(ptr, &CL_ReadDemoMessage_OLD_Cbuf_AddText_CallHook);
|
||||||
@ -501,7 +659,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved){
|
|||||||
TCHAR sFileName[MAX_PATH];
|
TCHAR sFileName[MAX_PATH];
|
||||||
StringCchCopyN(sFileName, ARRAYSIZE(sFileName), lpFileName, lpExtension - lpFileName);
|
StringCchCopyN(sFileName, ARRAYSIZE(sFileName), lpFileName, lpExtension - lpFileName);
|
||||||
|
|
||||||
bool fPrefixDetected = false;
|
bool fPrefixDetected = true;
|
||||||
for (PTCHAR pch = sFileName; *pch != '\0'; pch++) {
|
for (PTCHAR pch = sFileName; *pch != '\0'; pch++) {
|
||||||
if (*pch == 'm') {
|
if (*pch == 'm') {
|
||||||
fPrefixDetected = true;
|
fPrefixDetected = true;
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include <TlHelp32.h>
|
#include <TlHelp32.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@ -42,7 +42,7 @@ using namespace std;
|
|||||||
#include "enginemsg.h"
|
#include "enginemsg.h"
|
||||||
#include "font.h"
|
#include "font.h"
|
||||||
#include "eventmsg.h"
|
#include "eventmsg.h"
|
||||||
|
#include "redirect.h"
|
||||||
|
|
||||||
extern cl_clientfunc_t *g_pClient;
|
extern cl_clientfunc_t *g_pClient;
|
||||||
extern cl_enginefunc_t *g_pEngine;
|
extern cl_enginefunc_t *g_pEngine;
|
||||||
|
80
MiniBase/redirect.h
Normal file
80
MiniBase/redirect.h
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
#ifndef EASYHOOK_HPP
|
||||||
|
#define EASYHOOK_HPP
|
||||||
|
#include <array>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <iostream>
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <winternl.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
|
Loading…
x
Reference in New Issue
Block a user