script

iOS Location Mapping with APOLLO – Part 2: Cellular and Wi-Fi Data (locationd)

My previous article showed a new capability of APOLLO with KMZ location file support. It worked great…for routined data, but there was something missing. What about the cellular and Wi-Fi locations that are stored in databases? Well, turns out I need to test better. I fixed the locationd modules to have the activity as “Location” versus “LOCATION”. Case sensitivity is apparently thing in Python…my bad. 🤷🏻‍♀️😉

I should also mention with the fixes, my total location data points for a iOS 12.1.1 device jumped to ~57,000! I should note this is not inclusive of workout locations. Those are a bit different as they are stored as separate records, one for latitude and one for longitude. In the future I might attempt to pair these up for KMZ support.

The previous article showed the routined (user/device patterns) data, I have found these locations to be quite accurate. To be fair, I have not looked at all (40k+) of them specifically, only spot checked. When I visualized the locationd data, I saw some interesting outliers.

The first module I found particularly interesting is the output from the locationd_cacheencryptedAB_celllocation module. Most of the locationd output is kept for about a week. This particular week I traveled from DC to Portland via Chicago for DFRWS and then back to DC (again via Chicago). You will notice that there are some data point clusters around DC, Chicago and Portland as expected – but there are a few scattered data points in the Midwest. I do not remember for sure if my device was in Airplane Mode, but this may be an artifact of potentially being able to access cell towers during my flight. (The locationd_cacheencryptedAB_ltecelllocation module output showed a similar pattern.)

The next module, locationd_cacheencryptedAB_ltecelllocationlocal, shows my path home from fairly accurately. These locations tend to be kept for less time. I was going north on 95, past the DC Beltway (near Springfield, VA) and onto Glebe Road towards Arlington, VA. It may be hard to see in the screenshot but the airport to the right near the Potomac is DCA. Just north of that is the Pentagon and Arlington Cemetery.

Finally, we have the output from the locationd_cacheencryptedAB_wifilocation module. This one has a few more outliers that I have a hard time explaining. I was DC and Chicago in this screenshot but not in Buffalo (NY), Pennsylvania, or NYC.

These are good examples of not completely believing and relying on what you see in the data. I can only imagine forensics cases relying heavily on this data. While I have found routined data points to be far more accurate, locationd on the other hand does have its oddities. Perhaps it is something with how the data is populated or the coordinates being reported by cell towers and/or access points. This requires additional investigation. TL;DR – Don’t assume what you are looking at is the end all be all of the data – always investigate further and correlate with other information.

In other news, if anyone knows more about how this data is populated – I’d love to know. Drop me a note!

iOS Location Mapping with APOLLO - I Know Where You Were Today, Yesterday, Last Month, and Years Ago!

I added preliminary KMZ (zipped KML) support to APOLLO. If any APOLLO module’s SQL query has “Location” in its Activity field, it will extract the location coordinates in the column “Coordinates” as long as they are in Latitude, Longitude format (ie: 38, -77). These are more a less an upgrade/replacement from my previous iOS location scripts. (FYI: Those will not likely be updated further.)

You can find more details on the different modules and outputs here. The APOLLO output will also show counts of how many location data points were extracted from each module. An example from my own data contained 41,262 points! Due to the amount of data points and how applications like Google Earth might handle them I’ve decided to split them by module to be loaded separately. It’s not ideal, but my goal is not to crash Google Earth. (FWIW, I’m still working on other solutions, if you have experience in this area - drop me a line.) The most troublesome module (by a large magnitude) is routined_cache_zrtcllocationmo since it keeps track of extremely granular locations for about the last week. Mine had ~38,000 coordinates!

Let’s take a look at some examples! This data was collected on 07/18/2019 on iOS 12.1.1 to give you an idea on timeframe.

This one is from is from the routined_cloud_visit_inbound_start module. The earliest coordinate is from a few months prior from my trip to Amsterdam to teach FOR518 - Mac and iOS Forensic Analysis and Incident Response.

These are some of my “Significant Locations”, you can click on any coordinate and gather more detail. This is the same output that is captured in the APOLLO database or CSV file. 

