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.
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:
- Inject malicious code in the heap into all active processes.
- Hook the CloseHandle function of the injected processes.
- 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:
- Continue to inject malicious code into all active processes for persistence.
- 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:
- Use DGA to dynamically obtain C2 domain names to bypass malicious name detection by antivirus software.
- Upload the stolen user information to the C2 server.
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”.
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.
The sample uses the string “antisemitismgavenuteq.com” 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 “antisemitismgavenuteq.com” is the seed domain, the second and the 15374th C2 domains are both “nzrvsemitismgavenuteq.com”.
Some domains are regenerated after a few rounds, but some are not. For example, for the domain “gfaqsemitismgavenuteq.com”, 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 .
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].
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.