Author: Shawn (L. Spiro) Wilcoxen
Translator: riusksk (quange)
Preface
Escaping from the anti-plug-in system is the biggest obstacle for new game hackers today. DLL injection is the longest surviving method. Hacker technologies/tools circulating outside are the easiest to block, which can only be achieved by linking them with system functions that frequently interact with the target game. This article covers the methods for bypassing the detection of these technologies and tools. By injecting DLL to the target process only, this avoids calling hook system functions, so that these hacker tools can access any target process, if it is called directly, it may be detected by the anti-plug-in system and then scanned and killed. There are two separate codes in this article: one is the DLL file used to inject the game process, and the other is the tool used to interact with the DLL, which is mainly used to secretly obtain information about the target process.
Create DLL
DLL files are the most basic component of the entire process. We first create a basic frame structure of the DLL and then inject it into the process. There is nothing special about the DLL Code. Its source code is shown in Listing 1:
Simply call the function: Beep () to let us know whether the DLL has been injected into the target process. This DLL injection tool can be used to inject our DLL to any process, if the sound is heard, the DLL has been successfully injected and executed.
Note: In Windows 7, the Beep () function uses the default sound card. Unlike other versions of Windows, the sound is replayed to the motherboard speaker.
Note: To use Microsoft®Visual Studio®Firewall (Windows XP has been installed with minesweeper.exe "(Windows Vista or Windows 7 ), all of the above are created under Debug build (you can choose Release build on your own ). In the Debug version, press F5 to start Minesweeper and inject the created DLL using any software (such as the Memory search and modification tool MHS and CheatEngine. If it is interrupted in DLLMain () at this time, you can see that the DLL is broken when it is injected. Next, you can perform one-step or common debugging here.
Inject DLL
Before testing DLL injection, you need to find a method that can secretly inject all processes. There are several methods to inject DLL into the target. After DLL is injected into the process, the DLL can work normally without being detected. Anti-plug-in software is usually used to detect the use of CreateRemoteThread () and SetWindowsHookEx () brute force injection methods, but if you want to use these injection processes freely, you can refer to the methods described in this article: the Applnit_DLLs registry key value frequently used by non_intrusive programs is used to initialize a dynamic link library, which can call a dll list for any process, after the process starts, the dll file in AppInit_DLLs will be injected into the program to start ). The simplest way to test this method is to manually add the DLL file path to HKEY_LOCAL_MACHINESoftwareMicrosoftWindows NTCurrentVersionWindowsAppInit_DLLs in the Registry, and then load a process, such as NotePad or calculator.
Note: in Windows XP, this work is very simple, but in Windows Vista, This method may be limited due to the protection of various security mechanisms. While it can be implemented on Windows 7, the same key value (LoadAppInit_DLLs and RequireSignedAppInit_DLLs) in the Registry can only be modified through loop jumps ). For these systems, it is best to use some methods to replace DLL injection. When you set AppInit_DLLs to "F: empMyDll. dll" (without quotation marks), because this value is separated by spaces, you can only use a path that does not contain spaces. After changing the registry, open the calculator on the Windows system and you will be able to hear the sound. It can be seen that the DLL has been loaded. To restore it to its original state, you only need to delete the value in the Registry and restart it.
Communication Principle
The DLL file needs to broadcast its existence to every process in the system. If a (or more) process responds, it will "Connect" the process, and conduct more communications. There are many ways to build a Private communication network. The so-called "Private" means that the communication network will not trigger a warning inside the software. If you use SendMessage () with the HWND_BROADCAST and (WM_USER + 0x100) parameters, the anti-plug-in system will capture the message and assume that your communication network is active, the game process will be terminated.
Many methods can be used to mask network communication. One method is to detect Communication Networks Based on LAN communication. Other methods do not send messages to the target window. However, because your DLL file name should be random, only the DLL itself and the client software actually know the DLL name. If the client software uninstalled the DLL, the DLL needs to send secret information to other processes that have not loaded the DLL for further communication. This is also the method selected in this article. Client software cannot communicate in other ways, because it may damage some protection mechanisms in the game. At the same time, the DLL does not know whether the given process is a client process in advance, so the address for data sharing cannot be determined in advance. This method can be first connected through SendMessage (), and then use ReadProcessMemory () and WriteProcessMemory () for subsequent communication.
Prepare
Several key issues need to be addressed before implementing the communication layer. First, it is important to create a class for dealing with the target. This class encapsulates some system functions to facilitate subsequent rewriting and modification. For example, to directly replace the function ReadProcess (), you can use an instance in the class to call the encapsulated function. Instead, it calls the function ReadProcess (). Then, when you want to add a kernel driver to change the method of reading the process memory, you only need to simply rewrite the class function and create an instance of this class, then the code that uses this class to encapsulate the function will be automatically corrected. The following code is a class:
Establish a connection
Finally, we establish a connection with the client program through DLL and use a class to manage each connection. However, to achieve this, we must first check the client program. This seems simple, but simply sends messages to each process and determines whether the process responds. In this method, only one buffer is allocated to store the client response information, and then the address is sent to each process. If the buffer of a process is filled with response information, it is a client process. However, unfortunately, we can open multiple client program instances. If they send the response information to the same buffer at the same time, one response will be lost, the DLL can only be connected to one instance. Therefore, we need to provide a buffer for every process that may respond (basically possible. Once a response is found, we send the buffer to the class it accepts. This class processes all the communication with the DLL and responds to the client program.
Communication buffer zone
The working principle of our communication system is that every program (DLL and client) writes information to the receiving address specified in RAM, which will be continuously monitored. Each message is sent in a specific format that can be parsed by DLL and client software. This format can be constructed through struct, Consortium, and enumeration. First, the actual message type needs to be enumerated, as shown in listing 3:
Secondly, the definition of each message format is shown in Listing 4:
Finally, a consortium is used to allow a single struct to contain data in the format shown in Listing 4. For details, see Code List 5:
Note that this struct will be used in both the client and DLL.
First connection
When the DLL program is not injected with the DLL, You need to initialize the connection first. Since the DLL is to be injected into every startup process (but not limited to this), we can assume that the process not injected with the DLL will uninstall the DLL from itself, and may become the client software we want to establish a connection. In addition, if the game process is protected by an anti-plug-in system, it is difficult for malicious programs to send suspicious detection messages to the game process. Generally, all connections work the same. The client software will have a memory area, which is strictly regulated by the DLL. When a change is detected, the same buffer zone will be used to respond to messages, however, to initialize the connection, you need to send a Windows message to set all the settings. Even more complicated, the DLL does not know which client window is the first connection window, so it must send messages to every window created by the client thread. This code is simple but long. For more information about the code, see the notes in Listing 6:
Call: The following helper function is required for EnumThreadWindows (). This function is used to send a message to the client for request response. For the code, see listing 7:
M_lpcbBuffers is a class member defined by std: vector <LPHITB_COMMUNICATION_BUFFER> m_lpcbBuffers. We use it to record every initial connection and use it to determine whether or not