Category Archives: Developer

how to love (and read) crash reports




Crash Reports are essential, if often opaque, guides to problems in your app that every developer has to deal with from time to time.

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:

cd ~/Desktop/CrashWork

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:

7. Now, going to my source file, I see exactly where the app crashed (lo! and behold, what do you know? An unwrapped optional, of course!):






Enjoy! 🙂



Featured pic: crash by febra-febra



accessing TCC.db without privileges



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.

Enjoy! 🙂



Have your own tips about accessing TCC.db? Let us know in the Comments!
Featured pic: Can’t STOP Me by smilejustbcuz


how to protect your app from hijacking


I was lucky enough to get a great tip from MalwareBytes’ Thomas Reed this week on the possibilities of code hijacking.

Thomas was kind enough to share details of a talk he gave at MacTech last year, in which he demonstrated how some 3rd party apps are susceptible to having their binaries replaced by a fake binary even when the original application is properly code signed with a valid developer’s signature.

The vulnerability lies not so much in the code signing itself, but in the mechanism for when and why it gets checked. In short, code signing is checked when an app is first launched, but after that, except in a few special situations, macOS’s security mechanisms pretty much ignore it. That means once an app has passed GateKeeper, it’s a ripe target for attackers to come in and replace the binary with one of their own.

In order to ensure the app on disk is still in fact the app that was downloaded and first launched, developers need to implement a check on each launch.

If you’re using Swift, some example code for doing that (pictured above) is available from my pastebin here. I’ve also got a version for Objective-C, adapted from here.

The key to it is what you specify in the entitlement constant. In this example, I’ve specified three things: that the code is signed by Apple, that is has the app’s bundle identifier and that it has the developer’s Team ID. Don’t forget to change my dummy values for your real ones in the code! You can get all these details for your app by running this in Terminal:

codesign --display -r- <path to your app>

With that information, the function verifies that the application in memory meets the requirements specified in the entitlement.

Call the function at some point after launch (e.g, when your main nib has loaded) and handle the boolean result appropriately. For example, if the function returns false, you might throw an alert like this one from DetectX Swift telling the user that the app is damaged and needs to be re-downloaded, and then terminate the app when they hit “OK”:

Let’s keep our code (and users!) safe everybody. 🙂


how to quickly toggle Swift Compiler warnings





I thought I’d share this little AppleScript for anyone working with Xcode 8.3.3 and using Swift.

One of the things I find intrusive are the constant Swift Compiler warnings while I’m actually in the middle of writing a block of code (e.g, ‘…value was never used consider replacing…’). Well, yeah, it’s not been used *yet* …grrr!

However, turning off compiler warnings isn’t something I want to do either. It’s too easy to go into the build settings, turn them off, do a bit of coding, take a break, do a bit more coding…oh, three thousand lines later and I suddenly realize why Xcode hasn’t been correcting my mistakes all afternoon!

This script allows you to quickly and easily toggle the warnings from a hotkey, and just gives you a gentle reminder as to what you’ve done. Of course that won’t stop you forgetting, but assigning a hotkey for this script makes it painless to just turn warnings off and back on again as soon as you’ve got past whatever bit of code the compiler was complaining about.


Xcode unfortunately doesn’t have its own scripts menu, so in order to assign the script a hotkey, you’ll need to either make it into a Service with Automator or use a script runner like Red Sweater’s FastScripts.

#start
on sendNotification(aVal)

display notification "Suppress Warnings was set to " & aVal with title "Swift Compiler - Warnings Policies"

end sendNotification

