diff --git a/cmd/hack-browser-data/main.go b/cmd/hack-browser-data/main.go index bfc53fc..0b1ea46 100644 --- a/cmd/hack-browser-data/main.go +++ b/cmd/hack-browser-data/main.go @@ -29,7 +29,7 @@ func Execute() { Name: "hack-browser-data", Usage: "Export passwords/cookies/history/bookmarks 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.2", + Version: "0.4.3", Flags: []cli.Flag{ &cli.BoolFlag{Name: "verbose", Aliases: []string{"vv"}, Destination: &verbose, Value: false, Usage: "verbose"}, &cli.BoolFlag{Name: "compress", Aliases: []string{"zip"}, Destination: &compress, Value: false, Usage: "compress result to zip"}, diff --git a/internal/browingdata/browsingdata.go b/internal/browingdata/browsingdata.go index 01024a4..356706c 100644 --- a/internal/browingdata/browsingdata.go +++ b/internal/browingdata/browsingdata.go @@ -35,7 +35,6 @@ func New(sources []item.Item) *Data { } func (d *Data) Recovery(masterKey []byte) error { - for _, source := range d.sources { if err := source.Parse(masterKey); err != nil { log.Errorf("parse %s error %s", source.Name(), err.Error()) @@ -48,7 +47,6 @@ func (d *Data) Output(dir, browserName, flag string) { output := NewOutPutter(flag) for _, source := range d.sources { - filename := fileutil.Filename(browserName, source.Name(), output.Ext()) f, err := output.CreateFile(dir, filename) diff --git a/internal/browingdata/creditcard/creditcard.go b/internal/browingdata/creditcard/creditcard.go index 75eeee5..fb772ad 100644 --- a/internal/browingdata/creditcard/creditcard.go +++ b/internal/browingdata/creditcard/creditcard.go @@ -71,6 +71,7 @@ func (c *ChromiumCreditCard) Parse(masterKey []byte) error { } return nil } + func (c *ChromiumCreditCard) Name() string { return "creditcard" } @@ -122,6 +123,7 @@ func (c *YandexCreditCard) Parse(masterKey []byte) error { } return nil } + func (c *YandexCreditCard) Name() string { return "creditcard" } diff --git a/internal/browingdata/localstorage/localstorage.go b/internal/browingdata/localstorage/localstorage.go index c129d24..dd34e28 100644 --- a/internal/browingdata/localstorage/localstorage.go +++ b/internal/browingdata/localstorage/localstorage.go @@ -40,7 +40,7 @@ func (c *ChromiumLocalStorage) Parse(masterKey []byte) error { if len(value) > 1024*5 { continue } - var s = new(storage) + s := new(storage) s.fillKey(key) s.fillValue(value) // don't save meta data @@ -114,13 +114,11 @@ func (f *FirefoxLocalStorage) Parse(masterKey []byte) error { } defer rows.Close() for rows.Next() { - var ( - originKey, key, value string - ) + var originKey, key, value string if err = rows.Scan(&originKey, &key, &value); err != nil { log.Warn(err) } - var s = new(storage) + s := new(storage) s.fillFirefox(originKey, key, value) *f = append(*f, *s) } diff --git a/internal/browingdata/outputter.go b/internal/browingdata/outputter.go index d87ffef..3d80beb 100644 --- a/internal/browingdata/outputter.go +++ b/internal/browingdata/outputter.go @@ -50,7 +50,7 @@ func (o *OutPutter) CreateFile(dir, filename string) (*os.File, error) { if dir != "" { if _, err := os.Stat(dir); os.IsNotExist(err) { - err := os.MkdirAll(dir, 0777) + err := os.MkdirAll(dir, 0o777) if err != nil { return nil, err } @@ -60,7 +60,7 @@ func (o *OutPutter) CreateFile(dir, filename string) (*os.File, error) { 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) + file, err = os.OpenFile(p, os.O_TRUNC|os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o666) if err != nil { return nil, err } diff --git a/internal/browingdata/password/password.go b/internal/browingdata/password/password.go index e79b9de..14c049f 100644 --- a/internal/browingdata/password/password.go +++ b/internal/browingdata/password/password.go @@ -229,9 +229,7 @@ func (f *FirefoxPassword) Name() string { } func getFirefoxDecryptKey(key4file string) (item1, item2, a11, a102 []byte, err error) { - var ( - keyDB *sql.DB - ) + var keyDB *sql.DB keyDB, err = sql.Open("sqlite3", key4file) if err != nil { return nil, nil, nil, nil, err diff --git a/internal/browser/browser.go b/internal/browser/browser.go index 0cc1b8d..bec0c37 100644 --- a/internal/browser/browser.go +++ b/internal/browser/browser.go @@ -46,9 +46,12 @@ func pickChromium(name, profile string) []Browser { log.Noticef("find browser %s failed, profile folder does not exist", v.name) continue } - if b, err := chromium.New(v.name, v.storage, v.profilePath, v.items); err == nil { - log.Noticef("find browser %s success", b.Name()) - browsers = append(browsers, b) + if multiChromium, err := chromium.New(v.name, v.storage, v.profilePath, v.items); err == nil { + log.Noticef("find browser %s success", v.name) + for _, b := range multiChromium { + log.Noticef("find browser %s success", b.Name()) + browsers = append(browsers, b) + } } else { log.Errorf("new chromium error: %s", err.Error()) } @@ -61,12 +64,14 @@ func pickChromium(name, profile string) []Browser { if !fileutil.FolderExists(filepath.Clean(profile)) { log.Fatalf("find browser %s failed, profile folder does not exist", c.name) } - b, err := chromium.New(c.name, c.storage, profile, c.items) + chromiumList, err := chromium.New(c.name, c.storage, profile, c.items) if err != nil { - log.Fatalf("new chromium error:", err) + log.Fatalf("new chromium error: %s", err) + } + for _, b := range chromiumList { + log.Noticef("find browser %s success", b.Name()) + browsers = append(browsers, b) } - log.Noticef("find browser %s success", b.Name()) - browsers = append(browsers, b) } return browsers } @@ -106,10 +111,8 @@ func ListBrowser() []string { return l } -var ( - // home dir path for all platforms - homeDir, _ = os.UserHomeDir() -) +// home dir path for all platforms +var homeDir, _ = os.UserHomeDir() const ( chromeName = "Chrome" diff --git a/internal/browser/browser_windows.go b/internal/browser/browser_windows.go index ebcf11d..17fa899 100644 --- a/internal/browser/browser_windows.go +++ b/internal/browser/browser_windows.go @@ -15,7 +15,7 @@ var ( }{ "chrome": { name: chromeName, - profilePath: chromeProfilePath, + profilePath: chromeUserDataPath, items: item.DefaultChromium, }, "edge": { @@ -25,12 +25,12 @@ var ( }, "chromium": { name: chromiumName, - profilePath: chromiumProfilePath, + profilePath: chromiumUserDataPath, items: item.DefaultChromium, }, "chrome-beta": { name: chromeBetaName, - profilePath: chromeBetaProfilePath, + profilePath: chromeBetaUserDataPath, items: item.DefaultChromium, }, "opera": { @@ -89,18 +89,18 @@ var ( ) var ( - chromeProfilePath = homeDir + "/AppData/Local/Google/Chrome/User Data/Default/" - chromeBetaProfilePath = homeDir + "/AppData/Local/Google/Chrome Beta/User Data/Default/" - chromiumProfilePath = homeDir + "/AppData/Local/Chromium/User Data/Default/" - edgeProfilePath = homeDir + "/AppData/Local/Microsoft/Edge/User Data/Default/" - braveProfilePath = homeDir + "/AppData/Local/BraveSoftware/Brave-Browser/User Data/Default/" - speed360ProfilePath = homeDir + "/AppData/Local/360chrome/Chrome/User Data/Default/" - qqBrowserProfilePath = homeDir + "/AppData/Local/Tencent/QQBrowser/User Data/Default/" - operaProfilePath = homeDir + "/AppData/Roaming/Opera Software/Opera Stable/Default/" - operaGXProfilePath = homeDir + "/AppData/Roaming/Opera Software/Opera GX Stable/Default/" - vivaldiProfilePath = homeDir + "/AppData/Local/Vivaldi/User Data/Default/" - coccocProfilePath = homeDir + "/AppData/Local/CocCoc/Browser/User Data/Default/" - yandexProfilePath = homeDir + "/AppData/Local/Yandex/YandexBrowser/User Data/Default/" + chromeUserDataPath = homeDir + "/AppData/Local/Google/Chrome/User Data/Default/" + chromeBetaUserDataPath = homeDir + "/AppData/Local/Google/Chrome Beta/User Data/Default/" + chromiumUserDataPath = homeDir + "/AppData/Local/Chromium/User Data/Default/" + edgeProfilePath = homeDir + "/AppData/Local/Microsoft/Edge/User Data/Default/" + braveProfilePath = homeDir + "/AppData/Local/BraveSoftware/Brave-Browser/User Data/Default/" + speed360ProfilePath = homeDir + "/AppData/Local/360chrome/Chrome/User Data/Default/" + qqBrowserProfilePath = homeDir + "/AppData/Local/Tencent/QQBrowser/User Data/Default/" + operaProfilePath = homeDir + "/AppData/Roaming/Opera Software/Opera Stable/Default/" + operaGXProfilePath = homeDir + "/AppData/Roaming/Opera Software/Opera GX Stable/" + vivaldiProfilePath = homeDir + "/AppData/Local/Vivaldi/User Data/Default/" + coccocProfilePath = homeDir + "/AppData/Local/CocCoc/Browser/User Data/Default/" + yandexProfilePath = homeDir + "/AppData/Local/Yandex/YandexBrowser/User Data/Default/" firefoxProfilePath = homeDir + "/AppData/Roaming/Mozilla/Firefox/Profiles/" ) diff --git a/internal/browser/chromium/chromium.go b/internal/browser/chromium/chromium.go index bd06594..dd0d246 100644 --- a/internal/browser/chromium/chromium.go +++ b/internal/browser/chromium/chromium.go @@ -1,7 +1,7 @@ package chromium import ( - "os" + "io/fs" "path/filepath" "strings" @@ -21,19 +21,27 @@ type chromium struct { } // New create instance of chromium browser, fill item's path if item is existed. -func New(name, storage, profilePath string, items []item.Item) (*chromium, error) { +func New(name, storage, profilePath string, items []item.Item) ([]*chromium, error) { c := &chromium{ - name: name, - storage: storage, + name: name, + storage: storage, + profilePath: profilePath, + items: items, } - itemsPaths, err := c.getItemPath(profilePath, items) + multiItemPaths, err := c.getMultiItemPath(c.profilePath, c.items) if err != nil { return nil, err } - c.profilePath = profilePath - c.itemPaths = itemsPaths - c.items = typeutil.Keys(itemsPaths) - return c, err + var chromiumList []*chromium + for user, itemPaths := range multiItemPaths { + chromiumList = append(chromiumList, &chromium{ + name: fileutil.BrowserName(name, user), + items: typeutil.Keys(itemPaths), + itemPaths: itemPaths, + storage: storage, + }) + } + return chromiumList, nil } func (c *chromium) Name() string { @@ -81,28 +89,49 @@ func (c *chromium) copyItemToLocal() error { return nil } -func (c *chromium) getItemPath(profilePath string, items []item.Item) (map[item.Item]string, error) { - var itemPaths = make(map[item.Item]string) +func (c *chromium) getMultiItemPath(profilePath string, items []item.Item) (map[string]map[item.Item]string, error) { + // multiItemPaths is a map of user to item path, map[profile 1][item's name & path key pair] + multiItemPaths := make(map[string]map[item.Item]string) parentDir := fileutil.ParentDir(profilePath) - baseDir := fileutil.BaseDir(profilePath) - err := filepath.Walk(parentDir, chromiumWalkFunc(items, itemPaths, baseDir)) + err := filepath.Walk(parentDir, chromiumWalkFunc(items, multiItemPaths)) if err != nil { - return itemPaths, err + return nil, err + } + var keyPath string + var dir string + for userDir, v := range multiItemPaths { + for _, p := range v { + if strings.HasSuffix(p, item.ChromiumKey.FileName()) { + keyPath = p + dir = userDir + break + } + } + } + t := make(map[string]map[item.Item]string) + for userDir, v := range multiItemPaths { + if userDir == dir { + continue + } + t[userDir] = v + t[userDir][item.ChromiumKey] = keyPath + fillLocalStoragePath(t[userDir], item.ChromiumLocalStorage) } - fillLocalStoragePath(itemPaths, item.ChromiumLocalStorage) - return itemPaths, nil + return t, nil } -func chromiumWalkFunc(items []item.Item, itemPaths map[item.Item]string, baseDir string) filepath.WalkFunc { - return func(path string, info os.FileInfo, err error) error { - for _, it := range items { - switch { - case it.FileName() == info.Name(): - if it == item.ChromiumKey { - itemPaths[it] = path +func chromiumWalkFunc(items []item.Item, multiItemPaths map[string]map[item.Item]string) filepath.WalkFunc { + return func(path string, info fs.FileInfo, err error) error { + for _, v := range items { + if info.Name() == v.FileName() { + parentBaseDir := fileutil.ParentBaseDir(path) + if parentBaseDir == "System Profile" { + continue } - if strings.Contains(path, baseDir) { - itemPaths[it] = path + if _, exist := multiItemPaths[parentBaseDir]; exist { + multiItemPaths[parentBaseDir][v] = path + } else { + multiItemPaths[parentBaseDir] = map[item.Item]string{v: path} } } } diff --git a/internal/browser/chromium/chromium_darwin.go b/internal/browser/chromium/chromium_darwin.go index 30f7772..ab5e6e2 100644 --- a/internal/browser/chromium/chromium_darwin.go +++ b/internal/browser/chromium/chromium_darwin.go @@ -1,3 +1,5 @@ +//go:build darwin + package chromium import ( @@ -46,7 +48,7 @@ func (c *chromium) GetMasterKey() ([]byte, error) { if chromeSecret == nil { return nil, ErrWrongSecurityCommand } - var chromeSalt = []byte("saltysalt") + chromeSalt := []byte("saltysalt") // @https://source.chromium.org/chromium/chromium/src/+/master:components/os_crypt/os_crypt_mac.mm;l=157 key := pbkdf2.Key(chromeSecret, chromeSalt, 1003, 16, sha1.New) if key == nil { diff --git a/internal/browser/chromium/chromium_linux.go b/internal/browser/chromium/chromium_linux.go index 76419a9..173971a 100644 --- a/internal/browser/chromium/chromium_linux.go +++ b/internal/browser/chromium/chromium_linux.go @@ -1,3 +1,5 @@ +//go:build linux + package chromium import ( @@ -60,7 +62,7 @@ func (c *chromium) GetMasterKey() ([]byte, error) { // @https://source.chromium.org/chromium/chromium/src/+/main:components/os_crypt/os_crypt_linux.cc;l=100 chromiumSecret = []byte("peanuts") } - var chromiumSalt = []byte("saltysalt") + chromiumSalt := []byte("saltysalt") // @https://source.chromium.org/chromium/chromium/src/+/master:components/os_crypt/os_crypt_linux.cc key := pbkdf2.Key(chromiumSecret, chromiumSalt, 1, 16, sha1.New) c.masterKey = key diff --git a/internal/browser/chromium/chromium_windows.go b/internal/browser/chromium/chromium_windows.go index 44b0963..0cd6846 100644 --- a/internal/browser/chromium/chromium_windows.go +++ b/internal/browser/chromium/chromium_windows.go @@ -1,3 +1,5 @@ +//go:build windows + package chromium import ( @@ -13,9 +15,7 @@ import ( "hack-browser-data/internal/utils/fileutil" ) -var ( - errDecodeMasterKeyFailed = errors.New("decode master key failed") -) +var errDecodeMasterKeyFailed = errors.New("decode master key failed") func (c *chromium) GetMasterKey() ([]byte, error) { keyFile, err := fileutil.ReadFile(item.TempChromiumKey) diff --git a/internal/browser/firefox/firefox.go b/internal/browser/firefox/firefox.go index e40db10..69441dc 100644 --- a/internal/browser/firefox/firefox.go +++ b/internal/browser/firefox/firefox.go @@ -21,13 +21,10 @@ type firefox struct { itemPaths map[item.Item]string } -var ( - ErrProfilePathNotFound = errors.New("profile path not found") -) +var ErrProfilePathNotFound = errors.New("profile path not found") // New returns a new firefox instance. func New(name, storage, profilePath string, items []item.Item) ([]*firefox, error) { - f := &firefox{ name: name, storage: storage, @@ -50,7 +47,7 @@ func New(name, storage, profilePath string, items []item.Item) ([]*firefox, erro } func (f *firefox) getMultiItemPath(profilePath string, items []item.Item) (map[string]map[item.Item]string, error) { - var multiItemPaths = make(map[string]map[item.Item]string) + multiItemPaths := make(map[string]map[item.Item]string) err := filepath.Walk(profilePath, firefoxWalkFunc(items, multiItemPaths)) return multiItemPaths, err } diff --git a/internal/decrypter/decrypter_darwin.go b/internal/decrypter/decrypter_darwin.go index 945dc37..d003e12 100644 --- a/internal/decrypter/decrypter_darwin.go +++ b/internal/decrypter/decrypter_darwin.go @@ -5,7 +5,7 @@ func Chromium(key, encryptPass []byte) ([]byte, error) { if len(key) == 0 { return nil, errSecurityKeyIsEmpty } - var chromeIV = []byte{32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32} + chromeIV := []byte{32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32} return aes128CBCDecrypt(key, chromeIV, encryptPass[3:]) } else { return nil, errDecryptFailed diff --git a/internal/decrypter/decrypter_linux.go b/internal/decrypter/decrypter_linux.go index d584f09..ccd5866 100644 --- a/internal/decrypter/decrypter_linux.go +++ b/internal/decrypter/decrypter_linux.go @@ -1,7 +1,7 @@ package decrypter func Chromium(key, encryptPass []byte) ([]byte, error) { - var chromeIV = []byte{32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32} + chromeIV := []byte{32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32} if len(encryptPass) > 3 { if len(key) == 0 { return nil, errSecurityKeyIsEmpty diff --git a/internal/utils/fileutil/filetutil.go b/internal/utils/fileutil/filetutil.go index 9f801fa..801557e 100644 --- a/internal/utils/fileutil/filetutil.go +++ b/internal/utils/fileutil/filetutil.go @@ -81,7 +81,7 @@ func CopyDirHasSuffix(src, dst, suffix string) error { if err != nil { return err } - if err := os.MkdirAll(dst, 0755); err != nil { + if err := os.MkdirAll(dst, 0o755); err != nil { return err } for index, file := range filelist { @@ -102,7 +102,7 @@ func CopyFile(src, dst string) error { if err != nil { return err } - err = ioutil.WriteFile(dst, d, 0777) + err = ioutil.WriteFile(dst, d, 0o777) if err != nil { return err } @@ -115,6 +115,11 @@ func Filename(browser, item, ext string) string { return strings.ToLower(fmt.Sprintf("%s_%s.%s", replace.Replace(browser), item, ext)) } +func BrowserName(browser, user string) string { + replace := strings.NewReplacer(" ", "_", ".", "_", "-", "_", "Profile", "User") + return strings.ToLower(fmt.Sprintf("%s_%s", replace.Replace(browser), replace.Replace(user))) +} + // ParentDir returns the parent directory of the provided path func ParentDir(p string) string { return filepath.Dir(filepath.Clean(p)) @@ -136,7 +141,7 @@ func CompressDir(dir string) error { if err != nil { return err } - var b = new(bytes.Buffer) + b := new(bytes.Buffer) zw := zip.NewWriter(b) for _, f := range files { fw, _ := zw.Create(f.Name()) diff --git a/internal/utils/typeutil/typeutil.go b/internal/utils/typeutil/typeutil.go index bbb7825..8ac96a7 100644 --- a/internal/utils/typeutil/typeutil.go +++ b/internal/utils/typeutil/typeutil.go @@ -24,7 +24,7 @@ func IntToBool[T constraints.Signed](a T) bool { } func Reverse[T any](s []T) []T { - var h = make([]T, len(s)) + h := make([]T, len(s)) for i := 0; i < len(s); i++ { h[i] = s[len(s)-i-1] } diff --git a/internal/utils/typeutil/typeutil_test.go b/internal/utils/typeutil/typeutil_test.go index 849ede3..7d5dc28 100644 --- a/internal/utils/typeutil/typeutil_test.go +++ b/internal/utils/typeutil/typeutil_test.go @@ -4,13 +4,11 @@ import ( "testing" ) -var ( - reverseTestCases = [][]any{ - []any{1, 2, 3, 4, 5}, - []any{"1", "2", "3", "4", "5"}, - []any{"1", 2, "3", "4", 5}, - } -) +var reverseTestCases = [][]any{ + {1, 2, 3, 4, 5}, + {"1", "2", "3", "4", "5"}, + {"1", 2, "3", "4", 5}, +} func TestReverse(t *testing.T) { for _, ts := range reverseTestCases {