› analyzing the persistence, features, and capabilities of a cross-platform backdoor
02/17/2018
love these blog posts? support my tools & writing on patreon :)
Want to play along? I've shared the malware, which can be downloaded here (password: infect3d).
Background
Next month, I'm stoked to be presenting some new research at SyScan360 in Singapore. Titled, "Synthetic Reality; Breaking macOS One Click at a Time" my talk will discuss a vulnerability I found in all recent versions of macOS that allowed unprivileged code to interact with any UI component including 'protected' security dialogs. Though reported and now patched, it allowed one to do things like dump passwords from the keychain or bypass High Sierra's "Secure Kext Loading" - in a manner that was invisible to the user 🙈.
As part of my talk, I'm covering various older (and currently mitigated) attacks, which sought to dismiss or avoid UI security prompts. Think, (ab)using AppleScript, sending simulated mouse events via core graphics, or directly interacting with the file system. An example of the latter was DropBox, which directly modified macOS's 'privacy database' (TCC.db) which contains the list of applications that are afforded 'accessibility' rights. With such rights, applications can then interact with system UIs, other applications, and even intercept key events (i.e. keylogging). By directly modifying the database, one could avoid the obnoxious system alert that is normally presented to the user:
Though Apple now thwarts this attack, by protecting TCC.db via System Integrity Protection (SIP) - various macOS keyloggers still attempt to utilize this 'attack.' I figured one of these keyloggers would be a good addition to my slides as an illustrative example.
Hopping over to VirusTotal, I searched for files containing references to the TCC.db database, which returned a handful of hits:
Besides a variety of CounterStrike hacks (csgohack.app), and (known) keyloggers (FreeKeylogger.dmg, KeyLogger.BlueBlood.A), an unflagged file named com.apple.audio.driver2.app (SHA-256: c20980d3971923a0795662420063528a43dd533d07565eb4639ee8c0ccb77fdf) caught my eye. It was recently submitted for a scan, in early January.
Note: Al Varnell, (@alvarnell), pointed out it's likely that the original file name was com.apple.audio.driver.app, which corresponds to internal strings within the binary. Thus we'll refer to this sample's application bundle as com.apple.audio.driver.app for the rest of this post.
Though currently no AV-engine on VirusTotal flags this application as malicious, the fact it contained a reference to (TCC.db) warranted a closer look.
__const:001D2804 text "UTF-16LE", 'touch /private/var/db/.AccessibilityAPIEnabled && s'
__const:001D2804 text "UTF-16LE", 'qlite3 "/Library/Application Support/com.apple.TCC/'
__const:001D2804 text "UTF-16LE", 'TCC.db" "INSERT or REPLACE INTO access (service, cl'
__const:001D2804 text "UTF-16LE", 'ient, client_type, allowed, prompt_count) VALUES (',27h
__const:001D2804 text "UTF-16LE", 'kTCCServiceAccessibility',27h,', ',27h,0
Using Digita Security's UXProtect, I was also able to easily confirm that Apple has not silently pushed out any XProtect signatures for the malware (to intrinsically protect macOS users):
Determining Malice
My first question was, "is com.apple.audio.driver.app malicious?"
Though there is no exact science to arrive at a conclusive answer for this question, several (massive) 'red flags' stick out here. Flags, that clearly confirm the malicious nature of com.apple.audio.driver.app:
As mentioned, the application contains a reference to TCC.db. AFAIK, there is no legitimate or benign reason why non-Apple code should ever reference this file!
The application is unsigned, though claims to be an "Apple audio driver". My WhatsYourSign Finder extension, will display any signing information (or lack thereof) via the UI:
The application is packed with UPX. Though packing a binary doesn't make it malicious per se, it's rare to see a legitimate binary packed on macOS:
$ python isPacked.py com.apple.audio.driver.app
scanning com.apple.audio.driver.app/Contents/MacOS/com.apple.audio.driver
UPX segments found
binary is packed (packer: UPX)
For it's main icon, the application uses macOS's standard 'document' icon to masquerade as a document. This is common tactic used by malware authors in order to trick user's in running their malicious creations:
When executed, the application displays a standard authentication prompt, requesting user credentials. After the user enters their creds, then application performs no other readily visible action. This is not normal application behavior:
Behind the scenes the application persists itself as a launch daemon. This is a common method employed by malware to ensure that it is automatically (re)started every time an infected system is rebooted. BlockBlock will detect this persistence:
Again, behind the scenes, the application will automatically beacon out to a server. While creating a network connection is itself not inherently malicious, it is a common tactic used by malware - specifically to check in with a command & control server for tasking. LuLu will intercept and alert on this connection attempt:
At this point I was thoroughly convinced that though no AV-engine on VirusTotal flagged com.apple.audio.driver.app, it was clearly malicious!
Let's now dive in and reverse it to gain a deeper understanding of its actions and capabilities.
Analysis
First, let's unpack the malware. Since it's packed with UPX, one can trivially unpack it via upx -d:
$ upx -d Contents/MacOS/com.apple.audio.driver
Ultimate Packer for eXecutables
Copyright (C) 1996 - 2013
UPX 3.09 Markus Oberhumer, Laszlo Molnar & John Reiser Feb 18th 2013
With LZMA support, Compiled by Mounir IDRASSI (mounir@idrix.fr)
File size Ratio Format Name
-------------------- ------ ----------- -----------
3292828 <- 983040 29.85% Mach/i386 com.apple.audio.driver
Unpacked 1 file.
Once the malware has been unpacked, one of the first things we notice when reversing its binary, is that it was apparently written in pascal. Though likely done to achieve cross-platform comparability, who the hell writes pascal on macOS!?! Well apparently at least one person!
How do we know it was likely written in pascal? First, looking at the malware's entry point, main(), we see it calling something named FPC_SYSTEMMAIN which in turn invokes a function named PASCALMAIN:
int _main(int arg0, int arg1, int arg2) {
eax = _FPC_SYSTEMMAIN(arg2, arg1, arg2);
return eax;
}
int _FPC_SYSTEMMAIN(int arg0, int arg1, int arg2) {
*_U_$SYSTEM_$$_ARGC = arg0;
_SYSTEM_$$_SET8087CW$WORD();
eax = _PASCALMAIN();
return eax;
}
The malware's malicious logic begins in the aforementioned PASCALMAIN function. Due to the presence of debug strings and verbose method names, reversing is actually quite easy!
First, the malware loads it 'settings'. It does by first building a path to its settings file, then invoking the LOADSETTINGS function. If the loading succeeds it logs a "LoadSettings ok" message:
Where is the malware's setting file? Well if we look at the disassembly we can see it appending "conx.wol" to file path of the malware's binary (e.g com.apple.audio.driver.app/Contents/MacOS/) - and the checking if that file exists:
A file monitor (such as macOS's built in fs_usage utility) dynamically reveals the path to this file, as the malware opens and reads it during execution:
# fs_usage -w -f filesystem
access (___F) com.apple.audio.driver.app/Contents/MacOS/conx.wol
open F=3 (R_____) com.apple.audio.driver.app/Contents/MacOS/conx.wol
flock F=3
read F=3 B=0x92
close F=3
Opening the settings file, "conx.wol", reveals the malware's configuration (in plaintext JSON):
The meaning of the settings can be ascertained by their abbreviation and/or value. For example, 'PO' is port (HTTP, 80), 'HO' is host (attacker's command & control server at 45.77.49.118). 'MU' is likely 'mutex', while 'VN' is the name of the victim. The 'LN' value is the name of the log file for the keylogger ('KL'). I'm guessing 'RN' is for run normal - meaning the implant can run as a default user (vs. root). Finally 'PN' is the process name of the malware.
Once the malware has loaded its setting from conx.wol, it persistently installs itself. The logic for the install is contained in the '_INSTALLMEIN_$$_INSTALL' function:
As previously noted, this persistent install attempt will trigger a BlockBlock alert:
The astute reader will have noted that the install (copy) operation and launching of the daemon is executed as root (user: 0). The malware accomplishes this by executing these operation via it's _LETMEIN_$$_EXEUTEWITHPRIVILEGES$$BOOLEAN function.
Reversing this function reveals it simply invokes Apple's AuthorizationExecuteWithPrivileges function. 'Under the hood' the OS invokes /usr/libexec/security_authtrampoline in order to execute the specified process as root (security_authtrampoline is setuid):
Of course in order for AuthorizationExecuteWithPrivileges to succeed, user credentials are required and must be entered via an OS authentication prompt. The malware hopes the naive user will simply enter such credentials:
Besides persistently installing itself as a launch daemon, the '_INSTALLMEIN_$$_INSTALL' function also attempts to provide the malware with accessibility rights (so that it may perform system-wide keylogging). In order to gain such rights the malware first creates the /private/var/db/.AccessibilityAPIEnabled file and then modifies the privacy database TCC.db, The former affords accessibility rights on older versions of macOS.
The logic to enable accessibility rights, can be found in a bash script that the malware creates in /private/var/tmp/runme.sh:
Though this script is executed as root, on newer versions of macOS (Sierra+) it will fail as the privacy database is now protected by SIP:
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.13.3
$ ls -lartO@ /Library/Application\ Support/com.apple.TCC/TCC.db
-rw-r--r-- 1 root wheel restricted /Library/Application Support/com.apple.TCC/TCC.db
However, on older versions of OSX/macOS the malware will gain accessibility rights:
At this point, the malware is now fully persistently installed and will be started as root, each time the infected system is (re)started:
Let's now look at the malware's features and capabilities.
Each time the malware is up and running it performs two main tasks:
kicks off keylogging logic
checks in with the command & control server and performs any received tasking
The keylogging logic (referred to as 'keyloser'), is started when the malware executes _KEYLOSER$_$TKEYLOGGERTHREAD_$__$$_CREATE$$TKEYLOGGERTHREAD from PASCALMAIN. The keylogger thread
eventually invokes a function at 0x0006a950 which starts the actual keylogging logic. Looking at its decompilation, it's easy to see that the malware is using Apple's CoreGraphics APIs to capture key presses:
int sub_6a950(int arg0, int arg1, int arg2, int arg3, int arg4) {
eax = CGEventTapCreate(0x1, 0x0, 0x0, 0x1c00, 0x0, sub_6a3d0);
if (eax != 0x0) {
CFRunLoopAddSource(CFRunLoopGetCurrent(),
CFMachPortCreateRunLoopSource(**_kCFAllocatorDefault, var_4, 0x0), **_kCFRunLoopCommonModes);
CGEventTapEnable(0x1, 0x1);
CFRunLoopRun();
}
...
return eax;
}
And speaking of keylogging via CoreGraphics APIs, I'm actually also talking about this in my SyScan360 talk:
As we can see in the malware's code and my slide, to capture keystrokes: simply create an 'event tap', enable it, and add it to the current runloop (note that root/accessibility is requires to capture all key presses). Now, any time the user generates a key event, the OS will automatically call the callback function that was specified in the call to CGEventTapCreate. For the malware, this is sub_6a3d0.
The code in the sub_6a3d0 function simply formats and logs the key press to file specified in the "LN" value of settings file: adobe_logs.log.
By 'tailing' the keylogger's log file, we can observe it in action...for example, logging my banking credentials:
Once the keylogging thread is off and running, kicks off the main client thread via a call to CONNECTIONTHREAD$_$TMAINCLIENTTHREAD_$__$$_CREATE$BOOLEAN$$TMAINCLIENTTHREAD. This first opens a connect to the malware's command & control server whose IP address and port are specified in the malware's settings file, conx.wol:
Once a connection has been made, the OSX/Coldroot gathers some information about the infected host and sends it to the server. The survey logic is implemented in a function at address 0x000636c0, which calls various functions such as 'GETHWIDSERIAL', 'GETUSERNAME', and 'GETRAMSIZEALL':
int sub_636c0() {
...
_OSFUNCTIONS_$$_GETHWIDSERIAL$$ANSISTRING();
_OSFUNCTIONS_$$_GETUSERNAME$$ANSISTRING();
_OSFUNCTIONS_$$_GETOS$$ANSISTRING();
_OSFUNCTIONS_$$_GETRAMSIZEALL$$INT64();
}
These functions invoke various macOS utilities such as sw_vers, uname, and id to gather the required information:
# ./procInfo
//get OS version
process start:
pid: 1569
path: /usr/bin/sw_vers
user: 501
args: (
"/usr/bin/sw_vers"
)
//get architecture
process start:
pid: 1566
path: /usr/bin/uname
user: 501
args: (
"/usr/bin/uname",
"-m"
)
//get user name
process start:
pid: 1567
path: /usr/bin/id
user: 501
args: (
"/usr/bin/id",
"-F"
)
In a debugger (lldb), we can set a breakpoint on send and then dump the bytes being sent to the command & control server:
Note that the malware actually prints this out to stdout as well:
(lldb) c
JSON Packet : {"Ver":1,"RAM":0,"CAM":false,"Serial":"x86_64\n","PCName":
"user\n - user","OS":"Mac OS X10.13.2","ID":"Mac_Vic","AW":"N\/A","AV":"N\/A"}
PC info sent ..
If we allow the malware to continue, we can also capture this same data in a network monitoring tools such as WireShark:
You might be wondering why in the survey data sent to the command & control server, 'Serial' is set to x86_64 or why the'RAM' is set to 0.
Well to generate the value for 'Serial', the malware executes uname with the -m flag...which return the architecture of the system (not the serial, which could be retrieved via something like: ioreg -l | grep IOPlatformSerialNumber). For determining the amount of RAM, the malware invokes a function called 'GETRAMSIZEALL'...this simply returns 0:
int _OSFUNCTIONS_$$_GETRAMSIZEALL$$INT64()
{
return 0x0;
}
Once OSX/Coldroot has checked in, it will process any tasking returned from the command & control server. The logic for this is implemented in the _NEWCONNECTIONS_$$_PROCESSPACKET$TIDTCPCLIENT$TIDBYTES function. This function parses out the command from the command & control server, and then processes (acts upon) it.
In disassembled code, this looks like the following:
__text:000691F7 call _CONNECTIONFUNC_$$_BYTEARRAYTOMAINPACKET$TIDBYTES$$TMAINPACKET
__text:000691FC mov eax, [ebp+command]
__text:000691FF test eax, eax
__text:00069201 jl loc_6986B
__text:00069207 test eax, eax
__text:00069209 jz loc_692C9
__text:0006920F sub eax, 2
__text:00069212 jz loc_692D9
__text:00069218 sub eax, 1
__text:0006921B jz loc_6935E
__text:00069221 sub eax, 2
__text:00069224 jz loc_69374
__text:0006922A sub eax, 1
__text:0006922D jz loc_693EC
__text:00069233 sub eax, 1
__text:00069236 jz loc_694AA
__text:0006923C sub eax, 2
__text:0006923F jz loc_695A2
...
Via static analysis, we can determine what commands are supported by the malware. Let's look at an example of this.
When the malware receives command #7 from the command & control server, it executes the logic at 0x000694aa. In the same block of code it contains the debug string "Delete File : ", a call to function named 'DELETEFILEFOLDER', and other debug string, "{{{{ Delete OK Lets test }}}}":
Probably safe to guess command #7 is the delete file (or directory) command! But let's confirm.
The 'DELETEFILEFOLDER' function calls _LAZFILEUTILS_$$_DELETEFILEUTF8$ANSISTRING$$BOOLEAN which in turn calls _SYSUTILS_$$_DELETEFILE$RAWBYTESTRING$$BOOLEAN which finally calls unlink (the system call to delete a file or directory).
Repeating this process for the other commands reveals the following capabilities:
file/directory list
file/directory rename
file/directory delete
process list
process execute
process kill
download
upload
get active window
remote desktop
shutdown
All are self-explanatory and implemented in fairly standard ways (i.e. delete file calls unlink), save perhaps for the remote desktop command.
When the malware receives a command from the server to start a remote desktop session, it spawns a new thread named: 'REMOTEDESKTOPTHREAD'. This basically sits in a while loop (until the 'stop remote desktop' command is issued), taking and 'streaming' screen captures of the user's desktop to the remote attacker:
while ( /* should capture */ ) {
...
_REMOTEDESKTOP_$$_GETSHOT$LONGINT$LONGINT$WORD$WORD$$TIDBYTES(...);
_CONNECTIONFUNC_$$_CLIENTSENDBUFFER$TIDTCPCLIENT$TIDBYTES$$BOOLEAN();
_CLASSES$_$TTHREAD_$__$$_SLEEP$LONGWORD();
}
It should be noted that if no command or tasking is received from the command & control server, the malware will simply continue beaconing...interestingly, sending the name of the user's active window in each heartbeat:
Alright, that wraps up our reversing sessions of OSX/Coldroot. Let's now discuss some other interesting aspects of the malware, such as its author, source-code, and business model!
Coldroot
Once the technical analysis of the malware was complete, I began googling around on the search term: Coldzer0. Looking at the disassembly of OSX/Coldroot we can see this string embedded in the binary, purportedly identifying the author's handle:
The source code, though (as noted), is both old and incomplete - provides some confirmation of our analysis. For example, the PacketTypes.pas file contains information about the malware's protocol and tasking commands:
The demo video is rather neat as it provides further insight into Coldroot, visually illustrating how an attacker can build (and customize) deployable agents:
...and also how they can be remotely interacted with, and tasked:
The video also confirms the fact that Coldroot is indeed a fully cross-platform 'remote admin tool' (RAT):
If you have some extra time on your hands, check the video, courtesy of Coldzer0:
In terms of the (apparent) hacker's plans for the Coldroot, he stated in the comments both its release date (1/1/2017) and that fact that it would be for sale:
Conclusions
In this blog post we provided a comprehensive technical analysis of the macOS agent of the cross-platform RAT OSX/Coldroot. Thought not particularly sophisticated, it's rather 'feature complete' and currently undetected all AV-engines on VirusTotal. Moreover, it is a good illustrative example that hackers continue to target macOS!
And remember if you want to stay safe, running the latest version of macOS will definitely help! For one, (due to a bug in UPX?) the OS refuses to even run the malware: