From 3d44f4d171ceb292e87dec54e8dc218f250e9154 Mon Sep 17 00:00:00 2001 From: reece394 <31659691+reece394@users.noreply.github.com> Date: Tue, 13 Jan 2026 20:16:35 +0000 Subject: [PATCH 1/3] Fix Firefox History Parsing --- definitions/Firefox_Bookmarks.yaml | 36 --------------- definitions/Firefox_History.yaml | 61 ++++++++++++++++++++++++++ definitions/Firefox_HistoryLegacy.yaml | 59 +++++++++++++++++++++++++ 3 files changed, 120 insertions(+), 36 deletions(-) create mode 100644 definitions/Firefox_History.yaml create mode 100644 definitions/Firefox_HistoryLegacy.yaml diff --git a/definitions/Firefox_Bookmarks.yaml b/definitions/Firefox_Bookmarks.yaml index 9d60f6b..e10fc8e 100644 --- a/definitions/Firefox_Bookmarks.yaml +++ b/definitions/Firefox_Bookmarks.yaml @@ -68,39 +68,3 @@ Sources: INNER JOIN moz_anno_attributes ON moz_annos.anno_attribute_id = moz_anno_attributes.id WHERE moz_anno_attributes.name IN ('downloads/destinationFileURI','downloads/destinationFileName','downloads/metaData') ORDER BY moz_annos.dateAdded ASC - -- name: History - Preamble: | - LET VisitType <= dict(`1`='TRANSITION_LINK', `2`='TRANSITION_TYPED', `3`='TRANSITION_BOOKMARK', - `4`='TRANSITION_EMBED', `5`= 'TRANSITION_REDIRECT_PERMANENT', `6`='TRANSITION_REDIRECT_TEMPORARY', - `7`='TRANSITION_DOWNLOAD', `8`='TRANSITION_FRAMED_LINK', `9`='TRANSITION_RELOAD') - - VQL: | - SELECT VisitID, FromVisitID, - timestamp(epoch= last_visit_date) AS LastVisitDate, - VisitCount, URL, Title, Description, - get(item= VisitType, field=str(str=visit_type), default="Unknown") AS VisitType, - Bool(Value=hidden) AS Hidden, - Bool(Value=typed) AS Typed, - Frecency, PreviewImageURL, OSPath - FROM Rows - WHERE LastVisitDate > DateAfter AND LastVisitDate < DateBefore - AND (Title, URL, Description) =~ FilterRegex - - SQL: | - SELECT - moz_historyvisits.id AS VisitID, - moz_historyvisits.from_visit AS FromVisitID, - moz_places.last_visit_date, - moz_places.visit_count AS VisitCount, - moz_places.url AS URL, - moz_places.title AS Title, - moz_places.description AS Description, - moz_historyvisits.visit_type, - moz_places.hidden, - moz_places.typed, - moz_places.frecency AS Frecency, - moz_places.preview_image_url AS PreviewImageURL - FROM moz_places - INNER JOIN moz_historyvisits ON moz_places.origin_id = moz_historyvisits.id - ORDER BY moz_places.last_visit_date ASC diff --git a/definitions/Firefox_History.yaml b/definitions/Firefox_History.yaml new file mode 100644 index 0000000..7c9a59e --- /dev/null +++ b/definitions/Firefox_History.yaml @@ -0,0 +1,61 @@ +Name: Firefox Places History +Author: Andrew Rathbun, Reece394 +Email: andrew.d.rathbun@gmail.com +Reference: https://github.com/EricZimmerman/SQLECmd +SQLiteIdentifyQuery: | + SELECT ( + SELECT COUNT(*) + FROM sqlite_master + WHERE type='table' + AND (name='moz_historyvisits' OR name='moz_bookmarks' + OR name='moz_places' OR name='moz_inputhistory')) + + (SELECT CASE WHEN (SELECT COUNT(*) FROM pragma_table_info('moz_places') WHERE name IN ('description','preview_image_url')) > 1 + THEN 1 ELSE 0 END) AS `Check`; +SQLiteIdentifyValue: 5 +Categories: + - Firefox + - Browser + +FilenameRegex: "places.sqlite" +Globs: + - "{{WindowsFirefoxProfiles}}/*/places.sqlite" + - "{{LinuxFirefoxProfiles}}/places.sqlite" + - "{{MacOSFirefoxProfiles}}/*/places.sqlite" + +Sources: +- Preamble: | + LET VisitType <= dict(`1`='TRANSITION_LINK', `2`='TRANSITION_TYPED', `3`='TRANSITION_BOOKMARK', + `4`='TRANSITION_EMBED', `5`= 'TRANSITION_REDIRECT_PERMANENT', `6`='TRANSITION_REDIRECT_TEMPORARY', + `7`='TRANSITION_DOWNLOAD', `8`='TRANSITION_FRAMED_LINK', `9`='TRANSITION_RELOAD') + + VQL: | + SELECT VisitID, FromVisitID, + timestamp(epoch= visit_date) AS VisitDate, + timestamp(epoch= last_visit_date) AS LastVisitDate, + VisitCount, URL, Title, Description, + get(item= VisitType, field=str(str=visit_type), default="Unknown") AS VisitType, + Bool(Value=hidden) AS Hidden, + Bool(Value=typed) AS Typed, + Frecency, PreviewImageURL, OSPath + FROM Rows + WHERE VisitDate > DateAfter AND VisitDate < DateBefore + AND (Title, URL, Description) =~ FilterRegex + + SQL: | + SELECT + moz_historyvisits.id AS VisitID, + moz_historyvisits.from_visit AS FromVisitID, + moz_historyvisits.visit_date, + moz_places.last_visit_date, + moz_places.visit_count AS VisitCount, + moz_places.url AS URL, + moz_places.title AS Title, + moz_places.description AS Description, + moz_historyvisits.visit_type, + moz_places.hidden, + moz_places.typed, + moz_places.frecency AS Frecency, + moz_places.preview_image_url AS PreviewImageURL + FROM moz_places + INNER JOIN moz_historyvisits ON moz_places.id = moz_historyvisits.place_id + ORDER BY moz_historyvisits.visit_date ASC diff --git a/definitions/Firefox_HistoryLegacy.yaml b/definitions/Firefox_HistoryLegacy.yaml new file mode 100644 index 0000000..6eb955a --- /dev/null +++ b/definitions/Firefox_HistoryLegacy.yaml @@ -0,0 +1,59 @@ +Name: Firefox Places History Legacy +Author: Andrew Rathbun, Reece394 +Email: andrew.d.rathbun@gmail.com +Reference: https://github.com/EricZimmerman/SQLECmd +SQLiteIdentifyQuery: | + SELECT ( + SELECT COUNT(*) + FROM sqlite_master + WHERE type='table' + AND (name='moz_historyvisits' OR name='moz_bookmarks' + OR name='moz_places' OR name='moz_inputhistory')) + + (SELECT CASE WHEN (SELECT COUNT(*) FROM pragma_table_info('moz_places') WHERE name IN ('description','preview_image_url')) > 1 + THEN 0 ELSE 1 END) AS `Check`; +SQLiteIdentifyValue: 5 +Categories: + - Firefox + - Browser + +FilenameRegex: "places.sqlite" +Globs: + - "{{WindowsFirefoxProfiles}}/*/places.sqlite" + - "{{LinuxFirefoxProfiles}}/places.sqlite" + - "{{MacOSFirefoxProfiles}}/*/places.sqlite" + +Sources: +- Preamble: | + LET VisitType <= dict(`1`='TRANSITION_LINK', `2`='TRANSITION_TYPED', `3`='TRANSITION_BOOKMARK', + `4`='TRANSITION_EMBED', `5`= 'TRANSITION_REDIRECT_PERMANENT', `6`='TRANSITION_REDIRECT_TEMPORARY', + `7`='TRANSITION_DOWNLOAD', `8`='TRANSITION_FRAMED_LINK', `9`='TRANSITION_RELOAD') + + VQL: | + SELECT VisitID, FromVisitID, + timestamp(epoch= visit_date) AS VisitDate, + timestamp(epoch= last_visit_date) AS LastVisitDate, + VisitCount, URL, Title, + get(item= VisitType, field=str(str=visit_type), default="Unknown") AS VisitType, + Bool(Value=hidden) AS Hidden, + Bool(Value=typed) AS Typed, + Frecency, OSPath + FROM Rows + WHERE VisitDate > DateAfter AND VisitDate < DateBefore + AND (Title, URL, Description) =~ FilterRegex + + SQL: | + SELECT + moz_historyvisits.id AS VisitID, + moz_historyvisits.from_visit AS FromVisitID, + moz_historyvisits.visit_date, + moz_places.last_visit_date, + moz_places.visit_count AS VisitCount, + moz_places.url AS URL, + moz_places.title AS Title, + moz_historyvisits.visit_type, + moz_places.hidden, + moz_places.typed, + moz_places.frecency AS Frecency + FROM moz_places + INNER JOIN moz_historyvisits ON moz_places.id = moz_historyvisits.place_id + ORDER BY moz_historyvisits.visit_date ASC From 2859e38c1edc5a75bdb7b4bb24ebcce59567dd51 Mon Sep 17 00:00:00 2001 From: reece394 <31659691+reece394@users.noreply.github.com> Date: Tue, 13 Jan 2026 21:18:19 +0000 Subject: [PATCH 2/3] Add name to Firefox Bookmarks --- definitions/Firefox_Bookmarks.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/definitions/Firefox_Bookmarks.yaml b/definitions/Firefox_Bookmarks.yaml index e10fc8e..fe55160 100644 --- a/definitions/Firefox_Bookmarks.yaml +++ b/definitions/Firefox_Bookmarks.yaml @@ -20,8 +20,9 @@ Globs: - "{{MacOSFirefoxProfiles}}/*/places.sqlite" Sources: -- Preamble: | - LET BookmarkTypes <= dict(`1`="URL", `2`="Folder", `3`="Separator") +- name: Bookmarks + Preamble: | + LET BookmarkTypes <= dict(`1`='URL', `2`='Folder', `3`='Separator') VQL: | SELECT ID, ParentID, From 2f16164bb016db772dd60fc99851b1764bfcf8c6 Mon Sep 17 00:00:00 2001 From: reece394 <31659691+reece394@users.noreply.github.com> Date: Fri, 16 Jan 2026 12:25:41 +0000 Subject: [PATCH 3/3] Attempt to fix tests --- test_files/Firefox/firefox.sqlite | Bin 1212416 -> 1212416 bytes testing/fixtures/TestArtifact.golden | 14 +++++++------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/test_files/Firefox/firefox.sqlite b/test_files/Firefox/firefox.sqlite index ea8808ffc21f62e9e6235014c45dbd4a19e68c1f..28676aced48392142c81fc93756653d3f640ad3f 100644 GIT binary patch delta 175 zcmZo@@M-{}7RD`1*XkvAU%9^Lu+s5$ey+F q!Zy+AXY2Wdr(gchEyByq%*F|{j<@{b{V=ZWj15fx|1V)~KtllFkV@46 delta 190 zcmZo@@M-{}7RD`1*Xku#@|HhQPiGZiVrSrBWaH#uVqgUdJ^Cl!{=S|Gh?#+y1&CRJ zm<@>8ftUk`If0l9h`G1FujhI9Uld{vGam~h8zbC|?Vsv-B^$PLH*lY**IUV3(es#> og@>7q5o`z0T4p#0Xdx3fGaDyZ=HdM?uI-EsO#lBcVQxS}0ExXtfB*mh diff --git a/testing/fixtures/TestArtifact.golden b/testing/fixtures/TestArtifact.golden index b8d7cb1..c18adec 100644 --- a/testing/fixtures/TestArtifact.golden +++ b/testing/fixtures/TestArtifact.golden @@ -5,25 +5,25 @@ " \"LastVisitDate\": \"2020-06-27T09:29:54.51375Z\",", " \"URL\": \"https://www.mozilla.org/privacy/firefox/\",", " \"Description\": null,", - " \"_Source\": \"Generic.Forensic.SQLiteHunter/Firefox Places_History\"", + " \"_Source\": \"Generic.Forensic.SQLiteHunter/Firefox Places History\"", " },", " {", " \"LastVisitDate\": \"2020-06-27T09:30:05.721357Z\",", " \"URL\": \"http://github.com/seanbreckenridge/dotfiles\",", " \"Description\": null,", - " \"_Source\": \"Generic.Forensic.SQLiteHunter/Firefox Places_History\"", + " \"_Source\": \"Generic.Forensic.SQLiteHunter/Firefox Places History\"", " },", " {", " \"LastVisitDate\": \"2020-06-30T05:53:37.171Z\",", " \"URL\": \"https://www.mozilla.org/en-US/firefox/78.0a2/firstrun/\",", " \"Description\": \"Firefox Developer Edition is the blazing fast browser that offers cutting edge developer tools and latest features like CSS Grid support and framework debugging\",", - " \"_Source\": \"Generic.Forensic.SQLiteHunter/Firefox Places_History\"", + " \"_Source\": \"Generic.Forensic.SQLiteHunter/Firefox Places History\"", " },", " {", " \"LastVisitDate\": \"2021-02-21T08:55:10.488Z\",", " \"URL\": \"https://www.mozilla.org/en-US/privacy/firefox/\",", " \"Description\": \"\\n Our Privacy Notices describe the data our products and services receive, share, and use, as well as choices available to you.\\n\",", - " \"_Source\": \"Generic.Forensic.SQLiteHunter/Firefox Places_History\"", + " \"_Source\": \"Generic.Forensic.SQLiteHunter/Firefox Places History\"", " }", "]" ], @@ -33,7 +33,7 @@ " \"LastVisitDate\": \"2021-02-21T08:55:10.488Z\",", " \"URL\": \"https://www.mozilla.org/en-US/privacy/firefox/\",", " \"Description\": \"\\n Our Privacy Notices describe the data our products and services receive, share, and use, as well as choices available to you.\\n\",", - " \"_Source\": \"Generic.Forensic.SQLiteHunter/Firefox Places_History\"", + " \"_Source\": \"Generic.Forensic.SQLiteHunter/Firefox Places History\"", " }", "]" ], @@ -43,7 +43,7 @@ " \"LastVisitDate\": \"2020-06-27T09:29:54.51375Z\",", " \"URL\": \"https://www.mozilla.org/privacy/firefox/\",", " \"Description\": null,", - " \"_Source\": \"Generic.Forensic.SQLiteHunter/Firefox Places_History\"", + " \"_Source\": \"Generic.Forensic.SQLiteHunter/Firefox Places History\"", " }", "]" ], @@ -53,7 +53,7 @@ " \"LastVisitDate\": \"2020-06-30T05:53:37.171Z\",", " \"URL\": \"https://www.mozilla.org/en-US/firefox/78.0a2/firstrun/\",", " \"Description\": \"Firefox Developer Edition is the blazing fast browser that offers cutting edge developer tools and latest features like CSS Grid support and framework debugging\",", - " \"_Source\": \"Generic.Forensic.SQLiteHunter/Firefox Places_History\"", + " \"_Source\": \"Generic.Forensic.SQLiteHunter/Firefox Places History\"", " }", "]" ]