> osx/proton (re)appears
Aloha it’s Patrick, Chief Security Researcher at Synack. In my free time, I also run a small OS X security website objective-see.com, where I share my personal OS X security tools and blog about OS X security and coding topics. Below is a post originally published on my site, which discusses one of my tools and more generally a way to monitor processing creation on OS X. Read & enjoy!
Today started like pretty much every other day in Hawaii, surf & beach 😉
However, around noon, Eric Holtam (@eholtam) tweeted the following:
Mahalo to @mikeymikey to notifying me about this tweet!
Handbrake is an ‘open-source video transcoder.’ Heading over to their website (handbrake.fr), we can see they’ve added a ‘Security Alert’ for Mac Users:
Following the url, links to a rather dire security alert, Mirror Download Server Compromised:
The security alert also provided a hash of the disk image (0935a43ca90c6c419a49e4f8f1d75e68cd70b274) that was trojaned by the hackers.
Hopping over to VirusTotal, we can see that while this .dmg was submitted for analysis, no anti-virus engines are currently flagging it. No surprise there 😐
Once we have a copy of the infected .dmg (I’ve shared it here password: infect3d), analysis can commence. Since it’s the weekend – I’m going to take the ‘lazy’ (efficient?) route and basically just run the infected application and see what happens 🙂
In order to facilitate malware analysis I wrote a simple user-mode ‘process monitor’ library that allows us to easy track what application is doing – in terms of spawning other processes, etc:
ProcessMonitor* procMon = nil;
ProcessCallbackBlock block = ^(Process* newProcess)
NSLog(@”new process: %@”, newProcess);
procMon = [[ProcessMonitor alloc] init];
[[NSRunLoop currentRunLoop] run];
Running this code and executing the infected Handbrake application, we can see exactly what’s going on:
signatureStatus = “-67062 (unsigned)
args: “-c”, “pgrep -x activity_agent && echo Queue.hbqueue”
args: “-P”, “qzyuzacCELFEYiJ52mhjEC7HYl4eUPAR1EEf63oQ5iTkuNIhzRk2JUKF4IXTRdiQ”,
So yah, when run, the infected Handbrake application:
- unzips Contents/Resources/HBPlayerHUDMainController.nib to /tmp/HandBrake.appâ€¨. This ‘nib’ is a password protected zip file who’s password is: qzyuzacCELFEYiJ52mhjEC7HYl4eUPAR1EEf63oQ5iTkuNIhzRk2JUKF4IXTRdiQ
- launches (opens) /tmp/HandBrake.app
Once the /tmp/HandBrake.app is launched, it displays a (fake) authentication popup – which is how the malware attempts to elevate its privileges:
If the user is tricked into providing a user name and password the malware will install itself (/tmp/HandBrake.app) persistently as: ‘activity_agent.app’.
Thankful, BlockBlock can alert us of this fact:
Dumping the Launch Agent plist file (fr.handbrake.activity_agent.plist), we can see the malware has been set to automatically start each time the user logs in:
<?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”>
According to the HandBrake advisory, the malware’s peristent component, activity_agent.app is a ‘a new variant of OSX.PROTON‘
Proton (variant ‘A’) was discussed earlier this year by the media (for example, see: “Hackers Selling Undetectable Proton Malware for macOS in 40 BTC”)
Though Apple released an XProtect signature for it, the sample was never publicly shared. However, the malware author was kind enough to describe (‘advertise’) its capabilties:
With the HandBrake hack, finally now we have a variant for analysis :). Initial triage confirms, yes this a variant of OSX/Proton (‘B’), although some of the features found in the ‘A’ variant, (such as the ability to take screenshots) are not present.
Again, unsurprisingly this new variant of OSX/Proton is also currently undetected by any anti-virus engines on VirusTotal:
Check back for more analysis on OSX/Proton!
As with KeRanger and Keydnap, hackers targeted an official distribution website of legitimate macOS software. With access to HandBrake’s mirror, they trojaned the legitimate application, meaning any user who downloaded the application would inadvertently infect themselves!
Luckily the trojaned disk image was only online for a few days. However as is often (always!?) the case, no anti-virus products flagged the malware 🙁 So if you recently download HandBrake, unless you were running something like BlockBlock you’d likely have been infected.
To check if you’re infected, look for the following:
- a process named ‘activity_agent’
- an application name ‘activity_agent.app in ~/Library/RenderFiles/
- a plist file: ‘~/Library/LaunchAgents/fr.handbrake.activity_agent.plist
Apple has now also pushed out an XProtect signature, meaning that all new infections should be twarted. Hooray!
$ cat /System/Library/CoreServices/XProtect.bundle/Contents/Resources/XProtect.yara
private rule Macho
description = “private rule to match Mach-O binaries”
uint32(0) == 0xfeedface or uint32(0) == 0xcefaedfe or uint32(0) == 0xfeedfacf
or uint32(0) == 0xcffaedfe or uint32(0) == 0xcafebabe or uint32(0) == 0xbebafeca
description = “OSX.Proton.B”
Macho and filesize < 800000 and hash.sha1(0, filesize) ==
Ok, so kudos to Apple for the quick turn around on signatures….but the signature is:
- just a SHA-1 hash
- matches on the trojaned Handbrake binary (HandBrake.app/Contents/MacOS/HandBrake on the .dmg)
$ shasum -a 1 /Volumes/HandBrake/HandBrake.app/Contents/MacOS/HandBrake
This means if the malware authors used any other infection vector, or even just recompiled the trojaned binary, this signature would no longer flag the malware :/ Do people still say ‘yolo’?
And even if you don’t have source code, you can just flip a single bit in the binary to thwart the signature. To test this, I changed the final byte in HandBrake.app/Contents/MacOS/HandBrake from an 0x00 to 0xFF. While this doesn’t impact functionality of the binary, it changes its SHA-1 hash, meaning the malware is no longer blocked by XProtect. The following, first shows XProtect ‘blocking’ OSX/Proton.B. However, a second modified version is allowed to run, as the signature no longer matches: