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
    Anti-Cheat Toolkit WebGL demo available!
    http://codestage.ru/unity/anti-cheat/demo/

    Yeah, I need to update my demo scene finally, it's too ascetic =)

    Please, report if it doesn't work for you (in latest Chrome or Firefox). One JS error popup is accessible (not my fault and it shouldn't break anything).
     
  2. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Oh, and I totally forgot to mention - ACTk now 50% OFF for only $12.50 until Feb, 27!
     
  3. arkon

    arkon

    Joined:
    Jun 27, 2011
    Posts:
    1,122
    I'm getting strange results with the plugin, I'm setting bools using ObscuredPrefs.SetBool("thingy",true); and when I read it back after a save it still says false. (This is on IOS) do I need to to call ObscuredPrefs.lockToDevice =ObscuredPrefs.DeviceLockLevel.Strict; at the beginning of each scene?

    currently I call ObscuredPrefs.lockToDevice =ObscuredPrefs.DeviceLockLevel.Strict; as the first thing done in the first scene loaded. Then I set and read the prefs in subsequent loaded scenes. What Am I doing wrong? Oh and it works fine in the editor, but not always.
     
  4. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Thanks for reporting this. I'll back to you soon with investigation results.
    Regarding lockToDevice - you doing it right, it's enough to set it once in the very beginning of your game.
     
  5. arkon

    arkon

    Joined:
    Jun 27, 2011
    Posts:
    1,122
    I should add I'm using Unity 4.6.3 building to IOS using IL2CPP, Arm64, Use Micro MSCorLib
     
  6. arkon

    arkon

    Joined:
    Jun 27, 2011
    Posts:
    1,122
    I've just created a small test projects and the cause is your plugin doesn't work on IL2CPP builds, it's nothing to do with stripping. Works fine on the device as Mono2.0 but fails at runtime on the device with IL2CPP
     
  7. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Hey, Arkon!
    IL2CPP compatibility issue I know should affect only ObscuredFloat, ObscuredDouble and ObscuredDecimal. I have workaround files for ObscuredFloat and ObscuredDouble to let you use ACTk with IL2CPP right now (just let me know you need them and I'll send them to you).
    This is a known Unity-side bug and bugfix should arrive with Unity 5 RC3 and some of upcoming patches for Unity 4.6.

    Could you please confirm you can reproduce IL2CPP issue with ObscuredPrefs exactly?
    In such case I'd be glad to have your tiny test project with repro case to let me look into it and help with workaround / fix.
    Thanks!
     
  8. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Nevermind, I just managed to reproduce it myself. It looks like some regression.
    They fixed IL2CPP bug leading to broken ObscuredFloat but now most ObscuredPrefs methods are broken.
    I'm going to investigate it deeper. I'll back with results ASAP.

    Interesting observation: ObscuredPrefs work fine with WebGL IL2CPP builds in Unity 5 RC2.
     
    Last edited: Feb 20, 2015
  9. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    And here are results: new regression breaks such code:
    Code (CSharp):
    1. uint inputDataHash = (uint)(dataHashBytes[0] | dataHashBytes[1] << 8 | dataHashBytes[2] << 16 | dataHashBytes[3] << 24);
    it's an actually optimized version of this:
    Code (CSharp):
    1. uint inputDataHash = BitConverter.ToUInt32(dataHashBytes, 0);
    So, to workaround it, you just need to replace 2 lines in ObscuredPrefs.cs. This line:
    Code (CSharp):
    1. uint inputDataHash = (uint)(dataHashBytes[0] | dataHashBytes[1] << 8 | dataHashBytes[2] << 16 | dataHashBytes[3] << 24);
    with this:
    Code (CSharp):
    1. uint inputDataHash = BitConverter.ToUInt32(dataHashBytes, 0);
    and line
    Code (CSharp):
    1. inputDeviceHash = (uint)(deviceHashBytes[0] | deviceHashBytes[1] << 8 | deviceHashBytes[2] << 16 | deviceHashBytes[3] << 24);
    with this:
    Code (CSharp):
    1. inputDeviceHash = BitConverter.ToUInt32(deviceHashBytes, 0);
     
  10. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    I'll make nice repro case and send this bug to Unity for resolution, so I hope it will be fixed in upcoming IL2CPP updates.
    Thanks for the heads up and for your report once again, @arkon!
     
  11. arkon

    arkon

    Joined:
    Jun 27, 2011
    Posts:
    1,122
    I've sent a repro project with this problem to Unity too, so fingers crossed.
     
  12. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Great, thanks! Hope they'll fix it soon.
    For now you may use workaraound I mentioned in one of my previous post.
     
  13. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Just tried Unity 5 RC3 WebGL - it has same issue with ObscuredPrefs now as Unity 4.6.3 has.
    And ObscuredFloat/Double-related IL2CPP issue is fixed just like in Unity 4.6.3.

    I've prepped workaround file for Unity 4.6.3 and Unity 5 RC3 IL2CPP issue (affects both iOS IL2CPP and WebGL) using one of my previous posts. So feel free to use hints in that post as well or just ask me for final file and I'll drop it to you.

    EDIT:
    I just got confirmation IL2CPP regression fixed and should land in the nearest patch release!
     
    Last edited: Feb 23, 2015
  14. arkon

    arkon

    Joined:
    Jun 27, 2011
    Posts:
    1,122
    I've just discovered another problem with value = ObscuredPrefs.GetInt("value",100);
    If the value has never been set it should initialise it with the 2nd parameter but it doesn't. I've even tried calling save afterwards bu testing no luck. I am trying to work out why now. Target mono IOS, 4.6.3P1
     
  15. arkon

    arkon

    Joined:
    Jun 27, 2011
    Posts:
    1,122
    Ok just run some test:

    ObscuredPrefs.SetNewCryptoKey(encryptionKey);
    ObscuredPrefs.lockToDevice =ObscuredPrefs.DeviceLockLevel.Soft;


    D.logx("Credits1 = {0}",ObscuredPrefs.GetInt("Credits")); //Prints 0
    D.logx("Credits2 = {0}",ObscuredPrefs.GetInt("Credits",InitialCredits)); //Prints 200
    ObscuredPrefs.Save();
    D.logx("Credits3 = {0}",ObscuredPrefs.GetInt("Credits")); //Prints 0 (Save clears the value!!)
    ObscuredPrefs.SetInt("Credits",200);
    D.logx("Credits4 = {0}",ObscuredPrefs.GetInt("Credits")); //Prints 200
    ObscuredPrefs.Save();
    D.logx("Credits5 = {0}",ObscuredPrefs.GetInt("Credits")); //Prints 200
     
  16. codestage

    codestage

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

    Thanks for report, I'll look into it.
     
  17. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Oh, but your example looks perfectly fine.
    D.logx("Credits3 = {0}",ObscuredPrefs.GetInt("Credits")); //Prints 0 (Save clears the value!!)

    it should return 0 since you're trying to read "Credits" which wasn't saved with SetInt before and you do not provide custom default value so it returns default one (0).
     
  18. arkon

    arkon

    Joined:
    Jun 27, 2011
    Posts:
    1,122
    Surely if you pass the second parameter to getint, the default value for if the store has not been set, it should store the default value. What's the point of a default value otherwise?
     
  19. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    It works same as for usual PlayerPrefs.
    It doesn't store anything unless you use Set* methods. And passed default value is returned if requested key doesn't exist.

    For example, player should have initially 1000 coins and you wish to read last saved money count:
    Code (CSharp):
    1. const newGameMoneyCount = 1000;
    2. //...
    3. currentMoneyCount = ObscuredPrefs.GetInt("PlayerMoney", newGameMoneyCount);
    In such case it will return last saved money count or default 1000 if game wasn't saved before.
     
  20. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Unity 4.6.3 Patch 1 is out and looks like all IL2CPP issues are fixed finally!
    Please let me know if you still experience any issues in 4.6.3 Patch 1.
     
  21. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Anti-Cheat Toolkit 1.4.0.2 is out with one tiny quickfix:
    - fixed ObscuredString editing in multiple objects (thanks VitaMin00)

    And I'd like to let you know I'm working hard on new plugin therefore I may be not as responsive as usual for a short time period (while I launching it), but I'll try to keep my responsiveness level anyway =)
     
  22. zbrusher

    zbrusher

    Joined:
    Dec 12, 2012
    Posts:
    19
    codestage likes this.
  23. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Hey, @zbrusher!
    Thanks for your feedback, your game looks awesome, soccer with bloody kills, hell yeah!!! =D
    I don't use Steam (really, have account for tests without rights to vote) thus I can't vote, but I'd like to, if I could!
     
  24. Ted-Brown

    Ted-Brown

    Joined:
    Oct 16, 2012
    Posts:
    33
    Hi Dmitriy,

    I'm upgrading Epic Skater to Unity 5.0.0p1 (from Unity 4), and we had previously been using ACT without issues. However, even after grabbing the latest version of ACT from the store, I am seeing this error:

    Assets/CodeStage/AntiCheatToolkit/Scripts/ObscuredTypes/ObscuredPrefs.cs(12,29): error CS0101: The namespace `CodeStage.AntiCheat.ObscuredTypes' already contains a definition for `ObscuredPrefs'

    We are currently building for the iOS platform.

    Have you encountered this error before? And do you know of a fix or workaround?

    Thank you!
     
  25. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Hey @Ted Brown!
    I'm sorry if my question will sound silly, but I have to ask - are you sure you completely removed previous ACT version before update?

    Such error may happen if you have different versions of the same ObscuredPrefs class in the project.
    Please, let me know if it still happens even with clean update and I'd be glad to help you further with resolving this issue.
     
  26. Ted-Brown

    Ted-Brown

    Joined:
    Oct 16, 2012
    Posts:
    33
    o_O

    A clean install resolved the issue, thanks!
     
  27. Liviuss

    Liviuss

    Joined:
    Apr 2, 2014
    Posts:
    101
    Hi Dima,
    Thanks for a great tool, work like a charm. I have a question about serialization to Json, did you have a solution for Json objects serialization? I mean Objects with Obscured properties not just some obscured variables? I work with JsonDotNet plugin to serialize objects and store them in ObscuredPlayerPrefs. At the moment i have a proxy class to convert obscured variables to primitives and back, otherwise the values won't be serialized.

    Thanks
     
  28. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
  29. Liviuss

    Liviuss

    Joined:
    Apr 2, 2014
    Posts:
    101
    How did i miss this post???!!!! ))))
    Thanks
     
  30. Liviuss

    Liviuss

    Joined:
    Apr 2, 2014
    Posts:
    101
    Hi Dmitriy,

    What do you think about adding a custom security library for signature checks? You know that we are facing 2 main problems with published games. The first one is memory cheating and your plugin beat 99,9% of the hacking tools. The second one is IAP hacking, based on security library substitution.
    With the second threat the only reliable solution at the moment is to check IAP receipt signature on a 3d party server where you know the security check will work.
    Do you think It's a good solution to have a separate library for security checks, library which will not rely on system security?
     
  31. codestage

    codestage

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

    I'd like to know about tools which sneak into this 1% =)

    Everything we can do from the client side will be vulnerable regardless of placement. So I'd suggest to not bother with separate library for security checks unless you're going to obfuscate it hardly (in such case it may increase time cheater will spend on your game).
    And I have IAP cheating research in my TODO, so I'll try to add something helpful in one of the next ACTk updates.
     
  32. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Hey everyone!
    Just FYI, I'm working on new WallHackDetector for the ACTk, late research phase in progress.
    Hopefully it will detect both CharacterController and RigidBody hacks.
    Stay tuned, I'll keep you updated.
     
  33. Zergling103

    Zergling103

    Joined:
    Aug 16, 2011
    Posts:
    392
    Will this detect when someone is using a modified assembly?

    Like, lets say I de-compile, modify and then recompile. Will it detect this? (For example, changing character speed using a multiplier in the code directly, not modifying memory.)
     
  34. codestage

    codestage

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

    ACTk had such module before (IntegrityChecker), but I decided to exclude it so far, since there is no reliable and clean way to get final assemblies before they put in build to take their crc signatures. I'm waiting for this: http://feedback.unity3d.com/suggestions/access-to-final-assemblies-before-they-put-in-build
    It will allow to reach final assemblies, obfuscate them, get their signatures, etc. on every build without extra hacks.

    And after all, assemblies validation should be done on the Unity Player side affecting Application.genuine flag since any checks in managed code can be patched away making all that job almost useless.

    Anyway, I'm definitely going to implement it again as soon as my suggestion will be live to make as much as possible to increase amount of the time cheater needs to do his dirty job =)
     
  35. cabanel

    cabanel

    Joined:
    Sep 22, 2014
    Posts:
    68
    Hi Dimitry

    i have a script that worked well,
    but after updating to the latest version of Anti-Cheat but error in this line:
    InjectionDetector.Instance.autoDispose = true;
    error is:
    NullReferenceException: Object reference not set to an instance of an object
    myDetectorsCheat.Start () (at Assets/_MY_GAME/SCRIPT/myDetectorsCheat.cs:37)

    why?

    thanks
     
  36. codestage

    codestage

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

    Here is a reason:
    1.3.4:
    - detectors Instance property reworked (can be null now)


    Looks like you're trying to access InjectionDetector.Instance before starting it.
    Just make sure you've called InjectionDetector.StartDetection() before accessing InjectionDetector.Instance.
     
  37. cabanel

    cabanel

    Joined:
    Sep 22, 2014
    Posts:
    68
  38. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Anti-Cheat Toolkit 1.4.1 out!

    Main highlight: new WallHackDetector!
    See this video for details:


    Full changelist:
    1.4.1
    - added new WallHackDetector! Detects 2 native hacks: Rigidbody and CharacterController patches
    - added new InjectionDetected and WallHackDetected Actions for the PlayMaker
    - added new WallHackDetected task to the BehaviorDesigner
    - InjectionDetector now detects case when there is 0 assemblies in current domain
    - fixes in filenames: ObscuredUint.cs to ObscuredUInt.cs, ObscuredUshort.cs to ObscuredUShort.cs
    - minor fixes and refactorings
    - fixes in readme
     
  39. VeTaL

    VeTaL

    Joined:
    Jul 2, 2012
    Posts:
    125
    Hi,

    I'm extending Unibill to be able to work with ObscuredPrefs, luckily its extremely easy to extend on their side. The problem is that some methods which works with Prefs are called from Update(), so i need extra cache layer.

    Is my current approach secure enough?

    Code (CSharp):
    1. public class UnityObscuredPrefsStorage : Uniject.IStorage
    2.     {
    3.         private const bool isLoggingEnabled = true;
    4.         private static Dictionary<string, ObscuredInt> storedInts = new Dictionary<string, ObscuredInt> ();
    5.  
    6.  
    7.         public int GetInt (string key, int defaultValue)
    8.         {
    9.             ObscuredInt result;
    10.             if (storedInts.TryGetValue (key, out result))
    11.             {
    12.                 if (isLoggingEnabled) Debug.LogWarning (System.Reflection.MethodBase.GetCurrentMethod ().Name + " is called. Result is taken from cache. Key: " + key + " Value: " + result);
    13.                 return result;
    14.             }
    15.  
    16.             result = ObscuredPrefs.GetInt (key, defaultValue);
    17.             storedInts [key] = result;
    18.             if (isLoggingEnabled) Debug.LogWarning (System.Reflection.MethodBase.GetCurrentMethod ().Name + " is called. Result is taken from the storage. Key: " + key + " Value: " + result);
    19.  
    20.             return result;
    21.         }
    22.  
    23.         public void SetInt (string key, int value)
    24.         {
    25.             storedInts [key] = value;
    26.             ObscuredPrefs.SetInt(key, value);
    27.  
    28.             if (isLoggingEnabled) Debug.LogWarning (System.Reflection.MethodBase.GetCurrentMethod ().Name + " is called. Key: " + key + " Value: " + value);
    29.         }
     
    twobob likes this.
  40. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Hey, @VeTaL !
    Yep, your approach looks fine!
     
  41. VeTaL

    VeTaL

    Joined:
    Jul 2, 2012
    Posts:
    125
    Thanks, Dmitriy.
    Keep up good work :)
     
  42. zumpar

    zumpar

    Joined:
    Sep 7, 2012
    Posts:
    2
    Hi,

    great job with the toolkit, I've been using it for a couple months now, but all of a sudden I've started experiencing some weird behavior (a month after migrating to Unity 5).

    In my script I have this definition:
    public ObscuredInt integerValue = 1;
    public ObscuredFloat stepValue = 1;

    I then change the stepValue value via inspector to let's say 0.5.

    Everything works fine, I save the scene, and close Unity. The problem occurs when I reopen Unity, this error is being thrown continuously when I click on a gameobject with the above mentioned script:

    It appears that the error is thrown whenever I want to view an ObscuredFloat variable in the inspector, and keeps being thrown nonstop when I have a gameobject selected that has that script attached. The editor only displays the first ObscuredInt variable, but not the ObscuredFloat.. just some blank space.

    I can temporarily fix this by changing the ObscuredFloat variable to a float variable, rebuild the project, and then change it back to an ObscuredFloat.. but this causes the values entered via inspector to be lost.

    Have you encountered such behavior?
    Thank you.

    Paul
     
    Last edited: Apr 10, 2015
  43. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Hi, @zumpar !
    I did tried to reproduce it without luck using latest ACTk and Unity 5.0.1.
    Could you please send me scene with script when it already throws that error and describe step-by-step how did you managed to reach this error?
     
  44. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Anti-Cheat Toolkit 1.4.1.1 is out!
    It's WallHackDetector fixes release mostly. Here is a full changelog:

    1.4.1.1
    - WallHackDetector: additional auto-correction for rigidbody module
    - WallHackDetector: service sandbox now survive scene load if detector has Keep Alive enabled
    - WallHackDetector: resources usage improvments
    - WallHackDetector: initialization performance improvments
    - all ACTk windows are moved to Window > Code Stage > Anti-Cheat Toolkit menu item
    - fixes in readme
     
  45. edu101

    edu101

    Joined:
    Apr 13, 2015
    Posts:
    3
    Hi, I never used anticheattoolkit before, so I'm a new user and in my first try. I have a compilation error cs0241 in the file xxHash.cs in line 44 "public static uint CalculateHash(byte[] buf, int len, uint seed = 0)", the game works however and the error appear when build the app in the monodevelop 4.0.1 in unity 4.6.3f1 working in a windows8 pro. As I said the game works but ever I get this error when build the unity app. It is normal? if not can you help me. I dont know if it is the right place for this question, but I searched for this topic and dont find anything, so thanks for all.
     
  46. codestage

    codestage

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

    Thanks for your report. What is your target platform?
    It looks like default params are the cause (uint seed = 0), but I forgot when I saw such errors last time, Unity isshould be compatible with the default params for a long time already.

    I'll change it to avoid such error anyway, just curious how did you managed to get this error though.

    Edit: sent you fixed xxHash file.
     
    Last edited: Apr 13, 2015
  47. edu101

    edu101

    Joined:
    Apr 13, 2015
    Posts:
    3
    thanks I pasted the fixed xxHash file and there are no errors in the horizont, great.
    I'm using it for winphone and android and I didnt nothing special only I install the anticheattoolkit from the asset store runned from within the unity editor, and since the first time this compile error appears, even if I dont use the kit. Only when I tried to use the kit for the first time in my app, I tried solve it.
    Other question, Can I use the obscured types for static variables? I use some of this for pass values between levels.

    Again thank you for you fast support, great!
     
  48. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Sure, you absolutely can use obscured types for static variables!
    Thanks for your report once again. Fix I sent you will be released with next ACTk update.
     
  49. zumpar

    zumpar

    Joined:
    Sep 7, 2012
    Posts:
    2
    Hi again,

    I was unable to reproduce this bug in a new project, even in the original project where the bug occurs the behavior is very strange. I'm using multiple ObscuredFloat variables in a script, but the bug only happens when I change the values of a few specific variables (via inspector). Anyway, I changed these variables to ObscuredInts since it's not critical for them to be float values, so everything is working fine for now.. it might be some crazy error due to my project setup or something like that since I can't reproduce it, so I'm going to leave it as it is.

    Thanks for your support.
    Paul
     
  50. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    Thanks for letting me know, @zumpar! Hope it's just a some glitch in Unity or something. Anyway, I'd be glad to know if it will appear again in another project.