diff --git a/README.md b/README.md index f10a012..0396a33 100644 --- a/README.md +++ b/README.md @@ -7,76 +7,76 @@ [![Lint](https://github.com/moonD4rk/HackBrowserData/actions/workflows/lint.yml/badge.svg)](https://github.com/moonD4rk/HackBrowserData/actions/workflows/lint.yml) [![build](https://github.com/moonD4rk/HackBrowserData/actions/workflows/build.yml/badge.svg)](https://github.com/moonD4rk/HackBrowserData/actions/workflows/build.yml) [![Release](https://github.com/moonD4rk/HackBrowserData/actions/workflows/release.yml/badge.svg)](https://github.com/moonD4rk/HackBrowserData/actions/workflows/release.yml) -[中文说明](https://github.com/moonD4rk/HackBrowserData/blob/master/README_ZH.md) +[中文说明](https://github.com/moonD4rk/HackBrowserData/blob/master/README_ZH.md) -`HackBrowserData` is an open-source tool that could help you decrypt data ( password|bookmark|cookie|history|credit card|download|localStorage|extension ) from the browser. It supports the most popular browsers on the market and runs on Windows, macOS and Linux. +`HackBrowserData` is a command-line tool for decrypting and exporting browser data ( passwords, history, cookies, bookmarks, credit cards, download records, localStorage and extension ) from the browser. It supports the most popular browsers on the market and runs on Windows, macOS and Linux. -> Disclaimer: This tool is limited to security research only, and the user assumes all legal and related responsibilities arising from its use! The author assumes no legal responsibility! +> Disclaimer: This tool is only intended for security research. Users are responsible for all legal and related liabilities resulting from the use of this tool. The original author does not assume any legal responsibility. ## Supported Browser ### Windows -| Browser | Password | Cookie | Bookmark | History | -| :---------------------------------- | :------: | :----: | :------: | :-----: | -| Google Chrome | ✅ | ✅ | ✅ | ✅ | -| Google Chrome Beta | ✅ | ✅ | ✅ | ✅ | -| Chromium | ✅ | ✅ | ✅ | ✅ | -| Microsoft Edge | ✅ | ✅ | ✅ | ✅ | -| 360 Speed | ✅ | ✅ | ✅ | ✅ | -| QQ | ✅ | ✅ | ✅ | ✅ | -| Brave | ✅ | ✅ | ✅ | ✅ | -| Opera | ✅ | ✅ | ✅ | ✅ | -| OperaGX | ✅ | ✅ | ✅ | ✅ | -| Vivaldi | ✅ | ✅ | ✅ | ✅ | -| Yandex | ✅ | ✅ | ✅ | ✅ | -| CocCoc | ✅ | ✅ | ✅ | ✅ | -| Firefox | ✅ | ✅ | ✅ | ✅ | -| Firefox Beta | ✅ | ✅ | ✅ | ✅ | -| Firefox Dev | ✅ | ✅ | ✅ | ✅ | -| Firefox ESR | ✅ | ✅ | ✅ | ✅ | -| Firefox Nightly | ✅ | ✅ | ✅ | ✅ | -| Internet Explorer | ❌ | ❌ | ❌ | ❌ | +| Browser | Password | Cookie | Bookmark | History | +|:-------------------|:--------:|:------:|:--------:|:-------:| +| Google Chrome | ✅ | ✅ | ✅ | ✅ | +| Google Chrome Beta | ✅ | ✅ | ✅ | ✅ | +| Chromium | ✅ | ✅ | ✅ | ✅ | +| Microsoft Edge | ✅ | ✅ | ✅ | ✅ | +| 360 Speed | ✅ | ✅ | ✅ | ✅ | +| QQ | ✅ | ✅ | ✅ | ✅ | +| Brave | ✅ | ✅ | ✅ | ✅ | +| Opera | ✅ | ✅ | ✅ | ✅ | +| OperaGX | ✅ | ✅ | ✅ | ✅ | +| Vivaldi | ✅ | ✅ | ✅ | ✅ | +| Yandex | ✅ | ✅ | ✅ | ✅ | +| CocCoc | ✅ | ✅ | ✅ | ✅ | +| Firefox | ✅ | ✅ | ✅ | ✅ | +| Firefox Beta | ✅ | ✅ | ✅ | ✅ | +| Firefox Dev | ✅ | ✅ | ✅ | ✅ | +| Firefox ESR | ✅ | ✅ | ✅ | ✅ | +| Firefox Nightly | ✅ | ✅ | ✅ | ✅ | +| Internet Explorer | ❌ | ❌ | ❌ | ❌ | ### MacOS Based on Apple's security policy, some browsers **require a current user password** to decrypt. -| Browser | Password | Cookie | Bookmark | History | -| :------- | :------: | :----: | :------: | :-----: | -| Google Chrome | ✅ | ✅ | ✅ | ✅ | -| Google Chrome Beta | ✅ | ✅ | ✅ | ✅ | -| Chromium | ✅ | ✅ | ✅ | ✅ | -| Microsoft Edge | ✅ | ✅ | ✅ | ✅ | -| Brave | ✅ | ✅ | ✅ | ✅ | -| Opera | ✅ | ✅ | ✅ | ✅ | -| OperaGX | ✅ | ✅ | ✅ | ✅ | -| Vivaldi | ✅ | ✅ | ✅ | ✅ | -| CocCoc | ✅ | ✅ | ✅ | ✅ | -| Firefox | ✅ | ✅ | ✅ | ✅ | -| Firefox Beta | ✅ | ✅ | ✅ | ✅ | -| Firefox Dev | ✅ | ✅ | ✅ | ✅ | -| Firefox ESR | ✅ | ✅ | ✅ | ✅ | -| Firefox Nightly | ✅ | ✅ | ✅ | ✅ | -| Yandex | ✅ | ✅ | ✅ | ✅ | -| Safari | ❌ | ❌ | ❌ | ❌ | +| Browser | Password | Cookie | Bookmark | History | +|:-------------------|:--------:|:------:|:--------:|:-------:| +| Google Chrome | ✅ | ✅ | ✅ | ✅ | +| Google Chrome Beta | ✅ | ✅ | ✅ | ✅ | +| Chromium | ✅ | ✅ | ✅ | ✅ | +| Microsoft Edge | ✅ | ✅ | ✅ | ✅ | +| Brave | ✅ | ✅ | ✅ | ✅ | +| Opera | ✅ | ✅ | ✅ | ✅ | +| OperaGX | ✅ | ✅ | ✅ | ✅ | +| Vivaldi | ✅ | ✅ | ✅ | ✅ | +| CocCoc | ✅ | ✅ | ✅ | ✅ | +| Firefox | ✅ | ✅ | ✅ | ✅ | +| Firefox Beta | ✅ | ✅ | ✅ | ✅ | +| Firefox Dev | ✅ | ✅ | ✅ | ✅ | +| Firefox ESR | ✅ | ✅ | ✅ | ✅ | +| Firefox Nightly | ✅ | ✅ | ✅ | ✅ | +| Yandex | ✅ | ✅ | ✅ | ✅ | +| Safari | ❌ | ❌ | ❌ | ❌ | ### Linux -| Browser | Password | Cookie | Bookmark | History | -| :---- | :------: | :----: | :------: | :-----: | -| Google Chrome | ✅ | ✅ | ✅ | ✅ | -| Google Chrome Beta | ✅ | ✅ | ✅ | ✅ | -| Chromium | ✅ | ✅ | ✅ | ✅ | -| Microsoft Edge Dev | ✅ | ✅ | ✅ | ✅ | -| Brave | ✅ | ✅ | ✅ | ✅ | -| Opera | ✅ | ✅ | ✅ | ✅ | -| Vivaldi | ✅ | ✅ | ✅ | ✅ | -| Firefox | ✅ | ✅ | ✅ | ✅ | -| Firefox Beta | ✅ | ✅ | ✅ | ✅ | -| Firefox Dev | ✅ | ✅ | ✅ | ✅ | -| Firefox ESR | ✅ | ✅ | ✅ | ✅ | -| Firefox Nightly | ✅ | ✅ | ✅ | ✅ | +| Browser | Password | Cookie | Bookmark | History | +|:-------------------|:--------:|:------:|:--------:|:-------:| +| Google Chrome | ✅ | ✅ | ✅ | ✅ | +| Google Chrome Beta | ✅ | ✅ | ✅ | ✅ | +| Chromium | ✅ | ✅ | ✅ | ✅ | +| Microsoft Edge Dev | ✅ | ✅ | ✅ | ✅ | +| Brave | ✅ | ✅ | ✅ | ✅ | +| Opera | ✅ | ✅ | ✅ | ✅ | +| Vivaldi | ✅ | ✅ | ✅ | ✅ | +| Firefox | ✅ | ✅ | ✅ | ✅ | +| Firefox Beta | ✅ | ✅ | ✅ | ✅ | +| Firefox Dev | ✅ | ✅ | ✅ | ✅ | +| Firefox ESR | ✅ | ✅ | ✅ | ✅ | +| Firefox Nightly | ✅ | ✅ | ✅ | ✅ | ## Getting started @@ -133,18 +133,22 @@ USAGE: Export all browingdata(password/cookie/history/bookmark) from browser Github Link: https://github.com/moonD4rk/HackBrowserData +VERSION: + 0.5.0 + GLOBAL OPTIONS: --verbose, --vv verbose (default: false) --compress, --zip compress result to zip (default: false) - --browser value, -b value available browsers: all|chrome|opera-gx|vivaldi|coccoc|brave|edge|chromium|chrome-beta|opera|yandex|firefox (default: "all") + --browser value, -b value available browsers: all|brave|chrome|chrome-beta|chromium|coccoc|edge|firefox|opera|opera-gx|vivaldi|yandex (default: "all") --results-dir value, --dir value export dir (default: "results") --format value, -f value file name csv|json (default: "csv") --profile-path value, -p value custom profile dir path, get with chrome://version - --help, -h show help (default: false) - --version, -v print the version (default: false) + --full-export, --full is export full browsing data (default: true) + --help, -h show help + --version, -v print the version -PS C:\test> .\hack-browser-data.exe -b all -f json --dir results -zip +PS C:\test> .\hack-browser-data.exe -b all -f json --dir results -zip [NOTICE] [browser.go:46,pickChromium] find browser Chrome success [NOTICE] [browser.go:46,pickChromium] find browser Microsoft Edge success [NOTICE] [browsingdata.go:59,Output] output to file results/microsoft_edge_download.json success @@ -163,8 +167,9 @@ PS C:\test> .\hack-browser-data.exe -b all -f json --dir results -zip ``` ### Run with custom browser profile folder +If you want to export data from a custom browser profile folder, you can use the `-p` parameter to specify the path of the browser profile folder. PS: use double quotes to wrap the path. ``` -PS C:\Users\User\Desktop> .\hack-browser-data.exe -b chrome -p 'C:\Users\User\AppData\Local\Microsoft\Edge\User Data\Default' +PS C:\Users\User\Desktop> .\hack-browser-data.exe -b chrome -p "C:\Users\User\AppData\Local\Microsoft\Edge\User Data\Default" [NOTICE] [browsingdata.go:59,Output] output to file results/chrome_creditcard.csv success [NOTICE] [browsingdata.go:59,Output] output to file results/chrome_bookmark.csv success diff --git a/README_ZH.md b/README_ZH.md index b998401..047e1e9 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -14,67 +14,67 @@ ### Windows -| 浏览器 | 密码 | Cookie | 书签 | 历史记录 | -| :------- | :------: | :----: | :------: | :-----: | -| Google Chrome| ✅ | ✅ | ✅ | ✅ | -| Google Chrome Beta| ✅ | ✅ | ✅ | ✅ | -| Chromium | ✅ | ✅ | ✅ | ✅ | -| Microsoft Edge| ✅ | ✅ | ✅ | ✅ | -| 360 极速浏览器 | ✅ | ✅ | ✅ | ✅ | -| QQ | ✅ | ✅ | ✅ | ✅ | -| Brave | ✅ | ✅ | ✅ | ✅ | -| Opera | ✅ | ✅ | ✅ | ✅ | -| OperaGX | ✅ | ✅ | ✅ | ✅ | -| Vivaldi | ✅ | ✅ | ✅ | ✅ | -| Yandex | ✅ | ✅ | ✅ | ✅ | -| CocCoc | ✅ | ✅ | ✅ | ✅ | -| Firefox | ✅ | ✅ | ✅ | ✅ | -| Firefox Beta | ✅ | ✅ | ✅ | ✅ | -| Firefox Dev | ✅ | ✅ | ✅ | ✅ | -| Firefox ESR | ✅ | ✅ | ✅ | ✅ | -| Firefox Nightly | ✅ | ✅ | ✅ | ✅ | -| IE 浏览器 | ❌ | ❌ | ❌ | ❌ | +| 浏览器 | 密码 | Cookie | 书签 | 历史记录 | +|:-------------------|:---:|:------:|:---:|:----:| +| Google Chrome | ✅ | ✅ | ✅ | ✅ | +| Google Chrome Beta | ✅ | ✅ | ✅ | ✅ | +| Chromium | ✅ | ✅ | ✅ | ✅ | +| Microsoft Edge | ✅ | ✅ | ✅ | ✅ | +| 360 极速浏览器 | ✅ | ✅ | ✅ | ✅ | +| QQ | ✅ | ✅ | ✅ | ✅ | +| Brave | ✅ | ✅ | ✅ | ✅ | +| Opera | ✅ | ✅ | ✅ | ✅ | +| OperaGX | ✅ | ✅ | ✅ | ✅ | +| Vivaldi | ✅ | ✅ | ✅ | ✅ | +| Yandex | ✅ | ✅ | ✅ | ✅ | +| CocCoc | ✅ | ✅ | ✅ | ✅ | +| Firefox | ✅ | ✅ | ✅ | ✅ | +| Firefox Beta | ✅ | ✅ | ✅ | ✅ | +| Firefox Dev | ✅ | ✅ | ✅ | ✅ | +| Firefox ESR | ✅ | ✅ | ✅ | ✅ | +| Firefox Nightly | ✅ | ✅ | ✅ | ✅ | +| IE 浏览器 | ❌ | ❌ | ❌ | ❌ | ### MacOS 由于 MacOS 的安全性设置,基于 `Chromium` 内核浏览器解密时**需要当前用户密码** -| 浏览器 | 密码 | Cookie | 书签 | 历史记录 | -| :--- | :------: | :----: | :------: | :-----: | -| Google Chrome | ✅ | ✅ | ✅ | ✅ | -| Google Chrome Beta | ✅ | ✅ | ✅ | ✅ | -| Chromium | ✅ | ✅ | ✅ | ✅ | -| Microsoft Edge | ✅ | ✅ | ✅ | ✅ | -| Brave | ✅ | ✅ | ✅ | ✅ | -| Opera | ✅ | ✅ | ✅ | ✅ | -| OperaGX | ✅ | ✅ | ✅ | ✅ | -| Vivaldi | ✅ | ✅ | ✅ | ✅ | -| Yandex | ✅ | ✅ | ✅ | ✅ | -| CocCoc | ✅ | ✅ | ✅ | ✅ | -| Firefox | ✅ | ✅ | ✅ | ✅ | -| Firefox Beta | ✅ | ✅ | ✅ | ✅ | -| Firefox Dev | ✅ | ✅ | ✅ | ✅ | -| Firefox ESR | ✅ | ✅ | ✅ | ✅ | -| Firefox Nightly | ✅ | ✅ | ✅ | ✅ | -| Safari | ❌ | ❌ | ❌ | ❌| +| 浏览器 | 密码 | Cookie | 书签 | 历史记录 | +|:-------------------|:---:|:------:|:---:|:----:| +| Google Chrome | ✅ | ✅ | ✅ | ✅ | +| Google Chrome Beta | ✅ | ✅ | ✅ | ✅ | +| Chromium | ✅ | ✅ | ✅ | ✅ | +| Microsoft Edge | ✅ | ✅ | ✅ | ✅ | +| Brave | ✅ | ✅ | ✅ | ✅ | +| Opera | ✅ | ✅ | ✅ | ✅ | +| OperaGX | ✅ | ✅ | ✅ | ✅ | +| Vivaldi | ✅ | ✅ | ✅ | ✅ | +| Yandex | ✅ | ✅ | ✅ | ✅ | +| CocCoc | ✅ | ✅ | ✅ | ✅ | +| Firefox | ✅ | ✅ | ✅ | ✅ | +| Firefox Beta | ✅ | ✅ | ✅ | ✅ | +| Firefox Dev | ✅ | ✅ | ✅ | ✅ | +| Firefox ESR | ✅ | ✅ | ✅ | ✅ | +| Firefox Nightly | ✅ | ✅ | ✅ | ✅ | +| Safari | ❌ | ❌ | ❌ | ❌ | ### Linux -| 浏览器 | 密码 | Cookie | 书签 | 历史记录 | -| :----- | :------: | :----: | :------: | :-----: | -| Google Chrome | ✅ | ✅ | ✅ | ✅ | -| Google Chrome Beta | ✅ | ✅ | ✅ | ✅ | -| Chromium | ✅ | ✅ | ✅ | ✅ | -| Microsoft Edge | ✅ | ✅ | ✅ | ✅ | -| Brave | ✅ | ✅ | ✅ | ✅ | -| Opera | ✅ | ✅ | ✅ | ✅ | -| Vivaldi | ✅ | ✅ | ✅ | ✅ | -| Chromium | ✅ | ✅ | ✅ | ✅ | -| Firefox | ✅ | ✅ | ✅ | ✅ | -| Firefox Beta | ✅ | ✅ | ✅ | ✅ | -| Firefox Dev | ✅ | ✅ | ✅ | ✅ | -| Firefox ESR | ✅ | ✅ | ✅ | ✅ | -| Firefox Nightly | ✅ | ✅ | ✅ | ✅ | +| 浏览器 | 密码 | Cookie | 书签 | 历史记录 | +|:-------------------|:---:|:------:|:---:|:----:| +| Google Chrome | ✅ | ✅ | ✅ | ✅ | +| Google Chrome Beta | ✅ | ✅ | ✅ | ✅ | +| Chromium | ✅ | ✅ | ✅ | ✅ | +| Microsoft Edge | ✅ | ✅ | ✅ | ✅ | +| Brave | ✅ | ✅ | ✅ | ✅ | +| Opera | ✅ | ✅ | ✅ | ✅ | +| Vivaldi | ✅ | ✅ | ✅ | ✅ | +| Chromium | ✅ | ✅ | ✅ | ✅ | +| Firefox | ✅ | ✅ | ✅ | ✅ | +| Firefox Beta | ✅ | ✅ | ✅ | ✅ | +| Firefox Dev | ✅ | ✅ | ✅ | ✅ | +| Firefox ESR | ✅ | ✅ | ✅ | ✅ | +| Firefox Nightly | ✅ | ✅ | ✅ | ✅ | ## 安装运行 ### 安装 @@ -128,18 +128,22 @@ USAGE: Export all browingdata(password/cookie/history/bookmark) from browser Github Link: https://github.com/moonD4rk/HackBrowserData +VERSION: + 0.5.0 + GLOBAL OPTIONS: --verbose, --vv verbose (default: false) --compress, --zip compress result to zip (default: false) - --browser value, -b value available browsers: all|chrome|opera-gx|vivaldi|coccoc|brave|edge|chromium|chrome-beta|opera|yandex|firefox (default: "all") + --browser value, -b value available browsers: all|brave|chrome|chrome-beta|chromium|coccoc|edge|firefox|opera|opera-gx|vivaldi|yandex (default: "all") --results-dir value, --dir value export dir (default: "results") --format value, -f value file name csv|json (default: "csv") --profile-path value, -p value custom profile dir path, get with chrome://version - --help, -h show help (default: false) - --version, -v print the version (default: false) + --full-export, --full is export full browsing data (default: true) + --help, -h show help + --version, -v print the version -PS C:\test> .\hack-browser-data.exe -b all -f json --dir results -zip +PS C:\test> .\hack-browser-data.exe -b all -f json --dir results -zip [NOTICE] [browser.go:46,pickChromium] find browser Chrome success [NOTICE] [browser.go:46,pickChromium] find browser Microsoft Edge success [NOTICE] [browsingdata.go:59,Output] output to file results/microsoft_edge_download.json success diff --git a/browingdata/bookmark/bookmark.go b/browingdata/bookmark/bookmark.go index 89d8283..5bfc7ef 100644 --- a/browingdata/bookmark/bookmark.go +++ b/browingdata/bookmark/bookmark.go @@ -47,23 +47,25 @@ func (c *ChromiumBookmark) Parse(masterKey []byte) error { return nil } +const ( + bookmarkID = "id" + bookmarkAdded = "date_added" + bookmarkURL = "url" + bookmarkName = "name" + bookmarkType = "type" + bookmarkChildren = "children" +) + func getBookmarkChildren(value gjson.Result, w *ChromiumBookmark) (children gjson.Result) { - const ( - bookmarkID = "id" - bookmarkAdded = "date_added" - bookmarkURL = "url" - bookmarkName = "name" - bookmarkType = "type" - bookmarkChildren = "children" - ) nodeType := value.Get(bookmarkType) + children = value.Get(bookmarkChildren) + bm := bookmark{ ID: value.Get(bookmarkID).Int(), Name: value.Get(bookmarkName).String(), URL: value.Get(bookmarkURL).String(), DateAdded: typeutil.TimeEpoch(value.Get(bookmarkAdded).Int()), } - children = value.Get(bookmarkChildren) if nodeType.Exists() { bm.Type = nodeType.String() *w = append(*w, bm) @@ -76,20 +78,11 @@ func getBookmarkChildren(value gjson.Result, w *ChromiumBookmark) (children gjso return children } -func bookmarkType(a int64) string { - switch a { - case 1: - return "url" - default: - return "folder" - } -} - func (c *ChromiumBookmark) Name() string { return "bookmark" } -func (c *ChromiumBookmark) Length() int { +func (c *ChromiumBookmark) Len() int { return len(*c) } @@ -101,38 +94,33 @@ const ( ) func (f *FirefoxBookmark) Parse(masterKey []byte) error { - var ( - err error - keyDB *sql.DB - bookmarkRows *sql.Rows - ) - keyDB, err = sql.Open("sqlite3", item.TempFirefoxBookmark) + db, err := sql.Open("sqlite3", item.TempFirefoxBookmark) if err != nil { return err } defer os.Remove(item.TempFirefoxBookmark) - defer keyDB.Close() - _, err = keyDB.Exec(closeJournalMode) + defer db.Close() + _, err = db.Exec(closeJournalMode) if err != nil { log.Error(err) } - bookmarkRows, err = keyDB.Query(queryFirefoxBookMark) + rows, err := db.Query(queryFirefoxBookMark) if err != nil { return err } - defer bookmarkRows.Close() - for bookmarkRows.Next() { + defer rows.Close() + for rows.Next() { var ( - id, bType, dateAdded int64 - title, url string + id, bt, dateAdded int64 + title, url string ) - if err = bookmarkRows.Scan(&id, &url, &bType, &dateAdded, &title); err != nil { + if err = rows.Scan(&id, &url, &bt, &dateAdded, &title); err != nil { log.Warn(err) } *f = append(*f, bookmark{ ID: id, Name: title, - Type: bookmarkType(bType), + Type: linkType(bt), URL: url, DateAdded: typeutil.TimeStamp(dateAdded / 1000000), }) @@ -147,6 +135,15 @@ func (f *FirefoxBookmark) Name() string { return "bookmark" } -func (f *FirefoxBookmark) Length() int { +func (f *FirefoxBookmark) Len() int { return len(*f) } + +func linkType(a int64) string { + switch a { + case 1: + return "url" + default: + return "folder" + } +} diff --git a/browingdata/browsingdata.go b/browingdata/browsingdata.go index 3bec04d..db63e6c 100644 --- a/browingdata/browsingdata.go +++ b/browingdata/browsingdata.go @@ -25,7 +25,7 @@ type Source interface { Name() string - Length() int + Len() int } func New(items []item.Item) *Data { @@ -49,7 +49,7 @@ func (d *Data) Output(dir, browserName, flag string) { output := newOutPutter(flag) for _, source := range d.sources { - if source.Length() == 0 { + if source.Len() == 0 { // if the length of the export data is 0, then it is not necessary to output continue } diff --git a/browingdata/cookie/cookie.go b/browingdata/cookie/cookie.go index 53aa750..dc5ebbf 100644 --- a/browingdata/cookie/cookie.go +++ b/browingdata/cookie/cookie.go @@ -36,13 +36,13 @@ const ( ) func (c *ChromiumCookie) Parse(masterKey []byte) error { - cookieDB, err := sql.Open("sqlite3", item.TempChromiumCookie) + db, err := sql.Open("sqlite3", item.TempChromiumCookie) if err != nil { return err } defer os.Remove(item.TempChromiumCookie) - defer cookieDB.Close() - rows, err := cookieDB.Query(queryChromiumCookie) + defer db.Close() + rows, err := db.Query(queryChromiumCookie) if err != nil { return err } @@ -71,11 +71,10 @@ func (c *ChromiumCookie) Parse(masterKey []byte) error { ExpireDate: typeutil.TimeEpoch(expireDate), } if len(encryptValue) > 0 { - var err error - if masterKey == nil { + if len(masterKey) == 0 { value, err = crypto.DPAPI(encryptValue) } else { - value, err = crypto.Chromium(masterKey, encryptValue) + value, err = crypto.DecryptPass(masterKey, encryptValue) } if err != nil { log.Error(err) @@ -94,7 +93,7 @@ func (c *ChromiumCookie) Name() string { return "cookie" } -func (c *ChromiumCookie) Length() int { +func (c *ChromiumCookie) Len() int { return len(*c) } @@ -105,13 +104,14 @@ const ( ) func (f *FirefoxCookie) Parse(masterKey []byte) error { - cookieDB, err := sql.Open("sqlite3", item.TempFirefoxCookie) + db, err := sql.Open("sqlite3", item.TempFirefoxCookie) if err != nil { return err } defer os.Remove(item.TempFirefoxCookie) - defer cookieDB.Close() - rows, err := cookieDB.Query(queryFirefoxCookie) + defer db.Close() + + rows, err := db.Query(queryFirefoxCookie) if err != nil { return err } @@ -136,6 +136,10 @@ func (f *FirefoxCookie) Parse(masterKey []byte) error { Value: value, }) } + + sort.Slice(*f, func(i, j int) bool { + return (*f)[i].CreateDate.After((*f)[j].CreateDate) + }) return nil } @@ -143,6 +147,6 @@ func (f *FirefoxCookie) Name() string { return "cookie" } -func (f *FirefoxCookie) Length() int { +func (f *FirefoxCookie) Len() int { return len(*f) } diff --git a/browingdata/creditcard/creditcard.go b/browingdata/creditcard/creditcard.go index 48c9611..45c12e9 100644 --- a/browingdata/creditcard/creditcard.go +++ b/browingdata/creditcard/creditcard.go @@ -29,13 +29,14 @@ const ( ) func (c *ChromiumCreditCard) Parse(masterKey []byte) error { - creditDB, err := sql.Open("sqlite3", item.TempChromiumCreditCard) + db, err := sql.Open("sqlite3", item.TempChromiumCreditCard) if err != nil { return err } defer os.Remove(item.TempChromiumCreditCard) - defer creditDB.Close() - rows, err := creditDB.Query(queryChromiumCredit) + defer db.Close() + + rows, err := db.Query(queryChromiumCredit) if err != nil { return err } @@ -56,17 +57,17 @@ func (c *ChromiumCreditCard) Parse(masterKey []byte) error { Address: address, NickName: nickname, } - if masterKey == nil { - value, err = crypto.DPAPI(encryptValue) - if err != nil { - return err + if len(encryptValue) > 0 { + if len(masterKey) == 0 { + value, err = crypto.DPAPI(encryptValue) + } else { + value, err = crypto.DecryptPass(masterKey, encryptValue) } - } else { - value, err = crypto.Chromium(masterKey, encryptValue) if err != nil { - return err + log.Error(err) } } + ccInfo.CardNumber = string(value) *c = append(*c, ccInfo) } @@ -77,21 +78,20 @@ func (c *ChromiumCreditCard) Name() string { return "creditcard" } -func (c *ChromiumCreditCard) Length() int { +func (c *ChromiumCreditCard) Len() int { return len(*c) } type YandexCreditCard []card func (c *YandexCreditCard) Parse(masterKey []byte) error { - creditDB, err := sql.Open("sqlite3", item.TempYandexCreditCard) + db, err := sql.Open("sqlite3", item.TempYandexCreditCard) if err != nil { return err } defer os.Remove(item.TempYandexCreditCard) - defer creditDB.Close() - defer creditDB.Close() - rows, err := creditDB.Query(queryChromiumCredit) + defer db.Close() + rows, err := db.Query(queryChromiumCredit) if err != nil { return err } @@ -112,15 +112,14 @@ func (c *YandexCreditCard) Parse(masterKey []byte) error { Address: address, NickName: nickname, } - if masterKey == nil { - value, err = crypto.DPAPI(encryptValue) - if err != nil { - return err + if len(encryptValue) > 0 { + if len(masterKey) == 0 { + value, err = crypto.DPAPI(encryptValue) + } else { + value, err = crypto.DecryptPass(masterKey, encryptValue) } - } else { - value, err = crypto.Chromium(masterKey, encryptValue) if err != nil { - return err + log.Error(err) } } ccInfo.CardNumber = string(value) @@ -133,6 +132,6 @@ func (c *YandexCreditCard) Name() string { return "creditcard" } -func (c *YandexCreditCard) Length() int { +func (c *YandexCreditCard) Len() int { return len(*c) } diff --git a/browingdata/download/download.go b/browingdata/download/download.go index 4209677..fc7827a 100644 --- a/browingdata/download/download.go +++ b/browingdata/download/download.go @@ -32,13 +32,13 @@ const ( ) func (c *ChromiumDownload) Parse(masterKey []byte) error { - historyDB, err := sql.Open("sqlite3", item.TempChromiumDownload) + db, err := sql.Open("sqlite3", item.TempChromiumDownload) if err != nil { return err } defer os.Remove(item.TempChromiumDownload) - defer historyDB.Close() - rows, err := historyDB.Query(queryChromiumDownload) + defer db.Close() + rows, err := db.Query(queryChromiumDownload) if err != nil { return err } @@ -71,7 +71,7 @@ func (c *ChromiumDownload) Name() string { return "download" } -func (c *ChromiumDownload) Length() int { +func (c *ChromiumDownload) Len() int { return len(*c) } @@ -83,33 +83,28 @@ const ( ) func (f *FirefoxDownload) Parse(masterKey []byte) error { - var ( - err error - keyDB *sql.DB - downloadRows *sql.Rows - ) - keyDB, err = sql.Open("sqlite3", item.TempFirefoxDownload) + db, err := sql.Open("sqlite3", item.TempFirefoxDownload) if err != nil { return err } defer os.Remove(item.TempFirefoxDownload) - defer keyDB.Close() - _, err = keyDB.Exec(closeJournalMode) + defer db.Close() + + _, err = db.Exec(closeJournalMode) if err != nil { - return err + log.Error(err) } - defer keyDB.Close() - downloadRows, err = keyDB.Query(queryFirefoxDownload) + rows, err := db.Query(queryFirefoxDownload) if err != nil { return err } - defer downloadRows.Close() - for downloadRows.Next() { + defer rows.Close() + for rows.Next() { var ( content, url string placeID, dateAdded int64 ) - if err = downloadRows.Scan(&placeID, &content, &url, &dateAdded); err != nil { + if err = rows.Scan(&placeID, &content, &url, &dateAdded); err != nil { log.Warn(err) } contentList := strings.Split(content, ",{") @@ -137,6 +132,6 @@ func (f *FirefoxDownload) Name() string { return "download" } -func (f *FirefoxDownload) Length() int { +func (f *FirefoxDownload) Len() int { return len(*f) } diff --git a/browingdata/extension/extension.go b/browingdata/extension/extension.go index e3b06bb..fe05680 100644 --- a/browingdata/extension/extension.go +++ b/browingdata/extension/extension.go @@ -30,12 +30,12 @@ func (c *ChromiumExtension) Parse(masterKey []byte) error { } defer os.RemoveAll(item.TempChromiumExtension) for _, f := range files { - file, err := fileutil.ReadFile(f) + content, err := fileutil.ReadFile(f) if err != nil { - log.Error("Failed to read file: %s", err) + log.Error("Failed to read content: %s", err) continue } - b := gjson.Parse(file) + b := gjson.Parse(content) *c = append(*c, &extension{ Name: b.Get("name").String(), Description: b.Get("description").String(), @@ -50,7 +50,7 @@ func (c *ChromiumExtension) Name() string { return "extension" } -func (c *ChromiumExtension) Length() int { +func (c *ChromiumExtension) Len() int { return len(*c) } @@ -78,6 +78,6 @@ func (f *FirefoxExtension) Name() string { return "extension" } -func (f *FirefoxExtension) Length() int { +func (f *FirefoxExtension) Len() int { return len(*f) } diff --git a/browingdata/history/history.go b/browingdata/history/history.go index 619d05c..492786a 100644 --- a/browingdata/history/history.go +++ b/browingdata/history/history.go @@ -28,13 +28,14 @@ const ( ) func (c *ChromiumHistory) Parse(masterKey []byte) error { - historyDB, err := sql.Open("sqlite3", item.TempChromiumHistory) + db, err := sql.Open("sqlite3", item.TempChromiumHistory) if err != nil { return err } defer os.Remove(item.TempChromiumHistory) - defer historyDB.Close() - rows, err := historyDB.Query(queryChromiumHistory) + defer db.Close() + + rows, err := db.Query(queryChromiumHistory) if err != nil { return err } @@ -66,7 +67,7 @@ func (c *ChromiumHistory) Name() string { return "history" } -func (c *ChromiumHistory) Length() int { +func (c *ChromiumHistory) Len() int { return len(*c) } @@ -78,34 +79,30 @@ const ( ) func (f *FirefoxHistory) Parse(masterKey []byte) error { - var ( - err error - keyDB *sql.DB - historyRows *sql.Rows - ) - keyDB, err = sql.Open("sqlite3", item.TempFirefoxHistory) + db, err := sql.Open("sqlite3", item.TempFirefoxHistory) if err != nil { return err } defer os.Remove(item.TempFirefoxHistory) - defer keyDB.Close() - _, err = keyDB.Exec(closeJournalMode) + defer db.Close() + + _, err = db.Exec(closeJournalMode) if err != nil { return err } - defer keyDB.Close() - historyRows, err = keyDB.Query(queryFirefoxHistory) + defer db.Close() + rows, err := db.Query(queryFirefoxHistory) if err != nil { return err } - defer historyRows.Close() - for historyRows.Next() { + defer rows.Close() + for rows.Next() { var ( id, visitDate int64 url, title string visitCount int ) - if err = historyRows.Scan(&id, &url, &visitDate, &title, &visitCount); err != nil { + if err = rows.Scan(&id, &url, &visitDate, &title, &visitCount); err != nil { log.Warn(err) } *f = append(*f, history{ @@ -125,6 +122,6 @@ func (f *FirefoxHistory) Name() string { return "history" } -func (f *FirefoxHistory) Length() int { +func (f *FirefoxHistory) Len() int { return len(*f) } diff --git a/browingdata/localstorage/localstorage.go b/browingdata/localstorage/localstorage.go index 6f3521a..5158f92 100644 --- a/browingdata/localstorage/localstorage.go +++ b/browingdata/localstorage/localstorage.go @@ -29,7 +29,6 @@ func (c *ChromiumLocalStorage) Parse(masterKey []byte) error { return err } defer os.RemoveAll(item.TempChromiumLocalStorage) - // log.Info("parsing local storage now") defer db.Close() iter := db.NewIterator(nil, nil) @@ -58,7 +57,7 @@ func (c *ChromiumLocalStorage) Name() string { return "localStorage" } -func (c *ChromiumLocalStorage) Length() int { +func (c *ChromiumLocalStorage) Len() int { return len(*c) } @@ -102,16 +101,13 @@ func (f *FirefoxLocalStorage) Parse(masterKey []byte) error { if err != nil { return err } - if err != nil { - return err - } defer os.Remove(item.TempFirefoxLocalStorage) defer db.Close() + _, err = db.Exec(closeJournalMode) if err != nil { - return err + log.Error(err) } - defer db.Close() rows, err := db.Query(queryFirefoxHistory) if err != nil { return err @@ -147,6 +143,6 @@ func (f *FirefoxLocalStorage) Name() string { return "localStorage" } -func (f *FirefoxLocalStorage) Length() int { +func (f *FirefoxLocalStorage) Len() int { return len(*f) } diff --git a/browingdata/password/password.go b/browingdata/password/password.go index 6196c92..e56c528 100644 --- a/browingdata/password/password.go +++ b/browingdata/password/password.go @@ -34,13 +34,14 @@ const ( ) func (c *ChromiumPassword) Parse(masterKey []byte) error { - loginDB, err := sql.Open("sqlite3", item.TempChromiumPassword) + db, err := sql.Open("sqlite3", item.TempChromiumPassword) if err != nil { return err } defer os.Remove(item.TempChromiumPassword) - defer loginDB.Close() - rows, err := loginDB.Query(queryChromiumLogin) + defer db.Close() + + rows, err := db.Query(queryChromiumLogin) if err != nil { return err } @@ -61,11 +62,10 @@ func (c *ChromiumPassword) Parse(masterKey []byte) error { LoginURL: url, } if len(pwd) > 0 { - var err error - if masterKey == nil { + if len(masterKey) == 0 { password, err = crypto.DPAPI(pwd) } else { - password, err = crypto.Chromium(masterKey, pwd) + password, err = crypto.DecryptPass(masterKey, pwd) } if err != nil { log.Error(err) @@ -90,7 +90,7 @@ func (c *ChromiumPassword) Name() string { return "password" } -func (c *ChromiumPassword) Length() int { +func (c *ChromiumPassword) Len() int { return len(*c) } @@ -101,13 +101,14 @@ const ( ) func (c *YandexPassword) Parse(masterKey []byte) error { - loginDB, err := sql.Open("sqlite3", item.TempYandexPassword) + db, err := sql.Open("sqlite3", item.TempYandexPassword) if err != nil { return err } defer os.Remove(item.TempYandexPassword) - defer loginDB.Close() - rows, err := loginDB.Query(queryYandexLogin) + defer db.Close() + + rows, err := db.Query(queryYandexLogin) if err != nil { return err } @@ -129,11 +130,10 @@ func (c *YandexPassword) Parse(masterKey []byte) error { } if len(pwd) > 0 { - var err error - if masterKey == nil { + if len(masterKey) == 0 { password, err = crypto.DPAPI(pwd) } else { - password, err = crypto.Chromium(masterKey, pwd) + password, err = crypto.DecryptPass(masterKey, pwd) } if err != nil { log.Errorf("decrypt yandex password error %s", err) @@ -158,7 +158,7 @@ func (c *YandexPassword) Name() string { return "password" } -func (c *YandexPassword) Length() int { +func (c *YandexPassword) Len() int { return len(*c) } @@ -183,24 +183,25 @@ func (f *FirefoxPassword) Parse(masterKey []byte) error { if err != nil { return err } - keyLin := []byte{248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1} if bytes.Contains(k, []byte("password-check")) { - m := bytes.Compare(nssA102, keyLin) - if m == 0 { + keyLin := []byte{248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1} + if bytes.Compare(nssA102, keyLin) == 0 { nssPBE, err := crypto.NewASN1PBE(nssA11) if err != nil { return err } finallyKey, err := nssPBE.Decrypt(globalSalt, masterKey) - finallyKey = finallyKey[:24] if err != nil { return err } - allLogin, err := getFirefoxLoginData() + + finallyKey = finallyKey[:24] + logins, err := getFirefoxLoginData() if err != nil { return err } - for _, v := range allLogin { + + for _, v := range logins { userPBE, err := crypto.NewASN1PBE(v.encryptUser) if err != nil { return err @@ -233,8 +234,7 @@ func (f *FirefoxPassword) Parse(masterKey []byte) error { } func getFirefoxDecryptKey(key4file string) (item1, item2, a11, a102 []byte, err error) { - var keyDB *sql.DB - keyDB, err = sql.Open("sqlite3", key4file) + keyDB, err := sql.Open("sqlite3", key4file) if err != nil { return nil, nil, nil, nil, err } @@ -251,15 +251,16 @@ func getFirefoxDecryptKey(key4file string) (item1, item2, a11, a102 []byte, err return item1, item2, a11, a102, nil } -func getFirefoxLoginData() (l []loginData, err error) { +func getFirefoxLoginData() ([]loginData, error) { s, err := os.ReadFile(item.TempFirefoxPassword) if err != nil { return nil, err } defer os.Remove(item.TempFirefoxPassword) - h := gjson.GetBytes(s, "logins") - if h.Exists() { - for _, v := range h.Array() { + loginsJSON := gjson.GetBytes(s, "logins") + var logins []loginData + if loginsJSON.Exists() { + for _, v := range loginsJSON.Array() { var ( m loginData user []byte @@ -277,16 +278,16 @@ func getFirefoxLoginData() (l []loginData, err error) { m.encryptUser = user m.encryptPass = pass m.CreateDate = typeutil.TimeStamp(v.Get("timeCreated").Int() / 1000) - l = append(l, m) + logins = append(logins, m) } } - return l, nil + return logins, nil } func (f *FirefoxPassword) Name() string { return "password" } -func (f *FirefoxPassword) Length() int { +func (f *FirefoxPassword) Len() int { return len(*f) } diff --git a/crypto/crypto_darwin.go b/crypto/crypto_darwin.go index 0a84f1d..a4ec686 100644 --- a/crypto/crypto_darwin.go +++ b/crypto/crypto_darwin.go @@ -4,7 +4,7 @@ package crypto var iv = []byte{32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32} -func Chromium(key, encryptPass []byte) ([]byte, error) { +func DecryptPass(key, encryptPass []byte) ([]byte, error) { if len(encryptPass) <= 3 { return nil, errPasswordIsEmpty } diff --git a/crypto/crypto_linux.go b/crypto/crypto_linux.go index e9c6108..03e95bc 100644 --- a/crypto/crypto_linux.go +++ b/crypto/crypto_linux.go @@ -4,7 +4,7 @@ package crypto var iv = []byte{32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32} -func Chromium(key, encryptPass []byte) ([]byte, error) { +func DecryptPass(key, encryptPass []byte) ([]byte, error) { if len(encryptPass) < 3 { return nil, errPasswordIsEmpty } diff --git a/crypto/crypto_windows.go b/crypto/crypto_windows.go index ba4e1a8..c5e1b58 100644 --- a/crypto/crypto_windows.go +++ b/crypto/crypto_windows.go @@ -9,7 +9,7 @@ import ( "unsafe" ) -func Chromium(key, encryptPass []byte) ([]byte, error) { +func DecryptPass(key, encryptPass []byte) ([]byte, error) { if len(encryptPass) < 15 { return nil, errPasswordIsEmpty } @@ -17,7 +17,7 @@ func Chromium(key, encryptPass []byte) ([]byte, error) { return aesGCMDecrypt(encryptPass[15:], key, encryptPass[3:15]) } -func ChromiumForYandex(key, encryptPass []byte) ([]byte, error) { +func DecryptPassForYandex(key, encryptPass []byte) ([]byte, error) { if len(encryptPass) < 3 { return nil, errPasswordIsEmpty }