unified logs

Analysis of Apple Unified Logs [Entry 12] – Quick & Easy Unified Log Collection from iOS Devices for Testing

Collection of Unified Logs on macOS systems is pretty straight forward. You can use the command, and yes – you do have to be root.

sudo log collect 

Collection from iOS device is not as obvious. I think most of us are doing the sysdiagnose/AirDrop method which is tricky. Trying to trigger a sysdiagnose on an iOS device can be frustrating to get the right button hits with the right timing. (Not completely unlike trying to get a device in DFU mode!)

In my recent testing, I noticed the argument--device-udid in ‘log’ man page. This functionality seems to have made an appearance in 10.15. The following also appeared

  • --device-name – The device name, ie: “Elwood’s iPhone”

  • --device – “First device found”. I guess I would consider this the #YOLO option. 🤷🏻‍♀️

This argument has been super handy in recent testing to bypass the frustration of sysdiagnose on iOS devices. I like using the UDID instead of the name, so I will use idevice_id from libimobiledevice to quickly get that.

I have a choice between two devices. One tethered over a lightning cable to my Mac, the other available over the local network. You can use either option to use collect unified logs.

To use this new log argument, iOS devices must be trusted and paired to the Mac, otherwise you’ll get this error.

The following is an example of what I might use for quick iOS testing. While I can dump all the logs, to make things go quicker I use --last to control how much I want to dig through (could also do this with --size). I also don’t use the default output name of system_logs.logarchive, but use the --output option to name them appropriately. This is nice if you are doing multiple tests over and over. Also, I couldn’t even tell you how many random system_logs.logarchives files I have on my system from many different test devices!)

sudo log collect --device-udid <UDID> --last 10m --output iphone_test1.logarchive

You may also see these devices in Console.app if you have it open.

One device we see in Console.app that we didn’t see via idevice_id, is my Apple Watch. You can load up the sysdiagnose profile on the paired iPhone by following these instructions. I AirDrop this to my iPhone to install it.

This profile will be usable for three days to read Apple Watch logs in Console.app before you will have to reload it.

I feel the Apple Watch can (should?) be collected in the same way by using –device-udid, however I get an “log: failed to create archive: Device not configured (6)” error and sometimes a partial and corrupt logarchive. If anyone has any pointers for this, please let me know!

I hope this argument gives us less of an excuse to review our Unified Logs on our iOS devices, we certainly need to know more about what is stored on them and how they are similar or different to our macOS devices.

Analysis of Apple Unified Logs: Quarantine Edition [Entry 11] – AirDropping Some Knowledge

I’ve written about this before in this article but wanted to revisit it for this series. For this scenario I want to test what certain items might look like when they are AirDrop’ed from an unknown source. Many schools have been receiving bomb threats via AirDrop, I want to see if there is a way to discover where they originated from.

In my testing you will see artifacts from two iOS devices:

  • Sender: Elwood’s iPhone

  • Receiver: miPhone11 

Note: This article focuses on iOS. For macOS you will likely have to add --info to these queries to acquire similar information.

Starting with the AirDrop basics – we need to determine the AirDrop ID for each user. One thing I’ve discovered since my last analysis was that the AirDrop ID is not consistent for the life of the device, it changes all the time! The last (current) AirDrop ID can be found in the /private/var/mobile/Library/Preferences/com.apple.sharingd.plist on iOS devices. I’ve even seen where there is no AirDrop ID in this plist due to AirDrop inactivity. The following query can provide the Airdrop IDs that are still available in the unified logs.

log show system_logs.logarchive --predicate 'eventMessage contains "AirDrop ID"'

We may also want to know what Discoverability Mode was being used at the time. A quick query for this is to look for ‘SharingDaemon’ which contains some sharingd metadata information.

log show system_logs.logarchive --predicate 'eventMessage contains "SharingDaemon State"'

These messages contain a few useful items:

  • Device make/model

  • iOS Version

  • Battery Status

  • Discoverability mode (Everyone, Contacts Only, Off)

  • Screen Status

  • Unlock Status

  • Wireless Proximity Status

