« Back to home

macOS Research Outtakes - File Extensions

If you follow our research over on MDSec’s blog, you will have seen a number of posts documenting macOS research we’ve recently completed.

As RedTeamer’s, we have a wealth of information available to us when it comes to attacking Windows endpoints, whether that be via a HTA, OLE, a macro office document or even simply binary hiding as a legitimate application, we are never short of options to gain access to a targets machine when phishing.

The same unfortunately can’t be said for macOS systems. If we take a look around, there are few posts or teardowns that show viable techniques we can use when targeting macOS.

In this post I wanted to show a few of the outtakes from our research which didn’t quite make up a full post, and provide a few tricks which may help you to gain a foothold during your next macOS engagement.

The barriers

So what are the barriers we face when coming up against a macOS system? Surprisingly the first is one of the most simple to work around, Gatekeeper.

Gatekeeper is macOS’s first line of defense against malicious applications being downloaded from the Internet.

Any regular Mac user will be familiar with the following prompt:


Here we see a nice dialog from macOS indicating that the application downloaded is untrusted, mainly because of a missing code signing certificate.

During an engagement, of course our job is to emulate some of the techniques used by real adversaries. Looking at malware reports, we can quickly see just how this is being bypassed in the wild:


That’s right, malware writers are simply using valid developer accounts.

Obviously acquiring certificates by any nefarious means would not be acceptable, which means we are generally left with the option of either purchasing a valid developer account, finding a nice Gatekeeper workaround, or extending our social engineering campaign to convince a user to bypass Gatekeeper.

For the remainder of this post we will assume the first option, however when delivering your campaign, it is important to factor in the obvious shortcomings of having your developer cert attached to your malware.

So just how can we craft a convincing campaign to compromise our targets machine?

Just send them an app

A few weeks ago (actually months, this post has been in draft for a while), I posted a quick screenshot on Twitter showing just how we can hide an app for our phishing purposes:

Playing around with some filetype phishing on MacOS. Spot the hidden .app…

Answer: They are all .app's :D pic.twitter.com/Lrh83K85pp
— Adam Chester (@xpn) July 25, 2018

As you may know, in previous versions of macOS it was possible to name a file as mysecrets.docx.app. Due to the way in which macOS removes the .app extension, what you were left with was a file extension which upon initial view looks exactly the same as a legitimate .docx.

Then Apple made a change in which any registered file extension could not appear before the .app without the true extension being revealed. For example, if we now name a file mysecrets.docx.app, we will see something like this:


It is interesting to note that an invalid extension will not result in the .app being shown. For example, if we name our application as secrets.docy.app, we see the following:


So how can we create something that meets the above requirements, but is a little more convincing? Well we can roll out homoglyphs to bypass the check for a legitimate file extension. For example, if we use IronGeek’s Homoglyph Generator, we see a few options which ultimately allow us to render arbitrary file extensions:


By simply selecting the appropriate homoglyph, we are able to meet the above requirement and hide the .app extension. Then all that is left to do is craft an icon for our payload, and we have an app which looks like this:


Delivering the app

Now we have our crafted payload and convincing filename, we just need to send this to our victim. Unfortunately unlike our Windows counterparts, this isn’t just a case of linking to a single file or wrapping within a HTML blob, as of course a .app is a directory which will need to be archived before we can send it on.

To deliver this file and have the most chance of success, we need to understand just what the target will be using to download our payload.

Assuming that your recon has showed Safari is in use, things are tipped in our favor, as Safari will automatically download and extract the file for us, leaving a nice icon for them to click on:


But quickly we learn that the users browser selection is not the only thing that we need to think about. What if the victim is using something like Google Mail? Well here we have a problem. In a bid to be helpful, we see that Google will often open a preview of .zip files, revealing pretty quickly that our file is not a .docx but is instead a .docx.app, raising suspicions:


So how can we work around this problem? Well, out of the box we know that macOS provides Archive Utility as it’s primary method of decompressing files. Loading Archive Utility, what we see are 3 filetypes supported:


Translated, we see that:

  • Compressed Archive - cpgz
  • Regular Archive - cpio
  • Zip Archive - zip

We know that a .zip will be expanded automatically by Google Mail, but what about the other two.

For a CPGZ, we simply see our embedded CPIO:


And if we use a CPIO:


Awesome, so looking at the above, if we send a .cpio, Google Mail will simply prompt the user to download the file. But what about that extension, would a .cpio file raise suspicions when we send this to our victim?

Let’s load Archive Utility to see if we can find a way around this. Using Hopper to peer inside Archive Utility, we start with the method -[BAHController doUnarchiveFile:]:


Here we see a call to -[BAHController dearchiveItem:withController:isIntermediateItem:]:


This leads to +[BAHCodec decompressorForFile:andOptions:] which shows just how Archive Utility goes about choosing a decompressor, using the +[BAHDecompressor classNameForFile:checkMagic:isPrimaryArchive:] method.

Initially we can see a number of common file extensions which are being searched for:


Things look quite straight forward, however once a supported file extension is found, we then see the following call:

r13 = [BAHDecompressor reconcileClassName:r13 withMagic:[[BAHController sharedInstance] magicInfoForFile:r12] isPrimaryArchive:sign_extend_64(var_2C)];

The first call is to -[BAHController magicInfoForFile:], which is simply a wrapper around the /usr/bin/file utility, used to grab the type of file independent of the file extension. The output is then passed to +[BAHDecompressor reconcileClassName:withMagic:isPrimaryArchive:] to ensure that the file extension matches the output from file:


Tracing, we actually see that the magic bytes identified by file result in the decompressor being selected ahead of the file extension…

So this means we can create any archive supported by Archive Utility, CPIO archive, GZIP etc.., and provide any other file extension supported .cpio, .tar.gz, .uu, .zip… and Archive Utility will reconcile the differences.

Using this knowledge, let’s create a CPIO, and simply rename it to .zip:


Awesome, Google Mail shows a generic error and prompts for download. And when the file is accessed by the victim, we see that Archive Utility extracts without a problem: