ProtectedInteger - Protect your game from memory editors

This code will prevent memory editors from easily being able to scan for a protected value in your game

public class ProtectedInteger {

        private int value;
        private int key;
        private static Random RND = new Random();
        
        public ProtectedInteger(int x) {
            set(x);
        }

        public int get() {
            return (~value) ^ key;
        }

        public void set(int value) {
            key = RND.nextInt();
            this.value = (~value) ^ key;
        }

        public void increment() {
            set(get() + 1);
        }

        public void decrement() {
            set(get() - 1);
        }
        
        public void add(int x) {
            set(get() + x);
        }
        
        public void dec(int x) {
            set(get() - x);
        }
    }

version without java.util.Random:


public final static class ProtectedInteger {

        private int value;
        private int key;
        private static long x = System.currentTimeMillis();

        private static int rnd() {
            x ^= (x << 21);
            x ^= (x >>> 35);
            x ^= (x << 4);
            int a = (int)x;
            int b = (int)(x << 16);
            return a^b;
        }

        public ProtectedInteger(int x) {
            set(x);
        }

        public int get() {
            return (~value) ^ key;
        }

        public void set(int value) {
            key = rnd();
            this.value = (~value) ^ key;
        }

        public void increment() {
            set(get() + 1);
        }

        public void decrement() {
            set(get() - 1);
        }

        public void add(int x) {
            set(get() + x);
        }

        public void dec(int x) {
            set(get() - x);
        }
    }

I know its not foolproof, anyone who knows Java ASM would be able to hack through, or patching the default constructor of Random() or something, but its enough to deter noob cheaters.

Test case:


    public static void main(String[] args) {
        ProtectedInteger val = new ProtectedInteger(10);

        for (int i = 0; i < 100; i++) {
            System.out.println(val.get() + " " + val.value);
            val.increment();
        }
    }

Outputs:


run:
10 -386515262
11 74483033
12 -1122491933
13 1118343985
14 762439197
15 -985898577
16 881353416
17 422096154
18 1505261334
19 121576051
20 17291655
21 -96702182
22 966360379
23 -1895779012
24 865142212
25 -1383423927
26 -589614975
27 1189690637
28 1072681489
29 161160089
30 -277172843
31 -302291489
32 -943339751
33 2101492437
34 1659792334
35 -1899310279
36 -1644697812
37 -705545973
38 -2093534530
39 -175402530
40 2057488254
41 -347530170
42 1502839416
43 283446646
44 -950056026
45 -5485854
46 1449997393
47 638291025
48 1349261190
49 -769018597
50 1951975830
51 -95943249
52 922065223
53 1911112935
54 1786356626
55 189190580
56 -1929887166
57 771225551
58 487991180
59 1895992282
60 970346814
61 -136259347
62 190481433
63 -391566216
64 -244039267
65 -1558266925
66 1090033047
67 1949180994
68 -867907562
69 -1447792821
70 -851498719
71 521997521
72 -1361123344
73 99077230
74 1730843655
75 1399665494
76 -918123877
77 -319369290
78 -359374539
79 1095699465
80 -1028016978
81 1566878876
82 1841794486
83 -2014225033
84 1012541623
85 -940605984
86 -1139109650
87 1808573676
88 1697456487
89 1260259679
90 -242734332
91 -1512041962
92 -228034694
93 -513819170
94 1750318446
95 1865684026
96 -1717677497
97 1202705953
98 1146459803
99 -508867389
100 -1395769789
101 -1185984196
102 56068681
103 -1419021223
104 -730578283
105 -1019730625
106 -290345062
107 1102347527
108 -1759749726
109 1915150644
BUILD SUCCESSFUL (total time: 0 seconds)


Cool stuff :slight_smile:

Sorry, I know nothing about memory editors, but why couldn’t someone read both the key and value and do the bitwise operations themselves?

From what I remember, they are based on this principle

  • Find a handle of the memory block;
  • Just change the memory;

The way you find memory block handle is:

  • Search all the handles and check their value. Lets say you currently have 150 money in game. You search for handles that contain data equal to 150.
  • There are literally thousands if not millions of values stored in memory. Just so many you can’t just “pick it”
  • If you create even a single “key” value with random long value, and the person is not seeing it in game, it is practically impossible for usual people to get their way to the “real” money.

Most people cheat in games by scanning for known values, rescanning when they change and locating the memory addresses of these values then freezing them to a certain value.

Cheat Engine does this through the WinAPI ReadProcessMemory and WriteProcessMemory which scans your games virtual memory into a buffer, repeatedly compares it to the search value and listing all memory addresses that match.

What this code will do is prevent memory scanners from easily being able to locate the value in memory, thus effectively preventing most noob cheaters from being able to find and modify the value in memory. Its just a thing you can add to prevent noobs from easily hacking your game, but it wont stop determined cheaters, they have full control over the system and can do things like patching java.util.Random, modifying the Java ASM of your binary or even replacing the entire class with something different, just take it as a little thing you can add to stop noobs from getting high on your leaderboards.

I added the bit negation part to make it harder to locate the value if they did something like patch java.util.Random#nextInt to always return 0 for example.

It’s a very basic encryption implementation for your Integers, so a memory editor won’t find the field because you are searching for the plaintext, which doesn’t exist in memory and it is encrypted.

Don’t use java.util.Random. Use a custom generator or ThreadLocalRandom. A simple custom generator inside the class would reasonable.

ThreadLocalRandom is JRE7 only. Random is probably the easiest, and your custom generator is just as prone to being hacked (patching currentTimeMillis) but anyway I did this just for completeness sake:


public final static class ProtectedInteger {

        private int value;
        private int key;
        private static long x = System.currentTimeMillis();

        private static int rnd() {
            x ^= (x << 21);
            x ^= (x >>> 35);
            x ^= (x << 4);
            int a = (int)x;
            int b = (int)(x << 16);
            return a^b;
        }

        public ProtectedInteger(int x) {
            set(x);
        }

        public int get() {
            return (~value) ^ key;
        }

        public void set(int value) {
            key = rnd();
            this.value = (~value) ^ key;
        }

        public void increment() {
            set(get() + 1);
        }

        public void decrement() {
            set(get() - 1);
        }

        public void add(int x) {
            set(get() + x);
        }

        public void dec(int x) {
            set(get() - x);
        }
    }

Don’t use Random just because it’s stupidly slow.

Hey if cheaters are making java.util.Random always return [whatever]

Why not just run a check to see if you ask java.util.Random to give you two random numbers and if they are the same you know the user is cheating.

Once someone is bothered to see how it works…whatever extra thing you do doesn’t make a difference.