We recently focused on the latest banking malware: Citadel. The Zeus source code release has made possible the creation of new banking malware, and Citadel is one of them. One of its particularities is the possibility for the customers to request and / or suggest the implementation of new features, so that the malware becomes as close as possible to their expectations.
This post presents the steps performed in order to decrypt the configuration file of a specific sample, which contains all the targets, web injections and other parameters of the malware.
Network
The first step consists in observing the malware network connections as it will likely try to retrieve its configuration file and thus give us a first information to guide our research.
We observe two POST requests to the malware’s C&C:
The two pieces of data sent have a respective size of 128 and 123 bytes, and are unfortunately encrypted.
The C&C then responds by sending data back, also encrypted, of 15kB and 408kB, but also adds an interesting HTTP header:
Content-Disposition: attachment; filename="%2e/files/cfgkass.bin" Content-Disposition: attachment; filename="%2e/files/cit_video.module"
The first query returns a file named cfgkass.bin. We believe that this is the configuration file.
The second file, bigger, might be a plugin responsible for video capture, as we have for SpyEye.
Curiosity now drives us to study how the malware handles the received data.
Encryption mechanisms
If we follow the progression of downloaded data in the malware code, we quickly spot a complex encryption function, whose number of rounds and key size reminds us some block cipher algorithms.
A Google search on some of the constants used quickly drives us to AES with a 128 bit key.
Once the AES decryption has been performed, a basic XOR loop, already present in Zeus but also in SpyEye, is responsible for finally making the data readable:
We now face a clear-text configuration file whose structure is identical to that of a Zeus configuration file, which confirms the source code reuse. We can also see that the version section indicates 1.3.1.0.
If we try to decipher the contents of the requests sent by the malware with the same algorithm, we get nothing readable, indicating that other algorithms are also used. Indeed, if we look for the source of the data sent by the malware in the execution flow, we notice an RC4 encryption function.
Using the same encryption key and replacing AES by RC4, we are able to decrypt the sent data:
Again, this structure was also used in Zeus when communicating with its C&C:
- 0×14: data size
- 0x1C: number of sections
- 0×20: MD5 of the following data
Then for each section:
- 0×0: Type (4 bytes)
- 0×8 and 0xC: size (4 bytes)
- 0×10: data
Now let’s find the origin of the encryption key, to determine if it is “hardcoded” in the binary or dynamically generated.
If we go back a few functions from the AES decryption, we face the following code:
- The function called get_rc4_blob “deciphers” (a simple XOR) an area of the binary which contains an RC4 permutation table (which reminds us of Zeus, again);
- The MD5 hash of a KEY string is then computed. This string is also present in the binary, and represents a sequence of 32 hexadecimal uppercase characters (this time, it is SpyEye that comes to mind);
- The MD5 hash is then encrypted using the previously extracted RC4 table, and the result is used as the AES decryption key.
Having previously implemented tools to dynamically retrieve the encryption keys of Zeus (RC4 permutation table) and SpyEye (string of 32 hexadecimal uppercase characters), we simply combine both to get the keys to the Citadel