Search Unity

Anti-Cheat Toolkit: stop cheaters easily!

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

  1. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    @guzzo thanks for reporting it anyways, I'll try to reproduce it.
     
  2. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    I've managed to reproduce it, huge thanks for reporting it once again!
    Unfortunately fix will be available only after I get back from 2-week vacation, now I just have no time gap to fill it with a fix.

    Please keep using old version until fix will out if you still have any issues after update.
     
    Aurigan likes this.
  3. Aurigan

    Aurigan

    Joined:
    Jun 30, 2013
    Posts:
    291
    Enjoy the vacation - and thanks again for the solid plugin and support - ACT is one of the very few I'll just auto-install in any new game project :)
     
    codestage likes this.
  4. aDazeHill

    aDazeHill

    Joined:
    Aug 11, 2015
    Posts:
    2
    Hello, do you know of any way to use reflexion (FieldInfo.SetField more specifically) with Anti Cheat? Maybe a logic involving a shell or something?

    EDIT: nevermind, this works:
    Code (CSharp):
    1. ObscuredInt val = (int)rawVal;
    2. info.SetValue(instance, val);
     
    Last edited: Aug 1, 2016
  5. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Hey, @aDazeHill , I'm not sure I got your question correctly.
    Reflection should work with ACTk as usual.
     
  6. aDazeHill

    aDazeHill

    Joined:
    Aug 11, 2015
    Posts:
    2
    I'm not sure either, all my reflection scripts stopped worked after migrating my fields to ObscuredFields, but finally found a quick workaround, weird that info.SetValue(instance, (ObscuredInt)val); gives me a "Cannot Cast" error, but this works.

    Precision: GetField works just right, only SetField gave me problems
     
  7. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Thanks I'll take a look.
     
  8. Fattie

    Fattie

    Joined:
    Jul 5, 2012
    Posts:
    476
    Hi Dmitriy !

    I haven't updated for awhile .... just wondering if you fixed this minor warning:

    Assets/CodeStage/AntiCheatToolkit/Scripts/ObscuredTypes/ObscuredString.cs(113,51): warning CS0618: `UnityEngine.Random.seed' is obsolete: `Deprecated. Use InitState() function or Random.state property instead.'​

    cheers!
     
  9. codestage

    codestage

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

    Yep, it was fixed (now I use Random.Range) at 1.5.1.0 I believe.
     
    Fattie likes this.
  10. bakira

    bakira

    Joined:
    Jul 1, 2016
    Posts:
    19
    Hi. I have two questions regarding this plugin.

    I read that ObscuredType have simple symmetric encryption method (or algorithm).
    Q1.1. In following methods, which method is the safest method?
    1) ObscuredType (ObscuredInt, ObscuredString, ...) 's Encrypt ()
    2) ObscuredType (ObscuredInt, ObscuredString, ...) 's GetEncrypted()
    3) ObscuredPrefs 's SetInt() / SetString() , ...
    Q1.2. Q1.1's 1) & 2) use same encryption method?
    Q2. If Question 1.1 's answer is number 3,
    can I use these encryption methods (or algorithm) to just encrypt my variables not save to playerprefs ?
    Because I use other saving method.

    Thank you :)
     
    Last edited: Aug 25, 2016
  11. bakira

    bakira

    Joined:
    Jul 1, 2016
    Posts:
    19
    Hi. I have one more question.
    Can I use ObscuredInt like following code?

    public ObscuredInt Money {get; private set;}
     
  12. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Hey, @bakira!

    They all are using same encryption mechanics under the hood.
    But all of them are different things for different goals.

    I'm not sure what you wish to achieve, but here are few hints for each case you asking about:
    1) used to encrypt your data, to store it somewhere later, outside the obscured var
    2) used to get raw encrypted data of the obscured variable, to store it somewhere and load it back to the variable later
    3) used to store your data between sessions in prefs, it's a secure analogue of the PlayerPrefs on steroids

    Yes.
     
  13. GloriaVictis

    GloriaVictis

    Joined:
    Sep 1, 2016
    Posts:
    133
    [ACTk] Injection Detector: has properly configured Detection Event in the inspector, but still get started with Action callback. Both Action and Detection Event will be called on detection. Are you sure you wish to do this?
    (Filename: C:/buildslave/unity/build/artifacts/generated/common/runtime/UnityEngineDebugBindings.gen.cpp Line: 42)

    Cheat detected UnityEngine.Cloud.Analytics.Util, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
    (Filename: C:/buildslave/unity/build/artifacts/generated/common/runtime/UnityEngineDebugBindings.gen.cpp Line: 42)

    NullReferenceException: Object reference not set to an instance of an object
    at CodeStage.AntiCheat.Detectors.InjectionDetector.OnCheatingDetected (System.String cause) [0x00000] in <filename unknown>:0
    at CodeStage.AntiCheat.Detectors.InjectionDetector.StartDetectionInternal (UnityEngine.Events.UnityAction`1 callback) [0x00000] in <filename unknown>:0
    at CodeStage.AntiCheat.Detectors.InjectionDetector.StartDetection (UnityEngine.Events.UnityAction`1 callback) [0x00000] in <filename unknown>:0
    at CheatsDetectors.Start () [0x00000] in <filename unknown>:0


    New Analytics doesn't like Injection Detecion.
     
    codestage likes this.
  14. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Hey, Gloria!

    Thanks for reporting this, this is a known issue and new analytics will be added to the default white list in next update.
    For now just add it to your custom whitelist as described in readme.

    Feel free to contact me via PM or email for any further assistance!

    BTW, looks like you have 2 callbacks for the InjectionDetector (one is configured at the inspector's event, second one is get passed to the StartDetection() function. It's recommended to have only 1 of this to avoid duplicate detection reaction.
     
    GloriaVictis likes this.
  15. fugogugo

    fugogugo

    Joined:
    Jun 18, 2013
    Posts:
    12
    Hi!

    I've emailed you about the problem with Anti Cheat Toolkit and android marshmellow permission
    basically it will generate READ_PHONE_STATE permission because there's SystemInfo.deviceUniqueIdentifier call in your code.
    please help me with this :)
     
  16. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Hey, @fugogugo !

    As mentioned in Readme, you may remove this permission if you're not using ObscuredPrefs' lock to device feature.
    Just add ACTK_PREVENT_READ_PHONE_STATE conditional compilation symbol if you wish to remove it.
    See readme's troubleshooting section for more details on this.
     
  17. cabanel

    cabanel

    Joined:
    Sep 22, 2014
    Posts:
    68
    Hello, I update my project with Anti-Cheat Toolkit from the 5.0.2 to 5.3, when I run the app on your phone, the app closes immediately after I deleted the Object DetectorCheat works well, can you help me ?
     
  18. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Hey, @cabanel!

    What do you see in the logs?
    And what is DetectorCeat object? Did you meant ObscuredCheatingDetector?

    Feel free to PM me here or write to email for direct support.
     
  19. cabanel

    cabanel

    Joined:
    Sep 22, 2014
    Posts:
    68
    Injction detect!
     
  20. codestage

    codestage

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

    It looks like you have false positives from some assembly appeared in Unity 5.3 (though ACTk should be fully compatible with all default assemblies from 5.3).
    Just follow the readme's section "How to fill user-defined whitelist" on how to add assembly to the custom whitelist.
     
  21. dmax9

    dmax9

    Joined:
    Jun 10, 2015
    Posts:
    6
    Hello,

    After importing PlayMaker actions (v 1.5.2.1) into PlayMaker (v 1.8.3) I got below error:

     
  22. codestage

    codestage

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

    This is a known issue and will be fixed in next update.
    For now, just change code at Line 19 of the
    Assets/CodeStage/AntiCheatToolkit/Scripts/PlayMaker/Actions/ObscuredPrefs/ObscuredPrefsSetNewCryptoKey.cs

    from

    Code (CSharp):
    1. if (!newCryptoKey.IsNone && !newCryptoKey.Value.Equals("")) ObscuredPrefs.SetNewCryptoKey(newCryptoKey.Value);
    to

    Code (CSharp):
    1. if (!newCryptoKey.IsNone && !newCryptoKey.Value.Equals("")) ObscuredPrefs.CryptoKey = newCryptoKey.Value;
     
    dmax9 likes this.
  23. DanielFF

    DanielFF

    Joined:
    Aug 29, 2012
    Posts:
    41
    Hi,
    When updload to itunes we need check "yes" on cryptography question ?

    Thank you!
     
  24. mcmorry

    mcmorry

    Joined:
    Dec 2, 2012
    Posts:
    580
    I already went through the approval process on itunes using Anti-Cheat Toolkit and was not needed to check yes.
     
  25. codestage

    codestage

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

    In short, you don't need to set it to yes unless you're using long crypto keys. Default keys are short enough to avoid declaring cryptography.

    For more details, see readme's Tips & Tricks section.

    Thanks for sharing your experience and congrats with approve!
     
  26. mrm83

    mrm83

    Joined:
    Nov 29, 2014
    Posts:
    345
    I am using this but I am noticing hacking with game guardian.

    I am not sure if I am doing it correctly, but I added this asset near the end of my project so I did not alter all my existing values to obscured values.

    The method I am using is in a separate class, created a bunch of dummy obsucredints
    ie:
    ObscuredInt hak = 1;
    ObscuredInt hak2= 2;
    ObscuredInt hak3 = 3;
    ObscuredInt hak4 = 4;
    ObscuredInt hak5 = 5;
    ObscuredInt hak6 = 6;
    ObscuredInt hak7 = 7;
    ObscuredInt hak8 = 8;
    ObscuredInt hak9 = 9;

    ObscuredInt[] hacks;

    hacks = new ObscuredInt[99999];
    for (int i = 0; i < hacks.Length; i++) {
    hacks = i + 1;
    }

    And then from start method, i have
    ObscuredCheatingDetector.StartDetection (OnFingHackerDetected);

    But the detection doesn't seem to always work.

    is my method flawed? If i only care about ints between 1 - 99999, then this class's declared variables should cover it right?
     
    Last edited: Nov 6, 2016
  27. codestage

    codestage

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

    I'm totally confused by the code you provided.
    What are you trying to achieve?

    Feel free to write me directly over PM or email to get quickier direct support. I'd like to help you as much as I can.
     
  28. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Hey guys!

    Glad to let you know tiny ACTk update to the 1.5.2.2 version is live on the store.
    It's mostly bugfix\stability update.

    1.5.2.2
    - updated InjectionDetector whitelist up to the Unity 5.5
    - fixed possible data corruption leading to false positives in Obscured types
    - updated third-party integration packages to the new APIs
    - improved compatibility with Unity 5.5
    - reduced chance of the wrong encrypted pref detection at the prefs editor
     
    mcmorry likes this.
  29. Simon_says

    Simon_says

    Joined:
    Oct 19, 2013
    Posts:
    141
    How would I store unsigned long using ObscuredPrefs? I see there is support for uint but not ulong.
     
  30. codestage

    codestage

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

    You're the first one who asked about this type.
    It will be added to the next update.

    For now, just use BitConverter.GetBytes(UInt64) to get bytes from your ulong value andsave those bytes using ObscuredPrefs.SetByteArray().

    Similar, use ObscuredPrefs.GetByteArray() to read your ulong bytes back, and convert them to ulong using BitConverter.ToUInt64().
     
    Simon_says likes this.
  31. Wadjey

    Wadjey

    Joined:
    Feb 4, 2015
    Posts:
    244
    Hi,
    Please to add support of optional arguments like void myFunction(ObscuredBool myVar = false){}
     
  32. codestage

    codestage

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

    Unfortunately it's impossible since Obscured types do not meet the specification requirements due to their "calculate at runtime" nature. They can't be constant.

    According to the MSDN:

    A default value must be one of the following types of expressions:
    • a constant expression;
    • an expression of the form new ValType(), where ValType is a value type, such as an enum or a struct;
    • an expression of the form default(ValType), where ValType is a value type.
     
  33. Simon_says

    Simon_says

    Joined:
    Oct 19, 2013
    Posts:
    141
    This code throws ArgumentException: Destination array is not long enough to copy all the items in the collection. Check array index and length.
    Code (CSharp):
    1.     private static ulong GetULong(string key)
    2.     {
    3.         var bytes = ObscuredPrefs.GetByteArray(key);
    4.         return BitConverter.ToUInt64(bytes, 0);
    5.     }
     
  34. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Could you please post a full stack log to let me take a look where exactly this exception happens?

    I just tried this code and it prints "5" without any exceptions:

    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3. using CodeStage.AntiCheat.ObscuredTypes;
    4.  
    5. public class ObscuredPrefsBug : MonoBehaviour
    6. {
    7.     private void Start()
    8.     {
    9.         SetULong("1", 5ul);
    10.         Debug.Log(GetULong("1"));
    11.     }
    12.  
    13.     private void SetULong(string key, ulong val)
    14.     {
    15.         var bytes = BitConverter.GetBytes(val);
    16.         ObscuredPrefs.SetByteArray(key, bytes);
    17.     }
    18.  
    19.     private ulong GetULong(string key)
    20.     {
    21.         var bytes = ObscuredPrefs.GetByteArray(key);
    22.         return BitConverter.ToUInt64(bytes, 0);
    23.     }
    24. }
     
  35. Simon_says

    Simon_says

    Joined:
    Oct 19, 2013
    Posts:
    141
    I can't reproduce it anymore, getting another exception now but it only happens if I try to get the ulong before it has been set in the prefs.

    ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
    Parameter name: startIndex
    System.BitConverter.PutBytes (System.Byte* dst, System.Byte[] src, Int32 start_index, Int32 count) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System/BitConverter.cs:176)
    System.BitConverter.ToUInt64 (System.Byte[] value, Int32 startIndex) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System/BitConverter.cs:267)
    ObscuredPrefsBug.GetULong (System.String key) (at Assets/Scripts/ObscuredPrefsBug.cs:23)
    ObscuredPrefsBug.Start () (at Assets/Scripts/ObscuredPrefsBug.cs:9)


    Code (CSharp):
    1.  
    2. void Start()
    3. {
    4.      Debug.Log(GetULong("1"));
    5.      SetULong("1", 5ul);
    6.      Debug.Log(GetULong("1"));
    7. }
    8.  
     
  36. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Ah, that's because ObscuredPrefs.GetByteArray will return System.Byte[0] if key is not found and BitConverter can't convert it obviously.

    You may check length of the array returned by the GetByteArray:

    Code (CSharp):
    1. private ulong GetULong(string key)
    2. {
    3.     var bytes = ObscuredPrefs.GetByteArray(key);
    4.     if (bytes != null && bytes.Length > 0)
    5.     {
    6.         return BitConverter.ToUInt64(bytes, 0);
    7.     }
    8.  
    9.     return 0;
    10. }
    Or just if key exists before trying to read it:
    Code (CSharp):
    1. private ulong GetULong(string key)
    2. {
    3.     if (ObscuredPrefs.HasKey(key))
    4.     {
    5.         var bytes = ObscuredPrefs.GetByteArray(key);
    6.         return BitConverter.ToUInt64(bytes, 0);
    7.     }
    8.  
    9.     return 0;
    10. }
     
    Simon_says likes this.
  37. Simon_says

    Simon_says

    Joined:
    Oct 19, 2013
    Posts:
    141
    I have managed to reproduce that exception that I got before in the editor. It happened when I built my game for Android and ran it on my phone. Here is full stack trace of the error: cmd_2016-12-16_02-32-41.png
     
  38. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Looking at your error, it looks like a same error you've posted for the case when you're trying to read a key before writing there anything.
    Did you tried to add an additional checks to your GetULong I've suggested in previous post?
     
  39. Simon_says

    Simon_says

    Joined:
    Oct 19, 2013
    Posts:
    141
    Yes, all works fine in the editor, but I've just noticed that I have cleared my PlayerPrefs there and on device no. I have now did the same on phone and there is no exception, so I guess the old player pref was present(which was uint and not ulong) which passed the null check.
     
    codestage likes this.
  40. rrsimon

    rrsimon

    Joined:
    Apr 16, 2012
    Posts:
    27
    Hello @Dmitriy-Yukhanov ,

    I'm reaching out because I don't think we've been using your ObscuredPrefs properly and would like your opinion on our current situation.

    First of all, we have been using using ObscuredPrefs.SetNewCryptoKey(SystemInfo.deviceUniqueIdentifier) (oops?) to save all of our player's progress into one big XML string ObscuredPrefs.SetString("PROFILES", saveXML).

    Now, for some reason, it looks like when we update our Store Build with an Xcode or TestFlight build, the SystemInfo.deviceUniqueIdentifier changes for our devices; resulting in a loss of progress. We have tried using the same Unity and Xcode version as our AppStore version and the UUID still changes.

    Another interesting detail is if I reinstall the AppStore version over our upgrade, it will reload our original save like if the upgrade never happened. This means that the KEY still exists in PlayerPrefs and VALUE gets unencrypted properly.

    I have tried messing around with emergencyMode and readForeignSaves but I don't think these features were meant for our particular case. Can you think of some other way I can retrieve the previous save? I am currently digging through our code to see if the previous UUID was stored somewhere so I can load it and use it to load a previous save but I still haven't found a solution. Any help would be appreciated.

    Thanks,
    Simon
     
  41. Simon_says

    Simon_says

    Joined:
    Oct 19, 2013
    Posts:
    141
    I think there is some bug with unsigned obscured types. When using ObscuredUInt or ObscuredULong as variable types, they are partially serialized in the editor. By that I mean that I can see the variable name in the inspector, but can't put any value on it because there is no textbox field generated next to the variable name. It works fine when using just uint or ulong. Also I'm using Unity 5.5.0p2.
     
  42. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Hey, @rrsimon !

    Such code will lock saves to the specified device ID. But this id may and more likely will change on modern iOS. And it's not the best way of locking to device, since in case of device id change you'll be not able to decrypt stuff back without getting the previous device ID.

    Actually ObscuredPrefs already have such feature (Lock to device) and for iOS it uses UnityEngine.iOS.Device.vendorIdentifier if possible and fall backs to the SystemInfo.deviceUniqueIdentifier under the hood.

    Also, built-in lock to device feature allows to restore saves if device id changes. That's where emergencyMode \ readForeignSaves will help.

    When deviceUniqueIdentifier changed for iOS first time, I did a some kind of research about possible ways of getting unique IDs for iOS devices and I found that UnityEngine.iOS.Device.vendorIdentifier should be more solid than deviceUniqueIdentifier, so I'd suggest to use it instead.

    In your particular case, I'm not sure it's possible to get previous device id somewhere from the new version with new device id.
    You need to know an encryption key to be able to decrypt saves, there is no way to work this around it seems =(
     
    rrsimon likes this.
  43. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Hey, @Simon_says !

    There is just no support for the ObscuredUInt and ObscuredULong for inspectors in current version.
    Since you're asking, I'll add it with next update!
     
  44. Simon_says

    Simon_says

    Joined:
    Oct 19, 2013
    Posts:
    141
    @Dmitriy-Yukhanov can you also add support for ObscuredPrefs.SetDecimal? I tried to do it using the same way ulong was implemented but BitConverter doesn't support decimal types.
     
  45. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    @Simon_says hey, I'll implement it, thanks for the feature request!
     
  46. MikeHergaarden

    MikeHergaarden

    Joined:
    Mar 9, 2008
    Posts:
    1,027
    Any known issues with using ACT and Obfuscator in 5.5?
    ACT suddenly detects incorrect obscuredtype cheating since we added Obfuscator. How should we setup these 2 packages together properly?

    Edit: Solved - my fault!
     
    Last edited: Jan 17, 2017
    codestage likes this.
  47. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Thanks for reporting this, @MikeHergaarden!
    I've replied to your email with additional details.

    For everyone else: this is a bug, and it will be fixed, I'll share more details as soon as I'll have them.
     
  48. MikeHergaarden

    MikeHergaarden

    Joined:
    Mar 9, 2008
    Posts:
    1,027
    Solved & our fault!
    Looks like the prefab serialization did not like an out of date ObscuredFloat. Simply editing the value in the prefab once solved the issue. Thanks for the support.
     
    codestage likes this.
  49. Simon_says

    Simon_says

    Joined:
    Oct 19, 2013
    Posts:
    141
    Any ETA about it?)
     
  50. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    I'll release it this week hopefully (and it will take about one week to pass a review).
     
    Simon_says likes this.