In this question on DLL injection multiple answers mention that DLL injection can be used to modify games, perhaps for the purposes of writing a bot. It seems desirable to be able to detect DLL injection to prevent this from happening. Is this possible?
There are multiple ways that you can use which might work (and see below for the reasons why they might not). Here are two:
- A process can debug itself, and then it will receive notifications of DLL loading.
- A process can host a TLS callback, and then it will receive notifications of thread creation. That can intercept thread creation such as what is produced by CreateRemoteThread. If the thread start address is LoadLibrary(), then you have a good indication that someone is about to force-load a DLL.
Other than that, you can periodically enumerate the DLL name list, but all of these techniques can be defeated by a determined attacker (debugging can be stopped temporarily; thread notification can be switched off; the injected DLL might not remain loaded long enough because it might use dynamically-allocated memory to host itself and then unload the file, etc).
What you're trying to do is very hard if the attacker is an experienced game hacker and the specifics of the cheat is unknown.
In general if you want to inject a DLL which is harder to detect and won't show up on the module list of the process you use something called manual mapping. What this does is that it emulates the behavior of LoadLibrary without putting the DLL into the process module list. Personally I'm a fan of MemoryModule. Study that if you want to understand a very common hiding technique. Even if your hack is never made public it's advisable to make sure your DLL never shows up in a crash report or something similar.
The problem is that once the fact that you're injecting into the process becomes known, your code will be reachable by the module you're trying to attack. A properly implemented client side anti cheat will enumerate all mapped memory regions and send a hash set of various offsets of all mapped memory segments to a server. The server then stores these hash sets so that if your cheat is ever made public you'll be banned retroactively.
If you want to avoid the process being able to detect your code you'll have to either wrap everything in a virtual machine and then interact with the process from outside of the virtual machine. The other weaker options are to write a driver and try to hide in ring 0, to simply create a debugger which interacts with the process or to use breakpoints and a sort of in process debugger to process hardware breakpoint events in order to avoid detection of your hooks.
A properly implemented game will not care if the client is compromised since as soon as you trust your players you have an issue. Ideally the game client would only render the state, react to the output of the server and send input to the server with all the logic server side. This is unfortunately not always possible due to latency and performance reasons. For every decision the client takes, ask yourself what the worst possible outcome of the client having that responsibility is. Because it will happen.
Patching game's executable + using loading order trick
- You should check the integrity of the games executable files before loading as there are way to patch it to load malicious Dll files, overlays if those were added (virus like)
- Check game directory for unknown dll files - strange names, dlls that mimic system library files
- Another thing is - some loader that will be placed with the name of the original file which will take care for all the things and at the end will load the actual game - so monitor the integrity of the whole game directory.
Process Injection - it does not have to be dll but some arbitrary code
- Monitor "invasion" API calls (for example) by patching
a. WriteProcessMemory b. VirtualAlloc(Ex)
f. CreateRemoteThread g. CreateProcess - with flags for Suspended state h. OpenProcess
- Create watchdog thread to monitor sensitive game memory regions for integrity
Yes, it is possible. There are a couple of generic approaches you can take for detecting injected processes (not just dlls). The first is to enumerate DLLs that are injected by the OS via registry key. The two known key/value are AppCertDLL & AppInitDLLs. The second is to search for all memory that is marked as RWX and then parse out the memory for clues of an executable file or injected code. The third is to search for private memory that contains an executable or injected code. Another approach is to search for inline hooks of APIs. Parse out the handler address and then query the memory address of the handler. The handler will likely be an injected process.
I have been doing research in this area for the past couple of weeks. My main focus is detecting injected malware. Here is a tool called injdmp that I released this week for detecting injected processes.