From 13c92b0a2ed3a76ea98dcd6f378e09874bcfd7c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=B4=8D=E1=B4=8F=E1=B4=8F=C9=B4D4=CA=80=E1=B4=8B?= Date: Mon, 18 Apr 2022 00:38:40 +0800 Subject: [PATCH 1/4] fix: add block size check, Close #120 --- internal/decrypter/decrypter.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/internal/decrypter/decrypter.go b/internal/decrypter/decrypter.go index d93d58f..88b4081 100644 --- a/internal/decrypter/decrypter.go +++ b/internal/decrypter/decrypter.go @@ -179,14 +179,17 @@ func aes128CBCDecrypt(key, iv, encryptPass []byte) ([]byte, error) { dst := make([]byte, encryptLen) mode := cipher.NewCBCDecrypter(block, iv) mode.CryptBlocks(dst, encryptPass) - dst = PKCS5UnPadding(dst) + dst = pkcs5UnPadding(dst, block.BlockSize()) return dst, nil } -func PKCS5UnPadding(src []byte) []byte { - length := len(src) - unpad := int(src[length-1]) - return src[:(length - unpad)] +func pkcs5UnPadding(src []byte, blockSize int) []byte { + n := len(src) + paddingNum := int(src[n-1]) + if n < paddingNum || paddingNum > blockSize { + return src + } + return src[:n-paddingNum] } // des3Decrypt use for decrypter firefox PBE @@ -198,7 +201,7 @@ func des3Decrypt(key, iv []byte, src []byte) ([]byte, error) { blockMode := cipher.NewCBCDecrypter(block, iv) sq := make([]byte, len(src)) blockMode.CryptBlocks(sq, src) - return sq, nil + return pkcs5UnPadding(sq, block.BlockSize()), nil } func paddingZero(s []byte, l int) []byte { From 04e620e54c08bda5630a7e51881316ad63c6c1ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=B4=8D=E1=B4=8F=E1=B4=8F=C9=B4D4=CA=80=E1=B4=8B?= Date: Mon, 18 Apr 2022 00:47:39 +0800 Subject: [PATCH 2/4] refactor: output browsing data package --- cmd/hack-browser-data/main.go | 21 +++------------------ internal/browingdata/browsingdata.go | 25 ++++++++++++++++++++++++- internal/browingdata/creditcard.go | 14 ++++++++------ internal/browingdata/password.go | 4 ++-- internal/browser/browser.go | 4 ++-- internal/log/log.go | 2 +- internal/outputter/outputter.go | 18 +++++++++++++----- internal/utils/fileutil/filetutil.go | 5 +++++ 8 files changed, 58 insertions(+), 35 deletions(-) diff --git a/cmd/hack-browser-data/main.go b/cmd/hack-browser-data/main.go index b480958..5858317 100644 --- a/cmd/hack-browser-data/main.go +++ b/cmd/hack-browser-data/main.go @@ -1,13 +1,11 @@ package main import ( - "fmt" "os" "strings" "hack-browser-data/internal/browser" "hack-browser-data/internal/log" - "hack-browser-data/internal/outputter" "hack-browser-data/internal/utils/fileutil" "github.com/urfave/cli/v2" @@ -45,7 +43,7 @@ func Execute() { if verbose { log.Init("debug") } else { - log.Init("error") + log.Init("notice") } var ( browsers []browser.Browser @@ -56,29 +54,16 @@ func Execute() { if err != nil { log.Error(err) } - output := outputter.New(outputFormat) for _, b := range browsers { data, err := b.GetBrowsingData() if err != nil { log.Error(err) } - var f *os.File - for _, source := range data.Sources { - filename := fmt.Sprintf("%s_%s.%s", b.Name(), source.Name(), outputFormat) - f, err = output.CreateFile(outputDir, filename) - if err != nil { - log.Error(err) - } - err = output.Write(source, f) - if err != nil { - log.Error(err) - } - } + data.Output(outputDir, browserName, outputFormat) } if compress { - err = fileutil.CompressDir(outputDir) - if err != nil { + if err = fileutil.CompressDir(outputDir); err != nil { log.Error(err) } } diff --git a/internal/browingdata/browsingdata.go b/internal/browingdata/browsingdata.go index aeed250..81215f5 100644 --- a/internal/browingdata/browsingdata.go +++ b/internal/browingdata/browsingdata.go @@ -1,10 +1,13 @@ package browingdata import ( + "path" "time" "hack-browser-data/internal/item" "hack-browser-data/internal/log" + "hack-browser-data/internal/outputter" + "hack-browser-data/internal/utils/fileutil" ) type Data struct { @@ -35,6 +38,24 @@ func (d *Data) Recovery(masterKey []byte) error { return nil } +func (d *Data) Output(dir, browserName, output string) { + outputter := outputter.New(output) + + for _, source := range d.Sources { + + filename := fileutil.Filename(browserName, source.Name(), outputter.Ext()) + + f, err := outputter.CreateFile(dir, filename) + if err != nil { + log.Error(err) + } + if err := outputter.Write(source, f); err != nil { + log.Error(err) + } + log.Noticef("output to file %s success", path.Join(dir, filename)) + } +} + func (d *Data) addSource(Sources []item.Item) { for _, source := range Sources { switch source { @@ -69,7 +90,7 @@ func (d *Data) addSource(Sources []item.Item) { } const ( - queryChromiumCredit = `SELECT guid, name_on_card, expiration_month, expiration_year, card_number_encrypted FROM credit_cards` + queryChromiumCredit = `SELECT guid, name_on_card, expiration_month, expiration_year, card_number_encrypted, billing_address_id, nickname FROM credit_cards` queryChromiumLogin = `SELECT origin_url, username_value, password_value, date_created FROM logins` queryYandexLogin = `SELECT action_url, username_value, password_value, date_created FROM logins` queryChromiumHistory = `SELECT url, title, visit_count, last_visit_time FROM urls` @@ -126,5 +147,7 @@ type ( ExpirationYear string ExpirationMonth string CardNumber string + Address string + NickName string } ) diff --git a/internal/browingdata/creditcard.go b/internal/browingdata/creditcard.go index 8ac135e..44a5b02 100644 --- a/internal/browingdata/creditcard.go +++ b/internal/browingdata/creditcard.go @@ -27,17 +27,19 @@ func (c *ChromiumCreditCard) Parse(masterKey []byte) error { defer rows.Close() for rows.Next() { var ( - name, month, year, guid string - value, encryptValue []byte + name, month, year, guid, address, nickname string + value, encryptValue []byte ) - if err := rows.Scan(&guid, &name, &month, &year, &encryptValue); err != nil { + if err := rows.Scan(&guid, &name, &month, &year, &encryptValue, &address, &nickname); err != nil { log.Warn(err) } - creditCardInfo := card{ + ccInfo := card{ GUID: guid, Name: name, ExpirationMonth: month, ExpirationYear: year, + Address: address, + NickName: nickname, } if masterKey == nil { value, err = decrypter.DPApi(encryptValue) @@ -50,8 +52,8 @@ func (c *ChromiumCreditCard) Parse(masterKey []byte) error { return err } } - creditCardInfo.CardNumber = string(value) - *c = append(*c, creditCardInfo) + ccInfo.CardNumber = string(value) + *c = append(*c, ccInfo) } return nil } diff --git a/internal/browingdata/password.go b/internal/browingdata/password.go index d4b2110..ba5bf10 100644 --- a/internal/browingdata/password.go +++ b/internal/browingdata/password.go @@ -189,8 +189,8 @@ func (f *FirefoxPassword) Parse(masterKey []byte) error { } *f = append(*f, loginData{ LoginUrl: v.LoginUrl, - UserName: string(decrypter.PKCS5UnPadding(user)), - Password: string(decrypter.PKCS5UnPadding(pwd)), + UserName: string(user), + Password: string(pwd), CreateDate: v.CreateDate, }) } diff --git a/internal/browser/browser.go b/internal/browser/browser.go index 11ee860..4dac386 100644 --- a/internal/browser/browser.go +++ b/internal/browser/browser.go @@ -85,12 +85,12 @@ func pickFirefox(name, profile string) []Browser { } if multiFirefox, err := firefox.New(v.name, v.storage, profile, v.items); err == nil { for _, b := range multiFirefox { - log.Noticef("find browser: firefox %s success", b.Name()) + log.Noticef("find browser firefox %s success", b.Name()) browsers = append(browsers, b) } } else { if strings.Contains(err.Error(), "profile path is not exist") { - log.Noticef("find browser: firefox %s failed, profile path is not exist", v.name) + log.Noticef("find browser firefox %s failed, profile path is not exist", v.name) } else { log.Error(err) } diff --git a/internal/log/log.go b/internal/log/log.go index 09b302d..b775298 100644 --- a/internal/log/log.go +++ b/internal/log/log.go @@ -13,7 +13,7 @@ func Init(l string) { if l == "debug" { std = newStdLogger(slog.DebugLevel) } else { - std = newStdLogger(slog.ErrorLevel) + std = newStdLogger(slog.NoticeLevel) } } diff --git a/internal/outputter/outputter.go b/internal/outputter/outputter.go index 7548d7d..f74418b 100644 --- a/internal/outputter/outputter.go +++ b/internal/outputter/outputter.go @@ -13,13 +13,13 @@ import ( "hack-browser-data/internal/browingdata" ) -type outPutter struct { +type OutPutter struct { json bool csv bool } -func New(flag string) *outPutter { - o := &outPutter{} +func New(flag string) *OutPutter { + o := &OutPutter{} if flag == "json" { o.json = true } else { @@ -28,7 +28,7 @@ func New(flag string) *outPutter { return o } -func (o *outPutter) Write(data browingdata.Source, writer io.Writer) error { +func (o *OutPutter) Write(data browingdata.Source, writer io.Writer) error { switch o.json { case true: encoder := jsoniter.NewEncoder(writer) @@ -45,7 +45,7 @@ func (o *outPutter) Write(data browingdata.Source, writer io.Writer) error { } } -func (o *outPutter) CreateFile(dir, filename string) (*os.File, error) { +func (o *OutPutter) CreateFile(dir, filename string) (*os.File, error) { if filename == "" { return nil, errors.New("empty filename") } @@ -68,3 +68,11 @@ func (o *outPutter) CreateFile(dir, filename string) (*os.File, error) { } return file, nil } + +func (o *OutPutter) Ext() string { + if o.json { + return ".json" + } else { + return ".csv" + } +} diff --git a/internal/utils/fileutil/filetutil.go b/internal/utils/fileutil/filetutil.go index 6b7bf60..05957e1 100644 --- a/internal/utils/fileutil/filetutil.go +++ b/internal/utils/fileutil/filetutil.go @@ -8,6 +8,7 @@ import ( "os" "path" "path/filepath" + "strings" "hack-browser-data/internal/item" "hack-browser-data/internal/log" @@ -61,6 +62,10 @@ func CopyItemToLocal(itemPaths map[item.Item]string) error { return nil } +func Filename(browser, item, ext string) string { + return strings.ToLower(fmt.Sprintf("%s_%s.%s", browser, item, ext)) +} + func ParentDir(p string) string { return filepath.Dir(p) } From 6217ca3bed0e2ec565b8debecce704f9ef876f45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=B4=8D=E1=B4=8F=E1=B4=8F=C9=B4D4=CA=80=E1=B4=8B?= Date: Mon, 18 Apr 2022 02:07:31 +0800 Subject: [PATCH 3/4] docs: update readme to v0.4.0 --- README.md | 101 ++++++++---------- README_ZH.md | 74 ++++++------- .../browingdata/{ => bookmark}/bookmark.go | 0 internal/browingdata/{ => cookie}/cookie.go | 0 .../{ => creditcard}/creditcard.go | 0 .../browingdata/{ => download}/download.go | 0 .../outputter_test.go | 0 .../browingdata/{ => password}/password.go | 0 internal/outputter/outputter.go | 78 -------------- 9 files changed, 78 insertions(+), 175 deletions(-) rename internal/browingdata/{ => bookmark}/bookmark.go (100%) rename internal/browingdata/{ => cookie}/cookie.go (100%) rename internal/browingdata/{ => creditcard}/creditcard.go (100%) rename internal/browingdata/{ => download}/download.go (100%) rename internal/{outputter => browingdata}/outputter_test.go (100%) rename internal/browingdata/{ => password}/password.go (100%) delete mode 100644 internal/outputter/outputter.go diff --git a/README.md b/README.md index 41a8028..172c05b 100644 --- a/README.md +++ b/README.md @@ -47,13 +47,13 @@ Based on Apple's security policy, some browsers **require a current user passwor | Opera | ✅ | ✅ | ✅ | ✅ | | OperaGX | ✅ | ✅ | ✅ | ✅ | | Vivaldi | ✅ | ✅ | ✅ | ✅ | -| Yandex | ✅ | ✅ | ✅ | ✅ | | CocCoc | ✅ | ✅ | ✅ | ✅ | | Firefox | ✅ | ✅ | ✅ | ✅ | | Firefox Beta | ✅ | ✅ | ✅ | ✅ | | Firefox Dev | ✅ | ✅ | ✅ | ✅ | | Firefox ESR | ✅ | ✅ | ✅ | ✅ | | Firefox Nightly | ✅ | ✅ | ✅ | ✅ | +| Yandex | ✅ | ✅ | ✅ | ✅ | | Safari | ❌ | ❌ | ❌ | ❌ | ### Linux @@ -84,14 +84,14 @@ Installation of `HackBrowserData` is dead-simple, just download [the release for ### Building from source -support `go 1.14+` +only support `go 1.18+` with go generics ```bash -git clone https://github.com/moonD4rk/HackBrowserData +$ git clone https://github.com/moonD4rk/HackBrowserData -cd HackBrowserData +$ cd HackBrowserData/cmd/hack-browser-data -go build +$ CGO_ENABLED=1 go build ``` ### Cross compile @@ -125,70 +125,57 @@ NAME: USAGE: [hack-browser-data -b chrome -f json -dir results -cc] - Get all data(password/cookie/history/bookmark) from chrome + Export all browingdata(password/cookie/history/bookmark) from browser + Github Link: https://github.com/moonD4rk/HackBrowserData VERSION: - 0.3.7 + 0.4.0 + GLOBAL OPTIONS: - --verbose, --vv verbose (default: false) - --compress, --cc compress result to zip (default: false) - --browser value, -b value available browsers: all|opera|firefox|chrome|edge (default: "all") - --results-dir value, --dir value export dir (default: "results") - --format value, -f value format, csv|json|console (default: "csv") - --profile-dir-path value, -p value custom profile dir path, get with chrome://version - --key-file-path value, -k value custom key file path - --help, -h show help (default: false) - --version, -v print the version (default: false) - -PS C:\test> .\hack-browser-data.exe -b all -f json --dir results -cc -[x]: Get 44 cookies, filename is results/microsoft_edge_cookie.json -[x]: Get 54 history, filename is results/microsoft_edge_history.json -[x]: Get 1 passwords, filename is results/microsoft_edge_password.json -[x]: Get 4 bookmarks, filename is results/microsoft_edge_bookmark.json -[x]: Get 6 bookmarks, filename is results/360speed_bookmark.json -[x]: Get 19 cookies, filename is results/360speed_cookie.json -[x]: Get 18 history, filename is results/360speed_history.json -[x]: Get 1 passwords, filename is results/360speed_password.json -[x]: Get 12 history, filename is results/qq_history.json -[x]: Get 1 passwords, filename is results/qq_password.json -[x]: Get 12 bookmarks, filename is results/qq_bookmark.json -[x]: Get 14 cookies, filename is results/qq_cookie.json -[x]: Get 28 bookmarks, filename is results/firefox_bookmark.json -[x]: Get 10 cookies, filename is results/firefox_cookie.json -[x]: Get 33 history, filename is results/firefox_history.json -[x]: Get 1 passwords, filename is results/firefox_password.json -[x]: Get 1 passwords, filename is results/chrome_password.json -[x]: Get 4 bookmarks, filename is results/chrome_bookmark.json -[x]: Get 6 cookies, filename is results/chrome_cookie.json -[x]: Get 6 history, filename is results/chrome_history.json -[x]: Compress success, zip filename is results/archive.zip -``` -### Run with custom browser profile path + --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") + --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) + + +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 +[NOTICE] [browsingdata.go:59,Output] output to file results/microsoft_edge_password.json success +[NOTICE] [browsingdata.go:59,Output] output to file results/microsoft_edge_creditcard.json success +[NOTICE] [browsingdata.go:59,Output] output to file results/microsoft_edge_bookmark.json success +[NOTICE] [browsingdata.go:59,Output] output to file results/microsoft_edge_cookie.json success +[NOTICE] [browsingdata.go:59,Output] output to file results/microsoft_edge_history.json success +[NOTICE] [browsingdata.go:59,Output] output to file results/chrome_history.json success +[NOTICE] [browsingdata.go:59,Output] output to file results/chrome_download.json success +[NOTICE] [browsingdata.go:59,Output] output to file results/chrome_password.json success +[NOTICE] [browsingdata.go:59,Output] output to file results/chrome_creditcard.json success +[NOTICE] [browsingdata.go:59,Output] output to file results/chrome_bookmark.json success +[NOTICE] [browsingdata.go:59,Output] output to file results/chrome_cookie.json success ``` -PS C:\Users\User\Desktop> .\hack-browser-data.exe -b edge -p 'C:\Users\User\AppData\Local\Microsoft\Edge\User Data\Default' -k 'C:\Users\User\AppData\Local\Microsoft\Edge\User Data\Local State' +### Run with custom browser profile folder -[x]: Get 29 history, filename is results/microsoft_edge_history.csv -[x]: Get 0 passwords, filename is results/microsoft_edge_password.csv -[x]: Get 1 credit cards, filename is results/microsoft_edge_credit.csv -[x]: Get 4 bookmarks, filename is results/microsoft_edge_bookmark.csv -[x]: Get 54 cookies, filename is results/microsoft_edge_cookie.csv - - -PS C:\Users\User\Desktop> .\hack-browser-data.exe -b edge -p 'C:\Users\User\AppData\Local\Microsoft\Edge\User Data\Default' - -[x]: Get 1 credit cards, filename is results/microsoft_edge_credit.csv -[x]: Get 4 bookmarks, filename is results/microsoft_edge_bookmark.csv -[x]: Get 54 cookies, filename is results/microsoft_edge_cookie.csv -[x]: Get 29 history, filename is results/microsoft_edge_history.csv -[x]: Get 0 passwords, filename is results/microsoft_edge_password.csv +``` +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 +[NOTICE] [browsingdata.go:59,Output] output to file results/chrome_cookie.csv success +[NOTICE] [browsingdata.go:59,Output] output to file results/chrome_history.csv success +[NOTICE] [browsingdata.go:59,Output] output to file results/chrome_download.csv success +[NOTICE] [browsingdata.go:59,Output] output to file results/chrome_password.csv success ``` ### Some other projects based on HackBrowserData [Sharp-HackBrowserData](https://github.com/S3cur3Th1sSh1t/Sharp-HackBrowserData) [Reflective-HackBrowserData](https://github.com/idiotc4t/Reflective-HackBrowserData) -... ## Contributors diff --git a/README_ZH.md b/README_ZH.md index c12362b..1863d44 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -80,16 +80,14 @@ ### 从源码编译 -支持版本 `go 1.14+` +仅支持 `go 1.18+` 以后版本,一些函数使用到了泛型 ``` bash -git clone https://github.com/moonD4rk/HackBrowserData +$ git clone https://github.com/moonD4rk/HackBrowserData -cd HackBrowserData +$ cd HackBrowserData/cmd/hack-browser-data -go get -v -t -d ./... - -go build +$ CGO_ENABLED=1 go build ``` ### 跨平台编译 @@ -122,43 +120,39 @@ NAME: USAGE: [hack-browser-data -b chrome -f json -dir results -cc] - Get all data(password/cookie/history/bookmark) from chrome + Export all browingdata(password/cookie/history/bookmark) from browser + Github Link: https://github.com/moonD4rk/HackBrowserData VERSION: - 0.3.7 + 0.4.0 + GLOBAL OPTIONS: - --verbose, --vv verbose (default: false) - --compress, --cc compress result to zip (default: false) - --browser value, -b value available browsers: all|opera|firefox|chrome|edge (default: "all") - --results-dir value, --dir value export dir (default: "results") - --format value, -f value format, csv|json|console (default: "csv") - --profile-dir-path value, -p value custom profile dir path, get with chrome://version - --key-file-path value, -k value custom key file path - --help, -h show help (default: false) - --version, -v print the version (default: false) - -PS C:\test> .\hack-browser-data.exe -b all -f json --dir results --cc -[x]: Get 44 cookies, filename is results/microsoft_edge_cookie.json -[x]: Get 54 history, filename is results/microsoft_edge_history.json -[x]: Get 1 passwords, filename is results/microsoft_edge_password.json -[x]: Get 4 bookmarks, filename is results/microsoft_edge_bookmark.json -[x]: Get 6 bookmarks, filename is results/360speed_bookmark.json -[x]: Get 19 cookies, filename is results/360speed_cookie.json -[x]: Get 18 history, filename is results/360speed_history.json -[x]: Get 1 passwords, filename is results/360speed_password.json -[x]: Get 12 history, filename is results/qq_history.json -[x]: Get 1 passwords, filename is results/qq_password.json -[x]: Get 12 bookmarks, filename is results/qq_bookmark.json -[x]: Get 14 cookies, filename is results/qq_cookie.json -[x]: Get 28 bookmarks, filename is results/firefox_bookmark.json -[x]: Get 10 cookies, filename is results/firefox_cookie.json -[x]: Get 33 history, filename is results/firefox_history.json -[x]: Get 1 passwords, filename is results/firefox_password.json -[x]: Get 1 passwords, filename is results/chrome_password.json -[x]: Get 4 bookmarks, filename is results/chrome_bookmark.json -[x]: Get 6 cookies, filename is results/chrome_cookie.json -[x]: Get 6 history, filename is results/chrome_history.json -[x]: Compress success, zip filename is results/archive.zip + --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") + --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) + + +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 +[NOTICE] [browsingdata.go:59,Output] output to file results/microsoft_edge_password.json success +[NOTICE] [browsingdata.go:59,Output] output to file results/microsoft_edge_creditcard.json success +[NOTICE] [browsingdata.go:59,Output] output to file results/microsoft_edge_bookmark.json success +[NOTICE] [browsingdata.go:59,Output] output to file results/microsoft_edge_cookie.json success +[NOTICE] [browsingdata.go:59,Output] output to file results/microsoft_edge_history.json success +[NOTICE] [browsingdata.go:59,Output] output to file results/chrome_history.json success +[NOTICE] [browsingdata.go:59,Output] output to file results/chrome_download.json success +[NOTICE] [browsingdata.go:59,Output] output to file results/chrome_password.json success +[NOTICE] [browsingdata.go:59,Output] output to file results/chrome_creditcard.json success +[NOTICE] [browsingdata.go:59,Output] output to file results/chrome_bookmark.json success +[NOTICE] [browsingdata.go:59,Output] output to file results/chrome_cookie.json success + ``` ### 基于此工具的一些其他项目 diff --git a/internal/browingdata/bookmark.go b/internal/browingdata/bookmark/bookmark.go similarity index 100% rename from internal/browingdata/bookmark.go rename to internal/browingdata/bookmark/bookmark.go diff --git a/internal/browingdata/cookie.go b/internal/browingdata/cookie/cookie.go similarity index 100% rename from internal/browingdata/cookie.go rename to internal/browingdata/cookie/cookie.go diff --git a/internal/browingdata/creditcard.go b/internal/browingdata/creditcard/creditcard.go similarity index 100% rename from internal/browingdata/creditcard.go rename to internal/browingdata/creditcard/creditcard.go diff --git a/internal/browingdata/download.go b/internal/browingdata/download/download.go similarity index 100% rename from internal/browingdata/download.go rename to internal/browingdata/download/download.go diff --git a/internal/outputter/outputter_test.go b/internal/browingdata/outputter_test.go similarity index 100% rename from internal/outputter/outputter_test.go rename to internal/browingdata/outputter_test.go diff --git a/internal/browingdata/password.go b/internal/browingdata/password/password.go similarity index 100% rename from internal/browingdata/password.go rename to internal/browingdata/password/password.go diff --git a/internal/outputter/outputter.go b/internal/outputter/outputter.go deleted file mode 100644 index f74418b..0000000 --- a/internal/outputter/outputter.go +++ /dev/null @@ -1,78 +0,0 @@ -package outputter - -import ( - "encoding/csv" - "errors" - "io" - "os" - "path/filepath" - - "github.com/gocarina/gocsv" - jsoniter "github.com/json-iterator/go" - - "hack-browser-data/internal/browingdata" -) - -type OutPutter struct { - json bool - csv bool -} - -func New(flag string) *OutPutter { - o := &OutPutter{} - if flag == "json" { - o.json = true - } else { - o.csv = true - } - return o -} - -func (o *OutPutter) Write(data browingdata.Source, writer io.Writer) error { - switch o.json { - case true: - encoder := jsoniter.NewEncoder(writer) - encoder.SetIndent(" ", " ") - encoder.SetEscapeHTML(false) - return encoder.Encode(data) - default: - gocsv.SetCSVWriter(func(w io.Writer) *gocsv.SafeCSVWriter { - writer := csv.NewWriter(w) - writer.Comma = ',' - return gocsv.NewSafeCSVWriter(writer) - }) - return gocsv.Marshal(data, writer) - } -} - -func (o *OutPutter) CreateFile(dir, filename string) (*os.File, error) { - if filename == "" { - return nil, errors.New("empty filename") - } - - if dir != "" { - if _, err := os.Stat(dir); os.IsNotExist(err) { - err := os.MkdirAll(dir, 0777) - if err != nil { - return nil, err - } - } - } - - var file *os.File - var err error - p := filepath.Join(dir, filename) - file, err = os.OpenFile(p, os.O_TRUNC|os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) - if err != nil { - return nil, err - } - return file, nil -} - -func (o *OutPutter) Ext() string { - if o.json { - return ".json" - } else { - return ".csv" - } -} From aa3326f1a3071ce788d32939caa5f87b0056f395 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=B4=8D=E1=B4=8F=E1=B4=8F=C9=B4D4=CA=80=E1=B4=8B?= Date: Mon, 18 Apr 2022 02:11:33 +0800 Subject: [PATCH 4/4] feat: update to v0.4.0, based by generics --- cmd/hack-browser-data/main.go | 10 +- internal/browingdata/bookmark/bookmark.go | 7 +- internal/browingdata/browsingdata.go | 107 ++++-------------- internal/browingdata/cookie/cookie.go | 25 +++- internal/browingdata/creditcard/creditcard.go | 31 +++-- internal/browingdata/download/download.go | 21 +++- internal/browingdata/{ => history}/history.go | 19 +++- internal/browingdata/outputter.go | 76 +++++++++++++ internal/browingdata/outputter_test.go | 4 +- internal/browingdata/password/password.go | 24 +++- internal/browser/browser.go | 32 +++--- internal/browser/chromium/chromium.go | 6 +- internal/browser/chromium/chromium_linux.go | 4 +- internal/browser/firefox/firefox.go | 10 +- internal/log/log.go | 2 +- internal/utils/fileutil/filetutil.go | 9 +- 16 files changed, 252 insertions(+), 135 deletions(-) rename internal/browingdata/{ => history}/history.go (84%) create mode 100644 internal/browingdata/outputter.go diff --git a/cmd/hack-browser-data/main.go b/cmd/hack-browser-data/main.go index 5858317..5ab77f3 100644 --- a/cmd/hack-browser-data/main.go +++ b/cmd/hack-browser-data/main.go @@ -28,14 +28,14 @@ func Execute() { app := &cli.App{ Name: "hack-browser-data", Usage: "Export passwords/cookies/history/bookmarks from browser", - UsageText: "[hack-browser-data -b chrome -f json -dir results -cc]\nGet all browingdata(password/cookie/history/bookmark) from browser", + UsageText: "[hack-browser-data -b chrome -f json -dir results -cc]\nExport all browingdata(password/cookie/history/bookmark) from browser\nGithub Link: https://github.com/moonD4rk/HackBrowserData", Version: "0.4.0", Flags: []cli.Flag{ &cli.BoolFlag{Name: "verbose", Aliases: []string{"vv"}, Destination: &verbose, Value: false, Usage: "verbose"}, - &cli.BoolFlag{Name: "compress", Aliases: []string{"cc"}, Destination: &compress, Value: false, Usage: "compress result to zip"}, + &cli.BoolFlag{Name: "compress", Aliases: []string{"zip"}, Destination: &compress, Value: false, Usage: "compress result to zip"}, &cli.StringFlag{Name: "browser", Aliases: []string{"b"}, Destination: &browserName, Value: "all", Usage: "available browsers: all|" + strings.Join(browser.ListBrowser(), "|")}, &cli.StringFlag{Name: "results-dir", Aliases: []string{"dir"}, Destination: &outputDir, Value: "results", Usage: "export dir"}, - &cli.StringFlag{Name: "format", Aliases: []string{"f"}, Destination: &outputFormat, Value: "csv", Usage: "format, csv|json|console"}, + &cli.StringFlag{Name: "format", Aliases: []string{"f"}, Destination: &outputFormat, Value: "csv", Usage: "file name csv|json"}, &cli.StringFlag{Name: "profile-path", Aliases: []string{"p"}, Destination: &profilePath, Value: "", Usage: "custom profile dir path, get with chrome://version"}, }, HideHelpCommand: true, @@ -56,11 +56,11 @@ func Execute() { } for _, b := range browsers { - data, err := b.GetBrowsingData() + data, err := b.BrowsingData() if err != nil { log.Error(err) } - data.Output(outputDir, browserName, outputFormat) + data.Output(outputDir, b.Name(), outputFormat) } if compress { if err = fileutil.CompressDir(outputDir); err != nil { diff --git a/internal/browingdata/bookmark/bookmark.go b/internal/browingdata/bookmark/bookmark.go index ec2a17c..2a79058 100644 --- a/internal/browingdata/bookmark/bookmark.go +++ b/internal/browingdata/bookmark/bookmark.go @@ -1,4 +1,4 @@ -package browingdata +package bookmark import ( "database/sql" @@ -82,6 +82,11 @@ func (c *ChromiumBookmark) Name() string { type FirefoxBookmark []bookmark +const ( + queryFirefoxBookMark = `SELECT id, url, type, dateAdded, title FROM (SELECT * FROM moz_bookmarks INNER JOIN moz_places ON moz_bookmarks.fk=moz_places.id)` + closeJournalMode = `PRAGMA journal_mode=off` +) + func (f *FirefoxBookmark) Parse(masterKey []byte) error { var ( err error diff --git a/internal/browingdata/browsingdata.go b/internal/browingdata/browsingdata.go index 81215f5..adf8128 100644 --- a/internal/browingdata/browsingdata.go +++ b/internal/browingdata/browsingdata.go @@ -2,11 +2,15 @@ package browingdata import ( "path" - "time" + "hack-browser-data/internal/browingdata/bookmark" + "hack-browser-data/internal/browingdata/cookie" + "hack-browser-data/internal/browingdata/creditcard" + "hack-browser-data/internal/browingdata/download" + "hack-browser-data/internal/browingdata/history" + "hack-browser-data/internal/browingdata/password" "hack-browser-data/internal/item" "hack-browser-data/internal/log" - "hack-browser-data/internal/outputter" "hack-browser-data/internal/utils/fileutil" ) @@ -38,18 +42,18 @@ func (d *Data) Recovery(masterKey []byte) error { return nil } -func (d *Data) Output(dir, browserName, output string) { - outputter := outputter.New(output) +func (d *Data) Output(dir, browserName, flag string) { + output := NewOutPutter(flag) for _, source := range d.Sources { - filename := fileutil.Filename(browserName, source.Name(), outputter.Ext()) + filename := fileutil.Filename(browserName, source.Name(), output.Ext()) - f, err := outputter.CreateFile(dir, filename) + f, err := output.CreateFile(dir, filename) if err != nil { log.Error(err) } - if err := outputter.Write(source, f); err != nil { + if err := output.Write(source, f); err != nil { log.Error(err) } log.Noticef("output to file %s success", path.Join(dir, filename)) @@ -60,94 +64,31 @@ func (d *Data) addSource(Sources []item.Item) { for _, source := range Sources { switch source { case item.ChromiumPassword: - d.Sources[source] = &ChromiumPassword{} + d.Sources[source] = &password.ChromiumPassword{} case item.ChromiumCookie: - d.Sources[source] = &ChromiumCookie{} + d.Sources[source] = &cookie.ChromiumCookie{} case item.ChromiumBookmark: - d.Sources[source] = &ChromiumBookmark{} + d.Sources[source] = &bookmark.ChromiumBookmark{} case item.ChromiumHistory: - d.Sources[source] = &ChromiumHistory{} + d.Sources[source] = &history.ChromiumHistory{} case item.ChromiumDownload: - d.Sources[source] = &ChromiumDownload{} + d.Sources[source] = &download.ChromiumDownload{} case item.ChromiumCreditCard: - d.Sources[source] = &ChromiumCreditCard{} + d.Sources[source] = &creditcard.ChromiumCreditCard{} case item.YandexPassword: - d.Sources[source] = &YandexPassword{} + d.Sources[source] = &password.YandexPassword{} case item.YandexCreditCard: - d.Sources[source] = &YandexCreditCard{} + d.Sources[source] = &creditcard.YandexCreditCard{} case item.FirefoxPassword: - d.Sources[source] = &FirefoxPassword{} + d.Sources[source] = &password.FirefoxPassword{} case item.FirefoxCookie: - d.Sources[source] = &FirefoxCookie{} + d.Sources[source] = &cookie.FirefoxCookie{} case item.FirefoxBookmark: - d.Sources[source] = &FirefoxBookmark{} + d.Sources[source] = &bookmark.FirefoxBookmark{} case item.FirefoxHistory: - d.Sources[source] = &FirefoxHistory{} + d.Sources[source] = &history.FirefoxHistory{} case item.FirefoxDownload: - d.Sources[source] = &FirefoxDownload{} + d.Sources[source] = &download.FirefoxDownload{} } } } - -const ( - queryChromiumCredit = `SELECT guid, name_on_card, expiration_month, expiration_year, card_number_encrypted, billing_address_id, nickname FROM credit_cards` - queryChromiumLogin = `SELECT origin_url, username_value, password_value, date_created FROM logins` - queryYandexLogin = `SELECT action_url, username_value, password_value, date_created FROM logins` - queryChromiumHistory = `SELECT url, title, visit_count, last_visit_time FROM urls` - queryChromiumDownload = `SELECT target_path, tab_url, total_bytes, start_time, end_time, mime_type FROM downloads` - queryChromiumCookie = `SELECT name, encrypted_value, host_key, path, creation_utc, expires_utc, is_secure, is_httponly, has_expires, is_persistent FROM cookies` - queryFirefoxHistory = `SELECT id, url, last_visit_date, title, visit_count FROM moz_places where title not null` - queryFirefoxDownload = `SELECT place_id, GROUP_CONCAT(content), url, dateAdded FROM (SELECT * FROM moz_annos INNER JOIN moz_places ON moz_annos.place_id=moz_places.id) t GROUP BY place_id` - queryFirefoxBookMark = `SELECT id, url, type, dateAdded, title FROM (SELECT * FROM moz_bookmarks INNER JOIN moz_places ON moz_bookmarks.fk=moz_places.id)` - queryFirefoxCookie = `SELECT name, value, host, path, creationTime, expiry, isSecure, isHttpOnly FROM moz_cookies` - queryMetaData = `SELECT item1, item2 FROM metaData WHERE id = 'password'` - queryNssPrivate = `SELECT a11, a102 from nssPrivate` - closeJournalMode = `PRAGMA journal_mode=off` -) - -type ( - loginData struct { - UserName string - encryptPass []byte - encryptUser []byte - Password string - LoginUrl string - CreateDate time.Time - } - cookie struct { - Host string - Path string - KeyName string - encryptValue []byte - Value string - IsSecure bool - IsHTTPOnly bool - HasExpire bool - IsPersistent bool - CreateDate time.Time - ExpireDate time.Time - } - history struct { - Title string - Url string - VisitCount int - LastVisitTime time.Time - } - download struct { - TargetPath string - Url string - TotalBytes int64 - StartTime time.Time - EndTime time.Time - MimeType string - } - card struct { - GUID string - Name string - ExpirationYear string - ExpirationMonth string - CardNumber string - Address string - NickName string - } -) diff --git a/internal/browingdata/cookie/cookie.go b/internal/browingdata/cookie/cookie.go index 8ea4252..08aca0a 100644 --- a/internal/browingdata/cookie/cookie.go +++ b/internal/browingdata/cookie/cookie.go @@ -1,9 +1,10 @@ -package browingdata +package cookie import ( "database/sql" "os" "sort" + "time" _ "github.com/mattn/go-sqlite3" @@ -15,6 +16,24 @@ import ( type ChromiumCookie []cookie +type cookie struct { + Host string + Path string + KeyName string + encryptValue []byte + Value string + IsSecure bool + IsHTTPOnly bool + HasExpire bool + IsPersistent bool + CreateDate time.Time + ExpireDate time.Time +} + +const ( + queryChromiumCookie = `SELECT name, encrypted_value, host_key, path, creation_utc, expires_utc, is_secure, is_httponly, has_expires, is_persistent FROM cookies` +) + func (c *ChromiumCookie) Parse(masterKey []byte) error { cookieDB, err := sql.Open("sqlite3", item.TempChromiumCookie) if err != nil { @@ -77,6 +96,10 @@ func (c *ChromiumCookie) Name() string { type FirefoxCookie []cookie +const ( + queryFirefoxCookie = `SELECT name, value, host, path, creationTime, expiry, isSecure, isHttpOnly FROM moz_cookies` +) + func (f *FirefoxCookie) Parse(masterKey []byte) error { cookieDB, err := sql.Open("sqlite3", item.TempFirefoxCookie) if err != nil { diff --git a/internal/browingdata/creditcard/creditcard.go b/internal/browingdata/creditcard/creditcard.go index 44a5b02..3580f11 100644 --- a/internal/browingdata/creditcard/creditcard.go +++ b/internal/browingdata/creditcard/creditcard.go @@ -1,4 +1,4 @@ -package browingdata +package creditcard import ( "database/sql" @@ -13,6 +13,20 @@ import ( type ChromiumCreditCard []card +type card struct { + GUID string + Name string + ExpirationYear string + ExpirationMonth string + CardNumber string + Address string + NickName string +} + +const ( + queryChromiumCredit = `SELECT guid, name_on_card, expiration_month, expiration_year, card_number_encrypted, billing_address_id, nickname FROM credit_cards` +) + func (c *ChromiumCreditCard) Parse(masterKey []byte) error { creditDB, err := sql.Open("sqlite3", item.TempChromiumCreditCard) if err != nil { @@ -70,6 +84,7 @@ func (c *YandexCreditCard) Parse(masterKey []byte) error { } defer os.Remove(item.TempYandexCreditCard) defer creditDB.Close() + defer creditDB.Close() rows, err := creditDB.Query(queryChromiumCredit) if err != nil { return err @@ -77,17 +92,19 @@ func (c *YandexCreditCard) Parse(masterKey []byte) error { defer rows.Close() for rows.Next() { var ( - name, month, year, guid string - value, encryptValue []byte + name, month, year, guid, address, nickname string + value, encryptValue []byte ) - if err := rows.Scan(&guid, &name, &month, &year, &encryptValue); err != nil { + if err := rows.Scan(&guid, &name, &month, &year, &encryptValue, &address, &nickname); err != nil { log.Warn(err) } - creditCardInfo := card{ + ccInfo := card{ GUID: guid, Name: name, ExpirationMonth: month, ExpirationYear: year, + Address: address, + NickName: nickname, } if masterKey == nil { value, err = decrypter.DPApi(encryptValue) @@ -100,8 +117,8 @@ func (c *YandexCreditCard) Parse(masterKey []byte) error { return err } } - creditCardInfo.CardNumber = string(value) - *c = append(*c, creditCardInfo) + ccInfo.CardNumber = string(value) + *c = append(*c, ccInfo) } return nil } diff --git a/internal/browingdata/download/download.go b/internal/browingdata/download/download.go index 8761bd8..ae7a939 100644 --- a/internal/browingdata/download/download.go +++ b/internal/browingdata/download/download.go @@ -1,10 +1,11 @@ -package browingdata +package download import ( "database/sql" "os" "sort" "strings" + "time" "hack-browser-data/internal/item" "hack-browser-data/internal/log" @@ -16,6 +17,19 @@ import ( type ChromiumDownload []download +type download struct { + TargetPath string + Url string + TotalBytes int64 + StartTime time.Time + EndTime time.Time + MimeType string +} + +const ( + queryChromiumDownload = `SELECT target_path, tab_url, total_bytes, start_time, end_time, mime_type FROM downloads` +) + func (c *ChromiumDownload) Parse(masterKey []byte) error { historyDB, err := sql.Open("sqlite3", item.TempChromiumDownload) if err != nil { @@ -58,6 +72,11 @@ func (c *ChromiumDownload) Name() string { type FirefoxDownload []download +const ( + queryFirefoxDownload = `SELECT place_id, GROUP_CONCAT(content), url, dateAdded FROM (SELECT * FROM moz_annos INNER JOIN moz_places ON moz_annos.place_id=moz_places.id) t GROUP BY place_id` + closeJournalMode = `PRAGMA journal_mode=off` +) + func (f *FirefoxDownload) Parse(masterKey []byte) error { var ( err error diff --git a/internal/browingdata/history.go b/internal/browingdata/history/history.go similarity index 84% rename from internal/browingdata/history.go rename to internal/browingdata/history/history.go index c7fb322..c1f5aa7 100644 --- a/internal/browingdata/history.go +++ b/internal/browingdata/history/history.go @@ -1,9 +1,10 @@ -package browingdata +package history import ( "database/sql" "os" "sort" + "time" _ "github.com/mattn/go-sqlite3" @@ -14,6 +15,17 @@ import ( type ChromiumHistory []history +type history struct { + Title string + Url string + VisitCount int + LastVisitTime time.Time +} + +const ( + queryChromiumHistory = `SELECT url, title, visit_count, last_visit_time FROM urls` +) + func (c *ChromiumHistory) Parse(masterKey []byte) error { historyDB, err := sql.Open("sqlite3", item.TempChromiumHistory) if err != nil { @@ -56,6 +68,11 @@ func (c *ChromiumHistory) Name() string { type FirefoxHistory []history +const ( + queryFirefoxHistory = `SELECT id, url, last_visit_date, title, visit_count FROM moz_places where title not null` + closeJournalMode = `PRAGMA journal_mode=off` +) + func (f *FirefoxHistory) Parse(masterKey []byte) error { var ( err error diff --git a/internal/browingdata/outputter.go b/internal/browingdata/outputter.go new file mode 100644 index 0000000..d87ffef --- /dev/null +++ b/internal/browingdata/outputter.go @@ -0,0 +1,76 @@ +package browingdata + +import ( + "encoding/csv" + "errors" + "io" + "os" + "path/filepath" + + "github.com/gocarina/gocsv" + jsoniter "github.com/json-iterator/go" +) + +type OutPutter struct { + json bool + csv bool +} + +func NewOutPutter(flag string) *OutPutter { + o := &OutPutter{} + if flag == "json" { + o.json = true + } else { + o.csv = true + } + return o +} + +func (o *OutPutter) Write(data Source, writer io.Writer) error { + switch o.json { + case true: + encoder := jsoniter.NewEncoder(writer) + encoder.SetIndent(" ", " ") + encoder.SetEscapeHTML(false) + return encoder.Encode(data) + default: + gocsv.SetCSVWriter(func(w io.Writer) *gocsv.SafeCSVWriter { + writer := csv.NewWriter(w) + writer.Comma = ',' + return gocsv.NewSafeCSVWriter(writer) + }) + return gocsv.Marshal(data, writer) + } +} + +func (o *OutPutter) CreateFile(dir, filename string) (*os.File, error) { + if filename == "" { + return nil, errors.New("empty filename") + } + + if dir != "" { + if _, err := os.Stat(dir); os.IsNotExist(err) { + err := os.MkdirAll(dir, 0777) + if err != nil { + return nil, err + } + } + } + + var file *os.File + var err error + p := filepath.Join(dir, filename) + file, err = os.OpenFile(p, os.O_TRUNC|os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) + if err != nil { + return nil, err + } + return file, nil +} + +func (o *OutPutter) Ext() string { + if o.json { + return "json" + } else { + return "csv" + } +} diff --git a/internal/browingdata/outputter_test.go b/internal/browingdata/outputter_test.go index e0785c4..83f8361 100644 --- a/internal/browingdata/outputter_test.go +++ b/internal/browingdata/outputter_test.go @@ -1,4 +1,4 @@ -package outputter +package browingdata import ( "os" @@ -6,7 +6,7 @@ import ( ) func TestNewOutPutter(t *testing.T) { - out := New("json") + out := NewOutPutter("json") if out == nil { t.Error("New() returned nil") } diff --git a/internal/browingdata/password/password.go b/internal/browingdata/password/password.go index ba5bf10..dc264b6 100644 --- a/internal/browingdata/password/password.go +++ b/internal/browingdata/password/password.go @@ -1,4 +1,4 @@ -package browingdata +package password import ( "bytes" @@ -20,6 +20,19 @@ import ( type ChromiumPassword []loginData +type loginData struct { + UserName string + encryptPass []byte + encryptUser []byte + Password string + LoginUrl string + CreateDate time.Time +} + +const ( + queryChromiumLogin = `SELECT origin_url, username_value, password_value, date_created FROM logins` +) + func (c *ChromiumPassword) Parse(masterKey []byte) error { loginDB, err := sql.Open("sqlite3", item.TempChromiumPassword) if err != nil { @@ -79,6 +92,10 @@ func (c *ChromiumPassword) Name() string { type YandexPassword []loginData +const ( + queryYandexLogin = `SELECT action_url, username_value, password_value, date_created FROM logins` +) + func (c *YandexPassword) Parse(masterKey []byte) error { loginDB, err := sql.Open("sqlite3", item.TempYandexPassword) if err != nil { @@ -139,6 +156,11 @@ func (c *YandexPassword) Name() string { type FirefoxPassword []loginData +const ( + queryMetaData = `SELECT item1, item2 FROM metaData WHERE id = 'password'` + queryNssPrivate = `SELECT a11, a102 from nssPrivate` +) + func (f *FirefoxPassword) Parse(masterKey []byte) error { globalSalt, metaBytes, nssA11, nssA102, err := getFirefoxDecryptKey(item.TempFirefoxKey4) if err != nil { diff --git a/internal/browser/browser.go b/internal/browser/browser.go index 4dac386..badecd3 100644 --- a/internal/browser/browser.go +++ b/internal/browser/browser.go @@ -9,14 +9,14 @@ import ( "hack-browser-data/internal/browser/firefox" "hack-browser-data/internal/log" "hack-browser-data/internal/utils/fileutil" + "hack-browser-data/internal/utils/typeutil" ) type Browser interface { + // Name is browser's name Name() string - - GetMasterKey() ([]byte, error) - // GetBrowsingData returns the browsing data for the browser. - GetBrowsingData() (*browingdata.Data, error) + // BrowsingData returns all browsing data in the browser. + BrowsingData() (*browingdata.Data, error) } func PickBrowser(name, profile string) ([]Browser, error) { @@ -47,11 +47,11 @@ func pickChromium(name, profile string) []Browser { browsers = append(browsers, b) } else { // TODO: show which browser find failed - if strings.Contains(err.Error(), "profile path is not exist") { - log.Infof("find browser %s failed, profile path is not exist", v.name) + if strings.Contains(err.Error(), "profile folder is not exist") { + log.Errorf("find browser %s failed, profile folder is not exist, maybe not installed", v.name) continue } else { - log.Error("new chromium error:", err) + log.Errorf("new chromium error:", err) } } } @@ -62,10 +62,10 @@ func pickChromium(name, profile string) []Browser { } b, err := chromium.New(c.name, c.storage, profile, c.items) if err != nil { - if strings.Contains(err.Error(), "profile path is not exist") { - log.Infof("find browser %s failed, profile path is not exist", c.name) + if strings.Contains(err.Error(), "profile folder is not exist") { + log.Fatalf("find browser %s failed, profile folder is not exist, maybe not installed", c.name) } else { - log.Error("new chromium error:", err) + log.Fatalf("new chromium error:", err) } } browsers = append(browsers, b) @@ -89,8 +89,8 @@ func pickFirefox(name, profile string) []Browser { browsers = append(browsers, b) } } else { - if strings.Contains(err.Error(), "profile path is not exist") { - log.Noticef("find browser firefox %s failed, profile path is not exist", v.name) + if strings.Contains(err.Error(), "profile folder is not exist") { + log.Errorf("find browser firefox %s failed, profile folder is not exist", v.name) } else { log.Error(err) } @@ -104,12 +104,8 @@ func pickFirefox(name, profile string) []Browser { func ListBrowser() []string { var l []string - for c := range chromiumList { - l = append(l, c) - } - for f := range firefoxList { - l = append(l, f) - } + l = append(l, typeutil.Keys(chromiumList)...) + l = append(l, typeutil.Keys(firefoxList)...) return l } diff --git a/internal/browser/chromium/chromium.go b/internal/browser/chromium/chromium.go index 135a6d1..3ffe53c 100644 --- a/internal/browser/chromium/chromium.go +++ b/internal/browser/chromium/chromium.go @@ -30,7 +30,7 @@ func New(name, storage, profilePath string, items []item.Item) (*chromium, error } // TODO: Handle file path is not exist if !fileutil.FolderExists(profilePath) { - return nil, fmt.Errorf("%s profile path is not exist: %s", name, profilePath) + return nil, fmt.Errorf("%s profile folder is not exist: %s", name, profilePath) } itemsPaths, err := c.getItemPath(profilePath, items) if err != nil { @@ -46,7 +46,7 @@ func (c *chromium) Name() string { return c.name } -func (c *chromium) GetBrowsingData() (*browingdata.Data, error) { +func (c *chromium) BrowsingData() (*browingdata.Data, error) { b := browingdata.New(c.items) if err := c.copyItemToLocal(); err != nil { @@ -72,7 +72,7 @@ func (c *chromium) copyItemToLocal() error { // TODO: Handle read file error d, err := ioutil.ReadFile(path) if err != nil { - fmt.Println(err.Error()) + return err } err = ioutil.WriteFile(filename, d, 0777) if err != nil { diff --git a/internal/browser/chromium/chromium_linux.go b/internal/browser/chromium/chromium_linux.go index 6af3a81..76419a9 100644 --- a/internal/browser/chromium/chromium_linux.go +++ b/internal/browser/chromium/chromium_linux.go @@ -2,6 +2,7 @@ package chromium import ( "crypto/sha1" + "errors" "os" "github.com/godbus/dbus/v5" @@ -49,8 +50,7 @@ func (c *chromium) GetMasterKey() ([]byte, error) { if label == c.storage { se, err := i.GetSecret(session.Path()) if err != nil { - log.Error(err) - return nil, err + return nil, errors.New("get storage from dbus error:" + err.Error()) } chromiumSecret = se.Value } diff --git a/internal/browser/firefox/firefox.go b/internal/browser/firefox/firefox.go index eea438a..4c15107 100644 --- a/internal/browser/firefox/firefox.go +++ b/internal/browser/firefox/firefox.go @@ -26,7 +26,7 @@ type firefox struct { // New returns a new firefox instance. func New(name, storage, profilePath string, items []item.Item) ([]*firefox, error) { if !fileutil.FolderExists(profilePath) { - return nil, fmt.Errorf("%s profile path is not exist: %s", name, profilePath) + return nil, fmt.Errorf("%s profile folder is not exist: %s", name, profilePath) } f := &firefox{ name: name, @@ -36,7 +36,7 @@ func New(name, storage, profilePath string, items []item.Item) ([]*firefox, erro } multiItemPaths, err := f.getMultiItemPath(f.profilePath, f.items) if err != nil { - if strings.Contains(err.Error(), "profile path is not exist") { + if strings.Contains(err.Error(), "profile folder is not exist") { log.Error(err) return nil, nil } @@ -45,7 +45,7 @@ func New(name, storage, profilePath string, items []item.Item) ([]*firefox, erro var firefoxList []*firefox for name, itemPaths := range multiItemPaths { firefoxList = append(firefoxList, &firefox{ - name: name, + name: fmt.Sprintf("firefox-%s", name), items: typeutil.Keys(itemPaths), itemPaths: itemPaths, }) @@ -66,7 +66,7 @@ func (f *firefox) copyItemToLocal() error { // TODO: Handle read file error d, err := ioutil.ReadFile(path) if err != nil { - fmt.Println(err.Error()) + return err } err = ioutil.WriteFile(filename, d, 0777) if err != nil { @@ -100,7 +100,7 @@ func (f *firefox) Name() string { return f.name } -func (f *firefox) GetBrowsingData() (*browingdata.Data, error) { +func (f *firefox) BrowsingData() (*browingdata.Data, error) { b := browingdata.New(f.items) if err := f.copyItemToLocal(); err != nil { diff --git a/internal/log/log.go b/internal/log/log.go index b775298..b5bbd0b 100644 --- a/internal/log/log.go +++ b/internal/log/log.go @@ -17,7 +17,7 @@ func Init(l string) { } } -const template = "hack-browser-data [{{level}}] [{{caller}}] {{message}} {{data}} {{extra}}\n" +const template = "[{{level}}] [{{caller}}] {{message}} {{data}} {{extra}}\n" // NewStdLogger instance func newStdLogger(level slog.Level) *slog.SugaredLogger { diff --git a/internal/utils/fileutil/filetutil.go b/internal/utils/fileutil/filetutil.go index 05957e1..e2681a0 100644 --- a/internal/utils/fileutil/filetutil.go +++ b/internal/utils/fileutil/filetutil.go @@ -52,7 +52,7 @@ func CopyItemToLocal(itemPaths map[item.Item]string) error { // TODO: Handle read file error d, err := ioutil.ReadFile(p) if err != nil { - fmt.Println(err.Error()) + log.Error(err.Error()) } err = ioutil.WriteFile(filename, d, 0777) if err != nil { @@ -63,7 +63,8 @@ func CopyItemToLocal(itemPaths map[item.Item]string) error { } func Filename(browser, item, ext string) string { - return strings.ToLower(fmt.Sprintf("%s_%s.%s", browser, item, ext)) + replace := strings.NewReplacer(" ", "_", ".", "_", "-", "_") + return strings.ToLower(fmt.Sprintf("%s_%s.%s", replace.Replace(browser), item, ext)) } func ParentDir(p string) string { @@ -106,7 +107,7 @@ func CompressDir(dir string) error { if err := zw.Close(); err != nil { return err } - filename := filepath.Join(dir, "archive.zip") + filename := filepath.Join(dir, fmt.Sprintf("%s.zip", dir)) outFile, err := os.Create(filename) if err != nil { return err @@ -115,6 +116,6 @@ func CompressDir(dir string) error { if err != nil { return err } - log.Debugf("Compress success, zip filename is %s", filename) + log.Noticef("compress success, zip filename is %s", filename) return nil }