Malware source code investigation: BlackLotus - part 2

BlackLotus is a UEFI bootkit that targets Windows and is capable of evading security software, persisting once it has infected a system, bypassing Secure Boot on fully patched installations of Windows 11, and executing payloads with the highest level of privileges available in the operating system.

blacklotus

The source code for the BlackLotus UEFI bootkit has been published on GitHub on July, 12, 2023.

blacklotus

We are continue our small research and today investigate the another modules of BlackLotus and highlights the main features.

Bot logic: Install

As we wrote before, a bot in this context refers to a device with the Agent installed.

First of all, we paid attention to files install.h and install.c:

blacklotus

The provided source code appears to be part of a malware installation process. This code is designed to install a bot or malicious payload onto a system and set up persistence. Let’s break down the logic step by step:

GenerateBotFileName(PDWORD Seed) - This function generates a bot filename based on a given seed using a simple pseudo-random number generator algorithm. It multiplies the seed by a constant value (1664525) to calculate the new seed, which is then returned:

blacklotus

GetBotFileName(PDWORD Seed) - Calls the GenerateBotFileName function to obtain the bot filename seed. Converts the seed to hexadecimal format and constructs the bot filename as a string. Returns the bot filename as a wide string (LPWSTR):

blacklotus

GetBotDirectory() - Calls GetBotFileName to get the bot filename. Constructs the bot directory path by concatenating the AppData directory path with the bot filename. Returns the bot directory path as a wide string (LPWSTR):

blacklotus

GetBotPath() - Calls GetBotFileName to get the bot filename. Calls GetBotDirectory to get the bot directory path. Constructs the full bot executable path by concatenating the bot directory path, a backslash, the bot filename, and ".exe". Returns the full bot executable path as a wide string (LPWSTR):

blacklotus

IsSystemInfected() - Calls GetBotPath to get the bot executable path. Compares the obtained bot executable path with a global variable g_BotInstallPath. Returns whether the system is infected (TRUE) or not (FALSE) based on the comparison:

blacklotus

InstallBot() - Calls GetBotDirectory to get the bot directory path. Calls GetBotPath to get the full bot executable path.Converts DOS-style paths to NT-style paths using DosPathToNtPath function. Creates the bot directory using FileCreateDirectory. Copies the current process executable (malware) to the bot executable path. Sets a global variable g_BotInstallPath to the bot executable path. Returns TRUE if installation is successful, otherwise FALSE:

blacklotus

Finally, UninstallBot() - This function is incomplete and does not contain the logic for uninstallation.

Bot logic: Anti-debug

Next files, are antidebug.h and antidebug.c:

The provided source code seems to be focused on anti-debugging techniques, specifically checking whether the current process is being debugged. Also it’s obvious from the file name:

blacklotus

IsBeingDebuggedAlt() - This function is intended to check whether the current process is being debugged by an external debugger. It retrieves the Process Environment Block (PEB) using the GetPeb() function. It checks the BeingDebugged field within the PEB to determine whether the process is being debugged.

IsBeingDebugged() - This function is an entry point for checking if the current process is being debugged. It calls the IsBeingDebuggedAlt() function to perform the check. If the IsBeingDebuggedAlt() function returns TRUE, indicating that the process is being debugged, the function returns an error code ERROR_UNSUCCESSFULL. If the process is not being debugged, the function returns NO_ERROR.

This code attempts to detect if the current process is being debugged using an alternative method by examining the BeingDebugged field in the Process Environment Block (PEB). Anti-debugging techniques like this are used by malware authors to make it harder for security analysts and researchers to analyze or debug their malicious code.

Bot source code: Communication functionality

The source code of http.c appears to be related to HTTP communication functionality for the BlackLotus bootkit. This code seems to handle HTTP connections, sending POST requests, and receiving data from a remote server. Let’s break down the code:

HttpConnect(LPSTR UserAgent, LPSTR Host, WORD Port, DWORD Flags) - This function establishes an HTTP connection to a specified host. It uses InternetOpenW API to create an internet session with the specified user agent. Then, it uses InternetConnectA to establish a connection to the specified host on the specified port (port 80 in this case):

