Friday, 30 September 2022

iOS 16 - Breaking Down the Biomes Part 5 -- "Hey Siri, find me some more data..."

 In this post within the "Breaking Down the Biomes" series we're going to take a dive into Siri driven artifacts. Previously we could track some Siri data within KnowledgeC.db but it's now a mixed bag as some of those points have moved out to the biome data. Siri has made it difficult in the past to figure out how it was used as the conversion from the voice data to text data is performed on Apple's end not on device. 

With iOS 16 and the movement of a lot of the Siri data, being able to timeline the events are becoming even more important due to Siri's ability to interact with more functions within our devices. Some of the past event such as /siri/ui have been moved out of KnowledgeC.db but it can still be used to track some usage of Siri. In the following screenshot, you can see that there are still events which track back to the voice dictation service being used as well as some SiriIntents being triggered. We'll continue to explore some of these SiriIntents to get a deeper look at what was actually performed by the built-in voice assistant. 



Siri.UI
Since the UI triggers are missing from KnowledgeC, we have to turn over to our favorite annoying data store, the biomes! There are several new biomes tied to Siri processes within iOS 16. While this post will cover some of them, there are still more that I noticed within my testing had not yet been populated so more testing will be done over time to see what gets dropped into these. 

Starting with the Siri.UI functions, we can use these biomes to track when the UI (user interface) for Siri gets launched. This can help us track when the UI starts and stops to figure out what actions were taken directly following. As a reminder, Apple states that Siri data is processed off your device so what you say to Siri is not going to be left behind. For more information on Siri's processing of data, go to Apple's legal site here

To start tracking the UI being triggered, the biome _DK.Event.SiriUI (found within /private/var/mobile/Library/Biome/streams/restricted) can help us see the events that used to be tracked in KnowledgeC.db. There are two different types of protobufs, one for the UI beginning, and one for the UI ending. 


Looking at the protobufs which reflect "com.apple.siri.ui.begin" the date and time tracks when the UI was triggered for the beginning event. There are two UUIDs listed but the second one is more important (the one in the screenshot ending in 9FC). More on this one as we track through this thread. 


The other record reflected in the SEGB file is the type which will reflect "com.apple.siri.ui.end." There are two UUIDs in this record. One for this individual record, and a second UUID which if you note is the same as the previous image. It will also track information about WHY the UI ended. In this case, it says "User" which isn't exactly super helpful, but the UUID can continue to help us. 

There is another biome which reflects information relating to the UI in SiriUI found within /private/var/mobile/Library/Biome/streams/public/). The information within the protobufs found inside this SEGB biome file don't tell a lot, unless you're looking at the previous information too. You'll have two events for each Siri activation inside the SEGB, one for the beginning and one for the end. 


These date and times are only tracking when these records are written, but the UUID matches the original events from _DKEvent.SiriUI. 


The second entry in the pair again shows the UUID, but also has a string value which reflects how the UI was exited. In this case, you can see that the exit reason was "HardwareButton" from the user pressing the button to end. There are other reasons tracked in these strings such as "OutgoingPhoneCall"  and "AppLaunch" or "Timeout." Seeing as some of these dismissal reasons mention applications being used, or calls being made, can we track what interaction directly followed the Siri activation? 


SiriExecution

Post the UI being enabled, we'll shift our attention to what was executed. The biome for SiriExecution (found within /private/var/mobile/Library/streams/public/) will contain a SEGB file with protobufs for execution events in Siri. It should be noted that multiple protobuf records within this file are tied together by a UUID value similar to the UI usage across multiple biomes, however, these UDID records are not tied to the original UI biomes [confused yet? It gets worse]. 


There are two UUIDs in these protobufs. The first UUID denotes the function such as calls or SMS while the second UUID is tied to the specific execution. The timestamps reflected in each protobuf are signifying when the records are written, not necessarily when the execution occurred.  

Several different "intent types" are found that can help show what the execution was tied to such as: 
  • SendMessageIntent
  • LaunchAppIntent
  • AppLaunchIntentExtension.LaunchAppIntent
  • StartCallIntent

Some intents will also denote what application the intent was tied to such as SendMessageIntent --> com.apple.mobileSMS. Not all will though, some will simply list "none." So how can we use this? Not all executions of the Siri environment have a direct Intent that will leave full traces behind. Some of the intents can be used to help us see what applications may have been launched, some will help us see that some system functions may have been launched. 

SiriIntents
While the UI trigger from KnowledgeC.db is gone, SiriIntents are now present in the device. From several scans of images, I was not able to find these prior to iOS 16 images. There are several biomes that relate to SiriIntents but have not been fully populated yet in this version of iOS. Within the KnowledgeC.db the previously mentioned /siri/intentEvent triggers will exist within the ZOBJECT.ZSTREAMNAME column. Taking a look at the previously posted image from KnowledgeC: 


