Search Unity

Anti-Cheat Toolkit: stop cheaters easily!

Discussion in 'Assets and Asset Store' started by codestage, Aug 20, 2013.

  1. dwmarcuskim_

    dwmarcuskim_

    Joined:
    Sep 10, 2020
    Posts:
    4
    Hi,

    I am currently using Anti-Cheat Toolkit for a long time. But as ieslam mentioned, hackers of our game find out the method bound to detectionEvent, and NOP it to avoid reporting. So we are trying to use Obfuscator from beebyte to obfuscate the method names. I'm trying to attach method at detectionEvent at Start() function instead of using [SkipRename] attribute at obfuscator, but it seems it is impossible to change detectionEvent in code. Should I modify original code so that I can modify detectionEvent? or is there any other way to use obfuscator correctly, while obfuscating method's name?
     
  2. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Hey @dwmarcuskim_

    I'm not sure of what are the best practices here, did you tried to contact Obfuscator support to get most relevant support regarding its features and functionality?

    Also did you tried to look for any native protector for your platform to increase overall code patching complexity?
     
  3. dwmarcuskim_

    dwmarcuskim_

    Joined:
    Sep 10, 2020
    Posts:
    4
    According to Obfuscator doc, it recommends attaching method at Start() method, so that the name of method can be obfuscated while it keeps binding.
    Below is what obfuscator recommended.

    Code (CSharp):
    1.    public Button Button;
    2.    public void Start()
    3.    {
    4.       Button.onClick.AddListener(CodedClick);
    5.    }
    6.    //Assigned in the Start() method
    7.    private void CodedClick() //This gets obfuscated
    8.    {
    9.       Debug.Log("Coded Click");
    10.    }
    So I want to know if I can use method something like below.
    Code (CSharp):
    1. public override void Start() {
    2.         speedHackDetector.AddDetectionEvent(() => {
    3.             // Do something...
    4.         });
    5. }
    Since we currently have a lot of codes based on AntiCheat Toolkit, we are looking for the solution with least modification of our development stack..
     
  4. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Sure, feel free to add event listeners at Start phase both as lambda or method, listener should work fine in both ways.
     
    dwmarcuskim_ likes this.
  5. mrm83

    mrm83

    Joined:
    Nov 29, 2014
    Posts:
    345
    When would the hash generator return nothing?

    I am noticing that many users (android) have nothing returned for the hash generator.
     
  6. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Hey @mrm83 ,

    This is interesting observation, thank you for reporting it.
    I can't help much here though until I do reproduce this behavior on my end, but I didn't saw such behavior before..

    First thing I'd checked - logs from such devices to see if there are some errors at the managed or native ACTk counterpart.
    Second - I'd looked for anything common for such devices (OS version, manufacturer, etc.).

    Please let me know if you'll have any news about this case.
     
  7. Quast

    Quast

    Joined:
    Jul 5, 2015
    Posts:
    560
    Is there an option for automatically get protected? One click and all done.
     
  8. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Hey @Quast ,

    ACTk has multiple anti-cheat features which should be applied depending on your specific conditions - what cheat threats your game has, what game parts are sensitive to the cheating. E.g. you don't need wall hack detector if your game does not suffer from wall hacks, you don't need obscured types if you store all sensitive variables on server etc.

    That's why there is no simple button to apply all possible features at once. But each separate feature is pretty easy to set up, so feel free to take a look at the Readme to know more about ACTk features for your specific use case.
     
  9. mrm83

    mrm83

    Joined:
    Nov 29, 2014
    Posts:
    345
    Don't really see a pattern. But I do notice it return nothing and returning something for the same user.

    Also, when I say return nothing, I actually mean the callback not getting called.
     
    Last edited: Apr 26, 2021
  10. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Would be great to know more about this case since I'm still a bit puzzled with this one.
    Any additional information would help to increase chances for reproduction and fix:
    - Android OS version
    - Device vendor
    - How exactly you get hash, at which moment
    - ADB logs with any ACTk-related errors, warnings etc. would be best

    I've tried to reproduce it on my usual Android devices I'm using for internal tests but nothing at this moment - it does works without problems all the time.
     
  11. mrm83

    mrm83

    Joined:
    Nov 29, 2014
    Posts:
    345
    I dont have any of those info as there is no logging for them. I wasn't able to reproduce myself.

    I am calling the gethash on script Start().
    Alot of users with these missing hash callback were hackers, but some seem to be legit.

    Could it be failing due to use of emulators?
     
  12. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    It shouldn't be a problem for CodeHashGenerator since it works with usual Android file system which have to be emulated too, and it works fine in Android emulator for me..

    Again, can't be sure about anything here without actual errors logs from device.

    CodeHashGenerator still should invoke a HashGenerated event with a HashGeneratorResult.ErrorMessage property filled while having Success property == false, or at least produce some error logs from the native counterpart if anything goes wrong during hash calculation.

    I could make a special debug version for you with more additional logs if regular logs would be not enough to catch it, but can't get there until we have any logs at all first.
     
  13. mrm83

    mrm83

    Joined:
    Nov 29, 2014
    Posts:
    345
    Hmm.. if HashGenerated is guaranteed to be called then thats very weird, because it is inside the event that I send the hashes to the server to validate. And the server only received events that have something.

    If hash generation fails, would HashGeneratorResult.FileHashes be null?

    Because I am looping HashGeneratorResult.FileHashes once the callback is called expecting HashGeneratorResult.FileHashes to have something.

    That is the only thing I can think of that would cause me to not get the result because if it is null it would trigger an exception breaking early.
     
  14. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Yes, it will be null for sure in case of errors.
    I'd suggest checking Success property before checking FileHashes, e.g. just like in the example:

    Code (CSharp):
    1. private void OnGotHash(HashGeneratorResult result)
    2. {
    3.     if (!result.Success)
    4.     {
    5.         status = "Error: " + result.ErrorMessage;
    6.         return;
    7.     }
    8.    
    9.     // ... check result.SummaryHash / result.FileHashes
    10. }
     
  15. mrm83

    mrm83

    Joined:
    Nov 29, 2014
    Posts:
    345
    Found a few cases of error. But their user incident is so low I dont think it is the cause.
    vivo/vivo 1904/1904
    Android OS 11 / API-30 (RP1A.200720.012/eng.compil.20210313.014407)
    ARM64 FP ASIMD AES
    Code (CSharp):
    1. Managed Stack Trace:
    2.  
    3. CodeStage.AntiCheat.Genuine.CodeHash.HashGeneratorResult.get_FileHashes () (at <00000000000000000000000000000000>:0)
    4. GameController.Generated (CodeStage.AntiCheat.Genuine.CodeHash.HashGeneratorResult result) (at <00000000000000000000000000000000>:0)
    5. CodeStage.AntiCheat.Genuine.CodeHash.HashGeneratorResultHandler.Invoke (CodeStage.AntiCheat.Genuine.CodeHash.HashGeneratorResult result) (at <00000000000000000000000000000000>:0)
    6. CodeStage.AntiCheat.Genuine.CodeHash.CodeHashGenerator+<CalculationAwaiter>d__20.MoveNext () (at <00000000000000000000000000000000>:0)
    7. UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) (at <00000000000000000000000000000000>:0)
    OnePlus/HD1910/HD1910
    Android OS 7.1.2 / API-25 (N2G48H/rel.se.infra.20200730.150525)
    ARMv7 VFPv3 NEON VMH
    Code (CSharp):
    1. Managed Stack Trace:
    2. CodeStage.AntiCheat.Genuine.CodeHash.HashGeneratorResultHandler.Invoke (CodeStage.AntiCheat.Genuine.CodeHash.HashGeneratorResult result) (at <00000000000000000000000000000000>:0)
    3. CodeStage.AntiCheat.Genuine.CodeHash.CodeHashGenerator+<CalculationAwaiter>d__20.MoveNext () (at <00000000000000000000000000000000>:0)
    4. UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) (at <00000000000000000000000000000000>:0)
     
    codestage likes this.
  16. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Thanks!

    I've checked out and looks like first case is caused by accessing FileHashes while Success was false (buildHashes field will be null in such case and will produce null reference exception on FileHashes property access) - it should be more clear what went wrong by checking ErrorMessage.
    One blind guess - it was not successful because something did not work well at ARM64 - I'll try reproducing it on my end with same Android version on ARM64 and will get back with results.

    Second case looks strange, I see event invocation but don't see any further trace path, like event listener was destroyed at the same moment or something like this.
    No guesses here so far.
     
  17. mrm83

    mrm83

    Joined:
    Nov 29, 2014
    Posts:
    345
    Ok, the app was updated to check for error and then if there is an error, the error gets logged.

    Have not seen any error yet, but have already caught a few hacked apks without the hash =(
     
  18. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    I'd recommend increasing your source code protection in such case.
    Please take a look at the "Code obfuscation and overall code protection notes" readme chapter for more details.

    P.S. still trying to reproduce problems with ARM64 without success so far, will write down results when I'll complete my tests.
     
  19. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    @mrm83
    All after all, can't reproduce this on my end =(
    ARM64 build works perfectly fine on all arm64-compatible devices I had including virtual ones and running Android 11.
     
  20. mrm83

    mrm83

    Joined:
    Nov 29, 2014
    Posts:
    345
    The code is already obfuscated and is not built in mono.
     
  21. TXiongyi

    TXiongyi

    Joined:
    Feb 17, 2021
    Posts:
    3
    Hey ! The asset seems nice, can i use to protect my Unity client written with Lua (not C#) ?
     
  22. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Ah, it's more advanced cheaters you have there, then it's time to think about some external native code protectors to further increase effort needed for the code patching.
     
  23. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Hey Xiongyi,

    I've answered to your email, sorry for the delay, let me shamelessly copy-paste my reply here as well:

     
  24. mrm83

    mrm83

    Joined:
    Nov 29, 2014
    Posts:
    345
    First error message log.

    Something went wrong while trying to hash current APK: java.util.zip.ZipException: Not a zip archive
     
    codestage likes this.
  25. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    That's something interesting, thanks!
    Does this message has any stacktrace log attached?

    Though still no clue how to reproduce it so APK couldn't be read as JarFile..
    It's either something is wrong with paths or with apk itself. I'm using java.util.jar.JarFile to read APK contents, it's a standard way to do this and should work fine with any genuine non damaged \ non repackaged apk I believe.

    All I can offer right now - compile special debug version of the ACTk Android plugin so you could get more additional information from logs. Please let me know if it would work for you and I'll make it and send it to you.
     
    Last edited: May 5, 2021
  26. mrm83

    mrm83

    Joined:
    Nov 29, 2014
    Posts:
    345
    found a few more..

    [CodeHashGenerator ERROR] Something went wrong while trying to hash current APK: java.lang.SecurityException: SHA1 digest error for lib/arm64-v8a/libil2cpp.so

    [CodeHashGenerator ERROR] Something went wrong while trying to hash current APK: java.lang.SecurityException: SHA-256 digest error for classes.dex

    No stack trace.
     
  27. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Looks like a standard errors from JarFile when it does unpacks incorrectly repackaged apk.
    Those files were modified but their hashes in Jar were not updated accordingly. I'm not using SHA-256 in my hashing code so it's definitely comes from JarFile internals (jarsigner would produce same errors in such case).

    Also both libil2cpp.so and classes.dex are most often targets for the code patching which does adds to my assumption more possibility.

    Thus empty hash in such case more likely signalizes about corrupted apk after unlucky code patching attempt (looks like not all cheaters know how to properly repackage and resign patched apks).
     
  28. modernator24

    modernator24

    Joined:
    Apr 7, 2017
    Posts:
    202
    Lucky Patcher. Already countless illegally modified my game apk files are spreaded all around the world.
     
  29. modernator24

    modernator24

    Joined:
    Apr 7, 2017
    Posts:
    202
    Seems like it doesn't work properly on replacing int to ObscuredInt in Serialized class. I'm using serialized class to save player data as JSON, and when I replaced int to obscured, the data is reset to zero.

    Is this glitch or it just can't be used in this case?

    P.S. Nice asset. Actually, I bought Anti-Cheat Tool Kit v1 a few years ago but haven't used it, but seems like v1 is outdated and you decided to release the v2 separately, so I just bought it too.
     
  30. modernator24

    modernator24

    Joined:
    Apr 7, 2017
    Posts:
    202
    Probably I need some more explanation. I'm using File IO to create a JSON file to save player data. The JSON structure is defined as class player like this:

    Code (CSharp):
    1. [System.Serializable]
    2. public partial class PlayerData {
    3.     public int cash;
    4.     public int gold;
    5.     // and some others...
    6. }
    7.  
    I just replaced "public int cash" with "public ObscuredInt cash", the value is reset to zero. If I'm using it the wrong way, would appreciate how to use it in this case. Thanks.
     
  31. modernator24

    modernator24

    Joined:
    Apr 7, 2017
    Posts:
    202
    Code (CSharp):
    1. [System.Serializable]
    2. public partial class PlayerData: ISerializable {
    3.     public PlayerData() {}
    4.  
    5.     private PlayerData(SerializationInfo info, StreamingContext context) {
    6.         cash = (int) info.GetValue("cash", typeof(int));
    7.         gold = (int) info.GetValue("gold", typeof(int));
    8.     }
    9.  
    10.     public void GetObjectData(SerializationInfo info, StreamingContext context) {
    11.         info.AddValue("cash", cash);
    12.         info.AddValue("gold", gold);
    13.     }
    14. }
    Tried this, but no luck.
     
  32. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Hey @modernator24,

    Yes serialization of obscured types should be made using ISerializable or JsonConverter if you are using Newtonsoft Json for the serialization.
    Your ISerializable example looks fine and should work, what problem do you have with it?

    For more information please take a look at this post where I showed working ISerializable example, there is also link to another solution using JsonConverter as well:
    https://forum.unity.com/threads/anti-cheat-toolkit-stop-cheaters-easily.196578/page-6#post-1837510
     
  33. modernator24

    modernator24

    Joined:
    Apr 7, 2017
    Posts:
    202
    Well, I'm not using Netwonsoft's Json.NET, I'm using a built-in JSON extension called JsonUtility. My game is already in the service(over 3m+ users), and I want to minimize the changes as much as possible to prevent some unexpected or unwanted losing game progress. Isn't there a way to work with JsonUtility?
     
  34. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Not sure JsonUtility would respect ISerializable, but you could try using ISerializationCallbackReceiver instead.
     
  35. modernator24

    modernator24

    Joined:
    Apr 7, 2017
    Posts:
    202
    Well, that's kind of disappointing, because JsonUtility is an official and built-in JSON support by Unity and I always used it in any Unity project. I never tried Newtonsoft's JSON library because JsonUtility works fine without any problem until now.

    It's a quite expensive paid asset that costs 50 dollars, so shouldn't you try using it with the official library and see your asset works with it? I little bit disappointed because you told me you can't sure that works. In fact, I think there are many indie developers who don't even know the concept of serialization. Actually, I don't know that well either, so I don't know what you're asking me to try.
     
  36. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    No worries, I've just checked it for you and can tell JsonUtility does not supports standard ISerializable interface and you'll need to work with Unity-specific ISerializationCallbackReceiver interface instead but its super simple and straightforward.

    Here is a simple example of how it could be used with Obscured types:

    1. Use at your data class to convert between obscured and regular types.

    Code (CSharp):
    1. [Serializable]
    2. public class PlayerData : ISerializationCallbackReceiver
    3. {
    4.    public ObscuredInt Lives { get; set; }
    5.  
    6.    [SerializeField]
    7.    private int livesInJson;
    8.  
    9.    public void OnBeforeSerialize()
    10.    {
    11.       livesInJson = Lives;
    12.    }
    13.  
    14.    public void OnAfterDeserialize()
    15.    {
    16.       Lives = livesInJson;
    17.    }
    18. }
    19.  
    2. Use JsonUtility with your data class:

    Code (CSharp):
    1. public class JsonConvertor : MonoBehaviour
    2. {
    3.     private void Start()
    4.     {
    5.         var playerData = new PlayerData
    6.         {
    7.             Lives = 100
    8.         };
    9.  
    10.         var json = JsonUtility.ToJson(playerData);
    11.         Debug.Log(json);
    12.         playerData = JsonUtility.FromJson<PlayerData>(json);
    13.         Debug.Log(playerData.Lives);
    14.        
    15.         playerData.Lives = 50;
    16.        
    17.         json = JsonUtility.ToJson(playerData);
    18.         Debug.Log(json);
    19.         playerData = JsonUtility.FromJson<PlayerData>(json);
    20.         Debug.Log(playerData.Lives);
    21.  
    22.        // produces in console:
    23.        // {"livesInJson":100}
    24.        // 100
    25.        // {"livesInJson":50}
    26.        // 50
    27.     }
    28. }
    Hope this helps!
     
    milox777 likes this.
  37. modernator24

    modernator24

    Joined:
    Apr 7, 2017
    Posts:
    202
    Isn't there a way to keep the current existed value names? Like cash and gold, I don't want to change it. In your example, it needs two values: Lives and livesInJson. If I changed cash to something like cashInJson, previous data will be just disappeared because the key was changed from cash to cashInJson. Or, if I add something like

    Code (CSharp):
    1.  
    2. public int cash; // Original one
    3. public ObscuredInt Cash { get; set; }
    4.  
    5. public void OnBeforeSerialize()
    6. {
    7.     cash = Cash;
    8. }
    9.  
    10. public void OnAfterDeserialize()
    11. {
    12.     Cash = cash;
    13. }
    14.  
    then I have to change all my codes to use PlayerData.Cash, not PlayerData.cash. Not just I have to replace all scripts, all other keys are starting with lower case and that will lose consistency.
     
  38. modernator24

    modernator24

    Joined:
    Apr 7, 2017
    Posts:
    202
    And while waiting for your answers, I tried Newtonsoft's JSON.net.

    Just replacing serialize/deserialize current existing code seems fine, however when I add these new codes for support obscured types:

    Code (CSharp):
    1. public PlayerData() {}
    2.  
    3. private PlayerData(SerializationInfo info, StreamingContext context) {
    4.     cash = (int) info.GetValue("cash", typeof(int));
    5.     gold = (int) info.GetValue("gold", typeof(int));
    6. }
    7.  
    8. public void GetObjectData(SerializationInfo info, StreamingContext context) {
    9.     info.AddValue("cash", cash);
    10.     info.AddValue("gold", gold);
    11. }
    Suddenly I got a null reference in my serialized List object.

    Code (CSharp):
    1. [System.Serializable]
    2. public partial class PlayerData: ISerializable {
    3.     public int cash;
    4.     public int gold;
    5.     public List<PerkData> perks;
    6.     ...
    7. }
    The value perks are List of PerkData class, and it was worked before adding additional code for the obscured type support. However since I put the additional serialization code, it always returns null.

    I'm not sure what makes this behavior, maybe GetObjectData or constructor requires every single member variables to specify its own type if the function exists?
     
  39. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Feel free to keep original names for json and make new for code APIs or vice versa, this is how Unity's serialization works with ISerializationCallbackReceiver - you need to have serializable field of simple type Unity can serialize to be able to store it in json.

    Yes, this is how ISerializable works - you need to fill all fields in the constructor when new instance gets deserialized.
     
  40. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
  41. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Hey there,

    Anti-Cheat Toolkit 2.3.2 update is live with a few fixes to stabilize v2 before major v3 update.

    2.3.2
    - prepare for legacy .NET 3.5 support deprecation in upcoming 3.0 major release
    - fix inverted ACTK_US_EXPORT_COMPATIBLE logic
    - improve minor stuff

    Stay tuned for more news about Anti-Cheat Toolkit v3 and another announcements this summer! ^^
     
  42. mrm83

    mrm83

    Joined:
    Nov 29, 2014
    Posts:
    345
    Hi

    Noticed new error, safe to assume this is hack?

    [CodeHashGenerator ERROR] Something went wrong while trying to hash current APK: java.lang.SecurityException: META-INF/MANIFEST.MF has invalid digest for classes.dex in classes.dex
     
  43. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Hey @mrm83

    This is a good indicator of incorrect APK repackaging. Also it possibly could happen due to the APK corruption caused by storage errors or similar, but in such case hashes would not match anyways.

    Thank you a ton for reporting these, going to make a good use of these errors in a future updates!
     
  44. OceanViewGames

    OceanViewGames

    Joined:
    Dec 26, 2019
    Posts:
    19
    Hello, I have been using your anti-cheat toolkit in my projects and I am getting an issue.
    When I am setting strings, ints, doubles est. sometimes very rarely this can happen. resulting in the loss of saved data.

    Do you know what can cause this?

    Code (CSharp):
    1. ArgumentException: Destination array is not long enough to copy all the items in the collection. Check array index and length.
    2. System.ThrowHelper.ThrowArgumentException (System.ExceptionResource resource) (at <695d1cc93cca45069c528c15c9fdd749>:0)
    3. System.BitConverter.ToInt32 (System.Byte[] value, System.Int32 startIndex) (at <695d1cc93cca45069c528c15c9fdd749>:0)
    4. CodeStage.AntiCheat.Storage.ObscuredPrefs.DecryptValue[T] (System.String key, System.String encryptedKey, T defaultValue, System.String encryptedInput) (at Assets/Asset Packs/AntiCheatToolkit/Runtime/Scripts/Storage/Prefs/ObscuredPrefs.Routines.cs:335)
    5. CodeStage.AntiCheat.Storage.ObscuredPrefs.GetInt (System.String key, System.Int32 defaultValue) (at Assets/Asset Packs/AntiCheatToolkit/Runtime/Scripts/Storage/Prefs/ObscuredPrefs.cs:261)
    6. SaveData.SaveGetInt (System.String _key) (at Assets/Scripts/Save Loading/SaveData.cs:119)
    7. SplashScreen+<CheckForUpdates>d__4.MoveNext () (at Assets/Scripts/Screens/SplashScreen.cs:41)
    8. UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) (at <ef667cdc82bf4a4e911d1ddea9ff581d>:0)
    9. UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
    10. SplashScreen:Start() (at Assets/Scripts/Screens/SplashScreen.cs:25)
    Thank you.
     
  45. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Hey @OceanViewGames ,

    Somehow got a notification on your message only now, not sure why it was so delayed.
    Just to let others know, we already discussed and resolved this issue at the shiny new discord server ^^

    The cause was using different types for set and get, e.g. saving value with SetInt and getting it with GetLong.
    I've made user-fiendly error message there which will get to the new updates so it will reduce possible confusion in future.
     
  46. studiolumiere_unity

    studiolumiere_unity

    Joined:
    Apr 24, 2020
    Posts:
    21
    I'd like to know the value of the hacker's tamper attempts numeric value in the callback of [Obscured Cheating Detector].
     
  47. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Hey @studiolumiere_unity ,

    Not sure I get your request correctly. ObscuredCheatingDetector fires CheatDetected event only once - at the attempt detection and then stops working, thus it's always 1 tamper attempt.

    Please let me know if you have something to add to your request.
     
  48. studiolumiere_unity

    studiolumiere_unity

    Joined:
    Apr 24, 2020
    Posts:
    21
    For example, if a cracked hacker tries to change the game money 50 -> 1700, I want to get 1700 as a callback. (I'm not good at English, so I'm using Google Translate. Thank you for your patience.)
     
  49. studiolumiere_unity

    studiolumiere_unity

    Joined:
    Apr 24, 2020
    Posts:
    21
    Additional question : Does the Code Hash Generator "summary hash" value change when repackaging an apk for distribution to the store in UDP(Unity Distribution Portal)?
     
  50. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Ah, got you, thanks for the clarification!

    Currently, ObscuredCheatingDetector has only 1 detection event but it covers multiple different types, so it's not trivial to add all possible types cheating values to the callback.
    I'm adding this to the internal task tracker anyways, will see if something could be make here and to track a demand on such a feature as well.

    It has a high risk of change after any manipulation with apk including repackaging but generally it shouldn't change when binaries with code are kept genuine.

    Please let me know if you can confirm it changes after apk repackage for UDP.