02 Jun

Enigma’s EP_CryptDecryptBuffer internals

For one of my private projects, I needed to decrypt some data. Original executable uses Enigma's EP_CryptDecryptBuffer function but I needed to implement the same thing using .NET. Much to my surprise, there was no information about what encryption algorithm is used by Enigma or how it works internally. So, I started by compiling Enigma's sample project CryptBuffer and debugging the executable.

TL;DR - IDEA cipher in CBC mode, password = MD5(user_password), IV for CBC comes from IDEA.Encrypt(8-zeroes, password).


After protecting my executable with Enigma, few assembly lines

got changed into something horrible that looked like an Enigma's VM:

I didn't feel like spending my time on analyzing that. Much easier solution was to put hardware breakpoints on my data and password and wait for them to trigger. In a few seconds I landed into code that looked like MD5 (notice the constants!):

and few hits later I landed into code that I didn't recognize at first:

Delphi compiler had helpfully included RTTI information telling me that this second piece of code belongs to a class called TIdeaCipher. Now I had all the information I needed, I just had to put it all together. smile

Implementing decryption in C#

There aren't many IDEA implementations in C#. In fact, there are 2: by BouncyCastle and by LexBritvin. Since I'm not a big fan of huge and complex libraries like BouncyCastle, so I took the simplest possible code: from Github and modified it a bit.

First, we need change password generation algorithm to use MD5 to generate real password:

Second, we need to add support for CBC mode. It requires both calculating correct IV value and pre/post-processing each block we're encrypting or decrypting.

Calculating IV is quite simple:

Processing each block is slightly harder but not a rocket science either. As explained in image borrowed from Wikipedia:

Before decrypting the data block, we need to store the encrypted values as IV for the next block. After decrypting the block, we need to XOR each byte of data with a corresponding byte of IV. Unfortunately, during encryption the data flow is different, so the simple crypt function has to be replaced with 2 functions: encrypt and decrypt.

Few more cosmetic changes and that's it! We got clean and nice implementation of EP_CryptDecryptBuffer in pure C#. smile
Download link: https://bitbucket.org/kao/ep_cryptdecryptbuffer/

Have fun!

P.S. My implementation only supports cases where data length is divisible by 8, adding support for other lengths is left as an exercise for the reader.

3 thoughts on “Enigma’s EP_CryptDecryptBuffer internals

  1. Great job kao as always and, as always, thanks for sharing.
    I'm sorry if I focus on the least important detail but can you, please, detail a bit the following step?

    "Delphi compiler had helpfully included RTTI information telling me that this second piece of code belongs to a class called TIdeaCipher."

    My only guess (forgive me for being a newbie) is that some *code* (not just some object files or dlls) of the protector is compiled and linked with your executable.

    You could, of course, answer like 'Oh my! Grab a version of Enigma and try on your own!' ... and that would be a perfect valid answer :)

    Best Regards,

    • I intentionally skipped over that part, as it's not really relevant to the subject. :) I'll do a short answer now and make note to do it in more details some other day..

      Enigma Protector is written in Delphi. It doesn't matter in what language your executable is written - when you protect your executable, protector code is added to your executable. This includes all the runtime information that Delphi compiler generated for Enigma Protector. So far, so good?

      In Delphi there is a special pattern for object creation which is quite easily recognizable. Delphi compiler also includes RTTI (run-time type information) in the compiled executable, which includes type names. The only challenge is to find it.

      So, I had landed on the address 004DB61C. Right-click code in IDA and choose "Xref graph to...". It will look like this (ignore the function names for a second):

      You can see that all calls are coming through sub_4bd9e0. Look at the disassembly (still ignoring function names):

      This is the object creation pattern I was looking for:

      When you look at the data (TIdeaCipherClass), it a has very recognizable structure and also a name.. :)

      So, that's how I knew which crypto algorithm is used..

  2. WoooW! Thank you so much kao for your answer and for the time you spent to explain to me these details, making screenshots and code listings! This is in fact NOT a short reply and it answers precisely my question, thanks again!

    I'm not a good IDA user and, even if I saw the "xref graph" option, I never understood its usefulness ...
    Moreover you "disclosed" some Delphi reversing tip like the object creation pattern, and this will be of great help in future too.

    So, what can I say? You're awesome!
    I'm only afraid I'm sure I won't be able to reciprocate your continued help :(

    Best Regards,

Leave a Reply

Your email address will not be published.