We can see that these "intentEvent" triggers have a UUID value within the ZVALUESTRING column. These same UUIDs can be found within the SiriExecution biome protobuf records tying the two together. These records from the ZOBJECT table is tied to the ZSTRUCTUREDMETADATA data. To match the /siri/intentEvent records to their proper ZSTRUCTUREDMETADATA records to recover more information about the intent, the following SQLite query can be run: 

SELECT ZOBJECT.ZSTARTDATE AS "START_TIME", 
      ZOBJECT.ZVALUESTRING AS "VALUE", 
ZSTRUCTUREDMETADATA.Z_DKSIRIINTENTEVENTMETADATAKEY__EVENTTYPE AS "TYPE", 
     ZSTRUCTUREDMETADATA.Z_DKSIRIINTENTEVENTMETADATAKEY__EVENTDATA AS "DATA",
      ZOBJECT.ZCREATIONDATE AS "WRITTEN_DATE",
      ZOBJECT.ZUUID AS "UUID", 
      ZOBJECT.Z_PK AS "ZOBJECT_ID"
   FROM
      ZOBJECT 
      LEFT JOIN
         ZSTRUCTUREDMETADATA 
         ON ZOBJECT.ZSTRUCTUREDMETADATA = ZSTRUCTUREDMETADATA.Z_PK 
   WHERE
      ZSTREAMNAME =  "/siri/intentEvent"; 

This will return the data similar to this: 

The data within Value tracks back to the same intent type as the SiriUI biomes. The BLOB records are... interesting. Buckle up, grab a drink, and let's explore them. 

First, examining the BLOB shows that it's a binary Plist file. Inside this plist file there is a record stored with JSON formatting. 

Pulling out this JSON record reveals a chunk of base64 encoded data under the intentData value. The intentType value should match what you saw within the database and will also match the intent found within the SiriExecution biome. 

Decoding this base64 reveals... another plist... (are you tired and annoyed yet?)


Pulling that plist value out and looking at it reveals some information about the intent, but some data stored in the "backingStore" value. These bytes are actually a protobuf. 


Pulling out the protobuf and looking at it shows us information that will differ depending on the intent. In the case of a SendMessage intent, it will show to whom Siri was directing the message. 


In the case of one of the recovered CallIntents you can see the information within the protobuf at the end of the line is structured a bit differently, but still reveals to whom the call was placed. 


So just to clarify, Apple decided to store this record as such: 

KnowledgeC.db --> BLOB --> Binary Plist --> JSON --> Base64 Encoded Data --> Binary Plist --> Protobuf.



Wrapping Up

What does all of this Siri information get us and how do we use it? What's the TL;DR? 

Previously we could track Siri UI event start and stops but almost had to make some assumptions about what might have happened in between. Now we must first look OUTSIDE of KnowledgeC.db into the _DKEvents.SiriUI and SiriUI biomes to figure out when Siri has been triggered (as can see when and how it was exited). In our examples we could see one where some apps were immediately launched and one where a call was started from the exiting of Siri. So how do we track WHAT Siri did if we can? That's where we have to go into our SiriExecution biomes to see if there are any Intents listed or AppLaunches. Remember that Apple tracks AppLaunches in the AppLaunch biome as previously mentioned as well as AppIntents. In addition, by returning back to KnowledgeC.db we can go down the long rabbit hole to return to whom the intent was directed. While this data might not be valuable in every case, I can see several examples where someone might want to know who was messaged or called  considering there could be messages or calls deleted which as we have seen does not always get cleared from the biome data storage. 

This was a fun, but exhausting little bit of digging to do. I've never seen Apple embed/encode data so deeply before but now at least you can figure out who Siri was calling/messaging.  We can also see how Apple are tying the biomes together from the things we have looked at in previous posts. Future posts will continue to track down this data as Apple continues to populate it. Until next time!








Wednesday, 28 September 2022

iOS 16 - Breaking Down the Biomes (Part 4) - Surfin' with Safari

 Oh Safari, I once thought your worst change was moving the navigation bar to the bottom of the screen. Turns out you said "Hold My Beer" with iOS 16 and decided to throw some switcharoos on us. To be honest, Safari has always been an interesting albeit annoying browser for iOS. It has some pretty strict limits when it comes to storing data including keeping history for only 30 days and downloads for 24 hours. It also mimics its history over into the KnowledgeC database which is great when you're trying to confirm that history came from a specific device (and the origin column isn't available that is). 

As this series has explored though, KnowledgeC has changed. Also, KnowledgeC syncs now so that means using it to show device attribution may be difficult too. That being said, the new biome changes give us some flexibility with this as well as give us some new artifacts to track through as well on top of the old favorites.


Safari History

