Google Keep Notes
___________Google Keep Notes_______________________________________
While working on a case recently, I came across the Google Keep Notes application installed and utilized on an Android mobile device. Both of the commercial parsing tools that I was using to analyze the data displayed the timestamps of the notes and the title of the notes but no note body was present in the parsed data.
So, I just check marked everything in the case created a Reader/Portable Case, and sent the data out. Because if the tool doesn’t parse it, it doesn’t exist, right? Wrong.
I followed the source file which is a SQLite database named keep.db. Inside of the database is a ton of additional data including the body of those notes!
How Google Keep Notes Work: Google Keep boasts the capability to add notes lists and photos to Google Keep. They have the capability to record a voice memo and Keep will transcribe it so you can find it later. The Google Keep notes are shareable and allow you to add a “collaborator” who can add to your notes.
Research based on Google Keep Notes version: 5.24.442.02.90
Test device utilized: Google Pixel 6 running Android version 15 (SPL 11/15/2024)
Extraction Tool: UFED4PC v7.70
Type of Extraction: App selective used to extract the Google Keep Notes data only
Tools used to perform additional analysis: DB Browser for SQLite
Where to Start: I started by going through each and every table in the SQLite database. Kept notes on what I was seeing in each table, what I thought was potentially important information to pull out of the database and what commonalities exist in each of the tables. The data deemed important included:
- time_created (Time Created)
- time_last_udated (Time Last Updated)
- user_edited_timestamp (User Edited Timestamp)
- title (Title)
- c0text (Text)
- last_modifier_email (Last Modifier Email)
- name (Account Name)
- file_name (Attachment Name)
- is_trashed (Deleted)
The columns above were located in several tables:
- text_search_note_content_content (where the text or body of the note is located)
- tree_entity (where the timestamps, title, and deleted status are located)
- blob (where the attachment filename is located)
- blob_node (needed to properly join the attachments with the correct notes)
- account (where the user account name is located)
How the Data Comes Together: I now have 9 artifact details that I would like to include in my report that are found in 5 different tables. The next step is locating the Primary Key for each of those tables. The one column that is used to join the table to another table to properly display the data in a readable format presentable for your case.
The _id in the tree_entity table is what is joined with the docid in the text_search_note_content_content table
In the text_search_note_content_content table, the docid is used to join the c0text to the appropriate notes in the tree_entity table
The account _id is joined with the tree_entity account_id
The tree_entity_id in the blob_node table is joined with the _id in the tree_entity table
In the blob table are the filenames of the attachments that are part of the notes. The blob_id is key in this table and it is joined with the blob_node, original_id or the edited_id (whichever has the blob_id present)
The attachments indicated in the file_name column are all stored in the following path: /data/data/com.google.android.keep/files/*/image/original/*
Here in the blob_node table are original_id and edited_id which relate with the blob_id in the blob table
Other Interesting Data Found in the Database: The note_changes table records timestamps related to note revisions. In this table the tree_entity_id identifies which note is being revised, the time_ms records the date/time of each revision and the user_id records which user is making the changes to the notes. In the note_changes_chunks table, the actual revisions are recorded. They appear to record each keystroke as a revision to the note. Example: In my note indicated as tree_entity_id 3, the first four words of my note are “This is the body”. With each letter as a revision, these are the first 16 entries in the command_chunk column of the note_changes_chunk table for tree_entity_id 3.
The text_search_extracted_text table contains extracted text from attachments to notes. The below image had the following extracted from the image (among many other text stings):
BEST BY 1925 Bes
100% Satisfaction
Guaranteed or
Your Money Back
THER
PROMISE
JUNE 2024
February 2024
The extracted text is from both the calendar and the container of nuts seen in this image.
The text_search_annotations table reviews the content of the image as well as the searchable text and provides a category for the images related to the notes. Example: The above attachment has the annotation “TV” and “MUSIC”.
What Tools Now Support this New Version of Google Keep Notes: Currently ALEAPP! With the help of Alexis Brignoni, I was able to take my SQLite query and apply it to ALEAPP to parse all of the data above, including the actual note attachments!! Thank you, Alex!!
Future Considerations:
Note Sharing: Google Keep Notes provides that user with the capability to add “collaborators” to notes. A collaborator is added by choosing the note to collaborate on and adding the person or email to share the note with. Once the person or email is added a message is sent or emailed with the following message “Note shared with you: “New note Amy is sharing with heather”.
When a note is shared, the notes that were shared with the device user log a shared_timestamp. The only notes that have that shared timestamp are the notes that were shared with the device user by another party. The shared timestamp was found to not be present for the notes when the device user initiated the share. This shared_timestamp is located in the tree_entity table.
Other data related to the sharing of notes includes information located in the sharing table. Inside of the sharing table is a column named email which is the person sharing the notes email address, a name, role and an is_deleted column.
For the sharing section of the Google Keep Notes, additional table relationships were made with the sharing tree_entity_id column and the tree_entity _id. Joining these two tables produces the additional fields:
- shared_timestamp (Shared Timestamp)
- email (Sharing Email)
- role (creator or collaborator of the note)
I am currently still working on the note sharing portion of the script and will add it to ALEAPP soon! 😊