In our contrived scenario we are assuming the receiver has their discoverability mode set to ‘Everyone’ during the time in question. The current mode can also be seen in the com.apple.sharingd.plist file. One more way of seeing the discoverability mode is by using this query (yes, I accidentally put in two --info arguments, this of course is not required):

log show --info system_logs.logarchive --predicate 'eventMessage contains "Scanning mode"'

On the Sender Device (Elwood’s iPhone):

Sharing Methods 

The first indication of AirDrop usage is how it is being initiated. This process is known as the ‘ShareSheet’. This is the window that is presented to the user to choose how they want to share an item. In this screenshot, I want to share a photo from within the Photos app. We can choose AirDrop, Messages, Mail, Notes, etc. Below that is a set of other activities that can be performed on the chosen photo.

This query can show us what application an item is being shared from. Each shared item may have different sharing options. This blog will show activity while AirDropping a photo, a note, a map, and a Safari link. 

log show system_logs.logarchive --predicate 'category = "ShareSheet" or category = "SharingUI"'

Starting at the top, a good indicator that something is about to be shared is to look for the message ‘Activating com.apple.sharing.sharesheet’. A connection will be made with the specific app that is to be shared from, in this example com.apple.mobileslideshow (Photos).

The items highlighted in red are looking for people to share with. This particular device is a test device with no contacts; therefore none were suggested. 

The items highlighted in purple and blue show the Share and Action activities that the user should see in the ShareSheet view.

In green, the “performing activity” message shows that AirDrop was selected by the user.

In pink, messages that start with “Item:” and have a GUID show that photos need a bit more preparation (file conversion, thumbnail creation, etc.). This was not seen in shared notes, maps, and Safari links. This specific activity can be filtered by using the GUID as shown below. The items highlighted in dark green provide temporary file paths used for the preparation but most importantly a filename that should be consistent with the item filename in the Photos.sqlite database (IMG_6782.JPG).

log show system_logs.logarchive --predicate 'eventMessage contains "74745469-9184-442C-B49D-5BE37CDD8CAA"'

More examples sharing methods of an AirDropped Note, Map, and a Safari Link are shown below. Notice the differences in the activities for each application. 

Note

Map

Safari Link

AirDropping an Item

Just because we see something was attempted to be shared, does not necessarily mean it was actually sent and received. The first part of this process is finding someone to AirDrop something to. I will be using the following query to go through some of these entries. 

log show system_logs.logarchive --predicate 'category = "AirDrop"'

In the screenshot above I’ve changed the default style to compact [with --style] to fit more in the screenshot. This shows the iPhone attempting to discover known and unknown contacts via Bonjour and AWDL. Highlighted are the entries that find my MacBook Air (Airdrop ID: eb4f5a53391b). Note the AWDL IPv6 addresses shown in yellow. These do appear get cached on the receiving end (look for messages that contain “com.apple.p2p: Caching peer:”). It appears AWDL IPv6/MAC addresses get rotated fairly frequently. These is another way of pairing two each device together (along with AirDrop IDs) but these are not kept forever and you need both devices to do this analysis.

Now that we have AirDrop contacts, lets send a photo! I sent a photo from Elwood’s iPhone to miPhone11 (IMG_6782.JPG) via Photos.

The message that start with “startSending” (in yellow) is what is being AirDrop’ed. It shows the item or file that it is sending along with the Receiver ID and Session ID. The Receiver ID is the AirDrop ID for the device that this item is being sent to, while the Session ID keeps track of this AirDrop session.

In green, the AirDrop transaction is started, however in dark green it shows that a connection cannot be made. During my testing, my miPhone11’s AirDrop ID got caught in an odd cached state with the wrong ID (3603f73a17de). The first time I attempted to AirDrop this photo it failed. It eventually discovered the correct ID (ecec57b722d8). Elwood’s iPhone showed a ‘Waiting…’ message and the transaction would not complete.

The second time around it actually sent. Note the changed AirDrop ID for miPhone11 is now 04f30cbdcb55. These IDs change all the time. It also recognizes the device can handle a live photo in an HEIC file format, so it sends that instead of the JPG.