tell application id "com.apple.dt.Xcode"
tell its front document
tell its front project
tell its front target
tell its build configuration "Debug"
set b to build setting "SWIFT_SUPPRESS_WARNINGS"
if b's value is "NO" then
set b's value to "YES"
else
set b's value to "NO"
end if
my sendNotification(b's value)
end tell
end tell
end tell
end tell
end tell
#EOF

If copying the code above doesn’t build, get the raw source from my pastebin here. Here’s how it looks in Script Debugger 6:

Enjoy! 🙂


how to create a bootable macOS installer

If you are preparing to install macOS on multiple computers, one of the things that can make your life simpler (and the waiting shorter) is a bootable USB installer.

The idea of the installer is that you only need to download the macOS Installer.app from the App Store once. Usually, when you run the installer after downloading it, it’ll delete itself and you have to go through the whole download process again on each machine or disk that you want to install macOS onto. By making a bootable USB drive, you simply plug the drive in to your mac, launch the installer app and tell it where to install the OS. You can repeat this as many times as you like as the installer will remain safe on your USB.

There are various ways to make a bootable USB installer, but they all involve the same process:

1. Download the macOS Installer from the App Store.
2. Run the createinstallmedia command from the Terminal, an AppleScript or a helper app.
3. Reboot your mac, choosing the newly created USB as the startup disk.
4. Run the installer.app from the USB.

Step 2 is where the fun is. The createinstallmedia command can be tricky to get right, particularly if you’re not familiar with working on the command line. For those of you that are, follow Apple’s instructions here.

For a little more convenience, I wrapped all that inside an AppleScript which will first ask you for the location of the installer, then ask you to choose the USB target.

For maximum convenience, I also wrote a free little Swift app I’ve dubbed ‘Boot Buddy‘ (cos “Create bootable macOS Installer Drive.app” just didn’t quite have the right ring to it..!) that will present the whole thing in a neat little user interface. Three clicks, more or less, and you’re done.

Boot Buddy doesn’t require an admin password to install, but you do need to provide an admin password to actually create the bootable installer as the createinstallmedia process has to be run as root. Boot Buddy doesn’t see or use this in any way whatsoever other than to start the createinstallmedia process or to cancel it (if you choose to do so); authorisation is handed off to macOS to take care of.

Boot Buddy requires macOS 10.11 or higher and can create bootable USBs from Mavericks, Yosemite, El Capitan, Sierra and High Sierra installer apps.











Share and enjoy! 🙂


Script Debugger 6: the complete review

SD Shot 2



It feels like cheating. When you’ve spent pretty much your entire AppleScripting life behind the wheel of Apple’s austere Script Editor application, taking Script Debugger 6 out for a 20-day spin feels like someone’s let you in on a secret you’re not supposed to know. Hurdles you’ve taught yourself to clear – through considerable effort, frustration and no small amount of bloody-minded tenacity – are removed before you get to them; obstacles you’ve habitually steered around or avoided have disappeared, and dark holes of AppleScript mystery appear, in the light shone on them by SD6, to be not the menacing entities you once feared but new friends that offer ways to do things faster and more effectively. The secret that Script Debugger seems to lay bare is that AppleScripting doesn’t have to be as painful as we’ve been conditioned to believe. And that does feel like a cheat. Read the full review…


learning the Terminal: Part Three

Screen Shot 2016-07-02 at 15.24.53
It’s been a while since we last posted about Terminal tips and tricks, but a question popped up today about how to discover what tools are available on the command line.

Most of the tools you use in Terminal are located in /usr/bin, and we can use a nifty little tool from there to find out about all its friends. The whatis tool gives you a one-liner description of what a tool does. If it looks interesting, you can find out more about the tool by typing man and the tool’s name on the command line to see its help manual.

On my current machine, there’s over 1000 tools in /usr/bin, and life is just too short to go through them all doing whatis on each and every one, so we’ll combine a bit of command line power with some AppleScript magic, and produce a nice, easy-to-scroll output of all the summaries like the one in the screenshot above.

Copy the script below (or from my pastebin here) and paste it into the Script Editor (/Applications/Utilities/Script Editor.app). Click the ▶︎ button to run it.

This script took about 1m 30 seconds to run on my machine, but you only need to run it once then save the output. Browse or search through it at your own convenience. 🙂

The script will choose TextWrangler for display if you have it installed; if not, it’ll default to TextEdit. The display is much nicer in TextWrangler, but if you’re stuck with TextEdit, turning off ‘Check Spelling’ in TextEdit will aid readability.

# start 

(* 

This script produces a summary of all the CLI tools 

in /usr/bin and displays it in a text document 

*)

set noDocsList to {}

on extractDescription(aText)

repeat with i from 1 to count of items in aText

set this_item to item i of aText

if this_item contains "NNAAMMEE" then

set r to item (i + 1) of aText

try

set o to offset of "" in r

set short_r to text (o + 1) thru -1 of r

set r to short_r

end try

return r

end if

end repeat

end extractDescription

set theDescriptions to return & return & "**********************************" & return & "SUMMARY OF CLI TOOLS (Version 2)" & return & "**********************************" & return & return & return

tell application "System Events"

set theItems to name of every file of folder "bin" of folder "usr" of startup disk

end tell

repeat with i from 1 to count of theItems

set this_item to item i of theItems

set n_item to length of this_item

try

set what_is to do shell script "whatis " & this_item

if text 1 thru n_item of what_is is this_item and what_is does not contain "nothing appropriate" then

set theDescriptions to theDescriptions & return & what_is & return

else

try

set getMan to paragraphs of (do shell script "man " & this_item)

set desc to extractDescription(getMan)

set what_is to this_item & tab & tab & tab & tab & desc

set theDescriptions to theDescriptions & return & what_is & return

on error

set end of my noDocsList to this_item & return

end try

end if

end try

end repeat

set theApp to "TextEdit"

tell application "Finder"

if exists POSIX file "/Applications/TextWrangler.app" then

set theApp to "TextWrangler"

end if

end tell

set theDescriptions to theDescriptions & return & return & return & "The following tools do not have any documentation: " & return & return & noDocsList

tell application theApp

activate

make new document

set front document's text to my theDescriptions

end tell

# EOF 



Related Posts
learning the Terminal – Part One
learning the Terminal – Part Two
learning the Terminal – Part Four

WWDC: get it for free (OSXClock)

Screen Shot 2016-06-13 at 20.31.55

Apple’s WWDC 2016 conference is about to start. Is it the end of OSX? Rumours are widespread that the venerable old operating system is about to change its name to macOS.

Right or wrong, commiserate or celebrate, we thought we’d mark the occasion by giving away free copies of the full-paid version of our OSXClock.app.

The offer is already up and live and will continue to be available until WWDC 2016 closes on the 17th.

We’ve also just released an update to OSXClock yesterday adding world time zones, so there’s no better time to take advantage of this giveaway.

Enjoy! 🙂

how to learn more about error codes

OSStatus.com


Scripters and coders are forever battling errors, and access to information on Apple’s error codes is always a bit of a hunt and dig around header files or documentation. Now thanks to Seth Willits from Araelium group, there’s a handy free search tool to spare us the effort.

I’ve already got osstatus.com bookmarked. Thanks Seth! 🙂


how to get Eclipse and Java to play on Yosemite

eclipse_by_a4size_ska-d2dvgyj

If you’re trying to launch the Eclipse IDE with Apple’s old 1.6 JDK installed and find that you’re having trouble updating your Java installation, try the following procedure.

1. Remove Apple’s JRE
First up, let’s get rid of the end user plug in. In Terminal, do

sudo rm -rf /Library/Internet\ Plug-Ins/JavaAppletPlugin.plugin

2. Remove Apple’s JDK
Next, we need to uninstall the Java Development Kit. Do not mess about in the System’s Frameworks/JavaVM.framework folders. You’ll need those. Rather, in Terminal do

sudo rm -rf /System/Library/Java/JavaVirtualMachines/1.6.0.jdk

If you’ve got later versions of the JDK (like 1.7), change the file name in the above command appropriately.

3. Install Oracle’s JDK for Mac
Next go to the Oracle Java page and look for the latest JDK. It’s important that you get the JDK for developers and NOT the JRE for end-users if you want to use Eclipse.

http://www.oracle.com/technetwork/java/javase/downloads/index.html

Download and run the installer. You should now be able to launch Eclipse without problems. 🙂





Picture: Eclipse by A4size-ska

%d bloggers like this: