Merge pull request #202 from moonD4rk/feat/item-parse

refactor: format browsing data export
pull/209/head
ᴍᴏᴏɴD4ʀᴋ 2 years ago committed by GitHub
commit 5d18f27050
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 23
      README.md
  2. 24
      README_ZH.md
  3. 55
      browingdata/bookmark/bookmark.go
  4. 4
      browingdata/browsingdata.go
  5. 26
      browingdata/cookie/cookie.go
  6. 41
      browingdata/creditcard/creditcard.go
  7. 33
      browingdata/download/download.go
  8. 10
      browingdata/extension/extension.go
  9. 33
      browingdata/history/history.go
  10. 12
      browingdata/localstorage/localstorage.go
  11. 59
      browingdata/password/password.go
  12. 2
      crypto/crypto_darwin.go
  13. 2
      crypto/crypto_linux.go
  14. 4
      crypto/crypto_windows.go

@ -9,15 +9,15 @@
[中文说明](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 ## Supported Browser
### Windows ### Windows
| Browser | Password | Cookie | Bookmark | History | | Browser | Password | Cookie | Bookmark | History |
| :---------------------------------- | :------: | :----: | :------: | :-----: | |:-------------------|:--------:|:------:|:--------:|:-------:|
| Google Chrome | ✅ | ✅ | ✅ | ✅ | | Google Chrome | ✅ | ✅ | ✅ | ✅ |
| Google Chrome Beta | ✅ | ✅ | ✅ | ✅ | | Google Chrome Beta | ✅ | ✅ | ✅ | ✅ |
| Chromium | ✅ | ✅ | ✅ | ✅ | | Chromium | ✅ | ✅ | ✅ | ✅ |
@ -43,7 +43,7 @@
Based on Apple's security policy, some browsers **require a current user password** to decrypt. Based on Apple's security policy, some browsers **require a current user password** to decrypt.
| Browser | Password | Cookie | Bookmark | History | | Browser | Password | Cookie | Bookmark | History |
| :------- | :------: | :----: | :------: | :-----: | |:-------------------|:--------:|:------:|:--------:|:-------:|
| Google Chrome | ✅ | ✅ | ✅ | ✅ | | Google Chrome | ✅ | ✅ | ✅ | ✅ |
| Google Chrome Beta | ✅ | ✅ | ✅ | ✅ | | Google Chrome Beta | ✅ | ✅ | ✅ | ✅ |
| Chromium | ✅ | ✅ | ✅ | ✅ | | Chromium | ✅ | ✅ | ✅ | ✅ |
@ -64,7 +64,7 @@ Based on Apple's security policy, some browsers **require a current user passwor
### Linux ### Linux
| Browser | Password | Cookie | Bookmark | History | | Browser | Password | Cookie | Bookmark | History |
| :---- | :------: | :----: | :------: | :-----: | |:-------------------|:--------:|:------:|:--------:|:-------:|
| Google Chrome | ✅ | ✅ | ✅ | ✅ | | Google Chrome | ✅ | ✅ | ✅ | ✅ |
| Google Chrome Beta | ✅ | ✅ | ✅ | ✅ | | Google Chrome Beta | ✅ | ✅ | ✅ | ✅ |
| Chromium | ✅ | ✅ | ✅ | ✅ | | Chromium | ✅ | ✅ | ✅ | ✅ |
@ -133,15 +133,19 @@ USAGE:
Export all browingdata(password/cookie/history/bookmark) from browser Export all browingdata(password/cookie/history/bookmark) from browser
Github Link: https://github.com/moonD4rk/HackBrowserData Github Link: https://github.com/moonD4rk/HackBrowserData
VERSION:
0.5.0
GLOBAL OPTIONS: GLOBAL OPTIONS:
--verbose, --vv verbose (default: false) --verbose, --vv verbose (default: false)
--compress, --zip compress result to zip (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") --results-dir value, --dir value export dir (default: "results")
--format value, -f value file name csv|json (default: "csv") --format value, -f value file name csv|json (default: "csv")
--profile-path value, -p value custom profile dir path, get with chrome://version --profile-path value, -p value custom profile dir path, get with chrome://version
--help, -h show help (default: false) --full-export, --full is export full browsing data (default: true)
--version, -v print the version (default: false) --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
@ -163,8 +167,9 @@ PS C:\test> .\hack-browser-data.exe -b all -f json --dir results -zip
``` ```
### Run with custom browser profile folder ### 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_creditcard.csv success
[NOTICE] [browsingdata.go:59,Output] output to file results/chrome_bookmark.csv success [NOTICE] [browsingdata.go:59,Output] output to file results/chrome_bookmark.csv success

@ -15,11 +15,11 @@
### Windows ### Windows
| 浏览器 | 密码 | Cookie | 书签 | 历史记录 | | 浏览器 | 密码 | Cookie | 书签 | 历史记录 |
| :------- | :------: | :----: | :------: | :-----: | |:-------------------|:---:|:------:|:---:|:----:|
| Google Chrome| | ✅ | | | | Google Chrome | | ✅ | ✅ | ✅ |
| Google Chrome Beta| ✅ | ✅ | ✅ | ✅ | | Google Chrome Beta | ✅ | ✅ | ✅ | ✅ |
| Chromium | ✅ | ✅ | ✅ | ✅ | | Chromium | ✅ | ✅ | ✅ | ✅ |
| Microsoft Edge| | ✅ | | | | Microsoft Edge | | ✅ | ✅ | ✅ |
| 360 极速浏览器 | ✅ | ✅ | ✅ | ✅ | | 360 极速浏览器 | ✅ | ✅ | ✅ | ✅ |
| QQ | ✅ | ✅ | ✅ | ✅ | | QQ | ✅ | ✅ | ✅ | ✅ |
| Brave | ✅ | ✅ | ✅ | ✅ | | Brave | ✅ | ✅ | ✅ | ✅ |
@ -40,7 +40,7 @@
由于 MacOS 的安全性设置,基于 `Chromium` 内核浏览器解密时**需要当前用户密码** 由于 MacOS 的安全性设置,基于 `Chromium` 内核浏览器解密时**需要当前用户密码**
| 浏览器 | 密码 | Cookie | 书签 | 历史记录 | | 浏览器 | 密码 | Cookie | 书签 | 历史记录 |
| :--- | :------: | :----: | :------: | :-----: | |:-------------------|:---:|:------:|:---:|:----:|
| Google Chrome | ✅ | ✅ | ✅ | ✅ | | Google Chrome | ✅ | ✅ | ✅ | ✅ |
| Google Chrome Beta | ✅ | ✅ | ✅ | ✅ | | Google Chrome Beta | ✅ | ✅ | ✅ | ✅ |
| Chromium | ✅ | ✅ | ✅ | ✅ | | Chromium | ✅ | ✅ | ✅ | ✅ |
@ -56,12 +56,12 @@
| Firefox Dev | ✅ | ✅ | ✅ | ✅ | | Firefox Dev | ✅ | ✅ | ✅ | ✅ |
| Firefox ESR | ✅ | ✅ | ✅ | ✅ | | Firefox ESR | ✅ | ✅ | ✅ | ✅ |
| Firefox Nightly | ✅ | ✅ | ✅ | ✅ | | Firefox Nightly | ✅ | ✅ | ✅ | ✅ |
| Safari | || | | | Safari || | | |
### Linux ### Linux
| 浏览器 | 密码 | Cookie | 书签 | 历史记录 | | 浏览器 | 密码 | Cookie | 书签 | 历史记录 |
| :----- | :------: | :----: | :------: | :-----: | |:-------------------|:---:|:------:|:---:|:----:|
| Google Chrome | ✅ | ✅ | ✅ | ✅ | | Google Chrome | ✅ | ✅ | ✅ | ✅ |
| Google Chrome Beta | ✅ | ✅ | ✅ | ✅ | | Google Chrome Beta | ✅ | ✅ | ✅ | ✅ |
| Chromium | ✅ | ✅ | ✅ | ✅ | | Chromium | ✅ | ✅ | ✅ | ✅ |
@ -128,15 +128,19 @@ USAGE:
Export all browingdata(password/cookie/history/bookmark) from browser Export all browingdata(password/cookie/history/bookmark) from browser
Github Link: https://github.com/moonD4rk/HackBrowserData Github Link: https://github.com/moonD4rk/HackBrowserData
VERSION:
0.5.0
GLOBAL OPTIONS: GLOBAL OPTIONS:
--verbose, --vv verbose (default: false) --verbose, --vv verbose (default: false)
--compress, --zip compress result to zip (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") --results-dir value, --dir value export dir (default: "results")
--format value, -f value file name csv|json (default: "csv") --format value, -f value file name csv|json (default: "csv")
--profile-path value, -p value custom profile dir path, get with chrome://version --profile-path value, -p value custom profile dir path, get with chrome://version
--help, -h show help (default: false) --full-export, --full is export full browsing data (default: true)
--version, -v print the version (default: false) --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

@ -47,23 +47,25 @@ func (c *ChromiumBookmark) Parse(masterKey []byte) error {
return nil return nil
} }
func getBookmarkChildren(value gjson.Result, w *ChromiumBookmark) (children gjson.Result) { const (
const (
bookmarkID = "id" bookmarkID = "id"
bookmarkAdded = "date_added" bookmarkAdded = "date_added"
bookmarkURL = "url" bookmarkURL = "url"
bookmarkName = "name" bookmarkName = "name"
bookmarkType = "type" bookmarkType = "type"
bookmarkChildren = "children" bookmarkChildren = "children"
) )
func getBookmarkChildren(value gjson.Result, w *ChromiumBookmark) (children gjson.Result) {
nodeType := value.Get(bookmarkType) nodeType := value.Get(bookmarkType)
children = value.Get(bookmarkChildren)
bm := bookmark{ bm := bookmark{
ID: value.Get(bookmarkID).Int(), ID: value.Get(bookmarkID).Int(),
Name: value.Get(bookmarkName).String(), Name: value.Get(bookmarkName).String(),
URL: value.Get(bookmarkURL).String(), URL: value.Get(bookmarkURL).String(),
DateAdded: typeutil.TimeEpoch(value.Get(bookmarkAdded).Int()), DateAdded: typeutil.TimeEpoch(value.Get(bookmarkAdded).Int()),
} }
children = value.Get(bookmarkChildren)
if nodeType.Exists() { if nodeType.Exists() {
bm.Type = nodeType.String() bm.Type = nodeType.String()
*w = append(*w, bm) *w = append(*w, bm)
@ -76,20 +78,11 @@ func getBookmarkChildren(value gjson.Result, w *ChromiumBookmark) (children gjso
return children return children
} }
func bookmarkType(a int64) string {
switch a {
case 1:
return "url"
default:
return "folder"
}
}
func (c *ChromiumBookmark) Name() string { func (c *ChromiumBookmark) Name() string {
return "bookmark" return "bookmark"
} }
func (c *ChromiumBookmark) Length() int { func (c *ChromiumBookmark) Len() int {
return len(*c) return len(*c)
} }
@ -101,38 +94,33 @@ const (
) )
func (f *FirefoxBookmark) Parse(masterKey []byte) error { func (f *FirefoxBookmark) Parse(masterKey []byte) error {
var ( db, err := sql.Open("sqlite3", item.TempFirefoxBookmark)
err error
keyDB *sql.DB
bookmarkRows *sql.Rows
)
keyDB, err = sql.Open("sqlite3", item.TempFirefoxBookmark)
if err != nil { if err != nil {
return err return err
} }
defer os.Remove(item.TempFirefoxBookmark) defer os.Remove(item.TempFirefoxBookmark)
defer keyDB.Close() defer db.Close()
_, err = keyDB.Exec(closeJournalMode) _, err = db.Exec(closeJournalMode)
if err != nil { if err != nil {
log.Error(err) log.Error(err)
} }
bookmarkRows, err = keyDB.Query(queryFirefoxBookMark) rows, err := db.Query(queryFirefoxBookMark)
if err != nil { if err != nil {
return err return err
} }
defer bookmarkRows.Close() defer rows.Close()
for bookmarkRows.Next() { for rows.Next() {
var ( var (
id, bType, dateAdded int64 id, bt, dateAdded int64
title, url string 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) log.Warn(err)
} }
*f = append(*f, bookmark{ *f = append(*f, bookmark{
ID: id, ID: id,
Name: title, Name: title,
Type: bookmarkType(bType), Type: linkType(bt),
URL: url, URL: url,
DateAdded: typeutil.TimeStamp(dateAdded / 1000000), DateAdded: typeutil.TimeStamp(dateAdded / 1000000),
}) })
@ -147,6 +135,15 @@ func (f *FirefoxBookmark) Name() string {
return "bookmark" return "bookmark"
} }
func (f *FirefoxBookmark) Length() int { func (f *FirefoxBookmark) Len() int {
return len(*f) return len(*f)
} }
func linkType(a int64) string {
switch a {
case 1:
return "url"
default:
return "folder"
}
}

@ -25,7 +25,7 @@ type Source interface {
Name() string Name() string
Length() int Len() int
} }
func New(items []item.Item) *Data { func New(items []item.Item) *Data {
@ -49,7 +49,7 @@ func (d *Data) Output(dir, browserName, flag string) {
output := newOutPutter(flag) output := newOutPutter(flag)
for _, source := range d.sources { 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 // if the length of the export data is 0, then it is not necessary to output
continue continue
} }

@ -36,13 +36,13 @@ const (
) )
func (c *ChromiumCookie) Parse(masterKey []byte) error { func (c *ChromiumCookie) Parse(masterKey []byte) error {
cookieDB, err := sql.Open("sqlite3", item.TempChromiumCookie) db, err := sql.Open("sqlite3", item.TempChromiumCookie)
if err != nil { if err != nil {
return err return err
} }
defer os.Remove(item.TempChromiumCookie) defer os.Remove(item.TempChromiumCookie)
defer cookieDB.Close() defer db.Close()
rows, err := cookieDB.Query(queryChromiumCookie) rows, err := db.Query(queryChromiumCookie)
if err != nil { if err != nil {
return err return err
} }
@ -71,11 +71,10 @@ func (c *ChromiumCookie) Parse(masterKey []byte) error {
ExpireDate: typeutil.TimeEpoch(expireDate), ExpireDate: typeutil.TimeEpoch(expireDate),
} }
if len(encryptValue) > 0 { if len(encryptValue) > 0 {
var err error if len(masterKey) == 0 {
if masterKey == nil {
value, err = crypto.DPAPI(encryptValue) value, err = crypto.DPAPI(encryptValue)
} else { } else {
value, err = crypto.Chromium(masterKey, encryptValue) value, err = crypto.DecryptPass(masterKey, encryptValue)
} }
if err != nil { if err != nil {
log.Error(err) log.Error(err)
@ -94,7 +93,7 @@ func (c *ChromiumCookie) Name() string {
return "cookie" return "cookie"
} }
func (c *ChromiumCookie) Length() int { func (c *ChromiumCookie) Len() int {
return len(*c) return len(*c)
} }
@ -105,13 +104,14 @@ const (
) )
func (f *FirefoxCookie) Parse(masterKey []byte) error { func (f *FirefoxCookie) Parse(masterKey []byte) error {
cookieDB, err := sql.Open("sqlite3", item.TempFirefoxCookie) db, err := sql.Open("sqlite3", item.TempFirefoxCookie)
if err != nil { if err != nil {
return err return err
} }
defer os.Remove(item.TempFirefoxCookie) defer os.Remove(item.TempFirefoxCookie)
defer cookieDB.Close() defer db.Close()
rows, err := cookieDB.Query(queryFirefoxCookie)
rows, err := db.Query(queryFirefoxCookie)
if err != nil { if err != nil {
return err return err
} }
@ -136,6 +136,10 @@ func (f *FirefoxCookie) Parse(masterKey []byte) error {
Value: value, Value: value,
}) })
} }
sort.Slice(*f, func(i, j int) bool {
return (*f)[i].CreateDate.After((*f)[j].CreateDate)
})
return nil return nil
} }
@ -143,6 +147,6 @@ func (f *FirefoxCookie) Name() string {
return "cookie" return "cookie"
} }
func (f *FirefoxCookie) Length() int { func (f *FirefoxCookie) Len() int {
return len(*f) return len(*f)
} }

@ -29,13 +29,14 @@ const (
) )
func (c *ChromiumCreditCard) Parse(masterKey []byte) error { func (c *ChromiumCreditCard) Parse(masterKey []byte) error {
creditDB, err := sql.Open("sqlite3", item.TempChromiumCreditCard) db, err := sql.Open("sqlite3", item.TempChromiumCreditCard)
if err != nil { if err != nil {
return err return err
} }
defer os.Remove(item.TempChromiumCreditCard) defer os.Remove(item.TempChromiumCreditCard)
defer creditDB.Close() defer db.Close()
rows, err := creditDB.Query(queryChromiumCredit)
rows, err := db.Query(queryChromiumCredit)
if err != nil { if err != nil {
return err return err
} }
@ -56,17 +57,17 @@ func (c *ChromiumCreditCard) Parse(masterKey []byte) error {
Address: address, Address: address,
NickName: nickname, NickName: nickname,
} }
if masterKey == nil { if len(encryptValue) > 0 {
if len(masterKey) == 0 {
value, err = crypto.DPAPI(encryptValue) value, err = crypto.DPAPI(encryptValue)
if err != nil {
return err
}
} else { } else {
value, err = crypto.Chromium(masterKey, encryptValue) value, err = crypto.DecryptPass(masterKey, encryptValue)
}
if err != nil { if err != nil {
return err log.Error(err)
} }
} }
ccInfo.CardNumber = string(value) ccInfo.CardNumber = string(value)
*c = append(*c, ccInfo) *c = append(*c, ccInfo)
} }
@ -77,21 +78,20 @@ func (c *ChromiumCreditCard) Name() string {
return "creditcard" return "creditcard"
} }
func (c *ChromiumCreditCard) Length() int { func (c *ChromiumCreditCard) Len() int {
return len(*c) return len(*c)
} }
type YandexCreditCard []card type YandexCreditCard []card
func (c *YandexCreditCard) Parse(masterKey []byte) error { func (c *YandexCreditCard) Parse(masterKey []byte) error {
creditDB, err := sql.Open("sqlite3", item.TempYandexCreditCard) db, err := sql.Open("sqlite3", item.TempYandexCreditCard)
if err != nil { if err != nil {
return err return err
} }
defer os.Remove(item.TempYandexCreditCard) defer os.Remove(item.TempYandexCreditCard)
defer creditDB.Close() defer db.Close()
defer creditDB.Close() rows, err := db.Query(queryChromiumCredit)
rows, err := creditDB.Query(queryChromiumCredit)
if err != nil { if err != nil {
return err return err
} }
@ -112,15 +112,14 @@ func (c *YandexCreditCard) Parse(masterKey []byte) error {
Address: address, Address: address,
NickName: nickname, NickName: nickname,
} }
if masterKey == nil { if len(encryptValue) > 0 {
if len(masterKey) == 0 {
value, err = crypto.DPAPI(encryptValue) value, err = crypto.DPAPI(encryptValue)
if err != nil {
return err
}
} else { } else {
value, err = crypto.Chromium(masterKey, encryptValue) value, err = crypto.DecryptPass(masterKey, encryptValue)
}
if err != nil { if err != nil {
return err log.Error(err)
} }
} }
ccInfo.CardNumber = string(value) ccInfo.CardNumber = string(value)
@ -133,6 +132,6 @@ func (c *YandexCreditCard) Name() string {
return "creditcard" return "creditcard"
} }
func (c *YandexCreditCard) Length() int { func (c *YandexCreditCard) Len() int {
return len(*c) return len(*c)
} }

@ -32,13 +32,13 @@ const (
) )
func (c *ChromiumDownload) Parse(masterKey []byte) error { func (c *ChromiumDownload) Parse(masterKey []byte) error {
historyDB, err := sql.Open("sqlite3", item.TempChromiumDownload) db, err := sql.Open("sqlite3", item.TempChromiumDownload)
if err != nil { if err != nil {
return err return err
} }
defer os.Remove(item.TempChromiumDownload) defer os.Remove(item.TempChromiumDownload)
defer historyDB.Close() defer db.Close()
rows, err := historyDB.Query(queryChromiumDownload) rows, err := db.Query(queryChromiumDownload)
if err != nil { if err != nil {
return err return err
} }
@ -71,7 +71,7 @@ func (c *ChromiumDownload) Name() string {
return "download" return "download"
} }
func (c *ChromiumDownload) Length() int { func (c *ChromiumDownload) Len() int {
return len(*c) return len(*c)
} }
@ -83,33 +83,28 @@ const (
) )
func (f *FirefoxDownload) Parse(masterKey []byte) error { func (f *FirefoxDownload) Parse(masterKey []byte) error {
var ( db, err := sql.Open("sqlite3", item.TempFirefoxDownload)
err error
keyDB *sql.DB
downloadRows *sql.Rows
)
keyDB, err = sql.Open("sqlite3", item.TempFirefoxDownload)
if err != nil { if err != nil {
return err return err
} }
defer os.Remove(item.TempFirefoxDownload) defer os.Remove(item.TempFirefoxDownload)
defer keyDB.Close() defer db.Close()
_, err = keyDB.Exec(closeJournalMode)
_, err = db.Exec(closeJournalMode)
if err != nil { if err != nil {
return err log.Error(err)
} }
defer keyDB.Close() rows, err := db.Query(queryFirefoxDownload)
downloadRows, err = keyDB.Query(queryFirefoxDownload)
if err != nil { if err != nil {
return err return err
} }
defer downloadRows.Close() defer rows.Close()
for downloadRows.Next() { for rows.Next() {
var ( var (
content, url string content, url string
placeID, dateAdded int64 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) log.Warn(err)
} }
contentList := strings.Split(content, ",{") contentList := strings.Split(content, ",{")
@ -137,6 +132,6 @@ func (f *FirefoxDownload) Name() string {
return "download" return "download"
} }
func (f *FirefoxDownload) Length() int { func (f *FirefoxDownload) Len() int {
return len(*f) return len(*f)
} }

@ -30,12 +30,12 @@ func (c *ChromiumExtension) Parse(masterKey []byte) error {
} }
defer os.RemoveAll(item.TempChromiumExtension) defer os.RemoveAll(item.TempChromiumExtension)
for _, f := range files { for _, f := range files {
file, err := fileutil.ReadFile(f) content, err := fileutil.ReadFile(f)
if err != nil { if err != nil {
log.Error("Failed to read file: %s", err) log.Error("Failed to read content: %s", err)
continue continue
} }
b := gjson.Parse(file) b := gjson.Parse(content)
*c = append(*c, &extension{ *c = append(*c, &extension{
Name: b.Get("name").String(), Name: b.Get("name").String(),
Description: b.Get("description").String(), Description: b.Get("description").String(),
@ -50,7 +50,7 @@ func (c *ChromiumExtension) Name() string {
return "extension" return "extension"
} }
func (c *ChromiumExtension) Length() int { func (c *ChromiumExtension) Len() int {
return len(*c) return len(*c)
} }
@ -78,6 +78,6 @@ func (f *FirefoxExtension) Name() string {
return "extension" return "extension"
} }
func (f *FirefoxExtension) Length() int { func (f *FirefoxExtension) Len() int {
return len(*f) return len(*f)
} }

@ -28,13 +28,14 @@ const (
) )
func (c *ChromiumHistory) Parse(masterKey []byte) error { func (c *ChromiumHistory) Parse(masterKey []byte) error {
historyDB, err := sql.Open("sqlite3", item.TempChromiumHistory) db, err := sql.Open("sqlite3", item.TempChromiumHistory)
if err != nil { if err != nil {
return err return err
} }
defer os.Remove(item.TempChromiumHistory) defer os.Remove(item.TempChromiumHistory)
defer historyDB.Close() defer db.Close()
rows, err := historyDB.Query(queryChromiumHistory)
rows, err := db.Query(queryChromiumHistory)
if err != nil { if err != nil {
return err return err
} }
@ -66,7 +67,7 @@ func (c *ChromiumHistory) Name() string {
return "history" return "history"
} }
func (c *ChromiumHistory) Length() int { func (c *ChromiumHistory) Len() int {
return len(*c) return len(*c)
} }
@ -78,34 +79,30 @@ const (
) )
func (f *FirefoxHistory) Parse(masterKey []byte) error { func (f *FirefoxHistory) Parse(masterKey []byte) error {
var ( db, err := sql.Open("sqlite3", item.TempFirefoxHistory)
err error
keyDB *sql.DB
historyRows *sql.Rows
)
keyDB, err = sql.Open("sqlite3", item.TempFirefoxHistory)
if err != nil { if err != nil {
return err return err
} }
defer os.Remove(item.TempFirefoxHistory) defer os.Remove(item.TempFirefoxHistory)
defer keyDB.Close() defer db.Close()
_, err = keyDB.Exec(closeJournalMode)
_, err = db.Exec(closeJournalMode)
if err != nil { if err != nil {
return err return err
} }
defer keyDB.Close() defer db.Close()
historyRows, err = keyDB.Query(queryFirefoxHistory) rows, err := db.Query(queryFirefoxHistory)
if err != nil { if err != nil {
return err return err
} }
defer historyRows.Close() defer rows.Close()
for historyRows.Next() { for rows.Next() {
var ( var (
id, visitDate int64 id, visitDate int64
url, title string url, title string
visitCount int 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) log.Warn(err)
} }
*f = append(*f, history{ *f = append(*f, history{
@ -125,6 +122,6 @@ func (f *FirefoxHistory) Name() string {
return "history" return "history"
} }
func (f *FirefoxHistory) Length() int { func (f *FirefoxHistory) Len() int {
return len(*f) return len(*f)
} }

@ -29,7 +29,6 @@ func (c *ChromiumLocalStorage) Parse(masterKey []byte) error {
return err return err
} }
defer os.RemoveAll(item.TempChromiumLocalStorage) defer os.RemoveAll(item.TempChromiumLocalStorage)
// log.Info("parsing local storage now")
defer db.Close() defer db.Close()
iter := db.NewIterator(nil, nil) iter := db.NewIterator(nil, nil)
@ -58,7 +57,7 @@ func (c *ChromiumLocalStorage) Name() string {
return "localStorage" return "localStorage"
} }
func (c *ChromiumLocalStorage) Length() int { func (c *ChromiumLocalStorage) Len() int {
return len(*c) return len(*c)
} }
@ -102,16 +101,13 @@ func (f *FirefoxLocalStorage) Parse(masterKey []byte) error {
if err != nil { if err != nil {
return err return err
} }
if err != nil {
return err
}
defer os.Remove(item.TempFirefoxLocalStorage) defer os.Remove(item.TempFirefoxLocalStorage)
defer db.Close() defer db.Close()
_, err = db.Exec(closeJournalMode) _, err = db.Exec(closeJournalMode)
if err != nil { if err != nil {
return err log.Error(err)
} }
defer db.Close()
rows, err := db.Query(queryFirefoxHistory) rows, err := db.Query(queryFirefoxHistory)
if err != nil { if err != nil {
return err return err
@ -147,6 +143,6 @@ func (f *FirefoxLocalStorage) Name() string {
return "localStorage" return "localStorage"
} }
func (f *FirefoxLocalStorage) Length() int { func (f *FirefoxLocalStorage) Len() int {
return len(*f) return len(*f)
} }

@ -34,13 +34,14 @@ const (
) )
func (c *ChromiumPassword) Parse(masterKey []byte) error { func (c *ChromiumPassword) Parse(masterKey []byte) error {
loginDB, err := sql.Open("sqlite3", item.TempChromiumPassword) db, err := sql.Open("sqlite3", item.TempChromiumPassword)
if err != nil { if err != nil {
return err return err
} }
defer os.Remove(item.TempChromiumPassword) defer os.Remove(item.TempChromiumPassword)
defer loginDB.Close() defer db.Close()
rows, err := loginDB.Query(queryChromiumLogin)
rows, err := db.Query(queryChromiumLogin)
if err != nil { if err != nil {
return err return err
} }
@ -61,11 +62,10 @@ func (c *ChromiumPassword) Parse(masterKey []byte) error {
LoginURL: url, LoginURL: url,
} }
if len(pwd) > 0 { if len(pwd) > 0 {
var err error if len(masterKey) == 0 {
if masterKey == nil {
password, err = crypto.DPAPI(pwd) password, err = crypto.DPAPI(pwd)
} else { } else {
password, err = crypto.Chromium(masterKey, pwd) password, err = crypto.DecryptPass(masterKey, pwd)
} }
if err != nil { if err != nil {
log.Error(err) log.Error(err)
@ -90,7 +90,7 @@ func (c *ChromiumPassword) Name() string {
return "password" return "password"
} }
func (c *ChromiumPassword) Length() int { func (c *ChromiumPassword) Len() int {
return len(*c) return len(*c)
} }
@ -101,13 +101,14 @@ const (
) )
func (c *YandexPassword) Parse(masterKey []byte) error { func (c *YandexPassword) Parse(masterKey []byte) error {
loginDB, err := sql.Open("sqlite3", item.TempYandexPassword) db, err := sql.Open("sqlite3", item.TempYandexPassword)
if err != nil { if err != nil {
return err return err
} }
defer os.Remove(item.TempYandexPassword) defer os.Remove(item.TempYandexPassword)
defer loginDB.Close() defer db.Close()
rows, err := loginDB.Query(queryYandexLogin)
rows, err := db.Query(queryYandexLogin)
if err != nil { if err != nil {
return err return err
} }
@ -129,11 +130,10 @@ func (c *YandexPassword) Parse(masterKey []byte) error {
} }
if len(pwd) > 0 { if len(pwd) > 0 {
var err error if len(masterKey) == 0 {
if masterKey == nil {
password, err = crypto.DPAPI(pwd) password, err = crypto.DPAPI(pwd)
} else { } else {
password, err = crypto.Chromium(masterKey, pwd) password, err = crypto.DecryptPass(masterKey, pwd)
} }
if err != nil { if err != nil {
log.Errorf("decrypt yandex password error %s", err) log.Errorf("decrypt yandex password error %s", err)
@ -158,7 +158,7 @@ func (c *YandexPassword) Name() string {
return "password" return "password"
} }
func (c *YandexPassword) Length() int { func (c *YandexPassword) Len() int {
return len(*c) return len(*c)
} }
@ -183,24 +183,25 @@ func (f *FirefoxPassword) Parse(masterKey []byte) error {
if err != nil { if err != nil {
return err 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")) { if bytes.Contains(k, []byte("password-check")) {
m := bytes.Compare(nssA102, keyLin) keyLin := []byte{248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
if m == 0 { if bytes.Compare(nssA102, keyLin) == 0 {
nssPBE, err := crypto.NewASN1PBE(nssA11) nssPBE, err := crypto.NewASN1PBE(nssA11)
if err != nil { if err != nil {
return err return err
} }
finallyKey, err := nssPBE.Decrypt(globalSalt, masterKey) finallyKey, err := nssPBE.Decrypt(globalSalt, masterKey)
finallyKey = finallyKey[:24]
if err != nil { if err != nil {
return err return err
} }
allLogin, err := getFirefoxLoginData()
finallyKey = finallyKey[:24]
logins, err := getFirefoxLoginData()
if err != nil { if err != nil {
return err return err
} }
for _, v := range allLogin {
for _, v := range logins {
userPBE, err := crypto.NewASN1PBE(v.encryptUser) userPBE, err := crypto.NewASN1PBE(v.encryptUser)
if err != nil { if err != nil {
return err return err
@ -233,8 +234,7 @@ func (f *FirefoxPassword) Parse(masterKey []byte) error {
} }
func getFirefoxDecryptKey(key4file string) (item1, item2, a11, a102 []byte, err 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 { if err != nil {
return nil, nil, nil, nil, err 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 return item1, item2, a11, a102, nil
} }
func getFirefoxLoginData() (l []loginData, err error) { func getFirefoxLoginData() ([]loginData, error) {
s, err := os.ReadFile(item.TempFirefoxPassword) s, err := os.ReadFile(item.TempFirefoxPassword)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer os.Remove(item.TempFirefoxPassword) defer os.Remove(item.TempFirefoxPassword)
h := gjson.GetBytes(s, "logins") loginsJSON := gjson.GetBytes(s, "logins")
if h.Exists() { var logins []loginData
for _, v := range h.Array() { if loginsJSON.Exists() {
for _, v := range loginsJSON.Array() {
var ( var (
m loginData m loginData
user []byte user []byte
@ -277,16 +278,16 @@ func getFirefoxLoginData() (l []loginData, err error) {
m.encryptUser = user m.encryptUser = user
m.encryptPass = pass m.encryptPass = pass
m.CreateDate = typeutil.TimeStamp(v.Get("timeCreated").Int() / 1000) 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 { func (f *FirefoxPassword) Name() string {
return "password" return "password"
} }
func (f *FirefoxPassword) Length() int { func (f *FirefoxPassword) Len() int {
return len(*f) return len(*f)
} }

@ -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} 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 { if len(encryptPass) <= 3 {
return nil, errPasswordIsEmpty return nil, errPasswordIsEmpty
} }

@ -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} 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 { if len(encryptPass) < 3 {
return nil, errPasswordIsEmpty return nil, errPasswordIsEmpty
} }

@ -9,7 +9,7 @@ import (
"unsafe" "unsafe"
) )
func Chromium(key, encryptPass []byte) ([]byte, error) { func DecryptPass(key, encryptPass []byte) ([]byte, error) {
if len(encryptPass) < 15 { if len(encryptPass) < 15 {
return nil, errPasswordIsEmpty return nil, errPasswordIsEmpty
} }
@ -17,7 +17,7 @@ func Chromium(key, encryptPass []byte) ([]byte, error) {
return aesGCMDecrypt(encryptPass[15:], key, encryptPass[3:15]) 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 { if len(encryptPass) < 3 {
return nil, errPasswordIsEmpty return nil, errPasswordIsEmpty
} }

Loading…
Cancel
Save