Stellaris – Enabling Achievements With Mods All game versions

Stellaris – Enabling Achievements With Mods All game versions 1 - steamlists.com
Stellaris – Enabling Achievements With Mods All game versions 1 - steamlists.com
In this new educational guide, I show you the basics of software reverse engineering (SRE). I show you how, starting from what we know, we arrive at what we are looking for.

Note: It is generally frowned upon to do SRE on a game, game developers generally don’t like it, what is normal. In this case I explain how this can be legitimely useful to do in the “What we know” section.

Disclaimer: Even if you like this guide, remember that you should not upload the modified Stellaris executable to download sites, as well as you are not allowed to share it with any other person. Sharing this file is totally illegal and could get you in troubles, please don’t try. Just share a link to this guide will be enough, and thus you will perhaps contribute to arouse new vocations, Knowledge is the key :s

Note to Paradox Interactive: Please don’t waste your efforts banning this method, this will be really difficult for you to counter and easy for us to workaround (we could teach each others on how to unpack binaries it is not that hard :s) Ideally to fix this you need to allocate more people on translating this title, it’s unacceptable to have to play in Frenglish, Italenglish, Spanenglish, seriously a project of this mature shouldn’t even need a mod for translations, and in this case, if you had done all this properly translated, yes it would be logical to disable the mods if the checksum does not match but only on important and untranstable files.

 
 

Installing Ghidra

 


 
Stellaris - Enabling Achievements With Mods All game versions 
 
Stellaris - Enabling Achievements With Mods All game versions 
Ghidra is a software reverse engineering (SRE) framework created and maintained by the National Security Agency[1] Research Directorate. This framework includes a suite of full-featured, high-end software analysis tools that enable users to analyze compiled code on a variety of platforms including Windows, macOS, and Linux. Capabilities include disassembly, assembly, decompilation, graphing, and scripting, along with hundreds of other features. Ghidra supports a wide variety of processor instruction sets and executable formats and can be run in both user-interactive and automated modes. Users may also develop their own Ghidra extension components and/or scripts using Java or Python. 
 
In support of NSA’s Cybersecurity mission, Ghidra was built to solve scaling and teaming problems on complex SRE efforts, and to provide a customizable and extensible SRE research platform. NSA has applied Ghidra SRE capabilities to a variety of problems that involve analyzing malicious code and generating deep insights for SRE analysts who seek a better understanding of potential vulnerabilities in networks and systems. 
 
Follow the installation instructions at https://ghidra-sre.org/ (requires Java 11+) 
 

Arch Linux advice

 

 
Little advice for my brothers under Arch Linux πŸ™‚ 
 
The following 3 versions are available 

  • community/ghidra[4] (official package, debugger is not enabled) 
  • aur/ghidra-git[5] (fork of official package, debugger is not enabled) 
  • aur/ghidra-dev[6] (debugger enabled)

 
If you just need Ghidra for the guide, community/ghidra[4] will suffice and will do all what you need. 
 
aur/ghidra-git[5] is a fork of community/ghidra[4], with it you will build Ghidra completely from the sources on the master branch at every new commit made on Github. It has no debugger because it is currently in development on another branch. 
 
I’m personally using and maintaining the aur/ghidra-dev[6] package, it is defined to use the debugger branch, it is faster to build with parallel mode enabled, and I enabled the debugger by pointing the package to the debugger branch on Github. I initially forked it from aur/ghidra-git[5], but it is now a rework from scratch to better follow the recommendations of Ghidra’s developers with a cleaner PKGBUILD master file. 
 
With aur/ghidra-dev[6] you can now have a disassembler and a debugger side by side in early preview (because it is not released yet), but it’s fully functionnal and really amazing to use. 
 
 

Installing Ghidra script : savePatch

 


 
Stellaris - Enabling Achievements With Mods All game versions 
With Ghidra, it’s very easy to understand and modify an executable, whether it is compiled for Windows, Linux or MacOS. 
 
But currently a very interesting feature is missing which should see the light of day soon. Currently with Ghidra, you are able to patch an executable in the own ram memory of Ghidra, it is called “Patch Instruction” but in order to be able to commit the patch in the executable on the disk, you will need to install a Ghidra script called savePatch[2]. 
 
In order to install it, please follow these instructions : 

  • Start Ghidra
  • If you see NO ACTIVE PROJECT as the picture below create a new one File > New project

Stellaris - Enabling Achievements With Mods All game versions 
 

  • Give the project the options of your choice

Stellaris - Enabling Achievements With Mods All game versions 
 
Stellaris - Enabling Achievements With Mods All game versions 
 

  • Run the CodeBrowser tool

Stellaris - Enabling Achievements With Mods All game versions 
 

  • Hit the Display Script Manager button

Stellaris - Enabling Achievements With Mods All game versions 

  • Hit the Create New Script button

Stellaris - Enabling Achievements With Mods All game versions 
 

  • Select Python and name the script as SavePatch.py

Stellaris - Enabling Achievements With Mods All game versions 
 
Stellaris - Enabling Achievements With Mods All game versions 
 
Stellaris - Enabling Achievements With Mods All game versions 
 

Stellaris - Enabling Achievements With Mods All game versions 
 
Stellaris - Enabling Achievements With Mods All game versions 
 

  • And finally, hit the Save button

Stellaris - Enabling Achievements With Mods All game versions 
 
Congratulations, your Ghidra installation is all set and we can start right now with the real deal πŸ™‚ 
 
 

What we know

 


 
Stellaris - Enabling Achievements With Mods All game versions 
 

  • The localization of Stellaris is partial, even if the game is translated into different languages, all translations still contains English to a point rarely matched in a game of this stature. 
     
  • Installing a translation mod, like this excellent one[3], disables the unlocking of Steam achievements
    Stellaris - Enabling Achievements With Mods All game versions 
    It’s a bad choice of architecture that has never been fixed by the PDX developers, surprising for a grand strategy game that has been in development for years, you will imagine that they push perfection to excess, but no, far from it, sadly… 
    Hopefully they will not work to ban my method because they would be really stupid and would prove to the whole world that they would rather waste their time instead of working to improve their product. 
    Technically if you want to ban my method, no problems, but allow the installation of translation mods without breaking the Steam Achivements too !
     
     
  • The game checks the integrity of certain files, and if it does not match, Steam achievements are disabled. 
     
  • A file named checksum_manifest.txt located in the root of Stellaris directory is apparently used in the integrity checking system.

 
Regardless of the file content, the name of the checksum_manifest.txt file seems like a good entry point to understand the integrity checking system, you will understand very soon. 
 
 

Analyzing Stellaris

 


 
Stellaris - Enabling Achievements With Mods All game versions 
The first step is to analyze with Ghidra the structure of the executable file of the game (stellaris on Linux, stellaris.exe on Windows, etc …) 
 
This step is better known as disassembling the Stellaris binary executable. 
 
In order to start the analysis, please follow these instructions : 
 

  • Start Ghidra
  • Drag and drop the Stellaris executable onto the Ghidra project (stellaris.exe on Windows or stellaris on Linux) and validate

Stellaris - Enabling Achievements With Mods All game versions 
 
Stellaris - Enabling Achievements With Mods All game versions 
 

  • Wait for the initial import to complete

Stellaris - Enabling Achievements With Mods All game versions 
 
Stellaris - Enabling Achievements With Mods All game versions 
 

  • Right-click on the binary > Open With > CodeBrowser

Stellaris - Enabling Achievements With Mods All game versions 
 

  • Answer ‘Yes’ to the question and leave the default options checked

Stellaris - Enabling Achievements With Mods All game versions 
 
Stellaris - Enabling Achievements With Mods All game versions 
 

  • Stellaris - Enabling Achievements With Mods All game versions 
    Take a coffee, have a break, this process can be very long (~1h on core i7). Wait until you see no more activity on the status bar. (the larger the size of the executable, the longer this step will be, 40MB is already big) 
     
    Stellaris - Enabling Achievements With Mods All game versions 
    In reality most of the executables are much smaller in size, good developers often take the time to split their code into * .dll and * .so libraries. 
    It is a fairly typical bad practice in the video game industry to put all the code in a single executable to end up with a gigantic executable. Some studios are not even ashamed to publish sizes even beyond 100MB. It’s pretty ridiculous and often indicates that the development team is building very poorly structured code…

Stellaris - Enabling Achievements With Mods All game versions 
 
