Uncovering the security protections in MAC - XProtect and MRT

In the second part of the series I will discuss on XProtect and MRT working and limitations for both the setups. This will give you an idea how robust Macos default malware detection solution is.

13 min read
Uncovering the security protections in MAC - XProtect and MRT

XProtect

Xprotect is a signature based malware detection solution available in MacOS, that scan for malicious content when a bundle or individual binary is executed. XProtect checks for known malicious content whenever:

  • An App is first launched

  • An app has been changed (in the file system)

  • XProtect signatures are updated

But in recent MacOS,  it checks the executable code of every app and command tool whenever it’s run, regardless of whether it's quarantine flag is set. The main XProtect related data is present in a loadable bundle located at /Library/Apple/System/Library/CoreServices/XProtect.bundle. We will discuss the bundle's structure later, let's first talk about how XProtect works.

  • When a new process is started with launchd(by double-clicking the app) or from terminal, the LaunchServices send and xpc message to CoreServicesUIAgent which handles the UI aspects of application loading.
  • CoreServicesUIAgent than call a  xpc service XprotectService.xpc which is part of XProtectFramework located at /System/Library/PrivateFrameworks/XprotectFramework.framework.  
  • The xprotect service scan for the malicious content in main executable and return the classification of the executable from this list in a parameter named XprotectMalwareType and send the information back to CoreServicesUIAgent.
  • Xprotect tags the file with value XprotectMalwareType even if the file is clean and signed. Based on the information received from xprotect, coreservicesuiagent  creates an alert for user and move the application to Bin. The alert message looks like this (may differ based on the XProtectMalwareType received from xprotect):

XProtect Components

Apple haven't open sourced any component of xprotect. Most of the content specific to xprotect is present in xprotect.bundle which is located at path mentioned above. The content in xprotect.bundle is updated periodically by Apple. You can check the version of xprotect content by using the following command.

$ system_profiler SPInstallHistoryDataType | grep -A 5 "XProtectPlistConfigData"

Now let's look inside xprotect.bundle. The bundle has the following resources inside it:

  • gk.db
  • LegacyEntitlementAllowlist.plist
  • XProtect.plist
  • XProtect.meta.plist
  • XProtect.yara

gk.db

It is again a sqlite db file with following tables:

table blocked_hashes has following format:

By default there are only 3 entries in this table. Let's check what each column means:

hash: cdhash of the executable

hash_type: cdhash type. Apple has updated code signing method in the past. Based on that cdhash differ. Older one has hash_type 1 and newer has 2.

flags: unknown

From name you can guess that these entries will be used to block executable having the above cdhash.

table blocked_teams has the following format:

There are total 132 entries in this file at the time of writing this post. This table is used to block malicious executable based on developer id. These developer IDs are associated with developer accounts, which apple has found to be used for shipping malware like Bundlore, Adload or UpdateAgent. It is my speculation that Apple is developing this list based on cdhashes it received for notarization check (link) since most of the team ids doesn't associate with any sample in VirusTotal.

table settings has field called schema_version which is set to 3.

You may think why this database file is named gk.db (gatekepper.db). The reason behind it is that this db is not called by xprotect but rather by gatekeeper(syspolicyd to be more specific) for blacklisting applications.

When you execute an application having cdhash or dev id  present in above blacklist, you will see the following alert:

Addition to this, this db is only queried when is application/executable is started with launch services (through double-clicking). An executable running from command line is safe from the blacklists in this db.

XProtect.yara

This is the core selling point for XProtect. This file contains yara rules associated with almost all famous malware families like Bundlore, HiddentLotus, Dok, Adload etc.  There are almost 160 rules while writing this post. Most of the rule names are in obscure format like MACOS.b70290c .

When you try to execute a macho file having yara signature here, you will get following alert from CoreServicesUIAgent:

When you click on "Move to Bin" button, CoreServicesUIAgent move the file to bin and add a deletion log in plist format inside Users/<Username>/Library/Logs/DiagnosticReports/XProtect_XXX-Mac.diag file with  yara rule name that has been matched.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
	<dict>
		<key>UserAction</key>
		<string>trash</string>
		<key>XProtectSignatureName</key>
		<string>MACOS.8f20223</string>
	</dict>
</array>
</plist>

If the detection is on an application bundle CoreServicesUIAgent will show the following alert:

In above alert box you will see the detection name as an extra field. This will happen since MacOS has verified the developer id in gk.db blacklist before checking XProtect.yara, hence it is more certain about the executable to be malicious.

XProtect.plist

XProtect.plist is a highly powerful and feature rich plist file, used to blacklist content present in form of application bundle or any other possible UTI like compressed files, scripts execution, java application, microsoft docs etc. This property list file have multiple entries in dictionary format. A typical entry looks like below:

	<dict>
		<key>Description</key>
		<string>OSX.ParticleSmasher.A</string>
		<key>LaunchServices</key>
		<dict>
			<key>LSItemContentType</key>
			<string>com.apple.application-bundle</string>
		</dict>
		<key>Matches</key>
		<array>
			<dict>
				<key>MatchFile</key>
				<dict>
					<key>NSURLTypeIdentifierKey</key>
					<string>public.unix-executable</string>
				</dict>
				<key>MatchType</key>
				<string>Match</string>
				<key>Pattern</key>
				<string>636F756C646E2774206F70656E2074686520646200</string>
			</dict>
			<dict>
				<key>MatchFile</key>
				<dict>
					<key>NSURLTypeIdentifierKey</key>
					<string>public.unix-executable</string>
				</dict>
				<key>MatchType</key>
				<string>Match</string>
				<key>Pattern</key>
				<string>25402F46495245464F585F25402E7A697000</string>
			</dict>
			<dict>
				<key>MatchFile</key>
				<dict>
					<key>NSURLTypeIdentifierKey</key>
					<string>com.apple.applescript.script</string>
				</dict>
				<key>MatchType</key>
				<string>Match</string>
				<key>Pattern</key>
				<string>46617364554153</string>
			</dict>
			
			</dict>
		</array>
	</dict>

There are total 94 signature currently. Let's go through each key to understand the usage clearly:

Description: This key holds the malware name. Most signatures are for infamous threats in MacOS like Bundlore, Aceinstaller, CoinMiner etc.

LauchServices: This key defines on what URI type the following signature should trigger.

A typical launchservices key looks like this:

<key>LaunchServices</key>
		<dict>
			<key>LSItemContentType</key>
			<string>com.apple.application-bundle</string>
		</dict>

LSItemContentType set to the value in content type seen by launchservice that should trigger the signature. Current signatures have the following LSItemContentType:

  • com.apple.application-bundle
  • com.microsoft.word.doc
  • com.apple.installer-package
  • public.data
  • com.apple.installer-meta-package
  • com.sun.java-archive

Matches: This key value holds an array of dictionary items, which has the  detection signature pattern. This key looks like this in general:

<key>Matches</key>
		<array>
			<dict>
				<key>MatchFile</key>
				<dict>
					<key>NSURLTypeIdentifierKey</key>
					<string>public.unix-executable</string>
					<key>NSURLFileSizeKey</key>
					<integer>110000</integer>
					<key>NSURLNameKey</key>
					<string>iCnat</string>
				</dict>
				<key>MatchType</key>
				<string>Match</string>
				<key>Identity</key>
				<data>iob/gI0JDUACAaH5TY9wap2hFso=</data>
			</dict>
            <dict>
				<key>MatchFile</key>
				<dict>
					<key>NSURLNameKey</key>
					<string>Codec-M.tar</string>
					<key>NSURLTypeIdentifierKey</key>
					<string>public.tar-archive</string>
				</dict>
				<key>MatchType</key>
				<string>Match</string>
				<key>Pattern</key>
				<string>636F6D2E7768697465736D6F6B652E</string>
			</dict>
		</array>

