using System.Collections.ObjectModel; using UnityEngine; namespace BetterAmongUs; class FileChecker { private static bool Enabled = true; private static readonly ReadOnlyCollection UnsupportedBepInExMods = new(new List { "TOHE", "YuAntiCheat" }); // Put BepInEx BepInPlugin name, not dll name here lol. private static readonly ReadOnlyCollection BannedBepInExMods = new(new List { "MalumMenu", "MalumMenu-Yu", "MalumMenuYu"/*, "AUnlocker" */}); // Put BepInEx BepInPlugin name, not dll name here lol. private static readonly ReadOnlyCollection KeyWordsInVersionInfo = new(new List { "Malum", "Sicko", "AUM" }); // Banned words for version text public static string UnauthorizedReason = string.Empty; public static List CheatTags = []; // For API report public static bool HasTrySpoofFriendCode = false; public static bool HasUnauthorizedFile = false; public static bool HasShownPopUp = false; private static float waitTime = 5f; // Set up if unauthorized files have been found. public static void UpdateUnauthorizedFiles() { if (GameStates.IsDev) { HasTrySpoofFriendCode = false; } if (Enabled == false) return; GameObject PlayButton = GameObject.Find("Main Buttons/PlayButton"); // Disable play button if (PlayButton != null) { if (EOSManager.Instance.userId == null || HasTrySpoofFriendCode) { PlayButton.GetComponent().enabled = false; GameObject.Find("Main Buttons/PlayButton/Inactive").GetComponent().color = Color.gray; } else { PlayButton.GetComponent().enabled = true; GameObject.Find("Main Buttons/PlayButton/Inactive").GetComponent().color = new Color(1.0f, 1.0f, 1.0f); } } // Unauthorized file or ban detected. if (HasUnauthorizedFile) { if (GameStates.IsInGame) { Utils.DisconnectSelf(OnlineMsg); } GameObject playOnlineButton = GameObject.Find("PlayOnlineButton"); if (playOnlineButton != null) { PassiveButton PassiveButtonComponent = playOnlineButton.GetComponent(); PlayOnlineButtonSprite PlayOnlineButtonSpriteComponent = playOnlineButton.GetComponent(); if (PassiveButtonComponent != null) { if (PassiveButtonComponent != null) PassiveButtonComponent.enabled = false; PlayOnlineButtonSpriteComponent?.SetGreyscale(); } } GameObject SignInStatus = GameObject.Find("SignInStatus"); if (SignInStatus != null) { SignInStatusComponent SignInStatusCom = SignInStatus.GetComponent(); SignInStatusCom?.SetOffline(); GameObject.Find("Account_CTA")?.SetActive(false); GameObject.Find("AccountTab/GameHeader/LeftSide/FriendCode")?.SetActive(false); if (GameObject.Find("Stats_CTA") != null) GameObject.Find("Stats_CTA").transform.position = new Vector2(1.7741f, -0.2442f); } SoundManager.instance?.ChangeMusicVolume(0); return; } if (EOSManager.Instance.editAccountUsername.gameObject.active || EOSManager.Instance.askToMergeAccount.gameObject.active) { HasTrySpoofFriendCode = true; } if (GameStates.IsInGame && GameStates.IsLobby) { waitTime -= Time.deltaTime; if (waitTime <= 0) { CheckIfUnauthorizedFiles(); waitTime = 5f; } } else { waitTime = 5f; } } private static readonly string UnauthorizedTextDetectedMsg = "Unauthorized {0} Detected"; private static readonly string UnauthorizedFileMsg = "Unauthorized Game Files Detected"; private static readonly string OnlineMsg = "Online access has been temporarily disabled!"; private static readonly string UnsupportedBepInExModMsg = "Unsupported BepInEx Mod Detected"; private static readonly string BannedBepInExModMsg = "Unauthorized BepInEx Mod Detected"; // Check if there's any unauthorized files. public static bool CheckIfUnauthorizedFiles() { if (Enabled == false) return false; // Get user info for later use with API. string ClientUserName = string.Empty; string ClientFriendCode = string.Empty; string ClientPUIDHash = string.Empty; if (!GameStates.IsInGame) { ClientUserName = GameObject.Find("AccountTab")?.GetComponent()?.userName.text; ClientFriendCode = EOSManager.Instance.friendCode; ClientPUIDHash = Utils.GetHashPuid(EOSManager.Instance.ProductUserId); } else { if (PlayerControl.LocalPlayer?.Data != null) { ClientUserName = PlayerControl.LocalPlayer.Data.PlayerName; ClientFriendCode = PlayerControl.LocalPlayer.Data.FriendCode; ClientPUIDHash = Utils.GetHashPuid(PlayerControl.LocalPlayer); } } if (GameStates.IsDev) { Enabled = false; return false; } // Check for Banned BepInEx Mods foreach (var bannedMod in BannedBepInExMods) { if (IsBepInExModLoaded(bannedMod)) { if (!HasUnauthorizedFile) UnauthorizedReason = BannedBepInExModMsg; if (!CheatTags.Contains($"{bannedMod}-BepInEx")) CheatTags.Add($"{bannedMod}-BepInEx"); HasUnauthorizedFile = true; } } // Check for Unsupported BepInEx Mods foreach (var unsupportedMod in UnsupportedBepInExMods) { if (IsBepInExModLoaded(unsupportedMod)) { if (!HasUnauthorizedFile) UnauthorizedReason = UnsupportedBepInExModMsg; HasUnauthorizedFile = true; } } // Check for version.dll if (File.Exists(Path.Combine(Environment.CurrentDirectory, "version.dll"))) { string versiondll = "'version.dll'"; if (!HasUnauthorizedFile) UnauthorizedReason = string.Format(UnauthorizedTextDetectedMsg, versiondll); if (!CheatTags.Contains("version.dll")) CheatTags.Add("version.dll"); HasUnauthorizedFile = true; } // Check for banned words in VersionInfo display. Aka check cheat developers ego foreach (var WordInVersionInfo in KeyWordsInVersionInfo) { if (!GameStates.IsInGame) { if (UnityEngine.Object.FindFirstObjectByType().text.text.ToLower().Contains(WordInVersionInfo.ToLower())) { if (!HasUnauthorizedFile) UnauthorizedReason = UnauthorizedFileMsg; if (!CheatTags.Contains($"{WordInVersionInfo}-VersionInfo")) CheatTags.Add($"{WordInVersionInfo}-VersionInfo"); HasUnauthorizedFile = true; } } else { if (UnityEngine.Object.FindFirstObjectByType().text.text.ToLower().Contains(WordInVersionInfo.ToLower())) { if (!HasUnauthorizedFile) UnauthorizedReason = UnauthorizedFileMsg; if (!CheatTags.Contains($"{WordInVersionInfo}-VersionInfo")) CheatTags.Add($"{WordInVersionInfo}-VersionInfo"); HasUnauthorizedFile = true; } } } // Check for Sicko leftover files if (File.Exists(Path.Combine(Environment.CurrentDirectory, "sicko-settings.json")) || File.Exists(Path.Combine(Environment.CurrentDirectory, "sicko-log.txt")) || File.Exists(Path.Combine(Environment.CurrentDirectory, "sicko-prev-log.txt")) || File.Exists(Path.Combine(Environment.CurrentDirectory, "sicko-config"))) { if (!HasUnauthorizedFile) UnauthorizedReason = UnauthorizedFileMsg; if (!CheatTags.Contains("Sicko-Menu-Files")) CheatTags.Add("Sicko-Menu-Files"); HasUnauthorizedFile = true; } // Check for AUM leftover files if (File.Exists(Path.Combine(Environment.CurrentDirectory, "settings.json")) || File.Exists(Path.Combine(Environment.CurrentDirectory, "aum-log.txt")) || File.Exists(Path.Combine(Environment.CurrentDirectory, "aum-prev-log.txt"))) { if (!HasUnauthorizedFile) UnauthorizedReason = UnauthorizedFileMsg; if (!CheatTags.Contains("AUM-Menu-Files")) CheatTags.Add("AUM-Menu-Files"); HasUnauthorizedFile = true; } // ----------- Unused Until API support is added! ----------- // Combine Player information and Tags string tagsAsString = string.Join(" - ", CheatTags); string playerInfo = $"{ClientUserName}.{ClientFriendCode}.{ClientPUIDHash} - {tagsAsString}"; // If Detection goes off send this information to the API database! // ---------------------------------------------------------- return HasUnauthorizedFile; } // Get all loaded BepInEx mods and check if one is on the ban list. private static bool IsBepInExModLoaded(string modName) { foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { if (assembly.FullName.Contains(modName, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } }