Investigating Session Desktop: Decryption and Artefact Analysis on Windows and macOS

Analysing Session chat application on Windows and macOS
Author: Arun KALACKATTU HARI (06/03/2026)
Session is an open-source, public-key-based secure messaging application designed to provide private and anonymous communication. The platform uses the Session encryption protocol together with the Oxen blockchain’s decentralised Service Node network to transmit messages without relying on centralised infrastructure.
Instead of routing communications through traditional servers, Session messages are relayed across distributed Service Nodes organised within the Oxen network. Messages are transmitted using onion routing, meaning that each message passes through multiple nodes before reaching its destination. This architecture prevents any single node from identifying both the sender and the recipient, significantly reducing metadata exposure.
Unlike many messaging platforms that require phone numbers or email addresses, Session generates a cryptographic account identity locally on the user’s device. This identity is derived from a public/private key pair and allows users to communicate without linking their real-world identity to the application.
This article examines how Session Desktop stores its artefacts on Windows and macOS systems, how its encryption mechanisms operate, and the methodology required to decrypt and reconstruct conversations and attachments during forensic analysis.
Location of Session Data
Windows
On Windows systems, Session stores its application data within the user’s roaming profile:
C:\Users\<username>\AppData\Roaming\Session\
Each Windows user account maintains its own independent Session directory. When analysing forensic images, this directory is typically accessible once the relevant user profile has been mounted.
macOS
On macOS systems, Session user artefacts are stored at:
/Users/<username>/Library/Application Support/Session/
Session Artefacts
The primary artefacts within the Session directory include:
config.json
Contains configuration settings and cryptographic material required by the application.
db.sqlite
An SQLCipher-encrypted SQLite database storing conversations, messages, metadata, and internal encryption material.
attachments.noindex/
A directory containing encrypted attachment blobs.
These artefacts must be analysed together in order to reconstruct conversations and recover associated media attachments.
Session Configuration File (config.json)
The config.json file contains configuration parameters used by the Session client as well as cryptographic material associated with database access.
Example configuration:
{
"key": "d406a9688fc33ee2b8f93bc8d83f1a4dc4347aba1b6a07c96f2c2bb548108813",
"opengroupPruning": true,
"dbHasPassword": false
}
Two operational scenarios may be encountered during forensic analysis depending on the value of the dbHasPassword parameter.
Scenario 1 – No Application Password Enabled
{
"key": "d406a9688fc33ee2b8f93bc8d83f1a4dc4347aba1b6a07c96f2c2bb548108813",
"opengroupPruning": true,
"dbHasPassword": false
}
When dbHasPassword is false, the SQLCipher key stored in the key field can be used directly to decrypt the db.sqlite database.
In this configuration:
- The database encryption key is stored in
config.json - The database can be opened using this key together with the required SQLCipher parameters
- No additional user password is required
Scenario 2 – Application Password Enabled
{
"key": "d406a9688fc33ee2b8f93bc8d83f1a4dc4347aba1b6a07c96f2c2bb548108813",
"opengroupPruning": true,
"dbHasPassword": true
}
When dbHasPassword is true, the user has enabled an application unlock password within the Session client.
In this configuration:
- The application password replaces the key stored in
config.jsonas the credential used to unlock the SQLCipher-encrypted database. - The key stored in
config.jsonalone is not sufficient to decryptdb.sqlite. - The user-defined application password must be supplied to access the database.
Database Encryption (SQLCipher)
db.sqlite is encrypted using SQLCipher, which implements AES-256 encryption.
Key characteristics include:
- The encryption key is stored in
config.json - The key is represented as a 64-character hexadecimal value
- The database cannot be opened without the correct key and cipher configuration
SQLCipher parameters used during forensic analysis include:
PRAGMA cipher_default_compatibility = 4; PRAGMA cipher_page_size = 4096; PRAGMA kdf_iter = 256000; PRAGMA cipher_hmac_algorithm = HMAC_SHA512; PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA512;
Once the correct key and parameters are applied, the encrypted database can be queried to perform analysis.
JSON-Centric Data Storage
Session stores much of its internal application data within JSON structures embedded inside SQLite tables.
These JSON objects may contain:
- Message bodies
- Sender identifiers
- Attachment metadata
- Original filenames
- Message timestamps
This structure differs from traditional relational schemas and requires additional parsing when reconstructing conversations.
Attachment Encryption
Media attachments are protected using a separate encryption mechanism.
Session encrypts attachments using ‘libsodium’s secretstream API’, specifically the XChaCha20-Poly1305 authenticated encryption scheme.
Key characteristics include:
- Each attachment is encrypted individually
- Attachments use a separate encryption key from the database
- The attachment encryption key is stored inside db.sqlite.
- Attachments cannot be decrypted until the database has been successfully decrypted
Extracting the Attachment Encryption Key
Within the decrypted database, the attachment encryption key is stored inside the items table under the entry:
'local_attachment_encrypted_key'
This value is stored as JSON data.
Attachment Decryption Process
Analysis of the TypeScript(ts) code responsible for attachment encryption (available in the Session GitHub repository) clearly documents how media attachments are encrypted and provides a reliable reference for forensic decryption.
Session uses:
- XChaCha20 for encryption
- Poly1305 for authentication and tamper detection
Each attachment file follows a consistent structure:
For each attachment:
- Initialise a libsodium secretstream pull state
- Decrypt the encrypted payload
- Identify the file type using magic byte signatures
- Write the decrypted file with the appropriate extension
This process converts encrypted attachment blobs into usable media files.
Restoring Original Filenames
Session stores original filenames within message metadata contained inside JSON objects in the database.
Using this metadata, decrypted attachments can be renamed to their original filenames.
During this process:
- Filenames are sanitised for filesystem compatibility
- File extensions are preserved
- Naming collisions are handled safely
This step transforms previously unreadable encrypted blobs into recognisable files suitable for review and disclosure.