Each dictionary holds a signature for a single file with filetype defined by NSURLTypeIdentifierKey. Current signatures have following filetypes present:

  • public.unix-executable
  • com.apple.applescript.script
  • public.data
  • com.apple.mach-o-dylib
  • {dyn.*}
  • com.apple.application-file
  • com.sun.java-archive
  • com.apple.installer-package-archive
  • public.zip-archive
  • com.microsoft.word.doc
  • public.tar-archive

You can see that XProtect is capable of blocking malicious content in form of quite a lot of file types. This also proofs that LaunchService is involved with all type of file open activity in MacOS whether it's executable/bundle or word document or any compressed file format.

Another subkey in this dictionary is NSURLNameKey which holds the name of the file in case NSURLTypeIdentifierKey is not present. The detection doesn't depend on this key( i.e you will see trigger from XProtect even if the filename is different).

The detection pattern is present in either of the following two keys:

Pattern: holds the hex bytes with * as separator.

Identity: hold the base64 value of the sha-1 hash.

When you try to open a document or an application having signature in XProtect.plist, you will receive an alert message like this:

XProtect.meta.plist

This plist file is used to block malicious safari extension and other outdated application plugins.

Safari Extension blocking: When you download a Safari extensions, it added a application bundle in /Applications. This bundle contains plugin with .appex extension which later move to /User/Username/Library/Safari/Extensions. Like other application bundle, these applications also hold CFBundleIdentifier and Developer id. The detection is based on that.

			<dict>
				<key>CFBundleIdentifier</key>
				<string>com.searchnt.safari</string>
				<key>Developer Identifier</key>
				<string>6ERPEMNB65</string>
			</dict>
			<dict>
				<key>CFBundleIdentifier</key>
				<string>com.shelfsick.safari</string>
				<key>Developer Identifier</key>
				<string>33HGJH7H8P</string>
			</dict>
			<dict>
				<key>CFBundleIdentifier</key>
				<string>com.searchnt.safari</string>
				<key>Developer Identifier</key>
				<string>LUZSN84HYP</string>
			</dict>
			<dict>
				<key>CFBundleIdentifier</key>
				<string>com.searchtrust.safariext</string>
				<key>Developer Identifier</key>
				<string>9V6HEQPZK3</string>
			</dict>
            ...
            ...

Note: During my research, I found that XProtect will only block the extension when they are executed by double click. If the main macho is executed from command line, then there is no alert for such case.

This plist also blocks other plugin with outdated version:

<key>com.apple.java.JavaAppletPlugin</key>
			<dict>
				<key>MinimumPlugInBundleVersion</key>
				<string>14.8.0</string>
				<key>PlugInUpdateAvailable</key>
				<true/>
			</dict>
			<key>com.apple.java.JavaPlugin2_NPAPI</key>
			<dict>
				<key>MinimumPlugInBundleVersion</key>
				<string>14.8.0</string>
				<key>PlugInUpdateAvailable</key>
				<true/>
			</dict>
			<key>com.macromedia.Flash Player ESR.plugin</key>
			<dict>
				<key>MinimumPlugInBundleVersion</key>
				<string>18.0.0.382</string>
				<key>PlugInUpdateAvailable</key>
				<true/>
			</dict>
			<key>com.macromedia.Flash Player.plugin</key>
			<dict>
				<key>MinimumPlugInBundleVersion</key>
				<string>32.0.0.101</string>
				<key>PlugInUpdateAvailable</key>
				<true/>
			</dict>
			<key>com.microsoft.SilverlightPlugin</key>
			<dict>
				<key>MinimumPlugInBundleVersion</key>
				<string>5.1.41212.0</string>
				<key>PlugInUpdateAvailable</key>
				<true/>
			</dict>
            ...
            ...

LegacyEntitlementAllowlist.plist

This is the last file we are covering for XProtect bundle. This plist contains a very long array of cdhashes which are encoded.