blacklotus

HttpRequest(HINTERNET Connect, BOOL bPost, LPSTR URI, LPSTR Referrer, PCHAR Data, DWORD Flags) - This function sends an HTTP request using the established connection. It uses HttpOpenRequestA to create an HTTP request to a specified URI. The method used can be POST or GET depending on the bPost parameter. It uses HttpSendRequestA to send the request with the specified headers and data:

blacklotus

HttpReceiveData(HINTERNET Request, PCHAR Buffer) - This function receives data from the HTTP response. It uses InternetReadFile to read data from the response into a buffer. The function appends the received data to the provided buffer.

blacklotus

HttpPostRequest(PCHAR Host, PCHAR URI, PCHAR Data, PCHAR Response) - This function is a higher-level wrapper for making an HTTP POST request. It calls HttpConnect to establish an HTTP connection to the specified host. Then, it calls HttpRequest to send a POST request with the provided data. After sending the request, it calls HttpReceiveData to read and store the response data:

blacklotus

Overall, this code appears to facilitate communication between the malware and a remote server through HTTP requests. It’s worth noting that malware often employs HTTP communication to send and receive commands, upload or download files, and exfiltrate data. Analyzing such code requires an understanding of HTTP communication mechanisms and malware analysis techniques.

Bot: Injection techniques

The next file is called inject.c and it’s interesting. It’s started from function GetImageBase(LPVOID ProcessAddress) which is used to retrieve the base address of a module within a process. It iterates backward in memory from the provided ProcessAddress to find the base address of the module by locating the IMAGE_DOS_HEADER and IMAGE_NT_HEADERS structures. The function returns the base address of the module:

blacklotus

ProcessRelocation(PIMAGE_BASE_RELOCATION Relocation, DWORD ImageBase, DWORD Delta, DWORD Size) - This function performs relocations for a loaded module within a process:

blacklotus

Function InjectData(HANDLE Process, LPVOID Data, DWORD Size) allocates memory in a remote process and writes data into that memory:

blacklotus

As we can see, it uses “classic” combination VirtualAllocEx, WriteProcessMemory.

InjectCode(HANDLE Process, LPVOID Function) - function injects a code block into a remote process. It obtains the base address and size of the function’s module, creates a file mapping, maps the remote process’ memory, and performs relocations:

blacklotus

It calculates the new address of the injected function and returns it.

InjectBot(DWORD ProcessId, LPTHREAD_START_ROUTINE Thread) function injects a thread into a remote process, starting execution at the specified Thread function:

blacklotus

It opens the target process with specific access rights. It calls InjectCode to inject the Thread function into the remote process. It creates a remote thread within the target process to execute the injected code.

Bot: Reporting

The provided source code appears to be related to the reporting functionality of the BlackLotus bootkit. This module is responsible for sending periodic reports to command and control (C2) servers about the status and information of the infected system:

blacklotus

ProcessServerResponse(CONST PCHAR Response) function processes the response received from the C2 server after reporting:

blacklotus

ReportThread() - This function is executed as a thread and handles the periodic reporting to C2 servers. It constructs a report data string using information such as infection type, bot GUID, OS, architecture, and username.

blacklotus

Function StartReportThread() starts the reporting thread by creating a new thread that executes ReportThread:

blacklotus

That’s all today. In the next part we will investigate the most interesting part: Bootkit logic.

We hope this post spreads awareness to the blue teamers of this interesting malware techniques, and adds a weapon to the red teamers arsenal.

By Cyber Threat Hunters from MSSPLab:

References

Malware source code investigation: BlackLotus - part 1
https://github.com/ldpreload/BlackLotus
https://malpedia.caad.fkie.fraunhofer.de/details/win.blacklotus
https://twitter.com/threatintel/status/1679906101838356480
https://twitter.com/TheCyberSecHub/status/1680044350820999168

Thanks for your time happy hacking and good bye!
All drawings and screenshots are MSSPLab’s

Article Link: Malware source code investigation: BlackLotus - part 2 - MSSP Lab