Stellaris - Enabling Achievements With Mods All game versions 
 

  • In the CodeBrowser, hit File > Save All (this will save the analysis in the ghidra project and this eliminates having to analyze the executable each time you restart Ghidra until the next update)

 
Well done, the analysis is over, it’s only a matter of minutes now to find what we’re looking for πŸ™‚ 
 
 

Discovering the point of interest

 


 
Stellaris - Enabling Achievements With Mods All game versions 
Now that the analysis of the executable is finished and saved, we can therefore search for our first point of interest, the point which will bring us closer to what is to patch to activate the achievements permanently. 
 
Do you remember the name we found in step “What we know”, checksum_manifest, now is the time to use it. 
 
We are therefore going to find out which part of the executable’s assembly code calls on the checksum_manifest.txt file, please follow these instructions : 

  • In the CodeBrowser, go in Window > Defined Strings and wait for the strings to load

Stellaris - Enabling Achievements With Mods All game versions 
 

  • In the Defined Strings window, search for checksum_manifest and click the entry found

Stellaris - Enabling Achievements With Mods All game versions 
 

  • Did you notice ? When you clicked the line in the previous step, the Listing window has automatically been synchronized and now it highlights the position of the string “checksum_manifest” in the .rodata section

Stellaris - Enabling Achievements With Mods All game versions 
 

  • The interesting part is the one annotated below, it means that the filename checksum_manifest is used in only 2 places which are both in the same method called CalculateGameFilesChecksum(), peanuts! 
    Now double left-click the red annotated area below to directly go to the referencing code

Stellaris - Enabling Achievements With Mods All game versions 
 

  • This puts us directly inside the CalculateGameFilesChecksum() method

Stellaris - Enabling Achievements With Mods All game versions 
 

  • Now we will activate the decompiler to understand a little better where we are. Now left-click the Decompiler tab as below

Stellaris - Enabling Achievements With Mods All game versions 
 

  • Did you notice ? In the window named “Decompile” the cursor is automatically placed on the same line as the one selected in the “Listing” window, you can even select the entire line for better readability

Stellaris - Enabling Achievements With Mods All game versions 
 

  • It would be interesting to stop here to analyze what this method does or to replace the return variable of the method, but in reality we want to make it much simpler. 
    Because this method is quite huge to handle, the further we are from her, the better. Instead we will find out the referencing code from where this CalculateGameFilesChecksum() method is called. 
     
    To do this we select the first line of the method as below

Stellaris - Enabling Achievements With Mods All game versions 
 

  • The interesting part is the one annotated below, it means CalculateGameFilesChecksum() is called from the InitGame() method. 
    Now double left-click the red annotated area below to directly go to the referencing code

Stellaris - Enabling Achievements With Mods All game versions 
 

  • We are now 4 lines away of the solution, well done πŸ™‚

Stellaris - Enabling Achievements With Mods All game versions 
 
Congratulations ! you just found the code responsible for checking whether the integrity of files is valid or not. Now you have to understand it and patch it in the simplest and cleanest way possible. 
 
 

Understanding the code to patch

 


 
Stellaris - Enabling Achievements With Mods All game versions 
One of the best options that Ghidra brings is its decompiler, it is able to translate assembly code into C code so that the program is easier to read. And in my opinion, it does that even better than IDA Pro, another paid disassembler that was the only one to offer this option for several years. 
 
There are several very useful informations that we can take from decompiled C code. 
 
Stellaris - Enabling Achievements With Mods All game versions 
 
Stellaris - Enabling Achievements With Mods All game versions 
strcmp() is a C method which does string comparison, a return value of 0 means strings are equal 

  • The official md5 hash for Stellaris v3.0.1 (c04b) is 43cd71b239a1a03991f563e6206ac04b 
  • The calculated md5 hash of your local files is in the ppcVar16 variable 
  • A string comparison is performed with strcmp() between the official md5 hash and the calculated md5 hash 
  • If they are equal, 0 is set in the variable iVar9 
  • And if iVar9 is equal to 0, also means CAchievementsManager::SetValidated(TRUE) 
  • And if iVar9 is equal to 0, also means FillCrashReporterChecksumInfo(FALSE)

 
