iOS

On the Fifth Day of APOLLO, My True Love Gave to Me – A Stocking Full of Random Junk, Some of Which Might be Useful!

Today we go over one of the stranger databases on iOS, the Aggregate Dictionary database, or ADDataStore.sqlitedb. This database is only available with a physical file system dump in the /private/var/mobile/Library/AggregateDictionary/ directory. The database also has a different way of storing its data. Instead of a “this time this event happened” storage system like many of the other database I’ve gone over. This one aggregates data for the last seven days. It only records data on a per-day basis so the APOLLO modules will only store a day timestamp. 

This database is good to find random bits of useful stuff, not every case will need it but you might be surprise what it is tracking. The Distributed Keys and the Scalars are each keeping track of seemingly obscure items. In my opinion, the Scalars are more interesting. On my example database I have 5398 unique keys for Scalars and 795 keys for the Distributed table. I can’t even begin to show you everything this database tracks, its best just to take a look at one yourself to see what might help in your own investigations. I will focus here on a few of the more interesting Scalars entries.

I’ve previously written about this database with respect to Pincodes, Passcodes, and Touch ID.

APOLLO only has two modules for the Aggregate Dictionary. Since these are using only a per-day timestamp, I’ve made them easy to filter out or as a user choose to not use these modules. They can look a tad messy in the final output.

The first item I pulled out of the stocking is CarPlay data. The example below shows how many cars I’ve connected using CarPlay in com.apple.CarPlay.VehicleCount. I’ve connected this device to three different cars. I’m still testing the difference between*.CarPlayCar.* and *.tCarPlayPhone.* keys, however I could guess that Activations has something to do with how many times the app was selected while the ActiveTime is how long the app was in use.

The next item has to do with the Messages application. This app is collecting metrics on the different types of items sent and received over SMS or iMessage protocols.

The Settings applications (com.apple.Preferences) keeps track of which setting got viewed. The example below shows I viewed the Bluetooth menu twice on the 10th, and the privacy settings once on the 14th. I encourage everyone to search for various bundle IDs of interest in this output – you never know what the apps are going to store!

The Clock app (com.apple.MobileTimer) keeps track of how many alarms the device has set, if any are active, number repeating, and named alarms. Some apps are better at storing data like this than others.

Safari records the number of tabs open on a particular day

The Photos app (com.apple.mobileslideshow) keeps track of how many photos there are in the albums.

Curious how many times a device was plugged in during a day, try the com.apple.power.state.pluggedin.count key. We will revisit this action in an upcoming device state article.

When I say obscure, I mean obscure – it also keeps track of button presses…because why not!

Some settings are also stored in this database. You can perform a filter for a couple of keywords – enabled or disabled. I’ve provided a screenshot for both. For the “Enabled” keys, I chose to filter on the main interface, Springboard (com.apple.Springboard). The value is a binary value that means on (1) or off (0). This is different for the “Disabled” keys.

If the keys have the term “disabled” in them, you have to think opposite. For example, all these Accessibility features are actually turned on or enabled. If the disabled setting is a 0, it means it is turned on (you can see many of the settings in the iOS screenshot, Shake to Undo and Vibration for example.)

Finally, in the toe of the stocking we can get some data usage information. I’ve filtered here by the Twitter application (com.atebits.Tweetie2). The screenshot shows how much data was transferred in kilobytes over Wi-Fi and/or WWAN – incoming or outgoing.

Discover & share this Drinking GIF with everyone you know. GIPHY is how you search, share, discover, and create GIFs.

On the Fourth Day of APOLLO, My True Love Gave to Me – Media Analysis to Prove You Listened to “All I Want for Christmas is You” Over and Over Since Before Thanksgiving

The fourth day brings us media artifacts using the knowledgeC.db and CurrentPowerlog.PLSQL databases. Each database stores similar yet somewhat different records when it comes to audio, and video usage.

Let’s get in the mood!

KnowledgeC.db 

Starting with the knowledgeC.db database we get an idea of audio inputs and outputs. Using the knowledge_audio_input_route and knowledge_audio_output_route modules we can extract this data.

The example below is audio inputs. Two different devices can be seen in the screenshot below, a CarPlay device and my AirPods.