<key>cdhashes</key>
        <array>
                <data>
                AAFd7LJtQHNzgvxZ5kOMf5kNDVo=
                </data>
                <data>
                AAQCJMThA3BGcNrYDj3cGpx+i3U=
                </data>
                <data>
                AAQYbKSnpJxvCtTZc7cRC9Jo+bQ=
                </data>
                <data>
                AAUzQNGkVn8nJMreEIqz4P0lahI=
                </data>
                <data>
                AAxqo7k51G/ak+Xg9hNNo61LqVI=
                </data>
                <data>
                ABBEGu7ZCbgrt3IAqg7k15zBR1Q=
                </data>
                <data>
                ABDXjTxbm1MVYk88ANcOTl7j8Qc=
                </data>
                ...
                ...

It is difficult to conclude any information about this plist. But It's my assumption that this is a whitelist for macho executable that requires outdated entitlements to function properly.

That's all about XProtect. In conclusion, XProtect holds a good amount of static signatures, but not as much as an Antivirus solution generally have. Besides that, a major limitation of xprotect is it only checks for malicious content during open phase of a document, specially when LaunchServices is involved. It's not much difficult to find a way to bypass the role of LaunchServices in file opening.

Malware Removal Tool (MRT)

As mentioned above, XProtect only scan for malicious content while the execution or opening of file. To make MacOS default security more robust, apple has included a tool called MRT for scanning file present in disk time to time to look for malicious content. From all Apple's documentation:

Malware Removal Tool (MRT) is an engine in macOS that remediates infections based on updates automatically delivered from Apple (as part of automatic updates of system data files and security updates). MRT removes malware upon receiving updated information and it continues to check for infections on restart and login.

The application bundle for MRT is located at /System/Volumes/Data/Library/Apple/System/Library/CoreServices/MRT.app on latest MacOS. MRT.app has two executables in MacOS directory MRT and mrt-helper.  MRT is a giant 3MB of  executable that holds all the important detection logics. mrt-helper is a small helper program contains few functions required by MRT. All of the MRT code is closed sourced. The only way to understand MRT working is through reverse engineering.

As mentioned above, MRT executed every time you login or restart your system. MRT runs in two mode - agent and daemon. It can also be spawned from command line:

When starting as agent, MRT send xpc request to MRT daemon and the MRT daemon scan the filesystem for the malicious indicators and resolve it, then send the status to agent using notifyd. Later, agent logs the details received from Daemon or stdout on terminal.

Initial triage on MRT gives me indications that it is a static scanner that runs on login/reboot. But after reversing the MRT code, I found it to be impressively powerful tool that has detection not only just based on pattern but different filesystem indicator to find malicious activity. Moreover it not just notify user but also remidiate the infection to put your machine on safe state.

All the malicious indicators are checked one by one over the filesystem. These all reside in a single function.

Currently, MRT have detection for almost 90 malware. Each Malware family signatures and detection are different.  Some are generic static pattern based detection.

Some are based on presence of certains files/directories in filesystem.

Looking for dufh and com.apple.updates.plist

Once daemon find these indicators file or main malicious file, It deletes those as a step for remediation. As a small activity, let's try to look through MRT working in action.

Following are the indicator MRT looks for in case it's scanning your system for OSX.ATG2 threat.

  • Presence of  ~/Library/LaunchAgents/com.apple.updater.plist
  • Presence of  /Users/Shared/dufh
  • Presence of  ~/Library/LaunchAgents/com.apple.updates.plist
  • Presence of  /Users/Shared/.local/kextd

Let's create these files on a test machine and start the MRT in agent mode.

From the above output, it is clear that MRT is performing two important actions here. First, putting your system in safe state by unloading any malicious tasks. And delete the indicators as part of remediation.

Conclusion

XProtect is a good malware protection solution for MacOS that will definitely protect the macos environment against common threats present in the wild. But a major limitation with the XProtect is its limited coverage and less frequent updates. It has detection for major malware families affecting OSX architecture, but far away from covering emerging threats. On top of XProtect, MRT is a game changing addition of Mac security but need more wider coverage to solely rely on.Initial triage on MRT gives me indications that it is a static scanner that runs on login/reboot. But after reversing the MRT code, I found it to be an impressively powerful tool that has detection not only just based on pattern but different filesystem indicator to find malicious activity. Moreover, it not just notify user but also remediate the infection.