diff --git a/compile/template.yaml b/compile/template.yaml index ade082b..c396409 100644 --- a/compile/template.yaml +++ b/compile/template.yaml @@ -157,8 +157,8 @@ sources: /* # Results From %v */ - SELECT * FROM source(source=%q) - ''', args=[Source, Source]), + SELECT * FROM source(source=%q, artifact=%q) + ''', args=[Source, Source, split(string=ArtifactName, sep='/')[0]]), output=format(format=''' Recalculate to show Results from %v with %v rows ''', args=[Source, Records])) AS NotebookModification diff --git a/definitions/Windows_ActivitiesCache.yaml b/definitions/Windows_ActivitiesCache.yaml index c907609..2d6a884 100644 --- a/definitions/Windows_ActivitiesCache.yaml +++ b/definitions/Windows_ActivitiesCache.yaml @@ -40,7 +40,7 @@ Sources: EndTime, Payload, OSPath[1] AS User, - base64decode(string=parse_json_array(data=ClipboardPayload)[0].content) AS ClipboardPayload, + base64decode(string=parse_json_array(data=ClipboardPayload || '[]')[0].content) AS ClipboardPayload, OSPath AS Path, Mtime FROM Rows diff --git a/docs/content/docs/rules/index.json b/docs/content/docs/rules/index.json index 23e4d6d..7815340 100644 --- a/docs/content/docs/rules/index.json +++ b/docs/content/docs/rules/index.json @@ -93,7 +93,7 @@ { "Name": "Chromium_Browser_Extensions", "Author": "Mike Cohen", - "Description": "Parses all installed chromium extensions.\n", + "Description": "Parses all installed chromium extensions.\n\nManifest V3 extensions list the sites they can read or change in\n`host_permissions` rather than `permissions`, so both are reported.\n`ContentScriptMatches` lists the sites where the extension injects\nits own scripts.\n", "Categories": [ "Chrome", "Browser" @@ -103,7 +103,7 @@ "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" + "RawData": "Name: Chromium Browser Extensions\nDescription: |\n Parses all installed chromium extensions.\n\n Manifest V3 extensions list the sites they can read or change in\n `host_permissions` rather than `permissions`, so both are reported.\n `ContentScriptMatches` lists the sites where the extension injects\n its own scripts.\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 -- Message names are case insensitive so lower case the keys to\n -- match ResolveName()\n LET LowerKeys(Item) = to_dict(item={\n SELECT lowcase(string=_key) AS _key, _value FROM items(item=Item)\n })\n\n -- Find the Locale file to help with.\n LET LocaleData = SELECT *, if(condition=Manifest.default_locale, else=dict(),\n then=LowerKeys(Item=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 -- Flatten the matches of all content scripts into one list of unique sites.\n LET ContentScriptMatches(Manifest) = SELECT * FROM foreach(\n row=Manifest.content_scripts,\n query={ SELECT _value FROM foreach(row=matches) })\n GROUP BY _value\n\n VQL: |\n SELECT OSPath,\n -- Manifests are stored in Extensions/\u003cID\u003e/\u003cVersion\u003e/\n OSPath.Components[-3] AS ID,\n OSPath.Components[-2] AS Version,\n 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.manifest_version AS ManifestVersion,\n Manifest.oauth2.scopes as Scopes,\n Manifest.permissions as Permissions,\n Manifest.host_permissions AS HostPermissions,\n ContentScriptMatches(Manifest=Manifest)._value AS ContentScriptMatches,\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", @@ -548,7 +548,7 @@ "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" + "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", diff --git a/testing/golden.go b/testing/golden_test.go similarity index 100% rename from testing/golden.go rename to testing/golden_test.go diff --git a/testing/testcases/chrome_extensions.in.yaml b/testing/testcases/chrome_extensions.in.yaml index 6852011..e74b262 100644 --- a/testing/testcases/chrome_extensions.in.yaml +++ b/testing/testcases/chrome_extensions.in.yaml @@ -7,5 +7,5 @@ Queries: FROM Artifact.Generic.Forensic.SQLiteHunter( MatchFilename=TRUE, All=FALSE, Chrome=TRUE, CustomGlob=testFiles + '/Chrome/Extensions/*/*/manifest.json') - WHERE _Source =~ "Chromium Browser Extensions" + WHERE _Source =~ "Chromium_Browser_Extensions" ORDER BY ID diff --git a/testing/testcases/chrome_extensions.out.yaml b/testing/testcases/chrome_extensions.out.yaml index ba7f967..96f5ee9 100644 --- a/testing/testcases/chrome_extensions.out.yaml +++ b/testing/testcases/chrome_extensions.out.yaml @@ -5,7 +5,7 @@ Query: SELECT ID, Version, name, description, ManifestVersion, FROM Artifact.Generic.Forensic.SQLiteHunter( MatchFilename=TRUE, All=FALSE, Chrome=TRUE, CustomGlob=testFiles + '/Chrome/Extensions/*/*/manifest.json') -WHERE _Source =~ "Chromium Browser Extensions" +WHERE _Source =~ "Chromium_Browser_Extensions" ORDER BY ID Output: [