[Auth] Use all 64 bits of the guid for fingerprints

This commit is contained in:
momo5502 2017-01-13 13:58:16 +01:00
parent e1aab7905b
commit 5c43859044
3 changed files with 30 additions and 13 deletions

View File

@ -165,7 +165,6 @@ namespace Components
// Parse the id // Parse the id
unsigned __int64 xuid = strtoull(steamId.data(), nullptr, 16); unsigned __int64 xuid = strtoull(steamId.data(), nullptr, 16);
unsigned int id = static_cast<unsigned int>(~0x110000100000000 & xuid);
SteamID guid; SteamID guid;
guid.Bits = xuid; guid.Bits = xuid;
@ -176,7 +175,7 @@ namespace Components
return; 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!"); Network::Send(address, "error\nXUID doesn't match the certificate!");
return; 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<unsigned __int64*>(const_cast<char*>(hash.data()));
}
return 0;
}
unsigned __int64 Auth::GetKeyHash()
{ {
Auth::LoadKey(); Auth::LoadKey();
return (Utils::Cryptography::JenkinsOneAtATime::Compute(Auth::GuidKey.getPublicKey())); return Auth::GetKeyHash(Auth::GuidKey.getPublicKey());
} }
void Auth::StoreKey() void Auth::StoreKey()
@ -385,6 +396,13 @@ namespace Components
Utils::Hook(0x6265F9, Auth::DirectConnectStub, HOOK_JUMP).install()->quick(); Utils::Hook(0x6265F9, Auth::DirectConnectStub, HOOK_JUMP).install()->quick();
Utils::Hook(0x41D3E3, Auth::SendConnectDataStub, HOOK_CALL).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<DWORD>(0x4D0D60, 0xC301B0);
// Guid command // Guid command
Command::Add("guid", [] (Command::Params*) Command::Add("guid", [] (Command::Params*)
{ {

View File

@ -14,7 +14,8 @@ namespace Components
static void StoreKey(); static void StoreKey();
static void LoadKey(bool force = false); 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 uint32_t GetSecurityLevel();
static void IncreaseSecurityLevel(uint32_t level, std::string command = ""); static void IncreaseSecurityLevel(uint32_t level, std::string command = "");

View File

@ -16,29 +16,27 @@ namespace Steam
SteamID User::GetSteamID() SteamID User::GetSteamID()
{ {
static unsigned int subId = 0; static unsigned __int64 idBits = 0;
SteamID id; SteamID id;
if (!subId) if (!idBits)
{ {
if (Components::Dedicated::IsEnabled() || Components::ZoneBuilder::IsEnabled()) // Dedi guid if (Components::Dedicated::IsEnabled() || Components::ZoneBuilder::IsEnabled()) // Dedi guid
{ {
subId = ~0xDED1CA7E; idBits = *reinterpret_cast<unsigned __int64*>("DEDICATE");
} }
else if (Components::Singleton::IsFirstInstance()) // ECDSA guid else if (Components::Singleton::IsFirstInstance()) // ECDSA guid
{ {
subId = Components::Auth::GetKeyHash(); idBits = Components::Auth::GetKeyHash();
} }
else // Random guid else // Random guid
{ {
subId = (Game::Sys_Milliseconds() + timeGetTime()); idBits = (static_cast<unsigned __int64>(Game::Sys_Milliseconds()) << 32) | timeGetTime();
} }
subId &= ~0x80000000; // Ensure it's positive
} }
id.Bits = 0x110000100000000 | subId; id.Bits = idBits;
return id; return id;
} }