Skip to content

Commit

Permalink
Merge pull request #190 from sapphonie/beta-2024
Browse files Browse the repository at this point in the history
Updates from the year 2024
  • Loading branch information
sapphonie authored Apr 7, 2024
2 parents 51b3eb3 + 77c09d5 commit 69764cd
Show file tree
Hide file tree
Showing 12 changed files with 199 additions and 118 deletions.
Binary file modified extensions/sourcetvmanager.ext.2.tf2.dll
Binary file not shown.
Binary file modified extensions/sourcetvmanager.ext.2.tf2.so
Binary file not shown.
65 changes: 46 additions & 19 deletions gamedata/sourcetvmanager.games.txt
Original file line number Diff line number Diff line change
Expand Up @@ -756,35 +756,42 @@

"Offsets"
{
// String: "NetMsg"
"CNetChan::SendNetMsg"
{
"windows" "41"
"linux" "42"
}


// cvar sv_maxrate->ClampClientRate->CBaseClient::SetRate (located below)
// CBaseClient::SetRate
"CBaseClient::m_NetChannel"
{
"windows" "224"
"linux" "228"
"windows" "228"
"linux" "232"
}

"CGameClient::ClientPrintf"
{
"linux" "26"
}


// String: "%s unpaused the game\n"
// The string above is passed to this function
"CBaseServer::BroadcastPrintf"
{
"windows" "36"
"linux" "37"
}

// Siring: "Valve_Reject_Background_Map"
"CHLTVServer::ConnectClient"
{
"windows" "50"
"linux" "51"
}

// String: "RejectConnection: %s - %s"
"CHLTVServer::RejectConnection"
{
"windows" "48"
Expand All @@ -796,13 +803,15 @@
"windows" "54"
"linux" "55"
}


// String: "UpdatePlayers"
"CBaseClient::ActivatePlayer"
{
"windows" "15"
"linux" "61"
}


// String: "server_pre_shutdown"
"CBaseClient::FireGameEvent"
{
"windows" "1"
Expand All @@ -814,29 +823,43 @@
"linux" "15"
}

// String: "Server shutting down"
"CHLTVServer::Shutdown"
{
"windows" "42"
"linux" "43"
}

// Library - server.dll
// String: "hltv_fixed"
// we will find the function - CHLTVDirector::StartFixedCameraShot,
// required offset inside
"CHLTVDirector::m_iPVSEntity"
{
"windows" "16"
"linux" "16"
"windows" "32"
"linux" "32"
}


// Library - server.dll
// String: "hltv_fixed"
// we will find the function - CHLTVDirector::StartFixedCameraShot,
// required offset inside
"CHLTVDirector::m_vPVSOrigin"
{
"windows" "20"
"linux" "20"
"windows" "36"
"linux" "36"
}

// Library - server.dll
// String: "Please wait for broadcast to start ...",
// we will find the function - CHLTVDirector::StartDelayMessage,
// required offset inside
"CHLTVDirector::m_nNextShotTick"
{
"windows" "40"
"linux" "40"
"windows" "56"
"linux" "56"
}

"CHLTVDemoRecorder_BaseOffset"
{
"windows" "0"
Expand All @@ -850,6 +873,7 @@
"library" "engine"
"linux" "@host_client"
// ping(CCommand const&) "Client ping times:\n"
// 55 8B EC 51 83 3D ? ? ? ? 01 75 ?
"windows" "\x55\x8B\xEC\x51\x83\x3D\x2A\x2A\x2A\x2A\x01\x75\x2A"
}

Expand All @@ -858,23 +882,26 @@
"library" "engine"
"linux" "@_ZN11CHLTVServer19BroadcastEventLocalEP10IGameEventb"
// "SourceTV broadcast local event: %s\n"
"windows" "\x55\x8B\xEC\x81\xEC\x58\x04\x00\x00\xA1\x2A\x2A\x2A\x2A\x33\xC5\x89\x45\xFC\x53\x56"
// 55 8B EC 81 EC A4 04 00 00 A1 ? ? ? ? 33 C5 89 45 FC D9 EE
"windows" "\x55\x8B\xEC\x81\xEC\xA4\x04\x00\x00\xA1\x2A\x2A\x2A\x2A\x33\xC5\x89\x45\xFC\xD9\xEE"
}

"CHLTVServer::BroadcastLocalChat"
{
"library" "engine"
"linux" "@_ZN11CHLTVServer18BroadcastLocalChatEPKcS1_"
// "hltv_chat"
"windows" "\x55\x8B\xEC\x81\xEC\x60\x04\x00\x00\xA1\x2A\x2A\x2A\x2A\x33\xC5\x89\x45\xFC\x8B\x45\x0C\x53\x8B\x5D\x08\x56\x57\x8B\xF1"
// "hltv_chat", "CHLTVServer: failed to serialize chat '%s'.\n"
// 55 8B EC 81 EC A8 04 00 00 A1 ? ? ? ? 33 C5 89 45 FC 8B 45 0C
"windows" "\x55\x8B\xEC\x81\xEC\xA8\x04\x00\x00\xA1\x2A\x2A\x2A\x2A\x33\xC5\x89\x45\xFC\x8B\x45\x0C"
}

