diff --git a/Makefile b/Makefile index ba752b7..8d7ef7f 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ windows: go build -o sqlitehunter_compiler.exe ./bin/*.go compile: FORCE - ./sqlitehunter_compiler compile ./definitions/ ./output/SQLiteHunter.yaml --output_zip ./output/SQLiteHunter.zip --index ./docs/content/docs/rules/index.json + go run ./bin/ compile ./definitions/ ./output/SQLiteHunter.yaml --output_zip ./output/SQLiteHunter.zip --index ./docs/content/docs/rules/index.json golden: compile ./testing/velociraptor.bin --definitions ./output --config ./testing/test.config.yaml golden --env testFiles=`pwd`/test_files ./testing/testcases -v --filter=${GOLDEN} diff --git a/compile/artifact.go b/compile/artifact.go index 03312c7..76e9c7b 100644 --- a/compile/artifact.go +++ b/compile/artifact.go @@ -102,6 +102,6 @@ func (self *Artifact) BuildIndex() []byte { }) } - serialized, _ := json.Marshal(defs) + serialized, _ := json.MarshalIndent(defs, " ", " ") return serialized } diff --git a/compile/template.yaml b/compile/template.yaml index a7a3f70..409e715 100644 --- a/compile/template.yaml +++ b/compile/template.yaml @@ -21,6 +21,8 @@ description: | column_types: - name: Image type: preview_upload +- name: Payload + type: preview_upload export: | LET SPEC <= "{{ .CompressedSpec }}" @@ -69,7 +71,7 @@ export: | then=OSPath =~ get(item=Specs.sources, field=SourceName).filename) -- Build a regex for all enabled categories. - LET all_categories = SELECT _value + LET all_categories = SELECT if(condition=_value = "All", then=".", else=_value) AS _value FROM foreach(row=["All"{{ range .Categories }},"{{ . }}"{{ end }}]) WHERE get(field=_value) @@ -143,10 +145,10 @@ sources: // 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][:-11] AS Source , - stat(accessor="fs", filename=Data.VFSPath).Size / 8 AS Records + 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 =~ "ResultIndex" AND Records > 0 + WHERE Type =~ "Result" AND Records > 0 LET _ <= SELECT notebook_update_cell(notebook_id=NotebookId, type="vql", input=format(format=''' @@ -183,7 +185,7 @@ sources: /* # {{ $v.Key }} */ - SELECT * FROM source(Source={{ Quote $v.Key }}) + SELECT * FROM source(source={{ Quote $v.Key }}) LIMIT 50 query: | LET Rows = SELECT * FROM {{ $action }}(SourceName={{ Quote $v.Key }}) diff --git a/definitions/Windows_Notification_Service.yaml b/definitions/Windows_Notification_Service.yaml new file mode 100644 index 0000000..cc4398f --- /dev/null +++ b/definitions/Windows_Notification_Service.yaml @@ -0,0 +1,80 @@ +Name: Windows WPNDatabase - Notifications +Description: | + Parse the `wpndatabase.db` file + +Author: Andrew Rathbun +Email: andrew.d.rathbun@gmail.com +Reference: https://github.com/EricZimmerman/SQLECmd + +SQLiteIdentifyQuery: | + SELECT count(*) AS `Check` + FROM sqlite_master + WHERE type='table' + AND (name='Notification' OR + name='HandlerAssets' OR + name='WNSPushChannel' OR + name='TransientTable' OR + name='NotificationData'); + +SQLiteIdentifyValue: 5 + +Categories: + - Windows + +FilenameRegex: "wpndatabase.db" +Globs: + - C:\Users\*\AppData\Local\Microsoft\Windows\Notifications\wpndatabase.db + +Sources: +- name: Notifications + VQL: | + 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 + + SQL: | + SELECT + Notification.Id AS ID, + Notification.'Order' AS 'Order', + Notification.HandlerId AS HandlerId, + NotificationHandler.PrimaryId AS Application, + NotificationHandler.ParentId AS Parent, + NotificationHandler.HandlerType AS HandlerType, + Notification.Type AS Type, + Notification.Payload AS Payload, + Notification.PayloadType AS PayloadType, + Notification.Tag AS Tag, + Notification."Group" AS "Group", + Notification.ArrivalTime AS ArrivalTime, + Notification.ExpiryTime AS ExpirationTime, + NotificationHandler.CreatedTime AS HandlerCreated, + NotificationHandler.ModifiedTime AS HandlerModified, + NotificationHandler.WNSId AS WNSId, + NotificationHandler.WNFEventName AS WNFEventName, + WNSPushChannel.ChannelId AS ChannelID, + WNSPushChannel.Uri AS URI, + WNSPushChannel.CreatedTime AS WNSCreatedTime, + WNSPushChannel.ExpiryTime AS WNSExpirationTime, + Notification.ActivityId AS ActivityId + FROM Notification + JOIN NotificationHandler ON NotificationHandler.RecordId = Notification.HandlerId + LEFT JOIN WNSPushChannel ON WNSPushChannel.HandlerId = NotificationHandler.RecordId + ORDER BY Id DESC diff --git a/docs/content/docs/rules/index.json b/docs/content/docs/rules/index.json index 9a49c46..81ba8db 100644 --- a/docs/content/docs/rules/index.json +++ b/docs/content/docs/rules/index.json @@ -1 +1,449 @@ -[{"Name":"iMessage","Author":"x64-julian","Description":"Parses the `chat.db` from IOS platforms.\n","Categories":["MacOS"],"Sources":[{"Name":"Profiles"}],"RawData":"Name: iMessage\nAuthor: x64-julian\nDescription: |\n Parses the `chat.db` from IOS platforms.\n\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='chat_handle_join' OR name='message_attachment_join'\n OR name='sync_deleted_messages');\nSQLiteIdentifyValue: 3\nCategories:\n - MacOS\nFilenameRegex: \"chat.db\"\nGlobs:\n - \"/Users/*/Library/Messages/chat.db\"\n\nSources:\n- name: Profiles\n VQL: |\n SELECT timestamp(epoch=date / 1000000000 + 978307200) AS Timestamp, *\n FROM Rows\n WHERE Timestamp \u003e DateAfter AND Timestamp \u003c DateBefore\n AND (MessageText, RoomName) =~ FilterRegex\n\n SQL: |\n SELECT\n m.rowid,\n coalesce(m.cache_roomnames, h.id) AS ThreadId,\n m.is_from_me AS IsFromMe,\n\n CASE when m.is_from_me = 1 THEN m.account\n ELSE h.id\n END AS FromPhoneNumber,\n\n CASE when m.is_from_me = 0 THEN m.account\n ELSE coalesce(h2.id, h.id)\n END AS ToPhoneNumber,\n\n m.service AS Service,\n m.date,\n m.text AS MessageText,\n c.display_name AS RoomName\n FROM message as m\n left join handle as h on m.handle_id = h.rowid\n left join chat as c on m.cache_roomnames = c.room_name -- note: chat.room_name is not unique, this may cause one-to-many join\n left join chat_handle_join as ch on c.rowid = ch.chat_id\n left join handle as h2 on ch.handle_id = h2.rowid\n WHERE\n -- try to eliminate duplicates due to non-unique\n -- message.cache_roomnames/chat.room_name\n (h2.service is null or m.service = h2.service)\n\n ORDER BY m.date DESC;\n"},{"Name":"Chromium Browser Autofill","Author":"Andrew Rathbun","Description":"Parses the `Web Data` file in the Chromium profile.\n\nThis file contains autofill data for forms such as email, addresses,\nnames etc.\n","Categories":["Chrome","Browser"],"Sources":[{"Name":"Profiles"},{"Name":"Masked Credit Cards"}],"RawData":"Name: Chromium Browser Autofill\nDescription: |\n Parses the `Web Data` file in the Chromium profile.\n\n This file contains autofill data for forms such as email, addresses,\n names etc.\n\nAuthor: Andrew Rathbun\nEmail: andrew.d.rathbun@gmail.com\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='autofill' OR name='credit_cards'\n OR name='offer_data' OR name='server_addresses' OR name='keywords');\nSQLiteIdentifyValue: 5\nCategories:\n - Chrome\n - Browser\n\nFilenameRegex: \"Web Data\"\nGlobs:\n - \"{{LinuxChromeProfiles}}/*/Web Data\"\n - \"{{WindowsChromeProfiles}}/*/Web Data\"\n - \"{{MacOSChromeProfiles}}/*/Web Data\"\n\nSources:\n- name: Profiles\n VQL: |\n SELECT GUID,\n timestamp(epoch= date_modified) AS DateModified,\n timestamp(epoch= use_date) AS UseDate,\n FirstName, MiddleName, LastName, EmailAddress,\n PhoneNumber, CompanyName, StreetAddress,\n City, State, ZipCode, UseCount, OSPath\n FROM Rows\n WHERE UseDate \u003e DateAfter AND UseDate \u003c DateBefore\n AND (FirstName, MiddleName, LastName, EmailAddress, CompanyName, StreetAddress) =~ FilterRegex\n\n SQL: |\n SELECT\n autofill_profiles.guid AS GUID,\n date_modified,\n use_date,\n autofill_profile_names.first_name AS FirstName,\n autofill_profile_names.middle_name AS MiddleName,\n autofill_profile_names.last_name AS LastName,\n autofill_profile_emails.email as EmailAddress,\n autofill_profile_phones.number AS PhoneNumber,\n autofill_profiles.company_name AS CompanyName,\n autofill_profiles.street_address AS StreetAddress,\n autofill_profiles.city AS City,\n autofill_profiles.state AS State,\n autofill_profiles.zipcode AS ZipCode,\n autofill_profiles.use_count AS UseCount\n FROM\n autofill_profiles\n INNER JOIN autofill_profile_emails ON autofill_profile_emails.guid = autofill_profiles.guid\n INNER JOIN autofill_profile_phones ON autofill_profiles.guid = autofill_profile_phones.guid\n INNER JOIN autofill_profile_names ON autofill_profile_phones.guid = autofill_profile_names.guid\n ORDER BY\n autofill_profiles.guid ASC\n\n- name: Masked Credit Cards\n VQL: \"SELECT * FROM Rows\"\n SQL: |\n SELECT\n masked_credit_cards.id AS ID,\n masked_credit_cards.name_on_card AS NameOnCard,\n masked_credit_cards.network AS CardNetwork,\n masked_credit_cards.last_four AS LastFour,\n masked_credit_cards.exp_month AS ExpMonth,\n masked_credit_cards.exp_year AS ExpYear,\n masked_credit_cards.bank_name AS BankName,\n masked_credit_cards.nickname AS CardNickname,\n masked_credit_cards.card_issuer AS CardIssuer,\n masked_credit_cards.instrument_id AS InstrumentID\n FROM masked_credit_cards\n ORDER BY masked_credit_cards.id ASC\n"},{"Name":"Chromium Browser Bookmarks","Author":"Sikha Puthanveedu @SikhaMohan, Mike Cohen","Description":"Parses the browser's Bookmarks file.\n","Categories":["Chrome","Browser"],"Sources":[{"Name":""}],"RawData":"Name: Chromium Browser Bookmarks\nDescription: |\n Parses the browser's Bookmarks file.\n\nAuthor: Sikha Puthanveedu @SikhaMohan, Mike Cohen\nCategories:\n - Chrome\n - Browser\n\nFilenameRegex: \"Bookmarks\"\nGlobs:\n - \"{{LinuxChromeProfiles}}/*/Bookmarks\"\n - \"{{WindowsChromeProfiles}}/*/Bookmarks\"\n - \"{{MacOSChromeProfiles}}/*/Bookmarks\"\n\nSources:\n- Preamble: |\n -- Recursive function to report the details of a folder\n LET ReportFolder(Data, BaseName) = SELECT * FROM chain(a={\n -- First row emit the data about the actual folder\n SELECT BaseName + \" | \" + Data.name AS Name,\n timestamp(winfiletime=int(int=Data.date_added) * 10) AS DateAdded,\n timestamp(winfiletime=int(int=Data.date_last_used) * 10) AS DateLastUsed,\n Data.type AS Type,\n Data.url || \"\" AS URL\n FROM scope()\n },\n b={\n -- If this folder has children recurse into it\n SELECT * FROM foreach(row={\n SELECT _value FROM items(item=Data.children)\n }, query={\n SELECT * FROM ReportFolder(Data=_value, BaseName=BaseName + \" | \" + Data.name)\n })\n })\n\n LET MatchingFiles = SELECT OSPath, parse_json(data=read_file(filename=OSPath)) AS Data\n FROM Rows\n\n VQL: |\n SELECT * FROM foreach(row=MatchingFiles, query={\n SELECT * FROM chain(\n a={\n SELECT OSPath, *, \"bookmark_bar\" AS Type\n FROM ReportFolder(Data=Data.roots.bookmark_bar, BaseName=\"\")\n },\n b={\n SELECT OSPath, *, \"other\" AS Type\n FROM ReportFolder(Data=Data.roots.other, BaseName=\"\")\n },\n c={\n SELECT OSPath, *, \"synced\" AS Type\n FROM ReportFolder(Data=Data.roots.synced, BaseName=\"\")\n })\n })\n"},{"Name":"Chromium Browser Cookies","Author":"Andrew Rathbun","Description":"Parses the cookies held by the Chromium browser.\n","Categories":["Chrome","Browser"],"Sources":[{"Name":"Cookies"}],"RawData":"Name: Chromium Browser Cookies\nDescription: |\n Parses the cookies held by the Chromium browser.\n\nAuthor: Andrew Rathbun\nEmail: andrew.d.rathbun@gmail.com\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master WHERE type='table' AND (name='cookies' OR name='meta');\nSQLiteIdentifyValue: 2\nCategories:\n - Chrome\n - Browser\nFilenameRegex: \"Cookies\"\nGlobs:\n - \"{{LinuxChromeProfiles}}/*/Cookies\"\n - \"{{WindowsChromeProfiles}}/*/Cookies\"\n - \"{{MacOSChromeProfiles}}/*/Cookies\"\n\nSources:\n- name: Cookies\n VQL: |\n SELECT timestamp(winfiletime=(creation_utc * 10) || 0) AS CreationUTC,\n timestamp(winfiletime=(expires_utc * 10) || 0) AS ExpiresUTC,\n timestamp(winfiletime=(last_access_utc * 10) || 0) AS LastAccessUTC,\n HostKey, Name, Path,\n Bool(Value=is_secure) AS IsSecure,\n Bool(Value=is_httponly) AS IsHttpOnly,\n Bool(Value=has_expires) AS HasExpiration,\n Bool(Value=is_persistent) AS IsPersistent,\n Priority, SourcePort, OSPath\n FROM Rows\n WHERE LastAccessUTC \u003e DateAfter AND LastAccessUTC \u003c DateBefore\n AND (Name, Path) =~ FilterRegex\n\n SQL: |\n SELECT\n cookies.creation_utc,\n cookies.expires_utc,\n cookies.last_access_utc,\n cookies.host_key AS HostKey,\n cookies.name AS Name,\n cookies.path AS Path,\n cookies.is_secure,\n cookies.is_httponly,\n cookies.has_expires,\n cookies.is_persistent,\n cookies.priority AS Priority,\n cookies.source_port AS SourcePort\n FROM cookies\n ORDER BY cookies.creation_utc ASC\n"},{"Name":"Chromium Browser Extensions","Author":"Mike Cohen","Description":"Parses all installed chromium extensions.\n","Categories":["Chrome","Browser"],"Sources":[{"Name":""}],"RawData":"Name: Chromium Browser Extensions\nDescription: |\n Parses all installed chromium extensions.\n\nAuthor: Mike Cohen\nCategories:\n - Chrome\n - Browser\n\nFilenameRegex: \"manifest.json\"\nGlobs:\n - \"{{LinuxChromeProfiles}}/*/Extensions/**/manifest.json\"\n - \"{{WindowsChromeProfiles}}/*/Extensions/**/manifest.json\"\n - \"{{MacOSChromeProfiles}}/*/Extensions/**/manifest.json\"\n\nSources:\n- Preamble: |\n -- Resolve the message string against the Locale dict\n LET ResolveName(Message, Locale) = get(item=Locale,\n field=lowcase(string=parse_string_with_regex(regex=\"^__MSG_(.+)__$\", string=Message).g1),\n default=Message).message || Message\n\n -- Read the manifest files\n LET ManifestData = SELECT OSPath, parse_json(data=read_file(filename=OSPath)) AS Manifest\n FROM Rows\n\n -- Find the Locale file to help with.\n LET LocaleData = SELECT *, if(condition=Manifest.default_locale, else=dict(),\n then=parse_json(data=read_file(\n filename=OSPath.Dirname + \"_locales\" + Manifest.default_locale + \"messages.json\"))) AS Locale\n FROM ManifestData\n\n LET GetIcon(Manifest) = Manifest.icons.`128` || Manifest.icons.`64` || Manifest.icons.`32` || Manifest.icons.`16`\n\n VQL: |\n SELECT OSPath, Manifest.author.email AS Email,\n ResolveName(Message = Manifest.name, Locale=Locale) AS name,\n ResolveName(Message = Manifest.description, Locale=Locale) AS description,\n Manifest.oauth2.scopes as Scopes,\n Manifest.permissions as Permissions,\n Manifest.key as Key, if(condition=GetIcon(Manifest=Manifest),\n then=upload(file=OSPath.Dirname + GetIcon(Manifest=Manifest))) AS Image,\n Manifest AS _Manifest\n FROM LocaleData\n WHERE (name, description) =~ FilterRegex\n"},{"Name":"Chromium Browser Favicons","Author":"Andrew Rathbun, Phill Moore","Description":"Extracts known favicons for visited websites.\n\nAlso uploads and previews the image thumbnails.\n","Categories":["Chrome","Browser"],"Sources":[{"Name":""}],"RawData":"Name: Chromium Browser Favicons\nDescription: |\n Extracts known favicons for visited websites.\n\n Also uploads and previews the image thumbnails.\n\nAuthor: Andrew Rathbun, Phill Moore\nEmail: andrew.d.rathbun@gmail.com, @phillmoore\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='icon_mapping' OR name='favicons' OR name='favicon_bitmaps');\nSQLiteIdentifyValue: 3\nCategories:\n - Chrome\n - Browser\n\nFilenameRegex: \"Favicons\"\nGlobs:\n - \"{{LinuxChromeProfiles}}/*/Favicons\"\n - \"{{WindowsChromeProfiles}}/*/Favicons\"\n - \"{{MacOSChromeProfiles}}/*/Favicons\"\n\nSources:\n- VQL: |\n SELECT ID, IconID,\n timestamp(winfiletime= (LastUpdated * 10) || 0) AS LastUpdated,\n PageURL, FaviconURL,\n upload(accessor=\"data\",\n file=_image,\n name=format(format=\"Image%v.png\", args=ID)) AS Image,\n OSPath as _OSPath\n FROM Rows\n WHERE LastUpdated \u003e DateAfter AND LastUpdated \u003c DateBefore\n\n SQL: |\n SELECT\n favicons.id AS ID,\n favicon_bitmaps.icon_id AS IconID,\n favicon_bitmaps.image_data as _image,\n favicon_bitmaps.last_updated AS LastUpdated,\n icon_mapping.page_url AS PageURL,\n favicons.url AS FaviconURL\n FROM favicons\n INNER JOIN icon_mapping\n INNER JOIN favicon_bitmaps\n ON icon_mapping.icon_id = favicon_bitmaps.icon_id\n AND favicons.id = favicon_bitmaps.icon_id\n ORDER BY favicons.id ASC\n"},{"Name":"Chromium Browser History","Author":"Andrew Rathbun","Description":"Extracts the Chromium Browser History\n","Categories":["Chrome","Browser"],"Sources":[{"Name":"Visits"},{"Name":"Downloads"},{"Name":"Keywords"}],"RawData":"Name: Chromium Browser History\nDescription: |\n Extracts the Chromium Browser History\n\nAuthor: Andrew Rathbun\nEmail: andrew.d.rathbun@gmail.com\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='urls' OR name='visits' OR name='downloads' OR name='segments');\nSQLiteIdentifyValue: 4\nCategories:\n - Chrome\n - Browser\nFilenameRegex: \"History\"\nGlobs:\n - \"{{LinuxChromeProfiles}}/*/History\"\n - \"{{WindowsChromeProfiles}}/*/History\"\n - \"{{MacOSChromeProfiles}}/*/History\"\n\nSources:\n- name: Visits\n VQL: |\n SELECT ID,\n timestamp(winfiletime=(visit_time * 10) || 0) AS VisitTime,\n timestamp(winfiletime=(last_visit_time * 10) || 0) AS LastVisitedTime,\n URLTitle, URL, VisitCount, TypedCount,\n if(condition=hidden =~ '1', then=\"Yes\", else=\"No\") AS Hidden,\n VisitID, FromVisitID,\n visit_duration / 1000000 AS VisitDurationInSeconds,\n OSPath\n FROM Rows\n WHERE VisitTime \u003e DateAfter\n AND VisitTime \u003c DateBefore\n AND (URLTitle, URL) =~ FilterRegex\n SQL: |\n SELECT\n urls.id AS ID,\n visits.visit_time as visit_time,\n urls.last_visit_time as last_visit_time,\n urls.title AS URLTitle,\n urls.url AS URL,\n urls.visit_count AS VisitCount,\n urls.typed_count AS TypedCount,\n urls.hidden as hidden,\n visits.id AS VisitID,\n visits.from_visit AS FromVisitID,\n visits.visit_duration as visit_duration\n FROM urls\n LEFT JOIN visits ON urls.id = visits.url\n ORDER BY visits.visit_time ASC\n\n- name: Downloads\n Preamble: |\n LET StateLookup \u003c= dict(`0`='In Progress', `1`='Complete', `2`=\"Cancelled\", `3`=\"Interrupted\", `4`=\"Interrupted\")\n LET DangerType \u003c= dict(`0`='Not Dangerous', `1`=\"Dangerous\", `2`='Dangerous URL', `3`='Dangerous Content',\n `4`='Content May Be Malicious', `5`='Uncommon Content', `6`='Dangerous But User Validated',\n `7`='Dangerous Host', `8`='Potentially Unwanted', `9`='Whitelisted by Policy')\n LET InterruptReason \u003c= dict(`0`= 'No Interrupt', `1`= 'File Error', `2`='Access Denied', `3`='Disk Full',\n `5`='Path Too Long',`6`='File Too Large', `7`='Virus', `10`='Temporary Problem', `11`='Blocked',\n `12`='Security Check Failed', `13`='Resume Error', `20`='Network Error', `21`='Operation Timed Out',\n `22`='Connection Lost', `23`='Server Down', `30`='Server Error', `31`='Range Request Error',\n `32`='Server Precondition Error', `33`='Unable to get file', `34`='Server Unauthorized',\n `35`='Server Certificate Problem', `36`='Server Access Forbidden', `37`='Server Unreachable',\n `38`='Content Length Mismatch', `39`='Cross Origin Redirect', `40`='Cancelled', `41`='Browser Shutdown',\n `50`='Browser Crashed')\n\n VQL: |\n SELECT ID, GUID, CurrentPath, TargetPath, OriginalMIMEType, ReceivedBytes, TotalBytes,\n timestamp(winfiletime=(start_time * 10) || 0) AS StartTime,\n timestamp(winfiletime=(end_time * 10) || 0) AS EndTime,\n timestamp(winfiletime=(opened * 10) || 0) AS Opened,\n timestamp(winfiletime=(last_access_time * 10) || 0) AS LastAccessTime,\n timestamp(epoch=last_modified) AS LastModified,\n get(item=StateLookup, field=str(str=state), default=\"Unknown\") AS State,\n get(item=DangerType, field=str(str=danger_type), default=\"Unknown\") AS DangerType,\n get(item=InterruptReason, field=str(str=interrupt_reason), default=\"Unknown\") AS InterruptReason,\n ReferrerURL, SiteURL, TabURL, TabReferrerURL, DownloadURL, OSPath\n FROM Rows\n WHERE LastAccessTime \u003e DateAfter AND LastAccessTime \u003c DateBefore\n AND (SiteURL, DownloadURL, TabURL, TabReferrerURL, ReferrerURL, DownloadURL) =~ FilterRegex\n\n SQL: |\n SELECT\n downloads.id AS ID,\n downloads.guid AS GUID,\n downloads.current_path AS CurrentPath,\n downloads.target_path AS TargetPath,\n downloads.original_mime_type AS OriginalMIMEType,\n downloads.received_bytes AS ReceivedBytes,\n downloads.total_bytes AS TotalBytes,\n downloads.start_time,\n downloads.end_time,\n downloads.opened,\n downloads.last_access_time,\n downloads.last_modified,\n downloads.state,\n downloads.danger_type,\n downloads.interrupt_reason,\n downloads.referrer AS ReferrerURL,\n downloads.site_url AS SiteURL,\n downloads.tab_url AS TabURL,\n downloads.tab_referrer_url AS TabReferrerURL,\n DownloadURL.url AS DownloadURL\n FROM downloads\n INNER JOIN downloads_url_chains AS DownloadURL ON downloads.id = DownloadURL.id\n ORDER BY downloads.id ASC\n\n- name: Keywords\n VQL: |\n SELECT KeywordID, URLID,\n timestamp(winfiletime=(last_visit_time * 10) || 0) AS LastVisitedTime,\n KeywordSearchTerm, Title, URL, OSPath\n FROM Rows\n WHERE LastVisitedTime \u003e DateAfter AND LastVisitedTime \u003c DateBefore\n AND (Title, KeywordSearchTerm, URL) =~ FilterRegex\n\n SQL: |\n SELECT\n keyword_search_terms.keyword_id AS KeywordID,\n keyword_search_terms.url_id AS URLID,\n urls.last_visit_time,\n keyword_search_terms.term AS KeywordSearchTerm,\n urls.title AS Title,\n urls.url AS URL\n FROM keyword_search_terms\n INNER JOIN urls ON keyword_search_terms.url_id = urls.id\n ORDER BY keyword_search_terms.keyword_id ASC\n"},{"Name":"Chromium Browser Media","Author":"Andrew Rathbun","Description":"Parses metadata about viewed media, such as videos.\n","Categories":["Chrome","Browser"],"Sources":[{"Name":"History"},{"Name":"Playback Session"}],"RawData":"Name: Chromium Browser Media\nDescription: |\n Parses metadata about viewed media, such as videos.\n\nAuthor: Andrew Rathbun\nEmail: andrew.d.rathbun@gmail.com\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='origin' OR name='playback' OR name='playbackSession');\nSQLiteIdentifyValue: 3\nCategories:\n - Chrome\n - Browser\nFilenameRegex: \"Media History\"\nGlobs:\n - \"{{LinuxChromeProfiles}}/*/Media History\"\n - \"{{WindowsChromeProfiles}}/*/Media History\"\n - \"{{MacOSChromeProfiles}}/*/Media History\"\n\nSources:\n- name: History\n VQL: |\n SELECT ID, URL, WatchTimeSeconds,\n Bool(Value=has_video) AS HasVideo,\n Bool(Value=has_audio) AS HasAudio,\n timestamp(winfiletime=last_updated_time_s || 0) AS LastUpdated,\n OriginID, OSPath\n FROM Rows\n WHERE LastUpdated \u003e DateAfter AND LastUpdated \u003c DateBefore\n AND URL =~ FilterRegex\n\n SQL: |\n SELECT\n playback.id AS ID,\n playback.url AS URL,\n playback.watch_time_s AS WatchTimeSeconds,\n playback.has_video,\n playback.has_audio,\n playback.last_updated_time_s,\n playback.origin_id AS OriginID\n FROM playback\n ORDER BY playback.id ASC\n\n- name: Playback Session\n VQL: |\n SELECT ID,\n timestamp(winfiletime=last_updated_time_s || 0) AS LastUpdated, URL,\n duration_ms / 1000 AS DurationInSeconds,\n position_ms / 1000 AS PositionInSeconds,\n Title, Artist, Album, SourceTitle, OriginID, OSPath\n FROM Rows\n WHERE LastUpdated \u003e DateAfter AND LastUpdated \u003c DateBefore\n AND URL =~ FilterRegex\n\n SQL: |\n SELECT\n playbackSession.id AS ID,\n playbackSession.last_updated_time_s,\n playbackSession.url AS URL,\n playbackSession.duration_ms,\n playbackSession.position_ms,\n playbackSession.title AS Title,\n playbackSession.artist AS Artist,\n playbackSession.album AS Album,\n playbackSession.source_title AS SourceTitle,\n playbackSession.origin_id AS OriginID\n FROM playbackSession\n ORDER BY playbackSession.id\n"},{"Name":"Chromium Browser Network","Author":"Andrew Rathbun","Description":"Parses the `Network Action Predictor` database\n","Categories":["Chrome","Browser"],"Sources":[{"Name":"Predictor"}],"RawData":"Name: Chromium Browser Network\nDescription: |\n Parses the `Network Action Predictor` database\n\nAuthor: Andrew Rathbun\nEmail: andrew.d.rathbun@gmail.com\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='resource_prefetch_predictor_host_redirect'\n OR name='network_action_predictor' OR name='resource_prefetch_predictor_metadata');\nSQLiteIdentifyValue: 3\nCategories:\n - Chrome\n - Browser\nFilenameRegex: \"Network Action Predictor\"\nGlobs:\n - \"{{LinuxChromeProfiles}}/*/Network Action Predictor\"\n - \"{{WindowsChromeProfiles}}/*/Network Action Predictor\"\n - \"{{MacOSChromeProfiles}}/*/Network Action Predictor\"\n\nSources:\n- name: Predictor\n VQL: |\n SELECT * FROM Rows\n WHERE UserText =~ FilterRegex\n\n SQL: |\n SELECT\n network_action_predictor.id AS ID,\n network_action_predictor.user_text AS UserText,\n network_action_predictor.url AS URL,\n network_action_predictor.number_of_hits AS NumberOfHits,\n network_action_predictor.number_of_misses AS NumberOfMisses\n FROM network_action_predictor, resource_prefetch_predictor_host_redirect\n ORDER BY network_action_predictor.id ASC\n"},{"Name":"Chromium Browser Notifications","Author":"Maxime Thiebaut (@0xThiebaut)","Categories":["Chrome","Edge","Browser"],"Sources":[{"Name":"Site Engagements"},{"Name":"App Banners"},{"Name":"Notification Preferences"},{"Name":"Notification Interactions"}],"RawData":"Name: Chromium Browser Notifications\nAuthor: Maxime Thiebaut (@0xThiebaut)\nCategories:\n - Chrome\n - Edge\n - Browser\n\nFilenameRegex: \"Preferences\"\nGlobs:\n - \"{{LinuxChromeProfiles}}/*/Preferences\"\n - \"{{WindowsChromeProfiles}}/*/Preferences\"\n - \"{{MacOSChromeProfiles}}/*/Preferences\"\n\nSources:\n- name: Site Engagements\n Preamble: |\n LET JSON = SELECT parse_json(data=read_file(filename=OSPath)) AS Data, OSPath FROM Rows\n\n VQL: |\n SELECT * FROM foreach(row={\n SELECT OSPath, Data.profile.content_settings.exceptions AS exceptions FROM JSON\n }, query={\n SELECT _key AS Site,\n timestamp(winfiletime=int(int=_value.last_modified) * 10 || 0) AS LastModified,\n timestamp(winfiletime=int(int=_value.setting.lastEngagementTime) * 10 || 0) AS LastEngagementTime,\n OSPath\n FROM items(item=exceptions.site_engagement)\n })\n\n- name: App Banners\n Preamble: |\n LET JSON = SELECT parse_json(data=read_file(filename=OSPath)) AS Data, OSPath FROM Rows\n\n VQL: |\n SELECT * FROM foreach(row={\n SELECT OSPath, Data.profile.content_settings.exceptions AS exceptions FROM JSON\n }, query={\n SELECT _key AS Site,\n timestamp(winfiletime=int(int=_value.last_modified) * 10 || 0) AS LastModified,\n {\n SELECT _key AS Site,\n timestamp(winfiletime=int(int=_value.couldShowBannerEvents) * 10 || 0) AS CouldShowBannerEvents,\n timestamp(winfiletime=int(int=_value.next_install_text_animation.last_shown) * 10 || 0) AS LastShown\n FROM items(item=_value.setting)\n } AS Setting,\n OSPath\n FROM items(item=exceptions.app_banner)\n })\n\n- name: Notification Preferences\n Preamble: |\n LET ContentSettings \u003c= array(`0`=\"Default\",`1`=\"Allow\",`2`=\"Block\",`3`=\"Ask\",`4`=\"Session Only\",`5`=\"Detect Important Content\")\n\n LET JSON = SELECT parse_json(data=read_file(filename=OSPath)) AS Data, OSPath FROM Rows\n\n VQL: |\n SELECT * FROM foreach(row={\n SELECT OSPath, Data.profile.content_settings.exceptions AS exceptions FROM JSON\n }, query={\n SELECT _key AS Site,\n timestamp(winfiletime=int(int=_value.last_modified) * 10 || 0) AS LastModified,\n ContentSettings[_value.setting] AS Setting,\n OSPath\n FROM items(item=exceptions.notifications)\n })\n\n- name: Notification Interactions\n Preamble: |\n LET JSON = SELECT parse_json(data=read_file(filename=OSPath)) AS Data, OSPath FROM Rows\n LET S = scope()\n\n VQL: |\n SELECT * FROM foreach(row={\n SELECT OSPath, Data.profile.content_settings.exceptions AS exceptions FROM JSON\n }, query={\n SELECT _key AS URL,\n timestamp(winfiletime=int(int=_value.last_modified) * 10 || 0) AS LastModified,\n _value.display_count as DisplayCount,\n _value.click_count as ClickCount,\n OSPath\n FROM items(item=S.notification_interactions || dict())\n })\n"},{"Name":"Chromium Browser Shortcuts","Author":"Andrew Rathbun","Categories":["Chrome","Browser"],"Sources":[{"Name":""}],"RawData":"Name: Chromium Browser Shortcuts\nAuthor: Andrew Rathbun\nEmail: andrew.d.rathbun@gmail.com\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='meta' OR name='omni_box_shortcuts');\nSQLiteIdentifyValue: 2\nCategories:\n - Chrome\n - Browser\n\nFilenameRegex: \"Shortcuts\"\nGlobs:\n - \"{{LinuxChromeProfiles}}/*/Shortcuts\"\n - \"{{WindowsChromeProfiles}}/*/Shortcuts\"\n - \"{{MacOSChromeProfiles}}/*/Shortcuts\"\n\nSources:\n- VQL: |\n SELECT ID,\n timestamp(winfiletime= (last_access_time * 10) || 0) AS LastAccessTime,\n TextTyped, FillIntoEdit, URL, Contents,\n Description, Type, Keyword, TimesSelectedByUser, OSPath\n FROM Rows\n WHERE LastAccessTime \u003e DateAfter AND LastAccessTime \u003c DateBefore\n AND (Contents, Description) =~ FilterRegex\n\n SQL: |\n SELECT\n omni_box_shortcuts.last_access_time,\n omni_box_shortcuts.text AS TextTyped,\n omni_box_shortcuts.fill_into_edit AS FillIntoEdit,\n omni_box_shortcuts.url AS URL,\n omni_box_shortcuts.contents AS Contents,\n omni_box_shortcuts.description AS Description,\n omni_box_shortcuts.type AS Type,\n omni_box_shortcuts.keyword AS Keyword,\n omni_box_shortcuts.number_of_hits AS TimesSelectedByUser,\n omni_box_shortcuts.id AS ID\n FROM omni_box_shortcuts\n ORDER BY omni_box_shortcuts.last_access_time ASC\n"},{"Name":"Chromium Sessions","Author":"Mike Cohen","Categories":["Chrome","Browser"],"Sources":[{"Name":"Sessions"}],"RawData":"Name: Chromium Sessions\nAuthor: Mike Cohen\nReference: https://www.inversecos.com/2022/10/recovering-cleared-browser-history.html\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master WHERE type='table' AND (name='cookies' OR name='meta');\nSQLiteIdentifyValue: 2\nCategories:\n - Chrome\n - Browser\nFilenameRegex: \"Session\"\nGlobs:\n - \"{{LinuxChromeProfiles}}/*/Sessions/Session_*\"\n - \"{{WindowsChromeProfiles}}/*/Sessions/Session_*\"\n - \"{{MacOSChromeProfiles}}/*/Sessions/Session_*\"\n\nSources:\n- name: Sessions\n VQL: |\n SELECT timestamp(winfiletime=(creation_utc * 10) || 0) AS CreationUTC,\n timestamp(winfiletime=(expires_utc * 10) || 0) AS ExpiresUTC,\n timestamp(winfiletime=(last_access_utc * 10) || 0) AS LastAccessUTC,\n HostKey, Name, Path,\n Bool(Value=is_secure) AS IsSecure,\n Bool(Value=is_httponly) AS IsHttpOnly,\n Bool(Value=has_expires) AS HasExpiration,\n Bool(Value=is_persistent) AS IsPersistent,\n Priority, SourcePort, OSPath\n FROM Rows\n WHERE LastAccessUTC \u003e DateAfter AND LastAccessUTC \u003c DateBefore\n AND (Name, Path) =~ FilterRegex\n\n SQL: |\n SELECT\n cookies.creation_utc,\n cookies.expires_utc,\n cookies.last_access_utc,\n cookies.host_key AS HostKey,\n cookies.name AS Name,\n cookies.path AS Path,\n cookies.is_secure,\n cookies.is_httponly,\n cookies.has_expires,\n cookies.is_persistent,\n cookies.priority AS Priority,\n cookies.source_port AS SourcePort\n FROM cookies\n ORDER BY cookies.creation_utc ASC\n"},{"Name":"Chromium Browser Top Sites","Author":"Andrew Rathbun","Categories":["Chrome","Browser"],"Sources":[{"Name":""}],"RawData":"Name: Chromium Browser Top Sites\nAuthor: Andrew Rathbun\nEmail: andrew.d.rathbun@gmail.com\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='meta' OR name='top_sites');\nSQLiteIdentifyValue: 2\nCategories:\n - Chrome\n - Browser\n\nFilenameRegex: \"Top Sites\"\nGlobs:\n - \"{{LinuxChromeProfiles}}/*/Top Sites\"\n - \"{{WindowsChromeProfiles}}/*/Top Sites\"\n - \"{{MacOSChromeProfiles}}/*/Top Sites\"\n\nSources:\n- VQL: |\n SELECT * FROM Rows\n WHERE ( URL =~ FilterRegex OR Title =~ FilterRegex )\n\n SQL: |\n SELECT\n top_sites.url_rank AS URLRank,\n top_sites.url AS URL,\n top_sites.title AS Title\n FROM top_sites\n ORDER BY top_sites.url_rank ASC\n"},{"Name":"Edge Browser Autofill","Author":"Chris Hayes - Reliance Cyber","Categories":["Edge","Browser"],"Sources":[{"Name":"CombinedAutofill"}],"RawData":"Name: Edge Browser Autofill\nAuthor: Chris Hayes - Reliance Cyber\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='autofill_edge_field_client_info' OR name='autofill_edge_field_values');\nSQLiteIdentifyValue: 2\nCategories:\n - Edge\n - Browser\n\nFilenameRegex: \"Web Data\"\nGlobs:\n - \"{{LinuxChromeProfiles}}/*/Web Data\"\n - \"{{WindowsChromeProfiles}}/*/Web Data\"\n - \"{{MacOSChromeProfiles}}/*/Web Data\"\n\nSources:\n- name: CombinedAutofill\n VQL: |\n SELECT timestamp(epoch=date_last_used) AS DateLastUsed\n FROM Rows\n WHERE DateLastUsed \u003e DateAfter AND DateLastUsed \u003c DateBefore\n\n SQL: |\n SELECT\n autofill_edge_field_client_info.form_signature_v1,\n autofill_edge_field_client_info.form_signature_v2,\n autofill_edge_field_client_info.domain_value,\n autofill_edge_field_values.date_last_used,\n GROUP_CONCAT(autofill_edge_field_client_info.label || ': ' || autofill_edge_field_values.value, ', ') AS label_value_pairs,\n json_group_object(autofill_edge_field_client_info.label, autofill_edge_field_values.value) AS label_value_json\n FROM\n autofill_edge_field_values\n JOIN\n autofill_edge_field_client_info\n ON\n autofill_edge_field_values.field_id = autofill_edge_field_client_info.field_id\n GROUP BY\n autofill_edge_field_client_info.form_signature_v1,\n autofill_edge_field_client_info.form_signature_v2,\n autofill_edge_field_client_info.domain_value,\n autofill_edge_field_values.date_last_used;\n"},{"Name":"Edge Browser Navigation History","Author":"Suyash Tripathi","Categories":["Edge","Browser"],"Sources":[{"Name":"Navigation History"}],"RawData":"Name: Edge Browser Navigation History\nAuthor: Suyash Tripathi\nEmail: suyash.tripathi@cybercx.com.au\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND name='navigation_history';\nSQLiteIdentifyValue: 1\nCategories:\n - Edge\n - Browser\nFilenameRegex: \"WebAssistDatabase\"\nGlobs:\n - \"{{WindowsChromeProfiles}}/*/WebAssistDatabase\"\n - \"{{MacOSChromeProfiles}}/*/WebAssistDatabase\"\n\nSources:\n- name: Navigation History\n VQL: |\n SELECT ID,\n timestamp(epoch=`Last Visited Time`) AS `Last Visited Time`,\n Title, URL, VisitCount, OSPath\n FROM Rows\n WHERE `Last Visited Time` \u003e DateAfter\n AND `Last Visited Time` \u003c DateBefore\n AND (Title, URL) =~ FilterRegex\n\n SQL: |\n SELECT\n navigation_history.id AS ID,\n navigation_history.last_visited_time AS 'Last Visited Time',\n navigation_history.title AS Title,\n navigation_history.url AS URL,\n navigation_history.num_visits AS VisitCount\n FROM\n navigation_history\n ORDER BY\n navigation_history.last_visited_time ASC;\n"},{"Name":"Firefox Places","Author":"Andrew Rathbun","Categories":["Firefox","Browser"],"Sources":[{"Name":""},{"Name":"Downloads"},{"Name":"History"}],"RawData":"Name: Firefox Places\nAuthor: Andrew Rathbun\nEmail: andrew.d.rathbun@gmail.com\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='moz_historyvisits' OR name='moz_bookmarks'\n OR name='moz_places' OR name='moz_inputhistory');\nSQLiteIdentifyValue: 4\nCategories:\n - Firefox\n - Browser\n\nFilenameRegex: \"places.sqlite\"\nGlobs:\n - \"{{WindowsFirefoxProfiles}}/*/places.sqlite\"\n - \"{{LinuxFirefoxProfiles}}/places.sqlite\"\n - \"{{MacOSFirefoxProfiles}}/places.sqlite\"\n\nSources:\n- Preamble: |\n LET BookmarkTypes \u003c= dict(`1`=\"URL\", `2`=\"Folder\", `3`=\"Separator\")\n\n VQL: |\n SELECT ID, ParentID,\n get(item= BookmarkTypes, field=str(str=type), default=\"Unknown\") AS Type,\n timestamp(epoch=dateAdded) AS DateAdded,\n timestamp(epoch=lastModified) AS LastModified,\n Position, Title, URL, ForeignKey, OSPath\n FROM Rows\n WHERE LastModified \u003e DateAfter AND LastModified \u003c DateBefore\n AND (Title, URL) =~ FilterRegex\n\n SQL: |\n SELECT\n Bookmarks.id AS ID,\n Bookmarks.parent AS ParentID,\n Bookmarks.type,\n Bookmarks.dateAdded,\n Bookmarks.lastModified,\n Bookmarks.position AS Position,\n Bookmarks.title AS Title,\n moz_places.url AS URL,\n Bookmarks.fk AS ForeignKey\n FROM moz_bookmarks AS Bookmarks\n LEFT JOIN moz_places ON Bookmarks.fk = moz_places.id\n ORDER BY Bookmarks.id ASC\n\n- name: Downloads\n VQL: |\n SELECT PlaceID, Content,\n timestamp(epoch=dateAdded) AS DateAdded,\n timestamp(epoch=lastModified) AS LastModified,\n OSPath\n FROM Rows\n WHERE LastModified \u003e DateAfter AND LastModified \u003c DateBefore\n AND Content =~ FilterRegex\n\n SQL: |\n SELECT\n moz_annos.place_id AS PlaceID,\n moz_annos.content AS Content,\n dateAdded,\n lastModified\n FROM moz_annos\n WHERE anno_attribute_id IN (1,2)\n ORDER BY moz_annos.dateAdded ASC\n\n- name: History\n Preamble: |\n LET VisitType \u003c= dict(`1`='TRANSITION_LINK', `2`='TRANSITION_TYPED', `3`='TRANSITION_BOOKMARK',\n `4`='TRANSITION_EMBED', `5`= 'TRANSITION_REDIRECT_PERMANENT', `6`='TRANSITION_REDIRECT_TEMPORARY',\n `7`='TRANSITION_DOWNLOAD', `8`='TRANSITION_FRAMED_LINK', `9`='TRANSITION_RELOAD')\n\n VQL: |\n SELECT VisitID, FromVisitID,\n timestamp(epoch= last_visit_date) AS LastVisitDate,\n VisitCount, URL, Title, Description,\n get(item= VisitType, field=str(str=visit_type), default=\"Unknown\") AS VisitType,\n Bool(Value=hidden) AS Hidden,\n Bool(Value=typed) AS Typed,\n Frecency, PreviewImageURL, OSPath\n FROM Rows\n WHERE LastVisitDate \u003e DateAfter AND LastVisitDate \u003c DateBefore\n AND (Title, URL, Description) =~ FilterRegex\n\n SQL: |\n SELECT\n moz_historyvisits.id AS VisitID,\n moz_historyvisits.from_visit AS FromVisitID,\n moz_places.last_visit_date,\n moz_places.visit_count AS VisitCount,\n moz_places.url AS URL,\n moz_places.title AS Title,\n moz_places.description AS Description,\n moz_historyvisits.visit_type,\n moz_places.hidden,\n moz_places.typed,\n moz_places.frecency AS Frecency,\n moz_places.preview_image_url AS PreviewImageURL\n FROM moz_places\n INNER JOIN moz_historyvisits ON moz_places.origin_id = moz_historyvisits.id\n ORDER BY moz_places.last_visit_date ASC\n"},{"Name":"Firefox Cookies","Author":"Andrew Rathbun","Categories":["Firefox","Browser"],"Sources":[{"Name":""}],"RawData":"Name: Firefox Cookies\nAuthor: Andrew Rathbun\nEmail: andrew.d.rathbun@gmail.com\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='moz_cookies');\nSQLiteIdentifyValue: 1\nCategories:\n - Firefox\n - Browser\n\nFilenameRegex: \"cookies.sqlite\"\nGlobs:\n - \"{{WindowsFirefoxProfiles}}/*/cookies.sqlite\"\n - \"{{LinuxFirefoxProfiles}}/cookies.sqlite\"\n - \"{{MacOSFirefoxProfiles}}/cookies.sqlite\"\n\nSources:\n- VQL: |\n SELECT ID, Host, Name, Value,\n timestamp(epoch= creationTime) AS CreationTime,\n timestamp(epoch= lastAccessed) AS LastAccessedTime,\n timestamp(epoch= expiry) AS Expiration,\n Bool(Value= isSecure) AS IsSecure,\n Bool(Value= isHttpOnly) AS IsHTTPOnly, OSPath\n FROM Rows\n WHERE LastAccessedTime \u003e DateAfter\n AND LastAccessedTime \u003c DateBefore\n AND ( Name =~ FilterRegex OR Value =~ FilterRegex )\n\n SQL: |\n SELECT\n moz_cookies.id AS ID,\n moz_cookies.host AS Host,\n moz_cookies.name AS Name,\n moz_cookies.value AS Value,\n moz_cookies.creationTime,\n moz_cookies.lastAccessed,\n moz_cookies.expiry,\n moz_cookies.isSecure,\n moz_cookies.isHttpOnly\n FROM moz_cookies\n ORDER BY moz_cookies.id ASC\n"},{"Name":"Firefox Downloads","Author":"Andrew Rathbun","Categories":["Firefox","Browser"],"Sources":[{"Name":""}],"RawData":"Name: Firefox Downloads\nAuthor: Andrew Rathbun\nEmail: andrew.d.rathbun@gmail.com\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='moz_downloads');\nSQLiteIdentifyValue: 1\nCategories:\n - Firefox\n - Browser\n\nFilenameRegex: \"downloads.sqlite\"\nGlobs:\n - \"{{WindowsFirefoxProfiles}}/*/downloads.sqlite\"\n - \"{{LinuxFirefoxProfiles}}/downloads.sqlite\"\n - \"{{MacOSFirefoxProfiles}}/downloads.sqlite\"\n\nSources:\n- VQL: |\n SELECT ID, Name, MIMEType, Source, Target,\n timestamp(epoch= startTime) AS StartTime,\n timestamp(epoch= endTime) AS EndTime,\n timestamp(epoch= expiry) AS Expiration,\n CurrentBytes, MaxBytes, OSPath\n FROM Rows\n WHERE StartTime \u003e DateAfter\n AND StartTime \u003c DateBefore\n AND Name =~ FilterRegex\n\n SQL: |\n SELECT\n moz_downloads.id AS ID,\n moz_downloads.name AS Name,\n moz_downloads.mimeType AS MIMEType,\n moz_downloads.source AS Source,\n moz_downloads.target AS Target,\n startTime,\n endTime,\n moz_downloads.currBytes AS CurrentBytes,\n moz_downloads.maxBytes AS MaxBytes\n FROM moz_downloads\n ORDER BY moz_downloads.id ASC\n"},{"Name":"Firefox Favicons","Author":"Andrew Rathbun","Categories":["Firefox","Browser"],"Sources":[{"Name":""}],"RawData":"Name: Firefox Favicons\nAuthor: Andrew Rathbun\nEmail: andrew.d.rathbun@gmail.com\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='moz_icons' OR name='moz_icons_to_pages' OR name='moz_pages_w_icons');\nSQLiteIdentifyValue: 3\nCategories:\n - Firefox\n - Browser\n\nFilenameRegex: \"favicons.sqlite\"\nGlobs:\n - \"{{WindowsFirefoxProfiles}}/*/favicons.sqlite\"\n - \"{{LinuxFirefoxProfiles}}/favicons.sqlite\"\n - \"{{MacOSFirefoxProfiles}}/favicons.sqlite\"\n\nSources:\n- VQL: |\n SELECT ID, PageURL, FaviconURL,\n timestamp(epoch= expire_ms) AS Expiration,\n OSPath\n FROM Rows\n SQL: |\n SELECT\n moz_icons.id AS ID,\n moz_pages_w_icons.page_url AS PageURL,\n moz_icons.icon_url AS FaviconURL,\n moz_icons.expire_ms\n FROM moz_icons\n INNER JOIN moz_icons_to_pages ON moz_icons.id = moz_icons_to_pages.icon_id\n INNER JOIN moz_pages_w_icons ON moz_icons_to_pages.page_id = moz_pages_w_icons.id\n ORDER BY moz_icons.expire_ms ASC\n"},{"Name":"Firefox Form History","Author":"Andrew Rathbun","Categories":["Firefox","Browser"],"Sources":[{"Name":""}],"RawData":"Name: Firefox Form History\nAuthor: Andrew Rathbun\nEmail: andrew.d.rathbun@gmail.com\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='moz_formhistory');\n\nSQLiteIdentifyValue: 1\nCategories:\n - Firefox\n - Browser\n\nFilenameRegex: \"formhistory.sqlite\"\nGlobs:\n - \"{{WindowsFirefoxProfiles}}/*/formhistory.sqlite\"\n - \"{{LinuxFirefoxProfiles}}/formhistory.sqlite\"\n - \"{{MacOSFirefoxProfiles}}/formhistory.sqlite\"\n\nSources:\n- VQL: |\n SELECT ID, FieldName, Value, TimesUsed,\n timestamp(epoch= firstUsed) AS FirstUsed,\n timestamp(epoch= lastUsed) AS LastUsed,\n GUID, OSPath\n FROM Rows\n WHERE LastUsed \u003e DateAfter AND LastUsed \u003c DateBefore\n AND ( FieldName =~ FilterRegex OR Value =~ FilterRegex )\n\n SQL: |\n SELECT\n id AS ID,\n fieldname AS FieldName,\n value AS Value,\n timesUsed AS TimesUsed,\n firstUsed,\n lastUsed,\n guid AS GUID\n FROM moz_formhistory\n ORDER BY id ASC\n"},{"Name":"IE or Edge WebCacheV01","Categories":["Edge","InternetExplorer","Browser"],"Sources":[{"Name":"All Data"},{"Name":"Highlights"}],"RawData":"Name: IE or Edge WebCacheV01\nCategories:\n - Edge\n - InternetExplorer\n - Browser\n\nFilenameRegex: \"WebCacheV01.dat\"\nGlobs:\n - C:/Users/*/AppData/Local/Microsoft/Windows/WebCache/WebCacheV01.dat\n\nSources:\n- name: All Data\n Preamble: |\n LET MatchingFiles = SELECT OSPath FROM Rows\n LET S = scope()\n\n LET Containers(OSPath) = SELECT Table\n FROM parse_ese_catalog(file=OSPath)\n WHERE Table =~ \"Container_\"\n GROUP BY Table\n\n LET AllHits(OSPath) = SELECT * FROM foreach(row={\n SELECT * FROM Containers(OSPath=OSPath)\n }, query={\n SELECT timestamp(winfiletime=ExpiryTime) AS ExpiryTime,\n timestamp(winfiletime=ModifiedTime) AS ModifiedTime,\n timestamp(winfiletime=AccessedTime) AS AccessedTime,\n S.Url AS Url, *\n FROM parse_ese(file=OSPath, table=Table)\n })\n\n VQL: |\n SELECT * FROM foreach(row=MatchingFiles, query={\n SELECT * FROM AllHits(OSPath=OSPath)\n })\n WHERE AccessedTime \u003e DateAfter AND AccessedTime \u003c DateBefore\n AND Url =~ FilterRegex\n\n\n- name: Highlights\n VQL: |\n SELECT * FROM foreach(row=MatchingFiles, query={\n SELECT AccessedTime, ModifiedTime, ExpiryTime, Url\n FROM AllHits(OSPath=OSPath)\n })\n WHERE AccessedTime \u003e DateAfter AND AccessedTime \u003c DateBefore\n AND Url =~ FilterRegex\n"},{"Name":"MacOS Applications Cache","Author":"Wes Lambert - @therealwlambert","Description":"Applications can use the NSURL cache to store specific data that is\nuseful to the operation of the application in a `Cache.db` file on\ndisk. The data contained within this file could potentially be\nuseful to investigators or incident responders, such as URLs that\nwere accessed, as well as data requested or returned.\n","Categories":["MacOS"],"Sources":[{"Name":""}],"RawData":"Name: MacOS Applications Cache\nAuthor: Wes Lambert - @therealwlambert\nDescription: |\n Applications can use the NSURL cache to store specific data that is\n useful to the operation of the application in a `Cache.db` file on\n disk. The data contained within this file could potentially be\n useful to investigators or incident responders, such as URLs that\n were accessed, as well as data requested or returned.\n\nReference: https://developer.apple.com/documentation/foundation/nsurl\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='cfurl_cache_response' OR name='cfurl_cache_blob_data'\n OR name='cfurl_cache_receiver_data');\nSQLiteIdentifyValue: 3\nCategories:\n - MacOS\n\nFilenameRegex: \"Cache.db\"\nGlobs:\n - \"/Users/*/Library/Caches/*/Cache.db\"\n\nSources:\n- VQL: |\n SELECT\n time_stamp AS Timestamp,\n OSPath.Base AS Application,\n entry_ID AS EntryID,\n version AS Version,\n hash_value AS Hash,\n storage_policy AS StoragePolicy,\n request_key AS URL,\n plist(file=request_object, accessor=\"data\") AS Request,\n plist(file=response_object, accessor=\"data\") AS Response,\n partition AS Partition,\n OSPath\n FROM Rows\n WHERE Timestamp \u003e DateAfter AND Timestamp \u003c DateBefore\n AND Application =~ FilterRegex\n\n SQL: |\n SELECT cfurl_cache_response.entry_ID AS entry_ID,\n version, hash_value, storage_policy, request_key,\n time_stamp, partition, request_object, response_object\n FROM cfurl_cache_response\n INNER JOIN cfurl_cache_blob_data ON cfurl_cache_response.entry_ID = cfurl_cache_blob_data.entry_ID\n INNER JOIN cfurl_cache_receiver_data ON cfurl_cache_response.entry_ID = cfurl_cache_receiver_data.entry_ID\n"},{"Name":"MacOS NetworkUsage","Author":"Wes Lambert - @therealwlambert","Description":"On macOS, the NetUsage DB can provide various details around\napplication network utilization. With this artifact, we can get an\nidea of what applications are utilizing the network for\ncommunications and to what degree. We can also identify if usage\nhas occurred through a WIFI network or a wired network.\n\nMore information about this database can be found here:\n\nhttp://www.mac4n6.com/blog/2019/1/6/network-and-application-usage-using-netusagesqlite-amp-datausagesqlite-ios-databases\n","Categories":["MacOS"],"Sources":[{"Name":""}],"RawData":"Name: MacOS NetworkUsage\nAuthor: Wes Lambert - @therealwlambert\nDescription: |\n On macOS, the NetUsage DB can provide various details around\n application network utilization. With this artifact, we can get an\n idea of what applications are utilizing the network for\n communications and to what degree. We can also identify if usage\n has occurred through a WIFI network or a wired network.\n\n More information about this database can be found here:\n\n http://www.mac4n6.com/blog/2019/1/6/network-and-application-usage-using-netusagesqlite-amp-datausagesqlite-ios-databases\n\nReference: http://www.mac4n6.com/blog/2019/1/6/network-and-application-usage-using-netusagesqlite-amp-datausagesqlite-ios-databases\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='ZLIVEUSAGE' OR name='ZPROCESS');\nSQLiteIdentifyValue: 2\nCategories:\n - MacOS\n\nFilenameRegex: \"netusage.sqlite\"\nGlobs:\n - /private/var/networkd/netusage.sqlite\n - /private/var/networkd/db/netusage.sqlite\n\nSources:\n- VQL: |\n SELECT timestamp(epoch= ZTIMESTAMP + 978307200) AS Timestamp,\n timestamp(epoch= ZFIRSTTIMESTAMP + 978307200) AS FirstTimestamp,\n timestamp(epoch= LIVE_USAGE_TIMESTAMP + 978307200) AS LiveUsageTimestamp,\n ZBUNDLENAME AS BundleID,\n ZPROCNAME AS ProcessName,\n ZWIFIIN AS WifiIn,\n ZWIFIOUT AS WifiOut,\n ZWWANIN AS WanIn,\n ZWWANOUT AS WandOut,\n ZWIREDIN AS WiredIn,\n ZWIREDOUT AS WiredOut,\n ZXIN AS _XIn,\n ZXOUT AS _XOut,\n Z_PK AS LiveUsageTableID\n FROM Rows\n\n SQL: |\n SELECT\n ZPROCESS.ZTIMESTAMP,\n ZPROCESS.ZFIRSTTIMESTAMP,\n ZLIVEUSAGE.ZTIMESTAMP AS LIVE_USAGE_TIMESTAMP\",\n ZBUNDLENAME,\n ZPROCNAME,\n ZWIFIIN,\n ZWIFIOUT,\n ZWWANIN,\n ZWWANOUT,\n ZWIREDIN,\n ZWIREDOUT,\n ZXIN,\n ZXOUT,\n ZLIVEUSAGE.Z_PK,\n FROM ZLIVEUSAGE\n LEFT JOIN ZPROCESS ON ZPROCESS.Z_PK = ZLIVEUSAGE.ZHASPROCESS\n"},{"Name":"MacOS Notes","Author":"Wes Lambert - @therealwlambert","Description":"This artifact provides details about notes taken using the default\nNotes application on macOS. These notes can be useful during an\ninvestigation, especially if tied to interesting files.\n\nDeleted notes and attachments can also be recovered in some\ninstances.\n\nThe SQL query within this artifact was primarily derived from\nYogesh Khatri's referenced blog post.\n\nNOTE: This artifact may not cover all attachments at this time, and\nthere are many more great pieces of data to discover! More\ninformation can be found in the `ZICCLOUDSYNCINGOBJECT` table.\n","Categories":["MacOS"],"Sources":[{"Name":""}],"RawData":"Name: MacOS Notes\nAuthor: Wes Lambert - @therealwlambert\nDescription: |\n This artifact provides details about notes taken using the default\n Notes application on macOS. These notes can be useful during an\n investigation, especially if tied to interesting files.\n\n Deleted notes and attachments can also be recovered in some\n instances.\n\n The SQL query within this artifact was primarily derived from\n Yogesh Khatri's referenced blog post.\n\n NOTE: This artifact may not cover all attachments at this time, and\n there are many more great pieces of data to discover! More\n information can be found in the `ZICCLOUDSYNCINGOBJECT` table.\n\nReference: http://www.swiftforensics.com/2018/02/reading-notes-database-on-macos.html\n\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='ZICNOTEDATA' OR name='ZICCLOUDSYNCINGOBJECT');\nSQLiteIdentifyValue: 2\nCategories:\n - MacOS\n\nFilenameRegex: \"NoteStore.sqlite|NotesV.+storedata\"\nGlobs:\n - /Users/*/Library/Containers/com.apple.Notes/Data/Library/Notes/NotesV*.storedata\n - /Users/*/Library/Group Containers/group.com.apple.notes/NoteStore.sqlite\n\nSources:\n- VQL: |\n SELECT Key AS _Key,\n OSPath[1] AS User,\n Note,\n Title,\n Snippet,\n NoteID AS _NoteID,\n timestamp(cocoatime=CreatedTS) AS CreatedTime,\n timestamp(cocoatime=LastOpenedDate) AS LastOpenedTime,\n timestamp(cocoatime=DirModificationDate) AS LastDirModifcation,\n Account AS _Account,\n Directory,\n DirectoryID,\n AttachmentName,\n AttachmentSize,\n AttachmentUUID,\n if(condition=AttachmentUUID,\n then=OSPath[:2] + '/Library/Group Containers/group.com.apple.notes/Accounts/LocalAccount/Media/' + AttachmentUUID + '/' + AttachmentName) AS AttachmentLocation,\n AccountName AS _AccountName,\n AccountID AS _AccountID,\n AccountType AS _AccountType,\n gunzip(string=Data) AS Data,\n OSPath\n FROM Rows\n WHERE LastOpenedTime \u003e DateAfter AND LastOpenedTime \u003c DateBefore\n AND ( Title =~ FilterRegex OR Data =~ FilterRegex )\n\n SQL: |\n SELECT n.Z_PK AS Key,\n n.ZNOTE as Note,\n c1.ZTITLE1 as Title,\n c1.ZSNIPPET as Snippet,\n c1.ZIDENTIFIER as NoteID,\n c1.ZCREATIONDATE3 as CreatedTS,\n c1.ZFOLDERMODIFICATIONDATE AS DirModificationDate,\n c1.ZLASTOPENEDDATE AS LastOpenedDate,\n c2.ZACCOUNT3 as Account,\n c2.ZTITLE2 as Directory,\n c2.ZIDENTIFIER as DirectoryID,\n c4.ZFILENAME as AttachmentName,\n c3.ZFILESIZE as AttachmentSize,\n c4.ZIDENTIFIER as AttachmentUUID,\n c5.ZNAME as AccountName,\n c5.ZIDENTIFIER as AccountID,\n c5.ZACCOUNTTYPE as AccountType,\n n.ZDATA as Data\n FROM ZICNOTEDATA as n\n LEFT JOIN ZICCLOUDSYNCINGOBJECT as c1 ON c1.ZNOTEDATA = n.Z_PK\n LEFT JOIN ZICCLOUDSYNCINGOBJECT as c2 ON c2.Z_PK = c1.ZFOLDER\n LEFT JOIN ZICCLOUDSYNCINGOBJECT as c3 ON c3.ZNOTE= n.ZNOTE\n LEFT JOIN ZICCLOUDSYNCINGOBJECT as c4 ON c4.ZATTACHMENT1= c3.Z_PK\n LEFT JOIN ZICCLOUDSYNCINGOBJECT as c5 ON c5.Z_PK = c1.ZACCOUNT2\n ORDER BY Key\n"},{"Name":"MacOS XProtect Detections","Author":"Matt Green - @mgreen27","Description":"This artifact provides details about XProtect detections on macOS.\n\nmacOS includes built-in antivirus technology called XProtect for \nthe signature-based detection and removal of malware. The system \nuses YARA and behavorial signatures.\n","Categories":["MacOS"],"Sources":[{"Name":""}],"RawData":"Name: MacOS XProtect Detections\nAuthor: Matt Green - @mgreen27\nDescription: |\n This artifact provides details about XProtect detections on macOS.\n\n macOS includes built-in antivirus technology called XProtect for \n the signature-based detection and removal of malware. The system \n uses YARA and behavorial signatures.\n\nReference: https://www.huntress.com/blog/dmxprotect-stop-drop-shut-malware-down-before-it-opens-up-shop\n\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND name='events';\nSQLiteIdentifyValue: 1\n\nCategories:\n - MacOS\n\nFilenameRegex: \"XPdb\"\nGlobs:\n - \"/private/var/protected/xprotect/XPdb\"\n\nSources:\n- VQL: |\n SELECT *\n FROM Rows\n WHERE dt \u003e DateAfter\n AND dt \u003c DateBefore\n AND (violated_rule, exec_path, responsible_path, responsible_signing_id,\n exec_cdhash, exec_sha256, responsible_cdhash, responsible_sha256 ) =~ FilterRegex\n\n SQL: |\n SELECT * FROM events\n"},{"Name":"Windows Activities Cache","Author":"Eric Zimmerman","Categories":["Windows"],"Sources":[{"Name":"ActivityPackageId"},{"Name":"Clipboard"}],"RawData":"Name: Windows Activities Cache\nAuthor: Eric Zimmerman\nEmail: saericzimmerman@gmail.com\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='Activity' OR name='Activity_PackageId' OR name='ActivityOperation');\nSQLiteIdentifyValue: 3\nCategories:\n - Windows\n\nFilenameRegex: \"ActivitiesCache.db\"\nGlobs:\n - \"C:/Users/*/AppData/Local/ConnectedDevicesPlatform/L.*/ActivitiesCache.db\"\n\nSources:\n- name: ActivityPackageId\n VQL: |\n SELECT format(format=\"%0X-%0X-%0X-%0X-%0X\", args=[\n ActivityId[0:4], ActivityId[4:6], ActivityId[6:8],\n ActivityId[8:10], ActivityId[10:] ]) AS ActivityId,\n Platform, PackageName, ExpirationTime, OSPath\n FROM Rows\n\n SQL: |\n Select ActivityId, Platform, PackageName, ExpirationTime\n FROM Activity_PackageId\n\n- name: Clipboard\n SQL: |\n SELECT * FROM ActivityOperation\n VQL: |\n SELECT\n CreatedTime,\n timestamp(epoch=LastModifiedTime) AS LastModifiedTime,\n timestamp(epoch=LastModifiedOnClient) AS LastModifiedOnClient,\n StartTime,\n EndTime,\n Payload,\n OSPath[1] AS User,\n base64decode(string=parse_json_array(data=ClipboardPayload)[0].content) AS ClipboardPayload,\n OSPath AS Path,\n Mtime\n FROM Rows\n WHERE StartTime \u003e DateAfter\n AND StartTime \u003c DateBefore\n AND ClipboardPayload =~ FilterRegex\n"},{"Name":"Windows Search Service","Description":"Analysis of the Windows search index database. See\nhttps://www.aon.com/cyber-solutions/aon_cyber_labs/windows-search-index-the-forensic-artifact-youve-been-searching-for/\n","Categories":["Windows"],"Sources":[{"Name":"SystemIndex_Gthr"},{"Name":"SystemIndex_GthrPth"},{"Name":"SystemIndex_PropertyStore"},{"Name":"SystemIndex_PropertyStore_Highlights"},{"Name":"BrowsingActivity"},{"Name":"UserActivityLogging"}],"RawData":"Name: Windows Search Service\n\nDescription: |\n Analysis of the Windows search index database. See\n https://www.aon.com/cyber-solutions/aon_cyber_labs/windows-search-index-the-forensic-artifact-youve-been-searching-for/\n\nCategories:\n - Windows\n\nFilenameRegex: \"Windows.edb\"\nGlobs:\n - C:\\ProgramData\\Microsoft\\Search\\Data\\Applications\\Windows\\Windows.edb\n\nSources:\n- name: SystemIndex_Gthr\n Preamble: |\n LET MatchingFiles = SELECT OSPath FROM Rows\n\n LET FormatTimeB(T) = timestamp(winfiletime=parse_binary(\n filename=T, accessor=\"data\", struct=\"uint64b\"))\n\n LET FormatTime(T) = timestamp(winfiletime=parse_binary(\n filename=T, accessor=\"data\", struct=\"uint64\"))\n\n LET FormatSize(T) = parse_binary(\n filename=T, accessor=\"data\", struct=\"uint64\")\n\n VQL: |\n SELECT * FROM foreach(row=MatchingFiles, query={\n SELECT ScopeID, DocumentID, SDID,\n FormatTimeB(T=LastModified) AS LastModified,\n FileName\n FROM parse_ese(file=OSPath, table= \"SystemIndex_Gthr\")\n })\n WHERE LastModified \u003e DateAfter AND LastModified \u003c DateBefore\n AND FileName =~ FilterRegex\n\n- name: SystemIndex_GthrPth\n VQL: |\n SELECT * FROM foreach(row=MatchingFiles, query={\n SELECT Scope, Parent, Name\n FROM parse_ese(file=OSPath, table= \"SystemIndex_GthrPth\")\n })\n WHERE Name =~ FilterRegex\n\n- name: SystemIndex_PropertyStore\n Preamble: |\n LET X = scope()\n\n -- The PropertyStore columns look like\n -- \u003crandom\u003e-ProperName so we strip the\n -- random part off to display it properly.\n LET FilterDict(Dict) = to_dict(item={\n SELECT split(sep_string=\"-\", string=_key)[1] || _key AS _key, _value\n FROM items(item=Dict)\n })\n\n LET PropStore(OSPath) = SELECT *,\n FormatTime(T=X.System_Search_GatherTime) AS System_Search_GatherTime,\n FormatSize(T=X.System_Size) AS System_Size,\n FormatTime(T=X.System_DateModified) AS System_DateModified,\n FormatTime(T=X.System_DateAccessed) AS System_DateAccessed,\n FormatTime(T=X.System_DateCreated) AS System_DateCreated\n FROM foreach(row={\n SELECT *, FilterDict(Dict=_value) AS _value\n FROM items(item={\n SELECT * FROM parse_ese(file=OSPath, table=\"SystemIndex_PropertyStore\")\n })\n }, column=\"_value\")\n\n VQL: |\n SELECT * FROM foreach(row=MatchingFiles, query={\n SELECT *\n FROM PropStore(OSPath=OSPath)\n })\n WHERE System_DateAccessed \u003e DateAfter AND System_DateAccessed \u003c DateBefore\n\n- name: SystemIndex_PropertyStore_Highlights\n VQL: |\n SELECT * FROM foreach(row=MatchingFiles, query={\n SELECT WorkID,\n System_Search_GatherTime,\n System_Size,\n System_DateModified,\n System_DateCreated,\n X.System_FileOwner AS System_FileOwner,\n X.System_ItemPathDisplay AS System_ItemPathDisplay,\n X.System_ItemType AS System_ItemType,\n X.System_FileAttributes AS System_FileAttributes,\n X.System_Search_AutoSummary AS System_Search_AutoSummary\n FROM PropStore(OSPath=OSPath)\n })\n WHERE System_DateAccessed \u003e DateAfter AND System_DateAccessed \u003c DateBefore\n\n- name: BrowsingActivity\n VQL: |\n SELECT * FROM foreach(row=MatchingFiles, query={\n SELECT X.ItemPathDisplay AS ItemPathDisplay,\n X.Activity_ContentUri AS Activity_ContentUri,\n X.Activity_Description AS Activity_Description\n FROM PropStore(OSPath=OSPath)\n WHERE Activity_ContentUri\n })\n\n- name: UserActivityLogging\n VQL: |\n SELECT * FROM foreach(row=MatchingFiles, query={\n SELECT X.System_ItemPathDisplay AS System_ItemPathDisplay,\n FormatTime(T=X.ActivityHistory_StartTime) AS ActivityHistory_StartTime,\n FormatTime(T=X.ActivityHistory_EndTime) AS ActivityHistory_EndTime,\n X.ActivityHistory_AppId AS ActivityHistory_AppId\n FROM PropStore(OSPath=OSPath)\n WHERE ActivityHistory_AppId\n })\n WHERE ActivityHistory_StartTime \u003e DateAfter\n AND ActivityHistory_StartTime \u003c DateBefore\n"}] \ No newline at end of file +[ + { + "Name": "iMessage", + "Author": "x64-julian", + "Description": "Parses the `chat.db` from IOS platforms.\n", + "Categories": [ + "MacOS" + ], + "Sources": [ + { + "Name": "Profiles" + } + ], + "RawData": "Name: iMessage\nAuthor: x64-julian\nDescription: |\n Parses the `chat.db` from IOS platforms.\n\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='chat_handle_join' OR name='message_attachment_join'\n OR name='sync_deleted_messages');\nSQLiteIdentifyValue: 3\nCategories:\n - MacOS\nFilenameRegex: \"chat.db\"\nGlobs:\n - \"/Users/*/Library/Messages/chat.db\"\n\nSources:\n- name: Profiles\n VQL: |\n SELECT timestamp(epoch=date / 1000000000 + 978307200) AS Timestamp, *\n FROM Rows\n WHERE Timestamp \u003e DateAfter AND Timestamp \u003c DateBefore\n AND (MessageText, RoomName) =~ FilterRegex\n\n SQL: |\n SELECT\n m.rowid,\n coalesce(m.cache_roomnames, h.id) AS ThreadId,\n m.is_from_me AS IsFromMe,\n\n CASE when m.is_from_me = 1 THEN m.account\n ELSE h.id\n END AS FromPhoneNumber,\n\n CASE when m.is_from_me = 0 THEN m.account\n ELSE coalesce(h2.id, h.id)\n END AS ToPhoneNumber,\n\n m.service AS Service,\n m.date,\n m.text AS MessageText,\n c.display_name AS RoomName\n FROM message as m\n left join handle as h on m.handle_id = h.rowid\n left join chat as c on m.cache_roomnames = c.room_name -- note: chat.room_name is not unique, this may cause one-to-many join\n left join chat_handle_join as ch on c.rowid = ch.chat_id\n left join handle as h2 on ch.handle_id = h2.rowid\n WHERE\n -- try to eliminate duplicates due to non-unique\n -- message.cache_roomnames/chat.room_name\n (h2.service is null or m.service = h2.service)\n\n ORDER BY m.date DESC;\n" + }, + { + "Name": "Chromium Browser Autofill", + "Author": "Andrew Rathbun", + "Description": "Parses the `Web Data` file in the Chromium profile.\n\nThis file contains autofill data for forms such as email, addresses,\nnames etc.\n", + "Categories": [ + "Chrome", + "Browser" + ], + "Sources": [ + { + "Name": "Profiles" + }, + { + "Name": "Masked Credit Cards" + } + ], + "RawData": "Name: Chromium Browser Autofill\nDescription: |\n Parses the `Web Data` file in the Chromium profile.\n\n This file contains autofill data for forms such as email, addresses,\n names etc.\n\nAuthor: Andrew Rathbun\nEmail: andrew.d.rathbun@gmail.com\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='autofill' OR name='credit_cards'\n OR name='offer_data' OR name='server_addresses' OR name='keywords');\nSQLiteIdentifyValue: 5\nCategories:\n - Chrome\n - Browser\n\nFilenameRegex: \"Web Data\"\nGlobs:\n - \"{{LinuxChromeProfiles}}/*/Web Data\"\n - \"{{WindowsChromeProfiles}}/*/Web Data\"\n - \"{{MacOSChromeProfiles}}/*/Web Data\"\n\nSources:\n- name: Profiles\n VQL: |\n SELECT GUID,\n timestamp(epoch= date_modified) AS DateModified,\n timestamp(epoch= use_date) AS UseDate,\n FirstName, MiddleName, LastName, EmailAddress,\n PhoneNumber, CompanyName, StreetAddress,\n City, State, ZipCode, UseCount, OSPath\n FROM Rows\n WHERE UseDate \u003e DateAfter AND UseDate \u003c DateBefore\n AND (FirstName, MiddleName, LastName, EmailAddress, CompanyName, StreetAddress) =~ FilterRegex\n\n SQL: |\n SELECT\n autofill_profiles.guid AS GUID,\n date_modified,\n use_date,\n autofill_profile_names.first_name AS FirstName,\n autofill_profile_names.middle_name AS MiddleName,\n autofill_profile_names.last_name AS LastName,\n autofill_profile_emails.email as EmailAddress,\n autofill_profile_phones.number AS PhoneNumber,\n autofill_profiles.company_name AS CompanyName,\n autofill_profiles.street_address AS StreetAddress,\n autofill_profiles.city AS City,\n autofill_profiles.state AS State,\n autofill_profiles.zipcode AS ZipCode,\n autofill_profiles.use_count AS UseCount\n FROM\n autofill_profiles\n INNER JOIN autofill_profile_emails ON autofill_profile_emails.guid = autofill_profiles.guid\n INNER JOIN autofill_profile_phones ON autofill_profiles.guid = autofill_profile_phones.guid\n INNER JOIN autofill_profile_names ON autofill_profile_phones.guid = autofill_profile_names.guid\n ORDER BY\n autofill_profiles.guid ASC\n\n- name: Masked Credit Cards\n VQL: \"SELECT * FROM Rows\"\n SQL: |\n SELECT\n masked_credit_cards.id AS ID,\n masked_credit_cards.name_on_card AS NameOnCard,\n masked_credit_cards.network AS CardNetwork,\n masked_credit_cards.last_four AS LastFour,\n masked_credit_cards.exp_month AS ExpMonth,\n masked_credit_cards.exp_year AS ExpYear,\n masked_credit_cards.bank_name AS BankName,\n masked_credit_cards.nickname AS CardNickname,\n masked_credit_cards.card_issuer AS CardIssuer,\n masked_credit_cards.instrument_id AS InstrumentID\n FROM masked_credit_cards\n ORDER BY masked_credit_cards.id ASC\n" + }, + { + "Name": "Chromium Browser Bookmarks", + "Author": "Sikha Puthanveedu @SikhaMohan, Mike Cohen", + "Description": "Parses the browser's Bookmarks file.\n", + "Categories": [ + "Chrome", + "Browser" + ], + "Sources": [ + { + "Name": "" + } + ], + "RawData": "Name: Chromium Browser Bookmarks\nDescription: |\n Parses the browser's Bookmarks file.\n\nAuthor: Sikha Puthanveedu @SikhaMohan, Mike Cohen\nCategories:\n - Chrome\n - Browser\n\nFilenameRegex: \"Bookmarks\"\nGlobs:\n - \"{{LinuxChromeProfiles}}/*/Bookmarks\"\n - \"{{WindowsChromeProfiles}}/*/Bookmarks\"\n - \"{{MacOSChromeProfiles}}/*/Bookmarks\"\n\nSources:\n- Preamble: |\n -- Recursive function to report the details of a folder\n LET ReportFolder(Data, BaseName) = SELECT * FROM chain(a={\n -- First row emit the data about the actual folder\n SELECT BaseName + \" | \" + Data.name AS Name,\n timestamp(winfiletime=int(int=Data.date_added) * 10) AS DateAdded,\n timestamp(winfiletime=int(int=Data.date_last_used) * 10) AS DateLastUsed,\n Data.type AS Type,\n Data.url || \"\" AS URL\n FROM scope()\n },\n b={\n -- If this folder has children recurse into it\n SELECT * FROM foreach(row={\n SELECT _value FROM items(item=Data.children)\n }, query={\n SELECT * FROM ReportFolder(Data=_value, BaseName=BaseName + \" | \" + Data.name)\n })\n })\n\n LET MatchingFiles = SELECT OSPath, parse_json(data=read_file(filename=OSPath)) AS Data\n FROM Rows\n\n VQL: |\n SELECT * FROM foreach(row=MatchingFiles, query={\n SELECT * FROM chain(\n a={\n SELECT OSPath, *, \"bookmark_bar\" AS Type\n FROM ReportFolder(Data=Data.roots.bookmark_bar, BaseName=\"\")\n },\n b={\n SELECT OSPath, *, \"other\" AS Type\n FROM ReportFolder(Data=Data.roots.other, BaseName=\"\")\n },\n c={\n SELECT OSPath, *, \"synced\" AS Type\n FROM ReportFolder(Data=Data.roots.synced, BaseName=\"\")\n })\n })\n" + }, + { + "Name": "Chromium Browser Cookies", + "Author": "Andrew Rathbun", + "Description": "Parses the cookies held by the Chromium browser.\n", + "Categories": [ + "Chrome", + "Browser" + ], + "Sources": [ + { + "Name": "Cookies" + } + ], + "RawData": "Name: Chromium Browser Cookies\nDescription: |\n Parses the cookies held by the Chromium browser.\n\nAuthor: Andrew Rathbun\nEmail: andrew.d.rathbun@gmail.com\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master WHERE type='table' AND (name='cookies' OR name='meta');\nSQLiteIdentifyValue: 2\nCategories:\n - Chrome\n - Browser\nFilenameRegex: \"Cookies\"\nGlobs:\n - \"{{LinuxChromeProfiles}}/*/Cookies\"\n - \"{{WindowsChromeProfiles}}/*/Cookies\"\n - \"{{MacOSChromeProfiles}}/*/Cookies\"\n\nSources:\n- name: Cookies\n VQL: |\n SELECT timestamp(winfiletime=(creation_utc * 10) || 0) AS CreationUTC,\n timestamp(winfiletime=(expires_utc * 10) || 0) AS ExpiresUTC,\n timestamp(winfiletime=(last_access_utc * 10) || 0) AS LastAccessUTC,\n HostKey, Name, Path,\n Bool(Value=is_secure) AS IsSecure,\n Bool(Value=is_httponly) AS IsHttpOnly,\n Bool(Value=has_expires) AS HasExpiration,\n Bool(Value=is_persistent) AS IsPersistent,\n Priority, SourcePort, OSPath\n FROM Rows\n WHERE LastAccessUTC \u003e DateAfter AND LastAccessUTC \u003c DateBefore\n AND (Name, Path) =~ FilterRegex\n\n SQL: |\n SELECT\n cookies.creation_utc,\n cookies.expires_utc,\n cookies.last_access_utc,\n cookies.host_key AS HostKey,\n cookies.name AS Name,\n cookies.path AS Path,\n cookies.is_secure,\n cookies.is_httponly,\n cookies.has_expires,\n cookies.is_persistent,\n cookies.priority AS Priority,\n cookies.source_port AS SourcePort\n FROM cookies\n ORDER BY cookies.creation_utc ASC\n" + }, + { + "Name": "Chromium Browser Extensions", + "Author": "Mike Cohen", + "Description": "Parses all installed chromium extensions.\n", + "Categories": [ + "Chrome", + "Browser" + ], + "Sources": [ + { + "Name": "" + } + ], + "RawData": "Name: Chromium Browser Extensions\nDescription: |\n Parses all installed chromium extensions.\n\nAuthor: Mike Cohen\nCategories:\n - Chrome\n - Browser\n\nFilenameRegex: \"manifest.json\"\nGlobs:\n - \"{{LinuxChromeProfiles}}/*/Extensions/**/manifest.json\"\n - \"{{WindowsChromeProfiles}}/*/Extensions/**/manifest.json\"\n - \"{{MacOSChromeProfiles}}/*/Extensions/**/manifest.json\"\n\nSources:\n- Preamble: |\n -- Resolve the message string against the Locale dict\n LET ResolveName(Message, Locale) = get(item=Locale,\n field=lowcase(string=parse_string_with_regex(regex=\"^__MSG_(.+)__$\", string=Message).g1),\n default=Message).message || Message\n\n -- Read the manifest files\n LET ManifestData = SELECT OSPath, parse_json(data=read_file(filename=OSPath)) AS Manifest\n FROM Rows\n\n -- Find the Locale file to help with.\n LET LocaleData = SELECT *, if(condition=Manifest.default_locale, else=dict(),\n then=parse_json(data=read_file(\n filename=OSPath.Dirname + \"_locales\" + Manifest.default_locale + \"messages.json\"))) AS Locale\n FROM ManifestData\n\n LET GetIcon(Manifest) = Manifest.icons.`128` || Manifest.icons.`64` || Manifest.icons.`32` || Manifest.icons.`16`\n\n VQL: |\n SELECT OSPath, Manifest.author.email AS Email,\n ResolveName(Message = Manifest.name, Locale=Locale) AS name,\n ResolveName(Message = Manifest.description, Locale=Locale) AS description,\n Manifest.oauth2.scopes as Scopes,\n Manifest.permissions as Permissions,\n Manifest.key as Key, if(condition=GetIcon(Manifest=Manifest),\n then=upload(file=OSPath.Dirname + GetIcon(Manifest=Manifest))) AS Image,\n Manifest AS _Manifest\n FROM LocaleData\n WHERE (name, description) =~ FilterRegex\n" + }, + { + "Name": "Chromium Browser Favicons", + "Author": "Andrew Rathbun, Phill Moore", + "Description": "Extracts known favicons for visited websites.\n\nAlso uploads and previews the image thumbnails.\n", + "Categories": [ + "Chrome", + "Browser" + ], + "Sources": [ + { + "Name": "" + } + ], + "RawData": "Name: Chromium Browser Favicons\nDescription: |\n Extracts known favicons for visited websites.\n\n Also uploads and previews the image thumbnails.\n\nAuthor: Andrew Rathbun, Phill Moore\nEmail: andrew.d.rathbun@gmail.com, @phillmoore\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='icon_mapping' OR name='favicons' OR name='favicon_bitmaps');\nSQLiteIdentifyValue: 3\nCategories:\n - Chrome\n - Browser\n\nFilenameRegex: \"Favicons\"\nGlobs:\n - \"{{LinuxChromeProfiles}}/*/Favicons\"\n - \"{{WindowsChromeProfiles}}/*/Favicons\"\n - \"{{MacOSChromeProfiles}}/*/Favicons\"\n\nSources:\n- VQL: |\n SELECT ID, IconID,\n timestamp(winfiletime= (LastUpdated * 10) || 0) AS LastUpdated,\n PageURL, FaviconURL,\n upload(accessor=\"data\",\n file=_image,\n name=format(format=\"Image%v.png\", args=ID)) AS Image,\n OSPath as _OSPath\n FROM Rows\n WHERE LastUpdated \u003e DateAfter AND LastUpdated \u003c DateBefore\n\n SQL: |\n SELECT\n favicons.id AS ID,\n favicon_bitmaps.icon_id AS IconID,\n favicon_bitmaps.image_data as _image,\n favicon_bitmaps.last_updated AS LastUpdated,\n icon_mapping.page_url AS PageURL,\n favicons.url AS FaviconURL\n FROM favicons\n INNER JOIN icon_mapping\n INNER JOIN favicon_bitmaps\n ON icon_mapping.icon_id = favicon_bitmaps.icon_id\n AND favicons.id = favicon_bitmaps.icon_id\n ORDER BY favicons.id ASC\n" + }, + { + "Name": "Chromium Browser History", + "Author": "Andrew Rathbun", + "Description": "Extracts the Chromium Browser History\n", + "Categories": [ + "Chrome", + "Browser" + ], + "Sources": [ + { + "Name": "Visits" + }, + { + "Name": "Downloads" + }, + { + "Name": "Keywords" + } + ], + "RawData": "Name: Chromium Browser History\nDescription: |\n Extracts the Chromium Browser History\n\nAuthor: Andrew Rathbun\nEmail: andrew.d.rathbun@gmail.com\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='urls' OR name='visits' OR name='downloads' OR name='segments');\nSQLiteIdentifyValue: 4\nCategories:\n - Chrome\n - Browser\nFilenameRegex: \"History\"\nGlobs:\n - \"{{LinuxChromeProfiles}}/*/History\"\n - \"{{WindowsChromeProfiles}}/*/History\"\n - \"{{MacOSChromeProfiles}}/*/History\"\n\nSources:\n- name: Visits\n VQL: |\n SELECT ID,\n timestamp(winfiletime=(visit_time * 10) || 0) AS VisitTime,\n timestamp(winfiletime=(last_visit_time * 10) || 0) AS LastVisitedTime,\n URLTitle, URL, VisitCount, TypedCount,\n if(condition=hidden =~ '1', then=\"Yes\", else=\"No\") AS Hidden,\n VisitID, FromVisitID,\n visit_duration / 1000000 AS VisitDurationInSeconds,\n OSPath\n FROM Rows\n WHERE VisitTime \u003e DateAfter\n AND VisitTime \u003c DateBefore\n AND (URLTitle, URL) =~ FilterRegex\n SQL: |\n SELECT\n urls.id AS ID,\n visits.visit_time as visit_time,\n urls.last_visit_time as last_visit_time,\n urls.title AS URLTitle,\n urls.url AS URL,\n urls.visit_count AS VisitCount,\n urls.typed_count AS TypedCount,\n urls.hidden as hidden,\n visits.id AS VisitID,\n visits.from_visit AS FromVisitID,\n visits.visit_duration as visit_duration\n FROM urls\n LEFT JOIN visits ON urls.id = visits.url\n ORDER BY visits.visit_time ASC\n\n- name: Downloads\n Preamble: |\n LET StateLookup \u003c= dict(`0`='In Progress', `1`='Complete', `2`=\"Cancelled\", `3`=\"Interrupted\", `4`=\"Interrupted\")\n LET DangerType \u003c= dict(`0`='Not Dangerous', `1`=\"Dangerous\", `2`='Dangerous URL', `3`='Dangerous Content',\n `4`='Content May Be Malicious', `5`='Uncommon Content', `6`='Dangerous But User Validated',\n `7`='Dangerous Host', `8`='Potentially Unwanted', `9`='Whitelisted by Policy')\n LET InterruptReason \u003c= dict(`0`= 'No Interrupt', `1`= 'File Error', `2`='Access Denied', `3`='Disk Full',\n `5`='Path Too Long',`6`='File Too Large', `7`='Virus', `10`='Temporary Problem', `11`='Blocked',\n `12`='Security Check Failed', `13`='Resume Error', `20`='Network Error', `21`='Operation Timed Out',\n `22`='Connection Lost', `23`='Server Down', `30`='Server Error', `31`='Range Request Error',\n `32`='Server Precondition Error', `33`='Unable to get file', `34`='Server Unauthorized',\n `35`='Server Certificate Problem', `36`='Server Access Forbidden', `37`='Server Unreachable',\n `38`='Content Length Mismatch', `39`='Cross Origin Redirect', `40`='Cancelled', `41`='Browser Shutdown',\n `50`='Browser Crashed')\n\n VQL: |\n SELECT ID, GUID, CurrentPath, TargetPath, OriginalMIMEType, ReceivedBytes, TotalBytes,\n timestamp(winfiletime=(start_time * 10) || 0) AS StartTime,\n timestamp(winfiletime=(end_time * 10) || 0) AS EndTime,\n timestamp(winfiletime=(opened * 10) || 0) AS Opened,\n timestamp(winfiletime=(last_access_time * 10) || 0) AS LastAccessTime,\n timestamp(epoch=last_modified) AS LastModified,\n get(item=StateLookup, field=str(str=state), default=\"Unknown\") AS State,\n get(item=DangerType, field=str(str=danger_type), default=\"Unknown\") AS DangerType,\n get(item=InterruptReason, field=str(str=interrupt_reason), default=\"Unknown\") AS InterruptReason,\n ReferrerURL, SiteURL, TabURL, TabReferrerURL, DownloadURL, OSPath\n FROM Rows\n WHERE LastAccessTime \u003e DateAfter AND LastAccessTime \u003c DateBefore\n AND (SiteURL, DownloadURL, TabURL, TabReferrerURL, ReferrerURL, DownloadURL) =~ FilterRegex\n\n SQL: |\n SELECT\n downloads.id AS ID,\n downloads.guid AS GUID,\n downloads.current_path AS CurrentPath,\n downloads.target_path AS TargetPath,\n downloads.original_mime_type AS OriginalMIMEType,\n downloads.received_bytes AS ReceivedBytes,\n downloads.total_bytes AS TotalBytes,\n downloads.start_time,\n downloads.end_time,\n downloads.opened,\n downloads.last_access_time,\n downloads.last_modified,\n downloads.state,\n downloads.danger_type,\n downloads.interrupt_reason,\n downloads.referrer AS ReferrerURL,\n downloads.site_url AS SiteURL,\n downloads.tab_url AS TabURL,\n downloads.tab_referrer_url AS TabReferrerURL,\n DownloadURL.url AS DownloadURL\n FROM downloads\n INNER JOIN downloads_url_chains AS DownloadURL ON downloads.id = DownloadURL.id\n ORDER BY downloads.id ASC\n\n- name: Keywords\n VQL: |\n SELECT KeywordID, URLID,\n timestamp(winfiletime=(last_visit_time * 10) || 0) AS LastVisitedTime,\n KeywordSearchTerm, Title, URL, OSPath\n FROM Rows\n WHERE LastVisitedTime \u003e DateAfter AND LastVisitedTime \u003c DateBefore\n AND (Title, KeywordSearchTerm, URL) =~ FilterRegex\n\n SQL: |\n SELECT\n keyword_search_terms.keyword_id AS KeywordID,\n keyword_search_terms.url_id AS URLID,\n urls.last_visit_time,\n keyword_search_terms.term AS KeywordSearchTerm,\n urls.title AS Title,\n urls.url AS URL\n FROM keyword_search_terms\n INNER JOIN urls ON keyword_search_terms.url_id = urls.id\n ORDER BY keyword_search_terms.keyword_id ASC\n" + }, + { + "Name": "Chromium Browser Media", + "Author": "Andrew Rathbun", + "Description": "Parses metadata about viewed media, such as videos.\n", + "Categories": [ + "Chrome", + "Browser" + ], + "Sources": [ + { + "Name": "History" + }, + { + "Name": "Playback Session" + } + ], + "RawData": "Name: Chromium Browser Media\nDescription: |\n Parses metadata about viewed media, such as videos.\n\nAuthor: Andrew Rathbun\nEmail: andrew.d.rathbun@gmail.com\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='origin' OR name='playback' OR name='playbackSession');\nSQLiteIdentifyValue: 3\nCategories:\n - Chrome\n - Browser\nFilenameRegex: \"Media History\"\nGlobs:\n - \"{{LinuxChromeProfiles}}/*/Media History\"\n - \"{{WindowsChromeProfiles}}/*/Media History\"\n - \"{{MacOSChromeProfiles}}/*/Media History\"\n\nSources:\n- name: History\n VQL: |\n SELECT ID, URL, WatchTimeSeconds,\n Bool(Value=has_video) AS HasVideo,\n Bool(Value=has_audio) AS HasAudio,\n timestamp(winfiletime=last_updated_time_s || 0) AS LastUpdated,\n OriginID, OSPath\n FROM Rows\n WHERE LastUpdated \u003e DateAfter AND LastUpdated \u003c DateBefore\n AND URL =~ FilterRegex\n\n SQL: |\n SELECT\n playback.id AS ID,\n playback.url AS URL,\n playback.watch_time_s AS WatchTimeSeconds,\n playback.has_video,\n playback.has_audio,\n playback.last_updated_time_s,\n playback.origin_id AS OriginID\n FROM playback\n ORDER BY playback.id ASC\n\n- name: Playback Session\n VQL: |\n SELECT ID,\n timestamp(winfiletime=last_updated_time_s || 0) AS LastUpdated, URL,\n duration_ms / 1000 AS DurationInSeconds,\n position_ms / 1000 AS PositionInSeconds,\n Title, Artist, Album, SourceTitle, OriginID, OSPath\n FROM Rows\n WHERE LastUpdated \u003e DateAfter AND LastUpdated \u003c DateBefore\n AND URL =~ FilterRegex\n\n SQL: |\n SELECT\n playbackSession.id AS ID,\n playbackSession.last_updated_time_s,\n playbackSession.url AS URL,\n playbackSession.duration_ms,\n playbackSession.position_ms,\n playbackSession.title AS Title,\n playbackSession.artist AS Artist,\n playbackSession.album AS Album,\n playbackSession.source_title AS SourceTitle,\n playbackSession.origin_id AS OriginID\n FROM playbackSession\n ORDER BY playbackSession.id\n" + }, + { + "Name": "Chromium Browser Network", + "Author": "Andrew Rathbun", + "Description": "Parses the `Network Action Predictor` database\n", + "Categories": [ + "Chrome", + "Browser" + ], + "Sources": [ + { + "Name": "Predictor" + } + ], + "RawData": "Name: Chromium Browser Network\nDescription: |\n Parses the `Network Action Predictor` database\n\nAuthor: Andrew Rathbun\nEmail: andrew.d.rathbun@gmail.com\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='resource_prefetch_predictor_host_redirect'\n OR name='network_action_predictor' OR name='resource_prefetch_predictor_metadata');\nSQLiteIdentifyValue: 3\nCategories:\n - Chrome\n - Browser\nFilenameRegex: \"Network Action Predictor\"\nGlobs:\n - \"{{LinuxChromeProfiles}}/*/Network Action Predictor\"\n - \"{{WindowsChromeProfiles}}/*/Network Action Predictor\"\n - \"{{MacOSChromeProfiles}}/*/Network Action Predictor\"\n\nSources:\n- name: Predictor\n VQL: |\n SELECT * FROM Rows\n WHERE UserText =~ FilterRegex\n\n SQL: |\n SELECT\n network_action_predictor.id AS ID,\n network_action_predictor.user_text AS UserText,\n network_action_predictor.url AS URL,\n network_action_predictor.number_of_hits AS NumberOfHits,\n network_action_predictor.number_of_misses AS NumberOfMisses\n FROM network_action_predictor, resource_prefetch_predictor_host_redirect\n ORDER BY network_action_predictor.id ASC\n" + }, + { + "Name": "Chromium Browser Notifications", + "Author": "Maxime Thiebaut (@0xThiebaut)", + "Categories": [ + "Chrome", + "Edge", + "Browser" + ], + "Sources": [ + { + "Name": "Site Engagements" + }, + { + "Name": "App Banners" + }, + { + "Name": "Notification Preferences" + }, + { + "Name": "Notification Interactions" + } + ], + "RawData": "Name: Chromium Browser Notifications\nAuthor: Maxime Thiebaut (@0xThiebaut)\nCategories:\n - Chrome\n - Edge\n - Browser\n\nFilenameRegex: \"Preferences\"\nGlobs:\n - \"{{LinuxChromeProfiles}}/*/Preferences\"\n - \"{{WindowsChromeProfiles}}/*/Preferences\"\n - \"{{MacOSChromeProfiles}}/*/Preferences\"\n\nSources:\n- name: Site Engagements\n Preamble: |\n LET JSON = SELECT parse_json(data=read_file(filename=OSPath)) AS Data, OSPath FROM Rows\n\n VQL: |\n SELECT * FROM foreach(row={\n SELECT OSPath, Data.profile.content_settings.exceptions AS exceptions FROM JSON\n }, query={\n SELECT _key AS Site,\n timestamp(winfiletime=int(int=_value.last_modified) * 10 || 0) AS LastModified,\n timestamp(winfiletime=int(int=_value.setting.lastEngagementTime) * 10 || 0) AS LastEngagementTime,\n OSPath\n FROM items(item=exceptions.site_engagement)\n })\n\n- name: App Banners\n Preamble: |\n LET JSON = SELECT parse_json(data=read_file(filename=OSPath)) AS Data, OSPath FROM Rows\n\n VQL: |\n SELECT * FROM foreach(row={\n SELECT OSPath, Data.profile.content_settings.exceptions AS exceptions FROM JSON\n }, query={\n SELECT _key AS Site,\n timestamp(winfiletime=int(int=_value.last_modified) * 10 || 0) AS LastModified,\n {\n SELECT _key AS Site,\n timestamp(winfiletime=int(int=_value.couldShowBannerEvents) * 10 || 0) AS CouldShowBannerEvents,\n timestamp(winfiletime=int(int=_value.next_install_text_animation.last_shown) * 10 || 0) AS LastShown\n FROM items(item=_value.setting)\n } AS Setting,\n OSPath\n FROM items(item=exceptions.app_banner)\n })\n\n- name: Notification Preferences\n Preamble: |\n LET ContentSettings \u003c= array(`0`=\"Default\",`1`=\"Allow\",`2`=\"Block\",`3`=\"Ask\",`4`=\"Session Only\",`5`=\"Detect Important Content\")\n\n LET JSON = SELECT parse_json(data=read_file(filename=OSPath)) AS Data, OSPath FROM Rows\n\n VQL: |\n SELECT * FROM foreach(row={\n SELECT OSPath, Data.profile.content_settings.exceptions AS exceptions FROM JSON\n }, query={\n SELECT _key AS Site,\n timestamp(winfiletime=int(int=_value.last_modified) * 10 || 0) AS LastModified,\n ContentSettings[_value.setting] AS Setting,\n OSPath\n FROM items(item=exceptions.notifications)\n })\n\n- name: Notification Interactions\n Preamble: |\n LET JSON = SELECT parse_json(data=read_file(filename=OSPath)) AS Data, OSPath FROM Rows\n LET S = scope()\n\n VQL: |\n SELECT * FROM foreach(row={\n SELECT OSPath, Data.profile.content_settings.exceptions AS exceptions FROM JSON\n }, query={\n SELECT _key AS URL,\n timestamp(winfiletime=int(int=_value.last_modified) * 10 || 0) AS LastModified,\n _value.display_count as DisplayCount,\n _value.click_count as ClickCount,\n OSPath\n FROM items(item=S.notification_interactions || dict())\n })\n" + }, + { + "Name": "Chromium Browser Shortcuts", + "Author": "Andrew Rathbun", + "Categories": [ + "Chrome", + "Browser" + ], + "Sources": [ + { + "Name": "" + } + ], + "RawData": "Name: Chromium Browser Shortcuts\nAuthor: Andrew Rathbun\nEmail: andrew.d.rathbun@gmail.com\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='meta' OR name='omni_box_shortcuts');\nSQLiteIdentifyValue: 2\nCategories:\n - Chrome\n - Browser\n\nFilenameRegex: \"Shortcuts\"\nGlobs:\n - \"{{LinuxChromeProfiles}}/*/Shortcuts\"\n - \"{{WindowsChromeProfiles}}/*/Shortcuts\"\n - \"{{MacOSChromeProfiles}}/*/Shortcuts\"\n\nSources:\n- VQL: |\n SELECT ID,\n timestamp(winfiletime= (last_access_time * 10) || 0) AS LastAccessTime,\n TextTyped, FillIntoEdit, URL, Contents,\n Description, Type, Keyword, TimesSelectedByUser, OSPath\n FROM Rows\n WHERE LastAccessTime \u003e DateAfter AND LastAccessTime \u003c DateBefore\n AND (Contents, Description) =~ FilterRegex\n\n SQL: |\n SELECT\n omni_box_shortcuts.last_access_time,\n omni_box_shortcuts.text AS TextTyped,\n omni_box_shortcuts.fill_into_edit AS FillIntoEdit,\n omni_box_shortcuts.url AS URL,\n omni_box_shortcuts.contents AS Contents,\n omni_box_shortcuts.description AS Description,\n omni_box_shortcuts.type AS Type,\n omni_box_shortcuts.keyword AS Keyword,\n omni_box_shortcuts.number_of_hits AS TimesSelectedByUser,\n omni_box_shortcuts.id AS ID\n FROM omni_box_shortcuts\n ORDER BY omni_box_shortcuts.last_access_time ASC\n" + }, + { + "Name": "Chromium Sessions", + "Author": "Mike Cohen", + "Categories": [ + "Chrome", + "Browser" + ], + "Sources": [ + { + "Name": "Sessions" + } + ], + "RawData": "Name: Chromium Sessions\nAuthor: Mike Cohen\nReference: https://www.inversecos.com/2022/10/recovering-cleared-browser-history.html\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master WHERE type='table' AND (name='cookies' OR name='meta');\nSQLiteIdentifyValue: 2\nCategories:\n - Chrome\n - Browser\nFilenameRegex: \"Session\"\nGlobs:\n - \"{{LinuxChromeProfiles}}/*/Sessions/Session_*\"\n - \"{{WindowsChromeProfiles}}/*/Sessions/Session_*\"\n - \"{{MacOSChromeProfiles}}/*/Sessions/Session_*\"\n\nSources:\n- name: Sessions\n VQL: |\n SELECT timestamp(winfiletime=(creation_utc * 10) || 0) AS CreationUTC,\n timestamp(winfiletime=(expires_utc * 10) || 0) AS ExpiresUTC,\n timestamp(winfiletime=(last_access_utc * 10) || 0) AS LastAccessUTC,\n HostKey, Name, Path,\n Bool(Value=is_secure) AS IsSecure,\n Bool(Value=is_httponly) AS IsHttpOnly,\n Bool(Value=has_expires) AS HasExpiration,\n Bool(Value=is_persistent) AS IsPersistent,\n Priority, SourcePort, OSPath\n FROM Rows\n WHERE LastAccessUTC \u003e DateAfter AND LastAccessUTC \u003c DateBefore\n AND (Name, Path) =~ FilterRegex\n\n SQL: |\n SELECT\n cookies.creation_utc,\n cookies.expires_utc,\n cookies.last_access_utc,\n cookies.host_key AS HostKey,\n cookies.name AS Name,\n cookies.path AS Path,\n cookies.is_secure,\n cookies.is_httponly,\n cookies.has_expires,\n cookies.is_persistent,\n cookies.priority AS Priority,\n cookies.source_port AS SourcePort\n FROM cookies\n ORDER BY cookies.creation_utc ASC\n" + }, + { + "Name": "Chromium Browser Top Sites", + "Author": "Andrew Rathbun", + "Categories": [ + "Chrome", + "Browser" + ], + "Sources": [ + { + "Name": "" + } + ], + "RawData": "Name: Chromium Browser Top Sites\nAuthor: Andrew Rathbun\nEmail: andrew.d.rathbun@gmail.com\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='meta' OR name='top_sites');\nSQLiteIdentifyValue: 2\nCategories:\n - Chrome\n - Browser\n\nFilenameRegex: \"Top Sites\"\nGlobs:\n - \"{{LinuxChromeProfiles}}/*/Top Sites\"\n - \"{{WindowsChromeProfiles}}/*/Top Sites\"\n - \"{{MacOSChromeProfiles}}/*/Top Sites\"\n\nSources:\n- VQL: |\n SELECT * FROM Rows\n WHERE ( URL =~ FilterRegex OR Title =~ FilterRegex )\n\n SQL: |\n SELECT\n top_sites.url_rank AS URLRank,\n top_sites.url AS URL,\n top_sites.title AS Title\n FROM top_sites\n ORDER BY top_sites.url_rank ASC\n" + }, + { + "Name": "Edge Browser Autofill", + "Author": "Chris Hayes - Reliance Cyber", + "Categories": [ + "Edge", + "Browser" + ], + "Sources": [ + { + "Name": "CombinedAutofill" + } + ], + "RawData": "Name: Edge Browser Autofill\nAuthor: Chris Hayes - Reliance Cyber\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='autofill_edge_field_client_info' OR name='autofill_edge_field_values');\nSQLiteIdentifyValue: 2\nCategories:\n - Edge\n - Browser\n\nFilenameRegex: \"Web Data\"\nGlobs:\n - \"{{LinuxChromeProfiles}}/*/Web Data\"\n - \"{{WindowsChromeProfiles}}/*/Web Data\"\n - \"{{MacOSChromeProfiles}}/*/Web Data\"\n\nSources:\n- name: CombinedAutofill\n VQL: |\n SELECT timestamp(epoch=date_last_used) AS DateLastUsed, *\n FROM Rows\n WHERE DateLastUsed \u003e DateAfter AND DateLastUsed \u003c DateBefore\n\n SQL: |\n SELECT\n autofill_edge_field_client_info.form_signature_v1,\n autofill_edge_field_client_info.form_signature_v2,\n autofill_edge_field_client_info.domain_value,\n autofill_edge_field_values.date_last_used,\n GROUP_CONCAT(autofill_edge_field_client_info.label || ': ' || autofill_edge_field_values.value, ', ') AS label_value_pairs,\n json_group_object(autofill_edge_field_client_info.label, autofill_edge_field_values.value) AS label_value_json\n FROM\n autofill_edge_field_values\n JOIN\n autofill_edge_field_client_info\n ON\n autofill_edge_field_values.field_id = autofill_edge_field_client_info.field_id\n GROUP BY\n autofill_edge_field_client_info.form_signature_v1,\n autofill_edge_field_client_info.form_signature_v2,\n autofill_edge_field_client_info.domain_value,\n autofill_edge_field_values.date_last_used;\n" + }, + { + "Name": "Edge Browser Navigation History", + "Author": "Suyash Tripathi", + "Categories": [ + "Edge", + "Browser" + ], + "Sources": [ + { + "Name": "Navigation History" + } + ], + "RawData": "Name: Edge Browser Navigation History\nAuthor: Suyash Tripathi\nEmail: suyash.tripathi@cybercx.com.au\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND name='navigation_history';\nSQLiteIdentifyValue: 1\nCategories:\n - Edge\n - Browser\nFilenameRegex: \"WebAssistDatabase\"\nGlobs:\n - \"{{WindowsChromeProfiles}}/*/WebAssistDatabase\"\n - \"{{MacOSChromeProfiles}}/*/WebAssistDatabase\"\n\nSources:\n- name: Navigation History\n VQL: |\n SELECT ID,\n timestamp(epoch=`Last Visited Time`) AS `Last Visited Time`,\n Title, URL, VisitCount, OSPath\n FROM Rows\n WHERE `Last Visited Time` \u003e DateAfter\n AND `Last Visited Time` \u003c DateBefore\n AND (Title, URL) =~ FilterRegex\n\n SQL: |\n SELECT\n navigation_history.id AS ID,\n navigation_history.last_visited_time AS 'Last Visited Time',\n navigation_history.title AS Title,\n navigation_history.url AS URL,\n navigation_history.num_visits AS VisitCount\n FROM\n navigation_history\n ORDER BY\n navigation_history.last_visited_time ASC;\n" + }, + { + "Name": "Firefox Places", + "Author": "Andrew Rathbun", + "Categories": [ + "Firefox", + "Browser" + ], + "Sources": [ + { + "Name": "" + }, + { + "Name": "Downloads" + }, + { + "Name": "History" + } + ], + "RawData": "Name: Firefox Places\nAuthor: Andrew Rathbun\nEmail: andrew.d.rathbun@gmail.com\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='moz_historyvisits' OR name='moz_bookmarks'\n OR name='moz_places' OR name='moz_inputhistory');\nSQLiteIdentifyValue: 4\nCategories:\n - Firefox\n - Browser\n\nFilenameRegex: \"places.sqlite\"\nGlobs:\n - \"{{WindowsFirefoxProfiles}}/*/places.sqlite\"\n - \"{{LinuxFirefoxProfiles}}/places.sqlite\"\n - \"{{MacOSFirefoxProfiles}}/places.sqlite\"\n\nSources:\n- Preamble: |\n LET BookmarkTypes \u003c= dict(`1`=\"URL\", `2`=\"Folder\", `3`=\"Separator\")\n\n VQL: |\n SELECT ID, ParentID,\n get(item= BookmarkTypes, field=str(str=type), default=\"Unknown\") AS Type,\n timestamp(epoch=dateAdded) AS DateAdded,\n timestamp(epoch=lastModified) AS LastModified,\n Position, Title, URL, ForeignKey, OSPath\n FROM Rows\n WHERE LastModified \u003e DateAfter AND LastModified \u003c DateBefore\n AND (Title, URL) =~ FilterRegex\n\n SQL: |\n SELECT\n Bookmarks.id AS ID,\n Bookmarks.parent AS ParentID,\n Bookmarks.type,\n Bookmarks.dateAdded,\n Bookmarks.lastModified,\n Bookmarks.position AS Position,\n Bookmarks.title AS Title,\n moz_places.url AS URL,\n Bookmarks.fk AS ForeignKey\n FROM moz_bookmarks AS Bookmarks\n LEFT JOIN moz_places ON Bookmarks.fk = moz_places.id\n ORDER BY Bookmarks.id ASC\n\n- name: Downloads\n VQL: |\n SELECT PlaceID, Content,\n timestamp(epoch=dateAdded) AS DateAdded,\n timestamp(epoch=lastModified) AS LastModified,\n OSPath\n FROM Rows\n WHERE LastModified \u003e DateAfter AND LastModified \u003c DateBefore\n AND Content =~ FilterRegex\n\n SQL: |\n SELECT\n moz_annos.place_id AS PlaceID,\n moz_annos.content AS Content,\n dateAdded,\n lastModified\n FROM moz_annos\n WHERE anno_attribute_id IN (1,2)\n ORDER BY moz_annos.dateAdded ASC\n\n- name: History\n Preamble: |\n LET VisitType \u003c= dict(`1`='TRANSITION_LINK', `2`='TRANSITION_TYPED', `3`='TRANSITION_BOOKMARK',\n `4`='TRANSITION_EMBED', `5`= 'TRANSITION_REDIRECT_PERMANENT', `6`='TRANSITION_REDIRECT_TEMPORARY',\n `7`='TRANSITION_DOWNLOAD', `8`='TRANSITION_FRAMED_LINK', `9`='TRANSITION_RELOAD')\n\n VQL: |\n SELECT VisitID, FromVisitID,\n timestamp(epoch= last_visit_date) AS LastVisitDate,\n VisitCount, URL, Title, Description,\n get(item= VisitType, field=str(str=visit_type), default=\"Unknown\") AS VisitType,\n Bool(Value=hidden) AS Hidden,\n Bool(Value=typed) AS Typed,\n Frecency, PreviewImageURL, OSPath\n FROM Rows\n WHERE LastVisitDate \u003e DateAfter AND LastVisitDate \u003c DateBefore\n AND (Title, URL, Description) =~ FilterRegex\n\n SQL: |\n SELECT\n moz_historyvisits.id AS VisitID,\n moz_historyvisits.from_visit AS FromVisitID,\n moz_places.last_visit_date,\n moz_places.visit_count AS VisitCount,\n moz_places.url AS URL,\n moz_places.title AS Title,\n moz_places.description AS Description,\n moz_historyvisits.visit_type,\n moz_places.hidden,\n moz_places.typed,\n moz_places.frecency AS Frecency,\n moz_places.preview_image_url AS PreviewImageURL\n FROM moz_places\n INNER JOIN moz_historyvisits ON moz_places.origin_id = moz_historyvisits.id\n ORDER BY moz_places.last_visit_date ASC\n" + }, + { + "Name": "Firefox Cookies", + "Author": "Andrew Rathbun", + "Categories": [ + "Firefox", + "Browser" + ], + "Sources": [ + { + "Name": "" + } + ], + "RawData": "Name: Firefox Cookies\nAuthor: Andrew Rathbun\nEmail: andrew.d.rathbun@gmail.com\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='moz_cookies');\nSQLiteIdentifyValue: 1\nCategories:\n - Firefox\n - Browser\n\nFilenameRegex: \"cookies.sqlite\"\nGlobs:\n - \"{{WindowsFirefoxProfiles}}/*/cookies.sqlite\"\n - \"{{LinuxFirefoxProfiles}}/cookies.sqlite\"\n - \"{{MacOSFirefoxProfiles}}/cookies.sqlite\"\n\nSources:\n- VQL: |\n SELECT ID, Host, Name, Value,\n timestamp(epoch= creationTime) AS CreationTime,\n timestamp(epoch= lastAccessed) AS LastAccessedTime,\n timestamp(epoch= expiry) AS Expiration,\n Bool(Value= isSecure) AS IsSecure,\n Bool(Value= isHttpOnly) AS IsHTTPOnly, OSPath\n FROM Rows\n WHERE LastAccessedTime \u003e DateAfter\n AND LastAccessedTime \u003c DateBefore\n AND ( Name =~ FilterRegex OR Value =~ FilterRegex )\n\n SQL: |\n SELECT\n moz_cookies.id AS ID,\n moz_cookies.host AS Host,\n moz_cookies.name AS Name,\n moz_cookies.value AS Value,\n moz_cookies.creationTime,\n moz_cookies.lastAccessed,\n moz_cookies.expiry,\n moz_cookies.isSecure,\n moz_cookies.isHttpOnly\n FROM moz_cookies\n ORDER BY moz_cookies.id ASC\n" + }, + { + "Name": "Firefox Downloads", + "Author": "Andrew Rathbun", + "Categories": [ + "Firefox", + "Browser" + ], + "Sources": [ + { + "Name": "" + } + ], + "RawData": "Name: Firefox Downloads\nAuthor: Andrew Rathbun\nEmail: andrew.d.rathbun@gmail.com\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='moz_downloads');\nSQLiteIdentifyValue: 1\nCategories:\n - Firefox\n - Browser\n\nFilenameRegex: \"downloads.sqlite\"\nGlobs:\n - \"{{WindowsFirefoxProfiles}}/*/downloads.sqlite\"\n - \"{{LinuxFirefoxProfiles}}/downloads.sqlite\"\n - \"{{MacOSFirefoxProfiles}}/downloads.sqlite\"\n\nSources:\n- VQL: |\n SELECT ID, Name, MIMEType, Source, Target,\n timestamp(epoch= startTime) AS StartTime,\n timestamp(epoch= endTime) AS EndTime,\n timestamp(epoch= expiry) AS Expiration,\n CurrentBytes, MaxBytes, OSPath\n FROM Rows\n WHERE StartTime \u003e DateAfter\n AND StartTime \u003c DateBefore\n AND Name =~ FilterRegex\n\n SQL: |\n SELECT\n moz_downloads.id AS ID,\n moz_downloads.name AS Name,\n moz_downloads.mimeType AS MIMEType,\n moz_downloads.source AS Source,\n moz_downloads.target AS Target,\n startTime,\n endTime,\n moz_downloads.currBytes AS CurrentBytes,\n moz_downloads.maxBytes AS MaxBytes\n FROM moz_downloads\n ORDER BY moz_downloads.id ASC\n" + }, + { + "Name": "Firefox Favicons", + "Author": "Andrew Rathbun", + "Categories": [ + "Firefox", + "Browser" + ], + "Sources": [ + { + "Name": "" + } + ], + "RawData": "Name: Firefox Favicons\nAuthor: Andrew Rathbun\nEmail: andrew.d.rathbun@gmail.com\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='moz_icons' OR name='moz_icons_to_pages' OR name='moz_pages_w_icons');\nSQLiteIdentifyValue: 3\nCategories:\n - Firefox\n - Browser\n\nFilenameRegex: \"favicons.sqlite\"\nGlobs:\n - \"{{WindowsFirefoxProfiles}}/*/favicons.sqlite\"\n - \"{{LinuxFirefoxProfiles}}/favicons.sqlite\"\n - \"{{MacOSFirefoxProfiles}}/favicons.sqlite\"\n\nSources:\n- VQL: |\n SELECT ID, PageURL, FaviconURL,\n timestamp(epoch= expire_ms) AS Expiration,\n OSPath\n FROM Rows\n SQL: |\n SELECT\n moz_icons.id AS ID,\n moz_pages_w_icons.page_url AS PageURL,\n moz_icons.icon_url AS FaviconURL,\n moz_icons.expire_ms\n FROM moz_icons\n INNER JOIN moz_icons_to_pages ON moz_icons.id = moz_icons_to_pages.icon_id\n INNER JOIN moz_pages_w_icons ON moz_icons_to_pages.page_id = moz_pages_w_icons.id\n ORDER BY moz_icons.expire_ms ASC\n" + }, + { + "Name": "Firefox Form History", + "Author": "Andrew Rathbun", + "Categories": [ + "Firefox", + "Browser" + ], + "Sources": [ + { + "Name": "" + } + ], + "RawData": "Name: Firefox Form History\nAuthor: Andrew Rathbun\nEmail: andrew.d.rathbun@gmail.com\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='moz_formhistory');\n\nSQLiteIdentifyValue: 1\nCategories:\n - Firefox\n - Browser\n\nFilenameRegex: \"formhistory.sqlite\"\nGlobs:\n - \"{{WindowsFirefoxProfiles}}/*/formhistory.sqlite\"\n - \"{{LinuxFirefoxProfiles}}/formhistory.sqlite\"\n - \"{{MacOSFirefoxProfiles}}/formhistory.sqlite\"\n\nSources:\n- VQL: |\n SELECT ID, FieldName, Value, TimesUsed,\n timestamp(epoch= firstUsed) AS FirstUsed,\n timestamp(epoch= lastUsed) AS LastUsed,\n GUID, OSPath\n FROM Rows\n WHERE LastUsed \u003e DateAfter AND LastUsed \u003c DateBefore\n AND ( FieldName =~ FilterRegex OR Value =~ FilterRegex )\n\n SQL: |\n SELECT\n id AS ID,\n fieldname AS FieldName,\n value AS Value,\n timesUsed AS TimesUsed,\n firstUsed,\n lastUsed,\n guid AS GUID\n FROM moz_formhistory\n ORDER BY id ASC\n" + }, + { + "Name": "IE or Edge WebCacheV01", + "Categories": [ + "Edge", + "InternetExplorer", + "Browser" + ], + "Sources": [ + { + "Name": "All Data" + }, + { + "Name": "Highlights" + } + ], + "RawData": "Name: IE or Edge WebCacheV01\nCategories:\n - Edge\n - InternetExplorer\n - Browser\n\nFilenameRegex: \"WebCacheV01.dat\"\nGlobs:\n - C:/Users/*/AppData/Local/Microsoft/Windows/WebCache/WebCacheV01.dat\n\nSources:\n- name: All Data\n Preamble: |\n LET MatchingFiles = SELECT OSPath FROM Rows\n LET S = scope()\n\n LET Containers(OSPath) = SELECT Table\n FROM parse_ese_catalog(file=OSPath)\n WHERE Table =~ \"Container_\"\n GROUP BY Table\n\n LET AllHits(OSPath) = SELECT * FROM foreach(row={\n SELECT * FROM Containers(OSPath=OSPath)\n }, query={\n SELECT timestamp(winfiletime=ExpiryTime) AS ExpiryTime,\n timestamp(winfiletime=ModifiedTime) AS ModifiedTime,\n timestamp(winfiletime=AccessedTime) AS AccessedTime,\n S.Url AS Url, *\n FROM parse_ese(file=OSPath, table=Table)\n })\n\n VQL: |\n SELECT * FROM foreach(row=MatchingFiles, query={\n SELECT * FROM AllHits(OSPath=OSPath)\n })\n WHERE AccessedTime \u003e DateAfter AND AccessedTime \u003c DateBefore\n AND Url =~ FilterRegex\n\n\n- name: Highlights\n VQL: |\n SELECT * FROM foreach(row=MatchingFiles, query={\n SELECT AccessedTime, ModifiedTime, ExpiryTime, Url\n FROM AllHits(OSPath=OSPath)\n })\n WHERE AccessedTime \u003e DateAfter AND AccessedTime \u003c DateBefore\n AND Url =~ FilterRegex\n" + }, + { + "Name": "MacOS Applications Cache", + "Author": "Wes Lambert - @therealwlambert", + "Description": "Applications can use the NSURL cache to store specific data that is\nuseful to the operation of the application in a `Cache.db` file on\ndisk. The data contained within this file could potentially be\nuseful to investigators or incident responders, such as URLs that\nwere accessed, as well as data requested or returned.\n", + "Categories": [ + "MacOS" + ], + "Sources": [ + { + "Name": "" + } + ], + "RawData": "Name: MacOS Applications Cache\nAuthor: Wes Lambert - @therealwlambert\nDescription: |\n Applications can use the NSURL cache to store specific data that is\n useful to the operation of the application in a `Cache.db` file on\n disk. The data contained within this file could potentially be\n useful to investigators or incident responders, such as URLs that\n were accessed, as well as data requested or returned.\n\nReference: https://developer.apple.com/documentation/foundation/nsurl\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='cfurl_cache_response' OR name='cfurl_cache_blob_data'\n OR name='cfurl_cache_receiver_data');\nSQLiteIdentifyValue: 3\nCategories:\n - MacOS\n\nFilenameRegex: \"Cache.db\"\nGlobs:\n - \"/Users/*/Library/Caches/*/Cache.db\"\n\nSources:\n- VQL: |\n SELECT\n time_stamp AS Timestamp,\n OSPath.Base AS Application,\n entry_ID AS EntryID,\n version AS Version,\n hash_value AS Hash,\n storage_policy AS StoragePolicy,\n request_key AS URL,\n plist(file=request_object, accessor=\"data\") AS Request,\n plist(file=response_object, accessor=\"data\") AS Response,\n partition AS Partition,\n OSPath\n FROM Rows\n WHERE Timestamp \u003e DateAfter AND Timestamp \u003c DateBefore\n AND Application =~ FilterRegex\n\n SQL: |\n SELECT cfurl_cache_response.entry_ID AS entry_ID,\n version, hash_value, storage_policy, request_key,\n time_stamp, partition, request_object, response_object\n FROM cfurl_cache_response\n INNER JOIN cfurl_cache_blob_data ON cfurl_cache_response.entry_ID = cfurl_cache_blob_data.entry_ID\n INNER JOIN cfurl_cache_receiver_data ON cfurl_cache_response.entry_ID = cfurl_cache_receiver_data.entry_ID\n" + }, + { + "Name": "MacOS NetworkUsage", + "Author": "Wes Lambert - @therealwlambert", + "Description": "On macOS, the NetUsage DB can provide various details around\napplication network utilization. With this artifact, we can get an\nidea of what applications are utilizing the network for\ncommunications and to what degree. We can also identify if usage\nhas occurred through a WIFI network or a wired network.\n\nMore information about this database can be found here:\n\nhttp://www.mac4n6.com/blog/2019/1/6/network-and-application-usage-using-netusagesqlite-amp-datausagesqlite-ios-databases\n", + "Categories": [ + "MacOS" + ], + "Sources": [ + { + "Name": "" + } + ], + "RawData": "Name: MacOS NetworkUsage\nAuthor: Wes Lambert - @therealwlambert\nDescription: |\n On macOS, the NetUsage DB can provide various details around\n application network utilization. With this artifact, we can get an\n idea of what applications are utilizing the network for\n communications and to what degree. We can also identify if usage\n has occurred through a WIFI network or a wired network.\n\n More information about this database can be found here:\n\n http://www.mac4n6.com/blog/2019/1/6/network-and-application-usage-using-netusagesqlite-amp-datausagesqlite-ios-databases\n\nReference: http://www.mac4n6.com/blog/2019/1/6/network-and-application-usage-using-netusagesqlite-amp-datausagesqlite-ios-databases\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='ZLIVEUSAGE' OR name='ZPROCESS');\nSQLiteIdentifyValue: 2\nCategories:\n - MacOS\n\nFilenameRegex: \"netusage.sqlite\"\nGlobs:\n - /private/var/networkd/netusage.sqlite\n - /private/var/networkd/db/netusage.sqlite\n\nSources:\n- VQL: |\n SELECT timestamp(epoch= ZTIMESTAMP + 978307200) AS Timestamp,\n timestamp(epoch= ZFIRSTTIMESTAMP + 978307200) AS FirstTimestamp,\n timestamp(epoch= LIVE_USAGE_TIMESTAMP + 978307200) AS LiveUsageTimestamp,\n ZBUNDLENAME AS BundleID,\n ZPROCNAME AS ProcessName,\n ZWIFIIN AS WifiIn,\n ZWIFIOUT AS WifiOut,\n ZWWANIN AS WanIn,\n ZWWANOUT AS WandOut,\n ZWIREDIN AS WiredIn,\n ZWIREDOUT AS WiredOut,\n ZXIN AS _XIn,\n ZXOUT AS _XOut,\n Z_PK AS LiveUsageTableID\n FROM Rows\n\n SQL: |\n SELECT\n ZPROCESS.ZTIMESTAMP,\n ZPROCESS.ZFIRSTTIMESTAMP,\n ZLIVEUSAGE.ZTIMESTAMP AS LIVE_USAGE_TIMESTAMP\",\n ZBUNDLENAME,\n ZPROCNAME,\n ZWIFIIN,\n ZWIFIOUT,\n ZWWANIN,\n ZWWANOUT,\n ZWIREDIN,\n ZWIREDOUT,\n ZXIN,\n ZXOUT,\n ZLIVEUSAGE.Z_PK,\n FROM ZLIVEUSAGE\n LEFT JOIN ZPROCESS ON ZPROCESS.Z_PK = ZLIVEUSAGE.ZHASPROCESS\n" + }, + { + "Name": "MacOS Notes", + "Author": "Wes Lambert - @therealwlambert", + "Description": "This artifact provides details about notes taken using the default\nNotes application on macOS. These notes can be useful during an\ninvestigation, especially if tied to interesting files.\n\nDeleted notes and attachments can also be recovered in some\ninstances.\n\nThe SQL query within this artifact was primarily derived from\nYogesh Khatri's referenced blog post.\n\nNOTE: This artifact may not cover all attachments at this time, and\nthere are many more great pieces of data to discover! More\ninformation can be found in the `ZICCLOUDSYNCINGOBJECT` table.\n", + "Categories": [ + "MacOS" + ], + "Sources": [ + { + "Name": "" + } + ], + "RawData": "Name: MacOS Notes\nAuthor: Wes Lambert - @therealwlambert\nDescription: |\n This artifact provides details about notes taken using the default\n Notes application on macOS. These notes can be useful during an\n investigation, especially if tied to interesting files.\n\n Deleted notes and attachments can also be recovered in some\n instances.\n\n The SQL query within this artifact was primarily derived from\n Yogesh Khatri's referenced blog post.\n\n NOTE: This artifact may not cover all attachments at this time, and\n there are many more great pieces of data to discover! More\n information can be found in the `ZICCLOUDSYNCINGOBJECT` table.\n\nReference: http://www.swiftforensics.com/2018/02/reading-notes-database-on-macos.html\n\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='ZICNOTEDATA' OR name='ZICCLOUDSYNCINGOBJECT');\nSQLiteIdentifyValue: 2\nCategories:\n - MacOS\n\nFilenameRegex: \"NoteStore.sqlite|NotesV.+storedata\"\nGlobs:\n - /Users/*/Library/Containers/com.apple.Notes/Data/Library/Notes/NotesV*.storedata\n - /Users/*/Library/Group Containers/group.com.apple.notes/NoteStore.sqlite\n\nSources:\n- VQL: |\n SELECT Key AS _Key,\n OSPath[1] AS User,\n Note,\n Title,\n Snippet,\n NoteID AS _NoteID,\n timestamp(cocoatime=CreatedTS) AS CreatedTime,\n timestamp(cocoatime=LastOpenedDate) AS LastOpenedTime,\n timestamp(cocoatime=DirModificationDate) AS LastDirModifcation,\n Account AS _Account,\n Directory,\n DirectoryID,\n AttachmentName,\n AttachmentSize,\n AttachmentUUID,\n if(condition=AttachmentUUID,\n then=OSPath[:2] + '/Library/Group Containers/group.com.apple.notes/Accounts/LocalAccount/Media/' + AttachmentUUID + '/' + AttachmentName) AS AttachmentLocation,\n AccountName AS _AccountName,\n AccountID AS _AccountID,\n AccountType AS _AccountType,\n gunzip(string=Data) AS Data,\n OSPath\n FROM Rows\n WHERE LastOpenedTime \u003e DateAfter AND LastOpenedTime \u003c DateBefore\n AND ( Title =~ FilterRegex OR Data =~ FilterRegex )\n\n SQL: |\n SELECT n.Z_PK AS Key,\n n.ZNOTE as Note,\n c1.ZTITLE1 as Title,\n c1.ZSNIPPET as Snippet,\n c1.ZIDENTIFIER as NoteID,\n c1.ZCREATIONDATE3 as CreatedTS,\n c1.ZFOLDERMODIFICATIONDATE AS DirModificationDate,\n c1.ZLASTOPENEDDATE AS LastOpenedDate,\n c2.ZACCOUNT3 as Account,\n c2.ZTITLE2 as Directory,\n c2.ZIDENTIFIER as DirectoryID,\n c4.ZFILENAME as AttachmentName,\n c3.ZFILESIZE as AttachmentSize,\n c4.ZIDENTIFIER as AttachmentUUID,\n c5.ZNAME as AccountName,\n c5.ZIDENTIFIER as AccountID,\n c5.ZACCOUNTTYPE as AccountType,\n n.ZDATA as Data\n FROM ZICNOTEDATA as n\n LEFT JOIN ZICCLOUDSYNCINGOBJECT as c1 ON c1.ZNOTEDATA = n.Z_PK\n LEFT JOIN ZICCLOUDSYNCINGOBJECT as c2 ON c2.Z_PK = c1.ZFOLDER\n LEFT JOIN ZICCLOUDSYNCINGOBJECT as c3 ON c3.ZNOTE= n.ZNOTE\n LEFT JOIN ZICCLOUDSYNCINGOBJECT as c4 ON c4.ZATTACHMENT1= c3.Z_PK\n LEFT JOIN ZICCLOUDSYNCINGOBJECT as c5 ON c5.Z_PK = c1.ZACCOUNT2\n ORDER BY Key\n" + }, + { + "Name": "MacOS XProtect Detections", + "Author": "Matt Green - @mgreen27", + "Description": "This artifact provides details about XProtect detections on macOS.\n\nmacOS includes built-in antivirus technology called XProtect for \nthe signature-based detection and removal of malware. The system \nuses YARA and behavorial signatures.\n", + "Categories": [ + "MacOS" + ], + "Sources": [ + { + "Name": "" + } + ], + "RawData": "Name: MacOS XProtect Detections\nAuthor: Matt Green - @mgreen27\nDescription: |\n This artifact provides details about XProtect detections on macOS.\n\n macOS includes built-in antivirus technology called XProtect for \n the signature-based detection and removal of malware. The system \n uses YARA and behavorial signatures.\n\nReference: https://www.huntress.com/blog/dmxprotect-stop-drop-shut-malware-down-before-it-opens-up-shop\n\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND name='events';\nSQLiteIdentifyValue: 1\n\nCategories:\n - MacOS\n\nFilenameRegex: \"XPdb\"\nGlobs:\n - \"/private/var/protected/xprotect/XPdb\"\n\nSources:\n- VQL: |\n SELECT *\n FROM Rows\n WHERE dt \u003e DateAfter\n AND dt \u003c DateBefore\n AND (violated_rule, exec_path, responsible_path, responsible_signing_id,\n exec_cdhash, exec_sha256, responsible_cdhash, responsible_sha256 ) =~ FilterRegex\n\n SQL: |\n SELECT * FROM events\n" + }, + { + "Name": "Windows Activities Cache", + "Author": "Eric Zimmerman", + "Categories": [ + "Windows" + ], + "Sources": [ + { + "Name": "ActivityPackageId" + }, + { + "Name": "Clipboard" + } + ], + "RawData": "Name: Windows Activities Cache\nAuthor: Eric Zimmerman\nEmail: saericzimmerman@gmail.com\nReference: https://github.com/EricZimmerman/SQLECmd\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='Activity' OR name='Activity_PackageId' OR name='ActivityOperation');\nSQLiteIdentifyValue: 3\nCategories:\n - Windows\n\nFilenameRegex: \"ActivitiesCache.db\"\nGlobs:\n - \"C:/Users/*/AppData/Local/ConnectedDevicesPlatform/L.*/ActivitiesCache.db\"\n\nSources:\n- name: ActivityPackageId\n VQL: |\n SELECT format(format=\"%0X-%0X-%0X-%0X-%0X\", args=[\n ActivityId[0:4], ActivityId[4:6], ActivityId[6:8],\n ActivityId[8:10], ActivityId[10:] ]) AS ActivityId,\n Platform, PackageName, ExpirationTime, OSPath\n FROM Rows\n\n SQL: |\n Select ActivityId, Platform, PackageName, ExpirationTime\n FROM Activity_PackageId\n\n- name: Clipboard\n SQL: |\n SELECT * FROM ActivityOperation\n VQL: |\n SELECT\n CreatedTime,\n timestamp(epoch=LastModifiedTime) AS LastModifiedTime,\n timestamp(epoch=LastModifiedOnClient) AS LastModifiedOnClient,\n StartTime,\n EndTime,\n Payload,\n OSPath[1] AS User,\n base64decode(string=parse_json_array(data=ClipboardPayload)[0].content) AS ClipboardPayload,\n OSPath AS Path,\n Mtime\n FROM Rows\n WHERE StartTime \u003e DateAfter\n AND StartTime \u003c DateBefore\n AND ClipboardPayload =~ FilterRegex\n" + }, + { + "Name": "Windows WPNDatabase - Notifications", + "Author": "Andrew Rathbun", + "Description": "Parse the `wpndatabase.db` file\n", + "Categories": [ + "Windows" + ], + "Sources": [ + { + "Name": "Notifications" + } + ], + "RawData": "Name: Windows WPNDatabase - Notifications\nDescription: |\n Parse the `wpndatabase.db` file\n\nAuthor: Andrew Rathbun\nEmail: andrew.d.rathbun@gmail.com\nReference: https://github.com/EricZimmerman/SQLECmd\n\nSQLiteIdentifyQuery: |\n SELECT count(*) AS `Check`\n FROM sqlite_master\n WHERE type='table'\n AND (name='Notification' OR\n name='HandlerAssets' OR\n name='WNSPushChannel' OR\n name='TransientTable' OR\n name='NotificationData');\n\nSQLiteIdentifyValue: 5\n\nCategories:\n - Windows\n\nFilenameRegex: \"wpndatabase.db\"\nGlobs:\n - C:\\Users\\*\\AppData\\Local\\Microsoft\\Windows\\Notifications\\wpndatabase.db\n\nSources:\n- name: Notifications\n VQL: |\n SELECT *, Parent || \"\" AS Parent,\n timestamp(winfiletime= ArrivalTime) AS ArrivalTime,\n if(condition= ExpirationTime \u003e 0,\n then=timestamp(winfiletime= ExpirationTime),\n else='Expired') AS ExpirationTime,\n format(format=\"%02x\", args=ActivityId) As ActivityId,\n WNSId || \"\" AS WNSId,\n\n if(condition= WNSCreatedTime \u003e 0,\n then=timestamp(winfiletime= WNSCreatedTime),\n else='') AS WNSCreatedTime,\n\n if(condition= WNSExpirationTime \u003e 0,\n then=timestamp(winfiletime= WNSExpirationTime),\n else='') AS WNSExpirationTime,\n\n upload(accessor=\"data\",\n file=Payload,\n name=format(format=\"Payload%v.png\", args=ID)) AS Payload\n\n FROM Rows\n\n SQL: |\n SELECT\n Notification.Id AS ID,\n Notification.'Order' AS 'Order',\n Notification.HandlerId AS HandlerId,\n NotificationHandler.PrimaryId AS Application,\n NotificationHandler.ParentId AS Parent,\n NotificationHandler.HandlerType AS HandlerType,\n Notification.Type AS Type,\n Notification.Payload AS Payload,\n Notification.PayloadType AS PayloadType,\n Notification.Tag AS Tag,\n Notification.\"Group\" AS \"Group\",\n Notification.ArrivalTime AS ArrivalTime,\n Notification.ExpiryTime AS ExpirationTime,\n NotificationHandler.CreatedTime AS HandlerCreated,\n NotificationHandler.ModifiedTime AS HandlerModified,\n NotificationHandler.WNSId AS WNSId,\n NotificationHandler.WNFEventName AS WNFEventName,\n WNSPushChannel.ChannelId AS ChannelID,\n WNSPushChannel.Uri AS URI,\n WNSPushChannel.CreatedTime AS WNSCreatedTime,\n WNSPushChannel.ExpiryTime AS WNSExpirationTime,\n Notification.ActivityId AS ActivityId\n FROM Notification\n JOIN NotificationHandler ON NotificationHandler.RecordId = Notification.HandlerId\n LEFT JOIN WNSPushChannel ON WNSPushChannel.HandlerId = NotificationHandler.RecordId\n ORDER BY Id DESC\n" + }, + { + "Name": "Windows Search Service", + "Description": "Analysis of the Windows search index database. See\nhttps://www.aon.com/cyber-solutions/aon_cyber_labs/windows-search-index-the-forensic-artifact-youve-been-searching-for/\n", + "Categories": [ + "Windows" + ], + "Sources": [ + { + "Name": "SystemIndex_Gthr" + }, + { + "Name": "SystemIndex_GthrPth" + }, + { + "Name": "SystemIndex_PropertyStore" + }, + { + "Name": "SystemIndex_PropertyStore_Highlights" + }, + { + "Name": "BrowsingActivity" + }, + { + "Name": "UserActivityLogging" + } + ], + "RawData": "Name: Windows Search Service\n\nDescription: |\n Analysis of the Windows search index database. See\n https://www.aon.com/cyber-solutions/aon_cyber_labs/windows-search-index-the-forensic-artifact-youve-been-searching-for/\n\nCategories:\n - Windows\n\nFilenameRegex: \"Windows.edb\"\nGlobs:\n - C:\\ProgramData\\Microsoft\\Search\\Data\\Applications\\Windows\\Windows.edb\n\nSources:\n- name: SystemIndex_Gthr\n Preamble: |\n LET MatchingFiles = SELECT OSPath FROM Rows\n\n LET FormatTimeB(T) = timestamp(winfiletime=parse_binary(\n filename=T, accessor=\"data\", struct=\"uint64b\"))\n\n LET FormatTime(T) = timestamp(winfiletime=parse_binary(\n filename=T, accessor=\"data\", struct=\"uint64\"))\n\n LET FormatSize(T) = parse_binary(\n filename=T, accessor=\"data\", struct=\"uint64\")\n\n VQL: |\n SELECT * FROM foreach(row=MatchingFiles, query={\n SELECT ScopeID, DocumentID, SDID,\n FormatTimeB(T=LastModified) AS LastModified,\n FileName\n FROM parse_ese(file=OSPath, table= \"SystemIndex_Gthr\")\n })\n WHERE LastModified \u003e DateAfter AND LastModified \u003c DateBefore\n AND FileName =~ FilterRegex\n\n- name: SystemIndex_GthrPth\n VQL: |\n SELECT * FROM foreach(row=MatchingFiles, query={\n SELECT Scope, Parent, Name\n FROM parse_ese(file=OSPath, table= \"SystemIndex_GthrPth\")\n })\n WHERE Name =~ FilterRegex\n\n- name: SystemIndex_PropertyStore\n Preamble: |\n LET X = scope()\n\n -- The PropertyStore columns look like\n -- \u003crandom\u003e-ProperName so we strip the\n -- random part off to display it properly.\n LET FilterDict(Dict) = to_dict(item={\n SELECT split(sep_string=\"-\", string=_key)[1] || _key AS _key, _value\n FROM items(item=Dict)\n })\n\n LET PropStore(OSPath) = SELECT *,\n FormatTime(T=X.System_Search_GatherTime) AS System_Search_GatherTime,\n FormatSize(T=X.System_Size) AS System_Size,\n FormatTime(T=X.System_DateModified) AS System_DateModified,\n FormatTime(T=X.System_DateAccessed) AS System_DateAccessed,\n FormatTime(T=X.System_DateCreated) AS System_DateCreated\n FROM foreach(row={\n SELECT *, FilterDict(Dict=_value) AS _value\n FROM items(item={\n SELECT * FROM parse_ese(file=OSPath, table=\"SystemIndex_PropertyStore\")\n })\n }, column=\"_value\")\n\n VQL: |\n SELECT * FROM foreach(row=MatchingFiles, query={\n SELECT *\n FROM PropStore(OSPath=OSPath)\n })\n WHERE System_DateAccessed \u003e DateAfter AND System_DateAccessed \u003c DateBefore\n\n- name: SystemIndex_PropertyStore_Highlights\n VQL: |\n SELECT * FROM foreach(row=MatchingFiles, query={\n SELECT WorkID,\n System_Search_GatherTime,\n System_Size,\n System_DateModified,\n System_DateCreated,\n X.System_FileOwner AS System_FileOwner,\n X.System_ItemPathDisplay AS System_ItemPathDisplay,\n X.System_ItemType AS System_ItemType,\n X.System_FileAttributes AS System_FileAttributes,\n X.System_Search_AutoSummary AS System_Search_AutoSummary\n FROM PropStore(OSPath=OSPath)\n })\n WHERE System_DateAccessed \u003e DateAfter AND System_DateAccessed \u003c DateBefore\n\n- name: BrowsingActivity\n VQL: |\n SELECT * FROM foreach(row=MatchingFiles, query={\n SELECT X.ItemPathDisplay AS ItemPathDisplay,\n X.Activity_ContentUri AS Activity_ContentUri,\n X.Activity_Description AS Activity_Description\n FROM PropStore(OSPath=OSPath)\n WHERE Activity_ContentUri\n })\n\n- name: UserActivityLogging\n VQL: |\n SELECT * FROM foreach(row=MatchingFiles, query={\n SELECT X.System_ItemPathDisplay AS System_ItemPathDisplay,\n FormatTime(T=X.ActivityHistory_StartTime) AS ActivityHistory_StartTime,\n FormatTime(T=X.ActivityHistory_EndTime) AS ActivityHistory_EndTime,\n X.ActivityHistory_AppId AS ActivityHistory_AppId\n FROM PropStore(OSPath=OSPath)\n WHERE ActivityHistory_AppId\n })\n WHERE ActivityHistory_StartTime \u003e DateAfter\n AND ActivityHistory_StartTime \u003c DateBefore\n" + } + ] \ No newline at end of file diff --git a/output/SQLiteHunter.yaml b/output/SQLiteHunter.yaml index 6a96a9a..c3cd3b2 100644 --- a/output/SQLiteHunter.yaml +++ b/output/SQLiteHunter.yaml @@ -21,9 +21,11 @@ description: | column_types: - name: Image type: preview_upload +- name: Payload + type: preview_upload export: | - LET SPEC <= "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" + 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") @@ -69,7 +71,7 @@ export: | then=OSPath =~ get(item=Specs.sources, field=SourceName).filename) -- Build a regex for all enabled categories. - LET all_categories = SELECT _value + LET all_categories = SELECT if(condition=_value = "All", then=".", else=_value) AS _value FROM foreach(row=["All","MacOS","Chrome","Browser","Edge","Firefox","InternetExplorer","Windows"]) WHERE get(field=_value) @@ -170,10 +172,10 @@ sources: // 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][:-11] AS Source , - stat(accessor="fs", filename=Data.VFSPath).Size / 8 AS Records + 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 =~ "ResultIndex" AND Records > 0 + WHERE Type =~ "Result" AND Records > 0 LET _ <= SELECT notebook_update_cell(notebook_id=NotebookId, type="vql", input=format(format=''' @@ -206,7 +208,7 @@ sources: /* # iMessage_Profiles */ - SELECT * FROM source(Source="iMessage_Profiles") + SELECT * FROM source(source="iMessage_Profiles") LIMIT 50 query: | LET Rows = SELECT * FROM ApplyFile(SourceName="iMessage_Profiles") @@ -234,7 +236,7 @@ sources: /* # Chromium Browser Autofill_Profiles */ - SELECT * FROM source(Source="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") @@ -267,7 +269,7 @@ sources: /* # Chromium Browser Autofill_Masked Credit Cards */ - SELECT * FROM source(Source="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") @@ -290,7 +292,7 @@ sources: /* # Chromium Browser Bookmarks */ - SELECT * FROM source(Source="Chromium Browser Bookmarks") + SELECT * FROM source(source="Chromium Browser Bookmarks") LIMIT 50 query: | LET Rows = SELECT * FROM FilterFile(SourceName="Chromium Browser Bookmarks") @@ -349,7 +351,7 @@ sources: /* # Chromium Browser Cookies_Cookies */ - SELECT * FROM source(Source="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") @@ -383,7 +385,7 @@ sources: /* # Chromium Browser Extensions */ - SELECT * FROM source(Source="Chromium Browser Extensions") + SELECT * FROM source(source="Chromium Browser Extensions") LIMIT 50 query: | LET Rows = SELECT * FROM FilterFile(SourceName="Chromium Browser Extensions") @@ -432,7 +434,7 @@ sources: /* # Chromium Browser Favicons */ - SELECT * FROM source(Source="Chromium Browser Favicons") + SELECT * FROM source(source="Chromium Browser Favicons") LIMIT 50 query: | LET Rows = SELECT * FROM ApplyFile(SourceName="Chromium Browser Favicons") @@ -465,7 +467,7 @@ sources: /* # Chromium Browser History_Visits */ - SELECT * FROM source(Source="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") @@ -501,7 +503,7 @@ sources: /* # Chromium Browser History_Downloads */ - SELECT * FROM source(Source="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") @@ -530,7 +532,7 @@ sources: get(item=InterruptReason, field=str(str=interrupt_reason), default="Unknown") AS InterruptReason, ReferrerURL, SiteURL, TabURL, TabReferrerURL, DownloadURL, OSPath FROM Rows - WHERE StartTime > DateAfter AND StartTime < DateBefore + WHERE LastAccessTime > DateAfter AND LastAccessTime < DateBefore AND (SiteURL, DownloadURL, TabURL, TabReferrerURL, ReferrerURL, DownloadURL) =~ FilterRegex SELECT * FROM @@ -549,7 +551,7 @@ sources: /* # Chromium Browser History_Keywords */ - SELECT * FROM source(Source="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") @@ -579,7 +581,7 @@ sources: /* # Chromium Browser Media_History */ - SELECT * FROM source(Source="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") @@ -611,7 +613,7 @@ sources: /* # Chromium Browser Media_Playback Session */ - SELECT * FROM source(Source="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") @@ -643,7 +645,7 @@ sources: /* # Chromium Browser Network_Predictor */ - SELECT * FROM source(Source="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") @@ -667,7 +669,7 @@ sources: /* # Chromium Browser Notifications_Site Engagements */ - SELECT * FROM source(Source="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") @@ -698,7 +700,7 @@ sources: /* # Chromium Browser Notifications_App Banners */ - SELECT * FROM source(Source="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") @@ -734,7 +736,7 @@ sources: /* # Chromium Browser Notifications_Notification Preferences */ - SELECT * FROM source(Source="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") @@ -767,7 +769,7 @@ sources: /* # Chromium Browser Notifications_Notification Interactions */ - SELECT * FROM source(Source="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") @@ -802,7 +804,7 @@ sources: /* # Chromium Browser Shortcuts */ - SELECT * FROM source(Source="Chromium Browser Shortcuts") + SELECT * FROM source(source="Chromium Browser Shortcuts") LIMIT 50 query: | LET Rows = SELECT * FROM ApplyFile(SourceName="Chromium Browser Shortcuts") @@ -833,7 +835,7 @@ sources: /* # Chromium Sessions_Sessions */ - SELECT * FROM source(Source="Chromium Sessions_Sessions") + SELECT * FROM source(source="Chromium Sessions_Sessions") LIMIT 50 query: | LET Rows = SELECT * FROM ApplyFile(SourceName="Chromium Sessions_Sessions") @@ -869,7 +871,7 @@ sources: /* # Chromium Browser Top Sites */ - SELECT * FROM source(Source="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") @@ -895,14 +897,14 @@ sources: /* # Edge Browser Autofill_CombinedAutofill */ - SELECT * FROM source(Source="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 + LET Output = SELECT timestamp(epoch=date_last_used) AS DateLastUsed, * FROM Rows WHERE DateLastUsed > DateAfter AND DateLastUsed < DateBefore @@ -922,7 +924,7 @@ sources: /* # Edge Browser Navigation History_Navigation History */ - SELECT * FROM source(Source="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") @@ -953,7 +955,7 @@ sources: /* # Firefox Places */ - SELECT * FROM source(Source="Firefox Places") + SELECT * FROM source(source="Firefox Places") LIMIT 50 query: | LET Rows = SELECT * FROM ApplyFile(SourceName="Firefox Places") @@ -985,7 +987,7 @@ sources: /* # Firefox Places_Downloads */ - SELECT * FROM source(Source="Firefox Places_Downloads") + SELECT * FROM source(source="Firefox Places_Downloads") LIMIT 50 query: | LET Rows = SELECT * FROM ApplyFile(SourceName="Firefox Places_Downloads") @@ -1016,7 +1018,7 @@ sources: /* # Firefox Places_History */ - SELECT * FROM source(Source="Firefox Places_History") + SELECT * FROM source(source="Firefox Places_History") LIMIT 50 query: | LET Rows = SELECT * FROM ApplyFile(SourceName="Firefox Places_History") @@ -1052,7 +1054,7 @@ sources: /* # Firefox Cookies */ - SELECT * FROM source(Source="Firefox Cookies") + SELECT * FROM source(source="Firefox Cookies") LIMIT 50 query: | LET Rows = SELECT * FROM ApplyFile(SourceName="Firefox Cookies") @@ -1086,7 +1088,7 @@ sources: /* # Firefox Downloads */ - SELECT * FROM source(Source="Firefox Downloads") + SELECT * FROM source(source="Firefox Downloads") LIMIT 50 query: | LET Rows = SELECT * FROM ApplyFile(SourceName="Firefox Downloads") @@ -1119,7 +1121,7 @@ sources: /* # Firefox Favicons */ - SELECT * FROM source(Source="Firefox Favicons") + SELECT * FROM source(source="Firefox Favicons") LIMIT 50 query: | LET Rows = SELECT * FROM ApplyFile(SourceName="Firefox Favicons") @@ -1147,7 +1149,7 @@ sources: /* # Firefox Form History */ - SELECT * FROM source(Source="Firefox Form History") + SELECT * FROM source(source="Firefox Form History") LIMIT 50 query: | LET Rows = SELECT * FROM ApplyFile(SourceName="Firefox Form History") @@ -1176,7 +1178,7 @@ sources: /* # IE or Edge WebCacheV01_All Data */ - SELECT * FROM source(Source="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") @@ -1219,7 +1221,7 @@ sources: /* # IE or Edge WebCacheV01_Highlights */ - SELECT * FROM source(Source="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") @@ -1249,7 +1251,7 @@ sources: /* # MacOS Applications Cache */ - SELECT * FROM source(Source="MacOS Applications Cache") + SELECT * FROM source(source="MacOS Applications Cache") LIMIT 50 query: | LET Rows = SELECT * FROM ApplyFile(SourceName="MacOS Applications Cache") @@ -1288,7 +1290,7 @@ sources: /* # MacOS NetworkUsage */ - SELECT * FROM source(Source="MacOS NetworkUsage") + SELECT * FROM source(source="MacOS NetworkUsage") LIMIT 50 query: | LET Rows = SELECT * FROM ApplyFile(SourceName="MacOS NetworkUsage") @@ -1327,7 +1329,7 @@ sources: /* # MacOS Notes */ - SELECT * FROM source(Source="MacOS Notes") + SELECT * FROM source(source="MacOS Notes") LIMIT 50 query: | LET Rows = SELECT * FROM ApplyFile(SourceName="MacOS Notes") @@ -1376,7 +1378,7 @@ sources: /* # MacOS XProtect Detections */ - SELECT * FROM source(Source="MacOS XProtect Detections") + SELECT * FROM source(source="MacOS XProtect Detections") LIMIT 50 query: | LET Rows = SELECT * FROM ApplyFile(SourceName="MacOS XProtect Detections") @@ -1406,7 +1408,7 @@ sources: /* # Windows Activities Cache_ActivityPackageId */ - SELECT * FROM source(Source="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") @@ -1435,7 +1437,7 @@ sources: /* # Windows Activities Cache_Clipboard */ - SELECT * FROM source(Source="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") @@ -1464,6 +1466,51 @@ sources: }) + + +- name: "Windows WPNDatabase - Notifications_Notifications" + notebook: + - type: vql + 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: vql @@ -1472,7 +1519,7 @@ sources: /* # Windows Search Service_SystemIndex_Gthr */ - SELECT * FROM source(Source="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") @@ -1511,7 +1558,7 @@ sources: /* # Windows Search Service_SystemIndex_GthrPth */ - SELECT * FROM source(Source="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") @@ -1538,7 +1585,7 @@ sources: /* # Windows Search Service_SystemIndex_PropertyStore */ - SELECT * FROM source(Source="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") @@ -1586,7 +1633,7 @@ sources: /* # Windows Search Service_SystemIndex_PropertyStore_Highlights */ - SELECT * FROM source(Source="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") @@ -1622,7 +1669,7 @@ sources: /* # Windows Search Service_BrowsingActivity */ - SELECT * FROM source(Source="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") @@ -1651,7 +1698,7 @@ sources: /* # Windows Search Service_UserActivityLogging */ - SELECT * FROM source(Source="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")