Analysis of Apple Unified Logs: Quarantine Edition [Entry 1] – Converting Log Archive Files on 10.15 (Catalina)

Please review this post first as it contains an update to this post. Keeping the contents of this blog intact for reference purposes only.


Apple introduce Unified Logging many years ago in 10.12 and has constantly been changing it since its introduction. My main problem is usually using the ‘log’ utility. It has changed over time and those changes are not documented nor is the current documentation adequate in many cases.

My most recent adventure using ‘log’ came when I was running through my course image to create a logarchive bundle from a dead system image. This particular system was running 10.13.1 and will have to be read from whatever macOS the student is running at the time. Silly me for thinking that ‘log’ would always “just work”™️. 

When students upgraded to 10.14.x, they could still create the log archive via the manual process of doing a recursive copy of the /private/var/db/diagnostics and /private/var/db/uuidtext directories into a *.logarchive directory bundle. Works great! Even works (worked?) on iOS devices! On 10.14.x systems we have “force” it into the proper format but it was readable by ‘log’ and the timestamps appeared correct.

When 10.15 came out, this changed. Attempting to create and read the same data produces a corruption error. There is no option to “force” it.

I have been racking my brain and researching this on and off since Catalina was introduced. How the heck can I make this older logarchive readable using a newer versions of macOS?

Comparing the older and newer logarchive formats, they are nearly the same except for a few items. One difference I focused on was the key OSArchiveVersion in the Info.plist. On 10.14 and 10.15 they are on version 4, while on 10.13 they were on version 3. (Note: Doing a recursive copy from a dead image does not create this Info.plist file in the root of the logarchive bundle.)

In my first test, I simply added an Info.plist file to the root of the logarchive bundle with one key, OSArchiveVersion. For the value I tried 4 – why not just give it what it wants. (This testing was done on 10.15.3). 

Great, it parses! However the timestamps are not quite right. I’m lucky to have a dataset that I’m familiar with and have a course labs with specific log entries and their timestamps to validate the conversion. This particular entry I’ve blogged about before – this entry should have the timestamp 2018-02-26 01:49:08.719840+0000. You can see it is only off by a smidge, what gives? These things bother me, so I decided to dive deeper.

Something else is part of this conversion. (I knew it would have been too easy to just change a plist value!)

Next, I changed the value of OSArchiveVersion to a 3. In theory, I hoped to upgrade it to version 4 but still got the same wrong timestamp. I was also not even offered the “force” option. (I really should have known it would have been too easy to just change a plist value!)

In a moment of ‘why not, let me just try this for fun’, I changed the value to 2. …and it actually WORKED! It freaking worked! I had to force it and the timestamps matched up with my original values.

I would love to know why this worked. It makes no logical sense to me.

What happens if I just go straight to version 2 for OSArchiveVersion? It also worked!

A quick command to get this done:

/usr/libexec/PlistBuddy -c "Add :OSArchiveVersion integer 2" galaga.logarchive/Info.plist

What changes in this “forced” conversion? 

I created a new copy of the logarchive bundle and put the Info.plist with OSArchiveVersion = 2. Using one of my favorite file system monitoring tools, fsmon [https://github.com/nowsecure/fsmon]. I was able to monitor what the --force flag changed in the logarchive bundle.

It deletes the timesync directory (and the *.timesync file within) then creates it again with a different timesync file. Also as expected the Info.plist changes from 2 to 4.

What the heck are these timesync files? Not entirely sure, they are binary files that obviously has some sort of time syncing purpose which is why the timestamps now match up. Perhaps I will dig into these another time.

Afterthoughts 

I’m not sure why 10.15 refuses to convert log archives as 10.14 did. Perhaps it is a bug, maybe it is intentional but it sure does make doing forensics difficult. I’m sure this will cause problems with newer versions of macOS as well as other platforms. I’ve heard the same problem exists with iOS, which again will likely be another blog entry when I get to testing iOS specifically.

It does however bring up a good lesson…do not implicitly trust timestamps. I’ll state this over and over until I can get people to test these things. I had it easy with this one because I had known test data – but that doesn’t work so well with random case data.

Below is the mapping of macOS version to Unified Logs Archiver versions (found in the Info.plist files while doing a ‘log collect’ command on a live system.) There are many empty spots – I have no idea if it will help or not but I tried to document it here. If you can help fill it in, I would be grateful please contact me. (Seems most folks update to the latest!)

Log Archive Mapping Table