Today, I would like to cover 4 aspects of EFT's internals in 4 different articles:
secured comminucation, payload encryption, response caching and file
integrity scanning. These articles are mostly aimed at SuperMod author
and anyone else interested in making modding more secure.
This article will sadly be very technical since there is no other way around it. Hope the article will be enjoyable nonetheless!
Since EFT 0.12.11, there is a new capability: the data from the server is encrypted. For AKI, this is not a problem; they hook deep into EFT's code to grab the data for the server, and up until now the encryption is advisatory, not mandatory. If it ever will become mandatory, AKI has a load of work to do. Luckily I did most of the work beforehand in my research server.
This was an absolute massive pain to get working because EFT's code is a shitshow.
The payload (the data send from the server to the client) has the following properties:
– The data is encrypted using an AES-192 key in CBC mode
– The encrypted data is ZLIB compressed (RFC1950)
AES is an algorithm in which there is a key and a randomized hash (IV, initialization vector) to encrypt the payload. The key itself is easy enough to find within the game's code, but the IV is the annoying part. Since EFT rarely conforms to standards, the IV is not send the normal way. Instead, the first bytes of the payload contains the IV.
Alright, with those requirements in mind, let's write the decryption code!
In this code, _eftKey is the key extracted from the client. Inside Decrypt we grab the IV from the beginning. The rest is standard.
Sadly, this is only the first step. It's the second step I got really stuck on. You see, AES decrypts data in blocks of a fixed size. If the data is smaller than the block, it will insert 0x00 for each non-occupied byte left in the block. This is what we call a zero-bytes tail. These bytes are harmless, normally.
BUT NOT TODAY.
EFT uses ComponentAce.Compressions.libs.zlib partially with their own additional code on top for (de)compression. It is a library that can decompress RFC1950 formatted data to it's original form. ZLib is often confused with normal zip files, which generally use gzip or deflate. That's why I specify the standard here. Because EFT managed to use another non-standard method! Attempting to compress the data as deflate or gzip will cause EFT to decompress prematurely, soft-locking the game.
You see, normally it's not a problem that EFT uses zlib. However, remember the zero-bytes tail? It causes componentace's code to hang indefinetly, hard locking the game. EFT is using a non-standard implementation of AES to get rid of these bytes. This was a problem that is very hard to debug.
The fix is the following: force EFT to use my research server's implementation of zlib (de)compression, and remove the zero-bytes tail when decompressing.
In addition, this solves another issue: EFT's (de)compression doesn't support multi-threaded scenarios (which you'll see in the last article of this series), as thing my research server heavily relies on. Attempting to use their code in such a scenario causes buffer overrides, and thus malformed data, which in turn crashes the game.
Getting EFT to use my implementation is simple enough: find the method and override it to use my code
Removing the tail itself is also not too complicated; count from the end of the payload the amount of 0x00 bytes and remove it.
This is not the first time the decompression library from BSG caused grief. At this point, the amount of comments in the code is larger than the actual functionality!
From all the challenges this caused, I hear you wondering:
Was it really worth it?
…and the answer is yes! I've never written encryption code like this before, so there was a lot to learn and get creative with. Overcoming challenges makes one a better person, and more the wiser. The hardest challenge is to keep things organized and readable, especially when the concepts are very technical and often difficult to read.
I am really proud of my solution since the other options are vastly more complex. keeping things simple where it matters is very important.
Why is this important?
Securing a connection over SSL is often not enough to ensure secure comminucation. In order to prevent lowlife hackers from stealing mods, extra security is required. AES encryption is perfect from this. It is really hard to extract without the technical know-how, and conventional tools won't work due to EFT's implementation.