Initialization vectors: iOS Snapshots Triage Parser & working with KTX files

Sunday, September 29, 2019

iOS Snapshots Triage Parser & working with KTX files

Short version

Collection of scripts that assist with parsing iOS snapshot bplists in the applicationState.db data store. Snapshot images show what was last on screen for a particular app before the app is closed or sent to the background. The research behind this artifact was conducted by Geraldine Blay (@iam_the_gia). For details on the meaning and importance of these files read her awesome write up here:
https://gforce4n6.blogspot.com/2019/09/a-quick-look-into-ios-snapshots.html
Script download:
https://github.com/abrignoni/iOS-Snapshot-Triage-Parser
Script purpose and workflow:
  1. Run SnapshotImageFinder.py to identify iOS snapshot images and extract them from a targeted iOS file system extraction directory. These files end with @3.ktx or @2.ktx.
  2. Extract the macOS Automator quick action from the ktx_quick.zip file. With it convert all the .ktx files extracted in step #1 to .png format.
  3. Run SnapshotTriage.py to extract, parse and match the images with the snapshot metadata contained in the extracted bplists from the applicationState.db datastore. This script accepts 2 parameters, the directory where the applicationState.db is located and the directory where the .png files are located.
  4. After execution of the previews steps a triage report directory will be created containing the extracted bplists and iOS snapshot reports in HTML per app. 
Full details with screenshots are below in the long version section of the blog.

Results:

The following image is of a iOS Snapshot report generated SnapshotTraige.py for the Uber app. It is of note that these snapshots can contain chats, images, maps, anything the app was doing at the time it was taken out of focus and/or sent to the background.

iOS snapshot for the Uber app.

Long version


The importance on being able to recover what was on screen when an app was last used is pretty clear. But beyond the evidentiary value of the images and when where they generated this speaks to the pressing need to teach our first responders to limit interactions with a suspect/target device. By manipulating the device on scene this data might reflect the first responder's fingering around instead of data of value for the case.

The functionality that enables the creation of such screenshots in iOS devices is called Snapshots. Android has the same functionality and it is called Recent Tasks. I made a script to parse these, it is located here:
https://github.com/abrignoni/Android-Recent-Tasks-XML-Parser
I became aware fully of the snapshot functionality in iOS by my dear friend and colleage Geraldine Blay. You can and should follow her on Twitter here:
@i_am_the_gia
Her research can be found on her blog post here:
ddsdfdf
I have made a script that automates the extraction of these snapshots and their timestamps. In her blog post you can find the paths and structures needed to validate by hand the automated output from my script.

The script to parse the iOS snapshots is located here:
https://github.com/abrignoni/iOS-Snapshot-Triage-Parser
Script prerequisites:

To parse the iOS snapshots one needs to be working with an iOS full file system extraction. For details on iOS file system extractions see the acquisition section of the following blog post:
https://abrignoni.blogspot.com/2018/08/finding-discord-chats-in-ios.html
Since the app images are in ktx format from Apple, a macOS computer will be needed. After much searching and asking around I have yet to find a python library or CLI tool that can convert ktx images to png. This is necessary since ktx files are not a widely supported image format. Our script output will produce a more universal form of output, png images in html. To do the ktx to png conversion we will use an Automator Quick Action in macOS.

The scripts and detailed workflow:

1. SnapshotImageFinder.py
Used to extract snapshot ktx files from the iOS file system extraction. Usage is really simple:

usage: SnapshotKtxFinder.py [-h] data_dir_to_analyze

This script will recursively go through and pull out all the relevant ktx files. It will place them in the FoundSnapshotImages directory. Here is the CLI output for some sample data I provided to it:


Searching for iOS Snapshot images.Please wait...
Snapshot ktx files moved to: /Users/abrignoni/Desktop/iOS-Snapshot-Triage-Parser-master/FoundSnapshotImages
Snapshot ktx files moved total: 485

2. ktx_quick.zip

This zip file contains a macOS Automate Quick Action that will convert the ktx files to png files automatically.

First unzip the file on your macOS computer and click the unzipped file. When asked if you want to install say yes. If this gives you the heebie-jeebies use Automate to create the conversion file. After install you will see the following:

