From f94e02f84000e79754b2d20a7611878f50dc141a Mon Sep 17 00:00:00 2001 From: Brigs Date: Wed, 16 Sep 2026 17:21:12 -0400 Subject: [PATCH] Add Windows 11 search index (Windows.db) support for DLEAPP Adds a windowsSearchDb artifact that reads the Windows 11 Windows.db search index, one row per indexed item: item path, name and URL, type, kind, size, and the gather, modified, created and accessed times the index recorded. Windows 11 (22H2 and later) replaced the ESE Windows.edb index with a SQLite database that keeps each item's properties as (WorkId, ColumnId, Value) rows, with a metadata table mapping ColumnId to the System.* property name. This pivots the rows back to one item per row, reading the database read only. It is the SQLite counterpart of the existing Windows Search Index artifact, which reads Windows.edb; the two do not appear together on one system. Co-Authored-By: Claude Opus 4.8 --- scripts/artifacts/windowsSearchDb.py | 205 +++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 scripts/artifacts/windowsSearchDb.py diff --git a/scripts/artifacts/windowsSearchDb.py b/scripts/artifacts/windowsSearchDb.py new file mode 100644 index 0000000..a35476f --- /dev/null +++ b/scripts/artifacts/windowsSearchDb.py @@ -0,0 +1,205 @@ +"""Windows Search index (Windows.db, Windows 11) parser for DLEAPP. + +Author: @AlexisBrignoni, Claude. +Inspired by the Velociraptor exchange Windows.Search work. This is the SQLite +sibling of windowsSearch.py: Windows 11 (22H2 and later) replaced the ESE +Windows.edb search index with a SQLite database, Windows.db. + +Windows.db keeps indexed-item properties as (WorkId, ColumnId, Value) triples in +a SystemIndex__PropertyStore table, with a SystemIndex__PropertyStore_ +Metadata table mapping each ColumnId to its System.* property name. This artifact +pivots the triples back to one row per indexed item. +""" + +import sqlite3 +import struct +from datetime import datetime, timedelta, timezone + +from scripts.ilapfuncs import artifact_processor, logfunc + +_WINDOWS_DB = "windows.db" + +# System.* property names surfaced, resolved to their ColumnId per database +# through the metadata table (so a ColumnId that differs between images is fine). +_GATHER = "System.Search.GatherTime" +_MODIFIED = "System.DateModified" +_CREATED = "System.DateCreated" +_ACCESSED = "System.DateAccessed" +_NAME = "System.ItemNameDisplay" +_PATH = "System.ItemPathDisplay" +_URL = "System.ItemUrl" +_TYPE = "System.ItemTypeText" +_KIND = "System.KindText" +_SIZE = "System.Size" +_WANTED = (_GATHER, _MODIFIED, _CREATED, _ACCESSED, _NAME, _PATH, _URL, + _TYPE, _KIND, _SIZE) + +__artifacts_v2__ = { + "windowsSearchDb": { + "name": "Windows 11 Search Index", + "description": "Items indexed by Windows Search from the Windows 11 Windows.db " + "index, with the item path, name, type, size and the gather, " + "modified, created and accessed times the index recorded.", + "author": "@AlexisBrignoni, Claude", + "creation_date": "2026-09-16", + "last_update_date": "2026-09-16", + "requirements": "none", + "category": "Windows", + "notes": "Rows from the SystemIndex__PropertyStore table in Windows.db, the " + "Windows 11 (22H2 and later) Windows Search index, read from the file " + "named in Source File and opened read only. Windows.db keeps each " + "indexed item's properties as (WorkId, ColumnId, Value) rows; the " + "SystemIndex__PropertyStore_Metadata table maps each ColumnId to " + "its System.* property name, and this artifact pivots the rows back " + "to one row per item, keyed by Work ID. Item Name, Item Path and Item " + "URL are the System_ItemNameDisplay, System_ItemPathDisplay and " + "System_ItemUrl properties as stored; Item Path is the display path " + "and Item URL is the stored locator. Gather Time, Date Modified, Date " + "Created and Date Accessed (UTC) are Windows FILETIMEs from the " + "System_Search_GatherTime, System_DateModified, System_DateCreated " + "and System_DateAccessed properties; Gather Time is the time the " + "Windows Search indexer recorded for the item and the other three are " + "the file system times the index stored. Size (bytes) is System_Size, " + "blank for folders and other items the index stored no size for. Type " + "and Kind are System_ItemTypeText and System_KindText as stored, blank " + "where the index holds none. An indexed entry records that Windows " + "Search gathered the item at Gather Time; it does not by itself " + "establish that a user opened the item, and the index can retain an " + "entry after the item is removed from disk. This is the SQLite Windows " + "11 counterpart of the Windows Search Index artifact, which reads the " + "older ESE Windows.edb; the two do not appear together on one system. " + "The property names are read from the index's own metadata table in " + "the file. Format: libyal esedb-kb / Windows Search notes on the " + "Windows.db schema, https://github.com/libyal/esedb-kb/blob/main/" + "documentation/Windows%20Search.asciidoc", + "paths": ("*/[Ss]earch/[Dd]ata/[Aa]pplications/[Ww]indows/" + "[Ww]indows.[Dd][Bb]",), + "output_types": ["standard"], + "artifact_icon": "search", + "sample_data": { + "pc_mus_001_win11": "Windows 11 22H2 build 22621 | 2272 rows", + }, + }, +} + + +def _filetime(value): + if isinstance(value, (bytes, bytearray)) and len(value) == 8: + value = struct.unpack("