Game reverse engineering_Android read and write game content

1. Background

The implementation of Android plug-ins needs to involve the reading and writing of corresponding game content. Read and write game content including code and data

For different read and write objects, the general steps are to find the object address (location) → obtain the corresponding permission → read and write. The implementation is described in more detail below.

2. Implementation method

Implementations can be divided into two categories: injected and non-injected.

Injection: It needs to be injected into the corresponding game process space. The common method is to inject through ptrace and zygote.

Non-injection: It does not need to be injected into the game process space, and the game content is read and written from other places through the Android system mechanism.

Depending on the nature of the game content that needs to be read and written, different approaches can be used. Injection type is suitable for reading and writing dynamic data, such as intermediate variables calculated during the game (damage, etc.), dynamically loaded attributes (life value, etc.), game status (success flag, etc.), dynamically compiled code (Unity, lua scripts, etc.). Non-injection is more suitable for modifying static code, resource information, etc. (for games with anti-injection protection, non-injection can also be used to obtain dynamic data).

(1) Non-injection type:

1. Data modification in the private folder of /data/data/$PackageName, such as modifying SO in the lib directory (actually loading the SO library when the game is running). After obtaining ROOT permission, you can modify the contents inside. For example, to modify the main logic module, directly use a hexadecimal editor (UltraEdit and other tools) to modify and save.

2. Directly use tools such as APKTOOL to decrypt the APK file, and obtain some game resource information. The common file directories of APK are introduced as follows:

AndroidManifest.xml Every application must have, including package name, permission, Activity and other related information;

META-INF The signature information of the application is stored in this directory;

Res This directory stores resource files (image strings, etc.);

Lib This directory stores SO files;

Assets This directory stores configuration files (but the process contains resource file information);

Classes.dex Java bytecode file (compiled from Java source code);

resources.arsc Compiled binary resource file.

It can be seen that a lot of game content can be obtained in this way. For example, for some Lua engine mobile games with poor security, their Lua scripts will be stored in the Assets directory in plain text (usually named with lua or script-related characters). Another example is the Unity game, as shown in Figure 1, the compiled DLL of the C# script will be stored in assets/bin/Data/Managed/Assembly-CSharp.dll, and the game script code can be decompiled directly using tools such as ILSpy (about The auxiliary or cracked version of Unity has the function of directly modifying the content of this file).
insert image description here
3. Using the /proc file system, each process has a corresponding file in this folder (the mentioned process is of course only available during the running process), which will contain some important files, as shown in Figure 2. Some important documents are introduced as follows:

/proc/$pid/cmdline the command used to start the process;

/proc/$pid/cwd A link to the working directory of the current process;

/proc/$pid/environ list of available process environment variables;

/proc/$pid/exe link to the program running in the process;

/proc/$pid/fd/ link to each file opened by the process;

/proc/$pid/mem The contents of the process in memory;

/proc/$pid/stat Status information of the process;

/proc/$pid/statm Process memory usage information;

/proc/$pid/maps Process virtual address space usage information.

Through these files, the corresponding game information can be obtained. Among them, the mem file can obtain the memory image of the game, which means that the purpose of modifying the content of the game process space can be realized by modifying the file. For example, the Huluxia modifier implements the general modifier function through this non-injection method (the sample code in "Debug Hacks", as shown in Figure 3, can directly use functions such as read and write to read and write process content. Generally, it needs Obtain the base address information of the module with the content in the maps.)
insert image description here
insert image description here
(2) Injection:

Injected reading and writing has a strong purpose, that is, it has been determined through static or dynamic debugging that the content address can be obtained at a specific location, and then it is necessary to read and write the corresponding address content during the dynamic running of the game (involving memory reading and writing) Operation, such as memset, memcpy, mmap, strcpy and other functions). Its specific implementation is as follows:

1. After injecting into the game process space, directly modify the assembly instructions at specific locations to change its read and write logic for specific addresses. For example, the method of modifying function parameters commonly used in game plug-ins can be realized in this way: after analyzing and locating a specific function, find a parameter use point in the first assembly instruction segment of it, and change its assignment. As shown in Figure 4, a function parameter R1 of a certain game represents the energy value. Rewriting the instruction of the address in the red box into FF25 (MOVS R5, #0xFF) can achieve the purpose of dynamically modifying the function parameter to 0xFF (to achieve constant energy full plug-in function).

This method needs to understand the common read and write instructions of assembly instructions such as ARM and Thumb. For example, the write operation, the Opcode of the ARM assembly instruction MOV R3, #0 is 00 30 A0 E3.
insert image description here
2. The above method is actually the most basic injective writing method, with the simplest logic: Static analysis to the address → rewriting the page attribute (the mprotect function rewrites the attribute) → directly modifying the content. Furthermore, when some reading and writing operations need to occupy a large number of bytes, and the corresponding assembly instructions cannot be constructed at the original address, HOOK technology is required. There are two types here: one is to use MSHOOKFUNCTION, GOT table replacement, etc. to realize function address replacement, and the other is to use Inline Hook to realize function intermediate process jump. Since this article is not a HOOK topic article, a relatively simple introduction to these methods is as follows:

A. MSHOOKFUNCTION, GOT table replacement and other methods can be implemented by simply calling functions, which is more convenient. However, it has strong limitations, and cannot obtain the intermediate variable data of the function, and is limited to the reading and writing of parameters and return values.

B. The Inline Hook method is more complicated to implement, but has obvious advantages: it can read and write the intermediate operation data of the function. For example, the game has a huge attack calculation function, which involves the calculation of damage and defense power. The damage value is only a temporary variable. At this time, it is necessary to statically analyze the storage location of the damage value (which register is which position), and then use Inline Hook can read and write the corresponding data.

Guess you like

Origin blog.csdn.net/douluo998/article/details/130113203