The previous /safari/history data from the ZSTREAMNAME column of KnowledgeC has gone missing and been replaced with a biome: _DKEvent.Safari.History which can be found within /private/var/db/biome/streams/restricted/. This file is going to contain a lot of the same protobuf structure as mentioned previously, but there are some more interesting things going on here with Safari too. First, let's break down the protobuf within the SEGB file. 


Like many other protobuf records before it in the post series, this one will store an identifier "/safari/history" as well as a date and time in Apple Time format. IMPORTANT NOTE: In my testing, the dates and time listed in the beginning of the file appear to be DIFFERENT from the main Safari History.db file records. They seem to only be off by a few seconds but they are coming AFTER the record within the Safari database. The URL for the page is recorded as well as the title of the page later down the protobuf. 

The other important thing to note about the SEGB files is that where previously the KnowledgeC database records confirmed this came from one device, the location of the SEGB files within the biome directory can confirm if these records were generated on this device or on other devices. Remember that any file within the local directory came from the local device while SEGB files within the remote directory were synced to this device from others. 

But what happens when Safari history is cleared? Or if the data is viewed in private browsing mode? When the Safari history is manually cleared from the settings application in iOS, it triggers some deletions within the biome for Safari history. In testing, a tombstone record (a separate SEGB file cerated within he tombstone folder) got created during the destruction event and records were written to it but they did NOT contain the original URLs. 

In addition to the tombstone file being created, there is also changes to the original SEGB files too. What is interesting is that the records are modified in place, and not just simply destroyed or the entire file replaced. Each individual protobuf is written over and replaced with 0x00 within the leftover bytes. 

What makes this even more interesting is what happens when you delete individual records, not through the Settings app, but through the history area of the Safari browser. When this is done, the record within the SEGB file will NOT get removed immediately or overwritten. 


Now, when the same area of Safari issued to purge ALL the history, it has the same response as when you clear it from the Settings. The records in place within the local/{SEGB} file get overwritten with 0x00. 

BEFORE

AFTER


So to recap: delete ALL the records, SEGB gets overwritten; delete individual records, SEGB does NOT get overwritten. 

It should also be noted that records that are done in private browsing tabs never seem to get written to the SEGB files in the first place. This doesn't mean they can't be recovered, but we'll get to that later. 

One last thing to mention on this, is that if you don't also close the tabs, there might still be traces of the data behind even after the HISTORY is cleared. 

SafariPageView

The SafariPageView biome can also contain pieces of the safari history, but can give more context to the URLs. The SafariPageView biome will record the page's textual content without any formatting or images. This allows the examiner to see some of the content of the page as well as use this as a great place to get keyword hits back. 

The data will contain a date and time of when the information is "donated" to the biome, the title of the page, and the textual content of the website. These protobufs can be large, but at the end of the data should be the URL that this content belongs to. 


Aligning with the history, private browsing mode records did not appear in this file and after a full deletion of the history these records were also purged. 

Shared With You 

The "Shared With You" feature that was added in iOS 15 also lives within the biome data so we might as well break that down here since I haven't seen a lot on it. Records that are shared via iMessage show up in separate "Shared With You" areas depending on the content that is sent. For Safari, these website shared from contacts via iMessage will appear on the new tab Home Screen. More information on Shared With You can be found on Apple's website here


The records are stored within a SEGB file in the location /private/var/mobile/Library/Biome/streams/restricted/feedbackSocialHightlights. There are both local and remote subdirectories in this location. The URLs that are shared as well as who did the sharing are available within the protobuf records inside this file. 


Note there are two timestamp records inside the protobuf. In fact, there will be multiple records of the same shared URL in the SEGB file in separate protobufs. The first timestamp is the written time to the SEGB file while the second timestamp stored within the main Message block is when the message was sent. 

Speaking of Shared With You data, each application that can handle that information will react differently. For information on how the Photos app is handling it, go check out Scott's post on it over here.  

Some Other Safari Stuff!

Let's face it. I love tracking Safari information. I've done multiple posts on Safari information and some webinars. I might as well take the opportunity to share some information on some more recent Safari changes. Unlike the biome data which can only be extracted from file system level examinations, this one is going to be available in Quick style images as well. 

In many versions of iOS, turning the BrowserState.db was a great location to go and find records of websites that were beyond 30 days old as well as records of private browsing history. This is still partially true, but not the only place to look anymore. The BrowserState.db will continue to track tabs from iOS 15 that has been restored to iOS 16 devices but will also now only track tabs once they have been closed. 

The new go-to spot for currently open tabs is in the same directory (private/var/mobile/Library/Safari) but called SafariTabs.db. The bookmarks table will store information relating to all of the currently open tabs. The first key is understanding how to categorize the tabs. 


The parent column for all of the following tab information will reflect the "id" column value that relates to one of the above shown categories. This allows us to track pinned, recently closed, local, and even private browsing records within this database. 


