feat: add is full export browsing data option

This commit is contained in:
moonD4rk
2023-03-11 20:09:10 +08:00
parent fbe61a2cf4
commit 84ab4005f9
15 changed files with 125 additions and 79 deletions
+13 -12
View File
@@ -17,9 +17,10 @@ type Browser interface {
// Name is browser's name
Name() string
// BrowsingData returns all browsing data in the browser.
BrowsingData() (*browingdata.Data, error)
BrowsingData(isFullExport bool) (*browingdata.Data, error)
}
// PickBrowsers returns a list of browsers that match the name and profile.
func PickBrowsers(name, profile string) ([]Browser, error) {
var browsers []Browser
clist := pickChromium(name, profile)
@@ -42,18 +43,18 @@ func pickChromium(name, profile string) []Browser {
name = strings.ToLower(name)
if name == "all" {
for _, v := range chromiumList {
if !fileutil.FolderExists(filepath.Clean(v.profilePath)) {
if !fileutil.IsDirExists(filepath.Clean(v.profilePath)) {
log.Noticef("find browser %s failed, profile folder does not exist", v.name)
continue
}
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())
multiChromium, err := chromium.New(v.name, v.storage, v.profilePath, v.items)
if err != nil {
log.Errorf("new chromium error: %v", err)
continue
}
for _, b := range multiChromium {
log.Noticef("find browser %s success", b.Name())
browsers = append(browsers, b)
}
}
}
@@ -61,7 +62,7 @@ func pickChromium(name, profile string) []Browser {
if profile == "" {
profile = c.profilePath
}
if !fileutil.FolderExists(filepath.Clean(profile)) {
if !fileutil.IsDirExists(filepath.Clean(profile)) {
log.Fatalf("find browser %s failed, profile folder does not exist", c.name)
}
chromiumList, err := chromium.New(c.name, c.storage, profile, c.items)
@@ -86,7 +87,7 @@ func pickFirefox(name, profile string) []Browser {
} else {
profile = fileutil.ParentDir(profile)
}
if !fileutil.FolderExists(filepath.Clean(profile)) {
if !fileutil.IsDirExists(filepath.Clean(profile)) {
log.Noticef("find browser firefox %s failed, profile folder does not exist", v.name)
continue
}
+15 -9
View File
@@ -28,7 +28,7 @@ func New(name, storage, profilePath string, items []item.Item) ([]*Chromium, err
profilePath: profilePath,
items: items,
}
multiItemPaths, err := c.getMultiItemPath(c.profilePath, c.items)
multiItemPaths, err := c.userItemPaths(c.profilePath, c.items)
if err != nil {
return nil, err
}
@@ -48,8 +48,13 @@ func (c *Chromium) Name() string {
return c.name
}
func (c *Chromium) BrowsingData() (*browingdata.Data, error) {
b := browingdata.New(c.items)
func (c *Chromium) BrowsingData(isFullExport bool) (*browingdata.Data, error) {
items := c.items
if !isFullExport {
items = item.FilterSensitiveItems(c.items)
}
data := browingdata.New(items)
if err := c.copyItemToLocal(); err != nil {
return nil, err
@@ -61,10 +66,10 @@ func (c *Chromium) BrowsingData() (*browingdata.Data, error) {
}
c.masterKey = masterKey
if err := b.Recovery(c.masterKey); err != nil {
if err := data.Recovery(c.masterKey); err != nil {
return nil, err
}
return b, nil
return data, nil
}
func (c *Chromium) copyItemToLocal() error {
@@ -72,7 +77,7 @@ func (c *Chromium) copyItemToLocal() error {
filename := i.String()
var err error
switch {
case fileutil.FolderExists(path):
case fileutil.IsDirExists(path):
if i == item.ChromiumLocalStorage {
err = fileutil.CopyDir(path, filename, "lock")
}
@@ -89,8 +94,8 @@ func (c *Chromium) copyItemToLocal() error {
return nil
}
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]
// userItemPaths return a map of user to item path, map[profile 1][item's name & path key pair]
func (c *Chromium) userItemPaths(profilePath string, items []item.Item) (map[string]map[item.Item]string, error) {
multiItemPaths := make(map[string]map[item.Item]string)
parentDir := fileutil.ParentDir(profilePath)
err := filepath.Walk(parentDir, chromiumWalkFunc(items, multiItemPaths))
@@ -120,6 +125,7 @@ func (c *Chromium) getMultiItemPath(profilePath string, items []item.Item) (map[
return t, nil
}
// chromiumWalkFunc return a filepath.WalkFunc to find item's 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 {
@@ -145,7 +151,7 @@ func chromiumWalkFunc(items []item.Item, multiItemPaths map[string]map[item.Item
func fillLocalStoragePath(itemPaths map[item.Item]string, storage item.Item) {
if p, ok := itemPaths[item.ChromiumHistory]; ok {
lsp := filepath.Join(filepath.Dir(p), storage.FileName())
if fileutil.FolderExists(lsp) {
if fileutil.IsDirExists(lsp) {
itemPaths[item.ChromiumLocalStorage] = lsp
}
}
+13 -12
View File
@@ -6,6 +6,7 @@ import (
"bytes"
"crypto/sha1"
"errors"
"fmt"
"os"
"os/exec"
"strings"
@@ -22,34 +23,34 @@ var (
)
func (c *Chromium) GetMasterKey() ([]byte, error) {
var (
cmd *exec.Cmd
stdout, stderr bytes.Buffer
)
// don't need chromium key file for macOS
defer os.Remove(item.TempChromiumKey)
// Get the master key from the keychain
// $ security find-generic-password -wa 'Chrome'
cmd = exec.Command("security", "find-generic-password", "-wa", strings.TrimSpace(c.storage)) //nolint:gosec
var (
stdout, stderr bytes.Buffer
)
cmd := exec.Command("security", "find-generic-password", "-wa", strings.TrimSpace(c.storage)) //nolint:gosec
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
return nil, err
if err := cmd.Run(); err != nil {
return nil, fmt.Errorf("run security command failed: %w, message %s", err, stderr.String())
}
if stderr.Len() > 0 {
if strings.Contains(stderr.String(), "could not be found") {
return nil, errCouldNotFindInKeychain
}
return nil, errors.New(stderr.String())
}
chromeSecret := bytes.TrimSpace(stdout.Bytes())
if chromeSecret == nil {
secret := bytes.TrimSpace(stdout.Bytes())
if len(secret) == 0 {
return nil, errWrongSecurityCommand
}
chromeSalt := []byte("saltysalt")
salt := []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)
key := pbkdf2.Key(secret, salt, 1003, 16, sha1.New)
if key == nil {
return nil, errWrongSecurityCommand
}
+13 -10
View File
@@ -4,7 +4,7 @@ package chromium
import (
"crypto/sha1"
"errors"
"fmt"
"os"
"github.com/godbus/dbus/v5"
@@ -17,12 +17,13 @@ import (
func (c *Chromium) GetMasterKey() ([]byte, error) {
// what is d-bus @https://dbus.freedesktop.org/
var chromiumSecret []byte
// don't need chromium key file for Linux
defer os.Remove(item.TempChromiumKey)
conn, err := dbus.SessionBus()
if err != nil {
return nil, err
}
defer os.Remove(item.TempChromiumKey)
svc, err := keyring.GetSecretService(conn)
if err != nil {
return nil, err
@@ -40,6 +41,7 @@ func (c *Chromium) GetMasterKey() ([]byte, error) {
if err != nil {
return nil, err
}
var secret []byte
for _, col := range collections {
items, err := col.GetAllItems()
if err != nil {
@@ -54,19 +56,20 @@ func (c *Chromium) GetMasterKey() ([]byte, error) {
if label == c.storage {
se, err := i.GetSecret(session.Path())
if err != nil {
return nil, errors.New("get storage from dbus error:" + err.Error())
return nil, fmt.Errorf("get storage from dbus error: %v" + err.Error())
}
chromiumSecret = se.Value
secret = se.Value
}
}
}
if chromiumSecret == nil {
// @https://source.chromium.org/chromium/chromium/src/+/main:components/os_crypt/os_crypt_linux.cc;l=100
chromiumSecret = []byte("peanuts")
if len(secret) == 0 {
// set default secret @https://source.chromium.org/chromium/chromium/src/+/main:components/os_crypt/os_crypt_linux.cc;l=100
secret = []byte("peanuts")
}
chromiumSalt := []byte("saltysalt")
salt := []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)
key := pbkdf2.Key(secret, salt, 1, 16, sha1.New)
c.masterKey = key
log.Infof("%s initialized master key success", c.name)
return key, nil
+8 -5
View File
@@ -9,6 +9,7 @@ import (
"github.com/tidwall/gjson"
"github.com/moond4rk/HackBrowserData/crypto"
"github.com/moond4rk/HackBrowserData/item"
"github.com/moond4rk/HackBrowserData/log"
"github.com/moond4rk/HackBrowserData/utils/fileutil"
@@ -17,20 +18,22 @@ import (
var errDecodeMasterKeyFailed = errors.New("decode master key failed")
func (c *Chromium) GetMasterKey() ([]byte, error) {
keyFile, err := fileutil.ReadFile(item.TempChromiumKey)
b, err := fileutil.ReadFile(item.TempChromiumKey)
if err != nil {
return nil, err
}
defer os.Remove(keyFile)
encryptedKey := gjson.Get(keyFile, "os_crypt.encrypted_key")
defer os.Remove(item.TempChromiumKey)
encryptedKey := gjson.Get(b, "os_crypt.encrypted_key")
if !encryptedKey.Exists() {
return nil, nil
}
pureKey, err := base64.StdEncoding.DecodeString(encryptedKey.String())
key, err := base64.StdEncoding.DecodeString(encryptedKey.String())
if err != nil {
return nil, errDecodeMasterKeyFailed
}
c.masterKey, err = crypto.DPAPI(pureKey[5:])
c.masterKey, err = crypto.DPAPI(key[5:])
log.Infof("%s initialized master key success", c.name)
return c.masterKey, err
}
+8 -3
View File
@@ -39,7 +39,7 @@ func New(name, storage, profilePath string, items []item.Item) ([]*Firefox, erro
firefoxList := make([]*Firefox, 0, len(multiItemPaths))
for name, itemPaths := range multiItemPaths {
firefoxList = append(firefoxList, &Firefox{
name: fmt.Sprintf("Firefox-%s", name),
name: fmt.Sprintf("firefox-%s", name),
items: typeutil.Keys(itemPaths),
itemPaths: itemPaths,
})
@@ -87,8 +87,13 @@ func (f *Firefox) Name() string {
return f.name
}
func (f *Firefox) BrowsingData() (*browingdata.Data, error) {
b := browingdata.New(f.items)
func (f *Firefox) BrowsingData(isFullExport bool) (*browingdata.Data, error) {
items := f.items
if !isFullExport {
items = item.FilterSensitiveItems(f.items)
}
b := browingdata.New(items)
if err := f.copyItemToLocal(); err != nil {
return nil, err