diff --git a/src/Components/Modules/Auth.cpp b/src/Components/Modules/Auth.cpp index e1aac55d..f35b648b 100644 --- a/src/Components/Modules/Auth.cpp +++ b/src/Components/Modules/Auth.cpp @@ -165,7 +165,6 @@ namespace Components // Parse the id unsigned __int64 xuid = strtoull(steamId.data(), nullptr, 16); - unsigned int id = static_cast(~0x110000100000000 & xuid); SteamID guid; guid.Bits = xuid; @@ -176,7 +175,7 @@ namespace Components return; } - if ((xuid & 0xFFFFFFFF00000000) != 0x110000100000000 || id != (Utils::Cryptography::JenkinsOneAtATime::Compute(connectData.publickey()) & ~0x80000000)) + if (xuid != Auth::GetKeyHash(connectData.publickey())) { Network::Send(address, "error\nXUID doesn't match the certificate!"); return; @@ -220,10 +219,22 @@ namespace Components } } - unsigned int Auth::GetKeyHash() + unsigned __int64 Auth::GetKeyHash(std::string key) + { + std::string hash = Utils::Cryptography::SHA1::Compute(key); + + if (hash.size() >= 8) + { + return *reinterpret_cast(const_cast(hash.data())); + } + + return 0; + } + + unsigned __int64 Auth::GetKeyHash() { Auth::LoadKey(); - return (Utils::Cryptography::JenkinsOneAtATime::Compute(Auth::GuidKey.getPublicKey())); + return Auth::GetKeyHash(Auth::GuidKey.getPublicKey()); } void Auth::StoreKey() @@ -385,6 +396,13 @@ namespace Components Utils::Hook(0x6265F9, Auth::DirectConnectStub, HOOK_JUMP).install()->quick(); Utils::Hook(0x41D3E3, Auth::SendConnectDataStub, HOOK_CALL).install()->quick(); + // SteamIDs can only contain 31 bits of actual 'id' data. + // The other 33 bits are steam internal data like universe and so on. + // Using only 31 bits for fingerprints is pretty insecure. + // The function below verifies the integrity steam's part of the SteamID. + // Patching that check allows us to use 64 bit for fingerprints. + Utils::Hook::Set(0x4D0D60, 0xC301B0); + // Guid command Command::Add("guid", [] (Command::Params*) { diff --git a/src/Components/Modules/Auth.hpp b/src/Components/Modules/Auth.hpp index 0703eafd..8cd4bef2 100644 --- a/src/Components/Modules/Auth.hpp +++ b/src/Components/Modules/Auth.hpp @@ -14,7 +14,8 @@ namespace Components static void StoreKey(); static void LoadKey(bool force = false); - static unsigned int GetKeyHash(); + static unsigned __int64 GetKeyHash(); + static unsigned __int64 GetKeyHash(std::string key); static uint32_t GetSecurityLevel(); static void IncreaseSecurityLevel(uint32_t level, std::string command = ""); diff --git a/src/Steam/Interfaces/SteamUser.cpp b/src/Steam/Interfaces/SteamUser.cpp index 367dbf97..2e99b4de 100644 --- a/src/Steam/Interfaces/SteamUser.cpp +++ b/src/Steam/Interfaces/SteamUser.cpp @@ -16,29 +16,27 @@ namespace Steam SteamID User::GetSteamID() { - static unsigned int subId = 0; + static unsigned __int64 idBits = 0; SteamID id; - if (!subId) + if (!idBits) { if (Components::Dedicated::IsEnabled() || Components::ZoneBuilder::IsEnabled()) // Dedi guid { - subId = ~0xDED1CA7E; + idBits = *reinterpret_cast("DEDICATE"); } else if (Components::Singleton::IsFirstInstance()) // ECDSA guid { - subId = Components::Auth::GetKeyHash(); + idBits = Components::Auth::GetKeyHash(); } else // Random guid { - subId = (Game::Sys_Milliseconds() + timeGetTime()); + idBits = (static_cast(Game::Sys_Milliseconds()) << 32) | timeGetTime(); } - - subId &= ~0x80000000; // Ensure it's positive } - id.Bits = 0x110000100000000 | subId; + id.Bits = idBits; return id; }