The ShareSheet information for the Live Photo is below. I recommend matching up the GUIDs to find this information. Filtering for 6C85AC86-BEF2-42BC-9862-4982211791DF (from the screenshot above) would allow me to run the query below to find the rest of the actions associated with this asset.

log show system_logs.logarchive --predicate 'eventMessage contains "A79A3C4F-AF63-486E-A7FC-4173753B12E2"'

A few more AirDrop examples, a note, a map, and a Safari link.

Note

These entries show a note with the title ‘This is a threatening note!’ was shared but no contents of the note itself.

Map

Sharing a Map item, provides title but no exact address in this example.

Safari Link

Sending a Safari link shows the domain but no specific details on the URL. 

The same Safari link as a PDF file:

Sending the same link but as a PDF shows no domain at all.

These items lose context when only the unified logs are looked at. You may have to correlate these actions with other application databases and artifacts (Photos, Notes, Maps, Safari History, etc.) to provide this context.

On the Receiving Device (miPhone11):

We will be using a generic AirDrop query to find all entries associated.

log show system_logs.logarchive --info --predicate 'category = "AirDrop"'

A user receiving files can choose to accept or decline. These responses are documented in the unified logs.

For an incoming transfer an AirDrop connection is made with an identifier (0x101495960). After this entry there are quite a few lines detailing what type of file it is and where it is coming from. To know if the user has Accepted or Declined the transfer we need to focus on the ‘userResponse’ sections. The entry shown in green is the popup alert that is presented to the user to do this action.

Once the user has selected ‘Accept’, the transfer continues and is opened up in the default application for the file. This example shows the photo being imported and opened in Photos (com.apple.mobileslideshow). Once complete, the AirDrop connection is terminated. This photo could be found by looking for the “16C753E1-309A-46FD-A742-998D7A31047E” ZUUID in the ZGENERICASSET table of the Photos.sqlite database and looking for the associated file name.

If the user declines the AirDrop transfer the same message would show Declined or Cancelled and the AirDrop connection is terminated. 

How about an all-in-one query to tell me what transfers were initiated, from whom, where they Accepted or Declined, and opening information.

log show system_logs.logarchive --predicate 'category = "AirDrop" and (eventMessage contains "New incoming transfer" or eventMessage contains "Opening URLs:" or eventMessage contains "alertLog: idx:")' --style compact

Each of the gray highlighted sections is an incoming transfer from Elwood’s iPhone. Some transfers have an ‘Opening URLs’ entry that provides more context to what was sent, especially when it comes to Map and Safari links. It should be pointed out that just because you see a hostname like Elwood’s iPhone to be careful with attributing it to Elwood. Device hostnames are incredibly easy to change to let’s say…’Jake’s Google Pixel! 

I spent ages trying to come up with a smoking gun on a ‘victim’ device to attribute an AirDrop action to a specific sender device. There really does not appear to be a static identifier to be able to identify a specific address. AirDrop ID, AWDL IPv6/MAC addresses are the only way to pair these actions between devices but you need both devices to be able to do this type of correlation. This, of course, can be tricky in most investigations. Even if you do have access to the devices, the data gets flushed fairly quickly – you may only have a few days to acquire these logs.

Analysis of Apple Unified Logs: Quarantine Edition [Entry 10] – You down with TCC? Yea, you know me! Tracking App Permissions and the TCC APOLLO Module

TCC Modifications in the Unified Logs

TCC or Transparency, Consent, and Control keeps track of various application permissions. A user can make changes to an application’s permissions in the respective Privacy settings on macOS and iOS. 

When changing these permissions on macOS entries do get written into the unified logs. While there are many related TCC entries, I want to focus on just permission changes. These can be extracted using a query where I’m looking for the text ‘Update Access Record:’ in the log message.

log show --info --predicate 'eventMessage contains[c] "Update Access Record:"'

To create these entries, I went into my own settings and toggled some on (Allowed) and some off (Denied). 

  • Camera access was denied to QuickTime Player (com.apple.QuicktimePlayerX)

  • Camera access was allowed for Zoom (us.zoom.xos)

  • Microphone access was denied to PowerPoint (com.microsoft.Powerpoint)

  • Microphone access was denied for SnagIt (com.TechSmith.Snagit2020)

  • Accessibility access was denied for SnagIt (com.TechSmith.Snagit2020)

  • Accessibility access was allowed for iStat Menus (com.bjango.istatmenus)

  • Accessibility access was allowed for SnagIt (com.TechSmith.Snagit2020)

