diff --git a/connect.games.txt b/connect.games.txt index b2b4da6..3decfb7 100644 --- a/connect.games.txt +++ b/connect.games.txt @@ -81,14 +81,6 @@ "windows" "\x55\x8B\xEC\x8B\x55\x08\x8B\x02\x89\x41\x59\x8B\x42\x04" } - "CBaseServer__CheckChallengeType" - { - "library" "engine" - "linux" "@_ZN11CBaseServer18CheckChallengeTypeEP11CBaseClientiR8netadr_siPKcii" - "mac" "@_ZN11CBaseServer18CheckChallengeTypeEP11CBaseClientiR8netadr_siPKcii" - "windows" "\x55\x8B\xEC\x83\xEC\x14\x56\x57\x8B\x7D\x2A\x8B\xF1" - } - "CBaseServer__CheckMasterServerRequestRestart" { "library" "engine" @@ -106,6 +98,22 @@ "Offsets" { + "ISteamGameServer__BeginAuthSession" + { + "linux" "26" + "linux64" "26" + "windows" "26" + "windows64" "26" + } + + "ISteamGameServer__EndAuthSession" + { + "linux" "27" + "linux64" "27" + "windows" "27" + "windows64" "27" + } + "CheckMasterServerRequestRestart_Steam3ServerFuncOffset" { "windows" "240" @@ -138,14 +146,6 @@ "windows" "\x55\x8B\xEC\x56\x8B\xF1\x57\x8B\x7D\x08\x8D\x4E\x04" } - "CBaseServer__CheckChallengeType" - { - "library" "engine" - "linux" "@_ZN11CBaseServer18CheckChallengeTypeEP11CBaseClientiR8netadr_siPKcii" - "linux64" "@_ZN11CBaseServer18CheckChallengeTypeEP11CBaseClientiR8netadr_siPKcii" - "windows" "\x55\x8B\xEC\x83\xEC\x14\x53\x8B\x5D\x14" - } - "CBaseServer__CheckMasterServerRequestRestart" { "library" "engine" diff --git a/extension/extension.cpp b/extension/extension.cpp index 424dbfd..2a1b337 100644 --- a/extension/extension.cpp +++ b/extension/extension.cpp @@ -21,6 +21,7 @@ #include "CDetour/detours.h" #include "steam/steamclientpublic.h" +#include Connect g_connect; @@ -114,6 +115,17 @@ typedef void (*SetSteamIDFunc)(CBaseClient *, const CSteamID &steamID); typedef void (__fastcall *SetSteamIDFunc)(CBaseClient *, void *, const CSteamID &steamID); #endif +CDetour* detourCBaseServer__ConnectClient = nullptr; +CDetour* detourCBaseServer__RejectConnection = nullptr; + +bool g_bEndAuthSessionOnRejectConnection = false; +bool g_bSuppressBeginAuthSession = false; +CSteamID g_lastClientSteamID; +const void* g_lastAuthTicket; +int g_lastcbAuthTicket; + +char passwordBuffer[255]; + Steam3ServerFunc g_pSteam3ServerFunc = NULL; RejectConnectionFunc g_pRejectConnectionFunc = NULL; SetSteamIDFunc g_pSetSteamIDFunc = NULL; @@ -155,89 +167,61 @@ class VFuncEmptyClass{}; int g_nBeginAuthSessionOffset = 0; int g_nEndAuthSessionOffset = 0; +SH_DECL_MANUALHOOK3(MHook_BeginAuthSession, 0, 0, 0, EBeginAuthSessionResult, const void *, int, CSteamID); +int g_nHookIdBeginAuthSession = -1; + +EBeginAuthSessionResult Hook_BeginAuthSession(const void *pAuthTicket, int cbAuthTicket, CSteamID steamID) +{ + if (!g_bSuppressBeginAuthSession) + { + RETURN_META_VALUE(MRES_IGNORED, k_EBeginAuthSessionResultOK); + } + g_bSuppressBeginAuthSession = false; + + if (strcmp(steamID.Render(), g_lastClientSteamID.Render()) == 0 + && g_lastAuthTicket == pAuthTicket + && g_lastcbAuthTicket == cbAuthTicket) + { + // Let the server know everything is fine + // g_pSM->LogMessage(myself, "You alright ;)"); + RETURN_META_VALUE(MRES_SUPERCEDE, k_EBeginAuthSessionResultOK); + } + + RETURN_META_VALUE(MRES_IGNORED, k_EBeginAuthSessionResultDuplicateRequest); +} + EBeginAuthSessionResult BeginAuthSession(const void *pAuthTicket, int cbAuthTicket, CSteamID steamID) { - if (!g_pSteam3Server || !g_pSteam3Server->m_pSteamGameServer || g_nBeginAuthSessionOffset == 0) - return k_EBeginAuthSessionResultOK; + if (g_nBeginAuthSessionOffset == 0) + return k_EBeginAuthSessionResultInvalidTicket; - void **this_ptr = *(void ***)&g_pSteam3Server->m_pSteamGameServer; - void **vtable = *(void ***)g_pSteam3Server->m_pSteamGameServer; - void *func = vtable[g_nBeginAuthSessionOffset]; + void *func = (*(void ***)g_pSteam3Server->m_pSteamGameServer)[g_nBeginAuthSessionOffset]; union { EBeginAuthSessionResult (VFuncEmptyClass::*mfpnew)(const void *, int, CSteamID); - -#ifndef WIN32 - struct { - void *addr; - intptr_t adjustor; - } s; + mfpDetails mfp; } u; + u.mfp.Init(func); - u.s.addr = func; - u.s.adjustor = 0; -#else - void *addr; - } u; - - u.addr = func; -#endif - - return (EBeginAuthSessionResult)(reinterpret_cast(this_ptr)->*u.mfpnew)(pAuthTicket, cbAuthTicket, steamID); + return (EBeginAuthSessionResult)(reinterpret_cast(g_pSteam3Server->m_pSteamGameServer)->*u.mfpnew)(pAuthTicket, cbAuthTicket, steamID); } void EndAuthSession(CSteamID steamID) { - if (!g_pSteam3Server || !g_pSteam3Server->m_pSteamGameServer || g_nEndAuthSessionOffset == 0) + if (g_nEndAuthSessionOffset == 0) return; - void **this_ptr = *(void ***)&g_pSteam3Server->m_pSteamGameServer; - void **vtable = *(void ***)g_pSteam3Server->m_pSteamGameServer; - void *func = vtable[g_nEndAuthSessionOffset]; + void *func = (*(void ***)g_pSteam3Server->m_pSteamGameServer)[g_nEndAuthSessionOffset]; union { void (VFuncEmptyClass::*mfpnew)(CSteamID); - -#ifndef WIN32 - struct { - void *addr; - intptr_t adjustor; - } s; + mfpDetails mfp; } u; + u.mfp.Init(func); - u.s.addr = func; - u.s.adjustor = 0; -#else - void *addr; - } u; - - u.addr = func; -#endif - - return (void)(reinterpret_cast(this_ptr)->*u.mfpnew)(steamID); + return (void)(reinterpret_cast(g_pSteam3Server->m_pSteamGameServer)->*u.mfpnew)(steamID); } -CDetour* detourCBaseServer__ConnectClient = nullptr; -CDetour* detourCBaseServer__RejectConnection = nullptr; -CDetour* detourCBaseServer__CheckChallengeType = nullptr; - -bool g_bEndAuthSessionOnRejectConnection = false; -CSteamID g_lastClientSteamID; - -bool g_bSuppressCheckChallengeType = false; - -char passwordBuffer[255]; - -#define DETOUR_DECL_MEMBER9(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name, p6type, p6name, p7type, p7name, p8type, p8name, p9type, p9name) \ -class name##Class \ -{ \ -public: \ - ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name, p8type p8name, p9type p9name); \ - static ret (name##Class::* name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type, p8type, p9type); \ -}; \ -ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type, p8type, p9type) = NULL; \ -ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name, p8type p8name, p9type p9name) - DETOUR_DECL_MEMBER9(CBaseServer__ConnectClient, IClient*, netadr_t&, address, int, nProtocol, int, iChallenge, int, iClientChallenge, int, nAuthProtocol, const char *, pchName, const char *, pchPassword, const char *, pCookie, int, cbCookie) { if (nAuthProtocol != k_EAuthProtocolSteam) @@ -264,7 +248,10 @@ DETOUR_DECL_MEMBER9(CBaseServer__ConnectClient, IClient*, netadr_t&, address, in g_bEndAuthSessionOnRejectConnection = true; g_lastClientSteamID = CSteamID(ullSteamID); + g_lastcbAuthTicket = cbTicket; + g_lastAuthTicket = pvTicket; + // Validate steam ticket EBeginAuthSessionResult result = BeginAuthSession(pvTicket, cbTicket, g_lastClientSteamID); if (result != k_EBeginAuthSessionResultOK) { @@ -291,8 +278,10 @@ DETOUR_DECL_MEMBER9(CBaseServer__ConnectClient, IClient*, netadr_t&, address, in pchPassword = passwordBuffer; - g_bSuppressCheckChallengeType = true; - return DETOUR_MEMBER_CALL(CBaseServer__ConnectClient)(address, nProtocol, iChallenge, iClientChallenge, nAuthProtocol, pchName, pchPassword, pCookie, cbCookie); + g_bSuppressBeginAuthSession = true; + auto client = DETOUR_MEMBER_CALL(CBaseServer__ConnectClient)(address, nProtocol, iChallenge, iClientChallenge, nAuthProtocol, pchName, pchPassword, pCookie, cbCookie); + g_bSuppressBeginAuthSession = false; + return client; } DETOUR_DECL_MEMBER3(CBaseServer__RejectConnection, void, netadr_t &, address, int, iClientChallenge, const char *, pchReason) @@ -306,21 +295,6 @@ DETOUR_DECL_MEMBER3(CBaseServer__RejectConnection, void, netadr_t &, address, in return DETOUR_MEMBER_CALL(CBaseServer__RejectConnection)(address, iClientChallenge, pchReason); } -DETOUR_DECL_MEMBER7(CBaseServer__CheckChallengeType, bool, CBaseClient *, pClient, int, nUserID, netadr_t &, address, int, nAuthProtocol, const char *, pCookie, int, cbCookie, int, iClientChallenge) -{ - if (g_bSuppressCheckChallengeType) - { - g_bEndAuthSessionOnRejectConnection = false; - - SetSteamID(pClient, g_lastClientSteamID); - - g_bSuppressCheckChallengeType = false; - return true; - } else { - return DETOUR_MEMBER_CALL(CBaseServer__CheckChallengeType)(pClient, nUserID, address, nAuthProtocol, pCookie, cbCookie, iClientChallenge); - } -} - bool Connect::SDK_OnLoad(char *error, size_t maxlen, bool late) { char conf_error[255] = ""; @@ -381,6 +355,12 @@ bool Connect::SDK_OnLoad(char *error, size_t maxlen, bool late) return false; } + if (!g_pSteam3Server->m_pSteamGameServer) + { + snprintf(error, maxlen, "Unable to get Steam Game Server.\n"); + return false; + } + /* META_CONPRINTF("ISteamGameServer: %p\n", g_pSteam3Server->m_pSteamGameServer); META_CONPRINTF("ISteamUtils: %p\n", g_pSteam3Server->m_pSteamGameServerUtils); @@ -394,6 +374,12 @@ bool Connect::SDK_OnLoad(char *error, size_t maxlen, bool late) snprintf(error, maxlen, "Failed to find ISteamGameServer__BeginAuthSession offset.\n"); return false; } + SH_MANUALHOOK_RECONFIGURE(MHook_BeginAuthSession, g_nBeginAuthSessionOffset, 0, 0); + if (SH_ADD_MANUALHOOK(MHook_BeginAuthSession, g_pSteam3Server->m_pSteamGameServer, SH_STATIC(Hook_BeginAuthSession), true) == 0) + { + snprintf(error, maxlen, "Failed to setup ISteamGameServer__BeginAuthSession hook.\n"); + return false; + } if (!g_pGameConf->GetOffset("ISteamGameServer__EndAuthSession", &g_nEndAuthSessionOffset) || g_nEndAuthSessionOffset == 0) { @@ -404,8 +390,20 @@ bool Connect::SDK_OnLoad(char *error, size_t maxlen, bool late) CDetourManager::Init(g_pSM->GetScriptingEngine(), g_pGameConf); detourCBaseServer__ConnectClient = DETOUR_CREATE_MEMBER(CBaseServer__ConnectClient, "CBaseServer__ConnectClient"); + if (detourCBaseServer__ConnectClient == nullptr) + { + snprintf(error, maxlen, "Failed to create CBaseServer__ConnectClient detour.\n"); + return false; + } + detourCBaseServer__ConnectClient->EnableDetour(); + detourCBaseServer__RejectConnection = DETOUR_CREATE_MEMBER(CBaseServer__RejectConnection, "CBaseServer__RejectConnection"); - detourCBaseServer__CheckChallengeType = DETOUR_CREATE_MEMBER(CBaseServer__CheckChallengeType, "CBaseServer__CheckChallengeType"); + if (detourCBaseServer__RejectConnection == nullptr) + { + snprintf(error, maxlen, "Failed to create CBaseServer__RejectConnection detour.\n"); + return false; + } + detourCBaseServer__RejectConnection->EnableDetour(); g_pConnectForward = g_pForwards->CreateForward("OnClientPreConnectEx", ET_LowEvent, 5, NULL, Param_String, Param_String, Param_String, Param_String, Param_String); @@ -435,16 +433,12 @@ bool Connect::SDK_OnMetamodUnload(char *error, size_t maxlen) detourCBaseServer__ConnectClient->DisableDetour(); delete detourCBaseServer__ConnectClient; } + if (detourCBaseServer__RejectConnection) { detourCBaseServer__RejectConnection->DisableDetour(); delete detourCBaseServer__RejectConnection; } - if (detourCBaseServer__CheckChallengeType) - { - detourCBaseServer__CheckChallengeType->DisableDetour(); - delete detourCBaseServer__CheckChallengeType; - } return true; } diff --git a/extension/extension.h b/extension/extension.h index 5d6fdd3..e1d9466 100644 --- a/extension/extension.h +++ b/extension/extension.h @@ -100,4 +100,24 @@ public: //IConCommandBaseAccessor bool RegisterConCommandBase(ConCommandBase *pCommand); }; +#define DETOUR_DECL_MEMBER9(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name, p6type, p6name, p7type, p7name, p8type, p8name, p9type, p9name) \ +class name##Class \ +{ \ +public: \ + ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name, p8type p8name, p9type p9name); \ + static ret (name##Class::* name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type, p8type, p9type); \ +}; \ +ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type, p8type, p9type) = NULL; \ +ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name, p8type p8name, p9type p9name) + +struct mfpDetails { + void *addr; + intptr_t adjustor; + + void Init(void* addr, intptr_t adj = 0) { + this->addr = addr; + this->adjustor = adj; + } +}; + #endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_