The ROKRAT (also referred to as DOGcall) malware is a sample that has been used by attackers originating from North Korea. The family continues to evolve and adopt techniques from other families also used by the same attack group. The ROKRAT core payload is typically deployed by a loader, which has also been observed dropping additional families. This paper will document the different phases typically observed when this malware is deployed, as well as the overlap in techniques used by this group.
As previously documented in public write ups, this variant has the ability to capture screenshots, steal stored browser password, as well as download and upload additional files or executables.
The request to analyze this sample, came from a Carbon Black IR partner. The partner observed a similar sample in the wild, and wanted to work with the Threat Analysis Unit (TAU) to determine the best way to detect this family and the techniques it employed.
This write up is being produced to provide practitioners or researchers additional insight into this malware family, as well as related YARA signatures, analysis scripts, and Cb specific content. A Python script was created to extract and decode the embedded shell code as well as the final payload, which is attached to this write up.
The original sample that was submitted by an IR partner is identical in functionality to the sample below, which was referenced publicly in previous analysis by Cisco Talos.
The ROKRAT malware (and associated loader) has been observed being deployed in several different manners. ROKRAT has been observed being dropped by carrier files (like Office documents that contain macros), as well as a second stage malware being dropped by other malware families.
The metadata for the sample analyzed is listed in the table below.
File Name : ROKRAT_sample.exe File Size : 626,688 bytes MD5 : d2881e56e66aeaebef7efaa60a58ef9b SHA1 : c09c1be69e5a206bcfe3d726773f0b0ddecb3622 SHA256 : e1546323dc746ed2f7a5c973dcecc79b014b68bdd8a6230239283b4f775f4bbd Fuzzy : 12288:cbeQy0+6dUlyAcdqfAkMvGpns9gKYLd+NjhzZkZf7:AfuJGv2ns9XRkZf Compiled Time : Wed Dec 20 02:18:28 2017 UTC PE Sections (5) : Name Size MD5 .text 36,352 462e65d46a453444d5fa86c0df10acb9 .rdata 8,192 d8b76044cedbd7db8cd7d35e35853552 .data 4,096 bbc2905f395f561cb2c59b0541c2758a .rsrc 571,392 da2c1226b37133a26f073e1b2e99725e .reloc 5,632 0c80569caa34549a9ed52c8e747656aa Magic : PE32 executable for MS Windows (GUI) Intel 80386 32-bit |
Table 1: ROKRAT loader information
This sample’s functionality is straightforward in that it will locate an embedded resource (by name, in this case JOK) and then load that resource into memory, which is highlighted in red below. The resource is raw shell code, which is detailed more below.
Figure 1: ROKRAT resource loading
The loader will then create a process, in this scenario wscript.exe (cmd.exe has also been observed being used), which is highlighted in green below. The loader will then allocate memory in the newly created wscript.exe process’ space and copy the previously loaded shellcode (JOK resource) into that memory space. The loader will then create a thread in the wscript.exe process, with the start address of the thread pointing to the copied shell code (highlighted in blue below).
Figure 2: ROKRAT loader shell code injection
After the shell code is running in memory, the loader will attempt to delete itself from the system. The loader will use the hard coded string (highlighted in red below), and format it with the file or module name, along with the command line. The loader will then create a process (cmd.exe) which will ping an IP Address redirecting the results to null (this creates a time gap so that the payload can be injected from the previous steps) and then will attempt to delete the loader file itself (highlighted in blue below).
Figure 3: ROKRAT loader clean up routine
Shell code
The metadata for the JOK resource, from the above loader, is listed in the table below.
File Name : JOK.resource File Size : 522,848 bytes MD5 : 220c7c1fe852af006a83412ecef642fe SHA1 : 60d465f1a6c35509174503e87ca106ad2fa40b39 SHA256 : 1bcefc2ccdee1aa41578507d638b33f2957010637d98bb83c011541f7d632efb Fuzzy : 12288:c0+6dUlyAcdqfAkMvGpns9gKYLd+NjhzZkZfI:duJGv2ns9XRkZfI |
Table 2: JOK Resource information
The shell code will initially clear some registers before calling a function, which is responsible for removing the first stage of code obfuscation. The code performs some basic math operations (highlighted in the below image in orange), which are used to determine the offset of the code that will be decoded. This is a method to avoid statically using an offset value, potentially evading different signatures. This technique is used throughout the shell code.
Figure 4: Shellcode Deobfuscation phase
The shell code will then take the first byte located at the calculated offset and XOR that value with 0x90 (highlighted in purple above). This resulting value will be used as a XOR key to decode the shell code. The shell code will then use two hard-coded values (subtracting the second from the first) to determine the amount of bytes (0x807) that will be decoded with the XOR key (highlighted in black). The below image is an overview of the shell code elements detailed above. The code underlined in blue is the above function. The byte highlighted in red is the first byte of the calculated offset and will be XOR’d with 0x90 (resulting in 0x13) and used as the XOR key. The remaining code (highlighted in red above) will XOR the shell code underlined in green (0x807 bytes in total) with the 0x13 XOR key.
Figure 5: Shellcode Deobfuscation overview
Once the shell code removes the initial layer of obfuscation, it will jump to a function that is ultimately responsible for injecting an embedded payload into the current process (which is wscript.exe). The image below provides an overview of this function. A sub-function is called (highlighted in green), that will first locate the process environment block (PEB) from the thread information block (TIB) to obtain a list of loaded modules.
Figure 6: Gather module information and locate marker
The shell code will then walk the preceding data (from a calculated offset) to locate a marker (0x90909090). This is highlighted in red in the code above, as well as in the data itself in the image below. Once the marker is located, the shell code will convert the dword following the marker, which is the size of the encoded payload (0x07F200), highlighted in green in the image below. The payload size and encoded data offset are then passed on the stack to a function responsible for decoding and injecting the payload.
Figure 7: Code overview of marker and encoded data
The decoding sub-function will use a name hashing algorithm (commonly used in shell code), to resolve the API’s GlobalAlloc and GlobalFree (highlighted in red in the image below). The code will then XOR the first byte of the encoded data with the static value 0x4D, and the result will be used to XOR the first byte of the encoded payload (highlighted in blue below). An initial value is also set (also highlighted in blue), which is used to generate a dynamic XOR key to decode the remaining payload.
Figure 8: Code overview of marker and encoded data
The initial XOR key and starting value are then used to decode the payload (highlighted in green in the above image). It should be noted that the variable names were changed and comments were added to document the actions. A python script was written to extract and decode the shell code along with the core payload, which is attached to this post. Once decoded the payload buffer is passed to another function responsible for injecting the decoded DLL into memory. The metadata for the decoded core payload is listed in the table below.
File Name : core_payload File Size : 520,704 bytes MD5 : 5c6c1ed910e7c9740a0289a6d278908a SHA1 : 0e46e026890982da526d8acf9f1ce6287451c9a6 SHA256 : e200517ab9482e787a59e60accc8552bd0c844687cd0cf8ec4238ed2fc2fa573 Fuzzy : 6144:Wh65XKGJs5Ve5psLyYuwAKdf9Q4p9FCAkko7cmxBZAk4+AJ6P3VNUo+wABK7Cl/:SAKdf+4p9J2x0k4+AQ3VNH+rZx7Aq9 Compiled Time : Tue Dec 19 06:18:10 2017 UTC PE Sections (6) : Name Size MD5 .text 398,848 31f84f4086f6cc29fdec3beb3d4143c7 .rdata 74,752 cd6c70f1550d4ec7ef8c2f9389052187 .data 8,192 199dba4e0d91649be88d319d6e35679c .tls 512 1f354d76203061bfdd5a53dae48d5435 .rsrc 512 2eaf2a4764a1e5f4ed5c4c03cb91d910 .reloc 36,864 807f171588560279c492b1bf5b5f1392 Magic : PE32 executable for MS Windows (GUI) Intel 80386 32-bit |
Table 3: ROKRAT corepayload information
The ROKRAT payload is a complete remote administration tool (RAT), with the typical functionality that is RAT malware. The payload itself will gather information about the OS and system before conducting a couple of anti-analysis checks when it is first executed. The payload will first profile the OS version (highlighted in red in the below image). If the OS version is 6.2 (Windows 8/2012) or greater, it will check to see if the current process is running under WOW64 (the x86 to x64 bit emulator).
Figure 9: ROKRAT OS profiling
The ROKRAT payload will gather the computer and user name, as well as the name of the FQP of the current module (highlighted in red below). As other researchers have stated, the payload will gather information from the SMBiosData (highlighted in green). The payload will then conduct a series of anti-analysis checks. The payload will initially do a check to determine if the process is being debugged (highlighted in blue).
Figure 10: Gather system information
The payload will then look for specific files that are typically observed in sandboxed environments. The file names (highlighted in red below) are related to Sanboxie, Microsoft debugging routines, and iDefense (the last two listed) programs respectively. These types of checks have been used in the wild among numerous types of malware and families, as well as being documented for pentesting. The payload will also attempt to write a randomly named .dat file to the Windows directory in an attempt to determine if the current process has elevated privileges.
Figure 11: Anti-analysis checks
After the payload completes the checks it will create an additional thread (from the Start Address) to initiate the communications with the command and control infrastructure (which has previously been documented by Cisco Talos). The following portion of the main communications function, displays how the payload will attempt to communicate with Dropbox, PCloud, and Yandex (highlighted in red below), to download commands and additional files. These sites are also used to exfiltrate out of the infected network. The malware has several of the associated cloud libraries components compiled into the binary to utilize the native API functionality of each solution.
Figure 12: C2 overview
The payload uses a hard-coded session key, to upload screen captures (saved on disk as pho_rand-8-char-string_capture#.jpg) of infected systems to PCloud, using the native API. It should be noted that each of the jpg files data has the previously harvested machine data (machine name, user name, FQP of module, hardware profile) prepended to the jpg image data.
Indicator |
Type |
Context |
2ca7c2048f247b871e455a9ac8bcb97927dd284477e7c2c4d2454509f97413b5 394e52e219feb1a5c403714154048728 |
SHA256 |
ROKrat Sample |
e1546323dc746ed2f7a5c973dcecc79b014b68bdd8a6230239283b4f775f4bbd d2881e56e66aeaebef7efaa60a58ef9b |
SHA256 |
ROKrat Sample |
rule ROKRAT_loader : TAU DPRK APT { meta: author = "CarbonBlack Threat Research" //JMyers date = "2018-Jan-11" description = "Designed to catch loader observed used with ROKRAT malware" rule_version = 1 yara_version = "3.7.0" TLP = "White" exemplar_hashes = "e1546323dc746ed2f7a5c973dcecc79b014b68bdd8a6230239283b4f775f4bbd" strings:
$s2 = "wscript.exe" $s3 = "cmd.exe" $s5 = "CreateProcess" $s6 = "VirtualAlloc" $s7 = "WriteProcessMemory" $s8 = "CreateRemoteThread" $s9 = "LoadResource" $s10 = "FindResource" $b1 = {33 C9 33 C0 E8 00 00 00 00 5E} //Clear Register, call+5, pop ESI $b2 = /\xB9.{3}\x00\x81\xE9?.{3}\x00/ //subtraction for encoded data offset $b3 = {03 F1 83 C6 02} //Fix up position $b4 = {3E 8A 06 34 90 46} //XOR decode Key $b5 = {3E 30 06 46 49 83 F9 00 75 F6} //XOR routine and jmp to code
//push api hash values plain text $hpt_1 = {68 EC 97 03 0C} //api name hash value - Global Alloc $hpt_2 = {68 54 CA AF 91} //api name hash value - Virtual Alloc $hpt_3 = {68 8E 4E 0E EC} //api name hash value - Load Library $hpt_4 = {68 AA FC 0D 7C} //api name hash value - GetProc Addr $hpt_5 = {68 1B C6 46 79} //api name hash value - Virtual Protect $hpt_6 = {68 F6 22 B9 7C} //api name hash value - Global Free //push api hash values encoded XOR 0x13 $henc_1 = {7B FF 84 10 1F} //api name hash value - Global Alloc $henc_2 = {7B 47 D9 BC 82} //api name hash value - Virtual Alloc $henc_3 = {7B 9D 5D 1D EC} //api name hash value - Load Library $henc_4 = {7B B9 EF 1E 6F} //api name hash value - GetProc Addr $henc_5 = {7B 08 D5 55 6A} //api name hash value - Virtual Protect $henc_6 = {7B E5 31 AA 6F} //api name hash value - Global Free condition: (4 of ($s*) and 4 of ($b*)) or all of ($hpt*) or all of ($henc*) } |
rule ROKRAT_payload : TAU DPRK APT { meta: author = "CarbonBlack Threat Research" //JMyers date = "2018-Jan-11" description = "Designed to catch loader observed used with ROKRAT malware" rule_version = 1 yara_version = "3.7.0" TLP = "White" exemplar_hashes = "e200517ab9482e787a59e60accc8552bd0c844687cd0cf8ec4238ed2fc2fa573" strings: $s1 = "api.box.com/oauth2/token" wide $s2 = "upload.box.com/api/2.0/files/content" wide $s3 = "api.pcloud.com/uploadfile?path=%s&filename=%s&nopartial=1" wide $s4 = "cloud-api.yandex.net/v1/disk/resources/download?path=%s" wide $s5 = "SbieDll.dll" $s6 = "dbghelp.dll" $s7 = "api_log.dll" $s8 = "dir_watch.dll" $s9 = "def_%s.jpg" wide $s10 = "pho_%s_%d.jpg" wide $s11 = "login=%s&password=%s&login_submit=Authorizing" wide $s12 = "gdiplus.dll" $s13 = "Set-Cookie:\\b*{.+?}\\n" wide $s14 = "charset={[A-Za-z0-9\\-_]+}" wide condition: 12 of ($s*) } |