There are several ways to correct this code, the shortest (2 bytes to modify) and fastest one is most definitely; If we manage to patch iVar9 so that it always contains 0 (regardless of the previous call to CalculateGameFilesChecksum), the integrity check will always be successful and we will be able to unlock achievements even with the mods enabled. 
 
Note: It won’t even trigger the alert Paradox Interactive seems to have maliciously concealed to be alerted to integrity test failures with the FillCrashReporterChecksumInfo(iVar9 != 0) instruction :s 
 
 

Patching Stellaris

 


 
Stellaris - Enabling Achievements With Mods All game versions 
 
Now let’s take a look at how this strcmp() method works with a side by side view. 
 
Stellaris - Enabling Achievements With Mods All game versions 
Stellaris - Enabling Achievements With Mods All game versions 
 
In assembly language, a conditionnal check is often represented by the CMP with the JNZ/JMP instructions or TEST and CALL instructions. 
 
Without going into details, here what we can see is that iVar9 is actually the EBX register, and if we manage to force EBX to be 0 all the time, the file integrity check will still run with success regardless of the call to strcmp πŸ™‚ 
 
The magic is in the XOR instruction. 
 
Stellaris - Enabling Achievements With Mods All game versions 
XORing an operand with itself changes the operand to 0. This is used to clear a register[7] 
 
In this case, we will use XOR to clear the EBX register to 0, we will replace

TEST EBX, EBX

by

XOR EBX, EBX

in order to force EBX to always contain 0 
 

  • In the CodeBrowser, right-click on the line containing the TEST EBX, EBX instruction and select Patch Instruction

Stellaris - Enabling Achievements With Mods All game versions 
 

  • Edit the TEST instruction, change it to XOR and press Enter

Stellaris - Enabling Achievements With Mods All game versions 
 

  • Notice the Listing window has been updated

Stellaris - Enabling Achievements With Mods All game versions 
 

  • The Decompile window as well

Stellaris - Enabling Achievements With Mods All game versions 
 
As you can see, the change we just made is visible directly in the decompiler. Thanks to Ghidra ! That confirms that this is exactly what we were looking to do ! 
 
Now keep in mind that these changes are currently residing in Ghidra’s ram memory. We need to send them to the executable on the hard disk. 
 
This is where the previously installed SavePatch script comes in. 

  • In the Listing window, don’t just click but select all the line XOR EBX, EBX

Stellaris - Enabling Achievements With Mods All game versions 
I insist on the fact that if you want SavePatch.py ​​to work correctly you have to select the whole modified row and not just click through 
Stellaris - Enabling Achievements With Mods All game versions 
 

  • In the toolbar, click the Display Script Manager button

Stellaris - Enabling Achievements With Mods All game versions 
 

  • Scroll the list down, select the SavePatch row and click the Run Script button

Stellaris - Enabling Achievements With Mods All game versions 
 

  • In the new window, navigate to the root of the Stellaris folder, select the stellaris executable and click Save Changes to overwrite the original executable

Stellaris - Enabling Achievements With Mods All game versions 
If you don’t see this screen but another instead, it means that you have wrongly selected the row in the Listing window, git gud at selecting ;s 
Stellaris - Enabling Achievements With Mods All game versions 
 

  • And finally in the Console window, you will see something similar to this

Stellaris - Enabling Achievements With Mods All game versions 
 
Stellaris is now patched. So you can, provided you have activated the IronMan mode, unlock the Steam achievements while having mods enabled. 
 
 

Credits

 


 
[1] https://www.nsa.gov 
[2] https://github.com/schlafwandler/ghidra_SavePatch 
[3] https://steamcommunity.com/sharedfiles/filedetails/?id=2457286454 
[4] https://archlinux.org/packages/community/x86_64/ghidra 
[5] https://aur.archlinux.org/packages/ghidra-git 
[6] https://aur.archlinux.org/packages/ghidra-dev 
[7] https://www.tutorialspoint.com/assembly_programming/assembly_logical_instructions.htm 
 
 

Changelog

 


 
04/17/21 – Initial guide creation 
 

Written by class101 [linux]

Hope you enjoy the Guide about Stellaris – Enabling Achievements With Mods All game versions, if you think we should add extra information or forget something, please let us know via comment below, and we will do our best to fix or update as soon as possible!
 
 
 
 


