Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Anti-Cheat Toolkit: stop cheaters easily!

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

  1. toyancsayan

    toyancsayan

    Joined:
    May 4, 2017
    Posts:
    5
    In our game we have a huge amount player who have ACTk version 1. If we update ACTk to v 2.0 , what can we do to keep our users' process ?
     
  2. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Please use obsolete CryptoKey property to migrate all your v1 data to the new v2 format.
    I'd suggest to set this property and read all your v1 prefs to automatically migrate them to the v2 format.
     
  3. abosaqr

    abosaqr

    Joined:
    Dec 4, 2016
    Posts:
    1
    Hi @codestage
    I tried to
    1. get code hash of my apk after building
    2. and get hash from external build hash

    but I got this error: look to the images

    Anti-Cheat Toolkit version: 2.1.2
    unity3d version: 2018.4.16f1



    1.
    1.jpg

    -------------------------------------------------------------------------
    --------------------------------------------------------------------------
    2.

    2.jpg
     
  4. codestage

    codestage

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

    Thank you for reporting this problem!

    Could you please drop me this information in a PM or via Contacts form:
    - android Player Settings screenshot (especially Publishing Settings, Other Settings
    - build window settings screenshot
    - full stacktrace of the error

    Thanks!
     
  5. evreng

    evreng

    Joined:
    Oct 24, 2014
    Posts:
    4
    Hi @codestage,

    To make it clearer:
    (In ObscuredPrefs.cs)
    private static string cryptoKeyObsolete = "<MyOldCrytoKey>";

    Then I used the method below:
    MigrateFromACTkV1("<MyObsduredPrefsKey>"));

    Is this the way to migrate old data to new?
    If not can you please specify which method to use?

    Thanks.
     
  6. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Something like that, yes, you also may just set the ObscuredPrefs.CryptoKey to your old key value and then just read all your existing v1 prefs as usual - they should migrate to the v2 format automatically.
     
  7. pistoleta

    pistoleta

    Joined:
    Sep 14, 2017
    Posts:
    539
    Hello, we are using Scriptable Objects for most of our game data. Is there any special approach to avoid this data to be tampered with or we simply should obfuscate the properties/variables inside of this Scriptable Objects we dont want the users to see?
     
  8. codestage

    codestage

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

    I'm sorry for a late reply, somehow totally missed your message!

    Feel free to use obscured types at scriptable objects as usual, it should work with same effect as for MonoBehaviours.
     
  9. OscarCybernetic

    OscarCybernetic

    Joined:
    Sep 12, 2018
    Posts:
    23
    Hi, we're trying to use the Anti-Cheat Toolkit along with Beebyte's Obfuscator, and it seems like the obfuscation makes the anti-cheat think that the game is cracked.

    We're having trouble figuring out why this is happening, so any insight would be greatly appreciated
     
  10. OscarCybernetic

    OscarCybernetic

    Joined:
    Sep 12, 2018
    Posts:
    23
    We took a closer look at our code and we found that we were providing the wrong path to our hash code file (oops).

    Everything seems to be working fine now!
     
    codestage likes this.
  11. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
  12. pistoleta

    pistoleta

    Joined:
    Sep 14, 2017
    Posts:
    539
    Hello there,
    I'm checking internet connection at the init of my app like this:
    Code (CSharp):
    1.   private void CheckStartUpInternetConnetion()
    2.     {
    3.         TimeCheatingDetector.GetOnlineTimeTask("https://google.com", TimeCheatingDetector.RequestMethod.Head)
    4.             .ContinueWithOnMainThread(task =>
    5.         {
    6.                 if (task.IsCanceled ||task.IsFaulted) {
    7.                     LogMgr.PrintError(LogsConfigSO.LogElem.gameInfo,"CheckStartInternetConnetion failed.");
    8.                     return;
    9.                 }
    10.  
    11.                 if (task.Result.success)
    12.                 {
    13.                     LogMgr.Print(LogsConfigSO.LogElem.gameInfo, "CheckInternetConnetion RESULT " + task.Result.success);
    14.                     secondsUTC = task.Result.onlineSecondsUtc;
    15.                 }
    16.                 else
    17.                 {
    18.                     LogMgr.PrintError(LogsConfigSO.LogElem.gameInfo,
    19.                         "CheckInternetConnetion RESULT " + task.Result.success);
    20.                     TimeManager.Instance.PauseCalendar(true);
    21.                     DialogManager.Instance.ShowFailedStartDialog();
    22.                 }
    23.         });
    When network's fine no problems, I get the CheckInternetConnetion RESULT TRUE log, but when I test with bad network (using Network Link Conditioner), I get this exception:

    unity Curl error 28: SSL connection timeout


    I'm trying to handle the exception's myself so I'm not sure why this appears in my console, do you have any idea why is showing up?

    Thanks!
     
  13. codestage

    codestage

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

    Thank you for reporting this problem.

    I suspect this error is printed from the UnityWebRequest internals and can't be controlled on our end, but I'd like to take a look at the full stack trace to be sure about this.

    Could you please share full stack trace for this error?
     
  14. pistoleta

    pistoleta

    Joined:
    Sep 14, 2017
    Posts:
    539
    Sorry I didnt see it before.
    I dont know why but there is not stack trace... just the [Error] Curl error 56: Receiving data failed with unitytls error code 1048578 error, im using console pro and the stack trace should show beneath but nothing, also if I click on copy selected stack and source the only thing I get is that message...
    Maybe this is something it just happens on editor.... I will keep you updated about it, I still have to test a lot on device.
    Thanks
     
    codestage likes this.
  15. pistoleta

    pistoleta

    Joined:
    Sep 14, 2017
    Posts:
    539
    I've been testing for a while on device and seems the mentioned error just happens in Editor.
    I have another doubt about the asset. You warn on the documentation : Avoid using detectors from code at the Awake phase.

    Does this apply to the following call?

    Code (CSharp):
    1. TimeCheatingDetector.OnlineTimeResult res =
    2.     await TimeCheatingDetector.GetOnlineTimeTask("https://google.com", TimeCheatingDetector.RequestMethod.Head);
    Im calling it from the awake phase, on editor seems to work well but im having problems on device, is the awake
    phase calling the problem?

    Thanks.
     
  16. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Thank you for letting me know, I can't do anything with this error anyways, since it does throws from the Unity internals and it doesn't falls to the try..catch.

    No, GetOnlineTimeTask is a static method which should work fine from the Awake as well.

    In general, it's more safe to avoid using detectors from awake phase due to the nature of the static instance gathering - it can be null at the Awake.
    But in your case, static instance is not involved and should not be a problem.
     
  17. Aurigan

    Aurigan

    Joined:
    Jun 30, 2013
    Posts:
    291
    Hi @codestage have been very happily using ACT for years now. First up, thank you for a great plugin and the very generous upgrade pricing.

    SO, now I'm using the v2 plugin and now ObscuredString.Get/SetEncrypted() require a key. Is the expectation that we store that key on our own webservers? Or if we're hard-coding it in the app code are there any best practices to recommend?
     
  18. codestage

    codestage

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

    Thank you for kind words!

    GetEncrypted has out char[] key argument - it gives you a key which was generated and used to encrypt value.
    You need to pass this key to the SetEncrypted method to be able to decrypt this value back.

    So please just store this key you get from GetEncrypted somewhere nearby to the encrypted value itself to be able to pass both encrypted value and crypto key to the SetEncrypted.
     
  19. Aurigan

    Aurigan

    Joined:
    Jun 30, 2013
    Posts:
    291
    The specific use-case for this was to encrypt save games prior to exporting them. This gives the player a way to save their game, outside of the app without being able to mess with it. The player could then load that save game on a different phone, or different user account, etc.

    The way ACTv2 now works I don't think there's a way to do this any more unless I tell the player the encryption key or attach it unencrypted to the exported text which sorta defeats the point of doing it in the first place. Am I missing something?
     
  20. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    @Aurigan this scenario is still possible, as usual - just export key along with data, and use it when importing data back.

    If you worried about passing keys with save data (which is relatively safe since keys can't be used without reverse-engineering your app) - you can encrypt exported data with your custom hardcoded \ serialized key using ObscuredString.Encrypt and decrypt it back with ObscuredString.Decrypt when importing saves data.
     
  21. Aurigan

    Aurigan

    Joined:
    Jun 30, 2013
    Posts:
    291
    Thanks for the reply, ended up stitching the key onto the end of the encrypted save like so:

    Code (CSharp):
    1. ObscuredString obscuredString = JsonSerializeGameState(g);
    2. var encrypted = obscuredString.GetEncrypted(out var key);
    3. var encodedBytes = Encoding.UTF8.GetBytes(encrypted.Concat(key).ToArray());
    I have no idea how most of the hacks on games are actually achieved so not sure if this is more or less secure than hardcoding in a key, feels like maybe it's a bit better!
     
  22. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Looks totally fine to me, it will work for most curious guys out there
     
  23. murat303

    murat303

    Joined:
    May 22, 2014
    Posts:
    38
    Hi, Can the system still be disabled as at this address? link1
    and we are using Obscured prefs, types and CodeHashGenerator. We check the hash at the entrance from firebase remote config. But somehow they get through it and they also change money in the game this way; link2
    Could they be disabling the anticheat completely?
     
  24. codestage

    codestage

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

    Anything can be done with your compiled code white it's not protected unfortunately.
    Please follow the "Code obfuscation and overall code protection notes" readme section to know how to prevent or at least make code patching much harder and time consuming process.

    CodeHashGenerator is best to use with online games so your server could compare hash from the player with genuine hash and properly react if hashes mismatch.

    It's still useful in offline games as well but only when you protect your code from reverse-engineering and patching.

    Also please try using ObscuredCheatingDetector in new game version in order to detect obscured types cheating attempts.
     
    Last edited: Apr 9, 2020
  25. murat303

    murat303

    Joined:
    May 22, 2014
    Posts:
    38
    I'm obfuscating Actk.runtime.dll with Obfuscator in the Assemblies section. This time nothing about the Anticheat is working.
     
  26. codestage

    codestage

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

    Are you compiling using IL2CPP?
    Also I wonder if it's possible to take a look at the cheated apk.
     
  27. murat303

    murat303

    Joined:
    May 22, 2014
    Posts:
    38
    Yes, I'm using IL2CPP, i'm sending apk from private chat
     
    codestage likes this.
  28. mrm83

    mrm83

    Joined:
    Nov 29, 2014
    Posts:
    345
    hi
    i currently have this, is it a problem that ABC is int instead of obsuredint??
    Code (CSharp):
    1. ObsuredInt abc = 10;
    2. public int ABC {
    3.   get { return abc; }
    4. }
     
  29. codestage

    codestage

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

    It's not a problem since backing field is using obscured type.
     
  30. jesusluvsyooh

    jesusluvsyooh

    Joined:
    Jan 10, 2012
    Posts:
    377
    Hi, Amazon Kindles not supported?
    They're basically a re-skin of android, and im pretty sure it used to work, but now i get a platform not supported message.
    I have posted some images showing the logs.

    https://www.dropbox.com/s/4ksp6pive2td581/IMG_6579.jpeg?dl=0
    https://www.dropbox.com/s/b0p12jg35skdze6/IMG_6580.jpeg?dl=0
    https://www.dropbox.com/s/6595r2v6y90kndt/IMG_6582.jpeg?dl=0

    Edit: Sent a 'conversation', i guess thats Unity forums PM's now.

    Edit: Red warning was fixed by disabling 'strip engine code' and a few other tweaks
    The platform not supported problem was solved, turns out it was a message for injection detection on IL2CPP (only needed for mono), rest still functions :D thanks for the help
     
    Last edited: May 12, 2020
  31. codestage

    codestage

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

    Looks like ACTk's native counterpart public APIs are get obfuscated or stripped from your build.
    Please make sure to add public APIs from AndroidNative.aar to the ignores to your native obfuscation or stripping tools (like ProGuardian).

    If you use ProGuardian, please refer to the Compatibility section of the readme and take a look at the "ProGuard notice".

    Please let me know if it will not help in PM or via Contacts form for fastest possible support.
     
    jesusluvsyooh likes this.
  32. toykanon

    toykanon

    Joined:
    Oct 19, 2016
    Posts:
    7
    Debugging connection is not working in Visual Studio 2017.
    Is the problem due to the anti cheat toolkit?
    Suggested solutions!

    Unity 2017.4.39
    Anti Cheat Toolkit: v2.2.2
     

    Attached Files:

  33. codestage

    codestage

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

    Does it reproduces if you remove ACTk or in new project?

    I believe ACTk should not cause such issues.
     
  34. drallcom3

    drallcom3

    Joined:
    Feb 12, 2017
    Posts:
    165
    I want to supply an encrypted JSON file somewhere in /assets. ACTk should then decrypt the content and it should work on any device with the same file.
    Is that possible with ACTk? How?

    ACTk is already great for Prefs and I'd like to extend it to JSON database files.
     
  35. codestage

    codestage

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

    Here is a scenario which should work:

    In Editor:
    - get original json as a string
    - encrypt it with ObscuredString.Encrypt or ObscuredByte.Encrypt and save result in file
    - put that file to the StreamingAssets for example

    At Runtime \ Play Mode:
    - read file from StreamingAssets
    - decrypt with ObscuredString.Decrypt \ ObscuredByte.Decrypt
    - deserialize or use as usual
     
  36. drallcom3

    drallcom3

    Joined:
    Feb 12, 2017
    Posts:
    165
    Thank you for the quick response.

    I was hoping it's that easy.
    What the recommended method of providing the client the key for decryption? Hardcode it in the class? Deliver it somehow online (which I would not prefer)?
    For ObscuredPrefs that's somehow automatically taken care of (thank god).
     
  37. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Best option here is to store it online but for offline games it's also fine to hide it in your build, for example, divide it into two parts - one part keep in code as a constant, and another part leave at the serialized field, set in the inspector. It will make it harder to reverse-engineer to reconstruct whole key.

    Code obfuscation in conjunction with IL2CPP will help a lot as well if applicable.

    Future ACTk updates will provide built-in tooling to work with encrypted binary files with additional tooling around it to make it easier to convert existing files to encrypted ones, this is on the internal tracker and planned for the implementation.
     
  38. toykanon

    toykanon

    Joined:
    Oct 19, 2016
    Posts:
    7
    Error when importing from an empty project
    Suggested solutions

    Cap 2020-05-28 17-43-28-665.png
     
  39. codestage

    codestage

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

    Could you please let me know what is your Unity version, scripting backend and scripting runtime version?
    Looks like you have some problems with Unity's .NET assemblies referencing (they should be auto-referenced by default).
     
  40. toykanon

    toykanon

    Joined:
    Oct 19, 2016
    Posts:
    7
    Unity Ver: 2017.4.40f1
    Setting Image
    Cap 2020-05-28 17-59-18-581.png
     
  41. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Please make sure you have not corrupted Unity installation and try to make full project re-import (close Unity, remove Library folder from your project and open project again).

    I just tried to reproduce and it works fine on my end, no compilation errors in console:
    upload_2020-5-28_12-4-57.png
     
  42. toykanon

    toykanon

    Joined:
    Oct 19, 2016
    Posts:
    7
    OK.
    Thank you.
     
    Last edited: May 29, 2020
  43. Hertzole

    Hertzole

    Joined:
    Jul 27, 2013
    Posts:
    423
    Hello!
    I'm currently in the process of upgrading an old project that has (I think) v1 and now I want to use v2. I'm sure this has been asked multiple times and I've been reading a bit but I just can't wrap my head around the upgrade process.

    To start with the obscured prefs: How would I make sure those are upgraded properly? Would it work automatically?
    Then with ObscuredStrings. I've used the old ObscuredString.EncryptDecrypt before but now it needs a key. From my understanding, you can generate this key now? But what key should I use for the old data and how can I make sure it loads the data with the old key and then saves with a new key if required? Is the old key the "crypto key" you can find in the prefs editor?

    Thanks :)
     
  44. codestage

    codestage

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

    Yes they will migrate from older v1 format automatically when you will read them first time in v2. You'll see console messages about migration when it will happen.

    To decrypt data saved with v1 ObscuredString please use ObscuredString.FromEncrypted(string, string) static API with default key and or use ObscuredString.EncryptDecrypt with default key from v1 ("4441").
     
  45. Hertzole

    Hertzole

    Joined:
    Jul 27, 2013
    Posts:
    423
    So I'm in the process of updating my code and would just like to ask for some advice on a few things.
    Do you know any way to detect if it's an old file or not? Right now the only idea I have is to try and decrypt it normally, read it as JSON and if the JSON read fails, try and decrypt it as an old file.
    As for storing the key, does it need to persist through sessions? If so, I'm not quite sure how I would save it. Are keys always a set number of characters that I can append it to my JSON save string and then remove it as to not mess up the JSON?
     
  46. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Yes, the only way to detect if it's encrypted with old version or not - is to validate decrypted data since ACTk does not add anything to the encrypted string and it does not know what the initial data was so it can't validate it on its side.

    If your data persists through sessions - key needs to persist as well, if it was used to encrypt that data.

    You're totally free how to store the key - feel free to append part of key to the saved data, store it online entirely or divide between code constant and serialized data in inspector - you choose here more suitable way for your needs.

    Storing key online would be the safest option here but it's secure enough for most cases to hide key somewhere in your app with your preferred method.
     
    Hertzole likes this.
  47. Hertzole

    Hertzole

    Joined:
    Jul 27, 2013
    Posts:
    423
    Thanks for the support! Just have to ask again, are the generated keys always a set length or can their length vary?
     
  48. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Key length is not fixed and you're free to use any length you would like to, but keep in mind keys longer than 56-bits will require you to specify you are using encryption in your app when releasing it to the AppStore. For more details about this please check "Apple Encryption Export Regulations compatibility" chapter of the readme.
     
    Hertzole likes this.
  49. Hertzole

    Hertzole

    Joined:
    Jul 27, 2013
    Posts:
    423
    Ah, I'm starting to understand now! I was a bit confused by the FromEncrypted function with the 'out' key variable, but it's all making sense now. Thanks for the help!
     
    codestage likes this.
  50. jmjd

    jmjd

    Joined:
    Nov 14, 2012
    Posts:
    50
    Hi @codestage, I've just upgraded ACTk from a pretty old version. I don't know the version exactly, but my best guess puts it around 1.3. Checksums were still being appended to the values. The MigrateFromACTkV1 doesn't account for this and is failing. Is there a way to migrate from such an old version?
     
    Last edited: Jun 8, 2020