feat: support custom browser profile path

pull/83/head
moond4rk 4 years ago committed by ᴍᴏᴏɴD4ʀᴋ
parent 138c33dade
commit 3fa262f66c
  1. 31
      cmd/cmd.go
  2. 75
      core/browser.go
  3. 4
      core/browser_windows.go

@ -11,11 +11,13 @@ import (
) )
var ( var (
browser string browserName string
exportDir string exportDir string
outputFormat string outputFormat string
verbose bool verbose bool
compress bool compress bool
customProfilePath string
customKeyPath string
) )
func Execute() { func Execute() {
@ -23,26 +25,39 @@ func Execute() {
Name: "hack-browser-data", Name: "hack-browser-data",
Usage: "Export passwords/cookies/history/bookmarks from browser", Usage: "Export passwords/cookies/history/bookmarks from browser",
UsageText: "[hack-browser-data -b chrome -f json -dir results -cc]\n Get all data(password/cookie/history/bookmark) from chrome", UsageText: "[hack-browser-data -b chrome -f json -dir results -cc]\n Get all data(password/cookie/history/bookmark) from chrome",
Version: "0.3.0", Version: "0.3.1",
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.BoolFlag{Name: "verbose", Aliases: []string{"vv"}, Destination: &verbose, Value: false, Usage: "Verbose"}, &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{"cc"}, Destination: &compress, Value: false, Usage: "compress result to zip"},
&cli.StringFlag{Name: "browser", Aliases: []string{"b"}, Destination: &browser, Value: "all", Usage: "Available browsers: all|" + strings.Join(core.ListBrowser(), "|")}, &cli.StringFlag{Name: "browser", Aliases: []string{"b"}, Destination: &browserName, Value: "all", Usage: "available browsers: all|" + strings.Join(core.ListBrowser(), "|")},
&cli.StringFlag{Name: "results-dir", Aliases: []string{"dir"}, Destination: &exportDir, Value: "results", Usage: "Export dir"}, &cli.StringFlag{Name: "results-dir", Aliases: []string{"dir"}, Destination: &exportDir, 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: "format, csv|json|console"},
&cli.StringFlag{Name: "profile-dir-path", Aliases: []string{"p"}, Destination: &customProfilePath, Value: "", Usage: "custom profile dir path, get with chrome://version"},
&cli.StringFlag{Name: "key-file-path", Aliases: []string{"k"}, Destination: &customKeyPath, Value: "", Usage: "custom key file path"},
}, },
HideHelpCommand: true, HideHelpCommand: true,
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
var (
browsers []core.Browser
err error
)
if verbose { if verbose {
log.InitLog("debug") log.InitLog("debug")
} else { } else {
log.InitLog("error") log.InitLog("error")
} }
if customProfilePath != "" {
browsers, err = core.PickCustomBrowser(browserName, customProfilePath, customKeyPath)
if err != nil {
log.Error(err)
}
} else {
// default select all browsers // default select all browsers
browsers, err := core.PickBrowser(browser) browsers, err = core.PickBrowser(browserName)
if err != nil { if err != nil {
log.Error(err) log.Error(err)
} }
}
err = utils.MakeDir(exportDir) err = utils.MakeDir(exportDir)
if err != nil { if err != nil {
log.Error(err) log.Error(err)

@ -3,6 +3,7 @@ package core
import ( import (
"errors" "errors"
"fmt" "fmt"
"os"
"path/filepath" "path/filepath"
"strings" "strings"
@ -170,7 +171,7 @@ func NewFirefox(profile, key, name, storage string) (Browser, error) {
return &Firefox{profilePath: profile, keyPath: key, name: name}, nil return &Firefox{profilePath: profile, keyPath: key, name: name}, nil
} }
// // GetAllItems return all item with firefox
func (f *Firefox) GetAllItems() ([]data.Item, error) { func (f *Firefox) GetAllItems() ([]data.Item, error) {
var items []data.Item var items []data.Item
for item, choice := range firefoxItems { for item, choice := range firefoxItems {
@ -259,8 +260,43 @@ func PickBrowser(name string) ([]Browser, error) {
return nil, errBrowserNotSupported return nil, errBrowserNotSupported
} }
// PickCustomBrowser pick single browser with custom browser profile path and key file path (windows only).
// If custom key file path is empty, but the current browser requires key file (chromium for windows version > 80)
// key file path will be automatically found in the profile path's parent directory.
func PickCustomBrowser(browserName, cusProfile, cusKey string) ([]Browser, error) {
var (
browsers []Browser
)
browserName = strings.ToLower(browserName)
supportBrowser := strings.Join(ListBrowser(), "|")
if browserName == "all" {
return nil, fmt.Errorf("can't select all browser, pick one from %s with -b flag\n", supportBrowser)
}
if choice, ok := browserList[browserName]; ok {
// if this browser need key path
if choice.KeyPath != "" {
var err error
// if browser need key path and cusKey is empty, try to get key path with profile dir
if cusKey == "" {
cusKey, err = getKeyPath(cusProfile)
if err != nil {
return nil, err
}
}
}
if err := checkKeyPath(cusKey); err != nil {
return nil, err
}
b, err := choice.New(cusProfile, cusKey, choice.Name, choice.Storage)
browsers = append(browsers, b)
return browsers, err
} else {
return nil, fmt.Errorf("%s not support, pick one from %s with -b flag\n", browserName, supportBrowser)
}
}
func getItemPath(profilePath, file string) (string, error) { func getItemPath(profilePath, file string) (string, error) {
p, err := filepath.Glob(profilePath + file) p, err := filepath.Glob(filepath.Join(profilePath, file))
if err != nil { if err != nil {
return "", err return "", err
} }
@ -270,6 +306,41 @@ func getItemPath(profilePath, file string) (string, error) {
return "", fmt.Errorf("find %s failed", file) return "", fmt.Errorf("find %s failed", file)
} }
// getKeyPath try get key file path with browser's profile path
// default key file path is in the parent directory of the profile dir, and name is [Local State]
func getKeyPath(profilePath string) (string, error) {
if _, err := os.Stat(filepath.Clean(profilePath)); os.IsNotExist(err) {
return "", err
}
parentDir := getParentDirectory(profilePath)
keyPath := filepath.Join(parentDir, "Local State")
return keyPath, nil
}
// check key file path is exist
func checkKeyPath(keyPath string) error {
if _, err := os.Stat(keyPath); os.IsNotExist(err) {
return fmt.Errorf("secret key path not exist, please check %s", keyPath)
}
return nil
}
func getParentDirectory(dir string) string {
var (
length int
)
// filepath.Clean(dir) auto remove
dir = strings.ReplaceAll(filepath.Clean(dir), `\`, `/`)
length = strings.LastIndex(dir, "/")
if length > 0 {
if length > len([]rune(dir)) {
length = len([]rune(dir))
}
return string([]rune(dir)[:length])
}
return ""
}
func ListBrowser() []string { func ListBrowser() []string {
var l []string var l []string
for k := range browserList { for k := range browserList {

@ -3,6 +3,7 @@ package core
import ( import (
"encoding/base64" "encoding/base64"
"errors" "errors"
"fmt"
"os" "os"
"hack-browser-data/core/decrypt" "hack-browser-data/core/decrypt"
@ -109,6 +110,9 @@ func (c *Chromium) InitSecretKey() error {
if c.keyPath == "" { if c.keyPath == "" {
return nil return nil
} }
if _, err := os.Stat(c.keyPath); os.IsNotExist(err) {
return fmt.Errorf("%s secret key path is empty", c.name)
}
keyFile, err := utils.ReadFile(c.keyPath) keyFile, err := utils.ReadFile(c.keyPath)
if err != nil { if err != nil {
return err return err

Loading…
Cancel
Save