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,306
    New 1.6.3 version is live!

    Main highlight of the update: root-level speed hack now detectable on any Android devices including Android 8.0+ ones.
    Also SpeedHackDetector on Android platform now much more effective and uses less resources.

    (captured from Android 8.0 device):
    upload_2018-6-22_20-45-4.png

    1.6.3
    - SpeedHackDetector on Android improvements:
    * now detects root level speed hack on Android 8.0 and newer (no root required)
    * more accurate algorythm removing chance of false positives
    * resources usage significantly improved​
    - fixed possible ObscuredCheatingDetector false positive on SetEncryptred() (thx Matt)
    - fixed TimeCheatingDetector compilation for the UWP IL2CPP platform
     
    Last edited: Jun 22, 2018
  2. dasfuhrer

    dasfuhrer

    Joined:
    Apr 29, 2017
    Posts:
    11
    i hacked your demo project in just 4 minutes :)
     
  3. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,306
    Congratulations! =D
    Though I'm not sure what you're trying to tell and how it can help anyone reading this forum =)
    Could you somehow describe in more details what exactly you did hacked and how?
     
  4. Paradoks

    Paradoks

    Joined:
    Oct 13, 2009
    Posts:
    421
    @dasfuhrer
    Give some informations please, i am interested in too.
     
  5. ChoYongGil

    ChoYongGil

    Joined:
    Jan 17, 2014
    Posts:
    9
    Hi,

    Too many people are detected in speed hack.

    I want to detect only users who have increased the speed abnormally. I can allow a slight speed increase.
    How much should I increase interval and maxFalsePositives or cool down?

    Thanks
     
  6. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,306
    Hey, @ChoYongGil !

    Could you please share a bit more info before I could offer a proper support to your case?
    - what ACTk version you are using?
    - on which platform you do register too many detections?
    - which settings you are now using for the SpeedHackDetector if not default?

    Thanks!
     
  7. ChoYongGil

    ChoYongGil

    Joined:
    Jan 17, 2014
    Posts:
    9
    Hi,

    - My ACTk version is 1.6.0
    - It is not detected in IOS. It is detected in 1% of Android users.
    - I am using the default settings. I only use this code.
    SpeedHackDetector.StartDetection(OnSpeedCheatingDetected);

    Thanks!
     
  8. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,306
    Hey, @ChoYongGil

    Try increasing max false positives to 10 and reduce cooldown to 10, it will make it more possible to temporary use speed hack and do not provoke detection.
    But in case speed hack is applied constantly even slightly, it will be detected after all anyway as soon as difference between cheated and reliable clocks will exceed 500 ms.
    Currently there is no way to allow speed hack at specific value to be ignored by detector.

    But this is a good idea and probably could be helpful for others too, so I'll think about implementing it, thanks!
     
  9. ChoYongGil

    ChoYongGil

    Joined:
    Jan 17, 2014
    Posts:
    9
    Thank you for answer. ^^

    Can I change this before actk is updated?

    Code (CSharp):
    1.         private const int Threshold =  25000000;
    2.         private const float ThresholdFloat = 2.5f;
     
  10. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,306
    @ChoYongGil
    Yes, feel free to change them.
    It for sure will help to decrease sensitivity for the temporary applied speed hack.
    Though it will not help much with ignoring constant speed hack since time difference will accumulate over time and will overshoot this threshold after all anyways leading to the cheat detection.

    Internal logic should be significantly refactored to make it possible to ignore slight constant time difference which is somewhat complicated and can't be easily made with small code change.
     
  11. ChoYongGil

    ChoYongGil

    Joined:
    Jan 17, 2014
    Posts:
    9
    Thank you for your kind and detailed explanation.
    I will temporarily change the code and wait for the update.
     
    codestage likes this.
  12. Nucci

    Nucci

    Joined:
    Sep 23, 2015
    Posts:
    5
    When i update from 1.5 version to current version i lose all reference values, could u help me?
     
  13. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,306
    Hey, @Nucci

    ObscuredFloats and ObscuredDoubles had a vulnerability which was fixed at 1.6.0 which required backwards-incompatible changes at the encryption code.

    If you did updated from 1.5.2.0+, then please follow carefully this particular paragraph of the Troubleshooting readme section to know how to perform the migration from the 1.5.2.0+ format to the new 1.6.0+ format:
    I see corrupted ObscuredFloats / ObscuredDoubles...

    If you are updating from 1.5.1.0 or earlier, you’ll need to make an additional migration step, which was added in 1.5.2.0 after first format change. Please let me know it's your case via PM and I'll drop you older ACTk version to let you make a full *.*.*.* - 1.5.2.0 - 1.6.0 migration.

    Also please let me know if you have a problems with any other obscured types except floats and doubles.

    Feel free to switch to the direct PM or email support channel for the quicker resolution of your case.


     
  14. IdiotsCode

    IdiotsCode

    Joined:
    Aug 23, 2015
    Posts:
    15
    Hullo @Dmitriy-Yukhanov!
    I've had my eyes on this project for a good amount of time and am considering purchasing it to use in a larger scaled multiplayer project. However, I need to know what it offers against programs such as DNSpy and other injectors; many members of the testing community are proficient with these tools and able to break into most Unity games including my current project. Is there anything that ACT does to stop this?

    [Video of a method that can easily stop the ACT functioning]
     
  15. Dreamer

    Dreamer

    Joined:
    Mar 8, 2011
    Posts:
    64
  16. codestage

    codestage

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

    @IdiotsCode
    @Dreamer

    Both cases are about code protection from reverse-engineering and altering.
    ACTk does not cover this area since it's a big separate topic, but there are few simple steps you can do to make it much harder to reverse-engineer and alter your code:

    - compile with IL2CPP (makes dnSpy and Co useless as there will be no .dll assemblies)
    - use obfuscator (makes it much harder to reverse-engineer IL2CPP build and metadata)

    Please read these posts for more info on topic and for more ideas about protecting your client-side code:
    https://forum.unity.com/threads/anti-cheat-toolkit-stop-cheaters-easily.196578/page-15#post-3131202
    https://forum.unity.com/threads/anti-cheat-toolkit-stop-cheaters-easily.196578/page-16#post-3326115
     
    dudeses and hopeful like this.
  17. Dreamer

    Dreamer

    Joined:
    Mar 8, 2011
    Posts:
    64
    When I try to modify the codes of InjectionDetector.

    1. Add Update(), it won't be called.
    2. Add any public variables, like public int XX. It won't show up in inspector. add new public UnityEvent, it won't show up, too.
    3. Even gameObject.SendMessage(), sending to itself even won't be called.

    What's wrong?
     
  18. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,306
    @Dreamer
    That's because its Inspector is drawn using Editor:
    CodeStage\AntiCheatToolkit\Editor\Scripts\Editors\InjectionDetectorEditor.cs
     
  19. Dreamer

    Dreamer

    Joined:
    Mar 8, 2011
    Posts:
    64
    So how can I do it? Modifying InjectionDetector, basicly communicate with my other script and run some other codes.
     
  20. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,306
    I'm not sure I fully understand what you're asking about =\
    If you wish to modify InjectionDetector inspector - just make sure to draw your new properties in the InjectionDetectorEditor.
    To know more about Editor scripting, please visit:
    https://docs.unity3d.com/ScriptReference/Editor.html
     
  21. Dreamer

    Dreamer

    Joined:
    Mar 8, 2011
    Posts:
    64
    OK. I want to modify OnCheatingDetected() in InjectionDetector.cs. Turn it to a keep alive sender. So if the guy "reverse-engineering and altering", disable OnCheatingDetected(). I will be able to catch "him", because no keep alive received in my own script.

    To do that, I need InjectionDetector.cs to be able to communicate with my own script which is not in "Plugins" folder and will able to run Update(), so it can send keep alive in every 1s.

    Hope it's clear enough.
     
  22. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,306
    @Dreamer InjectionDetector doesn't have any internal timers and doesn't uses Updates.
    But it's a usual MonoBehaviour under the hood, so Update, etc. should work fine if you wish to add them.

    Please email me an example of what you're trying to add to the detector and I'll try to help you as much as I can on your specific example.
     
  23. DarkCooker

    DarkCooker

    Joined:
    Jan 7, 2015
    Posts:
    93
    Currently I am using 1.5.2.2
    We found a bug that you may fix already.

    When we use Dictionary<ObscuredInt, ObscuredInt> dictionary,
    and when use Auto-Properties in this case, some bugs are triggered.

    e.g.
    class Foo {
    public ObscuredInt key = 1;
    public ObscuredInt Key { get; set; }
    }

    class AnotherClass {
    Dictionary<ObscuredInt, ObscuredInt> dictionary = // something.
    dictionary.Add(1, 1);
    }

    if we do this:
    dictionary[foo.Key] // this will trigger key not found
    even the Key is 1.

    but
    dictionary[foo.key] // this is ok

    I wonder if this is related to auto ctor that does not call the internal constructor of ObscuredInt
    which will give an encryption key.
    And it hits the rare case of equality and so the dictionary cannot find out the key.
     
    codestage likes this.
  24. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,306
    Hey, @M40-Dev

    But where do you set Key to 1?
    Please note, Key auto-property is 0 by default until you assign it to something.

    It will work fine for example if you will set Key to 1:
    Code (CSharp):
    1. var foo = new Foo();
    2. foo.Key = 1;
    3.  
    4. anotherClass.dictionary[foo.Key]; // 1
    Please let me know if I understood it incorrectly.
     
  25. DarkCooker

    DarkCooker

    Joined:
    Jan 7, 2015
    Posts:
    93
    I found that sometimes we get the hidden value.
    857788 inside the program and it does not use cryto key.
    Not sure why.
     
  26. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,306
    This is pretty strange indeed.
    Please let me know if you'll be able to find a way how to reproduce it so I could make it on my side and look for the cause of the issue.
     
  27. GloriaVictis

    GloriaVictis

    Joined:
    Sep 1, 2016
    Posts:
    99
    Hello,

    We are having a user with a fresh Windows installation which game is being shut down right after lauching because of SpeedHack detection. I am on his Team Viewer right now and everything seems legit - have you heard of issue like that already? Is there a way to return in debug which application exactly is shutting it down?
     
  28. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,306
    Hey, @GloriaVictis

    This is a first time I hear about such case. It detects time difference between in-game timers and local time of the device.
    So the only one possible cause of the SpeedHack detection is that in-game timers are running with not the same speed as system time.

    However, it should not detect right away by default as it allows few detections before firing detection callback ti make sure system temporary timers glitches will not affect it. So even if application is running with speed hack right from the beginning it will take more than 10 secs before firing detection event.
     
  29. GloriaVictis

    GloriaVictis

    Joined:
    Sep 1, 2016
    Posts:
    99
    Yes, it looks exactly like that actually - user launches application, it keeps alive for a few seconds (like 10) and it closes. I have just have more changed Interval into longer one and Max False Positives too, we will find out if it will help.
     
  30. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,306
    This is an interesting case, would be great to know what you'll find out!
     
  31. GloriaVictis

    GloriaVictis

    Joined:
    Sep 1, 2016
    Posts:
    99
    Sadly it didn't helped, same issue persist for this user. I have been trying to help him for a few hours already - having a callback with some kind of application name causing the detection would help us alot. Any chance to have something like that?
     
  32. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,306
    Yeah, sad to hear this user has this strange issue.
    SpeedHackDetector doesn't aware of any applications affecting timers.
    It just assumes timers should have no significant difference unless one of them is affected by the speed hack.

    It's possible, in some rare cases though, timers could be affected by hardware or performance issues, but there were no reports proving this before.

    In future updates, there will be added option to allow constant difference within specific range if desired (e.g. allow insignificant speed hack), it might be helpful in such cases.
     
  33. Pastille

    Pastille

    Joined:
    Jul 22, 2016
    Posts:
    2
    Does ObfuscatePrefs use PlayerPrefs or does it save it in some other manner? I am asking becaues im using a PlayerPrefs replacement for IOS that save the data to the cloud and what i want is to obfuscate and save to the cloud.
     
  34. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,306
    Hey, @Pastille

    ObscuredPrefs uses PlayerPrefs under the hood.
    You're free to encrypt your data before sending it to the cloud and decrypt it back after reading from cloud using appropriate obscured types static methods like
    ObscuredInt.Encrypt() / Decrypt()
     
  35. Pastille

    Pastille

    Joined:
    Jul 22, 2016
    Posts:
    2
    as long as it saves the playerprefs encrypted using your solution should just work out of the box without any need for modifications.


    I.E i Save values using obscure prefs, your api does it's thing but ultimately saves it encrypted to PlayerPrefs (that is actually not playerprefs on IOS but it sits between) and then the encrypted values are saved on the cloud and when i read it using Obfuscated it will decrypt it.

    It's likely enough to work for me to "risk" the money =)
     
    codestage likes this.
  36. DarkCooker

    DarkCooker

    Joined:
    Jan 7, 2015
    Posts:
    93
    I found what exactly happened.

    This is due to using Inspector.
    Many prefabs are used in the project with public ObscuredInt, ObscuredFloat, etc.

    And the default value in code is 0.
    But we set the values in Prefab's view/inspector.

    And we apply and saved the values.
    Many of them are okay
    But some of them may be "broken" and become zero or a very large number.
    I wonder if the hidden key or values are corrupted in meta files.
     
  37. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,306
    @M40-Dev there were few changes in ObscuredFloat \ ObscuredDouble encryption which leads to the corruption on prefabs - one at 1.6.0 and other at 1.5.2.0

    At the 1.5.5.0 the migration tool was introduced to fix the 1.5.2.0 corruption.
    At the 1.6.0 it was updated to fix only 1.6.0 corruption (it will not fix 1.5.2.0 corruption anymore).

    Please let me know if you wish to get 1.5.5.0 or later version through PM and I'll be glad to share it with you to let you fix the corruption with migration tool.
     
  38. DarkCooker

    DarkCooker

    Joined:
    Jan 7, 2015
    Posts:
    93
    Thanks for that.

    Currently I am 1.6.3. We did change to 1.6.3 from old version - but I can't find which version was it.
    Which version I should use/fix?

    Or I keep using 1.6.3. And clean all prefabs. Then stay at using 1.6.3 and it should not corrupt again?
     
  39. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,306
    This is a best option if you can afford it.

    If you have too much prefabs and it's too painful to reset them - I'd suggest to try migration tool from 1.6.3 and if it will not help - try the migration tool from any ACTk version in this range 1.5.5.0 to 1.5.8.0. Of course you'll need to make a backups of your project to avoid any negative effects of using non-compatible version of migration tool.
     
  40. seanybaby2

    seanybaby2

    Joined:
    May 17, 2013
    Posts:
    109
    Thoughts on how to prevent people from doing this?

     
  41. seanybaby2

    seanybaby2

    Joined:
    May 17, 2013
    Posts:
    109
    Also I know you have a way to encrypt player prefs but any recommendations how to encrypt data that is being saved without player prefs?

    Stuff that is being written to a data file.
     
  42. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,306
    Hey, @seanybaby2

    Yes, please read my thoughts I posted recently here:
    https://forum.unity.com/threads/anti-cheat-toolkit-stop-cheaters-easily.196578/page-18#post-3578619

    Yes, you're free to use Obscured types static Encrypt()/Decrypt()/EncryptDecrypt() methods to encrypt any data.

    For example:

    ObscuredByte.EncryptDecrypt(byte[] value, byte key)
     
  43. seanybaby2

    seanybaby2

    Joined:
    May 17, 2013
    Posts:
    109
  44. N1warhead

    N1warhead

    Joined:
    Mar 12, 2014
    Posts:
    3,542
    @Dmitriy-Yukhanov : just to make sure I understand your package correctly.

    Okay if I do for example

    ObscureString s = "David";
    String d = s;
    d will then output "David"?

    Or is there some extra steps I need to account for?
    Just bought it, so I just wanted to make sure I read the document correctly when I saw something similar to this in it.

    Thanks mate.
     
  45. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,306
    Hey, @N1warhead

    Thanks for your purchase!
    Yes, you got it right, obscured and regular types are casting to each other implicitly.
     
  46. N1warhead

    N1warhead

    Joined:
    Mar 12, 2014
    Posts:
    3,542
    Awesome thanks mate!

    Take care.
     
    codestage likes this.
  47. Doghelmer

    Doghelmer

    Joined:
    Aug 30, 2014
    Posts:
    112
    Just wanted to clarify something: I have an issue with a particular person who has created their own Assembly-CSharp.dll that modifies bits of my code. Users simply replace my own Assembly-CSharp.dll with the new one. To be totally clear, is this considered an injection, and would the injection tool be appropriate for dealing with this?
     
  48. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,306
  49. cpt_danko

    cpt_danko

    Joined:
    Oct 2, 2018
    Posts:
    6
    Hey Dmitriy!
    Just bought your asset, excellent job. Two questions:

    1. How would you do server side file integrity check? I'm thinking of using your InjectionDetector code for calulcating hashes and then sending them and comparing to server-side hashes. Would this be a good approach?

    2. How would I protect transform.position and other unity variables?
     
    Last edited: Oct 22, 2018
  50. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,306
    Hey @cpt_danko ,

    Thanks for your purchase and kind words!

    InjectionDetector does not calculate full assembly hashes since its purpose - detect foreign assemblies, not the modifications of the known ones.
    Integrity checks functionality is planned in future updates though.

    For now, I'd suggest to write it from the ground up - just hash whole assembly files (Injection Detector checks some internals of assemblies which is not necessary in case of full hashing) or even whole build \ other files in build (depending on your target platform).

    transform.position is not a variable, actually it's a Property which gets actual variable from the C++ part of the engine.

    So to protect them from memory search, you'll need to protect whole process memory from foreign access which is not a trivial and requires different approach on different platforms (and will require root on Android for example).

    From the managed C# side, you may just control actual values and make sure they are not changing in unrealistic way (look at the delta, or make more complex calculations to check speed, acceleration, movement vectors, etc for the realistic behavior).
    Better implement such checks on the server side if you have online game which has server.
     
    Last edited: Oct 24, 2018
    cpt_danko likes this.
unityunity