Unfortunately, these entries are removed from the logs after in a short time period. I’ve seen mine being removed anywhere from about 1 hour to 1h40m. 😧

iOS TCC Entries

On iOS many of the same privacy settings apply as well. In this example I toggled the WhatsApp permission for microphone access to on.

I’ve connected to my phone using the Console.app application on macOS. This particular phone is named miPhoneX (iPhone X running iOS 13.1). This is the easiest way to test certain scenarios on iOS devices, sadly there doesn’t appear to be a ‘log’ executable for jailbroken devices. Unified logs can also be extracted using sysdiagnose or copying them off a jailbroken device and manually creating a logarchive.

Toggling permissions back and forth I can see the same entries I might see on macOS, however notice the ‘Volatile’ column for these entries are set to a ‘1’ – meaning they are not being written to disk. These entries are removed after only a few minutes (less than 5 minutes in my experience). What you see in Console may not necessarily get written to disk. Some entries (like those for macOS) are written to disk but not necessarily kept for the entirety of unified logs themselves. Nothing lives forever!

macOS & iOS TCC APOLLO Module 

There may be a time when the macOS logs rollover or you are looking at an iOS device where these entries are volatile. Fortunately, the TCC.db database keeps track of the last modified time for these entries. I’ve created an APOLLO module for macOS and iOS to extract this information. The example below is from my macOS user TCC.db database using the SQLite query from the APOLLO module.

This database can be found on macOS and iOS devices in the following paths:

macOS:

  • User: ~/Library/Application Support/com.apple.TCC/TCC.db

  • System: /Library/Application Support/com.apple.TCC/TCC.db

iOS (Backup acquisitions may differ slightly): 

  • /private/var/mobile/Library/TCC.db

Analysis of Apple Unified Logs: Quarantine Edition [Entry 9] – We all know you're binging Netflix! Now Playing on your Apple Devices!

We’ve been trapped inside our homes for months. We’ve reached the end of Netflix, listened to everything on Apple Music, watched old vacation videos trying to remember what travel was like, and mindlessly browsed YouTube videos. All these actions have been recorded in your unified logs!

I came across this one while researching another topic and thought it might be useful and a quick write-up. Turns out it wasn’t as quick as I had hoped – so many different scenarios to test! I’d still like to dig into this one a bit more as it can be quirky as noted in the last section. While sometimes odd, I think this information can provide insight into what media a user is viewing on their systems - not just macOS, but iOS as well. 

The query below will show information related to media that is “Now Playing”, not just on the computer that the logs came from, but also potentially other AirPlay connected devices. There will be many entries but we will only focus some in this article.

log show --predicate 'category = "MediaRemote"'

Movie time in the Photos.app

Gather the family and start reminiscing over vacation videos. You might bring up Photos.app and search for various videos that you were going to show all your friends and family (and never actually did, but you just HAD to get that video.) 

In the screenshot below, the ‘MediaRemote’ is what we are filtering on in the query above (highlighted in yellow). 

Various pieces of data get recorded in the unified logs. In many entries you should see the bundle id or application name being used – in this example Photos or com.apple.photos. A good keyword to look for is “client-“ before the bundle id for the app.

You can also see two sections that contain media metadata that includes:

  • Media Duration (in seconds)

  • Elapsed Time – We can use this to determine how long it was viewed/listened to.

  • Item Identifier (GUID) – This GUID changes over the period of viewing so not a great filter for a specific file. It will change if media is stopped, paused, etc.

  • File Path & Name

This video is 10 seconds long, using the elapsedTime entry we can see that it was played all the way though.

The file path is in the user’s Photos Library package directory which is not surprising. This filename however, is not the original filename of this video. We can use ‘xattr -p’ to print the extended attribute that contains this data (com.apple.assetsd.originalFilename). Using the original file name IMG_3586.MOV we might be able to do a search across the system to find other artifacts of its use and more metadata in the Photos.sqlite database including a running count of how many times it was played.

