Gamers are an enterprisey bunch. You don’t give them enough X, so they go prodding around your game’s memory to try to give themselves more. Programs that have this purpose are called “Cheat engines”. Usually, how they work is a multi-step process.
The typical, and perhaps smartest way, to deal with this problem is to ignore it. A well architected game system will have any multiplayer values centralized on a server which means that a cheat engine will only mess around with a client of the game, and there are ways of checking for those hacked clients as well, (because they can give players a minor advantage). However it bears an interesting topic of discussion- how do you prevent this?
With some considerations, I have determined a method to do this- each time a value is assigned, generate a new random value, store that, and then only store a version of the original value that was encrypted. The idea being that the existence of the “actual” value- the value the cheater would be able to identify- is transient and only exists in limited scopes, making it nearly impossible to find the correct value to change, and even if they do find it, the method of encryption/hashing means they would need to know the corresponding algorithm and number in order to turn a new value they wanted and store it in memory so the Obfuscated
The trouble with this method lies in the fact that it is anything but transparent, and requires copius code changes all over the place.
Generics and Templates are the obvious solution to this problem. With C++, this sort of class nearly writes itself, actually; since templates are a compile time feature. you could then replace values that are int with something like Obfuscated
Being that I work primarily in C#, however, this was the focus of my attentions. And it is not quite as simple, though thankfully the addition of dynamics to the language really helps make the code more concise for this sort of purpose.
Everything seems to work fine initially; you can create a generic class Obfuscated
Dynamics to the rescue, however. Thanks to C# 4.0′s addition of the dynamic keyword, which introduced late-bound variables, we can actually make the call relatively simple. we can perform operators on dynamic variables and the call will be resolved at run-time, and will be handled appropriately even for the primitive types.
With that out of the way, there was only one question left: the encoding. I decided on a simple interface that allowed to decode and encode a arbitrary set of bytes. I implemented a simple xor encryption and used that for my tests. The tricky portion is of course getting some arbitrary set of bytes representing a variable of your generic type; this isn’t something you can really force with constraints. You really need a Type T that is either a structure or a serializable value. For this purpose I created two general purpose generic methods:
First, the method to convert a given value of a Type P to a array of byte [] :
If it is a ValueType, we use the Marshaller to get the actual in-memory representation of the structure, copy it to a array of bytes of the appropriate size, and then return that. Otherwise, we try to save it to a MemoryStream using a BinaryFormatter, slurp out the contents of that memorystream, and return that array of bytes to the caller. The corresponding function that turns a given array back into the corresponding type is obviously just the reverse of this:
by replacing a variable of a given type T with an Obfuscated
The Full source to my test project which contains and uses this class is attached:
Memory Obfuscation Class
718 total views, 4 views today
This is a old blog post that I seem to have forgotten to publish when I originally wrote it.
-BC_Programming
When you write a computer program, you are providing the computer with instructions on how it should work with values in memory using the Processor to perform a task. managing the allocation and deallocation of blocks of memory is memory management.
With some programming languages, the burden of implementation is on the programmer. For example, in C, most non-trivial applications are going to need to allocate and free blocks of memory. These are done by the now ubiquitous malloc() and free() functions, present in the C standard Library. What makes this interesting is that it breeds a pattern of memory usage, whereby— with the exception of bugs — memory is only allocated when it is being used by the program; the idea is to deallocate memory blocks as soon as they are no longer going to be used. This has an advantage in that it is ideal for reducing the memory footprint of a program, which is essential if that program runs on an embedded device or otherwise needs to keep a close eye on what it’s allocated. However, there is a tiny drawback with this approach- freeing memory, of course, takes processor time away from other tasks. A negligible amount, but it does; particularly when you perform a bunch of free() calls on smaller memory blocks as opposed to freeing the entire thing a single time.
In any case, with this pattern, there was of course a lot of repetition- Every allocation needs a corresponding free- and only one, otherwise you end up with bugs from freeing the same block of memory twice. This bred Design patterns- basically, constructs both within the language as well as via frameworks that made this task more automatic, so that developers could focus on their goal. With the advent of C++ and Object oriented constructs, there came RAII, or “Resource Acquisition Is Initialization”; the basic idea is that resources are allocated in the constructor of objects, and deallocated in the corresponding destructor; since destructors are guaranteed to run when an error occurs (well, with the exception of using balls-up hardware or a power failure or something) this generally guarantees that the memory is reclaimed. But, on the other hand, if an error occurs, the program will probably be left in an inconsistent state, to the point where it ought to be restarted; and once a process exists, all major operating systems will deallocate the process memory. (that is, leaks cannot last past the lifetime of the application leaking), so it’s questionable whether it is all that important. Also, all it really does is move the semantics; now instead of initializing and deallocating variables, you are initializating and deallocating class instances and calling members of those instances that correspond to the values you would have allocated as variables. Generally speaking, the concept is to manage the larger data structures in your application in a fashion that means destructors will deallocate it if anything goes wrong.
PCs have, for quite a number of years, had plenty of memory; even “low-end” machines like a Pentium 2 with 256MB of RAM don’t need to have program that use the absolute minimum amount of memory at all times; there is quite a bit of “leeway”. As a result, methods of trying to deal with the allocation and more specifically the deallocation of memory so that there is less worry on the programmers side as to whether they free’d a variable, should free a variable, or may have forgotten to free a variable, as well as allowing a slight speedup from not forcibly deallocating everything at the first opportunity. The use of a “Garbage Collector” typifies the implementation of this sort of technique.
Contrary to what some might believe, Garbage Collection is not tied to your language; you can use a conservative Garbage Collector in a language like C or C++ if you wanted to. However, typically, there are two things people are arguing against when they argue against the use of a Garbage Collector:
Sometimes, they bring up the point to argue against any sort of language that doesn’t leave clean-up in the programmer’s hands, such as Python or even D. These are the two most common, though. Both of these employ a Garbage Collector for memory management. Neither has a clear way to explicitly deallocate a class instance you created; you generally just allow variables and instances to go out of scope and become inaccessible at which point the Garbage Collector will determine it can clear it and will do so.
The arguments “Against” garbage collection generally come in the form of something like “it makes programmers lazy” or “it’s not REAL programming” or “it’s slow/wasteful”.
All of these, however, are false. It doesn’t make programmer’s lazy, programmers are lazy by definition, that’s why we use functions and subroutines rather then duplicating that code all over; that’s why even in C and C++ design patterns have sprung up to make it easier to deal with manual memory management. Having to manage memory manually doesn’t mean a programmer is lazy; and anybody who thinks managing memory manually is somehow “better” is simply stubborn; especially since they are already using predefined routines for allocation and deallocation anyway (malloc()/free()) what they are usually arguing about is deterministic memory usage; with manual memory management (malloc/free) you can practically tell how much memory your program is using by simply keeping track of what you allocate and deallocate. With Garbage collection, you don’t actually deallocate anything, and when that memory is actually deallocated is not deterministic. This results in two things:
People using System.gc() to force the garbage collector to run, and people complaining about the “jumpy” nature that the allocated memory looks like in a graph. One should never run the garbage collector manually unless they have a good reason; running the garbage collector takes time, and that time is almost always better spent doing other things in your application. The Garbage collector will run on it’s own when needed. The second is overanalysis- the overall footprint of memory usage remains the same, the only thing that changes is how much of that memory is actively holding “active” data. eg. A game written in C++, assuming no memory leaks, might appear to only use more memory during some scenes or intense action, then quickly go back down after that scene is over. A Java or C# Game may instead appear to have it’s memory balloon and stay there for some time. This is simply because they are different; C++ programming typically employs the RAII pattern- (Resource Allocation Is Initialization)- which will result in unused memory instantly being deallocated/destroyed. C# and Java’s Managed memory model puts that task in the hands of the Garbage Collector, which cleans up in a generational fashion. Eventually, the memory is freed. The real question is, Do you really need that memory? Worst case scenario is it get’s swapped out due to other memory demands, but by that time the GC will have kicked in. And even if it does get swapped out, deallocation by the GC will not “touch” the page so it won’t actually need to be swapped back in to be deleted unless something needs to be read from it.
346 total views, no views today
The next version of BASeBlock, which I have dubbed version 2.5 since that seems like a sensible update from 2.4- will use the .NET framework 4.0 and will be compiled with C# 4.0. Previously, all work was done in Visual Studio 2008, which of course doesn’t work with anything past Framework 4. After working in VS2010 some with BCDodger and starting to shift to it for general programming, I decided it was time to at the very least upgrade BASeBlock so I can enjoy the new features of VS2010. After doing so, I figured- in for a penny, in for a pound- and upgraded the targeted .NET framework to 4.0.
Some big advantages from this move, aside from having a few more language features at my disposal, include the DLR (Dynamic Language Runtime) which should allow the relatively easy addition of scripting capabilities much like I have for C# and VB.NET for languages like Python And Ruby. Another advantage that I wasn’t expecting was the improvements to the CLR which actually give the game another +20 frames per second on average just for the debug build.
Another nice thing is that this upgrade does not affect Mono compatibility- though it doesn’t work there because I use some windows specific platform/invoke in a few locations. Replacing those with appropriate platform specific equivalents as needed would fix those issues.
The idea for BASeBlock was to have it Open Source. The problem with that is that my connection is no longer uber awesome like it used to be, meaning that even uploading the binaries can take upwards of an hour. The source files would take significantly more time. THe Source for earlier versions is still available on the main downloads page entry for BASeBlock . When I get the ability to do so I will either upload the source separately or have it as part of the same installer package (optional feature).
The source will probably be licensed under the BSD license. Note however that this will only extend, at least for now, through the actual BASeBlock program. It uses a few satellite assemblies, such as “BASeCamp Update Library” Which will probably remain closed for the time being.
Currently, I am trying to get Polygon blocks working properly with the GameCharacter. Naturally, this is not that easy since a lot of the code with collision detection on the Gamecharacter is reliant on the fact that all blocks are rectangular. I have something that half-works so far, with a few errant issues that I need to fix; if I can’t I will simply revert it to the old detection and declare Polygon blocks and gamecharacters incompatible for the time being.
254 total views, no views today

Categories
Tag Cloud
Blog RSS
Comments RSS
Last 50 Posts
Back
Void « Default
Life
Earth
Wind
Water
Fire
Light 