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:
vendor/lib/libqti-iopd.so
Database name and location:
userdata/vendor/iop/io-prefetcher.db
The SQL query used to extract the data can be located at the following URL:
https://github.com/abrignoni/DFIR-SQL-Query-Repo/
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: https://android.stackexchange.com/questions/205200/what-happens-if-vendor-partition-is-corrupted.

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.

io-prefetcher.db
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/libqti-iopd.so. The QTI nomenclature stands for Qualcomm Technologies Inc.

Notice the libqti-iopd.so file resides in the vendor partition. These .so files are binaries/libraries. For a full explanation see the Android Concepts document here: https://developer.android.com/ndk/guides/concepts.html. 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: https://en.wikipedia.org/wiki/Executable_and_Linkable_Format.

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: https://linux.die.net/man/5/proc

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: https://abrignoni.blogspot.com/2019/02/android-usagestats-xml-parser.html. 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.