"CHLTVServer::Shutdown"
{
"library" "engine"
"linux" "@_ZN11CHLTVServer8ShutdownEv"
"library" "engine"
"linux" "@_ZN11CHLTVServer8ShutdownEv"
// "SourceTV stop."
"windows" "\x56\x8B\xF1\x8B\x86\x2A\x2A\x2A\x2A\x8B\x50\x2A\x8D\x8E\x2A\x2A\x2A\x2A\xFF\xD2\x8B\x86\x2A\x2A\x2A\x2A\x8B\x50\x2A\x8D\x8E"
// 56 8B F1 8B 86 ? ? ? ? 8B 50 ? 8D 8E ? ? ? ? FF D2 8B 86 ? ? ? ? 8B 50 ? 8D 8E
"windows" "\x56\x8B\xF1\x8B\x86\x2A\x2A\x2A\x2A\x8B\x50\x2A\x8D\x8E\x2A\x2A\x2A\x2A\xFF\xD2\x8B\x86\x2A\x2A\x2A\x2A\x8B\x50\x2A\x8D\x8E"
}

// StartRecording and StopRecording are virtual, but get called directly in the linux binary..
Expand Down
Binary file modified plugins/stac.smx
Binary file not shown.
5 changes: 2 additions & 3 deletions scripting/stac.sp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
#pragma semicolon 1
#pragma newdecls required

#define PLUGIN_VERSION "6.1.3-beta7"
#define PLUGIN_VERSION "6.1.4"

#define UPDATE_URL "https://raw.githubusercontent.com/sapphonie/StAC-tf2/master/updatefile.txt"

Expand Down Expand Up @@ -121,11 +121,10 @@ public void OnPluginStart()
}

// reg admin commands
// TODO: make these invisible for non admins
RegConsoleCmd("sm_stac_checkall", checkAdmin, "Force check all client convars (ALL CLIENTS) for anticheat stuff");
RegConsoleCmd("sm_stac_detections", checkAdmin, "Show all current detections on all connected clients");
RegConsoleCmd("sm_stac_getauth", checkAdmin, "Print StAC's cached auth for a client");
RegConsoleCmd("sm_stac_livefeed", checkAdmin, "Show live feed (debug info etc) for a client. This gets printed to SourceTV if available.");
RegConsoleCmd("sm_stac_livefeed", checkAdmin, "Show live feed (debug info etc) for a client. This gets printed to SourceTV too, if available.");

// steamidRegex = CompileRegex("^STEAM_[0-5]:[0-1]:[0-9]+$");

Expand Down
119 changes: 46 additions & 73 deletions scripting/stac/stac_client.sp
Original file line number Diff line number Diff line change
Expand Up @@ -44,89 +44,58 @@ public bool OnClientPreConnectEx(const char[] name, char password[255], const ch
strcopy(latestIP, sizeof(latestIP), ip);
strcopy(latestSteamID, sizeof(latestSteamID), steamID);


if (!stac_prevent_connect_spam.BoolValue)
{
return true;
}

// TODO: does this need to be higher? or lower? or...?
static int threshold = 5;
int connects;
IPBuckets.GetValue(ip, connects); // 0 if not present
connects++;
if (connects >= threshold)
{
rejectReason = "Rate limited.";

DataPack steamidPlusIP = new DataPack();
steamidPlusIP.Reset(true);
steamidPlusIP.WriteString(steamID);
steamidPlusIP.WriteString(ip);
steamidPlusIP.WriteString(name);
steamidPlusIP.Reset(false);

// This is not arbitrary!
RequestFrame(DelayedRateLimitBan, steamidPlusIP);

return false;
}
IPBuckets.SetValue(ip, connects);

if (stac_debug.BoolValue)
// DO NOT interfere with lan matches until we have a way to store port from here!
ConVar sv_lan = FindConVar("sv_lan");
if (sv_lan.BoolValue)
{
StacLog("-> connects from ip %s %i", ip, connects);
return true;
}

return true;
}
// connects is how many times have they connected recently, it decays by 1 every 5 seconds
// threshold how many times is "too many"
// thresholdEx is at what point we should start punishing & making each connect be worth double/triple/etc to the algorithm
int connects = 0;
static int threshold = 6;
static int thresholdEx = 10;
bool punish = false;
IPBuckets.GetValue(ip, connects); // 0 if not present

