Search Unity

Anti-Cheat Toolkit: stop cheaters easily!

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

  1. denlee0710

    denlee0710

    Joined:
    Mar 9, 2015
    Posts:
    36
    Hi Dmitriy,

    I've run into a problem with serializing/deserializing obscured types with JSON. We are using MiniJson.

    Decimal and bool obscured types are serialized as string since they failed the "is" checks for decimal/bool types. For example for an ObscuredInt, I have to either do an explicit cast back to an int before serialization, or do an explicit parse conversion from string to int, before I can assign it back to the ObscuredInt field.

    This is less of a problem for none-collections. But for obscured types inside a collection, for example List<ObscuredInt> or Dictionary<string, ObscuredInt>, I'll have to manually reconstruct the collection into one using regular types with a foreach loop. This is not an optimal solution as I have to manually do this for every collection with an obscured type that I need to serialize.

    Do you have a suggestion on how to solve this? I thought about adding is checks for obscured types into MiniJson, but I rather avoid modifying the plugin.

    Thanks,
    Dennis
     
  2. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
  3. denlee0710

    denlee0710

    Joined:
    Mar 9, 2015
    Posts:
    36
    Hi Dimtriy,

    I supposed it's limitation of MiniJson where obscured types are serialized as a string. This is their code snippet:

    Code (CSharp):
    1. void SerializeOther(object value) {
    2.                 // NOTE: decimals lose precision during serialization.
    3.                 // They always have, I'm just letting you know.
    4.                 // Previously floats and doubles lost precision too.
    5.                 if (value is float) {
    6.                     builder.Append(((float) value).ToString("R"));
    7.                 } else if (value is int
    8.                     || value is uint
    9.                     || value is long
    10.                     || value is sbyte
    11.                     || value is byte
    12.                     || value is short
    13.                     || value is ushort
    14.                     || value is ulong) {
    15.                     builder.Append(value);
    16.                 } else if (value is double
    17.                     || value is decimal) {
    18.                     builder.Append(Convert.ToDouble(value).ToString("R"));
    19.                 } else {
    20.                     SerializeString(value.ToString());
    21.                 }
    22.             }
    Since user-defined conversions are not considered in 'is' checks, obscured typed failed the checks a serializes as string. What do you suggest we do short of adding all obscured types into the 'is' checks?

    I would rather avoid having to cast obscured types to regular types manually before serialization, since sometimes the obscured types are inside a container, and we want to avoid writing custom code for every such instance.
     
  4. denlee0710

    denlee0710

    Joined:
    Mar 9, 2015
    Posts:
    36
    Hi,

    After using linq and converting obscuredInt collections to regular collection, deserialization still fails because the deserializer output all integer types as int64, which is not convertible to ObscuredInt. So I wrote kind of a dirty solution in case anyone else run into the same problem.

    Sample code:
    Code (CSharp):
    1.     Dictionary<WeaponID,  ObscuredInt> weaponInventory = new Dictionary<string, ObscuredInt> ();
    2.     string saveString;
    3.  
    4.     public void Save() {
    5.                                            
    6.         MiniJSON.Json.Serialize(weaponInventory);
    7.  
    8.         /* Save your save string here */
    9.     }
    10.    
    11.     public void Load() {
    12.         /* Load your save string here*/
    13.  
    14.         Dictionary<string, object> jsonDict = MiniJSON.Json.Deserialize(saveString) as Dictionary<string, object>;
    15.  
    16.                             // The ConvertJSONDict<T1, T2> method loop through dictionary and use
    17.                             // System.Convert.ChangeType to convert key and value to requested type.
    18.                             // The problem was that int64(parser output for integer types) are not convertable to ObscuredInt,
    19.                             // so we convert to int first then cast it to ObscuredInt
    20.         weaponInventory = ConvertJSONDict<WeaponID, int>(jsonDict).ToDictionary(item => item.Key, item => (ObscuredInt)item.Value);
    21.  
    22.         // This was breaking
    23.         //weaponInventory = ConvertJSONDict<WeaponID, ObscuredInt>(jsonDict);
    24.     }
     
    codestage likes this.
  5. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Yeah, I'd suggest to add obscured types to "is" checks as that serializer doesn't respect ISerializable.

    Thanks for sharing, it looks nice, not too dirty =)

    P.S. There is ObscuredLong which should be compatible with int64.
     
  6. edu101

    edu101

    Joined:
    Apr 13, 2015
    Posts:
    3
    Hi, there are some way to save/load encripted types to a file in windows phone or/and android. I think it is a good way to lock a phone to know when it is a first installation, for free gift in first time install.
     
  7. codestage

    codestage

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

    Sure, you may use GetEncrypted \ SetEncrypted methods to work with raw encrypted data in order to save and load values to any custom storage.
     
  8. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Just use DeviceID property to get or override current device ID.
     
  9. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    487
    Hi, Dmitry!

    Does your plugin protect from so called “replay attacks” on ObscuredPrefs?

    For example, I've got 100 coins (virtual currency), deduce corresponding key/value in prefs file, and copy'n'save it. Then I spend coins on weapons (virtual goods), go back to editing prefs and restore previously saved value for known key. So I've got both weapons and initial amount of coins.
     
  10. codestage

    codestage

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

    No, ACTk can't resist such attacks ATM since it uses PlayerPrefs under the hood and it can't control all own PlayerPrefs in a reliable way to get a signature of all own prefs.
    It will be done in future updates though, when I introduce ObscuredPrefsFile (not a final name) which will use own file under the hood which I'll be able to sign and re-encrypt after key change. There will be more freedom to make saved data even more secure.

    For now, I'd suggest to manually hash your data.
    Example:
    save money
    save items count
    save hash of (money + items count)
    ---
    read money
    read items count
    read hash and check it still valid

    You may use xxHash included in ACTk, it's a very fast high quality hash (https://code.google.com/p/xxhash).
     
    hopeful likes this.
  11. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    487
    Files are not that portable among different mobile and web platforms. Have you considered saving such a “file” like a single large entry in protected PlayerPrefs?

    Now we partially utilize this approach, but it's preferably to find well tested and accurately implemented third party plugin, with great support and customers base.

    Is it implemented in a way compatible with (or in terms of) standard .NET HMAC primitive?

    How is current version of ObscuredPrefs implemented? Does it use heavy encryption like DES/AES or even asymmetric one?
     
  12. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Unfortunately PlayerPrefs are not really friendly to large data. WebPlayer (and probably WebGL) have size limit for example.
    PlayerPrefs performance vary too much on different platforms and it's not as good as own binary file performance.

    I also considered using separate prefs record to store there all ObscuredPrefs values, but tests showed it's too complicated when there are lot of records made to the prefs - single pref value can't handle such big records on some platforms which require separation of the record with all obscured keys adding complexity and making it all more bug prone way.

    I see. Currently I can't offer such solution out of the box unfortunately, but it's matter of future updates.

    Feel free to check it youself: https://github.com/noricube/xxHashSharp
    But as I can see, it doesn't compatible with HMAC, it's a separate class which returns a hash of incoming byte[] buffer and uses only primitive types inside.

    It uses fastest possible symmetric xor and xxHash for data consistency checks.
     
  13. toto2003

    toto2003

    Joined:
    Sep 22, 2010
    Posts:
    528
  14. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
  15. ayalasan

    ayalasan

    Joined:
    Dec 10, 2012
    Posts:
    16
    Hello Dmitriy,

    We are using an old version of ACT (I believe it's v1.3.2.1 since that's the latest entry on Changelog.txt) for a very big project which is over a year's old. Now it's a bit tricky for us to re-import every plugin and retest this big beast considering stability issues which could arise.

    Now, coming to the point, we have been given google's featuring opportunity, for which we need to remove the READ_PHONE_STATE permission which somehow appears in the apk (even though it's not on the AndroidManifest.xml).

    I have surfed a bit and discovered that ACT's SystemInfo.deviceUniqueIdentifier could be the one triggering this dependency.

    We rely heavily on ObscuredPrefs for our game, so I am wondering if by removing all SystemInfo.deviceUniqueIdentifier lines from ObscuredPrefs.cs would we still have a good protection?

    I can see it in two places:

    #if !UNITY_FLASH
    private static string GetDeviceIDDeprecated()
    {
    // return SystemInfo.deviceUniqueIdentifier;
    return "";
    }
    #endif

    private static string GetDeviceID()
    {
    string deviceID = "";
    #if UNITY_IPHONE
    deviceID = iPhone.vendorIdentifier;
    #endif
    // if (String.IsNullOrEmpty(deviceID)) deviceID = SystemInfo.deviceUniqueIdentifier;
    return CalculateChecksum(deviceID);
    }
    #endif

    Considering our situation what would you suggest? Updating to latest ACT anyways? Would commenting this two lines (and returning empty string in the first) be a valid workaround for fixing this issue?

    Many thanks in advance,
     
  16. codestage

    codestage

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

    I'm sorry for a late reply. I'm currently far away from my PC (till June, 23) and have not so much time for support as usual.

    Anyway, yeah, you're totally right, READ_PHONE_STATE permission can be removed by commenting out the SystemInfo.deviceUniqueIdentifier lines.

    Be warned though: ObscuredPrefs uses it for the device lock feature and if you lock your saves to device (off by default), all those saves will be lost in case of commenting out
    deviceUniqueIdentifier (device ID will change and saves will be considered foreign).

    Please, let me know if you still have any questions.
     
    ayalasan likes this.
  17. ayalasan

    ayalasan

    Joined:
    Dec 10, 2012
    Posts:
    16
    Thanks Dmitriy!

    Just to be clear, then if we are not using the device lock feature (I dont think I have changed any default values) then having an invalid device ID will cause no conflict at all with save games nor protection? is that right?
     
  18. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Hey, yep, this is true.
     
  19. Groucho

    Groucho

    Joined:
    Dec 24, 2009
    Posts:
    73
    I'm trying to use ObscuredPrefs from a script in my Plugins folder, but I get a "type or namespace name `CodeStage' could not be found" error when I add #using CodeStage.AntiCheat.ObscuredTypes; to the top of my script. Is there a way to be able to use ObscuredPrefs from a script in Plugins?

    FWIW, I tried moving the CodeStage folder to the Plugins folder. That gave a bunch of UnityEditor errors when I tried to build for Windows. So, I put the CodeStage folder back where it belongs.

    Thanks!
     
  20. codestage

    codestage

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

    I'm sorry for a late reply, just went back from vacation.

    As stated in "Special Folders and Script Compilation Order" docs,

    The basic rule is that anything that will be compiled in a phase after the current one cannot be referenced. Anything that is compiled in the current phase or an earlier phase is fully available.

    The phases of compilation are as follows:
    Phase 1: Runtime scripts in folders called Standard Assets, Pro Standard Assets and Plugins.
    Phase 2: Editor scripts in folders called Standard Assets/Editor, Pro Standard Assets/Editor and Plugins/Editor.
    Phase 3: All other scripts that are not inside a folder called Editor.
    Phase 4: All remaining scripts (ie, the ones that are inside a folder called Editor).


    So, you can't access classes in the Plugins (Phase 1) from the usual code (Phase 3).

    ACTk designed as a loose scripts asset and it compiles in Phase 3+4, so it can't be accessed from the code in the Plugins folder.

    Though, you still may place ACTk scripts in the Plugins folder (except the Editor scripts - they can't be put in Plugins folder) by hand.

    Let me shamelessly quote my answer to the similar question from my PMs:

    you may try this solution:
    - move whole CodeStage/AntiCheatToolkit folder to the Plugins
    - create new CodeStage/AntiCheatToolkit folder outside the Plugins
    - create Editor subfolder, so you have CodeStage/AntiCheatToolkit/Editor
    - move the Plugins/CodeStage/AntiCheatToolkit/Editor/Scripts folder to the newly created one, so you have:
    CodeStage/AntiCheatToolkit/Editor/Scripts

    It should work. The point is you'll keep Plugins/AntiCheatToolkit/Editor/ServiceData in place which is needed for the correct injectiondetector work.


    Please, let me know if it works for you.
     
  21. Groucho

    Groucho

    Joined:
    Dec 24, 2009
    Posts:
    73
    No problem. Thanks a bunch for the reply. I'll see what I can do!
     
  22. Rithy-Jim

    Rithy-Jim

    Joined:
    Nov 10, 2012
    Posts:
    19
    I try SpeedHackDetector with GameKiller on android and the SpeedHackDetector can not detect the slow hack. Need help.
     
  23. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
  24. Rithy-Jim

    Rithy-Jim

    Joined:
    Nov 10, 2012
    Posts:
    19
    Thank for reply @Dmitriy Yukhanov .
    When will you release the new update with detect root privileges hack?
     
    Last edited: Jun 27, 2015
  25. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    @Rithy-Jim it's a matter of the future updates, since I have lots of tasks in TODO with higher priority I'd not expect it in near month or two.
     
    Rithy-Jim likes this.
  26. TogoMango

    TogoMango

    Joined:
    Oct 8, 2014
    Posts:
    5
    Hi. Dmitriy.

    I'm using your asset by playmaker well.

    and I imported playmaker actions of ACT from ACT folder.

    but there are only actions about playerpref n wallHack n SpeedHack.

    When i want detect values that is not playerpref.(ex. int, float)
    How to detect those?

    must i change values like tutorial video? (int >> Obscured int)
     
  27. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Hey, @TogoMango !
    Playmaker doesn't allow to add custom types, so obscured vars are not supported there.

    As stated in readme:
    Basic Obscured types for PM are not currently supported. PM doesn’t allow to add new variables types. But it’s possible to integrate them by hands. There is example and explanation by kreischweide.
     
  28. Rithy-Jim

    Rithy-Jim

    Joined:
    Nov 10, 2012
    Posts:
    19
    Hi Dmitriy,
    I detect speed hack by getting time from "time.nist.gov". In my script, I get "startTime" and every 5 second I get "nextTime" and then I get duration by (nextTime-startTime). If duration > falstTime(ex : 5 or 6 seconds) I fire event speed hack. Would you suggest me if I'm doing the right or wrong way? And sometime I get time error with 0001:01:01 00:00:00
     
  29. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Hi, @Rithy-Jim !
    Time server usage is one of the options I'm going to implement for SpeedHack detector. You're doing it right in general. Just don't forget to add some delta or errors correction (sometimes you need few secs to get answer from servers and sometimes you'll get no answer at all).
     
    Rithy-Jim likes this.
  30. codestage

    codestage

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

    I've noticed Unity 5.1 has few new assemblies which are not on the default whitelist yet (it wasn't updated since Unity 5.0).
    Nearest ACTk update will include them in the default whitelist.

    However, you don't need to wait for the update. You may add them to the custom whitelist right now (see readme.pdf for details on how to add new allowed assemblies to the custom whitelist).

    Here is the list:

    Mono.Cecil.Mdb.dll
    Mono.Cecil.Pdb.dll
    Unity.UNetWeaver.dll
    from
    C:\Program Files\Unity 5.1\Editor\Data\Managed

    UnityEngine.Networking.dll
    from
    C:\Program Files\Unity 5.1\Editor\Data\UnityExtensions\Unity\Networking

    UnityEngine.Analytics.dll
    from
    C:\Program Files\Unity 5.1\Editor\Data\UnityExtensions\Unity\UnityAnalytics
     
  31. codestage

    codestage

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

    Just a small announcement.
    As some of you already might knew, cheaters can find obscured variables using "unknown value" or similar search and then freeze them for example.
    Despite the fact ObscuredCheatingDetector still detects freezing (at least Cheat Enfine's one), the value itself still remains freezed, which is not very nice and obviously undesired in most cases.

    So, to completely prevent it, I'm going to include new API method for all Obscured vars in the upcoming update: RandomizeCryptoKey().
    Quote from docs:

    Allows to change current crypto key to the new random value and re-encrypt variable using it.
    Use it for extra protection against 'unknown value' search.
    Just call it sometimes when your variable doesn't change to fool the cheater.

    Using that method you now may force obscured variable to change its internal encrypted value, keeping original value unchanged. Just call this sometimes and when cheater will search "unchanged value", actual value will be changed, preventing the finding of variable at all.

    Note: current encryption key of the variable will be changed to the random value after calling this method.

    Note#2: Cheat Engine's Unrandomizer doesn't hurt.
     
    Last edited: Jul 13, 2015
    guzzo and hopeful like this.
  32. codestage

    codestage

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

    I'm here with another pack of good news.
    Upcoming ACTk update will also include new features for the WallHackDetector in addition to the current functionality (detection of the walking through the walls):
    • submodule which detects shooting through the walls
    • submodule which detects different kinds of wireframe wall hacking (when your walls and other objects look like this: http://i.imgur.com/HhizbXm.png)
    First one is already made, second one is on the late prototyping stage, both are tested on few native cheating tools which patch Unity Player.

    Thus, WallHackDetector will be able to detect all or at least most common cheating methods called "wall hacking".
     
    hopeful and nxrighthere like this.
  33. renguiyou

    renguiyou

    Joined:
    Aug 3, 2015
    Posts:
    2
    你好,我刚下了这个,很棒的工具,thanks
     
  34. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    很高兴你喜欢它!
     
  35. warde

    warde

    Joined:
    Sep 10, 2012
    Posts:
    7
    Speed hack detection is not working on Android. What I have done is simply build the TestScene from the plugin.
    I was using a tool named "shaobingxiugaiqi" to cheat. Speed up to x100, the cube was rotating so fast, but the GUI still saying that speed hack detection was false, sad... :(

    Edit:
    I was using 1.4.1
     

    Attached Files:

  36. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
  37. elmar1028

    elmar1028

    Joined:
    Nov 21, 2013
    Posts:
    2,359
    Hi,

    Sorry for a possible duplicate question, but can ACT obscure functions? Or is there a workaround for this?

    Thanks in advance,

    Elmar
     
  38. codestage

    codestage

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

    No, ACTk doesn't have any obfuscation functionality at this moment. It might appear in future though.
    For now, I'd suggest to use third-party obfuscators which support Unity, like Eazfuscator and similar.
     
  39. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Hey everyone!
    I'm with great news here.
    ACTk is 65% off at the Asset Store now! Best moment to obtain a copy if you didn't already.
    New update is almost ready, polishing things and updating docs, going to relese it after sale. It will bring to you the full power of the WallHack Detector which now able to detect all kinds of wall hacking (walk through, shoot through, see through) on all platforms and numerous of other fixes and improvements. Yay! =)
     
  40. alteregogi

    alteregogi

    Joined:
    Apr 13, 2015
    Posts:
    8
    Hello,

    is Anti Cheat Compatible with Easy Save 2 ? because ACT using a custom variable type, i already ask the ES2 on their forum about this and they said the ES2 can add custom Variable type, here the forum link .

    the ES2 code to save and load data is like this
    Code (CSharp):
    1. // Without ACT
    2.  
    3. public int myInt = 5;
    4.  
    5. ES2.Save(myInt, "savefile.sv?tag=myInt");
    6. int loadMyInt = ES2.Load<int>("myInt");
    7.  
    8. Debug.Log(loadMyInt);
    9.  
    10. // it should like this if using ACT
    11.  
    12. public ObscuredInt myInt = 5;
    13.  
    14. ES2.Save(myInt, "savefile.sv?tag=myInt");
    15. ObscuredInt loadMyInt = ES2.Load<ObscuredInt>("myInt");
    16.  
    17. Debug.Log(loadMyInt);
    i just want to know if ACT can do it like that or not.

    thanks!
     
  41. codestage

    codestage

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

    Just cast Obscured* to the regular type, like this:

    Code (CSharp):
    1. ObscuredInt myInt = 5;
    2.  
    3. ES2.Save((int)myInt, "savefile.sv?tag=myInt");
    4. ObscuredInt loadMyInt = ES2.Load<int>("savefile.sv?tag=myInt");
    5.  
    6. Debug.Log(loadMyInt);
    This will unencrypt variable before save and encrypt it back after load.
    You also may save Obscured variable in encrypted state if you don't wish to use ES2 encryption:

    Code (CSharp):
    1. ObscuredInt myInt = 5;
    2.  
    3. ES2.Save(myInt.GetEncrypted(), "savefile.sv?tag=myInt");
    4. ObscuredInt loadMyInt = 0;
    5. loadMyInt.SetEncrypted(ES2.Load<int>("savefile.sv?tag=myInt"));
    6.  
    7. Debug.Log(loadMyInt);
     
  42. grofie

    grofie

    Joined:
    Dec 9, 2013
    Posts:
    30
    Hi Dimitriy,

    we started using your plugin a couple of weeks ago. So far I can say: Great Job, really nice plugin, respect! =D

    But today I ran into a weird problem:

    I use a List<ObscuredInt> which gets filled OnEnable after the toolkit gets initialized (so also after ObscuredInt.SetNewCryptoKey gets called). Normally everything works fine. I can call List.Contains and it returns true as expected. But only on the first run of the game, after the Unity editor is opened freshly, the call List.Contains returns false all the time. The data is the same in all cases, but Contains simply won't return true. I put a Log into your Equals method (ObscuredInt Line 226), which is also used for the Contains function, and indeed: the compared values of hiddenValue differ completely but only on the first run of the game. When I start the game again a second or third time, everything is working fine again. Also when I check the int values in the list, they all look as expected in all cases.

    So I created a workaround where I loop through the list and compare the integers instead of the ObscuredInt. This is working fine but feels a bit hacky...

    Btw, it would also be really nice if you could create a forum for this plugin only. Reporting bugs in here is quite messy. A single topic per buck and a basic search function would help allot. Maybe this bug was reported before - but sorry - I don't have the time and patience to read all the pages before..
     
  43. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Hey, @grofie !
    Thanks for your purchase and your feedback!

    This is a previously unknown bug, thanks for your detailed report.
    I'll look into this as soon as possible and will get back to you with results or repro case request in case I'll not manage to reproduce it.

    Regarding forum for the ACTk - I had such thoughts before, but activity in this thread seemed not too high to split it to the separate forum... Anyway, thanks for your reminder, probably I'll find some time to set up own forum in future.
     
  44. codestage

    codestage

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

    It may happen in case ObscuredInts in your list were initially encrypted with different crypto key.
    Example:
    Code (CSharp):
    1. List<ObscuredInt> ints = new List<ObscuredInt>();
    2. ObscuredInt a = 1;
    3.  
    4. // a was encrypted with default crypto key
    5. ints.Add(a);
    6.  
    7. ObscuredInt.SetNewCryptoKey(123456789);
    8.  
    9. Debug.Log(ints.Contains(1)); // False because 1 here encrypts using 123456789 key
    10. Debug.Log(ints.Contains(a)); // True
    ApplyNewCryptoKey() fixes this issue:
    Code (CSharp):
    1. List<ObscuredInt> ints = new List<ObscuredInt>();
    2. ObscuredInt a = 1;
    3.  
    4. ints.Add(a);
    5.  
    6. ObscuredInt.SetNewCryptoKey(123456789);
    7.  
    8. a.ApplyNewCryptoKey();
    9.  
    10. Debug.Log(ints.Contains(1)); // True
    11. Debug.Log(ints.Contains(a)); // True
    So solutions are:
    - force new encryption key for every variable you've put into the list using ApplyNewCryptoKey();
    - use SetNewCryptoKey before creating any ObscuredInts you wish to put into List;
    - force re-encryption with new key using casting when you add and when you check variable:
    Code (CSharp):
    1. List<ObscuredInt> ints = new List<ObscuredInt>();
    2. ObscuredInt a = 1;
    3.  
    4. ObscuredInt.SetNewCryptoKey(123456789);
    5. ints.Add((int)a);
    6.  
    7. Debug.Log(ints.Contains(1)); // True
    8. Debug.Log(ints.Contains((int)a)); // True
    9.  
    Or I might Improve Equals method to take in account encryption keys... It might slow down comparison though.

    Please let me know if you have something different there.
    And I'd be also glad to know if any of solutions I suggested works for you.
     
  45. elmar1028

    elmar1028

    Joined:
    Nov 21, 2013
    Posts:
    2,359
    Hello,

    I have purchased your asset and so far integration was easy :)

    However, the function ObscuredCheatingDetector.StartDetection() is buggy. As soon as the game starts, it starts detecting a "hack" which I don't have.
    Upon running build on mobile device I get same error.

    My code:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using CodeStage.AntiCheat.ObscuredTypes;
    4. using CodeStage.AntiCheat.Detectors;
    5.  
    6. public class CheaterModule : MonoBehaviour {
    7.  
    8.     private ObscuredBool isCheating = false;
    9.  
    10.     private bool donePunishing = false;
    11.  
    12.     private void Start() {      
    13. ObscuredCheatingDetector.StartDetection(OnChangedVar);
    14.     }
    15.  
    16.     void Update()
    17.     {
    18.         if (isCheating && !donePunishing)
    19.         {
    20.             //do some sorcery
    21.             donePunishing = true;
    22.         }
    23.     }
    24.  
    25.     private void OnChangedVar()
    26.     {
    27.         Debug.Log("ChangedVar");
    28.         isCheating = true;
    29.     }
    Thanks in advance :)
     
  46. codestage

    codestage

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

    Thanks for your purchase and feedback!

    Could you please provide a little bit more info?
    - what Unity version you're using?
    - does it reproduces in Editor?
    - are you using any Obscured vars somewhere else in project?
    - do you change encryption key somewhere?

    I just tried to reproduce it with ACTk 1.4.1.1 in Unity 5.1.2f1 using your code sample without luck.
    Feel free to get in touch via Skype (dmitry.you) for quickier conversation.
     
  47. elmar1028

    elmar1028

    Joined:
    Nov 21, 2013
    Posts:
    2,359
    Hi @Dmitriy Yukhanov

    To answer your questions:
    - I am using Unity 5.1.2f1
    - It does reproduce in Editor
    - I am using Obscured variables in other scripts
    - I am not sure how is this possible
     
  48. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Thanks for your reply.
    I did tried to reproduce it in different ways at this moment, no luck yet though.

    Could you please send me repro case for this issue if possible to let me dive in and see what's wrong there?
     
  49. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    @elmar1028 and everyone else, just wish to let you know: upcoming update will have a support for the Unity Events introduced in Unity 4.6.

    So you'll be able to use all detectors without writing any code except the actual reaction on cheating.
    StartDetection() call is not required anymore.



    You can see new Auto Start option in the example above.
    It starts detector automatically and all you need to do now - write method with reaction on cheating and assign it to the detector.
     
    hopeful likes this.
  50. elmar1028

    elmar1028

    Joined:
    Nov 21, 2013
    Posts:
    2,359
    Hi,

    Unfortunately I wasn't able to reproduce the issue.

    Is it possible to track which variable has ACTk has detected "altered"? It will allow me to know which obscured variable causes issue. It would be a nice feature as well because I have lots of ObscuredInt and ObscuredBool variables and some debugging would be nice.
     
    Last edited: Aug 20, 2015