<BLOCKQUOTE><font size="1" face="Arial">quote:</font><HR><font face="Arial" size="3">Originally posted by DCrazy:
But all the encryption functions in the world can't do jack if the executable itself is compromised.
</font><HR></BLOCKQUOTE>
Agreed. That's why I was saying that the type and extent of Anti-Cheat measures that you can use depends on your available resources. Servers, Coder(s), etc...
Like in the AA one I wrote, I have access to about 6 servers that can run any server side code I want, as well as store and distribute client updates. I routinely distribute updates via the Auto-Updater whether or not I actually did any bug fixes etc...
Without these type of resources, you'll be limited to a one shot deal, which given time will definitely be circumvented.
You hit it right on the head about CS and the rest. They aren't all hacked directly.
One of the worst hacks for AA is a hack called EvilHack.
It originally worked by attaching to the AA process and intercepting DirectX calls. I easily defeated that just by checking the modules attached to the AA process.
He then changed it over to an IAT Patch that required a loader.
The simple explanation is that was detected by checking the base address of D3D8.dll and comparing it to what the IAT of D3D8.dll was in the AA process. (system files should be the same address for every app that uses it, but not always).
Now, he uses a similiar technique to get it loaded, but has added Detours (trampoline functions) to it. Now once it's loaded it changes the IAT back to what it's supposed to be.
This too can and is detected, but because it's my current method and this is a Public forum, I'm not going to explain.
Suffice it to say that even though AA has PunkBuster integrated into it now, PB only catches EvilHack when the EvilHack user is using certain options with it. The method I'm using catches it every time.
But, enough about AA, hehe.
Another key step in writing the client is to add fuzzy code. (ie. code with nonsense and cross jumps making it
harder to trace the code without making it noticably slower)
Nothing more frustrating than stepping through code when it's full of cross-jumps and do-nothing routines. Of course that's providing you get passed the API functions that can detect the process is running under a debugger in the first place.
Once a good stable core system is built, it would be very simple for Kevin to batch the builds and do exactly like you said. Change some small things here and there, and rebuild it.
But again, any type of real system will require resources.
Now it's my understanding that D3's updater used to, or rather tries, to get it's updates from Outrage.com, which is no longer.
If somebody from the community were to buy that domain, someone who has physical access to a server, wouldn't that fix the D3 update problem?
Remember, these are just ideas I'm kicking out, the same as everyone else here. I didn't say I was going to write anything myself, all I've offered is some advice from someone who's successfully done it. Some of the things I've done in the AA one aren't applicable to D3. But maybe one of the ideas will trigger another idea from someone else that would work for D3.
Here's some little tips that I've used, note, some are written in Assembly.
Don't use meaningful procedure names.
This should be a no-brainer. If you have a function named 'CRCThis', well, what do you think the first routine that gets scrutinized is gonna be.
Use checksums in DLL's and in the EXE. Have them check each other. Far away from "safe", but it just makes it harder to crack.
Don't use literal strings that tell the user: "Sorry, but... (whatever)." These are the first things to look for. Build strings dynamically or encrypt them.
Don't use validation functions. Write your validation code inline with the current process. That just makes more cracking for the cracker and bewares of just NUL'ing out your routine.
Use "reserved" names. When using hard-coded keys or passwords, make them look like program code or function calls (i.e., "73AF" or "GetWindowText"). This actually works very well and confuses some decompilers.
The rcr/rcl trick.
If a rcr/rcl is performed on a value, it becomes much more of a pain to crack - you can't reverse it with by negating it's effects without knowing what the value of the carry flag was before the original operation. If the carry flag is created as a result of some other pain in the neck operation, you are probably onto a winner.
Like stated earlier, stick conditional jumps in. Everywhere.
Conditional jumps are not fun to reverse engineer. No loops, but jumps which conditionally bypass/include portions of your key manipulation code. There is no easy inverse operation to be performed here.
Use portions of the code as magic number tables.
(preferably critical sections). You have no idea how annoying this can be, most crackers like to change things around using softice (a popular cracking tool).
Play with the cracker's mind.
This one is fun

Stick series of nops in, as though you were doing self-modifying code (oh my god! what the heck! nops? Aha! Self-modifying code! Idiot spends next three years trying to find the code that should be there.). Pepper the code with junk instructions. Cut the code up into little pieces and put them all over the executable, with (preferably conditional) jumps between them.
Detect SoftIce. Early.
Now crash the computer. You can crash a pentium or a pentium with MMX even without a vxd by the opcode: F0 0F C7 C8 (illegal form of cmpxchg8b instruction with lock prefix). Beyond that, you have to resort to the tried and true methods. Using a vxd, take the CPU out of protected mode. Windows doesn't like that. Wonder why?
But the biggest tip/advice that I can think of, is that ALL software can be hacked/cracked.
You just have to try and make it not worth the time.