In the output example we see the same two devices. Common to both is the fact that you may see it bouncing back and forth as devices are being used. For example, if you are using CarPlay rocking out to WHAM’s Last Christmas, it will bounce between playing your music and using the microphone/speaker to listen/dictate messages as they come in.

The knowledge_audio_media_nowplaying is where the real truth of your guilty musical pleasures will make an appearance. It provides a detailed listing of what the user was listening to at a particular time. The example below shows me listening to music, podcasts, and audio books. There is no denying that you started listening to holiday music entirely too early!

CurrentPowerlog.PLSQL

The powerlog_app_nowplaying module sounds like it should extract the same information as above, however it is different in that it will just show the application’s bundle ID being used to play the media.

More context can be found by using the powerlog_app_audio module. This module will extract the app/service name and/or bundle ID for the app using the audio function. In the screenshot below, I received a phone call and a bit later connected the iPhone to my car to listen to music. During that time, I was also using Siri (assistantd) to dictate messages. Fortunately for me, this database doesn’t show what I was listening to! 🤭

Similar to the module above, is the powerlog_audio_routing module. This shows where the audio was routed to, either the Speaker, Receiver, or Car in this example. 

Finally, the Powerlog populates a table just for videos. The powerlog_video module will show the application bundle ID that the video was played with, however not what video was playing.

On the Third Day of APOLLO, My True Love Gave to Me – Application Usage to Determine Who Has Been Naughty or Nice

On this third day, we will focus on application usage. We will cover three databases:

  • KnowledgeC.db

    • Be sure to check out more detailed information on this database in my two previous articles.

    • Access to this database is limited to a file system dump, it will be located in /private/var/mobile/Library/CoreDuet/Knowledge/KnowledgeC.db

  •  InteractionC.db

    • Access to this database is limited to a file system dump, it will be located in /private/var/mobile/Library/CoreDuet/People/InteractionC.db

  • CurrentPowerlog.PLSQL

    • Access to this database is usually limited to a file system dump, but I recently learned that if you can perform a sysdiagnose on the iOS device you can get this log as well! This method is certainly not forensically sound, but it will get you access to the database. You will have to rename this database to “CurrentPowerlog.PLSQL” from something like “powerlog_YYYY-MM-DD_##-##_########.PLSQL” to parse it with APOLLO. I have plans to update the script to support this naming scheme. 

    • In a file system dump, you can find this database in /private/var/containers/Shared/SystemGroup/<GUID>/Library/BatteryLife/CurrentPowerlog.PLSQL

      • It is worth a mention here that additional historical Gzipped PowerLog databases may be found in the /Archives directory in the path above. (My APOLLO script does not handle auto unarchiving of these yet, but it is planned for the future.)

Application Information, Installation, & Deletion

Let’s start by getting some basic app information. The Powerlog has a nice listing of iOS applications with their App name, executable name, bundle ID, and version and app type. These entries are not exactly an ongoing log file, but it does get updated frequently. The app type column can provide information on what type of application it is.

  •  1 – Background iOS Service

  • 3 – iOS Native App

  • 4 – 3rdParty App

These entries will also have information on if the app has been deleted. This listing can be extracted by using the powerlog_app_info module.

I have a very similar module called powerlog_app_deletion that uses the application deletion time as its key to get just the recently deleted applications.

To get a listing of recent application installs, we need to go to the KnowledgeC.db database. You will see in this blog series that you cannot rely on one database for all the answers. The module knowledge_app_install will extract the time of install and Bundle ID for the newly installed app. 

Application Play by Play 

Knowing what application was being used at any given moment, down to the second, can be a huge forensic win. Fortunately, we have a couple of options, each a little different.

The first is the KnowledgeC.db database. The knowledge_app_inFocus module shows the app Bundle ID, day of the week, GMT offset, start/end of the usage time from which I calculate usage time in seconds.

Another option is the powerlog_app_usage module which uses the CurrentPowerlog.PLSQL database. The output contains the app Bundle ID and a few other metadata items.

You will notice a few additional columns in the output:

  • ORIGINAL_SCREEN_STATE_TIMESTAMP

  • OFFSET_TIMESTAMP

  • TIME_OFFSET

