Perma's Gamehacking Blog

Avoiding cheat detection

Rate this Entry
by on 02-12-2010 at 08:00 PM (1432 Views)
Anyone who has done any amount of reverse engineering for games is well aware of all sorts of modern anti-cheat tools in use today. There is an entire line-up of software designed specifically for the purpose of catching and identifying users who are employing third party programs to gain an advantage in the game.

Many authors of cheat programs work very hard finding ways of circumvention, including myself. I would like to share some of the theory behind a potential solution to the anti-cheat problem.

To begin, imagine for a moment the way a game might start loading itself into memory. You run the executable file, which in turn loads a number of dynamic link libraries into its memory space so that it can utilize their functions or classes. This is done, generally, using the standard LoadLibrary() call and can be easily tracked down within a disassembled executable file. As you may know, when a library is loaded it is allocated a certain amount of memory in the target process by the operating system, then mapped into that memory space so that it can be called and used by the program.

Consider how an anti-cheat program would have to work in order to correctly identify the memory in which it would need to search for any anomalies. In order to get an accurate base address for whatever memory location it was intending to scan, the program would need to call GetModuleHandle() if it was within the process's memory already, or some equivalent if it was searching externally. This is because of how process memory is handled in Windows, particularly in more recent versions in which the base address of any given module can be completely dynamic.

Taking this fact into consideration, one can surmise that if we could keep an unmodified version of the library we're attempting to change (for the purposes of game hacking) loaded in memory, the anti-cheat software would pick up that module instead and ignore our modified version. Of course, how do we load two different versions of the library at once and make sure that the game will use our version rather than the unmodified version? And how do we know that the anti-cheat tool won't just pick up both instances of the library?

The answer is straightforward enough. We can write a hook in the original executable file that copies the contents of the library we're modifying into some buffer after it's been loaded by the game. We can then unload the library (or close the handle on the library), and copy the contents from our buffer back into the exact memory location where the library had been mapped. This gives the game executable the impression that the library is loaded and in the correct position in memory, and preserves all of the respective calls and structures associated with those memory locations. We can then load another version of the library into memory with LoadLibrary(), leaving the handle open so that it can be accessed by the anti-cheat software. This will not affect the game, as the executable is already satisfied after loading the library the first time. We can keep this library loaded in memory so that each time the anti-cheat program scans for specific offsets (after calculating the base address of our dummy library), it is scanning the memory of the fake module and ignoring the real code where we are making our modifications.

The down side to this method is that it can be detrimental in terms of memory usage when a large quantity of libraries need to be simulated in this way; however, often times all of your modifications can be done while spoofing only a single module.
Tags: None Add / Edit Tags
Categories
Gamehacking

Comments

  1. SC_Modder -
    SC_Modder's Avatar
    This works as long as these dynamic link libraries expect to be unloaded and loaded many times (most do). Complications can arise with multiple initializations.

    However, problems arise with dynamically located APIs (IE: GetProcAddress) referring to the unmodified original rather than the modified version in memory. You will also have problems if a DLL is compiled without a .reloc section (/FIXED and /BASE on msvc, and additionally /DYNAMICBASE:NO on msvc2008). When the DLL loads a second time the initialization routines will crash and the DLL will not be loaded, unless those routines do practically nothing.

    Problems arise also if the DLLs used shared sections but those scream bad coding practice and are not used much anymore.

    And of course the issue that to the compiled application, LoadLibrary("library") != GetModuleHandle("library") could cause all sorts of strange references to wrong areas, of course that's where the circumventing occurs so it should be obvious if that's going to be problem already if you're considering using the method already.

    The method is nice because of the little work it takes to implement but must be thoroughly tested to work on the given application.
    Updated 02-13-2010 at 06:55 AM by SC_Modder
    permalink
  2. Sight -
    Sight's Avatar
    Nice read, thanks!
    permalink
  3. kds -
    kds's Avatar
    that was a good read perma
    permalink
  4. Perma -
    Perma's Avatar
    Interesting thoughts SC_Modder. I never really considered the effect that setting /DYNAMICBASE:NO would have on the loading of the library. This would definitely introduce problems, so this solution is fairly dependent on the target game architecture.
    permalink
  5. Sparkle -
    Sparkle's Avatar
    So what else is new in the world?
    permalink
  6. K? Pŕo?ćtiόnŹ -
    K? Pŕo?ćtiόnŹ's Avatar
    What if the main module writes a value to the library and then reads it and doesnt read what it wrote because its writing to your modified library and not the dummy?
    permalink
  7. Perma -
    Perma's Avatar
    That could present a problem, but there would be very few instances where an application may write over the code portion of one of its modules. All of the variables and structures referred to are handled dynamically, so if the main module was writing to those it wouldn't know the difference.

    Also, if the main module wrote to the modified library it would be doing so strictly by using the memory reference it received when it loaded the module in the first place. Therefore it's extremely unlikely that it would read from the wrong memory location, as it would already have the necessary base address for the modified library and would not need to call GetModuleHandle().
    permalink