5 Comments

  1. With the recent “Overlord” expansion I felt like giving Stellaris another go. While patching my game, I found an even faster way to do it:

    All you really need is the Checksum from the game, which Paradox conveniently provides in the launcher as well as in the game itself. You’re looking for a 4 digit Hex-Code. For the 3.4.3 Version of the game it was for example “9d15”. If you can’t find it, you could also look it up on the patch site (https://stellaris.paradoxwikis.com/Patches).

    Now instead of searching for “checksum_manifest.txt” you right away search for the Checksum. You should find it as part of an even lager string e.g. “66bbe22a06c30e4f4e2f7941b6ff9d15” for version 3.4.3. After you click on the string you see in the Listing Window all the functions that use that string.

    As of Version 3.4.3 there were 4 function calls. If you jump into the first function (simply double click on it), you should find the following lines (the overall structure is important; your registers and functions could have different names):

    LEA RCX,[s_66bbe22a06c30e4f4e2f7941b6ff9d15_141911…
    CALL FUN_141722c70
    MOV ESI,EAX
    TEST EAX,EAX
    SETZ DIL
    CALL FUN_1403118b0

    And there again you find your “TEST EAX,EAX” line, which needs to be modified in the way outlined in the article.

    If you have trouble finding the correct function, look at the lines below each call in the Decompile View. You’re looking for something like this:

    Bevor XOR-Patch: FUN_140312530(uVar12,iVar7 == 0);
    After XOR-Patch: FUN_140312530(uVar12,1);

    If you find something like this, you have the WRONG function:

    iVar2 = FUN_141722c70(“66bbe22a06c30e4f4e2f7941b6ff9d15”,puVar12);
    if (iVar2 != 0)

    Cheers

  2. I don’t know what’s the reason why it looks differently on the screenshots but my guess is, that is has something to do with the fact, that Steam works on Linux.

    I have, however, figured it out for Windows:

    As written by “Anonymous” and “Nebula”, I also didn’t find the function call for “CalculatedGameFilesChecksum()” but some “XREF[1,3]: FUN_140fc74f0:140fc7546(R)”. The name of the function is irrelevant! Just as Steam described with “CalculatedGameFilesChecksum()” double click on the “FUN_140fc74f0:140fc7546(R)” function and then open the Decompiler.

    The function in decompile-view looks totally different then on Steams Screenshots but don’t worry. When you scroll to the top the first line should be something like “void FUN_140fc74f0(longlong param_1)”. Right click on the function name => References => Find References to FUN_140fc74f0″.

    A new window should open where all the function calls are listed. In my case there where 2 entries (one “UNCONDITIONAL_CALL” and one “DATA”). Since I want to find the place in the code that calls this function, I selected the “UNCONDITIONAL CALL”.

    The decompile-view should change (since you’re now in a different function) and the function call is highlighted in yellow. If you scroll down a few lines you find again the string-compare function (strcmp) that Steam mentioned. Left click on it and it will also be highlighted in the listing-window. For me it looked something like that:

    1401135ca e8 d1 fe CALL strcmp
    39 01
    1401135cf 8b f0 MOV ESI,EAX
    1401135d1 31 c0 TEST EAX,EAX

    And once again, just 2 lines below you find the “TEST EAX,EAX” line that Steam described. It is possible, that your register has a different name but it doesn’t matter. From here on just proceed as described by Steam, change the “TEST” part to “XOR” and write the changes back to the stellaris executable.

    Hope that helps.
    Happy Achievement hunting πŸ˜€

  3. Same for me when I try to do it like in the screenshots.

    “CalculateGameFilesChecksum()”, doesn’t seem to be there anywhere.

    From there it doesn’t really look like in the screenshots afterwards.

    Still thank you for the guide and thank you in advance for any help.

  4. Thank you very much for your detailed guide!

    I followed your instructions to the letter.
    However, for me it only works up to the point where i’m looking
    for “checksum_manifest”.

    It looks a bit different than your screenshot
    and instead of showing “CalculateGameFilesChecksum()”
    it says something like this:

    XREF[1,2]: FUN_140fc0420:140fc0476(R)

    When i try to progress from there it doesn’t look like
    anything in your guide anymore.
    What can i do to fix this?

    Also i’m on Windows 10.

Leave a Reply

Your email address will not be published.


*