void DelayedRateLimitBan(DataPack dp)
{
dp.Reset(false);
char steamID[MAX_AUTHID_LENGTH];
char ipAddr[256];
char playerName[MAX_NAME_LENGTH];
dp.ReadString(steamID, sizeof(steamID));
dp.ReadString(ipAddr, sizeof(ipAddr));
dp.ReadString(playerName, sizeof(playerName));
dp.Reset(true);
delete dp;

static int rateLimitBanTime = 60;

// BanIdentity(steamID, 60, BANFLAG_AUTHID, "");
// BanIdentity(ip, 60, BANFLAG_IP, "");

// THE REASON we are doing this so weirdly, is so that we hook into srcds's built in
// "firewall", basically, where with the default game banning system,
// srcds will ignore packets from banned ips.
// this prevents any clients from spamming, in a way that would otherwise not really be possible,
// without stupid memory hacks that would be overcomplicated anyway since this already exists

// We're doing sm_addban / sm_banip because SourceBans, at least, will propagate this to other servers as well
// which is what we want, so people don't have to get individually banned on each server on the same network that they try to spam on

// Probably before un-betaing this, i'm going to try to move this to sm_ban and then addip after?
// I don't really know. it's a tricky race condition here, since we're after OnClientPreConnectEx callback, so they should be rejected,
// but they can rejoin, but regardless we don't actually have a client index yet?
if ( CommandExists("sm_banip") && CommandExists("sm_addban") )
{
ServerCommand("sm_addban %i %s %s", rateLimitBanTime, steamID, "Rate limited");
ServerCommand("sm_banip %s %i %s", ipAddr, rateLimitBanTime, "Rate limited");
// inc by one since we're in this callback
connects++;

// strong punishment
if (connects > thresholdEx)
{
punish = true;
rejectReason = "Rate limited for retry spam. Please try again in a few minutes.";
// worth double
connects++;
}
else
// light punishment
else if (connects >= threshold)
{
ServerCommand("addip %i %s", rateLimitBanTime, ipAddr);
ServerCommand("banid %i %s kick", rateLimitBanTime, steamID);
punish = true;
rejectReason = "Rate limited for retry spam. Please try again in a bit.";
}
else { /* no punishment, they didn't trip any threshold */ }

char formattedMsg[1024];
Format(formattedMsg, sizeof(formattedMsg), "Rate limited %s / %s / %s for %i minutes for connect spam", playerName, steamID, ipAddr, rateLimitBanTime);

StacLog(formattedMsg);
// set our connects to our stupid global var thing
IPBuckets.SetValue(ip, connects);

StacNotify(0, formattedMsg, 1);
if (stac_debug.BoolValue)
{
StacLog("[stac_prevent_connect_spam - OnClientPreConnectEx] %i connects from ip %s", connects, ip);
}

// this func detour returns true to let them in, and false to prevent them from connecting
// rejectReason is displayed as the reason to their client.
// that's just how it is.
return !punish;
}

Action LeakIPConnectBucket(Handle timer)
Expand All @@ -150,14 +119,14 @@ Action LeakIPConnectBucket(Handle timer)

if (stac_debug.BoolValue)
{
StacLog("(LeakIPConnectBucket) connects from ip %s %i", ip, connects);
StacLog("[stac_prevent_connect_spam - LeakIPConnectBucket] %i connects from ip %s", connects, ip);
}

if (connects <= 0)
{
if (stac_debug.BoolValue)
{
StacLog("-> connects from ip %s %i [ REMOVING ] ", ip, connects);
StacLog("[stac_prevent_connect_spam - LeakIPConnectBucket] %i connects from ip %s [ REMOVING ] ", connects, ip);
}

IPBuckets.Remove(ip);
Expand Down Expand Up @@ -370,8 +339,10 @@ public void OnClientPutInServer(int cl)
StacLog("OCPIS steamid = %s", SteamAuthFor[cl]);
}

// bail if cvar is set to 0
if (stac_max_connections_from_ip.IntValue > 0)
ConVar sv_lan = FindConVar("sv_lan");

// bail if cvar is set to 0 or if we're in sv_lan 1
if ( stac_max_connections_from_ip.IntValue > 0 && !(sv_lan.BoolValue) )
{
checkIP(cl);
}
Expand Down Expand Up @@ -589,6 +560,7 @@ Action OnAllClientCommands(int cl, const char[] command, int argc)
return Plugin_Continue;
}

// Runs OnClientPutInServer (which runs on map change too!) and OnClientDisconnect
void ClearClBasedVars(int userid)
{
// get fresh cli id
Expand All @@ -605,6 +577,7 @@ void ClearClBasedVars(int userid)
cmdnumSpikeDetects [cl] = 0;
tbotDetects [cl] = -1;
invalidUsercmdDetects [cl] = 0;
stacProbingDetects [cl] = 0;

// frames since client "did something"
// [ client index ][history]
Expand Down
Loading

0 comments on commit 69764cd

Please sign in to comment.