Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Join us on March 30, 2023, between 5 am & 1 pm EST, in the Performance Profiling Dev Blitz Day 2023 - Q&A forum and Discord where you can connect with our teams behind the Memory and CPU Profilers.
    Dismiss Notice

Anti-Cheat Toolkit: stop cheaters easily!

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

  1. studiolumiere_unity

    studiolumiere_unity

    Joined:
    Apr 24, 2020
    Posts:
    21
    Thanks for your reply.
    My testing showed that the hash key changes during the UDP->store repack process, but I don't think it's a problem if you use the hash of the repackaged Apk.
     
    codestage likes this.
  2. studiolumiere_unity

    studiolumiere_unity

    Joined:
    Apr 24, 2020
    Posts:
    21
    I am uploading as .aab file to GooglePlayStore.
    Summery Hash with Upload [Calcuelate External Build Hashs] and Summery Hash (if actually downloaded via GooglePlayStore) were different.
    Does uploading the distribution hash value as an aab file change it?

    I am using Anti Cheat-Toolkit version 2.3.0
     
  3. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,853
    Hey @studiolumiere_unity ,

    Yes it's totally fine for hash to change when you use aab since it's a bundle format and Google splits it to different apks and sign them on their side which leads to hash value change.

    I'll take a look what could be done here to reduce chances for hash change when using aab, if this is possible at all.

    Added this to my internal task tracker (issue ACTK-188).
     
    studiolumiere_unity likes this.
  4. studiolumiere_unity

    studiolumiere_unity

    Joined:
    Apr 24, 2020
    Posts:
    21
    After uploading to the Google Play Store, I noticed something strange while checking the hash log of the user on the server.

    [1] aab hash before upload to google play store (Calcualte External Hash) = A580CFAAFB53827A9DC3C1A9D28E534DCAD91FCC
    [2] result.SummaryHash (80% of users) downloaded from Google Play Store = D16027CACB3C22C6B0078F233E5077BED8F7C4E2
    [3] Unknown result.SummaryHash (20% of users) = CE74C08C3A5DEF63CD4F1EFC5F4B5B54702700D7

    I don't know why the value [3] (unknown hash) is being generated.
    They believe they are players with no record of illegal activity, and Google in-app billing also happens.
    Any guesses as to why the value [3] is being generated?
     
  5. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,853
    Highly likely it's just another APK made from initial aab, as I mentioned earlier it's get splitted by Google into different apks for different platforms.
     
  6. studiolumiere_unity

    studiolumiere_unity

    Joined:
    Apr 24, 2020
    Posts:
    21
    Doesn't this happen when I upload to Google Play Store as .apk instead of .aab?

    [Google into different apks for different platforms.]
    => What do you mean specifically? I think all users are Android.

    Additional)
    Oh! I just ran it on PC emulator (NoxPlayer) and it came up with hash value 3 times.
     
    Last edited: Jun 10, 2021
  7. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,853
    Usually no, it does not touch code binaries from what I've seen so far. Please let me know if you'll see opposite.

    Androids can have different CPUs, like ARMv7 or x86 and different APKs with different binaries will be made from initial aab for different CPU architectures.
     
    studiolumiere_unity likes this.
  8. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,853
    ⚒ Anti-Cheat Toolkit 3.0 WIP update ⚒

    Thrilled to announce I'm working hard on next big paid upgrade: Anti-Cheat Toolkit 3.0 which among numerous fixes and improvements will deliver new features to your hands within its lifecycle, starting from ObscuredFile on first release!

    ObscuredFile allows writing and reading binary data with tampering detection, encryption, lock to device feature.

    It's async-friendly and can be used from separate thread to avoid main thread lock when working with big amount of data.

    ObscuredFile goes with ObscuredFilePrefs: simple and intuitive APIs to save as easy as with PlayerPrefs but with more data types and all ObscuredFile features and power.

    ObscuredFileEncryption.gif

    This feature currently at the late development stage and going to be released this summer after alpha and beta test phases.

    Beta Test notice

    Please PM me if you would like to participate in beta test and get a chance to win vouchers for this upgrade or others Code Stage assets.

    Stay tuned!

    Stay tuned for more news behind new paid upgrade reasons, its price, grace period, lifecycle and further big plans for Code Stage brand at the Asset Store!
     
    Last edited: Jun 10, 2021
  9. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,853
    ⚒ Anti-Cheat Toolkit 3.0 WIP update ⚒

    ObscuredPrefs just got generic APIs and few new types support!

    upload_2021-6-12_12-23-30.png
     
  10. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,853
    Anti-Cheat Toolkit 3.0 WIP update

    ObscuredFile & ObscuredFilePrefs implementation is finished and API is finalized.

    Small usage example with async operations is done as well ^^

    Now to the most boring part: testing, writing docs and such :rolleyes:

    a04bd722bf269683d1b3ee18697311dcd53425be.gif

    PM with invoice to request beta!
     
  11. EXOUST

    EXOUST

    Joined:
    Jan 19, 2019
    Posts:
    3
    How to use Hashes and etc? I don't see any documentation for this...
     
  12. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,853
    Hey @Detex_Studio ,

    Please refer to "Code Integrity validation" Readme chapter and CodeHashGenerator API reference.

    Also feel free to take a look at Examples/Code Genuine Validation

    Please let me know if you'll have any further questions.
     
  13. EXOUST

    EXOUST

    Joined:
    Jan 19, 2019
    Posts:
    3
    Okay. So actually I wanna compare Build Hash and SummaryHash in build. In this example we are looking for this texture which is really helpful but not what I want. How can I use this hash in build?
    upload_2021-6-29_0-43-41.png
     
  14. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,853
    You can store it at your webserver to make server-side integrity checks or hide in your build as shown in example, to compare it against actual hash you generate at runtime using CodeHashGenerator.

    Example demonstrates how to embed generated summary genuine hash into your build for the runtime comparison against actual generated hash.
     
    Last edited: Jun 28, 2021
    EXOUST likes this.
  15. EXOUST

    EXOUST

    Joined:
    Jan 19, 2019
    Posts:
    3
    Okay thanks!
     
  16. mrm83

    mrm83

    Joined:
    Nov 29, 2014
    Posts:
    332
    Is there any reason why our game is not protected against gameguardian even with anticheat implemented?

    Our values are already using obscured but search and replace seems to be working. I havn't tested this personally as I dont have rooted device, but these reports were from player provided videos.

    Edit:
    Is it possible to hack the obscured fields with game guardian or does this tool prevent hacking of obscured fields 100%?
     
    Last edited: Jul 14, 2021
  17. codestage

    codestage

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

    Obscured types make it harder to find and manipulate values since they are encrypted and change in not usual way so in most simple cases it's enough to hide your variables from curious eyes.

    However, there's no 100% protection unless you are storing your variables on remote server.

    Thus, I'd recommend:
    • Complement obscured variables with ObscuredCheatingDetector if you didn't used it yet (it will create fake variables honeypots while keeping original values encrypted) to catch cheating attempts
    • Make use of RandomizeCryptoKey API to increase unknown value search difficulty
    Please let me know if you need any further assistance with this case, I'd be glad to help!
     
  18. mrm83

    mrm83

    Joined:
    Nov 29, 2014
    Posts:
    332
    Already have ObscuredCheatingDetector running and already doing RandomizeCryptoKey but it doesn't appear to be doing the trick as players are still able to search and replace values.

    Does anything need to be setup in specific order for it to work?

    This is my current setup:
    The following class is executed first.
    Code (CSharp):
    1.  
    2. private void Awake() {
    3.         _instance = this;
    4.         ObscuredCheatingDetector.StartDetection(HACK);
    5.         SpeedHackDetector.StartDetection(HACK);
    6. }
    7.  
    Then when game runs and everytime inventory is opened for example, all inventory item's obscured types calls RandomizeCryptoKey.

    Inventory items's obscuredTypes are still being hacked in game guardian and no detection taking place.

    Could you please help me understand how this hack works?

    If for example, I have:
    int HP = 100 and I want to hack this value to 999.
    I will search for 100, and replace 100 to 999 to alter the value?

    If for example, I have:
    obscuredintHP = 100 and I want to hack this value to 999.
    encrypedValue is 182323
    I will search for 100 and nothing will show up.
    If I search for 182323 and update the value to 999, then HP will be hacked?

    So with the obscured case, if i know to look for "182323", then it is possible to hack the HP or replace the HP to something else? So basically, any obscured value can be hacked IF they find the encrypted value? Therefore, calling RandomizeCryptoKey frequently will change this encrypted value of 182323 to something else so they have to look for the new value in order to hack the value they want to hack?

    From the hacking videos, their process is very much like the tutorial video you have where they will alter HP from 100 to 99, do a search, alter 99 to 98, do a search, etc and then replace the value.

    Also, with RandomizeCryptoKey, the doc says to call it when a value doesn't change.. what if I call RandomizeCryptoKey after a value change and then the value changes immediately? Will it cause any issue? For example, HP of player changes often, will it be bad I call RandomizeCryptoKey every time the HP changes (performance issue excluded)?

    Also, one of the reporters mentioned that they were able to hack the game's item by looking for an "ID" of an item. Does this mean there is something wrong with the obscuredtype if they were able to look for that "ID"?
    ie: obscuredInt Food Id is 283232. Hacker does a bunch of stuff but uses "283232" in the hacking process. This means that FoodId is not protected by anticheat?
     
    Last edited: Jul 14, 2021
  19. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,853
    Thank you for detailed posting @mrm83 !

    That's great, but it really worrying obscured cheating detector remains silent, as it should trigger callback event when encrypted value does not match "clean" value (i.e. it should trigger when any of them is altered).

    It seems you've set up things correctly, I'd add crypto key randomization at random timeouts but it shouldn't affect how detector works, it should trigger on value manipulation regardless.

    Sure, let's dig it up together a bit.

    Yes, you also usually need to make few subsequent searches to filter out needed variable in order to change it.

    Actually it should be different every time you start an app since crypto key used to encrypt it is randomized. Please let me know if you see opposite.

    Nothing will show up only when you do not use ObscuredCheatingDetector. Otherwise, cheater will be able to find 100 but it will be fake "honeypot" value which is stored separately from the actual encrypted value.

    Not really, first of all, you'll need to find out crypto key used to encrypt variable, reverse engineer encryption algo and then calculate encrypted value to find it at least once (to save its memory address) which is a bit advanced level.

    When you find it, and change to 999, real value will not be "999" but "999 decrypted with crypto key" which, depending on key generated, may result in negative real value.
    Also such operation should be noticed by ObscuredCheatingDetector.

    Unless you protect your entire process memory from external access (which some commercial protectors do) - it will be possible to manipulate any values, but as for obscured ones, you'll need to find encrypted values first which will require crypto key lookup and then change them with correctly encrypted values, which is not trivial for most cheaters out there.

    The main idea behind the RandomizeCryptoKey is to change value in an unexpected way so when cheater will try to look for "unknown value" and filter it by looking at how actual value changes, it will not succeed since when it will make "value not changed" step, it would actually change under the hood making that filtering step invalid.

    This will not hurt but will not help much either because of initially another usage pattern for that API I described above.

    Could you please send me those videos in PM or via contact form?
    I would be glad to take a look at the process in order to better see a flaw they exploit if it will be visible there.

    Not sure what is ID here, is it initially encrypted value or dictionary key or something else? Perhaps, video would shed a light on this as well.
     
  20. mrm83

    mrm83

    Joined:
    Nov 29, 2014
    Posts:
    332
    Right, I have in the callback to ban the user and application quit, but I dont the user being banned from online in our logs.

    I've now added RandomizeCryptoKey on game start, and RandomizeCryptoKey when certain actions are performed. ie: hp change, inventory menu open, etc. Should be good right?

    Yes, it is different, i just made up a number for example.

    Ok I dont understand this part. Why wouldn't it help much? If the encrypted value is changing all the time, it would mean they can't find the unknown value right? If they can't find the unknown value, then they can't hack the real value?

    ID is the game's item ID.
    ie: Ive got a bunch of item scriptableobjects that is used to define items, and each item has an id value to determine what item it is.
    //magicstick weapon
    private obscuredint id = 119282;

    The hacker doing a search of "119282" to change their weapon to magicstick defined by id 119282. So if they are searching for the real value of 119282 and succeed, does it mean magicstick is not being protected? So something is wrong with setup?

    Is there a way to simulate hacking the game within unity? Or would using actual tool ie: gameguardian be required?

    Also, what would happen if the obscured value gets updated at the same time as RandomizeCryptoKey call? Will this trigger false detection?
     
    Last edited: Jul 15, 2021
  21. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,853
    Thanks for confirming this.

    Could be either code patching or unknown detector vulnerability exploitation.

    I'd add calls at timeouts (i.e. just using timer with random delay in range let say from 3 to 10 seconds) so crypto key would change even when no action performed by player.

    The unknown value search is usually made using fuzzy filtering, like "value changed", "value not changed", "value increased" etc. When such search is performed, it usually includes "value not changed" step since there are lot of stuff constantly changing in a game's memory. Thus if you call RandomizeCryptoKey while nothing visually changes and cheater performs "value not changed" filtering step, it will not find your variable since it would actually change internally.

    Got it, thanks for the explanation.

    Could you please clarify if initial value was set in inspector or from code so I could try reproducing it?

    Also would be nice to see this cheating process video if you have one (please send it via PM or using contact form).

    You can use Cheat Engine if you are using Unity for Windows for example.

    No, it wouldn't since it will be called from the same main thread, thus it will run sequentially, not simultaneously.
     
  22. Leonid

    Leonid

    Joined:
    Aug 20, 2013
    Posts:
    85
    Hello!
    Probably someone has asked this before, but I still haven't found an answer.
    I have a bunch of float variables in my scriptableObjects.
    I want to change the type of these variables to ObscuredFloat.
    Could you please tell me, how can I change type of variables AND keep their serialized values?
     
  23. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,853
    Hey Leonid!

    Unfortunately, this is currently not possible to do automatically but this feature is on the short list for future updates due to high demand, stay tuned for more news on this!

    For now, you'll need to manually update values after changing serialized field type to obscured one.
     
    Leonid likes this.
  24. Leonid

    Leonid

    Joined:
    Aug 20, 2013
    Posts:
    85
    Ok, got it.
    A little workaround for ScriptableObjects.
    You can use method OnValidate() to fill new obscured variables with values from old vars, and just change all references in your code to new vars after that.
     
    codestage likes this.
  25. jjobby

    jjobby

    Joined:
    Nov 28, 2009
    Posts:
    159
    Is it possible to support Rigibody2D for wall hack detection?
     
  26. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,853
    Hey @jjobby ,

    I believe this is possible to implement, I'll consider this feature request in future updates!
     
  27. jjobby

    jjobby

    Joined:
    Nov 28, 2009
    Posts:
    159
    Thank you. I intend to build for WebGL platform. Can this plugin also detect this hacking tool?
    https://github.com/Qwokka/Cetus
     
  28. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,853
    Variables cheating attempts should be detected as usual since it uses generic universal approach.

    As for in-memory code patching, it's more native code protectors relative which is currently out from ACTk scope but something I'm aware about and plan to investigate to check what can be done from my side to resist / detect it.
     
  29. pistoleta

    pistoleta

    Joined:
    Sep 14, 2017
    Posts:
    498
    Hello there!
    We are using your asset and now we are focusing on avoiding time cheating. For one side I have the component running in scene to avoid possible cheating. For another side... I Use:
    Code (CSharp):
    1.  TimeCheatingDetector.OnlineTimeResult res =
    2.            await TimeCheatingDetector.GetOnlineTimeTask(GetRandomNTPServer(),
    3.                TimeCheatingDetector.RequestMethod.Head);
    4.  
    To get the UTC real time. Until now I was always using www.google.com but now I went to look for some ntp servers so I can randomize the server I'm querying and I found out that some ntp servers seem NOT to work by web request. Such as the apple ones for example... Is it possible that those ones need to be queried by sockets? I found weird you didn't implement it if that's the case.
    For the moment im using 5 different google ntp servers which allow web request so its not a big deal... I just wonder if we could get our game 'canceled' by those servers if we get a lot of players and all start querying those same servers all the time... thats why I wanted to have the more ntp servers the better.

    Maybe I'm just overthinking and ntp servers won't ever complain :D
    Id like to know your opinion.
    Thanks!
     
    Last edited: Aug 13, 2021
  30. codestage

    codestage

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

    Yes, NTP servers are usually work over sockets and it was my first implementation of the TimeCheatingDetector.
    I used sockets and NTP servers but later I had to switch to the more reliable solution since sockets sometimes did crashed \ freezed and worked unexpectedly in Unity on different platforms back in 2018.

    It's 2021 already and it's possible they are more stable in Unity now and I could revisit that solution to make option for the TimeCheatingDetector to use either sockets or web request, adding this to the internal task tracker for now for the consideration in future updates.

    I had similar thoughts but I couldn't find anything which could confirm or deny that and I couldn't find a way to ask google about this, they just don't have general live customer support.

    I had no complains from other customers on this matter as well, so I'm thinking it's fine to use google webpage for this kind of requests until your game gets really big and you switch to your own webpage which you'll have for your big game anyways =)
     
    pistoleta likes this.
  31. Daybringer1

    Daybringer1

    Joined:
    Jun 5, 2013
    Posts:
    4
    Greetings!


    I hope all is well.

    I have been transferred to a Unity project from 2017, though it was worked on in the 2019 version of Unity.

    They have used your Anti-Cheat Toolkit and I must say, it does make life much easier!

    But I have noticed that all of the obscuredprefs that were used in this project are not visible in the prefs editor, even though everything is working as intended, it's just that I can't see the variables. The original person who worked on the project is not accessible anymore, and I do not know what can I do to see the list. I need all the variables and their types so I could sort them out in a database. I could do that by hand by searching in the scripts one by one, but that can take weeks.

    This is an older version of your software though, but I believe that that shouldn't be an issue.
     

    Attached Files:

  32. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,853
    Hey @Daybringer1,

    Thank you for getting in touch with your problem!

    Looks like it does not finds editor prefs for some reason o_O
    Could you please clarify few things:
    1. Which ACTk version you are using?
    2. What is your operating system?
    3. Does it shows nothing even after you save prefs? even in ACTk example scene?
    4. Do you see prefs exists at their location (see below)?

    Prefs location depends on 2 variables: PlayerSettings.companyName and PlayerSettings.productName.

    Thus, on Windows full prefs path in registry is:
    Code (CSharp):
    1. var registryLocation = Registry.CurrentUser.CreateSubKey("Software\\Unity\\UnityEditor\\" + PlayerSettings.companyName + "\\" + PlayerSettings.productName);
    On Mac:
    Code (CSharp):
    1. var plistPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + "/Library/Preferences/unity." + PlayerSettings.companyName + "." + PlayerSettings.productName + ".plist";
    On Linux:
    Code (CSharp):
    1. var prefsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + "/.config/unity3d/" + PlayerSettings.companyName + "/" + PlayerSettings.productName + "/prefs";
     
  33. Daybringer1

    Daybringer1

    Joined:
    Jun 5, 2013
    Posts:
    4
    Hi,

    Sorry for the later response, I was outside.

    Let's see about these questions...

    1. Based on the changelogs, the current version in the project is 1.5.2.1
    2. Windows 10 Pro 20H2
    3. I have opened the example scene, and upon opening the "pref editor as tab" option, the familiar blank screen appeared, and I tried adding a pref, just a regular string, and clicking on the "S" saved it, but upon a refresh, it disappears. All of the other variables are as expected, invisible.
    4. Upon locating the registry entry, I have found the encrypted values. I added some test entries just to see if it works, namely "teststring" and "testchar", and they popped up in the list. The rest are encrypted so I do not know what they are, but they are there at least. They do vanish without a trace in the prefs editor though.


    One thing to note, there are spaces in the company name and product name, multiple words. Probably not the cause but just adding in as much info as I think is important.
     

    Attached Files:

    codestage likes this.
  34. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,853
    Thanks for all the additional information!
    Could you please export your registry key with all values and let me know your crypto key you used to encrypt values? Feel free to drop those via PM.

    Also, looking at the ACTk changelog, this could be a known issue which was fixed in later updates, for example I do see such line in 1.5.2.2:
    Would you like to try 1.5.2.2 update and check if bug is gone? I'd drop you that plugin version then.

    ADDED:
    Issue was resolved in PM (updating to newer ACTk version helped).
     
    Last edited: Aug 27, 2021
  35. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,853
    Hey everyone,

    Anti-Cheat Toolkit Beta last call as it coming towards stable release: you still can participate in beta and get a chance to win voucher for Anti-Cheat Toolkit 3 or any other Code Stage asset of your choice (except bundles).

    Join Discord or PM me if you are interested: https://discord.gg/TNm9hEgVp4

    upload_2021-8-30_15-18-3.png

    Stay tuned for more news!
     
  36. Leonid

    Leonid

    Joined:
    Aug 20, 2013
    Posts:
    85
  37. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,853
    Hey, it should be safe to do this and it's totally makes sense, feel free to go for it and please let me know if you'll encounter any issues with that!
     
    Leonid likes this.
  38. codestage

    codestage

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

    Full time Code Stage production

    Today, since more than 2 years after first paid upgrade and more than 8 years of Anti-Cheat Toolkit presence on the market, I'm thrilled to announce I'm starting full-time production on all Code Stage assets as an independent developer (yes, I did it in my spare time before!) and going to both keep improving existing products and release new products as well.

    This become possible with all your support, inspiration and priceless feedback over the years.
    I would like to thank you all who support me and purchases my assets at the Asset Store.

    In order to give you more ways to support my Asset Store tools development and give me a bit more room to focus on Code Stage brand and invest as much time into it as possible, you now can find and support me at Patreon and Ko-fi! ♡

    Anti-Cheat Toolkit 2021 upgrade

    With Anti-Cheat Toolkit 2021, I'm going to try a new steady and predictable release cycle which would allow keeping full-throttle production while making sure you're getting the high-quality products with decent support and lifetime:
    • release major upgrade at least once per year
    • every major upgrade keeps getting packed with new features, improvements and fixes until the next major upgrade kicks in
    • previous version gets deprecated (but still accessible for those who purchased) once new major upgrade is out to reduce possible confusion
    • existing customers are getting new upgrade with 80% off from regular price and have 90 days of grace period (you get upgrade for free if you purchased asset in last 90 days)
    That said, I'm glad to let you know ACTk 2021 major upgrade already made its way to the Asset Store!

    For the 2 weeks, it's available with 50% off from the new price for new customers!
    Existing customers get it with 80% off or for free if got v2 in last 90 days.

    And this is what to expect from it:

    Binary files protection

    In response to the high-demand feature request, brand new ObscuredFile and ObscuredFilePrefs are here to complement ObscuredPrefs and help you with binary files protection against most common cheating threats with this feature set:
    • data encryption to hide sensitive content
    • data tampering detection to react on cheating attempts
    • data locking to the device or user ID to prevent data sharing (purchased goods sharing etc.)
    Those who like more control, have ObscuredFile to manually read and write byte[] data in a flexibly way.
    ObscuredFile is able to work from background threads and has plenty of settings to let you configure it for your needs.

    To keep things simple for those who likes PlayerPrefs approach, ObscuredFilePrefs wrapper for ObscuredFile was made.

    Including best from both worlds, it allows reading and writing prefs to the binary file using simple and intuitive generic APIs while keeping your data safe:

    Code (CSharp):
    1. ObscuredFilePrefs.Set("my value", 100);
    2. var value = ObscuredFilePrefs.Get("my value", 0);
    3. // or ObscuredFilePrefs.Get<int>("my value");
    It also can be used without anti-cheat features just to let you effortlessly save your data to the binary file.

    All simple C# types, System.DateTime and few popular Unity types are supported out of the box and any other data is supported through byte[] type so feel free to use serializer of your choice to save anything else!

    Please check out this tutorial video to find out more about new ObscuredFile and ObscuredFilePrefs features:


    ObscuredPrefs update

    To make it easier to use and match ObscuredFilePrefs supported types, new generic APIs and new types were added to the ObscuredPrefs as well!
    You'll find list of new types at the full changelog below.

    Other improvements and updates

    There are much more, like improved corner cases care with automatic link.xml generation for WallHackDetector and exceptions processing, feel free to find out what's new in full changes list attached below.

    Final 2021 release note

    This is just a beginning and I'm going to release more exciting features, improvements to the Anti-Cheat Toolkit and make few new more cheap and narrowed anti-cheat products in this release cycle so please stay tuned for updates and news here, at Twitter or at the brand new Discord Server!

    For now, feel free to check out new version at the Asset Store.

    Full changes log

    [2021.0.0] - 2021-09-06

    Added
    • Add new ObscuredFile and ObscuredFilePrefs tools to the ACTk
      • Encrypted and plain modes
      • All modes have data consistency validation
      • All modes have lock to device feature
      • ObscuredFilePrefs has simple and easy to use PlayerPrefs-like APIs
      • Async compatible
      • Supports UWP starting from Unity 2019.1
      • BehaviorDesigner and PlayMaker Actions
    • Add generic APIs to ObscuredPrefs
    • Add new types support to ObscuredPrefs:
      • rest of simple C# types (SByte, Byte, Int16, UInt16, Char)
      • System.DateTime
      • Color (it's possible to save HDR colors now)
      • Matrix4x4, RangeInt, Ray, Ray2D, RectInt, Vector2Int, Vector3Int, Vector4
    • Add ObscuredQuaternion property drawer (now it's editable from inspector)
    • Add automatic link.xml generation option to complement fix for WallHack Detector false positives due to stripping
    • Add additional information to the important error logs
    • Make ThreadSafeRandom utility public
    • Add Copy Player Prefs path context menu item to the Prefs Editor tab
    • Add new support contact, let's chat at Discord!
    Changed
    • Swap Changelog to md version to better match Unity packages format (Keep a Changelog)
    • Rename following ObscuredPrefs API in order to better suite coding style:
      • OnAlterationDetected -> NotGenuineDataDetected
      • OnPossibleForeignSavesDetected -> DataFromAnotherDeviceDetected
      • lockToDevice -> DeviceLockLevel
    • Move ObscuredPrefs.DeviceLockLevel enum out from the ObscuredPrefs type
    • Introduce DeviceLockTamperingSensitivity instead of readForeignSaves and emergencyMode settings for additional clarity
    • Decimal values processing at ObscuredPrefs are much faster now with much lesser GC-allocations footprint
    • Improve exceptions handling across whole codebase
    • Improve incorrect type usage handling at ObscuredPrefs (thx David E)
    • Improve Settings UI a bit
    • Improve detectors startup a bit
    • Improve Prefs Editor error handling
    • Minor code refactoring and cleanup
    • Update some API docs
    Deprecated
    • Deprecate non-generic ObscuredPrefs APIs (to be removed in future versions)
    Removed
    • Remove .NET 3.5 scripting runtime version support
    Fixed
    • Fix possible data corruption at all Obscured types in super rare scenarios (only one rare case for ObscuredBool was found)
    • Fix possible false positives from WallHackDetector on Unity 2019.3 or newer when IL2CPP "Strip Engine Code" setting is used (thx Hesham)
    • Fix compilation warning on UWP platform
    • Fix redundant injection detector support were added into IL2CPP builds in some conditions
    • Fix exceptions in Unity 2021.2 and newer while browsing ACTk settings
    • Fix code hash pre-generation was run redundantly when building with Create Visual Studio Solution option enabled
    • Fix Behavior Tree at BehaviorDesigner's integration ObscuredPrefsExample scene
    • Fix other minor stuff here and there
     
    Last edited: Oct 19, 2021
    NathanielAH likes this.
  39. ch1ky3n

    ch1ky3n

    Joined:
    Oct 26, 2017
    Posts:
    49
    Hi, I'm planning to use Anti Cheat on my project. I'm using a playmaker, and when using Obscured Variable, should I
    Make my own script to contain those variables, and make functions to generate() and to update() those values into Fake values that can be read and written by the playmaker. so, whenever I want to update the value, I generate a fake value, change it and update the obscured value with the fake one.
    or perhaps make an AddValue(int value), and make the pm actions based on it?
    or is there any better way when using PM?

    thank you
     
  40. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,853
    Hey @ch1ky3n ,

    It's actually possible to integrate it with the Playmaker by hands, as mentioned at the "Third party plugins integrations and notes" part of the Readme.pdf User Manual there is integration example with usage details available.

    Please let me know if you'll have any further questions on this matter!
     
  41. studiolumiere_unity

    studiolumiere_unity

    Joined:
    Apr 24, 2020
    Posts:
    21
    Hello I would like to ask an additional question.
    1. Using 'File Hashes' Google Play instead of 'Summery Hash'. Do you get the same value for uploads with extension '.aab'?
    (I'm obfuscating via beebyte obfuscator asset, could this be a problem?)

    2. Do 'InjectionDetector' and 'CodeHashGenerator' functions serve different purposes?
     
  42. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,853
    Hey @studiolumiere_unity ,

    From what I've seen - yes, individual file hashes doesn't change thus for Android I'd suggest checking file hashes.
    Please let me know if you'll see file hashes changes, this is unexpected behavior right now.

    It should be fine sine Beebyte's Obfuscator does its job before CodeHashGenerator thus you get hashes for already obfuscated binaries.
    Again, please let me know if you'll encounter any issues with this.

    Yes, InjectionDetector does detects Mono Assemblies (managed DLLs) injection into the application domain at runtime while Code Hash Generator provides tools for the application code binaries integrity validation.

    InjectionDetector doesn't works with IL2CPP (since managed injections are not possible in IL2CPP) while CodeHashGenerator works for both Mono and IL2CPP builds.
     
  43. C0dingschmuser

    C0dingschmuser

    Joined:
    Mar 23, 2021
    Posts:
    3
    I've been using the v2 version for almost 2 years now and will probably also get the new version, however there are a few questions i have:

    - Are there any plans / new features to prevent runtime assembly editing?
    Variable encryption is important and probably stops most of the more unexperienced Hackers but can be completely bypassed if said hacker just edits the runtime assembly code of a important function (for example a function which unlocks stuff or adds money). I've tested and seen this first hand*. Obviously if a hacker modifies the saved game binary directly your CodeHashGenerator detects it but as of now that only works on Android & Windows which brings me to my next question:
    - When can we expect CodeHashGenerator support for iOS?

    *To elaborate more: We used Beebyte's Obfuscator in combination with IL2CPP and ACTK. We then send the Android version of our game to a 3rd person who was not directly affiliated with our game but has a little experience with game hacking in general. Within roughly one or two hours he had deobfuscated our binary(s) with a open source .net deobfuscation tool and il2cpp dumper, searched for the "interesting functions", edited the runtime ARM Assembly of said functions in Memory and was able to unlock everything thus bypassing our entire anti-cheat solution.
     
  44. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,853
    Hey @C0dingschmuser ,

    Thanks for getting in touch over here!
    Let me please try answer your questions.

    Yes, it's a high priority for me to fill this gap due to high customer demand and I'm going to look into this in order to figure out if it's possible to provide something reliable from ACTk side to cover it.

    I'll post updates on this as soon as I'll have anything to share.

    Regardless, I usually suggest to consider using native protectors for target platforms to make cheating much harder including in-memory patching. Tools like VMProtect for PC platform (which in addition to anti-debug and such does virtualizes native IL2CPP code making it more challenging for cheater to tackle with) or DexGuard for Android etc.

    I don't see ACTk will ever replace those so I'll keep suggesting using native protectors regardless since it's always a good idea to complement ACTk with external protectors for additional hardening.

    Please don't have any illusion about this even being covered with native protectors, obfuscators and ACTk or even AAA anti-cheat system for thousands of dollars per month, your app is still vulnerable as soon as its sensitive code in binaries is available to the hackers and not hosted remotely. Client-side code is not able to 100% resist cheaters with decent reverse-engineering skills.

    Just to stay clear on this, what I'm trying to do with ACTk is to cover you from "casual" / massive cheating" in first place, hopefully saving you some time you'd have to spend in order to implement similar systems yourself.

    And I hope I'll find good reliable solution to cover (in any appropriate way be it a detection or prevention) in-memory patching threat during my research on the matter.

    New platforms support for CodeHashGenerator is currently not high priority due to low demand, seems PC and Android suffered most from it and demand on this feature went down after its release for those platforms.

    That said, I'm increasing CodeHashGenerator iOS support feature request priority at the internal task tracker as you are second customer who asked for this.

    Priority gets increased when more similar feature requests pops up as I'm trying to focus on most wanted features in first place.

    I can't guarantee both CodeHashGenerator for iOS and in-memory patching detection or prevention will get it to the ACTk 2021 yet but I hope this will be possible. Please stay tuned for news about these features.

    P.S. as for your case, I'd suggest checking (with il2cpp dumper) if Beebyte's Obfuscator did properly renamed all sensitive stuff you might have in your app as it's usually not that easy to navigate over properly obfuscated IL2CPP meta. You could try contacting Beebyte support with this inquiry to find out if there's any room for improvement.
     
    Last edited: Sep 10, 2021
    C0dingschmuser likes this.
  45. C0dingschmuser

    C0dingschmuser

    Joined:
    Mar 23, 2021
    Posts:
    3
    Thanks for the quick and extensive response!

    Good to know that there's high customer demand for memory patching. I completely understand that ACTk can't stop all Hackers from hacking & am nevertheless looking forward to further updates :D
     
    codestage likes this.
  46. studiolumiere_unity

    studiolumiere_unity

    Joined:
    Apr 24, 2020
    Posts:
    21
    I have 9 hash values under Files, Should the .aab file match all 9 hashes?
    Please let me know if there is a necessary hash

    Should I also use the HasFileHash() function?
    I'd like you to point me to some simple example code that I can compare.

    ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
    Summary hash: 0D38B9974FDE10993C78188D9C6B4A1D05160FBF
    Files:
    base/lib/armeabi-v7a/libunity.so : 09F2B613F048EFFDD75CE39563D971C8CD78C47F
    base/dex/classes2.dex : 192DBAC817F92BD186B363127063E9FB1DC90527
    base/lib/arm64-v8a/libmain.so : 2CFEF78492DBB6017F9FDF751CB5B33CFB7CF5BD
    base/lib/arm64-v8a/libunity.so : 356E4DA6D6E53E0E9415AA4FCFF07B2F75DCD435
    base/lib/armeabi-v7a/libmain.so : 797F9BB0E89A4C9F100CE7E7CA0C2E531A70B920
    base/assets/bin/Data/Managed/Metadata/global-metadata.dat : 86A6624C2A7F617BCF11A012AC1A840217FF156F
    base/lib/arm64-v8a/libil2cpp.so : C5441081977E3756EECD56420F6978034821502C
    base/dex/classes.dex : D33B5A5C0470498D21908E1414F612A01701216C
    base/lib/armeabi-v7a/libil2cpp.so : EB6AB0EE62C6C6CF1ADA97062F3BEC878E1AD8D6
    ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
     
    Last edited: Sep 13, 2021
  47. studiolumiere_unity

    studiolumiere_unity

    Joined:
    Apr 24, 2020
    Posts:
    21
    I have come to enlightenment

    1. armeabi-v7a Apk Installed (from .aab 6Count Hash)
    lib/armeabi-v7a/libmain.so
    lib/armeabi-v7a/libunity.so
    lib/armeabi-v7a/libil2cpp.so
    classes1.dex
    classes2.dex
    assets/bin/Data/Managed/Metadata/global-metadata.dat

    2. arm64-v8a Apk Installed (from .aab 6Count Hash)
    lib/arm64-v8a/libmain.so
    lib/arm64-v8a/libunity.so
    lib/arm64-v8a/libil2cpp.so
    classes1.dex
    classes2.dex
    assets/bin/Data/Managed/Metadata/global-metadata.dat

    3. serverHashs (from .aab 9 Count All Hash)
    lib/armeabi-v7a/libmain.so
    lib/armeabi-v7a/libunity.so
    lib/armeabi-v7a/libil2cpp.so
    lib/arm64-v8a/libmain.so
    lib/arm64-v8a/libunity.so
    lib/arm64-v8a/libil2cpp.so
    classes1.dex
    classes2.dex
    assets/bin/Data/Managed/Metadata/global-metadata.dat

    Compare 6 files
    Check if the hash value matches any of the 9 cases

    ex) for (int i = 0; i < result.FileHashes.Length; i++)
    {
    CodeHashGenerator.HashGenerated += (result) =>
    {
    if (result.Success)
    {
    if (serverHashs.Contains(result.FileHashes.Hash) == false)
    // decomplie
    }

    Am I right the way I think?
     
    Last edited: Sep 13, 2021
  48. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,853
    Yes, you got it right: you have known files "whitelist" with their hashes and if you see something new than it's either new file (injected hack?) or modified (patched) existing file.

    Comparing file names can help distinguish new files from patched existing files in case you would like to have more accurate reaction or track unknown files you encounter (to know more about possible cheats from their file names).
     
    studiolumiere_unity likes this.
  49. ramsayamarin

    ramsayamarin

    Joined:
    Feb 10, 2013
    Posts:
    16
    @codestage To upgrade from v2 to this new 2021 release, do I just simply delete v2 and import 2021 or is there more to it? I already have a game released so I don't want to accidently create incompatibility and wipe out existing players data on an update.
     
  50. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,853
    Hey @ramsayamarin,

    This should work just fine unless you're on .NET 3.5 which is not supported in ACTk 2021.
    You also may find few ObscuredPrefs APIs deprecated or moved, just use new APIs instead (check out changelog to know more about API changes).