Emotet’s Use of Cryptography Presented by the VMRay Labs Team
The group behind Emotet is the prime example of a very successful criminal enterprise. Emotet started out as a banking malware but over time evolved into a large botnet providing something akin to a malicious IaaS (Infrastructure-as-a-Service). It started providing access to its extensive list of infected devices to other threat actors and their malware (Trickbot, Dridex, IcedID). It started acting as their loader. Since the beginning of 2021, after a longer “break” which was the consequence of a coordinated take down of Emotet’s infrastructure by the law enforcement, Emotet resurfaced on the 14th of November 2021. Actively trying to rebuild its own infrastructure utilizing Trickbot. Many of the techniques stayed the same, but there are also some important differences.
The Emotet binaries, which were distributed starting from November 2021, come with two embedded elliptic-curve-based public keys of the server. The previous versions were using RSA as the primary asymmetric scheme. An RSA public key was embedded in the sample and used to encrypt the generated AES-128 key before sending it back to its C2. For message integrity, the packet was hashed with the SHA1 algorithm and the hash was appended to the request message. The new version comes with two public keys. One key is used for the Elliptic Curve Diffie–Hellman (ECDH) key exchange protocol while the other is used as part of the signature verification by the Digital Signature Algorithm (DSA). In this blog post, we’ll be looking at how Emotet uses elliptic curve cryptography to protect the network communication and verify the authenticity and integrity of the commands received from its C2.
View the Analysis
Background
Comparison: Past vs Present
Since the cryptographic part has changed in the newest version of Emotet we are providing a high level overview of the key steps taken by the older and new versions.
The previous version of Emotet that were using RSA roughly followed the following steps when encrypting a message:
- It generates a 128-bit AES key.
- Encrypts it with the server’s public key.
- Constructs the message sent to the server.
- Encrypts the message and hashes the message.C = SHA1(M) || AES128(M), where C is the resulting ciphertext and M is the plaintext message
- This results in the following request packet.R = RSA(AESkey) || C
For the newest version the flow and the packets it generates are different as seen below:
- It first generates its own ECDH public/private key pair.
- Then it generate an AES key based on a secret agreement.
- Constructs the message and hashes it.
- Encrypts the resulting payload: C = AES256(SHA256(M) || M)
- Request packet is then given by: R = ECDHmal_pub_key || C || <random bytes>
Elliptic Curve Diffie-Hellman (ECDH) Key Exchange
For the ECDH to work, the two communicating parties need to each have a key pair, a private and a public key. The public keys are points on an elliptic curve and are generated based on the private keys. The public keys are exchanged, i.e., known by both parties. For example, if s is a private key and P is a primitive element on the curve, then the public key S is calculated as sP=S, which is simply adding P to itself a times. The addition is a group operation. If both parties generate their public keys that way based on known domain parameters, they can calculate the same secret T(SM) (1).
The malware already has the ECDH public key of the server. Its own key pair is generated during the execution. Analogues to the example above, it can now generate a secret from the public key of the server and its own private key. Now it only needs to sends its public key to the server for the server to also be able to derive the same secret.
Implementation
Usage of ECDH
The Emotet’s cryptographic components are now utilizing Microsoft’s Cryptography API: Next Generation (CNG), most notably the BCrypt cryptographic primitive functions. Initially, the malware decrypts the two embedded public keys of the server (ECDH and ECDSA). It uses the same decryption method as with other strings. The keys are saved inside a BLOB structure which consists of a BCRYPT_ECCKEY_BLOB header immediately followed by the key data (Figure 2).
The ECDH public key of the server is passed to a function responsible for generating the symmetric key (256-bit AES key). On a higher-level it can be described by the following steps:
- Generate a new ECDH key pair for the malware.
- Generate a secret agreement based on the malware’s private key and the server’s public key.
- Derive an AES key from the secret agreement using SHA256 as the key derivation function (KDF).
In more detail, this function’s first step is to generate an ECDH key pair that is unique to the malware sample. It does so by calling BCryptOpenAlgorithmProvider to initialize a CNG provider with the AlgId ECDH_P256 which corresponds to the prime256v1 or P-256 elliptic curve. Next, it generates a new key pair using the combination of BCryptGenerateKeyPair and BCryptFinalizeKeyPair. The keys are then exported into a BLOB using BCryptExportKey for later use (Figure 3).
Having finalized its key pair, it now imports the servers public key to be able to use it in the generation of a shared secret. It’s using BCryptImportKeyPair that gets the public key as one of the arguments and returns a handle to it. This handle can then be passed to BCryptSecretAgreement together with a handle to it’s own key which it got in the previous step from calling BCryptExportKey (Figure 4). At this stage the secret agreement is equal to the T(SM) value from Figure 1 and Emotet can start deriving a symmetric key.
Usage of the Elliptic Curve Digital Signature Algorithm (ECDSA)
The server’s ECDSA public key is used to verify the response messages the malware receives. The server’s DSA public key is imported just like ECDH public key was. When an encrypted response from the server arrives, it is first decrypted with BCryptDecrypt (no padding is used). It then calculates the SHA256 hash of the decrypted data and uses BCryptVerifySignature to verify the integrity and authenticity, i.e., that it matches with the embedded signed hash – signature (Figure 6).
Conclusion
We have looked at one of the updated components of Emotet which involves the usage of cryptography. The most obvious element is that the malware developers switched from the RSA algorithm to using elliptic curves. Emotet has been encrypting its communication for a long time, but the recent change might be due to a lot of factors like, e.g., smaller key sizes and better security. The C2’s response is now checked for its integrity and authenticity by using ECDSA with a separate key. While using ECDH the symmetric key is never transmitted over the wire and instead the server generates the key from the public key of the malware. We have also observed the switch from CryptoAPI to CNG, which might be due to the fact that the CryptoAPI has been officially deprecated or that it simply didn’t support elliptic curve cryptography.
IOCs
Initial Sample 7443d5335a207cca176825bd774a412e72882c815206c7f59ace1feb111bb4e9
Server’s ECC keys
ECDH: 86M1tQ4uK/Q1Vs0KTCk+fPEQ3cuwTyCz+gIgzky2DB5Elr60DubJW5q9Tr2dj8/gEFs0TIIEJgLTuqzx+58sdg==
ECDSA: QF90tsTY3Aw9HwZ6N9y5+be9XoovpqHyD6F5DRTl9THosAoePIs/e5AdJiYxhmV8Gq3Zw1ysSPBghxjZdDxY+Q==
References
https://www.cert.ssi.gouv.fr/uploads/CERTFR-2021-CTI-003.pdf
https://www.europol.europa.eu/media-press/newsroom/news/world%e2%80%99s-most-dangerous-malware-emotet-disrupted-through-global-action
https://blog.malwarebytes.com/threat-intelligence/2021/11/trickbot-helps-emotet-come-back-from-the-dead/
https://link.springer.com/book/10.1007/978-3-642-04101-3
https://nakedsecurity.sophos.com/2017/08/10/watch-out-for-emotet-the-trojan-thats-nearly-a-worm/
https://unit42.paloaltonetworks.com/unit42-malware-team-malspam-pushing-emotet-trickbot/
https://www.virusbulletin.com/virusbulletin/2019/10/vb2019-paper-exploring-emotet-elaborate-everyday-enigma/
https://docs.microsoft.com/en-us/windows/win32/seccng/about-cng
https://docs.microsoft.com/en-us/windows/win32/seccng/cryptographic-primitives
https://docs.microsoft.com/de-de/windows/win32/api/bcrypt/ns-bcrypt-bcrypt_ecckey_blob