These additional columns are needed because the timestamps need to be normalized. The original timestamp is stored with an offset, sometimes in the future, sometimes in the past. This offset is stored in PLSTORAGEOPERATOR_EVENTFORWARD_TIMEOFFSET table in the CurrentPowerlog.PLSQL database. This offset gets used in many of the Powerlog tables. I want to provide a warning to other investigators to not always believe the timestamp provided in a database. You MUST test this, I’ve seen offsets from as little as a few seconds to as much as 15 minutes. In my queries I’ve done my best to test what I can, but I’m sure I’ve missed some and they may change per iOS version (we will see an instance of this in the next module). Noticed I missed one? Please let me know!

The modules powerlog_app_usage_by_hour and powerlog_app_usage_by_hour_iOS12 extract data usage on a per hour basis. During the research for this blog article, I was using my own iOS 12 Powerlog output from sysdiagnose to test differences with iOS 12. I came across one issue with this particular module, I determined in iOS 12 that the timestamp in this table now implements the same time offset that we saw above, however on iOS 11 (and older) it did not. Soon I will implement a function in the script to determine which iOS to perform which queries, however now it will run both so please be aware of this.

Below is an example from iOS 11.

Below is an example from iOS 12 with the time offset applied (offset columns are hidden from view). Not shown in the screenshot is a bug where the applied time offset may show the ADJUSTED_TIMESTAMP off by a single second for earlier records. If anyone has recommendations on a better SQLite query to perform this offset adjustment, drop me a line!

These modules extract an applications usage on a per hour basis. The query will extract the app bundle ID, screen and background time, and additional background usage with audio and location.

Context Providers 

The next step is to provide more context to each application being used. We have quite a few modules for this.

The InteractionC.db database contains lots of information to correlate contact information with application activity. The screenshot below only shows a portion of the contact data for each record, but it should be a good indication of what email was being read or what contact was being texted. This module is named interaction_contact_interactions.

Curious what the user was browsing when they were using Safari, try the knowledge_safari_browsing module. There are a few catches to this one, it will not record private browsing and entries will be removed when they are history is cleared (either by the system or user).

Using application activity streams in the KnowledgeC.db database we can extract more information using knowledge_app_activity module on to determine items like Apple Map directions, Mailbox or Message views, specific 3rd party application usage, and other native Apple iOS app activities.

I created a similar module, knowledge_app_calendar_activity, specifically for Calendar activity since it has a bit more calendar related metadata items associated with it.

Again using the KnowledgeC.db for context, I can use the knowledge_app_intents module to determine more details of application usage, including sent messages, map searches and navigation, Safari browsing, and phone calls. A keen eye will notice the data blob in the SERIALIZED INTERATION (HEX) column starts with the hex of a binary plist. This binary plist contains more specific contact information, such as who a message was sent to or what contact was called. I saved it in hex to easily copy/paste it into a hex editor or to save off as a plist file.

Finally, we can use the knowledge_application_portrait to get even more contact information for messages or account information for an associated email account. The items in GROUP ID can vary but usually if it’s a GUID it will correspond to a specific email account that can be found in the user’s Accounts database.

Parsing iOS “Frequent Locations”

The Artifact:

The phrase “Location, Location, Location” has special meaning for those looking for real estate but can also mean everything to a forensicator looking for locational data. One of the most useful (or creepy if its yours) artifacts on an iOS device is the “Frequent Locations”. iOS will store, for a lengthy amount of time, locations a user’s device has been. This feature came out in iOS 7 and is used to record a pattern of activity for the user. Most often, a user will notice a message like one in the screenshot below - this is the 'routined' process in action on iOS devices. My phone “knew” I was likely headed to Arlington at this specific moment and ‘helped me’ by showing the traffic times. (Way to be creepy, iPhone!)

Users can review and clear their frequent location histories as shown in the next screenshot. 

Settings -> Privacy -> Location Services -> System Services -> Frequent Locations

Got an iPhone? Play along! Take a look at your frequent locations.

Don’t have locations? Location Services must be enabled.  iOS Location Services must be enabled and more specifically the option ‘Frequent Locations’ under ‘System Services’ must be turned on. There are many services that may be configured under ‘Location Services’ this is only one setting. The ‘Frequent Locations’ are enabled by default.

Locations are clustered by general areas. In the example above you can see I live in the Northern Virginia area and visit many cities in and around the area. These clusters also include the number of sub-locations and general timestamps. You can select one of these areas and get a more detailed street-level overview. This level shows that there are a number of ‘visits’ for each location, and again - a general day-based timestamp.

