Banking Trojan Banjori Analysis Report

Banking Trojan Banjori Analysis Report

August 23, 2019 | Adeline Zhang

1 Sample Introduction

Banjori is a banking trojan that has been active since it was first spotted in 2013. It identifies personal online banking users in France, Germany, and the USA as major targets. After infecting a user, the trojan injects a malicious payload into the user’s active processes and collect the user’s information. Banking trojans and Banjori are mainly used to steal information via browsers.. Compared to Internet Explorer and Chrome, Firefox is a more sought after target for Banjori, which steals the majority of user information via query of hook and database files of the browser. It is worth noting that this family started to use the then modern dynamic domain generation algorithm (DGA) to obtain C&C server addresses in 2013. This renders the traditional blacklist of antivirus software ineffective, but also creates conditions for destroying andtaking over the Banjori botnets.

NSFOCUS Security Labs have tracked this family for one year and detected a total of 1,499 related botnets. This number is still increasing each month.

2 Sample Execution Process

The sample first drops malicious code onto the heap and then starts to infect other processes by means of injection. Malicious code injected works the same way, but with different types of behavior. This is due to the fact that different entry points are specified for the code. There are three such entry points, indicating three execution stages.

The first stage takes place within the malicious process. Malicious code is first decompressed and dropped into its own heap space and then skips to the entry point for first-stage execution.

At the first stage, the following tasks are fulfilled:

  1. Inject malicious code in the heap into all active processes.
  2. Hook the CloseHandle function of the injected processes.
  3. Set a flag bit for the injected processes to avoid repetitive injection. Replace the byte at offset 0x51 in the PE header of kernel32.dll loaded by an injected process with “@”. Then the DOS section of the PE header changes to “Th@s program cannot be run in DOS mode”.

The second stage takes place within the infected processes. After calling the CloseHandle function, the hook set at the first stage “jumps” to the entry point of the second stage.

At the second stage, the following tasks are fulfilled:

  1. Continue to inject malicious code into all active processes for persistence.
  2. Create a puppet process svchost and inject malicious code into this process.

The third stage takes place in the svchost process. Remote threads created at the second stage now come to the entry point of the third stage.

At the third stage, the following tasks are fulfilled:

  1. Use DGA to dynamically obtain C2 domain names to bypass malicious name detection by antivirus software.
  2. Upload the stolen user information to the C2 server.

3 Technical Details

3.1 Threat Persistence

During the first and second stages, the sample cyclically checks whether the mutex JbrDelete has been created, and if not, will continue to discover active processes and inject malicious code into these processes.

During the second stage, malicious code creates a hidden window. The message callback function of this window is responsible for creating the mutex JbrDelete, after which the cyclic check will stop. This mutex is created if, and only if, the window receives a user logout message “WM_QUERYENDSESSION”.

3.2 Information Theft

Malicious code injected in active processes during the second stage is responsible for stealing information. First, the malicious code checks the language of the operating system and, if and only if the language is English, will search \Users\%UserName%\AppData\Roaming\Microsoft\Windows\Cookies\ for sensitive files that contain bank names and copy them into a to-be-uploaded folder.

When the language is German, French, or English, the injected malicious code will attempt to hunt sqlite3.dll (not a component of Firefox of new versions) in the root directory of Firefox, and use the export function of this DLL to query cached files of Firefox and save the query result to a local disk drive.

The sample records all domains visited by zombies no matter what language their operating systems are using. The malicious code injected in processes checks whether it is within the process space of Firefox and, if so, will attempt to identify ssl3.dll from all DLLs loaded by Firefox and hook its export function SSL_SetURL. It should be noted that the network security service (NSS) library of earlier Firefox contained ssl3.dll, which was later renamed nss3.dll in a version iteration.

The hook function extracts domains visited by users from parameters and saves them to a local disk drive for subsequent uploading.

3.3 Dynamic Domain Generation Algorithm

