Developers Club geek daily blog

1 year ago

Kind hour, % %USERNAME! In my previous article "Steam CEG from Valve and what it is eaten with. Introduction" was given only abstract understanding and the principles of work of the CEG technology. In this article there will be on an absolute minimum of the theory also a prevailing majority of practice. Today and now we will consider whether it is possible "to disaccustom" to this protection the treasured performed file.

Step of I. Choice of "victim" and its analysis

Existence of CEG, and any version, it is possible to find easily on existence in heading the file of the section .version and the first four bytes in it (78 56 34 12):


Obviously knowing this information and a little poryskav in Steam library, my choice fell on HD reprinting of legendary Age of Mythology with the Extended Edition prefix. After a successful completion of loading, having waited couple of seconds until CEG signs the performed file, we open it in our debugger, in my case in x64dbg. Ah yes, It should be noted that the companion of CEG uses some means of anti-debugging therefore we will use ScyllaHide plug-in with the following settings:


So, having opened the performed file, we see that it is not covered by third-party packers therefore we can safely pass to the second step.

Step of II. Blamestorming session

Absolutely in any CEG version there is one function which makes the general calculation of the necessary values. It looks as follows:


Knowing it, we put bryak or on the instruction
mov eax, dword ptr ds:[ecx] ,
or on following:
mov dword ptr ds:[ecx],eax :


We click "Run" (F9) and we see that bryak worked! "And what it gave us?" — you ask, I answer: exact EAX value in the buffer. It is possible to be convinced of it, having looked in the right column opposite to the CPU tab:


Apparently from the image, we received EDB88320 value. Let's copy it in a clipboard and we will go further. We click "Step Over" (F8) two times and we are one of functions used by CEG inside. And here at this stage It is necessary to tell a couple of words about the existing types of such functions. Actually, all them there can be three types:

1. Functions with constant value (Constant) — return constant value which will always be identical. Patchatsya as:
mov eax, <значение> ret ;
2. Functions with accidental value (Random) — return any whole value. Patchatsya as:
mov eax, <значение> ret (are used only on the latest CEG versions);
3. Protective functions (Protect) — are the pointer which lead to true function of Patchatsya as:
jmp <адрес> .

Now let's return to our game. We in desired function and at us are in the buffer the correct value. Now we have to define a type of our function. Having scrolled couple of instructions down, we will see that the instruction is used
lea eax, dword ptr ds[esi+ebx] :


And it can mean only one — we deal with function which returns constant value. In general, it is necessary to remember that if in the EAX buffer there are values of type: EDB88320, 60, 11, 5, 3f, etc., will be clear at once that function which uses this value — will be constant. Why? Because it is "well-known" constant CEG values, they will be identical on any CEG version. Therefore, we move to the beginning of function and we adjust it, changing on
mov eax, EDB88320 ret :


So, that further? And further we again repeat everything (certainly, having the same bryak on function which calculates values) until game is not started (Profit!), that means that we underwent all testing of CEG. In total?! Well let's look. We save the file with the done patches and we try to start on other PC (on which game was already obviously downloaded). And here … fiasco. Game does not want to be started! Ah yes, we forgot about one more important part! The matter is that CEG as it was told in the first article, uses so-called file checks. Having again opened a debugger, we will be able easily to find these checks on existence of characteristic functions of remarkable WinAPI: GetFileInformationByHandle, CreateFileW, OpenFileById, StringFromGUID2, RegOpenKeyExW, SystemFunction036 and lstrcmpiW. At our game — there is only one such check, it is possible to find it at once having typed GetFileInformationByHandle into search engine of "References":


We go to the beginning and we look for function which causes this check (PKM-> Find references-> To Selected Address (es), or the CTRL+R keyboard shortcut). It will look as follows:


Well, let's make it! Though it can be made also more sophisticated method, but we will act simpler, using
mov eax, 1 ret


We save result of the done work and we test the second time and about Gods, game was started on other account Steam and on other PC!

Step of III. Complete untying of game from Steam (Yarr! Edition)

Certainly, after the derived pleasure, there was a wish more extreme. And what if I just want to play with the friend on a lokalka without everyone Steam as bearded times there? Well not a question. For this purpose I downloaded the excellent Steam emulator with partial support of overlay (!) under the name SmartSteamEmu. Having configured it, I started game without the included Steam. And what I see — the file * was created. STEAMSTART and game hung in processes. Having thought about thirty seconds, game was started and worked regularly. But why? We it seems made everything, so? Yes, it so, but we forgot about one small stroke. The matter is that this file of an event is created when process of Steam is not started and in fact is the last micro check. Well, we open a debugger for the third time and we look for all functions with CreateFileA. Without hesitating, we put bryak on all functions (in this case their of everything two). At game start bryak worked:


STEAMSTART, we see you! So, to finish this misunderstanding, simply we change upper JE for JNZ or JMP:


We save a patch, again we try to start game without Steam having crossed fingers. And voila — game was started in read seconds! We made with you it, CEG, you forgive us.

Actually, output

The got CEG in the game Age of Mythology: Extended Edition was not difficult. In this game there was neither Protect, nor Random of functions, only one Constant that considerably simplified a task. Also in this game there were no minor checks, in the form of old kind CRC or the newest checks of the ID processor or serial number of the hard drive.
In the future, I hope, I will be able to master these two new checks and to write new article for now — to fast meetings!

This article is a translation of the original post at
If you have any questions regarding the material covered in the article above, please, contact the original author of the post.
If you have any complaints about this article or you want this article to be deleted, please, drop an email here:

We believe that the knowledge, which is available at the most popular Russian IT blog, should be accessed by everyone, even though it is poorly translated.
Shared knowledge makes the world better.
Best wishes.

comments powered by Disqus