Security and access specifiers

I somewhat knew that public variables can be changed by memory editor software, I wanted to be sure, so I made a little test using “Cheat engine”, by using this code.

public int a =101;

void Start(){
        StartCoroutine(Count ());
}

void OnGUI(){
        GUILayout.Button(""+a);
}

IEnumerator Count(){
        for(;;){
            yield return new WaitForSeconds(2f);
            a ++;
        }
    }

Result: http://gyazo.com/0010223afdcfb943904f4190d8298e0b

Test Two, private and protected:

private int a = 5;
protected int b = 100;
	
void Start(){
	StartCoroutine(Count());	
}
	
void OnGUI(){
	GUI.TextArea(new Rect(10,Screen.height/2,120,30),"Private int a: "+a);
	GUI.TextArea(new Rect(10,Screen.height/2+40,120,30),"Protected int b: "+b);
}
	
IEnumerator Count(){
	for(;;){
		yield return new WaitForSeconds(2f);
		a++;
		b++;
	}
}

Result: Screenshot - 0517f5b8f0d4f580552e54b8ac067916 - Gyazo

Private and protected types can be found and edited same as public.

Public variable can be easily found an changed to any integer.
So my question is:
Only way to keep variables safe is by only using private and protected access specifiers? If so, that means most variable accessing should rewritten, which is a pain.

Or are there other method for keeping run-time data safe, thanks!

Any experience and hints very appreciated.

There is no universal way to keep run-time data safe.

One way you can keep your run-time data safe is to break value-types into multiple variables and use a getter to combine those. This method is still only effective against memory editors, as the code (at least C# code) can easily be decompiled from the assemblies. Native code can of course be decompiled into assembly and anyone with sufficient knowledge can figure out what you’re doing.

The key to preventing this decompilation (from being fruitful) is obfuscation.

Let’s consider your example. You have variable a, which you proved can easily be found with at least one memory editor. The way you could secure this data is to use variables a1 and a2, which split the responsibility of describing a value. In other words, you could have half of a in a1, and the other half in a2. Alternatively (possibly more secure) is to randomly add to either value). Then in a public int GetA() function sum the variables and return it. You would also need setters to determine which variable is being added to etc.

Same as above in code:

    private int a1;
    private int a2;
    
    public int A{
        get{ return a1+a2; }
        set{ 
            int temp = value/2;
            a1 += temp;
            a2 += value-temp;
        }
    }

And so many people complain how useless getters/setters (properties are the same thing) are…