Session parser tool is available on my GitHub repository: ardfr/Session-Chat-pasrer-for-Windows-and-MacOS.: Session chat application parser: Windows and MacOS
Forensic Analysis of the iOS Signal Application

Forensic Analysis of the iOS Signal Application
Author: Arun KALACKATTU HARI (26/02/2026)
Signal is widely regarded as one of the most secure messaging applications available today.
Its architecture prioritises privacy through strong end-to-end encryption, modern
cryptographic standards, and secure local storage.
This article outlines the forensic analysis of Signal on iOS, the methodology used to decrypt
its encrypted database, and the development of a custom parser to extract messages, calls,
and attachments in a structured manner.
This article outlines:
- The location of Signal artefacts on iOS
- Decryption of the SQLCipher-protected database
- Interpretation of message, call, and attachment structures
- Attachment decryption methodology
- Development of a custom Python GUI parser to automate structured extraction
Location of Signal Data on iOS
On iOS devices, Signal stores its user data within the shared App Group container:
/private/var/mobile/Containers/Shared/AppGroup//
The folder structure within this signal directory is :

the primary user database is located at:
/grdb/Signal.sqlite
This database contains message content, call records, attachment metadata, thread
information, and user profile data.
SQLCipher Encryption
The Signal.sqlite database is encrypted using SQLCipher. Successful decryption
requires correct PRAGMA configuration parameters.
The following configuration was required in this analysis:
PRAGMA key = “x'{key_hex}'”;
PRAGMA cipher_page_size = 4096;
PRAGMA kdf_iter = 256000;
PRAGMA cipher_hmac_algorithm = HMAC_SHA512;
PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA512;
PRAGMA cipher_plaintext_header_size = 32;
Key Observations
- The first 32 bytes of the database are plaintext (header).
- The database uses PBKDF2-HMAC-SHA512 with 256,000 iterations.
- HMAC validation is enabled using SHA512.
- Page size is 4096 bytes.
Once decrypted, the database can be queried using standard SQLite methods.

Figure 2: Unencrypted Signal.sqlite header.
Once the correct key and parameters are applied, the database becomes accessible for
standard SQL querying.
The decryption key was recovered from a full file system extraction. In this instance, the key
material was decoded from the keychain.plist artefact.

Figure 3: Signal. SQLite cipher key obtained form keychain.plist
Message Records – model_TSInteraction
The table model_TSInteraction contains the primary message records. This table
stores:
- Message text
- Timestamps (UNIX epoch in milliseconds)
- Thread identifiers
- Call-related metadata
- Message classification values
Table ‘model_TSInteraction’ column values are shown below:


Figure 3: deserialised Bplist with ‘recipientAddressStates’ value.

Figure 5: deserialised Bplist with ‘infoMessageUserInfo’ value.
Call Artefacts
Signal stores call information across two locations:
- model_TSInteraction.callType
Stores call-related message indicators. - CallRecord Table
Stores structured call log data, including: - type (voice, video, group)
- direction (incoming/outgoing)
- status (answered, declined, missed)
The column values of callRecord table are as below:

Attachments
Table: MessageAttachmentReference
This table links messages to attachment records.
Table ‘MessageAttachmentReference’ contains details about the attachments:

User information
Table ‘model_OWSUserProfile’ stores signal users’ information.

Chat Threads
Table ‘model_TSThread’ stores information about chat threads.

Attachment
Table ‘Attachment’ stores information regarding the attachment files.

Attachment decryption process
Attachments are encrypted using AES-256-CBC.
Each attachment record contains a 64-byte encryption key:
- First 32 bytes → AES key
- First 16 bytes of encrypted file → IV
Decryption workflow:
- Extract encryption key from Attachment.encryptionKey
- Separate AES key (first 32 bytes)
- Extract IV from encrypted file header
- Decrypt using AES-256-CBC
- Validate output using known file signatures (magic bytes)
SQL Query for signal. SQLite can be downloaded from:ardfr/signal-ios-parser: Signal iOS SQLCipher parser with HTML reporting and attachment decryption.
The following query consolidates:
- Messages
- Threads
- Attachments
- Call records
- Author information
iOS Signal Decoder – Custom Python Parser
To streamline this process, I developed a custom Python based iOS Signal Application Parser.
Capabilities are:
- Accepts encrypted Signal.sqlite
- Accepts recovered SQLCipher key
- Applies required PRAGMA parameters
- Executes structured extraction queries
- Generates:
- HTML reports
- CSV exports
- Decrypted attachment files

This tool is available on my GitHub repository: ardfr/signal-ios-parser: Signal iOS SQLCipher parser with HTML reporting and attachment decryption.
Forensic Analysis of Microsoft.ZuneMusic_8wekyb3d8bbwe (Windows Media Player)

Forensic Analysis of Microsoft.ZuneMusic_8wekyb3d8bbwe
Author: Arun KALACKATTU HARI (03/03/2026)
Modern Windows systems utilise packaged applications built on the Universal Windows Platform (UWP) framework. One such application is Windows Media Player (legacy Groove-based version), whose package identity is:
“Microsoft.ZuneMusic_8wekyb3d8bbwe”
The suffix:
“8wekyb3d8bbwe”
is Microsoft’s publisher ID, commonly seen across many built-in Microsoft Store applications.
Although the branding evolved from Zune Music to Groove Music, and later to the redesigned Windows Media Player in Windows 11, the underlying package identity remained unchanged for compatibility and update continuity.
Application Overview
Windows Media Player (UWP version) is designed to:
- Play audio and video files
- Automatically index media folders
- Create and manage playlists
- Display album and video metadata
- Track recently played content
All configured music and video folders on the local machine are automatically indexed and displayed within the application library.
User Data Location
User-specific data for this application is stored at:
C:\Users\<user-name>\AppData\Local\Packages\Microsoft.ZuneMusic_8wekyb3d8bbwe
Folder structure within this directory is:

Within this directory, the primary forensic artefacts reside in:
“LocalState”
Forensic Value of Microsoft.ZuneMusic_8wekyb3d8bbwe
From an investigative perspective, this package may provide:
- Indexed media file paths
- Media metadata (artist, album, title)
- Playback timestamps
- Recently played files
- Cached thumbnail images
- Video library folder references
Key Artefact: MediaPlayer.db
The primary database artefact is:
‘MediaPlayer.db’
This is an SQLite database located within:
‘LocalState’
It contains structured tables relating to indexed and recently played media.
AppState.json
Another important artefact is:
‘AppState.json’
This json file stores metadata relating to the most recent application activity, including:
- Last opened file
- Playback position
- Application state at closure
For example, if a video named 0019.MTS is opened in media player and paused at 10 seconds, the JSON file records (shown in figure below):
- The source file path
- Playback progress timestamp

This artefact can be useful in establishing:
- Exact playback position
- Whether the file was actively viewed
- Last interaction with the application
MediaPlayer.db – Table Analysis
1. Table ‘File’
The File table stores information relating to recently played media files.
| Column | Description |
|---|---|
| Uri | Full file path including file name |
| Id | Unique identifier linked to the RecentlyPlayed table |
Analysis indicates that this table stores up to 25 last played files.
2. Table ‘RecentlyPlayed’
This table records playback activity.
| Column | Description |
|---|---|
| Id | Unique identifier linked to File table |
| ItemType | ‘4’ = Audio file ‘5’ = Video file |
| PlayedTime | Last played timestamp (Microsoft ticks format) |
The PlayedTime value is stored in Microsoft ticks (100-nanosecond intervals since 1 January 1601 UTC).
Analysis suggests this table stores 29 recently played entries, including both audio and video content.
3. Album and Media Tables
The Album table reflects the album listings displayed on the Media Player home page.
This table is populated when:
- A user adds a folder containing media files
- The application indexes the contents of that folder

4. Adding a Folder to the Video Library
When a user adds a folder to the Video Library:
- The media files within that folder are indexed
- The Video table in
MediaPlayer.dbis populated - Corresponding entries appear in the application interface
5. Table ‘Video’
The Video table includes:
| Column | Description |
|---|---|
| Uri | Full video file path |
| ParentFolderId | Identifier linking to video folder table |
| ItemsCount | Number of media items within the folder |
SQL Query to find recently palyed files is:
“”SELECT
File.Uri,
datetime(
(RecentlyPlayed.PlayedTime / 10000000.0) – 62135596800,
‘unixepoch’
) AS PlayedTime_UTC
FROM File
JOIN RecentlyPlayed
ON File.Id = RecentlyPlayed.Id
ORDER BY PlayedTime_UTC ASC;””
LocalCache
This directory contains cached image artefacts generated by the application, including:
- Album artwork
- Video thumbnails
- Preview frames
- Media tile images
These images are generated when:
- A folder is added to the media library
- A media file is indexed
- A video is opened or previewed
- The media grid view renders thumbnails
Cached files are located within ‘LocalCache\Image’ as shown below:

Analysis showed that the filenames follow this path:
“”<Hash>-<Variant>-<Width>-<Height>””
For example:
0A-B0-86-2D-CD-66-43-7D-2A-45-19-87-54-C2-A8-F8-80-E4-D3-03-B6-A7-71-82-FF-1B-C0-23-ED-F8-05-AA-0-512-512.
The first 32 bytes of the file name is the sha256 of the normalized_media_identifier/uri.
The cache file names are cerated using the fucntion:
“SHA256(URI_string_UTF8)→ dash-separated hexadecimal→ append “-0-<width>-<height>””
To support validation and correlation, I have developed a tool that analyses URI values across MediaPlayer.db and links them to cache files located in LocalCache\Image. This enables deterministic verification of cache filename to media relationships.
This tool is available on my GitHub repository: ardfr/mediaplayer-localcache-cachekey: Deterministically correlates Windows Media Player LocalCache