If we keep selecting down, we can get specific visit and timing information. Each location can have multiple visits. (Note the ‘N Nelson St.' example with 49 visits above.) The example below shows one visit on December 13th at around 6:30 – 6:45pm, however the visit radius (shown in blue) can of course be very specific or more general depending on GPS availability. (I believe this was a visit to Whole Foods.)

Going back to the top - I recently traveled to San Francisco to teach my SANS FOR518 course and have locations from there in the broader ‘United States’ cluster history. Since I traveled outside of my normal Northern Virginia area, iOS made a new “cluster” of locations to include those in the San Francisco Area but also some in the NoVA area as well! I’m sure there is an algorithm somewhere to determine this – but sometimes it just doesn’t make sense how it is organized.

The Script:

Available Here

I wanted to study these artifacts in more detail as they have obvious benefit to the forensics community. These ‘frequent locations’ are stored in two binary plists in the following location:

/private/var/mobile/Library/Caches/com.apple.routined/

  • StateModel1.archive
  • StateModel2.archive

(Note: These files are protected and are only accessible in a physical dump or by physical (jailbroken) access to a device. You will not find these files in an iCloud/iTunes backup or a logical dump by forensic tools.)

I was elated to find them in a common file format, however the binary plist format used is the NSKeyedArchiver format which is less than human analyst friendly. (More on these types of binary plists in a future blog article.)

I needed to write a script to truly begin to understand how and why these entries get created as well as put the plist data into context. Enter, the script.

Big caveat here. I’m the first to tell anyone that I’m not a programmer. In fact – I’ve been avoiding it like the plague for the longest time (I had a not-so-fun experience with it in school – mind you I loved my scripting course.) I have come to realize that as a forensic analyst some times you just have to suck it up and script something to make your life easier - this is one of those times.

I decided to learn and script in Python since there were many forensic-based tools and packages that already use Python – it seems pretty industry standard. I’ve also noticed that I keep saying to myself (and my students) that this would be so much better or easier if there was a tool to do this or to do that! Sometimes you just gotta do it yourself if you want it done! So I will be trying to contribute as needed to the Mac forensics community – I foresee this being the first of many scripts.

The dump_freq_locs.py script takes in the StateModel#.archive files (where # is 1 or 2).

The script also has two dependencies, hexdump.py and ccl_bplist.py. These files can be installed or just simply placed in the same directory you are running the dump_freq_locs.py script from. (Installation on OS X 10.11 systems are limited thanks to SIP.)

The script parses the StateModel files and dumps the information to standard output so you will likely want to redirect to a file for later analysis.

$ python dump_freq_locs.py StateModel1.archive > SM1_parsed.txt

The script output contains three sections some of which I can describe here, but as stated above – I don’t know the significance of some of these items….yet. Parsing is the first step toward understanding.

  • Metadata – Contains metadata about the file (eg: when it was last updated, last location information, as well as other timestamps.)
  • RTVisitMonitor Data – Location information, timestamps, edge detection, outlier, last visit, and LOI (Location of Interest?) information.
  • Location Data – The ‘meat’ of plist file. Each location entry has the following:
    • A timestamp of when it was last updated (not necessarily visited)
    • Hexdump output of the location BLOB data containing reverse geolocation data
    • Hex Output - so you can input it into your favorite hex editor for additional analysis
    • Location Data -  The decimal latitude and longitude as well as ‘confidence’ and ‘uncertainty’ (I’m assuming these have something to do with how big the blue radius is) and the last update timestamp.
    • Visits – Entry and Exit timestamps for each visit.
    • Transition Data – When the device was ‘out of range’ of a location. The ‘Motion Activity’ may have something to do with if the device was in a vehicle or in a persons pocket while walking. Looking at my own data a value of 0 seems to be when I’m walking and a value of 4 seems to be when I’m in a car. Not sure what value 2 is yet.

This script was tested of a variety of different devices including iPhones and iPads on different iOS’s from iOS 7-9. As usual the format of these StateModel files has changed slightly from version to version. If you see I’m missing certain information from the parsed output please let me know! On that same note, if I’m not doing something Pythonically correct or weird – let me know too! I’m new to this Python/scripting thing.

I plan on adding future capabilities to this script, like CSV and KML outputs. If you have specific output format needs – let me know, I’ll take them into consideration!

Enjoy!

Sample script output is available here.