Summary
Brute Ratel C4 is a Red Team & Adversary Simulation software that can be considered an alternative to Cobalt Strike. In this blog post, we’re presenting a technical analysis of a Brute Ratel badger/agent that doesn’t implement all the recent features of the framework. There aren’t a lot of Brute Ratel samples available in the wild. The malware implements the API hashing technique and comes up with a configuration that contains the C2 server, the user-agent used during the network communications, a password used for authentication with the C2 server, and a key used for encrypting data transmitted to the C2 server. The badger takes control of the infected machine by executing 63 different commands issued by the C2 server. The first 20 commands will be described in this blog post, while the rest of them will be detailed in an upcoming blog post.
Technical analysis
SHA256: d71dc7ba8523947e08c6eec43a726fe75aed248dfd3a7c4f6537224e9ed05f6f
This is a 64-bit executable. The malware pushes the code to be executed on the stack in order to evade Antivirus and EDR software:
It implements the API hashing technique, which uses the “ROR EDI,0xD” instruction to compute 4-byte hashes that are compared with pre-computed ones (Figure 2).
The VirtualAllocEx API is used to allocate a new memory area that will store a DLL file (0x3000 = MEM_COMMIT | MEM_RESERVE, 0x40 = PAGE_EXECUTE_READWRITE):
The Brute Ratel C4 configuration is stored in clear text however, in recent versions, the config is encrypted and Base64-encoded. It contains the C2 IP address and port number, the user-agent used during the network communications, a password used to authenticate with the C2 server, a key used to encrypt data transmitted to the C2 server, and the URI:
A thread that executes the entry point of the new DLL is created via a function call to CreateRemoteThread:
The process extracts a pointer to the PEB from gs:[0x60] and another one to the PEB_LDR_DATA structure (+0x18), which contains information about the loaded DLLs. The InMemoryOrderModuleList doubly-linked list contains the loaded DLLs for the current process:
The malicious binary allocates new memory for another DLL that implements the main functionality using VirtualAlloc:
LoadLibraryA is utilized to load multiple DLLs into the address space of the current process:
The malware retrieves the address of relevant functions by calling the GetProcAddress method:
The binary flushes the instruction cache for the current process using the NtFlushInstructionCache function (see Figure 11).
Finally, the malware passes the execution flow to the newly constructed DLL:
As we can see below, one of the export functions of the DLL is called “badger_http_1”, which reveals a Brute Ratel agent/badger.
The FreeConsole method is used to detach the process from its console:
The DLL repeats the process of finding functions address, as highlighted in Figure 16.
The process extracts the system time and passes the result to the srand function:
The atoi method is utilized to convert the port number to integer:
The malicious process creates an unnamed mutex object by calling the CreateMutexA API, as displayed in Figure 19.
GetUserNameW is used to obtain the username associated with the current thread:
GetComputerNameExW is used to obtain the NetBIOS name associated with the local machine:
The badger retrieves a pseudo handle for the current process using GetCurrentProcess:
The OpenProcessToken API is utilized to open the access token associated with the process (0x8 = TOKEN_QUERY):
The malware verifies if the token is elevated using the GetTokenInformation method (0x14 = TokenElevation):
It obtains the current process ID via a function call to GetCurrentProcessId:
GetModuleFileNameW is utilized to extract the path of the executable file of the process:
The above path is Base64-encoded using the CryptBinaryToStringW API (0x40000001 = CRYPT_STRING_NOCRLF | CRYPT_STRING_BASE64):
The process retrieves version information about the current operating system using RtlGetVersion:
The WSAStartup function initiates the use of the Winsock DLL by the current process:
The badger constructs a JSON that stores the password extracted from the configuration, the computer name, the OS version, the Base64-encoded executable path, the username, and the process ID:
The JSON is encrypted using the XOR operator (key = “abcd@123” from configuration) and transformed by other operations:
The user-agent passed to the InternetOpenW function seems to indicate that the product was used by Deloitte China (Figure 34).
The process connects to the C2 server on port 80 by calling the InternetConnectW function:
It creates a POST request to the “/content.php” resource using HttpOpenRequestW, as displayed below.
The security flags for the handle are changed using the InternetSetOptionW API (0x1100 = SECURITY_FLAG_IGNORE_CERT_CN_INVALID | SECURITY_FLAG_IGNORE_UNKNOWN_CA):
HttpAddRequestHeadersW can be used to add one or more HTTP request headers to the handle however, the second parameter is NULL during malware’s execution (0x20000000 = HTTP_ADDREQ_FLAG_ADD):
The process encodes the encrypted JSON using Base64 and exfiltrates the resulting data using HttpSendRequestW:
It verifies whether the C2 server sends any data back via a function call to InternetQueryDataAvailable:
The C2 server’s response is read using InternetReadFile:
The response is Base64-decoded and decrypted using the same key that was previously mentioned. The “auth” field is set to the decrypted information, and another request is made to the C2 server, asking for commands:
FakeNet-NG was used to simulate the network communications with the C2 server. After decoding and decrypting the response, the first 2 bytes represent the command to be executed followed by additional parameters if necessary. A new thread handles the commands execution:
We’ll now describe the commands that can be issued by the C2 server.
0x2C74 ID – Exfiltrate file content to the C2 server
The PathFileExistsA API is utilized to confirm if the target file exists on the system:
The file is opened via a function call to CreateFileA (0x80000000 = GENERIC_READ, 0x1 = FILE_SHARE_READ, 0x3 = OPEN_EXISTING):
The content is read by calling the ReadFile method, as shown in Figure 46.
The data is sent to the C2 server along with the “[+] Download complete” message or the message shown in the figure below.
0xA905 ID – Copy files
The malware copies an existing file to a new file using CopyFileA:
0x9B84 ID – Move files
The process moves an existing file to another using the MoveFileA function (Figure 49).
0x13A1 ID – Create files and populate them with content received from the C2 server
Firstly, the file is created via a function call to CreateFileA:
The received data is Base64-decoded using CryptStringToBinaryA and written to the file:
0xE993 ID – Delete files
DeleteFileA is used to delete the target files, as highlighted below:
0x0605 ID – Close handles
The badger closes an object handle (i.e. file, process) using the CloseHandle API:
0x3F61 ID – Create directories
The malicious binary has the ability to create directories using the CreateDirectoryA method:
0x1139 ID – Change the current directory for the process
SetCurrentDirectoryA is utilized to perform the desired operation (see Figure 55).
0x3C9F ID – Obtain the current directory for the process
The malware extracts the current directory for the process by calling the GetCurrentDirectoryW API:
0x8F40 ID – Delete directories
The process deletes a target directory only if it’s empty using RemoveDirectoryA:
0x0A32 ID – Retrieve the Last-Write time for files/directories
The files are enumerated in the current directory using the FindFirstFileW and FindNextFileW functions:
For each of the file or directory that matches the pattern, the binary calls the CreateFileW API:
The process retrieves the Last-Write time via a function call to GetFileTime:
The file time is converted to system time format using FileTimeToSystemTime:
Finally, the above time is converted to the currently active time zone:
0x3D1D ID – Change the Desktop wallpaper
The malicious process opens the “TranscodedWallpaper” file that contains the Desktop wallpaper:
The above file is filled in with content received from the C2 server (Figure 65).
The SystemParametersInfoA method is utilized to change the Desktop wallpaper (0x14 = SPI_SETDESKWALLPAPER, 0x1 = SPIF_UPDATEINIFILE):
0xD53F ID – Retrieve the username
This command is used to obtain the username associated with the current thread:
0x0609 ID – Retrieve the available disk drives
The malware extracts a bitmask that contains the available disk drives by calling the GetLogicalDrives API, as shown in Figure 68.
0xC144 ID – Extract all device drivers
EnumDeviceDrivers is utilized to obtain the load address for all device drivers:
Using the above address, the process retrieves the name of the device driver by calling the GetDeviceDriverBaseNameA method:
0x0A01 ID – Compute the number of minutes that have elapsed since the system was started
The GetTickCount function is used to extract the number of milliseconds and a simple calculation is performed (see Figure 71).
0x73E6 ID – Argument Spoofing
The badger has the ability to hide the arguments by modifying the process environment block (PEB):
0x8AFA ID – Parent PID Spoofing
This command can be used to spoof the parent process ID in order to evade EDR software or other solutions:
0xC929 ID – Extract child process name
The binary could spawn multiple processes that can be displayed using this command (Figure 74).
0x9E72 ID – Display pipes name
The malware displays the name of a previously created pipe:
The other 30 relevant commands will be detailed in a second blog post.
INDICATORS OF COMPROMISE
SHA256: d71dc7ba8523947e08c6eec43a726fe75aed248dfd3a7c4f6537224e9ed05f6f
C2 server: 45.77.172.28
User-agent: trial@deloitte.com.cn
References
MSDN: https://docs.microsoft.com/en-us/windows/win32/api/
FakeNet-NG: https://github.com/mandiant/flare-fakenet-ng
Unit42: https://unit42.paloaltonetworks.com/brute-ratel-c4-tool/
nice
waiting for next part
it would be good to check NightHawk samples too
[…] Read more… […]