Introduction
BokBot, developed and operated by the actor named LUNAR SPIDER, was first observed in 2017 and the CrowdStrike’s Falcon® Overwatch™ and Falcon Intelligence™ teams have analyzed these infections to ensure customers are both protected and informed. Recently, BokBot infections have become more prevalent due to distribution campaigns through the Emotet malware, which is associated with MUMMY SPIDER. The BokBot malware provides robust functionality, such as:- Command and control of a system
- Process execution
- Registry editing
- Write to the file system
- Logging
- Polymorphism and other obfuscations
- TamperProofing
- Modular
- Credential theft
- Intercepting proxy
- Remote control via VNC
BokBot Container Execution
BokBot comes packed inside a crypter. The crypter goes through several stages before finally unpacking the BokBot binary and injecting it into svchost.exe. Here is a quick rundown of the different stages:- Stage 1 (crypter)
- Decode stage 2 and execute
- Stage 2 (crypter)
- Decodes shellcode and execute
- Stage 3 (shellcode)
- Hollows out the base process image
- Decodes the core process injection PE
- Overwrites the base process image with the core process injection PE
- Stage 4 (process injection)
- Executes the process injection code
- Launches svchost.exe child process
- Injects BokBot as a headless PE image into the child process
Process Injection
In order to bypass antivirus (AV) detections for process hollowing, BokBot hooks several Windows API functions, executes the hooking code, and then removes the hook.Simulating Process Hollowing
In order to simulate process hollowing, theZwCreateUserProcess
routine is hooked. BokBot calls ZwProtectVirtualMemory
to modify the permissions of the routine to PAGE_READWRITE
. Next, the first five opcodes (bytes) are replaced with the opcodes for a JMP
<address of hooking code>
instruction. Permissions are restored, and then
CreateProcessA
is called. Figure 1: Hooking
ZwCreateUserProcess
Once CreateProcessA
is called, a function call chain leads to calling ZwCreateUserProcess
and then the hooking code, as shown in Figure 1. At this point, no process has been created.
The hooking code will complete the creation of the child process by removing the hook from the ZwCreateUserprocess
routine, and then the non-hooked ZwCreateUserProcess
procedure is called. This will create the child process, but execution doesn’t begin until CreateProcessInternal
returns. The rest of the hook routine will decode and inject the embedded BokBot binary into the child svchost.exe process
Code Injection
Prior to injecting the code, the BokBot PE is decompressed and loaded into the local process memory. Once loaded, the following Windows procedures are used to allocate and write to the svchost child process: After the main BokBot module has been written to the child process, the steps to execute the BokBot code will begin.Code Execution
BokBot uses a novel technique to get the code to execute inside of the child process. Using the same APIs as earlier, the dropper hooksRtlExitUserProcess
in the child process. Since svchost.exe is launched without arguments, it will terminate immediately. As the process attempts to exit, it will call the hooked RtlExitUserProcess
, thus executing the BokBot payload.
There is one more task for the hooking routine to complete before CreateProcessInternalW
resumes execution.
Injecting a Context Data Structure
After the BokBot payload is injected into the child process, a context data structure is written to the child process. This context contains all of the data necessary to ensure that BokBot’s main module is able to execute without issue:- Windows
- ntdll.ZwAllocateVirtualMemory
- ntdll.ZwWriteVirtualMemory
- ntdll.ZwProtectVirtualMemory
- ntdll.ZwWaitForSingleObject
- ntdll.LdrLoadDll
- ntdll.LdrGetProcedureAddress
- ntdll.RtlExitUserProcess
- ntdll.ZwCreateUserProcess
- ntdll.RtlDecompressBuffer
- ntdll.ZwFlushInstructionCache
- Load address for payload
- Path to the dropper binary
- C2 URLs
- Project ID
CreateProcessInternalW
resumes, and the dropper process exits. BokBot’s main module starts the initialization phase.
BokBot Initialization
Prior to executing the primary loop to communicate with the C2, BokBot goes through several initialization steps to prepare itself for C2 communication. Initialization occurs in the following steps:- Remove the RtlExitUserProcess hook
- Create a memory-mapped file to store logging data
- Execute BokBot as the logged-on user (if the current process is running as System)
- Suppress error windows
- Collect System information
- Windows version information
- User SID
- Member of a domain
- Unique ID generation
- Prevent multiple executions
- Install BokBot on the host
- Inject existing downloaded modules into into child processes
Silence Errors
To prevent error windows from informing the victim of an issue, BokBot sets the error mode of the process to 0x8007, which corresponds to the following: This will disable most error notices that are generated when a process crashes.Generating Unique IDs
BokBot uses several unique IDS that are generated earlier on during process execution. These values are passed to the C2 (command and control), used as a key for RC4, and passed to child processes.Project ID
In addition to injecting the main BokBot module into svchost, the dropper also injects a chunk of binary data that provides context for BokBot to execute, including the Project ID. These unique Project ID values appear to be used to identify infections that correspond to distribution campaigns. The Project ID is a four-byte value.Bot ID
Bot IDs are unique to specific instances for a user on an infected host. The value is used as an encryption key and as a seed in the generation of the unique values that BokBot needs for a variety of purposes, such as the generation of pseudo-random strings for file and event names. This will be discussed further in subsequent sections. The Bot ID is generated in one of the two following ways:- Security ID (SID) of the account name
- System time in a file time format
ID Hash
In addition to this Bot ID, a simple hash is generated that can be used to verify the validity of both the Bot ID and the Project ID. This hash is generated using the Bot ID and the Project ID, in the following manner: This value will be passed along with the Project ID and the Bot ID as part of the C2 URL parameters. If this request is invalid, infected hosts will not receive any instructions from the C2.C2 Hostname Initialization
Bokbot contains an encoded list of C2 hostnames that were provided as part of the context data structure that was injected by the dropper. The C2 list within that structure is decoded using a key that was also provided by the context, and then re-encoded using a new key that was generated using an rdtsc instruction, and stored as an array of pointers.Prevent Multiple Executions
A unique global named event is generated using the Bot ID. A successful call toCreateEvent
is proceeded with a call to GetLastError
. If the malware is already executing, the last error is ERROR_ALREADY_EXISTS
, and the process exits.
Installation
During installation, the BokBot dropper binary is written to an installation directory, and a scheduled task is created for persistence. The installation directory is created in the following root directory:- c:\ProgramData
str_id
value in the script is a hard-coded integer that is used with the Bot ID to generate consistent strings. For instance, using a Bot ID of 0x2C6205B3 and str_id of 2 always results in ayxhmenpqgof
, but switching to a str_id
of 6 results in bwjncm.
The following is an example of the installation path:
C:\ProgramData\{P6A23L1G-A21G-2389-90A1-95812L5X9AB8}\ruizlfjkex.exe
A scheduled task is created to execute at windows logon. The task name is generated in the same manner as the installation directory:
- Task Name:
- Trigger: Logon
- Action: Start a program
- Details: BokBot dropper path
C2 Communication
BokBot communicates with C2 servers via HTTPS requests, passing various values to the server through URL parameters and via POST data. The URL request data is not encrypted or obfuscated beyond the SSL/TLS used by the server. The following sections detail parameters required by all requests, some additional optional parameters, and the bot registration process.Required C2 Request/Response Parameters
Every request/response will have these parameters sent to the server. These will provide the C2 with information that identifies the request/response type and to uniquely identify the infected machine: Table 1 describes these parameters in greater detail. The URL path often changes between versions: For instance, version 100-102 used/data100.php
instead of /in.php.
Additional C2 Request Parameters
BokBot contains a communication thread that loops continuously until the process exits, retrieving instructions from the C2 server. These requests include several additional parameters, detailed in Table 2, in addition to those already described. These parameters are not sent when a machine sends the result of a command issued by the C2, such as when uploading a screenshot. The following URL parameters showcase an example of the initial connection to the C2: In this example, there are no web injects, no C2 URLs, and no modules have been downloaded, therefore the highlighted parameters are either zero or empty. An initial timestamp has been generated, and the version number is static.Initial Bot Registration
A registration request is combined with the standard C2 URL parameters that are sent to the C2 with each request. After the initial request, the C2 server will send commands back to the victim, signaling it to download web injects, updated C2 hostnames, executable modules, or to perform other tasks. The initial registration URL contains parameters related to system information. The following string is an example: Table 3 describes the registration URI parameters. The following is an example of a registration request (in red) and a response from the C2 (in blue) containing commands for the infected host:C2 Commands
This section will cover the command requests made by the C2. Each command from the C2 takes the following format: The following commands are available in the current version of BokBot: Note that these command ID values may change between versions. As this list demonstrates, BokBot provides operators with a wide variety of options to interact with an infected machine.URL Download Command Handler
A lot of commands trigger a command handler function that requires communication with either a C2 URL or another URL specified in the server request arguments. If specified by the request, the data downloaded from the target URL will be written to a DAT. Whether or not the downloaded data is written to a DAT file, it will always be processed by a callback function for one of the following C2 commands:- Start a new executable module, restart current executable module
- Update web injects (either command)
- Update config
- Update BokBot
- Write to a file
- Download and execute a binary
Modules and DAT Files
All data received from the C2 that needs to persist between reboots is written out as a DAT file on the infected machine. These files include:- Web inject configuration
- C2 configuration
- External modules
Unique Tag Generation
BokBot assigns unique tag values for injected processes, downloaded modules, and the downloaded DAT files. These tags are a convenient method for the executing BokBot process to identify external process resources. Tag generation is simple:- 18 – Web injects configuration file, statically defined in the binary
- 19 – Reporting configuration file, statically defined in the binary
- 20 – C2 configuration file, statically defined in the binary
- 33-46 – Downloaded modules to be injected into child processes
- Assigned as needed in an incremental fashion
- Not necessarily a unique tag for what the module does
Downloading DAT Files
As previously mentioned, DAT files are downloaded based on commands sent from the C2. Once the command is received from the C2, a command handler specific to this command is called to process the request. In response, the infected machine notifies the C2 with the command that it is ready to receive an RC4-encrypted blob from the C2. Figure 3 illustrates the process of commands that download configuration files and modules. An eight-byte RC4 key is prepended to the data buffer. Prior to writing the BLOB to a file, BokBot decrypts the file, and then re-encrypts it using a new RC4 key based on the Bot ID.Write to a File
BokBot creates a new directory underC:\ProgramData
to store the DAT files. The directory name is generated using the string generation algorithm described previously. DAT file names are generated using the unique tag value. This value is run through a string generation algorithm (also dependent on the Bot ID), which returns a unique filename for the DAT file.
Table 4 references all of the DAT files that were written during the testing process used for writing this blog. In this case, the installation directory is C:\ProgramData\yyyyyyyyiu\.
These DAT files are further handled based on the specified type, depending on whether it is an executable module or a data file.
Executable Module
BokBot has several executable modules that can be downloaded and injected into a svchost.exe child process. Once the relevant DAT file is decoded using RC4, no additional decoding or decompression is necessary for the executable module DAT files. The executable module header contains information necessary to ID the module: The rest of the file contains data necessary to load and execute the module, including the various portions of a PE file along with a custom PE header.Module Injection and Execution
Executable modules are injected with a technique similar to the dropper, minus the hook ofZwCreateUserProcess
, and the child process start is suspended (CREATE_SUSPENDED
). It’s a little closer to traditional process migration with the addition of the RtlExitUserProcess
hook.
PE Image Loading
Because there is no standard PE header, the DAT file has to contain all of the relevant information (virtual sizes, relocations, etc.) to properly map this binary into the child process. This data is part of the header of the DAT file. BokBot builds the binary in local process memory prior to injecting it into the child process.Injection
Injection uses the same APIs as the dropper: ZwAllocateVirtualMemory, ZwWriteVirtualMemory, ZwProtectVirtualMemory. After injection the process is resumed using ResumeThread.Execution Context Injection
Once again, an execution context structure is written to the child process, prior to execution. Some of the information contained in this context includes:- Bot ID
- Project ID
- C2 hostnames
- A URL path format string
Data Files
The other DAT files contain data necessary to either communicate with a C2, or related to web injection. Essentially, these files provide whatever additional data the main BokBot process and the executable modules require to accomplish their job.Config File
The config file contains all of the data necessary for the BokBot main module to maintain communication with the C2. Once the file is decrypted using the process-specific RC4 key, no additional decompression or decryption is necessary.Signature Verification
Each config file comes with a digital signature block, used to verify the integrity of the C2 hostname data. The signature is verified based on the signature verification method outlined in the obfuscations section. The following is an example C2 configuration, with the signature block in red:Web Inject Files
There are multiple web inject files. One contains all of the target URL and hostname data, and the second contains regex patterns, as well as the code to inject. These files are both RC4-encrypted and compressed. These files are not parsed by the main BokBot binary, but rather by the intercepting proxy module. Thezeus
file magic is verified, a buffer is allocated, and then the files are decompressed.
A forthcoming blog post on the proxy module will cover decompression and usage of the web injection configuration files.
Communication with Child Processes
Memory-mapped files and events are used by BokBot to communicate with all child processes that contain an injected module. Through the process of leveraging named events withCreateEvent, OpenEvent
,
and OpenFileMapping
, the BokBot main module is able to provide additional information to these child processes.
Shared Module Log
Modules write to the same shared memory-mapped file. The memory-mapped file is created using a shared name between the parent and child processes. Each process that can generate this name can use it to open the memory-mapped file, and to write data to the shared modules log. Further details are covered in the next section, and specific data written will be covered in the separate module descriptions below. The main module is responsible for clearing the log and sending the data to the C2.Module-Specific Communication
BokBot’s main module often needs to issue commands to the child processes that contain injected module code. The commands can trigger an update of module-specific data, or instruct the module to perform a specific function, such as harvest data from Outlook. Figure 4 outlines this process, although it will be further explained in the subsequent sections. Figure 4: BokBot Communication Between Parent and Child ProcessesEvent Name Generation
In order for the BokBot main modules and the child process to communicate with events, unique names need to be generated and must consistent across all of the processes. Table 5 illustrates BokBot’s approach. These events will be used by the parent and child processes to exchange data.BokBot Main Module
This process has the ability to communicate with all of the children of the injected modules. These communication all revolve around commands generated by the C2. Once a command that requires notification of an executable module child process is initiated, a namedQ
event is opened to ensure that the child process is ready to receive the data. If this Q
event does not exist, then the child process has not been started. BokBot injects the target module into a child process, and loops a check to see if the event can be opened.
Once the Q
event has been successfully opened, BokBot creates a new named R
event, creates a memory-mapped file (named M
event), writes data to the file, signals the open Q
event, and waits for a response from the child process. After the child clears the R
event, the memory-mapped file is unmapped, and all handles are closed.
BokBot Executable Module
After initialization, the child process will create a namedQ
event and wait until it is signaled by the parent process. Once signaled, the named R
event is opened, and the data in the memory-mapped file is processed.
Data from the BokBot Parent
BokBot’s main module writes some contextual information to the injected module, telling it to perform specific actions. These actions change based on the module receiving the data. The following commands are consistent between modules, but the actions performed may vary:- 0xFF00: Process exit with a 0x1122 code
- 0xFF01: Check web injects or no operation
- 0xFF02: Update C2 hostnames
R
event is signaled, and all other open events are closed.
Obfuscations and TamperProofing
Bokbot uses several methods to obfuscate analysis:- String obfuscation
- Encrypted DAT files from the server
- Signature verification
- Polymorphism
String Obfuscation
To make analysis more difficult, significant strings have been XOR encoded using a shifting key algorithm. All encoded strings have the following structure: Here is the algorithm to decode the string (Python):Signature Verification
Signature verification occurs under two circumstances: updated C2 urls, and updated BokBot binary. In both cases, the process is the same. The verification function receives two things: a 128-byte signature to verify, and the data to verify. First, BokBot creates an MD5 hash of the data requiring verification. Next, an RSA public key embedded in the executing binary is importing viaCryptImportKey
. Once the hash is generated and the key imported, CryptVerifySignature
is used to verify the signature. This may be an attempt to prevent some third party from taking over or otherwise disrupting the botnet.
Polymorphism
Everytime BokBot is installed, prior to it being written to the install directory, the .text section of the binary is modified with junk data and the virtual size is updated. A new checksum is generated to replace the current checksum.How CrowdStrike Falcon® Prevent™ Stops BokBot
Bokbot spawns a svchost child process, injects the main module, and that svchost process spawns and injects into multiple child processes. The process tree in Figure 5 is an example of what BokBot looks like when process blocking is disabled in Falcon Prevent. As can be seen, several malicious child processes were launched by BokBot’s main module located inside of the first svchost process. Figure 5: BokBot Process Tree Without Process Blocking Enabled Without preventions enabled the customer will still be notified of the malicious activity, but no action will be taken to prevent the behavior.Suspicious Process Blocking
Falcon has the capability to prevent the execution of BokBot’s main module and all of the child modules. Turning on process blocking in Falcon Prevent kills the BokBot infection at the parent svchost process. Looking at the process tree in the Falcon UI with process blocking enabled, shows an analyst that the svchost process was prevented. The block message (see Figure 7) that occurs with this preventative action explains why this process was terminated. Suspicious process blocking is an example of malware prevention based on behavior. If the malware uses behavior that has not been caught by Falcon’s indicators of activity, then Falcon can also prevent malware execution by leveraging either next-generation AV machine learning ,or intelligence collected by Crowdstrike’s Falcon Intelligence team.In Summary
BokBot is a powerful banking trojan that provides attackers with a robust feature set. One of the more unique features of BokBot is the method in which it uses to communicate with it’s child modules. Additional blog posts for BokBot are coming that will contain more information for the downloaded modules.
BokBot Hashes
The following hashes were used in creation of this blog post.MITRE ATT&CK Framework Mapping
Additional Resources
- Read a Security Intelligence article: “New Banking Trojan IcedID Discovered by IBM X-Force Research.”
- Read a Talos Blog: “IcedID Banking Trojan Teams up with Ursnif/Dreambot for Distribution.”
- Visit Vitali Kremez | Ethical Hacker | Reverse Engineer and read: “Let's Learn: Deeper Dive into ‘IcedID’/’BokBot’ Banking Malware: Part 1.”
- Download the 2018 CrowdStrike Services Cyber Intrusion Casebook and read up on real-world IR investigations, with details on attacks and recommendations that can help your organizations get better prepared.
- Learn more about CrowdStrike’s next-gen endpoint protection by visiting the Falcon platform product page.
- Test CrowdStrike next-gen AV for yourself: Start your free trial of Falcon Prevent™ today.