The sample uses the string “” as the seed domain and obtains actual C2 domains upon computation of the first four characters. For the detailed computation process, see the following equations:

The C2 domains obtained by using the DGA algorithm are different from the seed domain in only the first four characters. All together there are 26^4 combinations. The following are some examples of the generated C2 domains:’’’’

The sample will keep using this algorithm to generate new C2 domains until it successfully connects to a domain generated this way. As the number of four-character combinations is limited, the algorithm will repeatedly generate the same domains, that is, loopback domains. For example, when “” is the seed domain, the second and the 15374th C2 domains are both “”.

Some domains are regenerated after a few rounds, but some are not. For example, for the domain “”, there is no input corresponding to “gfaq” obtained by using the DGA algorithm. A non-loopback domain can be used as the seed of the DGA algorithm, but cannot be used as a C2 domain. This is because this type of domain cannot be regenerated. The fact that the first connection fails indicates that C2 permanently loses control over the zombie. We can extract signatures of loopback domains and then typosquat them before taking over this botnet.


If the first four characters  are part of a loopback domain, there must be four characters   that generated them. Furthermore, if   are part of a loopback domain, the first two bytes   must have a corresponding pair of  .

When adding , we get:

It is evident that when   and   both exist, the sum of    can be divided by exactly 2. In other words, when  have the same parity,   is the necessary and inadequate condition of generating loopback addresses. In contrast, when the parity of  is different,   cannot be a loopback address. Non-loopback addresses account for  of the total addresses, that is [0.25, 0.5].

To sum up, with non-loopback domains, whose  can be  divided by exactly 2, however, attackers can still take over the botnet by typosquatting 75% or less of loopback domains.

3.4 Communication Protocols

During the third stage, malicious code in the puppet process scvhost is responsible for communicating with the C2 server. The sample generates two pipelines: One uses HTTP to notify C2 of the sample’s running status, and the other uses XMPP to upload user information. stolen at the second stage.

The message format used by pipeline 1 contains the following fields, which can be extracted to deduce traffic patterns:


&q=                     // Optional

&data=                 // Optional

&data_type=          // Optional

&action=               // Optional

&ver=                   // Optional

&ch=                    // Optional

&data_content=     // Optional

‘0xA’task’0xA’       // Optional

&id=                           // Hardcoded

&versionf=            // Hardcoded

&versiona=           // Hardcoded

&vendor=             // Hardcoded

&do=                    //Encoded C2 domain

&check=chek         // Hardcoded


The sample uses pipeline 1 to conduct the first interaction with the C2 server. The action field of the message is set to new.

The sample uses pipeline 2 to upload various files that contain user information.

First, the sample traverses the directory of to-be-uploaded files.

Next, the sample crafts a packet that contains basic information of the uploaded file and sends it to the C2 server. Before sending the packet, the sample adds the PGP header, but  encodes the payload with Base64 only without encrypting it as per requirements of the PGP protocol.

Finally, the sample uploads files in the directory one by one.


4 Indicators of Compromise

Seed Domain MD5 538da019729597b176e5495aa5412e83 5592456E82F60D2222C9F2BCE5444DE5 f9d02df23531cff89b0d054b30f98421 bc69a956b147c99f6d316f8cea435915 36a9c28031d07b82973f7c9eec3b995c 1e081e503668347c81bbba7642bef609 c2c980ea81547c4b8de34adf829ccc26 4e76a7ba69d1b6891db95add7b29225e abb80f23028c49d753e7c93a801444d8 eff48dae5e91845c2414f0a4f91a1518 5dda3983ac7cebd3190942ee47a13e50 eaeb5a9d8d955831c443d4a6f9e179fd 080b3f46356493aeb7ec38e30acbe4f5 40827866594cc26f12bda252939141f6 8e1d326b687fc4aacc6914e16652c288 a03971bff15ec6782ae25182f4533b92 b9fb8ae5e3985980175e74cf5deaa6fb f555132e0b7984318b965f984785d360