In the above screenshot you can see that id 12 relates to a page that is in private browsing mode while id 13 relates to parent 10 which is our "local" meaning just standard tab. The "order_index" column tracks the order the tabs were opened and you may see repeat values because of both normal and private browsing tabs. 

There are two BLOBS in the bookmark table, extra_attributes and local_attributes. The local_attributes BLOB is the most important as it will store information about the tab itself as well as all of its session data. These BLOBs are binary plist files.



The BLOB data contains good information such as the LastVisitTime but the "SessionState" key is what we're really after here. This contains ANOTHER binary plist file, but like the old BrowserState.db used to do to us, this is not all it stores. The first 4 bytes are actually padding so you can't just save the bytes of the SessionState key as a plist then open it normally. After removing the extra padding, the file can then be opened in your plist program of choice. 



Conclusion

Safari certainly knows how to keep it interesting for us, doesn't it? Even though we have lost the Safari history data within KnowledgeC, the web usage data is still there so that's a start. By parsing the biome data we are able to get the information we lost from KnowledgeC and then some! The PageView has been an interesting one for me and I'm curious to see how many folks will find that contextual keyword that helps their case when getting a look at what the user may have seen on the page. 

There's also the newer Shared With You (Me?) data that we can track now too thanks to our biome information. This is handle especially when tracking potentially deleted messages that might still leave the links behind. 