Installed ktx_quick 
By installing we have the ability to right click on any directory and from the context menu execute our quick action. For our purposes we will do so on the FoundSnapshotImages directory previously mentioned.

Notice the option in blue.
As the action is being run you will see a progress gear on the right side of the top side screen bar.

Progress
When done the converted_snapshots directory will be created on your desktop. Take that directory and place it in the same directory where the python scripts are located.

From here:

At the desktop.
To here:

Inside the directory for the scripts
3. ccl_bplist.py

This module is used to deserialize NSKeyedArchiver bplists. Thanks to Alex Caithness who came up with this module. It saves us a lot of headaches. I added his module to my repo for convenience. It can be downloaded directly from the source here: https://github.com/cclgroupltd/ccl-bplist.

4. SnapshotTriage.py

All output from this script will be created in a timestamped named folder. This allows us to run the script multiple times with any overwriting issues. Thanks to Phill Moore (@phillmoore)for the idea.

All script output directories will be in these.
The script will first locate the applicationState.db file. The following query will be used to identify the blob fields that contain the iOS snapshots bplists.

SELECT
application_identifier_tab.id,
application_identifier_tab.application_identifier,
kvs.value
FROM kvs, application_identifier_tab, key_tab
WHERE application_identifier_tab.id = kvs.application_identifier
and key_tab.key = 'XBApplicationSnapshotManifest'
and key_tab.id = kvs.key

The bplists will have the image filename, bundle id name, and the timestamps of the images. With the filename it is easy to connect the exported images to the corresponding app name/ bundle id and timestamps. As mentioned in previous blog posts bplists sometimes can be incepted. This means a bplist is inside another bplist. This case is one of those. The script will extract the bplist from the database and save the incetpted bplist in the ExtracteBplistFirstLevel directory. After doing so it will extract the internal bplist and save those in the ExtractedBplistSecondLevel directory. The idea of doing so is that it will allow the examiner to validate the whole process step by step as well as provide a way to execute third party tools over the extracted data.

A third folder will be created named Reports. In this folder there will be an HTML for every app on the device that had snapshot data. As stated previously these directories are inside the SnapshotTriageReports_timestamp named directories.

SnapshotTriage.py created directories
When the script runs one can see the bplists per bundle id being processed.

Script running.

The usage for the script is as follows:

Alexiss-MBP:iOS-Snapshot-Triage-Parser-master abrignoni$ python3 SnapshotTriage.py -h
usage: SnapTriage.py [-h] data_dir_snaps data_dir_appState

iOS Snapshot KTX Traige Parser
 Parse iOS snapshot plists and matching ktx files.
positional arguments:  data_dir_snaps     Path  to the Snapshot images Directory  data_dir_appState  Path to the applicationState.db Directory.
optional arguments:  -h, --help         show this help message and exit


The first positional argument is the directory where the png files are located, the converted_snapshots directory. The second positional argument is the directory for the full file system extraction or a directory that has the pertinent applicationState.db file. After the script is done running it shows how many snapshots were processed.

Total apps with snapshots.
Reports

The reports directory has HTML for all the apps with snapshots.
Reports
The reports contain all the images and timestamps found in the processed bplists.
The images the HTMLs reference are copied inside the reports directory within the images folder. This lets us copy or move the reports directory and view the images anywhere.

Hve images, will travel.
Sample report

The type data these screenshots records can include text messages, maps, documents, chats, anything that an app can show the user.

iOS snapshot for the calculator app.

The report allows the user to click on the images to view them full screen in a new tab. This is good since some of the images are downscaled or of horizontal orientation.

Super important: The fist timestamp under each image is the ktx file creation time. Some of the images have 2 timestamps per ktx image. We are currently trying to figure out where that 2nd time comes from. I have added it to the report in the name of completeness. In order to validate these timestamps, taken from inside the bplist, the examiner can go to the original ktx files and look at the creation times directly for each image of interest.

Conclusion

Thanks again to Geraldine Blay for her research. These artifacts can give context to what the user of the device was doing or seeing shortly before the time of seizure/examination. Also note that not knowing of a scripted or direct way of dealing with ktx files does not mean there is nothing that can be done. With a little but of creativity and help we can achieve our goals.


As always I can be reached on twitter @AlexisBrignoni and email 4n6[at]abrignoni[dot]com.