MOV Files in QuickTime

Maybe you don’t use Photos.app, instead you downloaded the movie to your macOS system and viewed it using QuickTime player (com.apple.QuickTimePlayerX). Many of the same metadata pieces are still there but the filename might look strange to you. This is a good example of a “File Reference URL”. This is the same video I used as the example above. I exported it out of Photos using the original filename, IMG_3586.MOV and saved in the Downloads directory.

In the screenshot above the elapsed time is 00:00:00, and duration is 00:00:10 (10 seconds). Below, the elapsed time is 00:00:05 (5 seconds, actually closer to 6 if we round up.). I started the video, watched ~5 seconds and played out the rest of the video (these additional entries are not shown.) The playback rate entry appears to be a 1 while playing and a 0 while stopped/paused. A GIF of this action was recorded below. Featuring a playful elephant at the Taronga Zoo in Sydney.

Getting back to that “File Reference URL”, you probably want to find the original file as part of an investigation. We can use the inode section of the URL to find it. In this example I renamed IMG_3586.MOV to elephants.mov. Most forensic tools should be able to query for a file system inode number. Inode numbers do not change when a file gets renamed.

Finding a sense of calm with Music.app

I queued up a new album by one of my favorite classical musicians, Ludovico Einaudi. An Italian, who created this album while in quarantine at his home in Italy. The album includes 12 songs, and one video (not shown in the screenshot.)

We can see the queue count for Music (com.apple.Music). While I listen to this album, it will tick down, one-by-one.

Finding the End of the Internet

To get a few laughs, I used Safari browser to watch clips of Archer on YouTube. Safari is not listed as the application, but com.apple.WebKit.WebContent is – this is a signature of Safari WebKit being used. Surrounding entries (not shown) will show hints that Safari.app is being used as this time.

In Chrome, I went to watch videos on the BBC and found this excellent video of a dog who helps rescue Koalas in Australia (running theme? 🤔). We can see the Google Chrome (com.google.Chrome) app is being used, but it may not necessarily state the website. You may have to determine this using other user activity artifacts (browsing history!).

What about AirPlay?

The media examples above were all viewed on a local macOS system, what would it look like if I used my extensive Apple ecosystem of devices? Might as well use these devices for “research”, right?

While doing this research, I was watching one of my favorite older television shows, Alias using Amazon Prime Video (com.amazon.aiv.AIVApp) on one of my Apple TVs. Every episode that it would run though would show entries on my Mac. My Mac had nothing to do with my binge watching, but the entries were recorded anyway…cool! I should note that if the system is not being used (laptop shut), these entries do not appear in my logs. The Apple TV is named ‘Living Room’.

Of course, I also have a HomePod and stream music and news to it all day long. In this example I’m streaming from my macOS laptop to my HomePod named StationX. I have found that the elapsed time doesn’t seem to update as the examples above did.

Quirky? Yes.

While doing this research and testing various applications, I came across entries while I was most definitely sleeping. Seems my laptop wanted me to listen to the radio very, very early in the morning for about 15 seconds. 🤷🏻‍♀️

Do entries like this make all the examples in the article inaccurate? Absolutely not. Computers act in weird ways. This is a great example of why correlating this information to user activity through other means (ie: sleep status, device unlocks, user activity in knowledge, etc.) is required in investigations.

I hope this article gets you thinking about all the other apps that you watch media from. Again, this is not just on macOS but also on iOS (and likely tvOS as well). All those applications, native and 3rd party, are just waiting to catch you binge watching your favorite show, finding the end of YouTube, and rocking out to your favorite 90’s boyband jams!

Analysis of Apple Unified Logs: Quarantine Edition [Entry 8] – Man! What a process!?

A quick trick to get more info when you are testing different Unified log examples is to use Terminal’s man page lookup feature. This is useful to provide more context to processes that you may not be familiar with. Perhaps you have something interesting in the eventMessage field and want to know more about what processes use that information.

In this example, I “right-clicked” some of the process names to get more information about them; sharingd, bluetoothd, and powerd. However, identifityservicesd does not have a man page so I’ll have to research that one another way!