The next example is from routined_local_learned_location_of_interest_entry. Here you can see some of my travels since 2017! These contain the “Learned Locations of Interest”. You will probably see a bit more historical location data. Looks like I need to visit the middle of the US more!

Last but not least is the massive amount of data points from the routined_cache_zrtcllocatiomo module. This will show nearly exact, granular location for about the last week before collection. Here is my trip to Portland, OR for DFRWS! Not many guesses as to how I got to downtown Portland from the airport is there! (This is the module that produces many, many datapoints. It took patience with Google Earth to even get this screenshot, this is your warning.)

I hope this adds a bit of visual context to some of the APOLLO output, let me know if you have different ideas on how to represent some of this data! Pictures can certainly tell a story where it might otherwise get lost in the noise.

On the First Day of APOLLO, My True Love Gave to Me - A Python Script – An Introduction to the Apple Pattern of Life Lazy Output’er (APOLLO) Blog Series

I originally released APOLLO at the Objective by the Sea conference in early November. Since then I’ve received a surprising amount of positive feedback about various analysts using this tool or the accompanying SQL queries on their file system dumps to help a variety of investigations.  

It now time for a proper introduction. I will present this to you in what I’d like to call “The Twelve Days of APOLLO” a holiday themed (very, very loosely) blog series starting today! 

Why

APOLLO stands for Apple Pattern of Life Lazy Output’er. I wanted to create this tool to be able to easily correlate multiple databases with hundreds of thousands of records into a timeline that would make the analyst (me, mostly) be able to tell what has happened on the device.

iOS (and MacOS) have these absolutely fantastic databases that I’ve been using for years with my own personal collection of SQL queries to do what I need to get done. This is also a way for me to share my own research and queries with the community. Many of these queries have taken hours, even days to research and compile into something useful. 

My goal with this script is to put the analysis function the SQL query itself. Each query will output a different part of the puzzle. The script itself just compiles the data into a CSV or SQLite database for viewing and filtering. While this database/spreadsheet can get very large, it is still more efficient that running queries on multiple databases and compiling the data into a timeline manually.

Because this script is all based on investigator provided queries it is highly customizable. If an investigator only wants health data, they can elect to run only those query modules. Each query can be customized by the investigator relatively easy, if you don’t need that column – remove or comment it out! I’ve uploaded many queries that I think most investigators would find useful. It is my hope that other investigators create their own and share them with the community.

How

The script is a simple Python script that intakes what I’m calling modules. Each module is a single SQL query that pulls out specific data from a database. The module will also have some metadata about what the SQL query

The module is a text file that contains a few required items:

  • DATABASE – The exact name of the database to perform the SQL query on.

  • ACTIVITY – What this particular record is categorized as.

  • KEY_TIMESTAMP – The timestamp to be used as the key for timelining.

  • SQL Query – The query that is performed on the database. They query should extract one specific type of record from the database, thus a database may have many modules for very specific outputs.

Depending on what the user is looking for they can run one, some, or all the modules and it will output to either a CSV or SQLite database file.

Example Usage

The script is a simple python script that only takes only a few arguments. 

python apollo.py -output {csv, sql} <modules directory> <data directory>

There are two output options, a CSV file or a SQLite database. Please let me know if other outputs are required. Following that, the path to the module’s directory and the path to the data directory. The data directory can be a single directory full of the databases needed to parse or a full file system dump – the script will find the databases by name in the module.

An example of the output is seen below. Each SQL query run will have different output for that particular query and database in the output column. In the example we see everything from health steps/distance, to location, to application usage. The Key column contains the timestamp that each record is organized on, the Activity contains the type of record. The database and module columns contain which database and module parsed that information.

Challenges 

One of the main challenges with these Pattern of Life databases is access. Most of the really good forensically useful POL data is not easily accessible, particularly with iOS devices. With macOS devices we may need to deal with FileVault encryption or database level encryption. This script assumes you have good data to work with. Some databases may be available some may not be.

Feedback

While I primarily created this script for my use (don’t we all), I am open to feedback. If instead of using ConfigParser module files you want something else, let me know. If you need different output formats, let me know. I will consider all feedback.

