Wednesday, January 16, 2019

QuickPic for Android - Don't forget external/emulated storage!

QuickPic Gallery for Android

QuickPic is an image gallery app for Android devices that used to be fairly popular before it was taken down from the Google Play Store. Since the app is still available via third-party APK repositories we might still come across it in our case work.


The main reason for this blog post on the QuickPic app is that it illustrates the value of checking related external, emulated, and adoptable storage in Android devices. In this particular app all the databases that track user generated activity were kept outside of the main app directory.

QuickPic app keeps relevant databases in the following directory:


SQLite Queries

Queries that can be used as to extract pertinent data can be found at:

The following queries are provided:
Quick analysis of SQLite databases

The app provides thumbnails for all the images it scans as seen in the next image.
These thumbnails are kept in a database titled thumbs_numeric-value.db where the words in red represent a series of numbers as seen below.

Notice the multiple thumbnail databases
In the image we can see that the databases of interest are named thumb_123904.db and thumb_220900.db. It appears that when one database reaches a particular point (size? directory paths? amount of records? year?) it continues registering thumbnail data in a second database.

The thumbnail databases contains a table named thumbs with the following columns: path, thumb, and modified.

Thumbnail database content
The columns provide the path where the original image is located on the device, a modified timestamp, and a thumbnail of the original image. To view the image export the blob within the thumb column and rename it with their proper extensions as seen in the path column. The usefulness of having a copy of the data in thumbnail form is apparent. This is even more so when the examiner has access to multiple data backups, be it by Android itself or by third party backup apps, of the same device.

When the user presses one of the thumbnails images in the application, in order to view a larger version of the image, the app keeps track of such activity in the preview database. The database can be seen in the cache directory image seen above. The preview database contains a table named cache with the following columns: document_id, _data, _size, accessed_time, and last_modified.

Preview database
As seen previous image the document_id columns keeps the location path for the original image. the _data column keeps the location path for a copy of the original image that was selected by the user. These images are kept, as seen in the path, in the .preview directory. The preview images themselves have alphanumeric names with no extensions. Just like the images in the thumbnails database one can add the proper extension to the preview files to view them. The rest of the fields are for preview image size, accessed time and last modified time. 

It is of note that files in the .preview directory tell us that the user had to select/press the thumbnail of a media item of interest in order to view a large version of it. It requires user interaction. 


This quick analysis made me think of how many times we can be in a hurry and overlook related app directories that are contained in SD cards or emulated storage space. Databases that tell us about user intent, what was selected for viewing, and what was actually seen can be missed if we don't make it a habit to always look for unfamiliar app ids in app directories AND emulated/external storage. A one minute check can provide us with amazing returns we did not expect. 

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

Sunday, January 6, 2019

iOS Mobile Installation Logs Parser

In the last two blog posts I wrote about ways of obtaining a list of currently installed apps and their corresponding app directories from an iOS file system extraction. My usual method is to query the contents of the applicationState.db file to find the app bundle id and what directory GUID like name corresponds to it. By finding the proper directory one can focus on the data stores it contains for parsing of user generated data when our forensic tools are not aware of them.

On my second post I received great feed back from Sarah Edwards. She pointed me to the contents of the mobile installation logs in iOS.

Cool stuff!
I immediately wondered if there was a script that could parse those logs for the data I was looking for. After asking Sarah Edwards and looking online I didn't find any.

I'll do it.
The link below is for a python script I made that parses the mobile installation logs.

These logs contain a lot of information. Currently the script only extracts the following events:
  • App install successful with date and time.
  • App container made live with date, time, and path.
  • App container moved with date, time, and path..
  • App destroying container with date, time, and path.
Here is a sample screen of how the logs look as taken from the device. The image has been zoomed out which could make it harder to read unless the preview image is clicked.

Lots of data.
The script is really simple to use.
  1. Have Python 3.6.4 or newer installed.
  2. Extract the logs from the /private/var/installd/Library/Logs/MobileInstallation/ directory.
  3. Place the script in the same directory as the extracted logs.
  4. Execute the script via CMD.
The screen, after done, should look something like this:

Run complete. Some stats.

The script will produce one SQLite database called mib.db, a directory named Apps_State, and a  directory named Apps_Historical.

Script with generated items.

The SQLite database holds the extracted information from the lines of log data. The script queries the database to produce the contents within the two directories.

The Apps_State directory can have two files within it. These are named InstalledApps.txt and UninstalledApps.txt. The contents reflect the name of the text files. Here is a sample image of InstalledApps.txt content:

List of installed apps.
Having this list handy is really useful since it can be used to compare the currently installed apps within the file system image that might have been missed by our third party forensic tool of choice. 

If one would like more context in regards to when the app was installed and where the app directory is located the Apps_Historical directory has all that information per app.

A txt file for every app.
Here is a sample of the historical information regarding an installed app.

Historical events for
Notice the report has a timestamp for every event. The scrip puts the most recent events at the top so the current path for the application directory can be at or near the top.

Here is a sample of historical information regarding an uninstalled app.

Historical event for org.videolan.vlc-ios
 Like the previous report there is a timestamp for every entry and events start with the most recent at the top. These report are useful if one wants to determine when an app was uninstalled or if a current app was uninstalled and then reinstalled multiple times.

Historical events for org.coolstar.electra1131
Notice the multiple 'Destroying', 'Made', and 'Install Successful' entries in the report. Again the most recent ones are at the top.

As seen above the script's output is responsive to the original requests of installed apps with corresponding app directory paths. It goes further by identifying uninstalled apps and by providing timestamps and historical app event aggregation.

By looking at the logs there seems to be further areas where the script can be improved. This is my soon to-do list:
  • Report on 'detected reboot' and other log entries that indicate system state as opposed to particular app states.
  • Add 'updated bundle entries' for 'container made live' context in the historical reports.
  • Add 'attempting delta patch update' and app version information in the historical reports.
  • Add 'uninstall requested' and 'uninstalling identifier' in the historical reports.
I can't thank enough my colleague @i_am_the_gia for testing out the script on her data sets and Sarah Edwards for making me aware of the logs.

If anyone gives the logs a look and finds further items to report on or wants to give other feedback I can, as always, be reached on twitter @alexisbrignoni and email 4n6[at]abrignoni[dot]com.