Itās been a while since my last blog post, even though I added React support to this blog and updated some styles last year, like the new Friends.
To show this site is still alive, let me write some random words here.
Iāve written this article to document details for my own reference, but I do not support any form of game hacking.
In my spare time, Iāve played many games, and some have a difficulty system where you must clear the previous difficuty to unlock the next. This makes sense for truly challenging games, but for others, it just means wasting time on easy levels to access the harder ones. Cluckmech Oasis (鸔械绿擲), for example, requires at least 15 hours to unlock the final difficulty. Thatās why I tried to hack its save file.
Cluckmech Oasis
What we have
Most steam games will store its data under C:\Users\<username>\AppData\, for Cluckmech Oasis, it is AppData\LocalLow\BlackLight\Cluckmech Oasis.
After some basic investigation, Iām sure the saving files are danju_m.cd and quanju_m.qjcd. Additionally, we have player.log to provide more information..

Guess
If the save file is plain text, congratulations! You can modify it directly, and youāre done.
However, danju_m.cd and quanju_m.qjcd are binary files.

After checking the player log, I found:
Odin Serializer ArchitectureInfo initialization with defaults (all unaligned read/writes disabled).
Odin Serializer detected whitelisted runtime platform WindowsPlayer and memory read test succeeded; enabling all unaligned memory read/writes.
å é¤ęåäŗdanju_m_beifen.cd
This indicates that the game deletes the save file copy after initializing the serializer. Itās reasonable to guess that the save file is serialized using Odin Serializer. Therefore, I installed Odin and tried to deserialize it, but encountered an Invalid Data Stream error.
There are two possible reasons for this:
- The save files are not serialized by Odin.
- The save files are encrypted.
Regardless of the reason, if guesses donāt work, we need RE.
Reverse
Cluckmech Oasis is developed in Unity, so its main logic should be located in a file like *Assembly*.dll. It wasnāt hard to find 鸔械绿擲\Cluckmech Oasis_Data\Managed\Assembly-CSharp.dll, and I loaded it into IDA. An interesting point is that IDA couldnāt show the function names properly, likely because the original function names are in Chinese ā an obfuscation technique, perhaps.
Fortunately, I was lucky enough to find the āsaving file encrypt keyā in the code, which means the save files are encrypted.

At this point, my friend @plusls told me that using IDA for C# reverse engineering is foolish and recommended dotPeek instead. Thanks to that advice, I found it much easier to view the code in dotPeek. I quickly discovered that the save files are encrypted by AES (seems like ECB mode) using a library called ES3 (Easy Save 3).

With a parser for ES3 that I found online and the encryption key I found in IDA, I was able to get everything I needed.
<A Pixel Western Shooting GM Game>
I came across a pixel western shooting gameāletās refer to it as GM. Its save file appears to be either encrypted or serialized, so to understand its structure, I loaded the executable into IDA. I discovered that itās built with GameMaker and compiled using YYC (YoYo Compiler).
For traditional GameMaker games, tools like UndertaleModTool are available to decompile them. However, since GM uses YYC, itās not supported by most existing GameMaker decompilers, UndertaleModTool also can not extract useful information from data.win like other GameMaker games. I spent some time to learned about YYC, it seems like not a easy work for reverse engineering: https://github.com/AurieFramework/YYToolkit/wiki/About-VM-and-YYC.
An alternative approach is to use YYToolkit, which operates at runtime. Iāve confirmed that YYToolkit can retrieve runtime information from GM.
The next step is to write a mod for GM that hooks into specific functions weāre interested in. This video tutorial is a good starting point: https://www.youtube.com/watch?v=sK8Cv7W_qlY.
Overall, itās been a fun journey exploring the inner workings of GameMaker and learning how YYC affects the reverse engineering process.
<A Unity Platformer Game>
While testing a small unity game, I found a save file that appears to store the payload inside a small C#/.NET-style binary wrapper.
The bytes before the payload, such as:
B6 18
are most likely a .NET 7-bit encoded integer, commonly used by BinaryWriter.Write(string) / Unity-style C# serialization.
This value seems to represent the payload length in bytes:
B6 18 = (0xB6 & 0x7F) + ((0x18 & 0x7F) << 7) = 3126
So if the payload size changes, this length field must be updated. For example, adding 6 ASCII bytes changes:
B6 18 -> BC 18
The trailing 0B should remain after the payload as the end marker.
More
If I found new game with encrypted saving file, I may update here.