A client connects to a server and sends its version upon doing so. The server does not process any further requests until the client's version is validated. This seems like a simple way to do a version check but the obvious flaw is the user can modify their client to send the true version (or even the packet data sent over the network). Are there any reliable methods for version checking? Are there any precautions developers can take to prevent the "layman" from modifying their client version (excluding the obvious eg. storing the version in plain text)?
Reliable client version checking (authoritative server)
The general answer is "no, the cheater can always write a program that sends whatever bits on the network he/she wants."
The slightly more specific answer is that "on the PlayStation and Xbox consoles, the platform vendor applies enough pressure on cheaters that you, the game developer, can assume that the client is not hacked; on less locked-down platforms like PC, Android, iOS, and such, there are no such guarantees."
You're asking "are there any reliable methods of making sure the client doesn't lie to the server?"
The general answer is "no, the cheater can always write a program that sends whatever bits on the network he/she wants."
The slightly more specific answer is that "on the PlayStation and Xbox consoles, the platform vendor applies enough pressure on cheaters that you, the game developer, can assume that the client is not hacked; on less locked-down platforms like PC, Android, iOS, and such, there are no such guarantees."
I understand what you're saying...and I completely agree. Perhaps the word reliable is misleading. There is no way to determine if the client has been modified. However, are there any ways to at least reduce the chance of it happening...specifically in this scenario of version checking? I will be satisfied to know there are absolutely no other alternatives.
The problem is that, the big hurdle to overcome is for your game to be so popular that people actually want to hack it.
Once that hurdle is passed, circumventing the client-side detection mechanisms is a smaller hurdle.
That being said, I recommend multiple layers, and make some of the layers be "advisory" only (sending some bit that indicates the problem as part of your network protocol in some out-of-the-ordinary place.)
The first layer may be a file that contains the checksum of each of the EXE and DLL files you ship, as well as any scripts.
Verify each of the files on start-up. Also calculate the checksum of the checksum file, and download that from your server on login, and verify that that file has not changed.
The second layer might be wrapping all important gameplay variables in classes that shroud the actual value, and store a "checksum" value in some other part of memory.
Use a template<> that turns an int into a shrouded_int, a float into a shrouded_float, and so forth. The shrouding is typically done by XOR-ing the bit value of the variable with some number (which might be random,) as well as storing a copy of the value somewhere else (such as in a new-ed copy on the heap,) also shrouded.
Override all the operators (operator=, operator int, etc) to apply and remove the shrouding when your code needs it, as well as to detect that the check version has not changed differently from the main version.
This kind of shrouding and checksumming can prevent and detect certain kinds of memory hacks on local clients.
The third layer might be detecting injected DLLs that aren't part of what you expect them to be, and processes attaching to your process as debuggers.
You might also want to look at the names of all processes running, and some of them might indicate cheating programs.
You can keep going. Sometimes send malformed packets to the client and see how it responds. Detect timing of incoming commands; accuracy of aiming and firing; and so on and so forth.
In the end, it's usually better to know who the cheaters are server-side, and not immediately let them know that you're on to them. Instead, make it so that cheaters only match-make with other cheaters, for example.
(Xbox Live tends to do this by banning known cheaters every X months, so that it's hard to tell whether they have picked up on you or not.)
You can also use various client-side packages, such as Valve Anti-Cheat, Punkbuster, and so on.
Are these methods worth it? Is the intrusive, privacy-busting, blue-screen-causing escalation of protection software worth the negative reputation? I don't know. It depends.