0% found this document useful (0 votes)
375 views

Windows Timeline

The document discusses Windows 10 Timeline and the ActivitiesCache.db database. It examines the structure and contents of both the old and new databases. The new database stores Timeline activity information for each user in the %LOCALAPPDATA%\ConnectedDevicesPlatform folder. It contains entries for different activity types like app launches and focuses. The database allows activity synchronization across devices when signed in with a Microsoft account and enabling features like Windows Hello.

Uploaded by

Alejandro
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
375 views

Windows Timeline

The document discusses Windows 10 Timeline and the ActivitiesCache.db database. It examines the structure and contents of both the old and new databases. The new database stores Timeline activity information for each user in the %LOCALAPPDATA%\ConnectedDevicesPlatform folder. It contains entries for different activity types like app launches and focuses. The database allows activity synchronization across devices when signed in with a Microsoft account and enabling features like Windows Hello.

Uploaded by

Alejandro
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 57

An examination of Win10 ActivitiesCache.

db database
Windows Timeline, is a new feature of Windows 10 introduced with version 1803.
It is part of the Connected Devices Platform

- The Connected Devices Platform Service, is a Windows service that provides a way for devices
such as PC's and smartphones to discover and send messages between each other.
- Connected Devices Platform Service (CDPSvc) Defaults in Windows 10.

and the Microsoft Graph’s Cross-device experience (Project Rome) .

The CDP settings for the Current User are stored in the registry at:
NTUSER.DAT -> ‘Software\Microsoft\Windows\CurrentVersion\CDP’

and
Before Windows 10 version 1803
The service and the ‘ActivitiesCache.db’ database existed before the 1803 upgrade (May 2018),
but with limited functionality. Another possibly related* activity store location is at:
‘Software\Microsoft\Windows\CurrentVersion\CloudStore\Store\Cache\DefaultAccount\$$wind
ows.data.taskflow.shellactivities\Current’

*(considering that the current ActivitiesCache.db uses taskflow to retrieve device information as
seen further below in this document)

where there is a value named ‘Data’:

Its value is in hex and it seems to hold interesting information, including the Filetime of last
update (which corresponds to the Last Write Timestamp of the registry key).

If Windows is updated to version 1803, this ‘log’ stops being updated. This can be checked by
looking in the SYSTEM hive at the Setup key like:
In that case, interestingly,

this Filetime is very close to the date of the ntuser.dat.LOG files (which coincides with the date
the 1803 update occurred), and that can also be seen from the last entry above:

Further examination shows a consistent pattern:

▪ 0xD2 14 = Start of Entry


▪ Next byte = length of block (x2)
▪ Start of path & executable
▪ 0xC6 1F = End of block
▪ Next 4 bytes = unknown
▪ 0xD2 23 = Executable Block
▪ Next byte = length of block (x2)
▪ Executable
▪ 0xD2 28 = Payload block
▪ Next byte = length of block (x2)
▪ Payload (eg email, URL etc.)
▪ 0xC6 32 = end of block
▪ Next 9 bytes = (A) is the same as (B) of the next entry (upwards)
▪ 0xC6 3C = Pointer to next entry
▪ Next 9 bytes = (B) is the same as (A) of the next entry (upwards) *
▪ 0x CA500000 = End of Entry
*Top most entry is the newest one, so for the last entry these 9 bytes are all 0xFF
With a bit of tweaking in Notepad++, it shows web page titles, email (used in accounts of
Outlook), File Explorer paths followed and name of the remote devices accessed with
Teamviewer among other.
Back to the ‘ActivitiesCache.db’ database.

The location of both old and new dBs is at the


“%userprofile%\appdata\local\ConnectedDevicesPlatform” folder.

The old dB table structure was similar to the new dB, but it included 6 tables + the master table
(the ‘Activity_PackageId’ table was missing, and there were different fields):

The information held was also different:


E.g. the ‘AppSettings’ table in the old DB looked like this:

And included UWP (Universal Windows Platform) Apps only.


The new dB does not have any entries in this table.

The ‘Metadata’ table was also different:

Looking at the entries in an L.username folder and a MS account id folder, the username (local
account) dB has these entries:

And the Microsoft Account dB these:

From this, we can deduce that ‘CurrentSettings’ is where the Activity Types of the entries
populating the database are defined.
The Smartlookup view (query, included in the dB):

select
[O].[Id],
[O].[AppId],
[O].[AppActivityId],
[O].[ActivityType],
[O].[ParentActivityId],
[O].[Tag],
[O].[Group],
[O].[MatchId],
[O].[LastModifiedTime],
[O].[ExpirationTime],
[O].[Payload],
[O].[Priority],
[O].[OriginatingDevice],
[A].[IsLocalOnly],
[A].[PlatformDeviceId],
[A].[CreatedInCloud],
[O].[StartTime],
[O].[EndTime],
[O].[LastModifiedOnClient],
[O].[ETag]
from [ActivityOperation] as [O]
left outer join [Activity] as [A] on [O].[Id] = [A].[Id]
where [O].[OperationType] <> 3
union
select
[Id],
[AppId],
[AppActivityId],
[ActivityType],
[ParentActivityId],
[Tag],
[Group],
[MatchId],
[LastModifiedTime],
[ExpirationTime],
[Payload],
[Priority],
[OriginatingDevice],
[IsLocalOnly],
[PlatformDeviceId],
[CreatedInCloud],
[StartTime],
[EndTime],
[LastModifiedOnClient],
[ETag]
from [Activity]
where [Id] not in (select [Id]
from [ActivityOperation])
Typical ActivityOperation table entries were of ActivityType 2 :

and were in fact Notifications, similar to the ones we can see in


%username%\AppData\Local\Microsoft\Windows\Notifications\wpndatabase.db

The AppID was a json blob like this:

And the Payload field

was an XML blob:

From this, another deduction can be made, that ActitivityType 2 is for Toast Notification entries.
The new (1803) dB has different fields:

After examination of various new ‘ActivitiesCache.db’ files, any entries seen in the new database
have an ‘ActivityType’ (as seen above) of 5 or 6, which appear to represent ‘Open App/File/Url’
and ‘App In Focus’ respectively – type 13 entries were not observed in any dB yet.

The ‘DatabaseInstanceIdUpdateTime’ date seen above, is the date & time (in UTC) that the
current dB file was created.

A Microsoft Account related DB includes one more field, the ‘CurrentEtag’ but instead of using
an ETAG in the form found elsewhere in the dB, it lists it in the form of a GUID – that is the Cloud
ETAG:
The ‘SmartLookUp’ view in the old DB was also different:
The new Timeline & ActivitiesCache.db
The NEW (updated) database stores information for each user in the
%LOCALAPPDATA% \ConnectedDevicesPlatform folder or more commonly familiar as:
C:\users\username\appdata\local\ConnectedDevicesPlatform

This folder has a file named ‘CDPGlobalSettings.cdp’ which is essentially a .json file

and includes information for the service including the store location for the database that holds
the windows timeline entries for the current user.

The folder name may include one or more of:

- A Local account starting with an L.UserName, and/or


- folder(s) which appear to be name with random numbers
but are the cid’s of Microsoft accounts
(e.g. Outlook.com, Live.com, Hotmail.com or MSN.com domains).
If a user logs in to Windows with a MS account, then the respective dB is populated.
Information as to which online account has this specific ID can be found at:
NTUSER.DAT -> ‘Software\Microsoft\IdentityCRL\UserExtendedProperties’
Under each online account (email) the ‘cid’ Value contains the respective value for each
Microsoft Account & folder.

If a user logs in with a local account, then the “L.UserName” database is populated.

A Microsoft Exchange (Office365 etc.) account starts with ‘AAD’ and is in the form of
AAD.[sid]. AAD denotes a business account (as in Azure Active Directory) and information
associated with this account ‘s [sid] can be found in NTUSER.dat at ->
‘Software\Microsoft\MSOIdentityCRL\UserExtendedProperties’ and/or
‘Software\Microsoft\OneDrive\Accounts\Business1’

However, there are two cases when, even if a user continues to use a local account to sign in
Windows 10 , the activities can still be synchronized across devices:

1. The User has set up a Microsoft Account at “Settings-> Accounts->Email&app


accounts” and set it up so that all apps can sign in with this account:

In this case the “L.UserName” folder is removed, and the active folder is the folder
that corresponds to this account. All activities are synched across devices.

2. The User has set up a Microsoft Account at “Settings-> Accounts->Email&app


accounts” and set it up so that Apps need permission to use this account:

In this case, the local activities are stored in the “L.Username” folder, but any
activity on other devices is stored in the respective folder that corresponds to this
MS account used on these devices.

The timeline settings (‘Settings –> Privacy –> Activity History’) enable or not activity to be
tracked in the ‘ActivitiesCache.db’. In order for the activity to be shared across devices (via the
cloud) you need to login with a Microsoft account, enable Windows Hello (i.e. create pin and or
biometric/photo login).
https://support.microsoft.com/en-us/help/4026102/windows-10-about-sync-settings

To enable cross-device experiences, your app users must login with either a Microsoft Account or
an Azure Active Directory account.
https://github.com/Microsoft/project-rome/blob/master/cross-device_app_configuration.md

https://github.com/microsoftgraph/microsoft-graph-docs/blob/master/api-
reference/beta/resources/intune_deviceconfig_windows10generalconfiguration.md

A list of settings that can be roamed or backed up (synced) across devices can be found here:
https://docs.microsoft.com/en-us/azure/active-directory/active-directory-windows-enterprise-
state-roaming-windows-settings-reference

The ‘AfcPrivacySettings’ in ‘CDPGlobalSettings.cdp’ depicts the relative settings in Windows 10


‘Settings –> Privacy- >Activity History’, for example:

All settings ON:

Upload to cloud off


Publish off, cloud off

The same settings can also be configured through Group Policy at ‘Computer Configuration ->
Administrative Templates -> System ->OS Policies’

Opening the respective folder we can see the ‘ActivitiesCache.db’ (and possibly also the
ActivitiesCache.wal and ActivitiesCache.db-sdb files) which is the storage of all timeline activity
for the current user. When a user switches from a Local to a MS account, the ‘L.UserName’ is
deleted and a new one is created (if it didn’t exist before) under the respective MS account
folder. Any previous entries in the ‘L.UserName’’s ‘ActivitiesCache.db’ now appear in the new
‘ActivitiesCache.db’ linked to the MS account, and sync to the cloud. Switching from a MS to a
local account, the MS account related db is still available and holds timeline data.

When a user logs in Windows with a MS account, and the relevant check boxes in ‘Settings –>
Privacy- >Activity History’ are set to On,
any activity created with his other MS account(s), is updated in the ‘ActivitiesCache.db’ in the
respective ‘%LOCALAPPDATA% \ConnectedDevicesPlatform\’ SubFolder, and can be seen in his
timeline view .

Any -excluded from sync- accounts (above setting set to off) can be seen at the registry at:
NTUSER.dat
Software\Microsoft\Windows\CurrentVersion\ActivityDataModel\ActivityAccountFilter

The synchronized entries in a MS account related dB will show the ‘Device ID’ of the machine
the entry originated from. The Device Name and Model of the originating machine can be seen
in the NTUSER.dat’s ‘Software\Microsoft\Windows\CurrentVersion\TaskFlow\DeviceCache\’:

Even if a user logs in with a local account, when a MS Account was previously used for login, the
entries of ‘ActivitiesCache.db’ of that account will also appear in the user’s timeline (for the
previous 7 days). So it may be prudent to examine all ‘ActivitiesCache.db’ databases in a system.
Following is the analysis of the new ‘ActivitiesCache.db’ file, using DB Browser for SQLite , SQLite
Expert Professional, Notepad++ and JSON Viewer.

The database has the following structure (7 tables + the master table):

The ‘Metadata’ table includes the date/time the database was created by the system:

Note: see page 2 above for the differences with the old database

The ‘ManualSequence’ table shows the last Activity (ETAG) recorded in the database:
From the 7 tables above, only three hold information of user activities:

‘Activity’, ‘ActivityOperation’ and ‘Activity_PackageID’


The Windows Timeline process looks like this:

Any new application execution or focus change, triggers an entry to the ‘Activity’ table, and
relevant entries in the ‘Activity_PackageID’ table.

Note: It should be noted that any new entries/transactions are written first to the write ahead
log (‘ActivitiesCache.wal’)

and the database is updated when the wal file reaches 1000 pages and commits the
transactions. The default settings of the database show that each page is 4096 bytes long:
The query below (which is in essence two united queries) extracts all possible useful information
from this database in a readable form. This query will not work properly in any SQLite browser
that does not include support for the json1 extension.
An updated version of this query can be found online at:
https://kacos2000.github.io/WindowsTimeline/

The above query pulls information from the ‘Activity’ , ‘ActivityOperation’ and
‘Activity_PackageId’ tables. The ‘Activity_PackageId’ table is more or less a ‘cache’ of the unique
IDs of each application execution and its expiration time.
Some field explanations provided by Microsoft:

The Activity’ table’s ‘ID’ (Primary key) field is a unique value:


[Activity]([Id] GUID PRIMARY KEY NOT NULL

It is the unique ID of each entry/user activity. The same ID can be seen more than 2 times in the
Activity_PackageID table depending on the ‘Platform’ field which has the following possible
values (Note: most of project Rome is still undocumented, so not all entries can be defined):

• “Host” (is listed as many times as the number of entries in the Activity table),
• “packageid”**, (is listed as many times as the number of entries and includes the
executable and its path for all x_exe & windows_win32 apps, as seen in the
Activity_PackageID’s PackageName field)
• “x_exe_path” for Programs called from a specific path (e.g. Standalone executables)

** as seen below:
By running the following query:
select
Activity.ETag,

hex(Activity_PackageId.ActivityId) as 'ID',

replace(replace(replace(replace(replace(replace(
Activity_PackageId.PackageName,
lower('308046B0AF4A39CB'), 'Mozilla Firefox'),
'{'||lower('6D809377-6AF0-444B-8957-A3773F02200E')||'}', '*ProgramFiles (x64)'),
'{'||lower('7C5A40EF-A0FB-4BFC-874A-C0F2E0B9FA8E')||'}', '*ProgramFiles (x32)'),
'{'||lower('1AC14E77-02E7-4E5D-B744-2EB1AE5198B7')||'}', '*System'),
'{'||lower('F38BF404-1D43-42F2-9305-67DE0B28FC23')||'}', '*Windows'),
'{'||lower('D65231B0-B2F1-4857-A4CE-A8E7C6EA7D27')||'}', '*System32') as
'Activity_PackageId.PackageName',

case
when json_extract(Activity.AppId, '$[0].platform') like '%packageid%' then
replace(replace(replace(replace(replace(replace
(json_extract(Activity.AppId, '$[0].application'),
'308046B0AF4A39CB', 'Mozilla Firefox'),
'{'||'6D809377-6AF0-444B-8957-A3773F02200E'||'}', '*ProgramFiles (x64)'),
'{'||'7C5A40EF-A0FB-4BFC-874A-C0F2E0B9FA8E'||'}', '*ProgramFiles (x32)'),
'{'||'1AC14E77-02E7-4E5D-B744-2EB1AE5198B7'||'}', '*System'),
'{'||'F38BF404-1D43-42F2-9305-67DE0B28FC23'||'}', '*Windows'),
'{'||'D65231B0-B2F1-4857-A4CE-A8E7C6EA7D27'||'}', '*System32')
when json_extract(Activity.AppId, '$[1].platform') like '%packageid%' then
replace(replace(replace(replace(replace(replace
(json_extract(Activity.AppId, '$[1].application'),
'308046B0AF4A39CB', 'Mozilla Firefox'),
'{'||'6D809377-6AF0-444B-8957-A3773F02200E'||'}', '*ProgramFiles (x64)'),
'{'||'7C5A40EF-A0FB-4BFC-874A-C0F2E0B9FA8E'||'}', '*ProgramFiles (x32)'),
'{'||'1AC14E77-02E7-4E5D-B744-2EB1AE5198B7'||'}', '*System'),
'{'||'F38BF404-1D43-42F2-9305-67DE0B28FC23'||'}', '*Windows'),
'{'||'D65231B0-B2F1-4857-A4CE-A8E7C6EA7D27'||'}', '*System32')
when json_extract(Activity.AppId, '$[2].platform') like '%packageid%' then
replace(replace(replace(replace(replace(replace
(json_extract(Activity.AppId, '$[2].application'),
'308046B0AF4A39CB', 'Mozilla Firefox'),
'{'||'6D809377-6AF0-444B-8957-A3773F02200E'||'}', '*ProgramFiles (x64)'),
'{'||'7C5A40EF-A0FB-4BFC-874A-C0F2E0B9FA8E'||'}', '*ProgramFiles (x32)'),
'{'||'1AC14E77-02E7-4E5D-B744-2EB1AE5198B7'||'}', '*System'),
'{'||'F38BF404-1D43-42F2-9305-67DE0B28FC23'||'}', '*Windows'),
'{'||'D65231B0-B2F1-4857-A4CE-A8E7C6EA7D27'||'}', '*System32')
when json_extract(Activity.AppId, '$[3].platform') like '%packageid%' then
replace(replace(replace(replace(replace(replace
(json_extract(Activity.AppId, '$[3].application'),
'308046B0AF4A39CB', 'Mozilla Firefox'),
'{'||'6D809377-6AF0-444B-8957-A3773F02200E'||'}', '*ProgramFiles (x64)'),
'{'||'7C5A40EF-A0FB-4BFC-874A-C0F2E0B9FA8E'||'}', '*ProgramFiles (x32)'),
'{'||'1AC14E77-02E7-4E5D-B744-2EB1AE5198B7'||'}', '*System'),
'{'||'F38BF404-1D43-42F2-9305-67DE0B28FC23'||'}', '*Windows'),
'{'||'D65231B0-B2F1-4857-A4CE-A8E7C6EA7D27'||'}', '*System32')
when json_extract(Activity.AppId, '$[4].platform') like '%packageid%' then
replace(replace(replace(replace(replace(replace
(json_extract(Activity.AppId, '$[4].application'),
'308046B0AF4A39CB', 'Mozilla Firefox'),
'{'||'6D809377-6AF0-444B-8957-A3773F02200E'||'}', '*ProgramFiles (x64)'),
'{'||'7C5A40EF-A0FB-4BFC-874A-C0F2E0B9FA8E'||'}', '*ProgramFiles (x32)'),
'{'||'1AC14E77-02E7-4E5D-B744-2EB1AE5198B7'||'}', '*System'),
'{'||'F38BF404-1D43-42F2-9305-67DE0B28FC23'||'}', '*Windows'),
'{'||'D65231B0-B2F1-4857-A4CE-A8E7C6EA7D27'||'}', '*System32')
when json_extract(Activity.AppId, '$[5].platform') like '%packageid%' then
replace(replace(replace(replace(replace(replace
(json_extract(Activity.AppId, '$[5].application'),
'308046B0AF4A39CB', 'Mozilla Firefox'),
'{'||'6D809377-6AF0-444B-8957-A3773F02200E'||'}', '*ProgramFiles (x64)'),
'{'||'7C5A40EF-A0FB-4BFC-874A-C0F2E0B9FA8E'||'}', '*ProgramFiles (x32)'),
'{'||'1AC14E77-02E7-4E5D-B744-2EB1AE5198B7'||'}', '*System'),
'{'||'F38BF404-1D43-42F2-9305-67DE0B28FC23'||'}', '*Windows'),
'{'||'D65231B0-B2F1-4857-A4CE-A8E7C6EA7D27'||'}', '*System32')
when json_extract(Activity.AppId, '$[6].platform') like '%packageid%' then
replace(replace(replace(replace(replace(replace
(json_extract(Activity.AppId, '$[6].application'),
'308046B0AF4A39CB', 'Mozilla Firefox'),
'{'||'6D809377-6AF0-444B-8957-A3773F02200E'||'}', '*ProgramFiles (x64)'),
'{'||'7C5A40EF-A0FB-4BFC-874A-C0F2E0B9FA8E'||'}', '*ProgramFiles (x32)'),
'{'||'1AC14E77-02E7-4E5D-B744-2EB1AE5198B7'||'}', '*System'),
'{'||'F38BF404-1D43-42F2-9305-67DE0B28FC23'||'}', '*Windows'),
'{'||'D65231B0-B2F1-4857-A4CE-A8E7C6EA7D27'||'}', '*System32')
when json_extract(Activity.AppId, '$[7].platform') like '%packageid%' then
replace(replace(replace(replace(replace(replace
(json_extract(Activity.AppId, '$[7].application'),
'308046B0AF4A39CB', 'Mozilla Firefox'),
'{'||'6D809377-6AF0-444B-8957-A3773F02200E'||'}', '*ProgramFiles (x64)'),
'{'||'7C5A40EF-A0FB-4BFC-874A-C0F2E0B9FA8E'||'}', '*ProgramFiles (x32)'),
'{'||'1AC14E77-02E7-4E5D-B744-2EB1AE5198B7'||'}', '*System'),
'{'||'F38BF404-1D43-42F2-9305-67DE0B28FC23'||'}', '*Windows'),
'{'||'D65231B0-B2F1-4857-A4CE-A8E7C6EA7D27'||'}', '*System32')
when json_extract(Activity.AppId, '$[8].platform') like '%packageid%' then
replace(replace(replace(replace(replace(replace
(json_extract(Activity.AppId, '$[8].application'),
'308046B0AF4A39CB', 'Mozilla Firefox'),
'{'||'6D809377-6AF0-444B-8957-A3773F02200E'||'}', '*ProgramFiles (x64)'),
'{'||'7C5A40EF-A0FB-4BFC-874A-C0F2E0B9FA8E'||'}', '*ProgramFiles (x32)'),
'{'||'1AC14E77-02E7-4E5D-B744-2EB1AE5198B7'||'}', '*System'),
'{'||'F38BF404-1D43-42F2-9305-67DE0B28FC23'||'}', '*Windows'),
'{'||'D65231B0-B2F1-4857-A4CE-A8E7C6EA7D27'||'}', '*System32') end as 'Activity_json_Packageid'

from Activity_PackageId
join Activity on Activity.Id = Activity_PackageId.ActivityId
where Activity_PackageId.ActivityId = Activity.Id and Activity_PackageId.Platform = 'packageid'
Order by etag desc

plus one or more of the following (platform-specific application IDs):

• “windows_win32” for Installed Software (non UWP) Applications


• “windows_universal’ for Windows UWP Apps
• “msa”,
• “ios”,
• “android”, and
• “web”

As seen by this MS example:

If the Sync activity is enabled (user logs in with a MS Account) then another entry may also be
seen: "afs_crossplatform" which shows a cloud sync enabled activity, and is an additional entry
to the same ones seen when using a local account.
When using a MS account:

When using a Local account there is NO ‘afs_crossplatform’ entry:

As can also be seen below (these are for a single ID of a Microsoft Word entry):

The above can be seen by using this query:

Select
hex(Activity_PackageId.ActivityId) as 'ActivityId',
Activity_PackageId.Platform ,
Activity_PackageId.PackageName ,
datetime (Activity_PackageId.ExpirationTime , 'unixepoch') as 'ExpirationTime'
FROM Activity_PackageId
join Activity on Activity_PackageId.ActivityId = Activity.Id
order by Activity.ActivityId

An example of the entry of Microsoft YourPhone’s app:

[{"application":"mmxsdktest.azurewebsites.net","platform":"host"},
{"application":"16815419600048394801","platform":"afs_crossplatform"},
{"application":"000000004018945C","platform":"msa"},
{"application":"","platform":"packageId"},
{"application":"","platform":"alternateId"},
{"application":"","platform":"windows_universal"}]
The afs_crossplatform field has been observed to contain a numeric representation of the
application used (?), with the exception of MS Office applications and MS Edge:

As seen by running the query below:

The ‘Activity_PackageId’ table seemingly has more information than the ‘Activity’ table. That is
not true though, as the ‘Activity’ table’s ‘AppID’ field holds this information and a lot more. The
‘Activity' and ‘ActivityOperation’ table 'AppID' fields are in fact Binary Large Objects (BLOB) in
‘json array’ format e.g.:

'AppID' entry for an Installed Application in Windows:


Note: Notice that the path shown above is in the form of a GUID. It is a KNOWNFOLDERID used
by windows for standard known folders like 'program files'. In the json file above, this is the GUID
for ProgramFilesX86 (C:\Program Files (x86)\) folder. There are various lists of CLSIDs in the
internet like https://msdn.microsoft.com/en-us/library/windows/desktop/dd378457(v=vs.85).aspx

'AppID' entry for a standalone executable:

and 'AppID' entry for a Windows UWP app

Since this is a json array, we can do a query to see what values it holds in the ‘application’ and
‘platform’ fields. The $[x]. depicts the number of the element in the array, and ‘platform’ or
‘application’ the respective field name:

-- List all entries in the AppID json array

select
hex(Activity.ID) as 'ID',
json_extract(Activity.AppId, '$[0].platform') as 'p0' ,
json_extract(Activity.AppId, '$[0].application') as '0' ,
json_extract(Activity.AppId, '$[1].platform') as 'p1' ,
json_extract(Activity.AppId, '$[1].application') as '1' ,
json_extract(Activity.AppId, '$[2].platform') as 'p2' ,
json_extract(Activity.AppId, '$[2].application') as '2' ,
json_extract(Activity.AppId, '$[3].platform') as 'p3' ,
json_extract(Activity.AppId, '$[3].application') as '3' ,
json_extract(Activity.AppId, '$[4].platform') as 'p4' ,
json_extract(Activity.AppId, '$[4].application') as '4',
json_extract(Activity.AppId, '$[5].platform') as 'p5' ,
json_extract(Activity.AppId, '$[5].application') as '5' ,
json_extract(Activity.AppId, '$[6].platform') as 'p6' ,
json_extract(Activity.AppId, '$[6].application') as '6' ,
json_extract(Activity.AppId, '$[7].platform') as 'p7' ,
json_extract(Activity.AppId, '$[7].application') as '7' ,
json_extract(Activity.AppId, '$[8].platform') as 'p8' ,
json_extract(Activity.AppId, '$[8].application') as '8'

from Activity
order by ID asc

Or

Similarly, the ‘Activity’ and the ‘ActivityOperation’ table 'payload' fields (blob) are also in json
format with different entries related to the different platform type as follows:

For "x_exe_path" , "windows_win32" and “windows_universal” it doesn't include duration


when an app is first executed:

but includes it in subsequent entries:


Having included my own duration calculation (calculated by subtracting the ‘StartTime’ from the
‘EndTime’), the duration is sometimes different than the one included in the json blob. A longer
calculated duration could indicate that the app is in focus but idle i.e. the user does not interact
with it.

When "windows_universal" or "windows_win32" applications open a file, the 'payload' field


includes quite a bit of information.

"windows_universal" (In this case MS Edge - which uses the Adaptive Card framework -
bing search for CDPTraces.log) can be seen below:

And ‘windows_win32’ here:


The ‘ExpirationTime’ fields in both Activity and Activity_PackageId tables are the same for each
‘ID’ and ‘ActivityId’ respectively (Unique field entry GUID).

All Dates/Times are stored by the database in UTC. To get the local times, we can adjust the
query by using, 'localtime' e.g. :

datetime(Activity.StartTime , 'unixepoch', 'localtime'),

The ‘ExpirationTime’ is exactly 2592000 seconds or 30 Days from the relevant entry’s
‘LastModified’ time, and is easily seen by using the following:

Select
(Activity.ExpirationTime - Activity.LastModifiedTime) as 'Expires in'
From Activity

Sorting the query by the 'ETAG' field gives a historical list (sort of a timeline) according to the
Events recorded in the db, but is not the same as if sorted by Start, End or Expiry datetimes.
The ETAG can change for a particular entry’s GUID depending on the current action the
database has recorded for that ID (e.g. user removed Tile from timeline).

An example that an ID can have multiple ETAGs associated with it, is shown below:

by running this query against a MS account’s ‘ActivitiesCache.db’:


The ‘PlatformDeviceID’ seen in the ‘Activity’ & ‘ActivityOperations’ tables:

can be found in the user’s NTUSER.dat at

“Software\Microsoft\Windows\CurrentVersion\TaskFlow\DeviceCache\”.

As seen below:

But it is not fixed - it looks encoded with the QuickXorHash Algorithm, similar to the
‘FileShellLink’ in the ‘Payload’ field blob - and it changes occasionally,
still depicting the same Machine (as seen at the relevant registry entries). I have not yet found
the pattern as to why or when it changes when a user logs in with a local account.

It is used to show the Device* origin of a Tile in the Timeline view, such as:

*(if no device name is seen in one or more tiles in the user’s Timeline view, then the activity is local)

The device name seen above is derived from the “DeviceModel” entry in the registry for the
specific DeviceID. That information originates from the OEM information value in
‘SystemProductName’ at “HKLM\SYSTEM\ControlSet001\Control\SystemInformation” which is
usually filled by the device manufacturer, or is blank when the computer is user assembled.

The ‘AppActivityId’ field has 3 possible observed values:

- ECB32AF3-1440-4086-94E3-5311F97F89C4 which looks like a GUID but having checked 4


different computers of different users except my own ones, this GUID remains the same in
all of them .
- An alphanumeric identifier (Hash?) following the above GUID, which is specific to a file
opened, or
- A URL opened by MS Edge (on MS Account related ‘ActivitiesCache.db’ databases).

This can be seen by running the following:

select
case when Activity.AppActivityId not like '%-%-%-%-%\%' then Activity.AppActivityId
when Activity.AppActivityId not like '%-%-%-%-%' then Activity.AppActivityId
else substr(Activity.AppActivityId , 38)
end as 'DeviceID',
datetime(Activity.StartTime, 'unixepoch', 'localtime') AS 'StartTime',
json_extract(Activity.Payload, '$.displayText') as 'File_Name'
from Activity
join Activity_PackageId on activity.id = Activity_PackageId.ActivityId
group by File_Name
order by StartTime asc
The ‘PackageIDHash’ field is a unique value related to each application. It appears to be the
‘QuickXorHash’ of the executable – with this query:

select
Activity.PackageIdHash as 'Hash',
Activity_PackageId.PackageName as 'Name',
datetime(Activity.StartTime, 'unixepoch', 'localtime') AS 'StartTime'
from Activity
join Activity_PackageId on activity.id = Activity_PackageId.ActivityId
group by Hash
order by StartTime desc

we can see that different versions of the same application have a different Hash value:

The ‘Activity’ table’s ‘ActivityStatus’ and ‘ActivityOperation’ tables’s ‘OperationType’ have 3


observed values ranging from 1 to 3 and depict the related Tile Status as:
1 -> Active (means it is still an open application)
2-> Updated (means the entry is an update for a previously Active entry)
3-> Deleted (means the Tile is removed from the Timeline)
And there could be a 4th entry with a value of 4, meaning that the entry is ‘Ignored’.

When a Tile is removed from the Timeline by the user,

the associated ID(s) to this Tile remain the same, but the entries are copied from the ‘Activity’ to
the ‘ActivityOperation’ table with a NEW ‘Etag’ and new type/status value:
When the user logs in with a local account, and a tile is removed from the Timeline, the
associated entries for that are copied from the ‘Activity’ to the ‘ActivityOperation’ table with a
different ‘ETAG’ value, and stay there until expiration time.

An easy way to figure out which entries are User Removed can be derived from viewing the
‘SmartLookup’ view (automatically created query included in the database) which, in essence, is
the source of the actual timeline a user observes:
The key here is the line: FROM [Activity] WHERE [Id] NOT IN (SELECT [Id] FROM [ActivityOperation])

If we check the ‘SmartLookup’ query data view, it lists all ‘Activity’ table entries plus all
‘ActivityOperation’ table entries minus the ‘Activity’ table entries that appear in both tables with
the same ID. Why? Because when the ActivityOperation.Id is also found in the Activity.Id then
the entry has been (user) removed from the timeline.

What this query also does, is to mark (and list) all entries in the ‘Activity’ table with a value of 0
in the field [IsInUploadQueue], and all entries in the ‘ActivityOperations with a value of 1 in the
[IsInUploadQueue]. What this means, is that the entries in the ‘ActivityOperations’ table are in
the ‘Upload to Cloud Queue’ unless they also appear in the ‘Activity’ table.

However, when a user is logged in with a MS Account, and the user removes a tile from the
Timeline, the respective entries are copied to the ‘ActivityOperation’ table with a new ‘Etag’
value and a new type/status of 3 (Deleted) momentarily until they are synced, and then they are
moved to the ‘Activity’ table until they expire. The type/status value 3 tells the other
synchronized devices not to display this tile in their Timeline. This may be confusing when
examining an offline system:

The following query checks every ID on ‘Activity_PackageID’ against both ‘Activity’ and
‘ActivityOperation’ tables and provides the relevant results:

Archived:
Activity.ID
ID not in either table.
Activity_PackageID.ActivityID

ActivityOperation.ID

Tile Removed:
Activity.ID
ID in both tables.
Activity_PackageID.ActivityID

ActivityOperation.ID

New Activity:
ID only in the Activity table. Activity.ID

Activity_PackageID.ActivityID

ActivityOperation.ID

In Upload Queue:
ID only in ActivityOperation table. Activity.ID

Activity_PackageID.ActivityID

ActivityOperation.ID

select
case
when
Activity_PackageId.ActivityId in (select Activity.Id from activity) and
Activity_PackageId.ActivityId in (select ActivityOperation.Id
from ActivityOperation)
then 'Tile Removed - '||hex(Activity_PackageId.ActivityId)
else
case
when Activity_PackageId.ActivityId not in
(select Activity.Id from activity) and
Activity_PackageId.ActivityId not in
(select ActivityOperation.Id from ActivityOperation)
then 'Is Archived - '||hex(Activity_PackageId.ActivityId)
else
case
when Activity_PackageId.ActivityId in
(select Activity.Id from activity) and
Activity_PackageId.ActivityId not in
(select ActivityOperation.Id from ActivityOperation)
then 'New Activity - '||hex(Activity_PackageId.ActivityId)
else
case
when Activity_PackageId.ActivityId
not in (select Activity.Id from Activity)
and Activity_PackageId.ActivityId
in (select ActivityOperation.Id from ActivityOperation)
then '
In Upload Queue - '||hex(Activity_PackageId.ActivityId)
end
end
end
end as 'Status_ID', -- This field includes both the Status and the unique ID of the associated activity
Activity_PackageId.PackageName as 'PackageName', -- The program/ associated with the above ID
datetime(Activity_PackageId.ExpirationTime, 'unixepoch', 'localtime') as 'ExpirationTime',
Activity_PackageId.Platform

from Activity_PackageId
where Activity_PackageId.Platform in ('windows_win32', 'windows_universal', 'x_exe_path')
group by Status_ID
order by ExpirationTime asc

We can see which ID’s entry is a:

- 'New activity'
- 'Had the associated timeline tile removed'
- 'In the Upload Queue'
- Archived' (until expiration time)

Another view of the timeline and the items discussed above can be seen with this query:
https://kacos2000.github.io/WindowsTimeline/WindowsTimeline2.sql

_____________________________
Upcoming changes with Windows 10 version 1809 (October 2018 update)
(The following in based on Win10 Insider’s build 17744.rc5_release.180818-1845)

The previous (1803) was structured like this:

With the main tables being ‘Activities’ and ‘ActivitiesOperation’, while ‘Activities_PackageID’
was the link and archive of all the activity entries.
The database structure has changed a bit with the new October 2018 Windows 10 update
(version 1809). A new table is introduced:

As well as new fields in both Activity & ActivityOperation tables:

Activity ActivityOperation

UploadAllowedByPolicy
UserActionState UserActionState
IsRead IsRead
GroupItems GroupItems
Before (1803) After (1809)
The Metadata table is the one major change. The Current Settings key, as previously, is where
the allowed Activity Types are listed:

New Keys are introduced:

• DatabaseNotificationSubscriptionInfo,
• DatabaseActivityPolicies and
• PendingActivityTypes

as well as new ActivityTypes & Policies:

In the ‘DatabaseActivityPolicies’ key’s value (json field), we can see


“AllowedSubscriptionSyncScopes” and “Policies” as the main fields:

“AllowedSubscriptionSyncScopes”’s Elements is where the Allowed Activity Types (to be synched


across devices) are listed as well as the respective application & platform. For example:
ActivityTypes 0-7 and 10, 13 and 15 are allowed for (*) all applications, but

Activity Types 11 and 12 are only allowed for the application “Microsoft.Credentials.WiFi” and
only for the Platform entry “data_boundary”.

The Policies field


Has entries like this in each Element:

Where the PermissionScope is the Application, and Type is the ActivityType blocked for this
application. BlockedOperationFlags has seen with values 0, 1 and 7. In the above screenshot,
MicrosoftPersonalization and Microsoft.Credentials apps are NOT blocked for ActivityTypes 11
and 12.

BlockedOperationFlags value 1 means that this Element is Blocked for example, ActivityType 8 is
blocked (we can see that in the AllowedTypes as well):
Whereas value 0 means that this ActivityType is NOT blocked:

(ActivityType 10 is in listed in the AllowedTypes).

However a BlockedOperationFlags with value 7

Is not yet explained. I suspect that it means that this is user configurable from “Sync your
Settings”, but not sure yet.

The key “DatabaseNotificationSubscriptionInfo” is also a JSON blob:

where in the ‘publisherFilters’ we see


that ActivitiyTypes 0-7, 13 and 15 are allowed for (*) all applications.

Finally ‘PendingActivityTypes’ value is also a JSON blob, but empty at this time.

Back to the ActivitiesCaches.db changes, there is also a new table, DataEncryptionKeys:


The Smartlookup view (query) view changed:

Smartlookup (1803) Smartlookup (1809)


select select
[O].[Id], [O].[Id],
[O].[AppId], [O].[AppId],
[O].[PackageIdHash], [O].[PackageIdHash],
[O].[AppActivityId], [O].[AppActivityId],
[O].[ActivityType], [O].[ActivityType],
[O].[OperationType] AS [ActivityStatus], [O].[OperationType] AS [ActivityStatus],
[O].[ParentActivityId], [O].[ParentActivityId],
[O].[Tag], [O].[Tag],
[O].[Group], [O].[Group],
[O].[MatchId], [O].[MatchId],
[O].[LastModifiedTime], [O].[LastModifiedTime],
[O].[ExpirationTime], [O].[ExpirationTime],
[O].[Payload], [O].[Payload],
[O].[Priority], [O].[Priority],
[A].[IsLocalOnly], [A].[IsLocalOnly],
[O].[PlatformDeviceId], [O].[PlatformDeviceId],
[A].[CreatedInCloud], [A].[CreatedInCloud],
[O].[StartTime], [O].[StartTime],
[O].[EndTime], [O].[EndTime],
[O].[LastModifiedOnClient], [O].[LastModifiedOnClient],
1 AS [IsInUploadQueue], 1 AS [IsInUploadQueue],
[O].[GroupAppActivityId], [O].[GroupAppActivityId],
[O].[ClipboardPayload], [O].[ClipboardPayload],
[O].[EnterpriseId], [O].[EnterpriseId],
[O].[OriginalPayload], [O].[UserActionState],
[O].[OriginalLastModifiedOnClient], [O].[IsRead],
[O].[ETag] [O].[OriginalPayload],
from [ActivityOperation] as [O] [O].[OriginalLastModifiedOnClient],
left outer join [Activity] as [A] on [O].[Id] = [A].[Id] [O].[GroupItems],
union [O].[ETag]
select from [ActivityOperation] as [O]
[Id], left outer join [Activity] as [A] on [O].[Id] = [A].[Id]
[AppId], union
[PackageIdHash], select
[AppActivityId], [Id],
[ActivityType], [AppId],
[ActivityStatus], [PackageIdHash],
[ParentActivityId], [AppActivityId],
[Tag], [ActivityType],
[Group], [ActivityStatus],
[MatchId], [ParentActivityId],
[LastModifiedTime], [Tag],
[ExpirationTime], [Group],
[Payload], [MatchId],
[Priority], [LastModifiedTime],
[IsLocalOnly], [ExpirationTime],
[PlatformDeviceId], [Payload],
[CreatedInCloud], [Priority],
[StartTime], [IsLocalOnly],
[EndTime], [PlatformDeviceId],
[LastModifiedOnClient], [CreatedInCloud],
0 AS [IsInUploadQueue], [StartTime],
[GroupAppActivityId], [EndTime],
[ClipboardPayload], [LastModifiedOnClient],
[EnterpriseId], 0 AS [IsInUploadQueue],
[OriginalPayload], [GroupAppActivityId],
[OriginalLastModifiedOnClient], [ClipboardPayload],
[ETag] [EnterpriseId],
from [Activity] [UserActionState],
where [Id] not in (select [Id] [IsRead],
from [ActivityOperation]) [OriginalPayload],
[OriginalLastModifiedOnClient],
[GroupItems],
[ETag]
from [Activity]
where [Id] not in (select [Id]
from [ActivityOperation])

We also see a new PlatformID entry: “data_boundary”

Associated with Activity types 11 and 12:

Whose payload is encoded/encrypted.


And one entry associated with Activity type 15:

whose Payload field is encoded with Base64, and encrypted. Using


https://gchq.github.io/CyberChef/#recipe=From_Base64('A-Za-z0-9%2B/%3D',true) I was able to
see the email (Microsoft account) associated with this Win 10 installation.

In the ActivityOperation table, a new column (field) named “UploadAllowedByPolicy” is


introduced:

With observed values 0 and 1. The obvious deduction is that entries with value 1 are Yes and
entries with value 0 are No. The Metadata table is where these policies are defined.
Note: The encryption (?) certificates are store at
C:\Users\%Username%\AppData\Roaming\Microsoft\Crypto\Keys

Update (Win 10 version 1903 OS Build 18875.1000)

In the latest update, we have a new “ActivityType” -> 10 which is clipboard data
(I have only observed clipboard text).
The Metadata table now includes ActivityType 10 :
The field “ClipboardPayload” (JSON blob) of entries with ActivityType 10 (Clipboard text) contain
the copied text in Base64 encoding in the form:

[{"content":"eyJBbGxvd2VkU3Vic2NyaXB0aW9uU3luY1Njb3BlcyI6W3siYWN0aXZpdHlUeXBlcyI6
WzAsMSwyLDMsNCw1LDYsNywxMCwxMywxNV0sImFwcGxpY2F0aW9uIjoiKiJ9LHsiYWN0aXZpd
HlUeXBlcyI6WzExLDEyXSwiYXBwbGljYXRpb24iOiJNaWNyb3NvZnQuQ3JlZGVudGlhbHMuVmF1bH
QiLCJwbGF0Zm9ybSI6ImRhdGFfYm91bmRhcnkifSx7ImFjdGl2aXR5VHlwZXMiOlsxMSwxMl0sImF
wcGxpY2F0aW9uIjoiTWljcm9zb2Z0LkNyZWRlbnRpYWxzLldpRmkiLCJwbGF0Zm9ybSI6ImRhdGFfY
m91bmRhcnkifSx7ImFjdGl2aXR5VHlwZXMiOlsxMV0sImFwcGxpY2F0aW9uIjoibWljcm9zb2Z0LmR
lZmF1bHQuZGVmYXVsdCIsInBsYXRmb3JtIjoiZGF0YV9ib3VuZGFyeSJ9XSwiUG9saWNpZXMiOlt7IkJ
sb2NrZWRPcGVyYXRpb25GbGFncyI6MCwiU2NvcGUiOnsiUGVybWlzaW9uU2NvcGUiOiIiLCJUeXBl
IjoxMX0sIlNvdXJjZSI6MX0seyJCbG9ja2VkT3BlcmF0aW9uRmxhZ3MiOjAsIlNjb3BlIjp7IlBlcm1pc2lv
blNjb3BlIjoiTWljcm9zb2Z0LkNyZWRlbnRpYWxzIiwiVHlwZSI6MTF9LCJTb3VyY2UiOjF9LHsiQmxvY2
tlZE9wZXJhdGlvbkZsYWdzIjowLCJTY29wZSI6eyJQZXJtaXNpb25TY29wZSI6Ik1pY3Jvc29mdC5QZXJ
zb25hbGl6YXRpb24iLCJUeXBlIjoxMX0sIlNvdXJjZSI6MX0seyJCbG9ja2VkT3BlcmF0aW9uRmxhZ3Mi
OjAsIlNjb3BlIjp7IlBlcm1pc2lvblNjb3BlIjoiIiwiVHlwZSI6MTJ9LCJTb3VyY2UiOjF9LHsiQmxvY2tlZE9w
ZXJhdGlvbkZsYWdzIjowLCJTY29wZSI6eyJQZXJtaXNpb25TY29wZSI6Ik1pY3Jvc29mdC5DcmVkZW5
0aWFscyIsIlR5cGUiOjEyfSwiU291cmNlIjoxfSx7IkJsb2NrZWRPcGVyYXRpb25GbGFncyI6MCwiU2Nv
cGUiOnsiUGVybWlzaW9uU2NvcGUiOiJNaWNyb3NvZnQuUGVyc29uYWxpemF0aW9uIiwiVHlwZS
I6MTJ9LCJTb3VyY2UiOjF9LHsiQmxvY2tlZE9wZXJhdGlvbkZsYWdzIjowLCJTY29wZSI6eyJQZXJtaXNp
b25TY29wZSI6IiIsIlR5cGUiOjExfSwiU291cmNlIjoyfSx7IkJsb2NrZWRPcGVyYXRpb25GbGFncyI6MC
wiU2NvcGUiOnsiUGVybWlzaW9uU2NvcGUiOiIiLCJUeXBlIjoxMn0sIlNvdXJjZSI6Mn0seyJCbG9ja2V
kT3BlcmF0aW9uRmxhZ3MiOjcsIlNjb3BlIjp7IlBlcm1pc2lvblNjb3BlIjoiIiwiVHlwZSI6MTB9LCJTb3Vy
Y2UiOjN9LHsiQmxvY2tlZE9wZXJhdGlvbkZsYWdzIjo3LCJTY29wZSI6eyJQZXJtaXNpb25TY29wZSI6IiI
sIlR5cGUiOjEyfSwiU291cmNlIjozfSx7IkJsb2NrZWRPcGVyYXRpb25GbGFncyI6NywiU2NvcGUiOnsi
UGVybWlzaW9uU2NvcGUiOiIiLCJUeXBlIjoxNX0sIlNvdXJjZSI6M30seyJCbG9ja2VkT3BlcmF0aW9uR
mxhZ3MiOjAsIlNjb3BlIjp7IlBlcm1pc2lvblNjb3BlIjoiIiwiVHlwZSI6MTB9LCJTb3VyY2UiOjR9LHsiQmx
vY2tlZE9wZXJhdGlvbkZsYWdzIjowLCJTY29wZSI6eyJQZXJtaXNpb25TY29wZSI6IiIsIlR5cGUiOjEwfSw
iU291cmNlIjo1fSx7IkJsb2NrZWRPcGVyYXRpb25GbGFncyI6MCwiU2NvcGUiOnsiUGVybWlzaW9u
U2NvcGUiOiIiLCJUeXBlIjoxMX0sIlNvdXJjZSI6NX0seyJCbG9ja2VkT3BlcmF0aW9uRmxhZ3MiOjcsIlN
jb3BlIjp7IlBlcm1pc2lvblNjb3BlIjoiTWljcm9zb2Z0LkFjY2Vzc2liaWxpdHkiLCJUeXBlIjoxMX0sIlNvdXJj
ZSI6NX0seyJCbG9ja2VkT3BlcmF0aW9uRmxhZ3MiOjcsIlNjb3BlIjp7IlBlcm1pc2lvblNjb3BlIjoiTWljc
m9zb2Z0LkNyZWRlbnRpYWxzIiwiVHlwZSI6MTF9LCJTb3VyY2UiOjV9LHsiQmxvY2tlZE9wZXJhdGlv
bkZsYWdzIjowLCJTY29wZSI6eyJQZXJtaXNpb25TY29wZSI6Ik1pY3Jvc29mdC5EZWZhdWx0IiwiVHlw
ZSI6MTF9LCJTb3VyY2UiOjV9LHsiQmxvY2tlZE9wZXJhdGlvbkZsYWdzIjo3LCJTY29wZSI6eyJQZXJtaX
Npb25TY29wZSI6Ik1pY3Jvc29mdC5MYW5ndWFnZSIsIlR5cGUiOjExfSwiU291cmNlIjo1fSx7IkJsb2N
rZWRPcGVyYXRpb25GbGFncyI6NywiU2NvcGUiOnsiUGVybWlzaW9uU2NvcGUiOiJNaWNyb3NvZn
QuUGVyc29uYWxpemF0aW9uIiwiVHlwZSI6MTF9LCJTb3VyY2UiOjV9LHsiQmxvY2tlZE9wZXJhdGlv
bkZsYWdzIjowLCJTY29wZSI6eyJQZXJtaXNpb25TY29wZSI6IiIsIlR5cGUiOjEyfSwiU291cmNlIjo1fSx7I
kJsb2NrZWRPcGVyYXRpb25GbGFncyI6NywiU2NvcGUiOnsiUGVybWlzaW9uU2NvcGUiOiJNaWNy
b3NvZnQuQWNjZXNzaWJpbGl0eSIsIlR5cGUiOjEyfSwiU291cmNlIjo1fSx7IkJsb2NrZWRPcGVyYXRp
b25GbGFncyI6NywiU2NvcGUiOnsiUGVybWlzaW9uU2NvcGUiOiJNaWNyb3NvZnQuQ3JlZGVudGl
hbHMiLCJUeXBlIjoxMn0sIlNvdXJjZSI6NX0seyJCbG9ja2VkT3BlcmF0aW9uRmxhZ3MiOjAsIlNjb3BlIj
p7IlBlcm1pc2lvblNjb3BlIjoiTWljcm9zb2Z0LkRlZmF1bHQiLCJUeXBlIjoxMn0sIlNvdXJjZSI6NX0seyJC
bG9ja2VkT3BlcmF0aW9uRmxhZ3MiOjcsIlNjb3BlIjp7IlBlcm1pc2lvblNjb3BlIjoiTWljcm9zb2Z0Lkxhb
md1YWdlIiwiVHlwZSI6MTJ9LCJTb3VyY2UiOjV9LHsiQmxvY2tlZE9wZXJhdGlvbkZsYWdzIjo3LCJTY2
9wZSI6eyJQZXJtaXNpb25TY29wZSI6Ik1pY3Jvc29mdC5QZXJzb25hbGl6YXRpb24iLCJUeXBlIjoxMn0
sIlNvdXJjZSI6NX0seyJCbG9ja2VkT3BlcmF0aW9uRmxhZ3MiOjEsIlNjb3BlIjp7IlBlcm1pc2lvblNjb3BlI
joiIiwiVHlwZSI6OH0sIlNvdXJjZSI6N30seyJCbG9ja2VkT3BlcmF0aW9uRmxhZ3MiOjEsIlNjb3BlIjp7Il
Blcm1pc2lvblNjb3BlIjoiIiwiVHlwZSI6OX0sIlNvdXJjZSI6N30seyJCbG9ja2VkT3BlcmF0aW9uRmxhZ3
MiOjAsIlNjb3BlIjp7IlBlcm1pc2lvblNjb3BlIjoiIiwiVHlwZSI6MTB9LCJTb3VyY2UiOjd9LHsiQmxvY2tlZE
9wZXJhdGlvbkZsYWdzIjowLCJTY29wZSI6eyJQZXJtaXNpb25TY29wZSI6IiIsIlR5cGUiOjExfSwiU291c
mNlIjo3fSx7IkJsb2NrZWRPcGVyYXRpb25GbGFncyI6MCwiU2NvcGUiOnsiUGVybWlzaW9uU2NvcG
UiOiIiLCJUeXBlIjoxMn0sIlNvdXJjZSI6N30seyJCbG9ja2VkT3BlcmF0aW9uRmxhZ3MiOjAsIlNjb3BlIjp
7IlBlcm1pc2lvblNjb3BlIjoiIiwiVHlwZSI6MTV9LCJTb3VyY2UiOjd9LHsiQmxvY2tlZE9wZXJhdGlvbkZs
YWdzIjowLCJTY29wZSI6eyJQZXJtaXNpb25TY29wZSI6IiIsIlR5cGUiOjV9LCJTb3VyY2UiOjh9LHsiQmx
vY2tlZE9wZXJhdGlvbkZsYWdzIjowLCJTY29wZSI6eyJQZXJtaXNpb25TY29wZSI6IiIsIlR5cGUiOjZ9LCJ
Tb3VyY2UiOjh9LHsiQmxvY2tlZE9wZXJhdGlvbkZsYWdzIjowLCJTY29wZSI6eyJQZXJtaXNpb25TY29
wZSI6IiIsIlR5cGUiOjh9LCJTb3VyY2UiOjh9LHsiQmxvY2tlZE9wZXJhdGlvbkZsYWdzIjowLCJTY29wZSI
6eyJQZXJtaXNpb25TY29wZSI6IiIsIlR5cGUiOjl9LCJTb3VyY2UiOjh9LHsiQmxvY2tlZE9wZXJhdGlvbkZ
sYWdzIjowLCJTY29wZSI6eyJQZXJtaXNpb25TY29wZSI6IiIsIlR5cGUiOjEwfSwiU291cmNlIjo5fV19","f
ormatName":"Text"}]

(Translated below:)
.

The payload of the above entry is:

{"gdprType":"ProductAndServiceUsage","clipboardDataId":"{B268A259-DAAD-47FA-A089-
55E3BB298BCB}"}

Another new ‘ActivityType’ 16 contains data on the application from where data was
copied/pasted from/to, and the ‘Group’ field shows what action was operated:

And where it was pasted:


We can now see copy pasted operations:

The copy paste operations can be linked with the ‘clipboardDataId' value in the Payload field
(JSON) eg:

{"gdprType":"ProductAndServiceUsage","clipboardDataId":"{BA306A6E-2B7B-483B-B9B6-
76BB7AF64D12}"}

The Clipboard text has a duration (ExpirationTime - LastModifiedTime) of 43200 seconds or 12


hours exactly.
*To be updated*

CC Attribution 4.0 International (CC BY 4.0)

You might also like