private void OnGotHash(HashGeneratorResult result) { if (!result.Success) { this.callback(null); } else { this.callback(result.SummaryHash); } }
private void OnGotHash(HashGeneratorResult result) { if (!result.Success) { status = "Error: " + result.ErrorMessage; return; } var filePath = Path.Combine(Path.GetFullPath(Application.dataPath + @"\..\"), FileName); if (!File.Exists(filePath)) { status = "No super secret file found, you're cheater!\n" + filePath; return; } var allBytes = File.ReadAllBytes(filePath); var allChars = BytesToUnicodeChars(allBytes); var decrypted = ObscuredString.Decrypt(allChars, StringKey); var separatorIndex = decrypted.IndexOf(Separator, StringComparison.InvariantCulture); if (separatorIndex == -1) { status = "Super secret file is corrupted, you're cheater!"; return; } var whitelistedHashes = decrypted.Split(new[] { Separator }, StringSplitOptions.RemoveEmptyEntries); var originalSummaryHash = whitelistedHashes[0]; // compare summary hashes first if (originalSummaryHash != result.SummaryHash) { // check all files against whitelisted hashes if summary differs // (it can differ if some files are absent due to build separation) for (var i = 1; i < whitelistedHashes.Length; i++) { var hash = whitelistedHashes[i]; if (!result.HasFileHash(hash)) { status = "Code hash differs, you're cheater!\nSummary hashes:\n" + originalSummaryHash + "\n" + result.SummaryHash + "\nWhitelisted hashes count: " + whitelistedHashes.Length; return; } } } status = "All fine!"; }
private void OnGotHash(HashGeneratorResult result) { if (!result.Success) { status = "Error: " + result.ErrorMessage; return; } var resultingHash = result.CodeHash; var filePath = Path.Combine(Path.GetFullPath(Application.dataPath + @"\..\"), FileName); if (!File.Exists(filePath)) { status = "No super secret file found, you're cheater!\n" + filePath; return; } var allBytes = File.ReadAllBytes(filePath); var allChars = BytesToUnicodeChars(allBytes); var decrypted = ObscuredString.Decrypt(allChars, StringKey); var separatorIndex = decrypted.IndexOf(Separator, StringComparison.InvariantCulture); if (separatorIndex == -1) { status = "Super secret file is corrupted, you're cheater!"; return; } var buildHash = decrypted.Substring(0, separatorIndex); var fileHash = decrypted.Substring(separatorIndex + SeparatorLength); var currentFileHash = GetHash(buildHash + HashSalt); if (currentFileHash != fileHash) { status = "Super secret file is corrupted, you're cheater!"; return; } if (buildHash != resultingHash) { status = "Code hash differs, you're cheater!\n" + resultingHash + "\n" + buildHash; return; } status = "All fine!"; }
private void OnHashGenerated(HashGeneratorResult result) { LastResult = result; CodeHashGenerator.HashGenerated -= OnHashGenerated; if (result.Success) { // Here you can upload your hashes to the server to make a validation check on the server side and punish cheater with server logic. // // This is a preferred use case since cheater will have to figure out proper hash using // packets sniffing (https packets harder to sniff) or debugging first to fake it on the client side requiring more // skills and motivation from cheater. // // check SummaryHash first and if it differs (it can if your runtime build has only portion of the initial build you made in Unity) // check FileHashes if SummaryHash differs to see if runtime build have any new hashes - it will indicate build is altered // // UploadHashes(result.SummaryHash, result.FileHashes); // Or you may compare it with hardcoded hashes if you did save them somewhere in the build previously. // // This is less preferred way since cheater can still try to hack your client-side validation check to make it always pass. // Anyways, this is better than nothing and will require some additional time from cheater reducing overall motivation to hack your game. // In case implementing it fully on the client side, make sure to compile IL2CPP build and use code // obfuscation which runs integrated into the Unity build process so hashing will happen AFTER code obfuscation. // If obfuscation will happen after hashing it will change code hash and you'll need to re-calculate it // using Tools > Code Stage > Anti-Cheat Toolkit > Calculate external build hash feature. // // if (!CompareHashes(result.SummaryHash, result.FileHashes)) // { // Debug.Log("You patched my code, cheater!"); // } } else { Debug.LogError("Oh, something went wrong while getting the hash!\n" + "Error message: " + result.ErrorMessage); } }
protected virtual void Complete(HashGeneratorResult result) { Result = result; IsBusy = false; }