I would appreciate all the help I can get. I’ve primarily tested these queries with a focus on iOS 11, however I know many will work on older versions and some have been tested with available data from iOS 12 (iOS Health). I’ve also tested running the script on macOS with Python 2.7 installed, it may not run as expected on other platforms. (FWIW: I will upgrade to python3 when macOS does.)

The script was just updated to be more efficient by Sam Alptekin of @sjc_CyberCrimes. Sam made the script much faster when running against full file system dumps. He was able to take it down from hours to run to mere minutes. Thanks Sam!

The Next Eleven Days

Each day will have a different topic that will guide you through the usefulness of the APOLLO framework. I focus primarily on iOS in these articles, but many of the queries can be ported over to macOS as well. I do intend to work on this in the future however I will discuss more on improvements later.

I will cover all sorts of topics in the next couple of weeks.

  • Device State

  • Media

  • Health

  • GUI Artifacts

  • Network and Communications

  • Connections

  • Application Usage

  • So much more!

Get APOLLO here and take it for a spin!

Day 2: On the Second Day of APOLLO, My True Love Gave to Me - Holiday Treats and a Trip to the Gym - A Look at iOS Health Data

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

Day 4: 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

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

Day 6: On the Sixth Day of APOLLO, My True Love Gave to Me – Blinky Things with Buttons – Device Status Analysis

Day 7: On the Seventh Day of APOLLO, My True Love Gave to Me – A Good Conversation – Analysis of Communications and Data Usage

Day 8: On the Eighth Day of APOLLO, My True Love Gave to Me – A Glorious Lightshow – Analysis of Device Connections

Day 9: On the Ninth Day of APOLLO, My True Love Gave to Me – A Beautiful Portrait – Analysis of the iOS Interface

Day 10: On the Tenth Day of APOLLO, My True Love Gave to Me – An Oddly Detailed Map of My Recent Travels – iOS Location Analysis

Day 11: On the Eleventh Day of APOLLO, My True Love Gave to Me – An Intriguing Story – Putting it All Together: A Day in the Life of My iPhone using APOLLO

Day 12: On the Twelfth Day of APOLLO, My True Love Gave to Me – A To Do List – Twelve Planned Improvements to APOLLO

Slides and Script! From Apple Seeds to Apple Pie & Introducing APOLLO: The Apple Pattern of Life Lazy Output'er

I had the privilege and honor to present at the first ever Objective by the Sea Mac Security Conference yesterday in Maui (hardship, right?). It was only the first day and it was absolutely spectacular, I may have to make this one a regular! I can easily recommend attending this conference.

I presented From Apple Seeds to Apple Pie - an Apple Pattern of Life talk (mostly focused on iOS devices). You can find the slides in my Resources section.

I also just released a (very) beta version of APOLLO (Apple Pattern of Life Lazy Output’er) on my GitHub page. The TL;DR of the script: Take all the creepy databases that Apple writes events to, perform individual SQL queries on them to pull out investigative useful data, and combine them into another SQLite database for easier/quicker analysis and correlation.

This script and its modules are still in the testing phases so please be careful when using this on real cases. Expect more modules and testing to be released, I’m holding some back due to some timestamp issues and other are partially written up.

Script Update - Mac MRU Parser v1.5 - Added Volume Analysis Support and Other Stuff!

Get the script here!

Added volume analysis support for the following plists. These are not really MRUs but it could be damn useful to gather this info.

  • Sidebar List plist [10.12-] - /Users/<username>/Library/Preferences/com.apple.sidebarlists.plist
  • Favorite Volumes SFL2 - [10.13+] /Users/<username>/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.FavoriteVolumes.sfl2
  • Finder Plist - /Users/<username>/Library/Preferences/com.apple.finder.plist
    • I was parsing FXRecentFolders Key, I've added FXDesktopVolumePositions Key
    • FXDesktopVolumePositions has a volume creation timestamp embedded into the "file" name for the volume (highlight in yellow below). This has been extracted and converted to human readable time (highlight in orange below).

Thanks to @4n68r for pointing out broke stuff (and for using the script!)

  • The ICNS Icon export function was also fixed.
  • Fixed support for some *.sfl2 files that were cranky and had no names.
  • Documentation/Spelling