If you’re not sure whether you want to invest time in learning AppleScript, this post is for you. Here I’ll outline four good reasons to learn AppleScript. I’m sure they’re not the only ones, but they’re the main ones that come to my mind as a daily user of the language. If, after reading this post, you want to give it a try, be sure to follow this series, as we’ll be quickly moving on with hands-on examples and detailed explanations that will rapidly turn you into an AppleScript power user! At the end of this post, I’ll briefly discuss tools, so that you’re ready to get started when the next in this series, User In, User Out, is published.
First of all, AppleScript can interact with other applications. That means it can get one app to perform a function and pipe the result to another app to perform a different function that the first app didn’t have. There’s no limit to the number of apps and functions you can chain together in this way (other than your computer’s resources). Why would you want to chain apps together like that?
To achieve things that none of those apps can do on their own.
Imagine this scenario (scripts for this appear later in this series of posts): Suppose you run a small business and customer orders come in via email. With an AppleScript, you can have those emails automatically scanned, the customers’ order details extracted, and your Excel or Numbers spreadsheet updated accordingly. You could then have the product details forwarded to another person (Packaging?) and the customer details forwarded to a third (Marketing?). Your script could tell Word, or Pages, to print out a label, and tell Mail to now send an automated response back to the customer. There is no one program on your computer that can accomplish all that, but you can, with AppleScript.
Once set up, none of this requires any interaction on your part. You build the script, test it, and add it as a Mail rule. The rest happens automatically when the mail arrives in your Inbox; you don’t need to monitor it. You can go on holiday. This ability to automate is what makes AppleScript so unique.
AppleScript’s ability to chain or pipe application functions together is similar to the Unix command line ability to pipe utilities together, only it allows you to do it with full-blown applications. But you can use it to connect those applications to command line utilities, too. This is the second thing that makes AppleScript unique: integration across the entire macOS environment. You can even chain it to other programming languages.
For example, I could have AppleScript run some Python code, take the result and run that through a Perl script, and take the result of that and display it to the user (or myself) in a dialog box or notification (or send an email, or a Chat message, etc). And I can do that without having to mess about worrying how to create graphical user interface elements like you might do with Tcl/Tk (if you know what that is; if you don’t, forget it!).
The relationship between AppleScript and the shell is symbiotic. If you’re a shell diehard, you’ll be happy to know that you can actually create and execute AppleScripts in
.sh files without ever going near an AppleScript editor.
AppleScript can not only harness the power of other scripting languages, it can harness the power of macOS itself. The AppleScript-ObjectiveC bridge means you could, if you wanted to – and many programmers do – create full on native macOS Cocoa apps without ever getting into the intricacies of Xcode projects and workspaces. You can even code sign your AppleScript apps from within the script editor.
Finally, AppleScript can drive the user interface and even drive apps that haven’t been specifically made to support AppleScript. If you find yourself repeatedly doing the same actions in the UI to achieve a task, you can cut-out the middle-man (you!) and tell AppleScript to click those buttons, move those windows or copy that text from Safari and paste it into Pages instead of laboriously and repeatedly doing it yourself. This creates an eery effect not unlike those old-time pianolas.
Where’s the catch? To achieve the level of automation and time-saving we’ve been discussing, you’re going to have to invest some time up front learning how to script. It won’t always be easy, and you won’t always be happy that it’s not easy, but that’s the price of investing in learning anything.
If you’re ready to learn this amazing, unique language, let’s get tooled up!
I’ll keep this short. You can learn AppleScript the hard way using the built-in Script Editor, or you can learn AppleScript the easier way by using the free 3rd-party editor Script Debugger.
Script Debugger gives you a full-featured trial for 20 days, and after that if you don’t want to buy it you lose some of the more advanced features but you can use the rest indefinitely anyway. It works in rather the same way as BBEdit’s trial does, if you’re familiar with that.
If you save scripts in Script Debugger (so long as they’re not debug scripts, more on that later), you can run (and edit) them in Script Editor and vice versa. In other words, you’re not locked in to a proprietary tool.
I’m not even going to consider that you’d choose to learn AppleScript the hard way since the easier way is free, so all the examples in this series of posts will use Script Debugger. However, unless otherwise marked as SD-only or SD-paid-only, you can do all of the examples in the series in either tool.
Don’t worry, at this point, about how to use either Script Editor or Script Debugger. We’ll get into that in the next post: hello, applescript 2: User In, User Out. Follow Applehelpwriter to be notified when a new post is published.
Ever wished you could see at a glance whether your network has changed without having to click on the Wifi icon in the Status bar to check the currently active connection? I know I have, particularly when toting the laptop between work, home and coffee shop.
Although you can require admin approval for changing networks in System Preferences, in practice that can often be quite disruptive. It also has the potential to expose your login password in public places or situations where it might be awkward or inconvenient to insist on privacy while you type it in.
It would be easier, it seemed to me, if I could just always see the name of the currently connected network in the Status bar, instead of having to actively go and look to see if it has changed.
I decided to solve the problem by writing my own little Wifi Display utility, which I’m sharing here for free for anyone that has a similar need.
The Wifi Display.app simply displays the currently active SSID Wifi name in the Status bar. You can command-drag the Wifi name along the Status bar to move it next to your Wifi icon for visual contiguity. The app is sandboxed and signed with my Apple developer ID.
Wifi Display is free to use and requires macOS 10.10 Yosemite or higher.
Share and enjoy! 🙂
There’s no doubt that System Integrity Protection has helped keep macOS more secure since its introduction in 10.11, and it continues to see updates that restrict what can be modified and where non-system files can be stored.
Apple’s official, user-facing documentation says:
Unfortunately, this documentation leaves out an important part of the story. The full list of protected paths and process labels can be found in a bunch of related files in the Sandbox folder within System/Library.
Among these are a list of protected locations in the rootless.conf file. The file, however, tells a little more than Apple’s user-facing documentation. Not only does it list the locations that can’t be modified, it also lists some that can. Despite what Apple officially says, not everything in System, it turns out, is in fact protected by SIP.
We can use a quick-one liner on the command line to output the exceptions on the current system like so:
awk '$1 ~ /^\*/' /System/Library/Sandbox/rootless.conf
On my 10.13.6 system that returns 9 locations, four of which are within the System’s Library folder:
Let’s check to see if these paths are really writable. We’ll create a simple script that, when run, produces a dialog box showing where the script is located. We first create the script in the /tmp folder, give it executable permissions, then move it into the System Library’s ‘Speech’ folder. We can do all this on the command line in Terminal, then execute it:
Sure enough, our test produces a script showing that it’s running out of one of the locations listed as an exception in rootless.conf.
This, of course, isn’t a SIP vulnerability. The paths we’re talking about are listed as exceptions to SIP protection, after all; what’s more, they do indeed require administrator privileges to write to (although not to run). The issue is that very few users will know that these paths are exceptions. In fact, aside from their being written in rootless.conf, there may be no other place where they are all documented, at least not at the user level. And that obscurity, of course, means many will have no idea that malware can install itself in places in the System folder where, for sure, most users will fear to tread.
Moreover, even if the user were to notice these paths in a process output or list of open files in Activity Monitor, it would be very easy to overlook them as being legitimate since they would all begin with the path ‘/System/Library/…’. Naturally, we assume the System’s folder is reserved for system files, not the user’s and not third-party applications’ either. Apple’s user-facing documentation that we referred to earlier encourages this very assumption.
What does it all mean?
In this post we’ve seen that there are places in the System folder that could easily be adopted as a nice hiding place for malware which has acquired elevated privileges. The aim here was to make these exceptions a little less obscure and to encourage people – especially those troubleshooting macOS for malware and adware issues – to add these locations to their list of places to keep an eye on.
Featured pic: Protection by disguy2k
It’s been a truism on macOS for some time that the most reviled piece of software on the platform is MacKeeper, but brother-in-arms Advanced Mac Cleaner must be running it a close second.
Advanced Mac Cleaner is produced by PCVark and has many incarnations. Aside from ‘AMC’, it’s also distributed as Mac Tonic, Mac Mechanic, Malware-Crusher, Mac Optimizer and now, the most recent form we’re seeing, Mac Auto Fixer.
Like all the other forms of AMC, this app gets bundled in with fake Flash installers and writes itself all over your Mac to multiple places inside your user and local domain Library folders. Here’s a 40-second video showing how Mac users get tricked into installing AMC and its fake virus scanner:
For those of you that want to remove Mac Auto Fixer and related manually, here’s a list of most of the paths you should look for:
/Applications/Mac Auto Fixer.app
/Library/Advanced Mac Cleaner
/Library/Application Support/Advanced Mac Cleaner
/Library/Application Support/Mac Mechanic
/Library/Application Support/Mac Tonic
/Volumes/MacAutoFixer/.hlpr/Mac Auto Fixer
~/Applications/Mac Auto Fixer.app
~/Library/Advanced Mac Cleaner
~/Library/Application Support/Advanced Mac Cleaner
~/Library/Application Support/Mac Auto Fixer
~/Library/Application Support/Mac Mechanic
~/Library/Application Support/Mac Tonic
~/Library/Logs/Advanced Mac Cleaner.log
~/Library/Logs/Mac Auto Fixer.log
~/Library/Mac Auto Fixer
You can also save yourself a whole lot of grief by using my shareware troubleshooting tool DetectX Swift, which will not only find all these pesky elements for you, it’ll remove them all for you, too. There’s no requirement to pay, we don’t mind ridding your Mac of this stuff for free!
Most recent update: Mon 3 Sep 2018
Want to remove MacKeeper? The easiest way is to use my free/shareware app DetectX Swift, but if you’re looking to do it yourself, here’s the complete list of all past and current known filepaths.
Bear in mind that DetectX Swift can find other MacKeeper paths that are not on the list due to its internal search heuristics; however, I’ll update this list as new paths come to light. If you happen to find any that are not on the list, please share in the comments!
Thx & Enjoy!
/Library/Security/SecurityAgentPlugins/MKAuthPlugin.bundle -- warning: deleting this file could harm your Mac! Contact me for help.
~/Library/Application Support/MacKeeper 3
~/Library/Application Support/MacKeeper Helper
Bundle Identifiers & Launch Labels
how to uninstall MacKeeper
For small enterprise developers like myself, commercial analytics aren’t really an option. And while there are open source alternatives like UKCrashReporter, I’ve been lucky enough to suffer relatively few crashes and typically just ask users to manually submit crash reports (stored in ~/Library/Logs/DiagnosticReports) as and when they occur.
Choosing a method of collecting crash reports is one thing, but scouring them for useful information is quite another, and the reams of data often included can seem a little overwhelming.
On a good day, your crash report may include a direct reference to the method or function that’s caused the issue, like this one from an early version of my troubleshooting app DetectX Swift:
On other days, though, you might get presented with nothing but a bunch of unhelpful memory addresses:
It’s at this point that you need to enlist the help of the built-in command-line tool atos. In the remainder of this post, we’re going to learn what it does and how to use it to find the line in our source code that caused the crash.
How does atos help?
The beauty of
atos is that it will give you a reference to the source file, function and even line number in your code where the crash occurred. Given that it can do this for a crash that occurred on another user’s machine that you can’t reproduce locally and don’t have access to, this seems like nothing short of magic.
Here’s an example of what
atos might provide from a crash log like the one above:
ViewController.checkReg(isCli:) (in DetectX Swift) (ViewController.swift:4042)
The output from
atos tells me the name of the Swift source file, the name of the function and — here’s the truly wonderous part — even the line number: 4042.
This is all part of the magic of symbollication, which is such an esoteric word I’m not even going to try to spell it again :-). Instead, let’s just get down to the practical nitty-gritty of how to get this kind of data out of our users’ crash reports.
How to use atos
The method is fairly simple and goes like this:
1. Create a folder called “CrashWork”.
2. Go to Xcode’s ‘Organizer’, and right-click on the archive of the version of the app that crashed.
Choose “Show in Finder”. That takes you to the
.xcarchive file in Finder, from which right-click again and choose “Show Package Contents” to open the package:
3. Click on the
.dSYM file and make a copy of it. Switch back to your CrashWork folder and paste the copy in there. Grab a copy of the same version of your app that crashed (you can also get that from the Products folder in the .xcarchive package, if you don’t have one handy elsewhere) and place it in the same folder:
Important: Be sure you’re working with the same version of your app as the user;
atos needs that to match up the addresses in the crash report, and any other version will produce incorrect results or an error.
4. It’s now time to head on over to the Terminal.
cd into your CrashWork directory:
5. The format of the command is generally going to be like this (see man atos for options):
atos -o <path to executable> -arch x86_64 -l <load address> <address>
<path to executable> is the path all the way to the Mach-O binary in your app bundle in the CrashWork folder, so the path in my example looks like this:
atos -o DetectX\ Swift.app/Contents/MacOS/DetectX\ Swift -arch x86_64 -l <load address> <address>
You need to be careful to get the
<load address> and the
<address> the right way around. They are the reverse order of what you see in the crash log:
Now my complete example looks like this:
atos -o DetectX\ Swift.app/Contents/MacOS/DetectX\ Swift -arch x86_64 -l 0x10a10e000 0x000000010a16a601
6. Hitting ‘return’ produces the magic:
Earlier this year, Digita Security’s Patrick Wardle took apart a cross-platform backdoor trojan he nicknamed ”ColdRoot’. Wardle was retro-hunting possible malware by searching for apps on VirusTotal that access Apple’s TCC privacy database.
For those unfamiliar, TCC.db is the database that backs the System Preferences > Security & Privacy | Accessibility preferences pane and which controls, among other things, whether applications are allowed access to the Mac’s Accessibility features. Of interest from a security angle is that one of the permissions an app with access to Accessibility can gain is the ability to simulate user clicks, such as clicking “OK” and similar buttons in authorisation dialogs.
One particular comment in Wardle’s article caught my eye:
there is no legitimate or benign reason why non-Apple code should ever reference [the TCC.db] file!
While in general that is probably true, there is at least one good reason I can think of why a legitimate app might reference that file: reading the TCC.db used to be the easiest way to programmatically retrieve the list of apps that are allowed Accessibility privileges, and one reason why a piece of software might well want to do that is if it’s a piece of security software like DetectX Swift.
If your aim is to inform unsuspecting users of any changes or oddities in the list (such as adware, malware or just sneaky apps that want to backdoor you for their own ends), then reading TCC.db directly is the best way to get that information.
Just call me ‘root’
Since Apple put TCC.db under SIP protection subsequent to my reports on Dropbox’s user-unfriendly behaviour, apps are no longer able to write to the database via SQL injection. An app with elevated privileges can, however, still read the database. A sufficiently privileged app (or user) can output the current list with:
sudo sqlite3 /Library/Application\ Support/com.apple.TCC/TCC.db 'select * from access'
On my machine, this indicates that there are twelve applications in the System Preferences’ Privacy pane, all of which are enabled save for two, namely LaunchBar and Safari:
We can see from the output that LaunchBar and Safari both have the ‘allowed’ integer set to ‘0’ (the middle of the three values in “0|0|1”) , whereas all the other apps have it set to ‘1’ (“0|1|1”).
It’s not clear to me why reading the database should require privileges. Certainly, Apple have provided APIs by which developers can test to see if their own apps are included in the database or not. The AXIsProcessTrusted() global function, for example, will return whether a calling process is a trusted accessibility client (see AXUIElement.h for related functions):
However, there remains a case (as I will demonstrate shortly) where developers may well need to know whether apps other than their own are, or are not, in the list. Moreover, there doesn’t seem to be any obvious vulnerability in allowing read access to that data, just so long as the write protection remains, as it does, in place.
The use case for being able to read the TCC.db database is clearly demonstrated by apps like DetectX Swift: security apps that conform to the principle of least privilege, always a good maxim to follow whenever practical. Asking users to grant elevated privileges just to check which apps are in Accessibility is akin to opening the bank vault in order to do an employee head count. Surely, it would be more secure to be able to determine who, if anyone, is in the vault without having to actually take the risk of unlocking the door.
Did they put a CCTV in there?
Without direct access to TCC.db, we might wonder whether there are any other less obvious ways by which we can determine which apps are able to access Accessibility features. There are three possibilities for keeping an eye on bad actors trying to exploit Accessibility without acquiring elevated privileges ourselves, each of which has some drawbacks.
1. Authorisation dialogs
The first is that we can read the property list that records all invocations of the Accessibility authorisation dialog, without admin rights:
defaults read ~/Library/Preferences/com.apple.universalaccessAuthWarning.plist
That gives us a list of all the apps that macOS has ever thrown the ‘some.app would like permission to control your computer’ dialog alert for, along with an indication of the user’s response (1= they opened sys prefs, 0= they hit Deny).
This list could prove useful for identifying adware installers that try to trick users into allowing them into Accessibility (looking at you, PDFPronto and friends), but it’s main drawback is that the list is historical and doesn’t indicate the current denizens of Accessibility. It doesn’t tell us whether the apps in the list are currently approved or not, only that each app listed once presented the user with the option of opening System Preferences and what the user chose to do about it at that time.
2. Distributed Notifications
The second option is that developers can register their apps to receive notifications when any other application gets added or removed from the list with code similar to this:
DistributedNotificationCenter.default().addObserver(self, selector: #selector(self.accessibilityChanged), name: NSNotification.Name.init("com.apple.accessibility.api"), object: nil)
This ability was in fact added to DetectX Swift in version 1.04.
However, Apple hasn’t made this API particularly useful. Although we don’t need elevated privileges to call it, the NSNotification returned doesn’t contain a userInfo dictionary – the part in Apple’s notification class that provides specific information about a notification event. All that the notification provides is news that some change occurred, but whether that was an addition or a deletion, and which app it refers to, is not revealed:
Even so, notification of the change is at least something we can present to the user. Alas, this is only useful if the app that’s receiving the notification is actually running at the time the change occurs. For an on-demand search tool like DetectX Swift, which is only active when the user launches it, the notification is quite likely to be missed.
It would be nice, at least, if Apple would provide a more useful notification or an API for developers wishing to keep their users safe and informed. The lack of a userInfo dictionary in the notification was apparently reported as a bug to Apple several years back, but I suppose it could always use a dupe.
3. AppleScript – everyone’s favourite ‘Swiss Army Knife’
There is, as it turns out, a third way to reliably get exactly all the info we need about who has access to Accessibility. We can use AppleScript to return a complete list of apps in Accessibility that are enabled. Note that the output of this unprivileged script, shown here in the results pane of Script Debugger, returns a more readable version of the same list of apps we obtained from the privileged sqlite3 query of TCC.db, minus Safari and LaunchBar, which as we previously noted were not enabled:
Fantastic! There’s just one problem. While this AppleScript does not require blanket elevated privileges to run – in short, it doesn’t require an administrator password – it does need to be run by an app that is itself already in the list of Accessibility apps. If you have a script runner like Apple’s Script Editor, or third-party tools like Script Debugger or FastScripts, already approved in Accessibility, then you can run it without authorisation. It’s also worth noting that the script relies on launching and quitting System Preferences, which it attempts to do as quietly as possible.
As for DetectX Swift, I may consider adding something like this to a future version as an option for users who are happy to add DetectX to the list of apps in Accessibility.
Have your own tips about accessing TCC.db? Let us know in the Comments!
Featured pic: Can’t STOP Me by smilejustbcuz
If you’re a regular user of DetectX Swift (DTXS), you’ll be familiar with the Folder Observer function. Although DetectX has always been and will remain an on-demand search tool in principle (i.e., it doesn’t do anything unless you launch it), the Folder Observer adds the capability to alert you and optionally launch DTXS if any items are added or removed from your Launch folders.
This is a useful feature which removes the need, for example, to set Folder Actions or other scripting solutions on the folders which are most likely to be written to in the event of an adware or malware attack. However, as some users (and even myself!) have noticed, the Folder Observer can, at times, be a little irritating.
For example, here at sqwarq I have Little Snitch installed, which puts daemons and agents in both of the local domain Launch folders. The annoyance occurs whenever Little Snitch requires an update. When that happens, the daemon and agents will get written to, and DTXS will dutifully throw me an alert:
Great, except that I don’t really want alerts for software I already trust. I only really want to know about stuff that I don’t know is already in those folders. Of course, I can uncheck the preference for the Folder Observer entirely to stop all alerts, but that then deprives me of the security of being warned of things that I do want to be informed about.
Fortunately, there’s a simple solution that will allow you to tame DTXS and customise the alerts to your personal needs.
1. Go to DetectX Swift > Preferences and click the ‘Observer’ tab.
2. Click the ‘Ignore Keywords’ checkbox (you need to be a registered or licensed user).
3. Click the ‘Edit’ button, and add the launch label of each item you want to ignore in a comma-separated list.
4. Click the ‘OK’ button to finish.
You can get the launch label either by reading it from each of the property lists that you want to ignore, or directly from DetectX Swift’s Profiler. The linked video shows one way you can do that.
While troubleshooting a user’s mac the other day, I happened to come across a curious line in one of the logs:
After a bit of digging, it occurred to me that this and the other flags being sent in the process command were possibly Preferences or Settings in the Chrome.app. Looking at
chrome://settings/privacy revealed, of course, Google’s phishing and malware protection setting, ‘Protect you and your device from dangerous sites’.
Here it is set to ‘On’, which is the default setting:
A quick test proved that setting it to ‘Off’ produced the `—disable-client-side-phishing-detection’ flag in the browser’s process output. Setting it back to ’On’ and relaunching the browser produced no output, confirming my theory.
A quick message to my user also confirmed that he wasn’t aware that phishing protection had been disabled, and to the best of his memory, had not been disabled by himself.
A simple preference setting
That got me to wondering whether that setting could be turned off programmatically by another, possibly malicious, process. To my surprise, it turns out that it’s trivial to do so.
All Chromium browsers have a Preferences file located in their Application Support folder. Usually this is within another folder called ‘Default’, but not always. Chrome and Vivaldi, for example, have it there, but Opera (and Opera Developer) store the Preferences file at the root level of their respective support folders.
The file contains the setting for whether the Phishing protection should be enabled or not. To determine how the preference was encoded in the file, I made a copy of the current Preferences file, toggled the setting, then made another copy. BBEdit’s ‘Find Differences’ function quickly told me the name of the key (if you don’t have BBEdit, you can also use Xcode’s FileMerge to run diffs, though it isn’t as pretty or as full-featured):
Again, there are differences among browsers. As shown above, Opera uses the key “fraud_protection_enabled” which takes a boolean. Chrome and Vivaldi, on the other hand, use a “safebrowsing” key which takes an array of key-value pairs, with the first item of the array being the key “enabled:”, and taking a bool for its value, like this:
With this information, it’s a pretty simple thing for another process running under your username to write to the Preferences file and turn off the built-in protections.
What about Safari?
Safari isn’t vulnerable to quite the same tactic as it doesn’t store its preferences in the same way. However, it’s even easier to defeat Safari’s ‘Warn when visiting a fraudulent website’ setting:
Apple hardened some of Safari’s preferences (like setting the Home page) some time ago to stop adware from making unauthorised changes, but this one is still unprotected in the current public release of macOS High Sierra. A one-liner in Terminal removes the preference:
defaults write com.apple.Safari WarnAboutFraudulentWebsites 0
What can you do?
The ease with which these protections can be surreptitiously turned off in all major browsers is a worry. And let’s face it, who would notice if this setting was quietly turned off? In both Chrome and Safari, the change takes effect immediately and does not even require a restart of the browser.
Fortunately, my shareware app DetectX Swift will warn you if browsing protection is off when you run a search and prompt you to turn it back on. To ensure that all insecure pages have been removed after turning the setting back on, DetectX Swift will continue to show the warning until you restart the browser and execute another search.
The protection covers all the browsers mentioned above. If you’re running some other browser and would like to know if it’s similarly vulnerable, drop a line in the Comments or contact Sqwarq Support and request support for your browser to be added.
Stay safe, folks! 😀
Featured pic: Nature by PichieArt
Xcode 10 beta has got some nice new touches (as well as the return of some old favourites, hello again the code folding ribbon!), but one that might disorientate you at first is the absence of the Snippets, Objects and Media libraries that typically live in the bottom right corner of IB in the Utilities sidebar.
I’ve always found this position and size to be somewhat awkward, so I’m overjoyed to find that Apple have now given the libraries their own floating panel. You can access the libraries either with the keyboard shortcut Command-Shift-L, or by clicking the button that’s now in the top-right of the toolbar, just to the left of the editor buttons.
The new button is context-sensitive, so you’ll notice you can’t access code snippets when in Interface Builder, and you can’t access the Objects library when you’re in the text editor. Makes sense to me!