SQLiteHunter Site

The Velociraptor SQLiteHunter Site #

This repository maintains the source for the Generic.Forensic.SQLiteHunter VQL artifact. This artifact is designed to be an efficient and mostly automated artifact to analyze and collect SQLite based artifacts from various applications on the endpoint.

The produced artifact is self contained and can be loaded into Velociraptor (https://docs.velociraptor.app) to hunt quickly and efficiently across a large number of endpoints.

You can download the latest artifact pack as a zip file, or as a YAML file and add it manually to Velociraptor.

Parameters #

  1. RuleFilter: If you dont want to run all the rules, you can filter the ones you need using this regular expression.

  2. Rules: Alteratively, the rules may be specified one at the time using a multi-choice selector.

  3. MatchFilename: Rules generally look for SQLite files using known filenames. If this option is unset, we relay on automatic detection to identify the filenames (For example, enumerate the tables in the SQLite file). This makes scanning much slower so by default this setting is enabled.

  4. CustomGlob: Rules default to search for SQLites using known globs. However, if you have a bunch of SQLite files in a different location, you may specify the custom glob to search for files.

  5. DateAfter and DateBefore: These setting allow you to time box the returned rows to only return items that occurred between the specified dates.

  6. FilterRegex: A filter that applies on the entire row (encoded as JSON). This is very useful to find all relevant rows relating to a specific item. For example, if you want to know any rows accessing www.example.com you can specify this filter which will return records like Visited links, bookmarks, favicons etc.

  7. SQLITE_ALWAYS_MAKE_TEMPFILE: By default Velociraptor will make a temporary copy of the SQLite file before parsing it. This ensure the file is not locked and can be freely accessed. If this setting is set to off parsing might be a lot slower as Velociraptor will have to contend with application locks. There is probably no reason to disable this.

  8. AlsoUpload: This option also uploads the raw SQLite files.

Artifact #



name: Generic.Forensic.SQLiteHunter
description: |
  Hunt for SQLite files.

  SQLite has become the de-facto standard for storing application data,
  in many types of applications:

  - Web Browsers
  - Operating Systems
  - Various applications, such as iMessage, TCC etc

  This artifact can hunt for these artifacts in a mostly automated way.
  More info at https://github.com/Velocidex/SQLiteHunter

  NOTE: If you want to use this artifact on just a bunch of files already
  collected (for example the files collected using the
  Windows.KapeFiles.Targets artifact) you can use the CustomGlob parameter
  (for example set it to "/tmp/unpacked/**" to consider all files in the
  unpacked directory).

column_types:
- name: Image
  type: preview_upload
- name: Payload
  type: preview_upload

export: |
  LET SPEC <= "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"
  LET Specs <= parse_json(data=gunzip(string=base64decode(string=SPEC)))
  LET CheckHeader(OSPath) = read_file(filename=OSPath, length=12) = "SQLite forma"
  LET Bool(Value) = if(condition=Value, then="Yes", else="No")

  -- In fast mode we check the filename, then the header then run the sqlite precondition
  LET matchFilename(SourceName, OSPath) = OSPath =~ get(item=Specs.sources, field=SourceName).filename
    AND CheckHeader(OSPath=OSPath)
    AND Identify(SourceName= SourceName, OSPath= OSPath)
    AND log(message=format(format="%v matched by filename %v",
            args=[OSPath, get(item=Specs.sources, field=SourceName).filename]))

  -- If the user wanted to also upload the file, do so now
  LET MaybeUpload(OSPath) = if(condition=AlsoUpload, then=upload(file=OSPath)) OR TRUE

  LET Identify(SourceName, OSPath) = SELECT if(
    condition=CheckHeader(OSPath=OSPath),
    then={
      SELECT *
      FROM sqlite(file=OSPath, query=get(item=Specs.sources, field=SourceName).id_query)
    }) AS Hits
  FROM scope()
  WHERE if(condition=Hits[0].Check = get(item=Specs.sources, field=SourceName).id_value,
    then= log(message="%v was identified as %v",
            args=[OSPath, get(item=Specs.sources, field=SourceName).Name]),
    else=log(message="%v was not identified as %v (got %v, wanted %v)",
             args=[OSPath, get(item=Specs.sources, field=SourceName).Name, str(str=Hits),
                   get(item=Specs.sources, field=SourceName).id_value]) AND FALSE)

  LET ApplyFile(SourceName) = SELECT * FROM foreach(row={
     SELECT OSPath FROM AllFiles
     WHERE if(condition=MatchFilename,  then=matchFilename(SourceName=SourceName, OSPath=OSPath),
      else=Identify(SourceName= SourceName, OSPath= OSPath))

  }, query={
     SELECT *, OSPath FROM sqlite(
        file=OSPath, query=get(item=Specs.sources, field=SourceName).SQL)
  })

  -- Filter for matching files without sqlite checks.
  LET FilterFile(SourceName) =
     SELECT OSPath FROM AllFiles
     WHERE if(condition=MatchFilename,
              then=OSPath =~ get(item=Specs.sources, field=SourceName).filename)

  -- Build a regex for all enabled categories.
  LET all_categories = SELECT if(condition=_value = "All", then=".", else=_value) AS _value
  FROM foreach(row=["All","MacOS","Browser","Chrome","Edge","Firefox","Google","Cloud","SyncClient","InternetExplorer","Windows"])
  WHERE get(field=_value)

parameters:
- name: RuleFilter
  type: regex
  description: Only collect rules matching this regex filter.
  default: "."

- name: Rules
  type: multichoice
  description: Only collect these rules
  default: '[]'
  choices:
  - "Chromium_Browser_Autofill"
  - "Chromium_Browser_Bookmarks"
  - "Chromium_Browser_Cookies"
  - "Chromium_Browser_Extensions"
  - "Chromium_Browser_Favicons"
  - "Chromium_Browser_History"
  - "Chromium_Browser_Media"
  - "Chromium_Browser_Network"
  - "Chromium_Browser_Notifications"
  - "Chromium_Browser_Shortcuts"
  - "Chromium_Browser_Top_Sites"
  - "Chromium_Sessions"
  - "Edge_Browser_Autofill"
  - "Edge_Browser_Collections"
  - "Edge_Browser_History_Screenshots"
  - "Edge_Browser_Navigation_History"
  - "Firefox_Cookies"
  - "Firefox_Downloads"
  - "Firefox_Favicons"
  - "Firefox_Form_History"
  - "Firefox_Places"
  - "Firefox_Places_History"
  - "Firefox_Places_History_Legacy"
  - "Google_Drive_Metadata"
  - "Google_Drive_Mirrored_Files"
  - "Google_Drive_Mirrored_Metadata_Files"
  - "Google_Drive_Sync_Roots"
  - "IE_or_Edge_WebCacheV01"
  - "IntelligencePlatform"
  - "MacOS_Applications_Cache"
  - "MacOS_NetworkUsage"
  - "MacOS_Notes"
  - "MacOS_XProtect_Detections"
  - "Safari_Browser_History"
  - "Windows_Activities_Cache"
  - "Windows_Search_Service"
  - "Windows_WPNDatabase___Notifications"
  - "iMessage"

- name: MatchFilename
  description: |
    If set we use the filename to detect the type of sqlite file.
    When unset we use heuristics (slower)
  type: bool
  default: Y

- name: CustomGlob
  description: Specify this glob to select other files

- name: DateAfter
  description: Timebox output to rows after this time.
  type: timestamp
  default: "1970-01-01T00:00:00Z"

- name: DateBefore
  description: Timebox output to rows after this time.
  type: timestamp
  default: "2100-01-01T00:00:00Z"

- name: FilterRegex
  description: Filter critical rows by this regex
  type: regex
  default: .

- name: All
  description: Select all targets
  type: bool
  default: Y

- name: MacOS
  description: Select targets with category MacOS
  type: bool
  default: N

- name: Browser
  description: Select targets with category Browser
  type: bool
  default: N

- name: Chrome
  description: Select targets with category Chrome
  type: bool
  default: N

- name: Edge
  description: Select targets with category Edge
  type: bool
  default: N

- name: Firefox
  description: Select targets with category Firefox
  type: bool
  default: N

- name: Google
  description: Select targets with category Google
  type: bool
  default: N

- name: Cloud
  description: Select targets with category Cloud
  type: bool
  default: N

- name: SyncClient
  description: Select targets with category SyncClient
  type: bool
  default: N

- name: InternetExplorer
  description: Select targets with category InternetExplorer
  type: bool
  default: N

- name: Windows
  description: Select targets with category Windows
  type: bool
  default: N

- name: SQLITE_ALWAYS_MAKE_TEMPFILE
  type: bool
  default: Y

- name: AlsoUpload
  description: If specified we also upload the identified file.
  type: bool

sources:
- name: AllFiles
  notebook:
   - type: vql
     template: |
       // This cell generates other cells to preview the collected
       // data.  DO NOT recalculate this cell - each time new cells
       // will be added. Instead delete the notebook and allow
       // Velociraptor to recreate the entire notebook.
       LET ArtifactsWithResults <=
         SELECT pathspec(accessor="fs", parse=Data.VFSPath)[4] AS Artifact ,
           pathspec(accessor="fs", parse=Data.VFSPath)[-1][:-5] AS Source ,
           stat(accessor="fs", filename=Data.VFSPath + ".index").Size / 8 AS Records
         FROM enumerate_flow(client_id=ClientId, flow_id=FlowId)
         WHERE Type =~ "Result" AND Records > 0

       LET _ <= SELECT notebook_update_cell(notebook_id=NotebookId, type="vql",
       input=format(format='''
       /*
       # Results From %v
       */
       SELECT * FROM source(source=%q, artifact=%q)
       ''', args=[Source, Source, split(string=ArtifactName, sep='/')[0]]),
       output=format(format='''
       <i>Recalculate</i> to show Results from <b>%v</b> with <b>%v</b> rows
       ''', args=[Source, Records])) AS NotebookModification
       FROM ArtifactsWithResults

       /*
       # Results Overview
       */
       SELECT Source, Records FROM ArtifactsWithResults ORDER BY Source

  query: |
    LET category_regex <= join(sep="|", array=all_categories._value)

    LET RuleFilter <= if(condition=Rules,
                         then=join(array=Rules, sep="|"),
                         else=RuleFilter)

    LET _ <= log(level="DEBUG", message="Rule Filter is %v", args=RuleFilter)

    LET AllGlobs <= filter(list=Specs.globs,
      condition="x=> x.tags =~ category_regex AND x.rule =~ RuleFilter")

    LET _ <= log(message="Globs for category %v is %v",
       args=[category_regex, CustomGlob || AllGlobs.glob])

    LET AllFiles <= SELECT OSPath FROM glob(globs=CustomGlob || AllGlobs.glob)
    WHERE NOT IsDir AND MaybeUpload(OSPath=OSPath)

    SELECT * FROM AllFiles



  
- name: IntelligencePlatform_Wifi
  notebook:
    - type: none
      output: "IntelligencePlatform_Wifi - Recalculate to view results"
      template: |
        /*
        # IntelligencePlatform_Wifi
        */
        SELECT * FROM source(source="IntelligencePlatform_Wifi")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="IntelligencePlatform_Wifi")

    // linter: symbol_mask_warn:timestamp

    LET Output = SELECT timestamp(cocoatime=timestamp) AS Timestamp,
           behaviorType,
           split(string=behaviorIdentifier, sep=':')[0] AS event,
           split(string=behaviorIdentifier, sep=':')[1] AS network,
           OSPath[1] AS User
    FROM Rows

    SELECT * FROM
    if(condition="IntelligencePlatform_Wifi" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Safari_Browser_History_Visits
  notebook:
    - type: none
      output: "Safari_Browser_History_Visits - Recalculate to view results"
      template: |
        /*
        # Safari_Browser_History_Visits
        */
        SELECT * FROM source(source="Safari_Browser_History_Visits")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Safari_Browser_History_Visits")

    

    LET Output = SELECT ID,
       timestamp(epoch=visit_time + 978307200) AS VisitTime,
       URL, Title, VisitCount, DomainExpansion,
       if(condition=Origin = 0,
          then="Local",
          else="iCloud Sync") AS Origin,
       Bool(Value=LoadSuccessful) AS LoadSuccessful,
       Bool(Value=HttpNonGet) AS HttpNonGet,
       RedirectSource, RedirectDestination, OSPath
    FROM Rows
    WHERE VisitTime > DateAfter AND VisitTime < DateBefore
      AND (URL, Title, RedirectSource, RedirectDestination) =~ FilterRegex

    SELECT * FROM
    if(condition="Safari_Browser_History_Visits" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: iMessage_Profiles
  notebook:
    - type: none
      output: "iMessage_Profiles - Recalculate to view results"
      template: |
        /*
        # iMessage_Profiles
        */
        SELECT * FROM source(source="iMessage_Profiles")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="iMessage_Profiles")

    

    LET Output = SELECT timestamp(epoch=date / 1000000000 + 978307200) AS Timestamp, *
    FROM Rows
    WHERE Timestamp > DateAfter AND Timestamp < DateBefore
      AND (MessageText, RoomName) =~ FilterRegex

    SELECT * FROM
    if(condition="iMessage_Profiles" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Chromium_Browser_Autofill_Profiles
  notebook:
    - type: none
      output: "Chromium_Browser_Autofill_Profiles - Recalculate to view results"
      template: |
        /*
        # Chromium_Browser_Autofill_Profiles
        */
        SELECT * FROM source(source="Chromium_Browser_Autofill_Profiles")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Chromium_Browser_Autofill_Profiles")

    

    LET Output = SELECT GUID,
      timestamp(epoch= date_modified) AS DateModified,
      timestamp(epoch= use_date) AS UseDate,
      FirstName, MiddleName, LastName, EmailAddress,
      PhoneNumber, CompanyName, StreetAddress,
      City, State, ZipCode, UseCount, OSPath
    FROM Rows
    WHERE UseDate > DateAfter AND UseDate < DateBefore
      AND (FirstName, MiddleName, LastName, EmailAddress, CompanyName, StreetAddress) =~ FilterRegex

    SELECT * FROM
    if(condition="Chromium_Browser_Autofill_Profiles" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Chromium_Browser_Autofill_Masked_Credit_Cards
  notebook:
    - type: none
      output: "Chromium_Browser_Autofill_Masked Credit Cards - Recalculate to view results"
      template: |
        /*
        # Chromium_Browser_Autofill_Masked Credit Cards
        */
        SELECT * FROM source(source="Chromium_Browser_Autofill_Masked Credit Cards")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Chromium_Browser_Autofill_Masked Credit Cards")

    

    LET Output = SELECT * FROM Rows

    SELECT * FROM
    if(condition="Chromium_Browser_Autofill_Masked Credit Cards" =~ RuleFilter, then={
       SELECT * FROM Output
    })


- name: Chromium_Browser_Bookmarks
  notebook:
    - type: none
      output: "Chromium_Browser_Bookmarks - Recalculate to view results"
      template: |
        /*
        # Chromium_Browser_Bookmarks
        */
        SELECT * FROM source(source="Chromium_Browser_Bookmarks")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM FilterFile(SourceName="Chromium_Browser_Bookmarks")

    -- Recursive function to report the details of a folder
    LET ReportFolder(Data, BaseName) = SELECT * FROM chain(a={
      -- First row emit the data about the actual folder
      SELECT BaseName + " | " + Data.name AS Name,
             timestamp(winfiletime=int(int=Data.date_added) * 10) AS DateAdded,
             timestamp(winfiletime=int(int=Data.date_last_used) * 10) AS DateLastUsed,
             Data.type AS Type,
             Data.url || ""  AS URL
      FROM scope()
    },
    b={
       -- If this folder has children recurse into it
       SELECT * FROM foreach(row={
          SELECT _value FROM items(item=Data.children)
       },  query={
          SELECT * FROM ReportFolder(Data=_value, BaseName=BaseName + " | " + Data.name)
       })
    })
    
    LET MatchingFiles = SELECT OSPath, parse_json(data=read_file(filename=OSPath)) AS Data
    FROM Rows

    LET Output = SELECT * FROM foreach(row=MatchingFiles, query={
      SELECT * FROM chain(
      a={
        SELECT OSPath, *, "bookmark_bar" AS Type
        FROM ReportFolder(Data=Data.roots.bookmark_bar, BaseName="")
      },
      b={
        SELECT OSPath, *, "other" AS Type
        FROM ReportFolder(Data=Data.roots.other, BaseName="")
      },
      c={
        SELECT OSPath, *, "synced" AS Type
        FROM ReportFolder(Data=Data.roots.synced, BaseName="")
      })
    })

    SELECT * FROM
    if(condition="Chromium_Browser_Bookmarks" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Chromium_Browser_Cookies_Cookies
  notebook:
    - type: none
      output: "Chromium_Browser_Cookies_Cookies - Recalculate to view results"
      template: |
        /*
        # Chromium_Browser_Cookies_Cookies
        */
        SELECT * FROM source(source="Chromium_Browser_Cookies_Cookies")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Chromium_Browser_Cookies_Cookies")

    

    LET Output = SELECT timestamp(winfiletime=(creation_utc * 10) || 0) AS CreationUTC,
           timestamp(winfiletime=(expires_utc * 10) || 0) AS ExpiresUTC,
           timestamp(winfiletime=(last_access_utc * 10) || 0) AS LastAccessUTC,
           timestamp(winfiletime=(last_update_utc * 10) || 0) AS LastUpdateUTC,
           HostKey, Name, Path,
           Bool(Value=is_secure) AS IsSecure,
           Bool(Value=is_httponly) AS IsHttpOnly,
           Bool(Value=has_expires) AS HasExpiration,
           Bool(Value=is_persistent) AS IsPersistent,
           Priority, SourcePort, OSPath
    FROM Rows
    WHERE LastAccessUTC > DateAfter AND LastAccessUTC < DateBefore
      AND (Name, Path) =~ FilterRegex

    SELECT * FROM
    if(condition="Chromium_Browser_Cookies_Cookies" =~ RuleFilter, then={
       SELECT * FROM Output
    })


- name: Chromium_Browser_Extensions
  notebook:
    - type: none
      output: "Chromium_Browser_Extensions - Recalculate to view results"
      template: |
        /*
        # Chromium_Browser_Extensions
        */
        SELECT * FROM source(source="Chromium_Browser_Extensions")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM FilterFile(SourceName="Chromium_Browser_Extensions")

    -- Resolve the message string against the Locale dict
    LET ResolveName(Message, Locale) = get(item=Locale,
          field=lowcase(string=parse_string_with_regex(regex="^__MSG_(.+)__$", string=Message).g1),
          default=Message).message || Message
    
    -- Read the manifest files
    LET ManifestData = SELECT OSPath, parse_json(data=read_file(filename=OSPath)) AS Manifest
    FROM Rows
    
    -- Message names are case insensitive so lower case the keys to
    -- match ResolveName()
    LET LowerKeys(Item) = to_dict(item={
       SELECT lowcase(string=_key) AS _key, _value FROM items(item=Item)
    })
    
    -- Find the Locale file to help with.
    LET LocaleData = SELECT *, if(condition=Manifest.default_locale, else=dict(),
         then=LowerKeys(Item=parse_json(data=read_file(
            filename=OSPath.Dirname + "_locales" + Manifest.default_locale + "messages.json")))) AS Locale
    FROM ManifestData
    
    LET GetIcon(Manifest) = Manifest.icons.`128` || Manifest.icons.`64` || Manifest.icons.`32` || Manifest.icons.`16`
    
    -- Flatten the matches of all content scripts into one list of unique sites.
    LET ContentScriptMatches(Manifest) = SELECT * FROM foreach(
       row=Manifest.content_scripts,
       query={ SELECT _value FROM foreach(row=matches) })
       GROUP BY _value

    LET Output = SELECT OSPath,
      -- Manifests are stored in Extensions/<ID>/<Version>/
      OSPath.Components[-3] AS ID,
      OSPath.Components[-2] AS Version,
      Manifest.author.email AS Email,
      ResolveName(Message = Manifest.name, Locale=Locale) AS name,
      ResolveName(Message = Manifest.description, Locale=Locale) AS description,
      Manifest.manifest_version AS ManifestVersion,
      Manifest.oauth2.scopes as Scopes,
      Manifest.permissions as Permissions,
      Manifest.host_permissions AS HostPermissions,
      ContentScriptMatches(Manifest=Manifest)._value AS ContentScriptMatches,
      Manifest.key as Key, if(condition=GetIcon(Manifest=Manifest),
                then=upload(file=OSPath.Dirname + GetIcon(Manifest=Manifest))) AS Image,
      Manifest AS _Manifest
    FROM LocaleData
    WHERE (name, description) =~ FilterRegex

    SELECT * FROM
    if(condition="Chromium_Browser_Extensions" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Chromium_Browser_Favicons
  notebook:
    - type: none
      output: "Chromium_Browser_Favicons - Recalculate to view results"
      template: |
        /*
        # Chromium_Browser_Favicons
        */
        SELECT * FROM source(source="Chromium_Browser_Favicons")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Chromium_Browser_Favicons")

    

    LET Output = SELECT ID, IconID,
      timestamp(winfiletime= (LastUpdated * 10) || 0) AS LastUpdated,
      PageURL, FaviconURL,
      upload(accessor="data",
         file=_image,
         name=format(format="Image%v.png", args=ID)) AS Image,
      OSPath as _OSPath
    FROM Rows
    WHERE LastUpdated > DateAfter AND LastUpdated < DateBefore

    SELECT * FROM
    if(condition="Chromium_Browser_Favicons" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Chromium_Browser_History_Visits
  notebook:
    - type: none
      output: "Chromium_Browser_History_Visits - Recalculate to view results"
      template: |
        /*
        # Chromium_Browser_History_Visits
        */
        SELECT * FROM source(source="Chromium_Browser_History_Visits")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Chromium_Browser_History_Visits")

    

    LET Output = SELECT ID,
       timestamp(winfiletime=(visit_time * 10) || 0) AS VisitTime,
       timestamp(winfiletime=(last_visit_time * 10) || 0) AS LastVisitedTime,
       URLTitle, URL, VisitCount, TypedCount,
       if(condition=hidden =~ '1', then="Yes", else="No") AS Hidden,
       VisitID, FromVisitID,
       visit_duration / 1000000 AS VisitDurationInSeconds,
       OSPath
    FROM Rows
    WHERE VisitTime > DateAfter
      AND VisitTime < DateBefore
      AND (URLTitle, URL) =~ FilterRegex

    SELECT * FROM
    if(condition="Chromium_Browser_History_Visits" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Chromium_Browser_History_Downloads
  notebook:
    - type: none
      output: "Chromium_Browser_History_Downloads - Recalculate to view results"
      template: |
        /*
        # Chromium_Browser_History_Downloads
        */
        SELECT * FROM source(source="Chromium_Browser_History_Downloads")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Chromium_Browser_History_Downloads")

    LET StateLookup <= dict(`0`='In Progress', `1`='Complete', `2`="Cancelled", `3`="Interrupted", `4`="Interrupted")
    LET DangerType <= dict(`0`='Not Dangerous', `1`="Dangerous", `2`='Dangerous URL', `3`='Dangerous Content',
        `4`='Content May Be Malicious', `5`='Uncommon Content', `6`='Dangerous But User Validated',
        `7`='Dangerous Host', `8`='Potentially Unwanted', `9`='Whitelisted by Policy',
        `10`='Download Pending Detailed Verdict', `11`='Blocked By Policy Password Protected', `12`='Blocked By Policy Download Too Large',
        `13`='Sensitive Content Warning', `14`='Sensitive Content Blocked', `15`='Deep Scanned Safe',
        `16`='Deep Scanned Dangerous But Opened By User', `17`='Prompt For Deep Scanning', `18`='Blocked Unsupported Filetype',
        `19`='Dangerous Associated With Account Compromise', `20`='Deep Scan Failed', `21`='Encrypted Archive Prompt for Local Password Scanning',
        `22`='Encrypted Archive Prompt for Local Password Scanning Pending Detailed Verdict', `23`='Blocked by Policy Scan Failed')
    LET InterruptReason <= dict(`0`= 'No Interrupt', `1`= 'File Error', `2`='Access Denied', `3`='Disk Full',
      `5`='Path Too Long',`6`='File Too Large', `7`='Virus', `10`='Temporary Problem', `11`='Blocked',
      `12`='Security Check Failed', `13`='Resume Error File Too Short', `14`='File Hash Mismatch', `15`='File Same As Source',
      `20`='Network Error', `21`='Operation Timed Out', `22`='Connection Lost', `23`='Server Down',
      `24`='Network Request Invalid', `30`='Server Error', `31`='Range Request Error',
      `32`='Server Precondition Error', `33`='Unable to get file', `34`='Server Unauthorized',
      `35`='Server Certificate Problem', `36`='Server Access Forbidden', `37`='Server Unreachable',
      `38`='Content Length Mismatch', `39`='Cross Origin Redirect', `40`='Cancelled', `41`='Browser Shutdown',
      `50`='Browser Crashed')

    LET Output = SELECT ID, GUID, CurrentPath, TargetPath, OriginalMIMEType, ReceivedBytes, TotalBytes,
      timestamp(winfiletime=(start_time * 10) || 0) AS StartTime,
      timestamp(winfiletime=(end_time * 10) || 0) AS EndTime,
      timestamp(winfiletime=(opened * 10) || 0) AS Opened,
      timestamp(winfiletime=(last_access_time * 10) || 0) AS LastAccessTime,
      timestamp(epoch=last_modified) AS LastModified,
      get(item=StateLookup, field=str(str=state), default="Unknown") AS State,
      get(item=DangerType, field=str(str=danger_type), default="Unknown") AS DangerType,
      get(item=InterruptReason, field=str(str=interrupt_reason), default="Unknown") AS InterruptReason,
      ReferrerURL, SiteURL, TabURL, TabReferrerURL, DownloadURL, OSPath
    FROM Rows
    WHERE LastAccessTime > DateAfter AND LastAccessTime < DateBefore
      AND (SiteURL, DownloadURL, TabURL, TabReferrerURL, ReferrerURL, DownloadURL) =~ FilterRegex

    SELECT * FROM
    if(condition="Chromium_Browser_History_Downloads" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Chromium_Browser_History_Keywords
  notebook:
    - type: none
      output: "Chromium_Browser_History_Keywords - Recalculate to view results"
      template: |
        /*
        # Chromium_Browser_History_Keywords
        */
        SELECT * FROM source(source="Chromium_Browser_History_Keywords")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Chromium_Browser_History_Keywords")

    

    LET Output = SELECT KeywordID, URLID,
       timestamp(winfiletime=(last_visit_time * 10) || 0) AS LastVisitedTime,
       KeywordSearchTerm, Title, URL, OSPath
    FROM Rows
    WHERE LastVisitedTime > DateAfter AND LastVisitedTime < DateBefore
      AND (Title, KeywordSearchTerm, URL) =~ FilterRegex

    SELECT * FROM
    if(condition="Chromium_Browser_History_Keywords" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Chromium_Browser_Media_History
  notebook:
    - type: none
      output: "Chromium_Browser_Media_History - Recalculate to view results"
      template: |
        /*
        # Chromium_Browser_Media_History
        */
        SELECT * FROM source(source="Chromium_Browser_Media_History")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Chromium_Browser_Media_History")

    

    LET Output = SELECT ID, URL, WatchTimeSeconds,
       Bool(Value=has_video) AS HasVideo,
       Bool(Value=has_audio) AS HasAudio,
       timestamp(winfiletime=last_updated_time_s || 0) AS LastUpdated,
       OriginID, OSPath
    FROM Rows
    WHERE LastUpdated > DateAfter AND LastUpdated < DateBefore
      AND URL =~ FilterRegex

    SELECT * FROM
    if(condition="Chromium_Browser_Media_History" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Chromium_Browser_Media_Playback_Session
  notebook:
    - type: none
      output: "Chromium_Browser_Media_Playback Session - Recalculate to view results"
      template: |
        /*
        # Chromium_Browser_Media_Playback Session
        */
        SELECT * FROM source(source="Chromium_Browser_Media_Playback Session")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Chromium_Browser_Media_Playback Session")

    

    LET Output = SELECT ID,
      timestamp(winfiletime=last_updated_time_s || 0) AS LastUpdated, URL,
      duration_ms / 1000 AS DurationInSeconds,
      position_ms / 1000 AS PositionInSeconds,
      Title, Artist, Album, SourceTitle, OriginID, OSPath
    FROM Rows
    WHERE LastUpdated > DateAfter AND LastUpdated < DateBefore
      AND URL =~ FilterRegex

    SELECT * FROM
    if(condition="Chromium_Browser_Media_Playback Session" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Chromium_Browser_Network_Predictor
  notebook:
    - type: none
      output: "Chromium_Browser_Network_Predictor - Recalculate to view results"
      template: |
        /*
        # Chromium_Browser_Network_Predictor
        */
        SELECT * FROM source(source="Chromium_Browser_Network_Predictor")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Chromium_Browser_Network_Predictor")

    

    LET Output = SELECT * FROM Rows
    WHERE UserText =~ FilterRegex

    SELECT * FROM
    if(condition="Chromium_Browser_Network_Predictor" =~ RuleFilter, then={
       SELECT * FROM Output
    })


- name: Chromium_Browser_Notifications_Site_Engagements
  notebook:
    - type: none
      output: "Chromium_Browser_Notifications_Site Engagements - Recalculate to view results"
      template: |
        /*
        # Chromium_Browser_Notifications_Site Engagements
        */
        SELECT * FROM source(source="Chromium_Browser_Notifications_Site Engagements")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM FilterFile(SourceName="Chromium_Browser_Notifications_Site Engagements")

    LET JSON = SELECT parse_json(data=read_file(filename=OSPath)) AS Data, OSPath FROM Rows

    LET Output = SELECT * FROM foreach(row={
      SELECT OSPath, Data.profile.content_settings.exceptions AS exceptions FROM JSON
    },  query={
      SELECT _key AS Site,
         timestamp(winfiletime=int(int=_value.last_modified) * 10 || 0) AS LastModified,
         timestamp(winfiletime=int(int=_value.setting.lastEngagementTime) * 10 || 0) AS LastEngagementTime,
         OSPath
      FROM items(item=exceptions.site_engagement)
    })

    SELECT * FROM
    if(condition="Chromium_Browser_Notifications_Site Engagements" =~ RuleFilter, then={
       SELECT * FROM Output
    })


- name: Chromium_Browser_Notifications_App_Banners
  notebook:
    - type: none
      output: "Chromium_Browser_Notifications_App Banners - Recalculate to view results"
      template: |
        /*
        # Chromium_Browser_Notifications_App Banners
        */
        SELECT * FROM source(source="Chromium_Browser_Notifications_App Banners")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM FilterFile(SourceName="Chromium_Browser_Notifications_App Banners")

    LET JSON = SELECT parse_json(data=read_file(filename=OSPath)) AS Data, OSPath FROM Rows

    LET Output = SELECT * FROM foreach(row={
      SELECT OSPath, Data.profile.content_settings.exceptions AS exceptions FROM JSON
    },  query={
      SELECT _key AS Site,
         timestamp(winfiletime=int(int=_value.last_modified) * 10 || 0) AS LastModified,
         {
           SELECT _key AS Site,
              timestamp(winfiletime=int(int=_value.couldShowBannerEvents) * 10 || 0) AS CouldShowBannerEvents,
              timestamp(winfiletime=int(int=_value.next_install_text_animation.last_shown) * 10 || 0) AS LastShown
           FROM items(item=_value.setting)
         } AS Setting,
         OSPath
      FROM items(item=exceptions.app_banner)
    })

    SELECT * FROM
    if(condition="Chromium_Browser_Notifications_App Banners" =~ RuleFilter, then={
       SELECT * FROM Output
    })


- name: Chromium_Browser_Notifications_Notification_Preferences
  notebook:
    - type: none
      output: "Chromium_Browser_Notifications_Notification Preferences - Recalculate to view results"
      template: |
        /*
        # Chromium_Browser_Notifications_Notification Preferences
        */
        SELECT * FROM source(source="Chromium_Browser_Notifications_Notification Preferences")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM FilterFile(SourceName="Chromium_Browser_Notifications_Notification Preferences")

    LET ContentSettings <= array(`0`="Default",`1`="Allow",`2`="Block",`3`="Ask",`4`="Session Only",`5`="Detect Important Content")
    
    LET JSON = SELECT parse_json(data=read_file(filename=OSPath)) AS Data, OSPath FROM Rows

    LET Output = SELECT * FROM foreach(row={
      SELECT OSPath, Data.profile.content_settings.exceptions AS exceptions FROM JSON
    },  query={
      SELECT _key AS Site,
        timestamp(winfiletime=int(int=_value.last_modified) * 10 || 0) AS LastModified,
        ContentSettings[_value.setting] AS Setting,
        OSPath
      FROM items(item=exceptions.notifications)
    })

    SELECT * FROM
    if(condition="Chromium_Browser_Notifications_Notification Preferences" =~ RuleFilter, then={
       SELECT * FROM Output
    })


- name: Chromium_Browser_Notifications_Notification_Interactions
  notebook:
    - type: none
      output: "Chromium_Browser_Notifications_Notification Interactions - Recalculate to view results"
      template: |
        /*
        # Chromium_Browser_Notifications_Notification Interactions
        */
        SELECT * FROM source(source="Chromium_Browser_Notifications_Notification Interactions")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM FilterFile(SourceName="Chromium_Browser_Notifications_Notification Interactions")

    LET JSON = SELECT parse_json(data=read_file(filename=OSPath)) AS Data, OSPath FROM Rows
    LET S = scope()

    LET Output = SELECT * FROM foreach(row={
      SELECT OSPath, Data.profile.content_settings.exceptions AS exceptions FROM JSON
    },  query={
      SELECT _key AS URL,
        timestamp(winfiletime=int(int=_value.last_modified) * 10 || 0) AS LastModified,
        _value.display_count as DisplayCount,
        _value.click_count as ClickCount,
        OSPath
      FROM items(item=S.notification_interactions || dict())
    })

    SELECT * FROM
    if(condition="Chromium_Browser_Notifications_Notification Interactions" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Chromium_Browser_Shortcuts
  notebook:
    - type: none
      output: "Chromium_Browser_Shortcuts - Recalculate to view results"
      template: |
        /*
        # Chromium_Browser_Shortcuts
        */
        SELECT * FROM source(source="Chromium_Browser_Shortcuts")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Chromium_Browser_Shortcuts")

    

    LET Output = SELECT ID,
      timestamp(winfiletime= (last_access_time * 10) || 0) AS LastAccessTime,
      TextTyped, FillIntoEdit, URL, Contents,
      Description, Type, Keyword, TimesSelectedByUser, OSPath
    FROM Rows
    WHERE LastAccessTime > DateAfter AND LastAccessTime < DateBefore
      AND (Contents, Description) =~ FilterRegex

    SELECT * FROM
    if(condition="Chromium_Browser_Shortcuts" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Chromium_Sessions_Sessions
  notebook:
    - type: none
      output: "Chromium_Sessions_Sessions - Recalculate to view results"
      template: |
        /*
        # Chromium_Sessions_Sessions
        */
        SELECT * FROM source(source="Chromium_Sessions_Sessions")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Chromium_Sessions_Sessions")

    

    LET Output = SELECT timestamp(winfiletime=(creation_utc * 10) || 0) AS CreationUTC,
           timestamp(winfiletime=(expires_utc * 10) || 0) AS ExpiresUTC,
           timestamp(winfiletime=(last_access_utc * 10) || 0) AS LastAccessUTC,
           HostKey, Name, Path,
           Bool(Value=is_secure) AS IsSecure,
           Bool(Value=is_httponly) AS IsHttpOnly,
           Bool(Value=has_expires) AS HasExpiration,
           Bool(Value=is_persistent) AS IsPersistent,
           Priority, SourcePort, OSPath
    FROM Rows
    WHERE LastAccessUTC > DateAfter AND LastAccessUTC < DateBefore
      AND (Name, Path) =~ FilterRegex

    SELECT * FROM
    if(condition="Chromium_Sessions_Sessions" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Chromium_Browser_Top_Sites
  notebook:
    - type: none
      output: "Chromium_Browser_Top_Sites - Recalculate to view results"
      template: |
        /*
        # Chromium_Browser_Top_Sites
        */
        SELECT * FROM source(source="Chromium_Browser_Top_Sites")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Chromium_Browser_Top_Sites")

    

    LET Output = SELECT * FROM Rows
    WHERE ( URL =~ FilterRegex OR Title =~ FilterRegex )

    SELECT * FROM
    if(condition="Chromium_Browser_Top_Sites" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Edge_Browser_Autofill_CombinedAutofill
  notebook:
    - type: none
      output: "Edge_Browser_Autofill_CombinedAutofill - Recalculate to view results"
      template: |
        /*
        # Edge_Browser_Autofill_CombinedAutofill
        */
        SELECT * FROM source(source="Edge_Browser_Autofill_CombinedAutofill")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Edge_Browser_Autofill_CombinedAutofill")

    

    LET Output = SELECT timestamp(epoch=date_last_used) AS DateLastUsed, *
    FROM Rows
    WHERE DateLastUsed > DateAfter AND DateLastUsed < DateBefore

    SELECT * FROM
    if(condition="Edge_Browser_Autofill_CombinedAutofill" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Edge_Browser_Collections_Collections__Items__and_Comments
  notebook:
    - type: none
      output: "Edge_Browser_Collections_Collections, Items, and Comments - Recalculate to view results"
      template: |
        /*
        # Edge_Browser_Collections_Collections, Items, and Comments
        */
        SELECT * FROM source(source="Edge_Browser_Collections_Collections, Items, and Comments")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Edge_Browser_Collections_Collections, Items, and Comments")

    LET ExtractImage(Data) = base64decode(
      string=split(string=parse_json(data=Data).image, sep=",")[1])

    LET Output = SELECT *,
       timestamp(epoch=Collection_CreationUTC) AS Collection_CreationUTC,
       timestamp(epoch=Collection_ModifiedUTC) AS Collection_ModifiedUTC,
       timestamp(epoch=ColletionSync_DateLastSynced) AS ColletionSync_DateLastSynced,
       timestamp(epoch=Item_CreationUTC) AS Item_CreationUTC,
       timestamp(epoch=Item_ModifiedUTC) AS Item_ModifiedUTC,
       parse_json(data= Item_Source) AS Item_Source,
       upload(accessor="data",
              file=ExtractImage(Data=Image),
              name=format(format="Screenshot_%v.png", args=item_id)) AS Image,
       timestamp(epoch=ItemSync_DaeLastSynced) AS ItemSync_DaeLastSynced
    FROM Rows

    SELECT * FROM
    if(condition="Edge_Browser_Collections_Collections, Items, and Comments" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Edge_Browser_Navigation_History_Navigation_History
  notebook:
    - type: none
      output: "Edge_Browser_Navigation_History_Navigation History - Recalculate to view results"
      template: |
        /*
        # Edge_Browser_Navigation_History_Navigation History
        */
        SELECT * FROM source(source="Edge_Browser_Navigation_History_Navigation History")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Edge_Browser_Navigation_History_Navigation History")

    

    LET Output = SELECT ID,
       timestamp(epoch=`Last Visited Time`) AS `Last Visited Time`,
       Title, URL, VisitCount, OSPath
    FROM Rows
    WHERE `Last Visited Time` > DateAfter
      AND `Last Visited Time` < DateBefore
      AND (Title, URL) =~ FilterRegex

    SELECT * FROM
    if(condition="Edge_Browser_Navigation_History_Navigation History" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Edge_Browser_History_Screenshots_Screenshots
  notebook:
    - type: none
      output: "Edge_Browser_History_Screenshots_Screenshots - Recalculate to view results"
      template: |
        /*
        # Edge_Browser_History_Screenshots_Screenshots
        */
        SELECT * FROM source(source="Edge_Browser_History_Screenshots_Screenshots")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Edge_Browser_History_Screenshots_Screenshots")

    

    LET Output = SELECT *,
           timestamp(winfiletime=VisitTime * 10) AS VisitTime,
           VisitTime AS VisitTimeInt,
           upload(accessor="data",
             file=Image,
             name=format(format="Screenshot_%v.png", args=VisitID)) AS Image
    FROM Rows

    SELECT * FROM
    if(condition="Edge_Browser_History_Screenshots_Screenshots" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Firefox_Places_Bookmarks
  notebook:
    - type: none
      output: "Firefox_Places_Bookmarks - Recalculate to view results"
      template: |
        /*
        # Firefox_Places_Bookmarks
        */
        SELECT * FROM source(source="Firefox_Places_Bookmarks")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Firefox_Places_Bookmarks")

    LET BookmarkTypes <= dict(`1`='URL', `2`='Folder', `3`='Separator')

    LET Output = SELECT ID, ParentID,
       get(item= BookmarkTypes, field=str(str=type), default="Unknown") AS Type,
       timestamp(epoch=dateAdded) AS DateAdded,
       timestamp(epoch=lastModified) AS LastModified,
       Position, Title, URL, ForeignKey, OSPath
    FROM Rows
    WHERE LastModified > DateAfter AND LastModified < DateBefore
      AND (Title, URL) =~ FilterRegex

    SELECT * FROM
    if(condition="Firefox_Places_Bookmarks" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Firefox_Places_Downloads
  notebook:
    - type: none
      output: "Firefox_Places_Downloads - Recalculate to view results"
      template: |
        /*
        # Firefox_Places_Downloads
        */
        SELECT * FROM source(source="Firefox_Places_Downloads")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Firefox_Places_Downloads")

    LET DownloadTypes <= dict(`downloads/destinationFileURI`='FileURI', `downloads/destinationFileName`='Filename', `downloads/metaData`='Metadata')

    LET Output = SELECT PlaceID, URL, Content,
       get(item= DownloadTypes, field=str(str=name), default="Unknown") AS Type,
       timestamp(epoch=dateAdded) AS DateAdded,
       timestamp(epoch=lastModified) AS LastModified,
       OSPath
    FROM Rows
    WHERE LastModified > DateAfter AND LastModified < DateBefore
      AND (URL, Content) =~ FilterRegex

    SELECT * FROM
    if(condition="Firefox_Places_Downloads" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Firefox_Cookies
  notebook:
    - type: none
      output: "Firefox_Cookies - Recalculate to view results"
      template: |
        /*
        # Firefox_Cookies
        */
        SELECT * FROM source(source="Firefox_Cookies")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Firefox_Cookies")

    

    LET Output = SELECT ID, Host, Name, Value,
       timestamp(epoch= creationTime) AS CreationTime,
       timestamp(epoch= lastAccessed) AS LastAccessedTime,
       timestamp(epoch= expiry) AS Expiration,
       Bool(Value= isSecure) AS IsSecure,
       Bool(Value= isHttpOnly) AS IsHTTPOnly, OSPath
    FROM Rows
    WHERE LastAccessedTime > DateAfter
      AND LastAccessedTime < DateBefore
      AND ( Name =~ FilterRegex OR Value =~ FilterRegex )

    SELECT * FROM
    if(condition="Firefox_Cookies" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Firefox_Downloads
  notebook:
    - type: none
      output: "Firefox_Downloads - Recalculate to view results"
      template: |
        /*
        # Firefox_Downloads
        */
        SELECT * FROM source(source="Firefox_Downloads")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Firefox_Downloads")

    

    LET Output = SELECT ID, Name, MIMEType, Source, Target,
       timestamp(epoch= startTime) AS StartTime,
       timestamp(epoch= endTime) AS EndTime,
       timestamp(epoch= expiry) AS Expiration,
       CurrentBytes, MaxBytes, OSPath
    FROM Rows
    WHERE StartTime > DateAfter
      AND StartTime < DateBefore
      AND Name =~ FilterRegex

    SELECT * FROM
    if(condition="Firefox_Downloads" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Firefox_Favicons
  notebook:
    - type: none
      output: "Firefox_Favicons - Recalculate to view results"
      template: |
        /*
        # Firefox_Favicons
        */
        SELECT * FROM source(source="Firefox_Favicons")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Firefox_Favicons")

    

    LET Output = SELECT ID, PageURL, FaviconURL,
       timestamp(epoch= expire_ms) AS Expiration,
       OSPath
    FROM Rows

    SELECT * FROM
    if(condition="Firefox_Favicons" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Firefox_Form_History
  notebook:
    - type: none
      output: "Firefox_Form_History - Recalculate to view results"
      template: |
        /*
        # Firefox_Form_History
        */
        SELECT * FROM source(source="Firefox_Form_History")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Firefox_Form_History")

    

    LET Output = SELECT ID, FieldName, Value, TimesUsed,
       timestamp(epoch= firstUsed) AS FirstUsed,
       timestamp(epoch= lastUsed) AS LastUsed,
       GUID, OSPath
    FROM Rows
    WHERE LastUsed > DateAfter AND LastUsed < DateBefore
      AND ( FieldName =~ FilterRegex OR Value =~ FilterRegex )

    SELECT * FROM
    if(condition="Firefox_Form_History" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Firefox_Places_History
  notebook:
    - type: none
      output: "Firefox_Places_History - Recalculate to view results"
      template: |
        /*
        # Firefox_Places_History
        */
        SELECT * FROM source(source="Firefox_Places_History")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Firefox_Places_History")

    LET VisitType <= dict(`1`='TRANSITION_LINK', `2`='TRANSITION_TYPED', `3`='TRANSITION_BOOKMARK',
      `4`='TRANSITION_EMBED', `5`= 'TRANSITION_REDIRECT_PERMANENT', `6`='TRANSITION_REDIRECT_TEMPORARY',
      `7`='TRANSITION_DOWNLOAD', `8`='TRANSITION_FRAMED_LINK', `9`='TRANSITION_RELOAD')

    LET Output = SELECT VisitID, FromVisitID, PlaceID,
       timestamp(epoch= visit_date) AS VisitDate,
       timestamp(epoch= last_visit_date) AS LastVisitDate,
       VisitCount, URL, Title, Description,
       get(item= VisitType, field=str(str=visit_type), default="Unknown") AS VisitType,
       Bool(Value=hidden) AS Hidden,
       Bool(Value=typed) AS Typed,
       Frecency, PreviewImageURL, OSPath
    FROM Rows
    WHERE VisitDate > DateAfter AND VisitDate < DateBefore
      AND (Title, URL, Description) =~ FilterRegex

    SELECT * FROM
    if(condition="Firefox_Places_History" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Firefox_Places_History_Legacy
  notebook:
    - type: none
      output: "Firefox_Places_History_Legacy - Recalculate to view results"
      template: |
        /*
        # Firefox_Places_History_Legacy
        */
        SELECT * FROM source(source="Firefox_Places_History_Legacy")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Firefox_Places_History_Legacy")

    LET VisitType <= dict(`1`='TRANSITION_LINK', `2`='TRANSITION_TYPED', `3`='TRANSITION_BOOKMARK',
      `4`='TRANSITION_EMBED', `5`= 'TRANSITION_REDIRECT_PERMANENT', `6`='TRANSITION_REDIRECT_TEMPORARY',
      `7`='TRANSITION_DOWNLOAD', `8`='TRANSITION_FRAMED_LINK', `9`='TRANSITION_RELOAD')

    LET Output = SELECT VisitID, FromVisitID, PlaceID,
       timestamp(epoch= visit_date) AS VisitDate,
       timestamp(epoch= last_visit_date) AS LastVisitDate,
       VisitCount, URL, Title,
       get(item= VisitType, field=str(str=visit_type), default="Unknown") AS VisitType,
       Bool(Value=hidden) AS Hidden,
       Bool(Value=typed) AS Typed,
       Frecency, OSPath
    FROM Rows
    WHERE VisitDate > DateAfter AND VisitDate < DateBefore
      AND (Title, URL) =~ FilterRegex

    SELECT * FROM
    if(condition="Firefox_Places_History_Legacy" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Google_Drive_Metadata_File_Metadata
  notebook:
    - type: none
      output: "Google_Drive_Metadata_File Metadata - Recalculate to view results"
      template: |
        /*
        # Google_Drive_Metadata_File Metadata
        */
        SELECT * FROM source(source="Google_Drive_Metadata_File Metadata")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Google_Drive_Metadata_File Metadata")

    

    LET Output = SELECT timestamp(epoch=modified_date ) AS Timestamp, *
    FROM Rows
    WHERE
      if(condition=DateAfter, then=Timestamp > DateAfter, else=TRUE) AND
      if(condition=DateBefore, then=Timestamp < DateBefore, else=TRUE) AND
      (local_title, mime_type) =~ FilterRegex

    SELECT * FROM
    if(condition="Google_Drive_Metadata_File Metadata" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Google_Drive_Metadata_Deleted_Items
  notebook:
    - type: none
      output: "Google_Drive_Metadata_Deleted Items - Recalculate to view results"
      template: |
        /*
        # Google_Drive_Metadata_Deleted Items
        */
        SELECT * FROM source(source="Google_Drive_Metadata_Deleted Items")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Google_Drive_Metadata_Deleted Items")

    

    LET Output = SELECT * FROM Rows

    SELECT * FROM
    if(condition="Google_Drive_Metadata_Deleted Items" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Google_Drive_Mirrored_Files_Mirrored_Items
  notebook:
    - type: none
      output: "Google_Drive_Mirrored_Files_Mirrored Items - Recalculate to view results"
      template: |
        /*
        # Google_Drive_Mirrored_Files_Mirrored Items
        */
        SELECT * FROM source(source="Google_Drive_Mirrored_Files_Mirrored Items")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Google_Drive_Mirrored_Files_Mirrored Items")

    

    LET Output = SELECT timestamp(epoch=local_mtime_ms ) AS Timestamp, *
    FROM Rows
    WHERE
      if(condition=DateAfter, then=Timestamp > DateAfter, else=TRUE) AND
      if(condition=DateBefore, then=Timestamp < DateBefore, else=TRUE) AND
      (local_filename, cloud_filename, volume) =~ FilterRegex

    SELECT * FROM
    if(condition="Google_Drive_Mirrored_Files_Mirrored Items" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Google_Drive_Mirrored_Metadata_Files_Mirrored_Metadata_Items
  notebook:
    - type: none
      output: "Google_Drive_Mirrored_Metadata_Files_Mirrored Metadata Items - Recalculate to view results"
      template: |
        /*
        # Google_Drive_Mirrored_Metadata_Files_Mirrored Metadata Items
        */
        SELECT * FROM source(source="Google_Drive_Mirrored_Metadata_Files_Mirrored Metadata Items")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Google_Drive_Mirrored_Metadata_Files_Mirrored Metadata Items")

    

    LET Output = SELECT timestamp(epoch=modified_date ) AS Timestamp, *
    FROM Rows
    WHERE
      if(condition=DateAfter, then=Timestamp > DateAfter, else=TRUE) AND
      if(condition=DateBefore, then=Timestamp < DateBefore, else=TRUE) AND
      (local_title, mime_type) =~ FilterRegex

    SELECT * FROM
    if(condition="Google_Drive_Mirrored_Metadata_Files_Mirrored Metadata Items" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Google_Drive_Sync_Roots_Sync_Folders
  notebook:
    - type: none
      output: "Google_Drive_Sync_Roots_Sync Folders - Recalculate to view results"
      template: |
        /*
        # Google_Drive_Sync_Roots_Sync Folders
        */
        SELECT * FROM source(source="Google_Drive_Sync_Roots_Sync Folders")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Google_Drive_Sync_Roots_Sync Folders")

    

    LET Output = SELECT *
    FROM Rows
    WHERE (root_path, title, media_id) =~ FilterRegex

    SELECT * FROM
    if(condition="Google_Drive_Sync_Roots_Sync Folders" =~ RuleFilter, then={
       SELECT * FROM Output
    })


- name: IE_or_Edge_WebCacheV01_All_Data
  notebook:
    - type: none
      output: "IE_or_Edge_WebCacheV01_All Data - Recalculate to view results"
      template: |
        /*
        # IE_or_Edge_WebCacheV01_All Data
        */
        SELECT * FROM source(source="IE_or_Edge_WebCacheV01_All Data")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM FilterFile(SourceName="IE_or_Edge_WebCacheV01_All Data")

    LET MatchingFiles = SELECT OSPath FROM Rows
    LET S = scope()
    
    LET Containers(OSPath) = SELECT Table
    FROM parse_ese_catalog(file=OSPath)
    WHERE Table =~ "Container_"
    GROUP BY Table
    
    LET AllHits(OSPath) = SELECT * FROM foreach(row={
        SELECT * FROM Containers(OSPath=OSPath)
    }, query={
       SELECT timestamp(winfiletime=ExpiryTime) AS ExpiryTime,
          timestamp(winfiletime=ModifiedTime) AS ModifiedTime,
          timestamp(winfiletime=AccessedTime) AS AccessedTime,
          S.Url AS Url, *
       FROM parse_ese(file=OSPath, table=Table)
    })

    LET Output = SELECT * FROM foreach(row=MatchingFiles, query={
      SELECT * FROM AllHits(OSPath=OSPath)
    })
    WHERE AccessedTime > DateAfter AND AccessedTime < DateBefore
      AND Url =~ FilterRegex

    SELECT * FROM
    if(condition="IE_or_Edge_WebCacheV01_All Data" =~ RuleFilter, then={
       SELECT * FROM Output
    })


- name: IE_or_Edge_WebCacheV01_Highlights
  notebook:
    - type: none
      output: "IE_or_Edge_WebCacheV01_Highlights - Recalculate to view results"
      template: |
        /*
        # IE_or_Edge_WebCacheV01_Highlights
        */
        SELECT * FROM source(source="IE_or_Edge_WebCacheV01_Highlights")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM FilterFile(SourceName="IE_or_Edge_WebCacheV01_Highlights")

    

    LET Output = SELECT * FROM foreach(row=MatchingFiles, query={
      SELECT AccessedTime, ModifiedTime, ExpiryTime, Url
      FROM AllHits(OSPath=OSPath)
    })
    WHERE AccessedTime > DateAfter AND AccessedTime < DateBefore
      AND Url =~ FilterRegex

    SELECT * FROM
    if(condition="IE_or_Edge_WebCacheV01_Highlights" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: MacOS_Applications_Cache
  notebook:
    - type: none
      output: "MacOS_Applications_Cache - Recalculate to view results"
      template: |
        /*
        # MacOS_Applications_Cache
        */
        SELECT * FROM source(source="MacOS_Applications_Cache")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="MacOS_Applications_Cache")

    // linter: symbol_mask_warn:version

    LET Output = SELECT
       time_stamp AS Timestamp,
       OSPath.Base AS Application,
       entry_ID AS EntryID,
       version AS Version,
       hash_value AS Hash,
       storage_policy AS StoragePolicy,
       request_key AS URL,
       plist(file=request_object, accessor="data") AS Request,
       plist(file=response_object, accessor="data") AS Response,
       partition AS Partition,
       OSPath
    FROM Rows
    WHERE Timestamp > DateAfter AND Timestamp < DateBefore
      AND Application =~ FilterRegex

    SELECT * FROM
    if(condition="MacOS_Applications_Cache" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: MacOS_NetworkUsage
  notebook:
    - type: none
      output: "MacOS_NetworkUsage - Recalculate to view results"
      template: |
        /*
        # MacOS_NetworkUsage
        */
        SELECT * FROM source(source="MacOS_NetworkUsage")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="MacOS_NetworkUsage")

    

    LET Output = SELECT timestamp(epoch= ZTIMESTAMP + 978307200) AS Timestamp,
      timestamp(epoch= ZFIRSTTIMESTAMP + 978307200) AS FirstTimestamp,
      timestamp(epoch= LIVE_USAGE_TIMESTAMP + 978307200) AS LiveUsageTimestamp,
      ZBUNDLENAME AS BundleID,
      ZPROCNAME AS ProcessName,
      ZWIFIIN AS WifiIn,
      ZWIFIOUT AS WifiOut,
      ZWWANIN AS WanIn,
      ZWWANOUT AS WandOut,
      ZWIREDIN AS WiredIn,
      ZWIREDOUT AS WiredOut,
      ZXIN AS _XIn,
      ZXOUT AS _XOut,
      Z_PK AS LiveUsageTableID
    FROM Rows

    SELECT * FROM
    if(condition="MacOS_NetworkUsage" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: MacOS_Notes
  notebook:
    - type: none
      output: "MacOS_Notes - Recalculate to view results"
      template: |
        /*
        # MacOS_Notes
        */
        SELECT * FROM source(source="MacOS_Notes")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="MacOS_Notes")

    

    LET Output = SELECT Key AS _Key,
     OSPath[1] AS User,
     Note,
     Title,
     Snippet,
     NoteID AS _NoteID,
     timestamp(cocoatime=CreatedTS) AS CreatedTime,
     timestamp(cocoatime=LastOpenedDate) AS LastOpenedTime,
     timestamp(cocoatime=DirModificationDate) AS LastDirModifcation,
     Account AS _Account,
     Directory,
     DirectoryID,
     AttachmentName,
     AttachmentSize,
     AttachmentUUID,
     if(condition=AttachmentUUID,
        then=OSPath[:2] + '/Library/Group Containers/group.com.apple.notes/Accounts/LocalAccount/Media/' + AttachmentUUID + '/' + AttachmentName) AS AttachmentLocation,
     AccountName AS _AccountName,
     AccountID AS _AccountID,
     AccountType AS _AccountType,
     gunzip(string=Data) AS Data,
     OSPath
    FROM Rows
    WHERE LastOpenedTime > DateAfter AND LastOpenedTime < DateBefore
      AND ( Title =~ FilterRegex OR Data =~ FilterRegex )

    SELECT * FROM
    if(condition="MacOS_Notes" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: MacOS_XProtect_Detections
  notebook:
    - type: none
      output: "MacOS_XProtect_Detections - Recalculate to view results"
      template: |
        /*
        # MacOS_XProtect_Detections
        */
        SELECT * FROM source(source="MacOS_XProtect_Detections")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="MacOS_XProtect_Detections")

    

    LET Output = SELECT *
    FROM Rows
    WHERE dt > DateAfter
      AND dt < DateBefore
      AND (violated_rule, exec_path, responsible_path, responsible_signing_id,
        exec_cdhash, exec_sha256, responsible_cdhash, responsible_sha256 ) =~ FilterRegex

    SELECT * FROM
    if(condition="MacOS_XProtect_Detections" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Windows_Activities_Cache_ActivityPackageId
  notebook:
    - type: none
      output: "Windows_Activities_Cache_ActivityPackageId - Recalculate to view results"
      template: |
        /*
        # Windows_Activities_Cache_ActivityPackageId
        */
        SELECT * FROM source(source="Windows_Activities_Cache_ActivityPackageId")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Windows_Activities_Cache_ActivityPackageId")

    

    LET Output = SELECT format(format="%0X-%0X-%0X-%0X-%0X", args=[
      ActivityId[0:4], ActivityId[4:6], ActivityId[6:8],
      ActivityId[8:10], ActivityId[10:] ]) AS ActivityId,
      Platform, PackageName, ExpirationTime, OSPath
    FROM Rows

    SELECT * FROM
    if(condition="Windows_Activities_Cache_ActivityPackageId" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Windows_Activities_Cache_Clipboard
  notebook:
    - type: none
      output: "Windows_Activities_Cache_Clipboard - Recalculate to view results"
      template: |
        /*
        # Windows_Activities_Cache_Clipboard
        */
        SELECT * FROM source(source="Windows_Activities_Cache_Clipboard")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Windows_Activities_Cache_Clipboard")

    

    LET Output = SELECT
      CreatedTime,
      timestamp(epoch=LastModifiedTime) AS LastModifiedTime,
      timestamp(epoch=LastModifiedOnClient) AS LastModifiedOnClient,
      StartTime,
      EndTime,
      Payload,
      OSPath[1] AS User,
      base64decode(string=parse_json_array(data=ClipboardPayload || '[]')[0].content) AS ClipboardPayload,
      OSPath AS Path,
      Mtime
    FROM Rows
    WHERE StartTime > DateAfter
      AND StartTime < DateBefore
      AND ClipboardPayload =~ FilterRegex

    SELECT * FROM
    if(condition="Windows_Activities_Cache_Clipboard" =~ RuleFilter, then={
       SELECT * FROM Output
    })



  
- name: Windows_WPNDatabase___Notifications_Notifications
  notebook:
    - type: none
      output: "Windows_WPNDatabase___Notifications_Notifications - Recalculate to view results"
      template: |
        /*
        # Windows_WPNDatabase___Notifications_Notifications
        */
        SELECT * FROM source(source="Windows_WPNDatabase___Notifications_Notifications")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM ApplyFile(SourceName="Windows_WPNDatabase___Notifications_Notifications")

    

    LET Output = SELECT *, Parent || "" AS Parent,
        timestamp(winfiletime= ArrivalTime) AS ArrivalTime,
        if(condition= ExpirationTime > 0,
           then=timestamp(winfiletime= ExpirationTime),
          else='Expired') AS ExpirationTime,
        format(format="%02x", args=ActivityId) As ActivityId,
        WNSId || "" AS WNSId,
    
        if(condition= WNSCreatedTime > 0,
           then=timestamp(winfiletime= WNSCreatedTime),
          else='') AS WNSCreatedTime,
    
        if(condition= WNSExpirationTime > 0,
           then=timestamp(winfiletime= WNSExpirationTime),
          else='') AS WNSExpirationTime,
    
        upload(accessor="data",
           file=Payload,
           name=format(format="Payload%v.png", args=ID)) AS Payload
    
    FROM Rows

    SELECT * FROM
    if(condition="Windows_WPNDatabase___Notifications_Notifications" =~ RuleFilter, then={
       SELECT * FROM Output
    })


- name: Windows_Search_Service_SystemIndex_Gthr
  notebook:
    - type: none
      output: "Windows_Search_Service_SystemIndex_Gthr - Recalculate to view results"
      template: |
        /*
        # Windows_Search_Service_SystemIndex_Gthr
        */
        SELECT * FROM source(source="Windows_Search_Service_SystemIndex_Gthr")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM FilterFile(SourceName="Windows_Search_Service_SystemIndex_Gthr")

    LET MatchingFiles = SELECT OSPath FROM Rows
    
    LET FormatTimeB(T) = timestamp(winfiletime=parse_binary(
       filename=T, accessor="data", struct="uint64b"))
    
    LET FormatTime(T) = timestamp(winfiletime=parse_binary(
       filename=T, accessor="data", struct="uint64"))
    
    LET FormatSize(T) = parse_binary(
       filename=T, accessor="data", struct="uint64")

    LET Output = SELECT * FROM foreach(row=MatchingFiles, query={
       SELECT ScopeID, DocumentID, SDID,
          FormatTimeB(T=LastModified) AS LastModified,
          FileName
       FROM parse_ese(file=OSPath, table= "SystemIndex_Gthr")
    })
    WHERE LastModified > DateAfter AND LastModified < DateBefore
      AND FileName =~ FilterRegex

    SELECT * FROM
    if(condition="Windows_Search_Service_SystemIndex_Gthr" =~ RuleFilter, then={
       SELECT * FROM Output
    })


- name: Windows_Search_Service_SystemIndex_GthrPth
  notebook:
    - type: none
      output: "Windows_Search_Service_SystemIndex_GthrPth - Recalculate to view results"
      template: |
        /*
        # Windows_Search_Service_SystemIndex_GthrPth
        */
        SELECT * FROM source(source="Windows_Search_Service_SystemIndex_GthrPth")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM FilterFile(SourceName="Windows_Search_Service_SystemIndex_GthrPth")

    

    LET Output = SELECT * FROM foreach(row=MatchingFiles, query={
       SELECT Scope, Parent, Name
       FROM parse_ese(file=OSPath, table= "SystemIndex_GthrPth")
    })
    WHERE Name =~ FilterRegex

    SELECT * FROM
    if(condition="Windows_Search_Service_SystemIndex_GthrPth" =~ RuleFilter, then={
       SELECT * FROM Output
    })


- name: Windows_Search_Service_SystemIndex_PropertyStore
  notebook:
    - type: none
      output: "Windows_Search_Service_SystemIndex_PropertyStore - Recalculate to view results"
      template: |
        /*
        # Windows_Search_Service_SystemIndex_PropertyStore
        */
        SELECT * FROM source(source="Windows_Search_Service_SystemIndex_PropertyStore")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM FilterFile(SourceName="Windows_Search_Service_SystemIndex_PropertyStore")

    LET X = scope()
    
    -- The PropertyStore columns look like
    -- <random>-ProperName so we strip the
    -- random part off to display it properly.
    LET FilterDict(Dict) = to_dict(item={
      SELECT split(sep_string="-", string=_key)[1] || _key AS _key, _value
      FROM items(item=Dict)
    })
    
    LET PropStore(OSPath) = SELECT *,
       FormatTime(T=X.System_Search_GatherTime) AS System_Search_GatherTime,
       FormatSize(T=X.System_Size) AS System_Size,
       FormatTime(T=X.System_DateModified) AS System_DateModified,
       FormatTime(T=X.System_DateAccessed) AS System_DateAccessed,
       FormatTime(T=X.System_DateCreated) AS System_DateCreated
    FROM foreach(row={
       SELECT *, FilterDict(Dict=_value) AS _value
       FROM items(item={
         SELECT * FROM parse_ese(file=OSPath, table="SystemIndex_PropertyStore")
      })
    }, column="_value")

    LET Output = SELECT * FROM foreach(row=MatchingFiles, query={
       SELECT *
       FROM PropStore(OSPath=OSPath)
    })
    WHERE System_DateAccessed > DateAfter AND System_DateAccessed < DateBefore

    SELECT * FROM
    if(condition="Windows_Search_Service_SystemIndex_PropertyStore" =~ RuleFilter, then={
       SELECT * FROM Output
    })


- name: Windows_Search_Service_SystemIndex_PropertyStore_Highlights
  notebook:
    - type: none
      output: "Windows_Search_Service_SystemIndex_PropertyStore_Highlights - Recalculate to view results"
      template: |
        /*
        # Windows_Search_Service_SystemIndex_PropertyStore_Highlights
        */
        SELECT * FROM source(source="Windows_Search_Service_SystemIndex_PropertyStore_Highlights")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM FilterFile(SourceName="Windows_Search_Service_SystemIndex_PropertyStore_Highlights")

    

    LET Output = SELECT * FROM foreach(row=MatchingFiles, query={
       SELECT WorkID,
          System_Search_GatherTime,
          System_Size,
          System_DateModified,
          System_DateCreated,
          X.System_FileOwner AS System_FileOwner,
          X.System_ItemPathDisplay AS System_ItemPathDisplay,
          X.System_ItemType AS System_ItemType,
          X.System_FileAttributes AS System_FileAttributes,
          X.System_Search_AutoSummary AS System_Search_AutoSummary
       FROM PropStore(OSPath=OSPath)
    })
    WHERE System_DateAccessed > DateAfter AND System_DateAccessed < DateBefore

    SELECT * FROM
    if(condition="Windows_Search_Service_SystemIndex_PropertyStore_Highlights" =~ RuleFilter, then={
       SELECT * FROM Output
    })


- name: Windows_Search_Service_BrowsingActivity
  notebook:
    - type: none
      output: "Windows_Search_Service_BrowsingActivity - Recalculate to view results"
      template: |
        /*
        # Windows_Search_Service_BrowsingActivity
        */
        SELECT * FROM source(source="Windows_Search_Service_BrowsingActivity")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM FilterFile(SourceName="Windows_Search_Service_BrowsingActivity")

    

    LET Output = SELECT * FROM foreach(row=MatchingFiles, query={
       SELECT X.ItemPathDisplay AS ItemPathDisplay,
          X.Activity_ContentUri AS Activity_ContentUri,
          X.Activity_Description AS Activity_Description
       FROM PropStore(OSPath=OSPath)
       WHERE Activity_ContentUri
    })

    SELECT * FROM
    if(condition="Windows_Search_Service_BrowsingActivity" =~ RuleFilter, then={
       SELECT * FROM Output
    })


- name: Windows_Search_Service_UserActivityLogging
  notebook:
    - type: none
      output: "Windows_Search_Service_UserActivityLogging - Recalculate to view results"
      template: |
        /*
        # Windows_Search_Service_UserActivityLogging
        */
        SELECT * FROM source(source="Windows_Search_Service_UserActivityLogging")
        LIMIT 50
  query: |
    LET Rows = SELECT * FROM FilterFile(SourceName="Windows_Search_Service_UserActivityLogging")

    

    LET Output = SELECT * FROM foreach(row=MatchingFiles, query={
       SELECT X.System_ItemPathDisplay AS System_ItemPathDisplay,
           FormatTime(T=X.ActivityHistory_StartTime) AS ActivityHistory_StartTime,
           FormatTime(T=X.ActivityHistory_EndTime) AS ActivityHistory_EndTime,
           X.ActivityHistory_AppId AS ActivityHistory_AppId
       FROM PropStore(OSPath=OSPath)
       WHERE ActivityHistory_AppId
    })
    WHERE ActivityHistory_StartTime > DateAfter
      AND ActivityHistory_StartTime < DateBefore

    SELECT * FROM
    if(condition="Windows_Search_Service_UserActivityLogging" =~ RuleFilter, then={
       SELECT * FROM Output
    })


docs/../static/artifact/SQLiteHunter.yaml