Android 9 uses the launcher.db sqlite database to keep track of where on the device screens are the app, folders, and widget shortcuts located. For stock Android the database can be found in the following directories depending on the available launcher:
/data/data/com.android.launcher3/databases/ - Quickstep Launcher
/com.google.android.apps.nexuslauncher/ - Pixel LauncherThe relevant forensic data in the table named favorites is as follows:
- Type of shortcut - Icon, folder, widget, etc...
- Unique ID - Integer value
- Name
- Modified time - Epoch timestamp in milliseconds
- Icon image blob - PNG file
Android home screens can be recreated using the following python3 Android Launcher DB parser script:
https://github.com/abrignoni/Android-LauncherDB-Parser/Here are the shortcuts as viewed via the device's screen:
Android screen + shortcuts |
Upper screen |
Lower screen |
It is of note that not all icons are contained within the launcher.db file. Additional details in the long version of the blog post.
Testing and analysis platform
Macbook Pro 14.1
Genymotion Android VM - Pixel 3 XL Stock Android (Quickstep & Nexus launchers)
SQLite Browser
Python 3 - Numpy + Pandas
Long version
A few weeks ago I participated in a capture the flag that included an Android device as part of the exercise. One of the questions wanted us to identify the name of a shortcut in a precise screen location within the Android image. As I looked for the answer that made me think on practical uses for this information. Why would anyone care where and on what screen/s are the shortcuts for apps, folders, and widgets on a mobile device? What could that tells us about our case that we would need? What forensic purpose could there be?
On many Windows OS cases showing what directories, LNKs, and files were located on the desktop painted a clear picture of what the user deemed important enough to have easy access to. It speaks of usage, convenience, and to how the user decides to aggregate data. Can the same be said of Android home screens? I believe so. Consider that folders on Android home screens are created by the user long pressing an icon/shortcut and dropping it on top of another shortcut. The name of the folder is user generated if it is not Unnamed Folder. A lot of user activity to place the items where they are. Same thing with widgets. There is a lot of user interaction to generate a widget and place it on the screen. What if these interactions were timestamped?
As stated in the short version at the top the data resides in the /data/data/com.android.launcher3/databases/ and /com.google.android.apps.nexuslauncher/ directories on stock Android devices. The control of how these screens operate is the responsibility of launcher software.
Google Play Store - Launcher Apps |
Launcher.db
Within the path the database of interest is a sqlite database named launcher.db. The favorites table has all the relevant data in regards to position of items on screen as well as when these items were placed in their locations.
The following image will show the most pertinent fields in the table.
Relevant launcher.db fields |
Blue area = Home screen. User can swipe left or right to access more screens.
Red area = Home bar. Persisten on all screens. Only has 5 spaces available.
Purpose of storage data per field:
- _id - Unique identifier for each app, widget, and folder. Integer value.
- title - Name of the app shortcut or folder. Widgets do not keep a name in this field.
- container - Number identifies the type of screen.
- -101 - Home bar. Bottom row that does not change as the home screens change when you swipe left or right.
- -100 - Home screen container number. If you have more than one screen that will be identified by the value in the screen field.
- Positive integer values - These map to the _id number in the previous field. This is important because it shows the items in question reside in a folder with the corresponding _id number.
- screen - Identifies the homescreen where the apps will be shown. Everytime a new screen is made the number increments by one. The exception is the home bar (container -101.) Apps in the home bar are limited to 5 and each position will be identified with a 'screen' number.
- cellX and cellY - Used to identify the location of the item to be place on screen. It is a 5x5 grid on the home screen and 1x5 for the home bar.
- spanX and spanY - Used to determine the ending location of the item on screen. If it is a widget that covers a 3x3 space the combination of cellX and cellY for the starting point and the spanX and SpanY as the end points will allow the mapping of items that span more than one space of the screen.
- itemType - Used to determine what type of item is on screen. So far I've identified the following:
- 0 - App
- 2 - Directory / Folder
- 4 - Widget that spans more than 1x1 space
- 6 - Widget spans a 1x1 space
- icon - Data blob that contains a PNG of the item to be displayed. Be aware some items, like folder and some widgets, might not have data in this field.
- appWidgetProvider - Widgets do not have values in the title field. This one indicates the bundle id for the app that populates the widget data.
- modified - Timestamp in epoch milliseconds that tells you when the placement of the icon on screen last occurred. If the user moves the location of an item the modified time changes to reflect when the move happened.
By understanding these relationships we can recreate the mapping of all items. For this purpose I created a python 3 script that can be located here:
https://github.com/abrignoni/Android-LauncherDB-Parser/
Python 3 Script
The script usage is very simple.
1- Extract the launcher.db file from the indicated path.
2- Place it in the same directory as the script
Just place the launcher.db file in the same directory as the script. |
EZ PZ |
Notice the timestamp for the run |
All the screens + all the folders/directories |
The script will do the necessary time conversions as well.
Conclusion
As always further testing and validation are never out of place. Although my script manages unknown item types it will be really useful to identify additional ones so a proper type descriptor can be included. Hopefully this type of reconstruction can give the examiner a window unto how the user managed the device, how some might have been group in folders, and maybe which app were of most interest to the user by the fact of being in the home screens and home bar.
As always I can be reached on twitter @AlexisBrignoni and via email 4n6[at]abrignoni[dot]com.