Speaking of deleted, it was really interesting (for me at least because I'm a big nerd) to see how the biome data is treating Safari history when it's individually removed versus removing the entire history. Combine that with not tracking the private mode data and it's really going to be an "it depends" situation for us, but we're used to those right? 

Finally, speaking of private mode, Apple didn't TOTALLY leave us out with that one. While the BrowserState.db's function has seemed to change a bit at least now we can track the same information in a separate database with a little bit of additional digging. Surf safely friends! Until next time!



Monday, 26 September 2022

iOS 16 - Breaking Down the Biomes (Part 3) - Keeping up with CarPlay

 CarPlay is Apple's attempt to make driving your car and using your phone at the same time safer. In order to do this, Apple has basically created a screen mirroring service which allows for your in-car infotainment system to stream data from your mobile device. This is great for listening to your favorite podcasts and use Siri to send/receive messages while driving. There's been some great research done previously on CarPlay and forensics including the talk by Heather Mahalik and Sarah Edwards which is available here (slides here) as well as Josh Hickman's take on the topic available here

Without rehashing the CarPlay artifacts that haven't really changed, this post is going to focus on the artifacts that have changed with iOS 16. Most of the plist files from the /private/var/mobile/Library/Preferences directory are still there and full of data. The biggest change when it comes to CarPlay is where we used to search for "carplay/isConnected" in the KnowledgeC database, those entries are no longer present. Instead, which you probably surmised from the title of this post, the data can be found within the Biome directories. 


CarPlay isConnected

Looking into the biome data there's a couple of places you can find CarPlay information. One of those places is the directory private\var\mobile\Library\Biome\streams\restricted\_DKEvent.Carplay.IsConnected\

Pulling apart this SEGB file (which for more information about them go back to Part 1 here) reveals protobufs that contain information about when CarPlay is connected or disconnected. 



The protobuf will contain a start and end date and time (in UTC) of when the CarPlay state was changed. The final timestamp will be when the protobuf is recorded to the SEGB file. 

A varint value will reflect 1 or 0 where 1 is when CarPlay is in the connected state, and 0 when CarPlay is in the disconnected state. The final varint value reflects the offset of the timezone the device was in during the recording of the event (recorded in seconds). 

CarPlay Red Herring

There's also a CarPlay folder within the biome directory under private\var\mobile\Library\Biome\streams\public\CarPlay\. The biome here doesn't tell much as each protobuf only contains two values. The first value will reflect a 0 or a 1, and the second value always a 0 in my testing. There are no timestamps or other identifiers within this data. The protobuf record header within the SEGB file does contain two 8 byte Apple timestamps but they didn't line up with events within my test evidence directly so are likely more related to when they are written. 


inMotion

Another KnowledgeC event "/inferred/motion" has made its way over to the biome data found within the directory private/var/mobile/Library/Biome/streams/restricted/_DKEvent.Inferred.Motion/. When parsing the protobufs stored within, its fairly familiar to others in the CarPlay family. 


There are again Apple Time values of the start and end of the event in UTC, a varint reflecting either (1) or (2), a string value recording the GUID of the event, a double storing an Apple Time value when it was written, and finally the offset for the timezone in seconds. 

One additional note is that when the GUID is searched across the device you will likely not find it. The GUID seems to be tied into the syncing process so that an event can be kept unique across multiple devices. 

DoNotDisturb / DoNotDistrubWhileDriving

Within the biome data another way to help track that CarPlay may being used is to check for the DoNotDisturbWhileDriving biome data. Similar to the CarPlay Red Herring above, the protobuf is very small. The protobuf for DoNotDisturbWhileDriving will only track a 0/1 record within the data but there are 8 bytes equating to an Apple Time timestamp within each protobuf record header in the SEGB file. 

One thing to make sure is to not confuse DoNotDisturbWhileDriving with the DoNotDisturb biome. While more research is being conducted, Apple treats the DND (do not disturb from here on out because I'm lazy) for driving a bit differently from other focus enabled DNDs. In the directory \private\var\mobile\Library\DoNotDisturb\DB\ there is a plist file: IDSSyncEngineMetadata.plist. This plist file tracks the user's Focus settings. Focus settings from the plist files are tracked within the DoNotDisturb biome but the DND for driving is not. To compare, the DoNotDisturb biome stores a lot more information within the biome's protobuf records and an example is below. 

Similar to other protobuf records, it will track a start and end time in Apple Time (UTC, of course), a varint of 0/1 for when that setting has changed, and the same information at the bottom including the GUID for the event, a timestamp for being written, and the timezone offset. 

CarPlay Plist Check

A couple of things to consider that have been added in more recent versions of iOS is tracking the difference between plugged-in CarPlay and wireless CarPlay. It's also important to track what vehicles or how many vehicles have been authorized to use CarPlay. As mentioned in some of the other posts linked at the beginning, the two main plist files for digging into are in the private/var/library/Mobile/Preferences directory. 

The com.apple.CarPlay.plist tracks our pairings between the two devices. You can see the connection to what I affectionately refer to as my own personal "DoomBuggy" (shout-out to anyone who gets the Disney reference from my all-time favorite ride). 


You can also see that this device supports WirelessCarPlay but NOT USBCarPlay. So by looking through this data, you wouldn't necessarily be able to correlate any events like "Plugged-In" or "Charging" from KnowledgeC or PowerLog. 

The other plist file to look at in this directory is com.apple.carplayapp.plist. This tracks some of the recent app usage of the CarPlay service. 


In the above screenshot you can see an example where the recently used app was com.apple.Maps and it is tracking a Unix epoch value of the last time it was used. You can also see what app is supposed to pop up on start on connection as well as some information about when the previous session may have ended. Using this as a pivot point in our case you might be able to find other supporting information that CarPlay was in use by using this "CARRecentAppHistory" timestamp value. The following is an example of searching within that same time window which shows some hits within PowerLog for the CarPlay application being used. 



Wrap-Up

Hopefully you've enjoyed our little drive through the neighborhood of iOS. While the previously tracked records of CarPlay in KnowledgeC.db are gone, they're not forgotten, just moved over to the biome areas. Seeing that several records store GUIDs for the events gives me hopes they'll be syncing to other devices too. For me it's always about tracking WHY something happened and a big one there is location data. Why was there location data being generated? Seeing a bunch of location points like in the next screenshot from our test phone, I would want to know why they're being generated. While the use of Apple Maps can help generate these, the points can also be passive just from being connected to CarPlay and its use of Apple Maps in the background even when no trips are active. 



Is CarPlay even in play? If you believe so, check the plist files! Once you know that to be the case, start digging into those biomes for more information to show that it was connected during that time frame, and don't forget it can be a wireless connection now too! What about trying to see if the user was doing something while they were driving? Were they locked into the DoNotDisturbWhileDriving mode? Were there any other set of DoNotDisturb settings applied? 

With Apple pushing harder into the CarPlay space and wanting to extend the features which was discussed during this year's WWDC event, I don't think we're going to see CarPlay going anywhere anytime soon. More and more manufactures are enabling CarPlay and Android Auto so expect to get familiar with these artifacts and what they can mean for your investigations as you proceed. Until next time!



Sunday, 25 September 2022

iOS 16 Breaking Down the Biomes Part 2 - AppInstalls, AppLaunch, & AppIntents

 In my previous post in the "Breaking Down the Biome" series, I covered the basic structure of biome data in iOS as well as mentioned how several things went missing from KnowledgeC in iOS 16. In this post I'm going to cover one of those that went missing,  Application Installs, as well as some data that can correlate as well as still exists in the KnowledgeC.db (but might not always). Something I've noticed in my testing of iMessages for this year's SANS DFIR Summit is that when a message is deleted from the device it may also delete itself from the KnowledgeC database but NOT always removing itself from the Application Intents biome data. You can see some evidence of this in this post where I talk about unending/editing/deleting iMessages in iOS 16. 


Application Installs

There are different ways to track what applications are currently installed and have been previously installed in iOS. One of my favorite ways relies on the use the mobileinstallationlog file which can track when apps get installed AND installed. However, one of the issues with this file is that it can get noisy as it also tracks when containers are created and destroyed which is something Apple tends to do frequently even if the app didn't have any associated activity. It also doesn't seem to be time based and more based on the number of records written/size of the file so data that you might want could be missing depending on the activity being recorded in that file. 

Because of that, I love turning over to the KnowledgeC.db file and looking at the app/install value within the ZOBJECT.ZSTREAMNAME area. Unfortunately, in my testing of iOS 16, that stream name value in no longer present. Similar to last post's ability to turn over to the biome data and look for the "app/inFocus" data, we'll do the same here for the install logs. 

This data can be found in the path: private\var\mobile\Library\Biome\streams\restricted\_DKEvent.App.Install\ and has the same structure as previously mentioned with a metadata plist file and a local folder containing SEGB binary files. The metadata plist file shows us another maxAge value of 28 days (after translating from seconds). 

Since my phone was just set up a few days before, a lot of the first records in this file are corresponding to first party system applications. This could be a good indicator to look for to see if a device was just restored or upgraded. 

Like other biome files, once the SEGB header ends at byte 56, each record following is a 32 byte header followed by the protobuf record. The first four bytes of the header (in little endian) still show the length of the protobuf record and the next record header will begin after the end of the protobuf padded to the next byte divisible by 8. Two records for WhatsApp and Snapchat have been included below. As a note, the install start and finished times are Apple Time values but seem to be rounded to the top of the minute in my tests. 




Application Launch

Previously a lot of tools have tracked "Application Usage" and while that can still be tracked in both KnowledgeC.db and the biome areas, there's another one that can be tracked referred to as "Application Launch" or the AppLaunch function. This function seems to be fairly prevalent in the biome data and mentioned in several database files when tracking syncing information. Similar to the inFocus data shown in the previous post, there is a number of transitions that can be tracked in these records as well. 

The path to the Application Launch biome is: private\var\mobile\Library\Biome\streams\public\AppLaunch\

As with many of the biome data points, the metadata plist files contains much of the same keys about the time to keep the files. In this case this data is 28 days. 

This is a good time to remind folks that not only can you have the "local" biome data but also potentially remote data like in the following screenshot. These folders under remote are tied to device GUIDs assigned as part of the biome's sync.db. 



The protobuf for each AppLaunch looks like this: 



There are several visible "transition types" that start out each protobuf record. The ones I've been able to record so far are listed below: 
  • com.apple.SpringBoard.backlight.transitionReason.idleTimer
  • com.apple.SpringBoard.com.sitionReason.homescreen
  • com.apple.SpringBoard.transitionReason.externalrequest
  • com.apple.SpringBoard.transitionReason.appswitcher
  • com.apple.SpringBoard.backlight.transitionReason.lockButton
  • com.apple.SpringBoard.transitionReason.spotlight

Application Intents

This is probably one of the most important things tracked within the biome data. Once the application is installed, Apple will then track different "intents" of applications, both first and third-party. The data tracked for each application depends on what APIs the application is using so your milage may vary when it comes to seeing if your target application is in the intent data and what it is tracking. Some applications that I have seen in here that have piqued my interest include: 
  • com.apple.mobileSMS
  • com.apple.mobilephone
  • com.toyopagroup.picaboo
  • net.whatsapp.WhatsApp
  • com.burbn.instagram
For more information on the AppIntent function, Apple has provided a bit of into on the developer documentation here. The short version on AppIntent is that it is providing content/context to certain functions for Siri Suggestions or Siri Shortcuts. This doesn't mean you have to use the Siri voice assistant to make something happen. Think of Siri as your iPhone's version of Alexa in that it's always listening/watching/learning. 

Application Intents record a number of different events for a number of different apps. Some of the more interesting intents that I've seen include: 
  • INSendMessageIntent
  • INStartCallIntent
  • INCreateNoteIntent
  • INAddTaskIntent
  • INPlayMediaIntent
  • INSendPaymentIntent
  • INRequestRideIntent
  • INStartWorkoutIntent
When it comes to the intent INSendMessageIntent it really is going to depend on what app you're investigating. While Snapchat, Instagram, and Twitter all record intents, they don't really keep the content of the messages within the biome. What you will more commonly get is the participants of the messages, dates and times, and the directionality of the messages though. 

The content of the protobuf for each intent is one of the more complicated ones that I have come across. Within the protobuf you will find information such as the app recorded (bundleID), a date/time of the action, the intent used, and usually a binary plist file saved within. The binary file is often our true jackpot within the protobuf data. 


The first key is going to be our Apple Time value of when the intent occurred. The next refers to the bundleID of the recorded app. In the above graphic, key 4 shows us the intent that was used, in this case the INSendMessageIntent. 

Extracting the binary plist file shows an NSKeyedArchiver style file. These files will contain ANOTHER protobuf (or two) that need parsed out. Depending on the tool you're using to review the plist file, you may need to convert the protobuf from Base64 first, but some tools may do this for you. You'll be looking for the key "<bytes>" that contains the protobuf data. 

Within the above screenshot you can see several key points such such as the value [5] containing the body of the message. The next value [8] contains the service and sender. The value under key [15] shows the sender while the data within key [2] shows the recipient. If the other party is a known contact, there will also be information showing the first and last name as well as the identifier GUID from within the AddressBook database. 

So to recap: 
Biome (SEGB) File --> Protobuf Record --> Binary Plist --> Protobuf Record. Yikes. 

Not all of the protobuf records at the end of the rainbow are pots of gold like the one for messages. The following one is from a Snapchat SendMessage intent. 

In this protobuf we can still track that our user "Paul Pelican" was talking to a user "Al Paca" on Snapchat but that's about as far as it goes. Still, could be valuable within investigations. 

Other intent types such as the INStartCallIntent also contain valuable information about who and when users are talking to each other. This can include calls through the standard phone service as well as VOIP services through third-party applications. 


A final couple thoughts on observed AppIntents. At times, you will find that within the binary plist file there is not a protobuf, but instead ANOTHER binary plist file which contains the final protobuf you're looking to find. 

Wrap-Up

If there's one thing I'm learning from parsing this biome data is that it can really make your head hurt. Tracking applications and when they're installed, when they're launched, and what they might be up to, however, is worth the headache. Remember that similar to when it was kept in KnowledgeC that this data is only going to be tied to approximately the last 28 days (outside of tombstone records which could contain more expired data), but with the switch to the biome storage it is important to look for the remote as well as local binary files to find information from other devices. While the tools don't support all of the biome data as of yet, forensics tools can be a good starting point for parsing this information out of specific biome files. Hopefully the roadmaps laid out above can help you identify more files worth digging into. 

Until next time!

Friday, 23 September 2022

iOS 16 - Now You 'C' It, Now You Don't -- Breaking Down The Biomes Part 1

 With the release of iOS 16, I did what I always do-get as many images as I can from my test phones and start ripping them apart to see what is and isn't there anymore. While quick images (iTunes-style backups) were pretty straightforward minus some enhancements to Messages and Safari (here if you're interested), filesystem images have been a bit different. Buckle up folks because this one is going to be a bit long. If you're looking for the TL;DR, scroll to the bottom to get a quick review of the good news/bad news. However, if you're curious in seeing how the new "biome" data structures are playing into things, keep reading. 

Finding the Missing Knowledge

While working through the file system I wanted to check on some of our favorite pattern of life activity such as PowerLog and KnowledgeC data. While PowerLog is still mostly intact (and still a mess to parse through), I noticed that KnowledgeC was missing several of my favorite artifacts. If you're not familiar with KnowledgeC.db, where have you been?! Jokes aside, I recommend reading up on it from the talented mind of Sarah Edwards over on her blog Mac4n6. Sarah's work into KnowledgeC and her tool APOLLO has been amazing for helping to deal with KnowledgeC work and the basis for a lot of our understanding of pattern of life information over the past few years. 

So what was missing? The easiest way I can show this is using a tool from my day job, Magnet AXIOM to show you a list of what was present from a device running iOS 15 to iOS 16. Now, take the number of recovered records with a grain of salt as the iOS 15 device was used for a longer period of time versus the iOS 16 one. What is key is taking note of the missing categories entirely. 


iOS 15


iOS 16


I'm sure that we all have our favorite artifacts within KnowledgeC but I quickly noticed several of my personal favorites such as Application Focus, Safari History, Install History, and many of what I call "nexus events" such as Device Orientation and Plugged-In States missing too. Yikes! Thinking that it was possible that the stream name of these events within KnowledgeC had changed, I dove into the database to see what was up. 

Looking in the ZOBJECT table of the database at the ZSTREAMNAME column, the app/inFocus key is missing entirely. Digging around the file system I found that there were some hits of the same data but in a totally different place. One such place is a folder called "_DKEvent.App.InFocus" which lives in the path /private/var/db/biome/streams/restricted. Biomes? Streams? What does all this mean? 

Understanding Biome Data

Let's face it Apple, you're not great at documentation when it comes to the outside world. We still haven't seen all the documentation when it comes to KnowledgeC and some of our other favorite artifacts, and now Apple's throwing us another curve ball! Biome data has been around for a bit in both macOS and iOS but is getting used a lot more now. Biome seems to mean less around "biometrics" and more around "suggestions." For more information on what one of the best macOS resources I've ever seen has to say on the topic, head over here to Howard Oakley's Eclectic Light blog on the topic. 

I would tend to agree with a lot of what Howard has talked about with biome data as it tracks with what I've found for a while now in iOS. You can see some examples of that in this post here when talking about iOS messages within AppIntents and other locations. 

From looking at iOS 16's file system information you can actually find several biome folders: 
/private/var/mobile/Library/Biome and /private/var/db/biome. You're not going to find either of these outside of a file system image in my experience. In these folders, you're going to find a "streams" folder with data separated into either "public" or "restricted" folders. Within each of these directories the data is then tracking a specific service or function with other subdirectories and binary files stored within. The age of the binary files seems to be approximately 30 days from my previous testing, but additional digging will be done to see if iOS 16 has changed that. 

The binary file is often referred to as a "SEGB" file by several developers and while its name looks like a timestamp, it seems to be tied to a serial number for that process. There is also a tombstone folder which contains expired versions of these binary files. 

Within the biome folders, you can see several points of interest in the following screenshots. Several of them match what we USED to see in the KnowledgeC database as well. 





Breaking Down the Biomes (Part 1-App.inFocus)

To be honest each of these folders need to be broken down in depth and will be in due time. However, because of the incredible amount of valuable data found within these folders, I think it's important to get the data out there to the community for some of the really crucial ones. Plus it gives me an excuse to turn this into a whole series and keeps me busy!

The best way we can attack these datapoints is to get a better understanding of these "segb" binary files and how they are structured. Luckily, while the records within the files are going to change depending upon what the binary file is tracking, the overall general structure is the same. 

There's some great additional information on these files available here as they relate to AppIntent data from BlueCrew Forensics. I'll take a higher level look at these binary files here as they pertain to a lot of the more generalized storage here in iOS 16. 

Let's start with one of my favorite KnowledgeC events that have moved over here, Application Focus. What used to track as app/inFocus in the KnowledgeC.db file can now be found within the _DKEvent.App.inFocus directory's binary files. 

Let's start with the "metadata" plist file outside of the binary file. This file exists for each subdirectory in the biome data and helps us better understand how long we can expect this data to exist. These NSKeyedArchiver style plist files can show us the max age of the data within the binary file. 

 The maxAge value (2419200) appears to be seconds, and if it is converted to days, shows us 28 days which lines up with previous biome experiences. 

The first 56 bytes of the binary files are referring to the header of the file itself. It will end with "SEGB" in ASCII. 


Immediately following the file header is the first record. These records will have two parts, a 32 byte record header and a variable length record stored as a protobuf. The 32 byte record header's most important part (in my opinion) is the the first four bytes. These four bytes inform us how long the protobuf record actually is. This value is stored in Little Endian format. 

From the above screenshot this particular record in question is 264 bytes long. There are also 2 timestamps stored in Mac Absolute Time  at offset 8 & 16 of the record header which seem to correspond to when these records are written to these binary files. At the end of the record header starts the protobuf record which in this case is our 264 bytes. If we sweep and extract that data we can open it up in a protobuf viewer such as using something like CyberChef. Note: If you're going to use CyberChef your recipe should be "From Hex"-->"Protobuf Decode."

I personally use a great tool built by a developer friend of mine for reviewing protobuf data that I'll include some screenshots of. In the following example, two records from the SEGB data that are right after another are being displayed. One thing to understand about these protobuf records is that even though the record header tells us how long they are, the next record header may not start immediately. Records may have some 0x00 padding and the next record header will start at next offset divisible by 8. 



The "Transition Type" as mentioned above have several observed types, but I'm sure there are going to be more we find. 
  • com.apple.SpringBoard.transitionReason.homescreen
  • com.apple.SpringBoard.transitionReason.externalrequest
  • com.apple.SpringBoard.transitionReason.appswitcher
  • com.apple.SpringBoard.transitionReason.spotlight

Some other Biome Info

Something else that should be noted about this biome data is that there are several clues that inform us that this data may be syncing to iCloud. First, in most of the files that are being examined, a record GUID is being given for each recorded action. There's also information within the main Biome folder (private/var/mobile/Library/Biome) which shows that the data is uploading to iCloud and a single device may have records synced from OTHER iOS/macOS devices. Other information within the KnowledgeC.db shows there are records syncing up and down to iCloud as well!

Using the sync.db found within /private/var/mobile/Library/Biome/sync/ you can see within the DevicePeer table records of devices that are syncing with your target device. Each device is assigned a GUID value as well as showing the last synced date in Unix numeric time. 


The GUID value listed within the database will also match subdirectories found within the "remote" folder  of each biome's service folder. This way we can track where these additional records are coming from when parsing the remote biome data points from the local. 


The TL;DR and Wrap-Up

Whew that felt like a lot. Okay, here's the good news/bad news. Bad News: KnowledgeC.db doesn't seem to have as much as it did previously. Good News: That data has moved to another location that while requires a bit more parsing, seems to have some amazing data stored within. In addition, we'll be able to track data from devices we might not have in our possession. 

This research is going to be ongoing for a while but I'll continue to break down additional biome files and their protobufs over the next few weeks or so.