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:
Script download:
Script purpose and workflow:
  1. Run 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 file. With it convert all the .ktx files extracted in step #1 to .png format.
  3. Run 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.


The following image is of a iOS Snapshot report generated 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:
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:
Her research can be found on her blog post here:
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:
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:
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:

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

usage: [-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


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.

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

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:


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.

FROM kvs, application_identifier_tab, key_tab
WHERE = kvs.application_identifier
and key_tab.key = 'XBApplicationSnapshotManifest'
and = 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. 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 -h
usage: [-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.

The reports directory has HTML for all the apps with snapshots.
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.


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.

Saturday, September 14, 2019

Vendor binaries and data stores: io-prefetcher.db

Short version

Certain Android devices that use Qualcomm processors contain vendor install binaries and libraries that create a SQLite database which keeps track of the name, last use timestamp, and use count of apps on the device.

Vendor library name and location:
Database name and location:
The SQL query used to extract the data can be located at the following URL:
It is of note that the app data being tracked does not encompass all app activity, only the ones gathered by the vendor binary while its service is enabled. A more complete characterization of app activity can be gathered from the UsageStats.xml files if available.

Testing and analysis platform

Long version

Since the beginning Android devices where designed to allow customization by original equipment manufacturer (OEM) vendors. Such capability permits a company like Samsung to sell Android devices with a different user interface that the one that comes with the stock (direct from Google) Android operating system. This ability is also used by hardware vendors for firmware updates and diagnostic purposes.

In order to enable this functionality modern Android devices have a partition named vendor that stores these 3rd party libraries and binaries. A short and to the point explanation of this concept can be found here:

An interesting example of this capability  can be seen in the creation and use of the io-prefetch.db SQLite database. Some Samsung devices that use Qualcomm hardware track device application use and frequency via a SQLite database named io-prefetcher.db. This database is located, as seen in the next image, in the userdata/vendor/iop/ directory.

Files in these directories tend to be related to hardware matters.
The table io_pkg_tbl contains the following columns:
  • pkg_name
  • pkg_last_use
  • pkg_use_count
The following image shows some sample content from the database.

An interesting factoid of this file is that its creation date matches a recovery event from the device data contained in the following directory and log file: recovery/last.log.10. This, plus the fact that the database did not reside in the userdata/data directory, made me think that the database had something to do with a native functionality of the device. When I saw some of the other files in the vendor folder I assumed that the native functionality had to do with Qualcomm hardware in some way. A string search of the forensic image for table names used in the database led me to the following directory and file: vendor/lib/ The QTI nomenclature stands for Qualcomm Technologies Inc.

Notice the file resides in the vendor partition. These .so files are binaries/libraries. For a full explanation see the Android Concepts document here: Note that if you look at some of these .so files in a hex editor the file signature is ELF. For details on that see here:

Vendor partition and target directory

The following image will show some of the ASCII content of this file. Pure SQL statements that correspond to the creation, use, and update of the io-prefetcher.db file.

In order to have a better understanding of the file I used a simple online decompiler to look at additional ASCII values. 

Notice the call to proc
I found the call to proc, among some others, to be interesting in regards to how the data is populated in the database by interrogating the system about what processes are running at the time of query. For details on what proc is see here:

Why is this of any importance?

When I focused my attention at the pkg_last_use values I noticed that these matched entries in the Android UsageStats xml files. As way of background these xml files keep track of app user activity. For details see here: Every pkg_last_use value I checked had a MOVE_TO_FOREGROUND corresponding value in UsageStats. The timestamps was the same or a second off. 

This is the value for one the Facebook packages in the io-prefetcher file:

Facebook pkg_last_use timestamp

This is the value at the same timestamp in the UsageStats xml file:

Facebook UsageStats timestamp

With all this being said be aware that the pkg_last_use date might not be the last time UsageStats has user generated app activity. Also know that the pkg_use_count values per package are less than the ones kept in UsageStats. It is obvious then that UsageStats gives us a more detailed and complete picture of app activity. That being the case, why bother with this database?

Looking at the contents of io-prefetcher.db might be of use due to the following:
  1. Not all examined devices will have UsageStats available. 
  2. The database will keep entries for installed as well as deleted apps.
  3. Even though there is no way to validate all the entries in the pkg_use_count field one can use these values as information to quickly determine what apps where of most interest to the user. This can refocus examination priorities or determine if person that is denying ever using an app is telling the truth.
Important to note that analysis like the previous will have limitations that will only come to light via testing. For example to simply assert that the pkg_use_count has all the times an user executed an app or that it exclusively marks user generated activity can lead to serious error. Recovered data can be informative even if incomplete or not totally understood as long as we don't try to make it say more than what it actually does. I think of it as intelligence that will drive further investigative steps.

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

Wednesday, August 21, 2019

iOS 11 & 12 Notifications Triage Parser

Update 9/21/19: Parser now so processes iOS 11 notifications. See usage example at github link below. 

Short Version

Introducing a Python 3 script that looks for the UserNotifications folder in iOS 12 full file system extractions and parses the iOS notifications to easily triage their content. The script detailed below is a technical application of the research done at by my friend Christopher Vance that he kindly shared with me before making it public. Check out his blog on the topic at:
Script download:
Script purpose:

  1. To parse the iOS notifications plists for every app that has the functionality enabled. 
  2. Make a report of the plist contents giving the user the ability of hiding non-human readable, repeatable, and well know data by pressing a button on the HTML report.
  3. Report on and export any incepted bplists (full bplists found within a plist) for further analysis.
Script reason:
  1. As stated in there can be a wealth of data in the iOS screen notifications to include snippets of user generated content like chat messages, images received, and distinct alerts that might not be accessible in other ways.
  1. Python 3.
  2. Full file system extraction of an iOS 12 device or the UserNotifications directory. If extracting the directory itself for processing be aware that the script depends on the UserNotification directory (where notifications on iOS are kept) to be at least one level down (or more) from the data directory provided to the script.

Long Version 

When Chris shared his latest research with me I was immediately impressed on how much relevant data is contained in iOS notifications. For further details his blog post above is required reading. In this post I will only go into how to use the script to triage these important plists that seem to be overlooked but shouldn't.

Script usage

After downloading the script and configurations files you should see 4 files in the image.

Scripts and configuration files.


    Used to deserialize NSKeyedArchiver bplists. Thanks to Alex Caithness came up with this module. It saves us a lot of headaches. Added his module to my repo for convenience. It can be downloaded directly from the source here:

    This is where the magic happens. It searches in a specified directory for the UserNotifications directory and when found parses the DelivereNotifications.plist for every app that has notification data.
  3. NotificationsParams.txt

    It contains strings that I consider to be common, unreadable, or repetitive. The items in the list (one per line) are used to determine if they are to be hidden, not eliminated, from the final report. Be aware that the final HTML report has a couple of buttons that allow you to hide or show those fields as needed. To add more string to hide just add a new line to the text file. One string per line.
  4. script.txt

    Contains the javascript necessary to enable the hide/show functionality in the HTML report. It gets added to each report at processing time.

The script only has one parameter, the data directory to be parsed. See the help below.

When the script runs it tells you what notification is parsing and if a bplist was found within the plist. If found it will tell you that it was exported.

See the highlighted section above that shows a bplist exported. When done it also advises how many plist were processed, how many exported bplist, and how long processing took.

After the script runs a report directory will be created in the same location where the script resides.

As seen the report directories are timestamps so the script can be run multiple times and each time it will generate a new report directory. Within the directory each app has its own unique directory named after the app's bundle id.

Each app will have a report and exported bplist if any exists. For the screen time notifications in this data set one sees the following:

Each HTML report has a header and the Hide/Show buttons on the top.

Let's zoom in a little on the buttons.

As Christopher explains some of the ASCII values might not be important, unreadable, too much, or are simply repetitive. Hide rows hides them as explained previously by referencing the content of the NotificationsParams.txt file.

It will go from tons of pages to something like the following:

This is the same report. It has hidden a lot of repetitive data. Important note. It is worthwhile to always look at the full report if the app is important to the case. The report is only for triage purposes and will always require validation after execution. This is even more true when talking about the contents of within a plist. In some cases is either data that is not relevant or unreadable. In many cases it can contain a full bplist in them. The report deserializes this data and lets you read it. It is hard to read due to a lack of proper formatting but at least it will let you know if further analysis is warranted. Here is how a bplist in an field would look on the report.

Yes, hard to read but still it can be read. If anything pertinent is found then go and take the exported bplist and use any viewer for further and proper analysis.

Here is an example of the exported bplist and how a third party viewer shows you the data with ease.

Future work

As stated in Christopher's blog post there are additional data sources in the iOS notifications directory. I plan on making parsers for these as well. Like everyone else on this floating rock in space, when can have to many things but the thing we will never have enough of is time. If only the days had more hours and our bodies less need for sleep.

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

Saturday, August 10, 2019

ARTEMIS - Android support for APOLLO

Short Version

Introducing a Python 3 script, with corresponding modules, that extend Sarah Edwards' APOLLO framework support to Android devices.


ARTEMIS (Android Review Timeline Events Modular Integrated Solution)
  1. Python 3 script that parses Android UsageStats XML files for automatic ingestion by APOLLO. 
  2. Add pattern of life analysis in Android devices to APOLLO.
  3. Continue to evolve ARTEMIS so it can parse additional non APOLLO supported data sources for APOLLO ingestion and analysis.
New APOLLO modules for Android devices:
  1.  UsageStats 
  2.  ContextLog 
  3. SamsungMembersDeviceEvents 
  4. SamsungSmartManagerUsageLog 
Converted the original Python 2 APOLLO script to Python 3. Works on Windows 10.
 Full file system extraction of Android device will produce best results.
ARTEMIS, updated APOLLO, and Android APOLLO modules can be found in the following fork/branch: here:
Long Version 

When Sarah Edwards released APOLLO on November last year I was highly impressed by the importance of aggregating specific pattern of life data (PLD) from iOS devices in a timeline format. Since then I have been looking for PLD in Android devices that can provide the same type of insight that APOLLO aggregates for iOS devices. This search motivated me to create the DFIR SQL Query Repo, a UsageStat XML parser, and multiple Magnet Forensic Artifact Exchange custom artifacts. Yesterday as I was driving home from work I thought about how to aggregate all those PLD artifacts in an APOLLO like format. Then it hit me, not a car but the idea of feeding non-sqlite Android files to APOLLO for parsing and analysis. Hence ARTEMIS was born.


If you are not familiar with APOLLO you will be well served to do so. It can be found here. The Python 2 script has been instrumental in many DFIR cases. In order to extend the functionality I had to port it to Python 3. The only issue with APOLLO was that it was coded in Python 2 which will reach end of life by the end of 2019. For reasons unknown to me I couldn't make APOLLO work in a Windows environment even if I had Python 2 installed. I depended on my trusty Apple computer but that required moving data to and from my main DFIR boxes. By coding APOLLO in Python 3 my Windows machines can play nicely with it. Also since I code in Python 3 I could integrated with my nascent ARTEMIS idea.


First order of business was to convert APOLLO to Python 3. Thanks to the Python Modernize project it was trivial to do so. With APOLLO properly converted the next step was to find a way to prepare the largest PLD source in Android for APOLLO ingestion.

One of the main data sources APOLLO leverages for PLD in iOS is the SQLite knowledgeC database. There is no analogous SQLite database in Android. Thanks to Jessica Hyde's research I was made aware that similar PLD information is contained in the UsageStats XML. In order to have APOLLO ingest UsageStats data it had to be converted from XML to SQLite. ARTEMIS purpose is to do this conversion.

Last step was to create a module so APOLLO could parse this new SQLite database. I created a module for that purpose. Also in order to avoid having to call to scripts and move things around manually I use most of the same arguments APOLLO uses so I can have ARTEMIS hand off processing to APOLLO without user intervention assuming both scripts are located in the same directory.


The following images will provide a visual on the results the user can expect ftom the APOLLO/ARTEMIS workflow.

  1.  Have APOLLO and ARTEMIS in the same directory
  2. ARTEMIS will use the YOLO option in APOLLO as default since APOLLO lacks any Android specific arguments. 
  3. Place your Android data sources aggregate in a directory. ARTEMIS, like APOLLO, will not parse forensic images. It will search logical files only.
  4. Place APOLLO modules that support your Android specific SQLite databases. At a minimum include the UsageStats module.
  5. Run After done it will call to finish processing.
The following image shows both scripts in the same directory. Your Android logical files will be located in the Data directory. The Android APOLLO modules are in the Artemis_Modules directory. The modules in the Artemis_Modules directory are a product of the research presented at the SANS DFIR Summit 2019. For details on the data these modules parse see here.

Both Python 3 scripts in the same directory 
ARTEMIS uses almost all of the same arguments as APOLLO.


Execute the following command:
python -o sql Artemis_Modules Data
UsageStats being processed and turned into a SQLite DB
 When ARTEMIS is done with the UsageStats it will call APOLLO to parse the data stores.

Yolo option selected by ARTEMIS
As seen at the end of the previous image the timeline will be found in the apollo.db file. I used the following SQL statement:

datetime(Key/1000, 'unixepoch', 'localtime') as time,
FROM APOLLO order by time asc

End product
It is awesome to see how multiple PLD sources come together to paint a more rich picture of what activity transpired on a device at a particular time.

Future development

A big part of ARTEMIS will be to add support for additional Android PLD sources that are not in SQLite form. In the immediate future I will work on having ARTEMIS automate the conversion of iOS mobile installation log data into a SQLite format for APOLLO ingestion.

Obligatory WARNING!!!!!

The output of these scripts is for lead purposes only. Verification by you is not optional. Be aware that there is always danger involved with timestamps from multiple disparate sources. Always verify the provenance of the data and how the timestamps related to each other.

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

Friday, July 26, 2019

Android - Samsung Traces of Deleted Apps

Short version

The following Android application artifacts were presented as part of the Traces of Deleted Apps presentation by Christopher Vance and Alexis Brignoni at the SANS DFIR Summit 2019 in Austin, Texas on July 26, 2019. Presentation slides will be available at
  • Samsung Members - Keeps a list of an app's display name, package name, is it system, and last used time in the following location, database, and -> table:
data/ -> android_app 
The app also keeps information on the following events: type (network, install, power, alerts), type values, and creation time. These are kept in the following location, database, and -> table:
data/ -> device_events
  • Samsung Smart Manager - Keeps a list of apps that have crashed during use. These are kept in the following location, database, and -> table:
data/ -> crash_info, excluded_app 
The app also keeps a list of app usage times to include package name, class name, start time and end time. These are kept in the following location, database, and -> table:
data/ -> usage_log
  • Samsung Context Log - Keeps a list of app usage to include timestamp, time offset, app id, app sub id, start and stop time, and duration in milliseconds between start and stop times. These are kept in the following location, database, and -> table:
data/ -> use_app
These artifacts keep the previously described data even after an app is deleted from the device.

Slight addition to the short version

The artifacts described previously are tied to factory installed apps on Android Samsung devices. These can be used for pattern of life analysis, app usage timelining, as well as indicators of app presence on a device after the app has been deleted.

The SQL queries used to extract the data can be located at the following URL:
 Within the DFIR SQL Query Repo go to the following locations:
  • Samsung Members
These will be available in Magnet Forensics Custom Artifact Exchange after final approval.

Longer addition to the slight addition to the short version

The following screenshots are examples of the type of data contained in these artifacts:

  • Samsung Members

com_pocketgeek_sdk_app_inventory.db -> android_app

App Inventory
com_pocketgeek_sdk.db -> device_events

Events. Notice the Package Installed Event.

  • Samsung Smart Manager
sm.db -> crash_info

Crash apps and time of crash
lowpowercontext-system-db -> usage_log

  • Samsung Context Log
ContextLog.db -> use_app

Notice how the data types being store are almost the same as the ones kept by usage stats.

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

Wednesday, June 12, 2019

Android - Samsung My Files App

Short version

Samsung mobile devices keep a list of stored media files in the following location and database:
These same devices also keep track of recent accessed media in the following location and database:
The following queries at can be used as templates to extract data from the aforementioned databases.

  • FileCache.db
    • Table: Filecache
    • Fields: storage, path, size, date, latest_date
  • myfiles.db
    • Table: recent_files
    • Fields: nane, size, date, _data, ext, _source, description, recent_date
Long version

Samsung devices come preinstalled with the Samsung My Files app. The app can also be used on other branded devices by download and install of the app via the Google Play store.

Samsung My Files app
The app description tells us the main software features.
[Key features]- Browse and manage files stored on your smartphone, SD card, or USB drive conveniently..Users can create folders; move, copy, share, compress, and decompress files; and view file details.
- Try our user-friendly features..The Recent Files list: Files the user has downloaded, run, and/or opened.The Categories list: Types of files, including downloaded, document, image, audio, video, and installation files (.APK)
Stored files analysis

The My Files app directory data resides in the data/data/ directory as seen in the next image.

App directory contents
Within this directory the SQLite FileCache.db file can be found. In the FileCache table one can find information on stored media to include path, size in bytes, date timestamp, and latest timestamp.

A simple query can be produce to extract this data. One can be found here.

Recent files list analysis

Within the same database directory one can also find the SQLite myfiles.db file. The recent_files tables keeps information on recently accessed files as explained in the app description from the Google Play store. This table tracks of file name, size in bytes, data, path, extension, source, description and recent date.

A simple query can be produced to extract this data. One can be found here.

Why does this matter?

A list of files as recorded by the app can give us clues on what files once existed on the device if these files were deleted before the usage of the My Files app. The utility of the recent apps list is even more apparent since we can correlate particular real world events with the last usage of pertinent media on the device. User generated artifacts should be of interest to the analyst, even more so when they intersect with other parts of the case we are working. Only by knowing that such artifacts exist can we make use of them.

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