feat: support profile path cmd options

pull/125/head
ᴍᴏᴏɴD4ʀᴋ 3 years ago
parent da2beb9453
commit f728d3201b
  1. 46
      cmd/hack-browser-data/main.go
  2. 3
      go.mod
  3. 2
      go.sum
  4. 47
      internal/browser/browser.go
  5. 20
      internal/browser/browser_darwin.go
  6. 14
      internal/browser/browser_linux.go
  7. 24
      internal/browser/browser_windows.go
  8. 9
      internal/browser/chromium/chromium.go
  9. 23
      internal/browser/firefox/firefox.go
  10. 2
      internal/decrypter/decrypter.go
  11. 62
      internal/utils/fileutil/filetutil.go
  12. 44
      internal/utils/utils.go

@ -8,18 +8,18 @@ import (
"hack-browser-data/internal/browser"
"hack-browser-data/internal/log"
"hack-browser-data/internal/outputter"
"hack-browser-data/internal/utils"
"hack-browser-data/internal/utils/fileutil"
"github.com/urfave/cli/v2"
)
var (
browserName string
exportDir string
outputFormat string
verbose bool
compress bool
customProfilePath string
browserName string
outputDir string
outputFormat string
verbose bool
compress bool
profilePath string
)
func main() {
@ -28,30 +28,33 @@ func main() {
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]\n Get all browingdata(password/cookie/history/bookmark) from chrome",
Version: "0.4.0",
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",
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.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: &exportDir, Value: "results", Usage: "export dir"},
&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: "profile-dir-path", Aliases: []string{"p"}, Destination: &customProfilePath, Value: "", Usage: "custom profile dir path, get with chrome://version"},
&cli.StringFlag{Name: "profile-dir-path", Aliases: []string{"p"}, Destination: &profilePath, Value: "", Usage: "custom profile dir path, get with chrome://version"},
},
HideHelpCommand: true,
Action: func(c *cli.Context) error {
var (
browsers []browser.Browser
err error
)
if verbose {
log.InitLog("debug")
} else {
log.InitLog("error")
}
browsers, err = browser.PickBrowser(browserName)
var (
browsers []browser.Browser
err error
)
// if profilePath != "" {
// browsers, err = browser.PickBrowserByProfilePath(browserName, profilePath)
// }
browsers, err = browser.PickBrowser(browserName, profilePath)
if err != nil {
log.Error(err)
}
@ -65,7 +68,10 @@ func Execute() {
var f *os.File
for _, source := range data.Sources {
filename := fmt.Sprintf("%s_%s.%s", b.Name(), source.Name(), outputFormat)
f, err = output.CreateFile(exportDir, filename)
f, err = output.CreateFile(outputDir, filename)
if err != nil {
log.Error(err)
}
err = output.Write(source, f)
if err != nil {
log.Error(err)
@ -73,7 +79,7 @@ func Execute() {
}
}
if compress {
err = utils.Compress(exportDir)
err = fileutil.CompressDir(outputDir)
if err != nil {
log.Error(err)
}

@ -4,7 +4,7 @@ go 1.18
require (
github.com/gocarina/gocsv v0.0.0-20211203214250-4735fba0c1d9
github.com/godbus/dbus v4.1.0+incompatible
github.com/godbus/dbus/v5 v5.1.0
github.com/json-iterator/go v1.1.12
github.com/mattn/go-sqlite3 v1.14.9
github.com/ppacher/go-dbus-keyring v1.0.1
@ -15,7 +15,6 @@ require (
require (
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect

@ -6,8 +6,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gocarina/gocsv v0.0.0-20211203214250-4735fba0c1d9 h1:ptTza/LLPmfRtmz77X+6J61Wyf5e1hz5xYMvRk/hkE4=
github.com/gocarina/gocsv v0.0.0-20211203214250-4735fba0c1d9/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI=
github.com/godbus/dbus v4.1.0+incompatible h1:WqqLRTsQic3apZUK9qC5sGNfXthmPXzUZ7nQPrNITa4=
github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=

@ -1,13 +1,14 @@
package browser
import (
"fmt"
"os"
"strings"
"hack-browser-data/internal/browingdata"
"hack-browser-data/internal/browser/chromium"
"hack-browser-data/internal/browser/firefox"
"hack-browser-data/internal/log"
"hack-browser-data/internal/utils/fileutil"
)
type Browser interface {
@ -18,15 +19,15 @@ type Browser interface {
GetBrowsingData() (*browingdata.Data, error)
}
func PickBrowser(name string) ([]Browser, error) {
func PickBrowser(name, profile string) ([]Browser, error) {
var browsers []Browser
clist := pickChromium(name)
clist := pickChromium(name, profile)
for _, b := range clist {
if b != nil {
browsers = append(browsers, b)
}
}
flist := pickFirefox(name)
flist := pickFirefox(name, profile)
for _, b := range flist {
if b != nil {
browsers = append(browsers, b)
@ -35,9 +36,27 @@ func PickBrowser(name string) ([]Browser, error) {
return browsers, nil
}
func pickChromium(name string) []Browser {
func PickBrowserByProfilePath(name, profile string) ([]Browser, error) {
var browsers []Browser
clist := pickChromium(name, profile)
for _, b := range clist {
if b != nil {
browsers = append(browsers, b)
}
}
flist := pickFirefox(name, profile)
for _, b := range flist {
if b != nil {
browsers = append(browsers, b)
}
}
return browsers, nil
}
func pickChromium(name, profile string) []Browser {
var browsers []Browser
name = strings.ToLower(name)
// TODO: add support for 「all」 flag and set profilePath
if name == "all" {
for _, c := range chromiumList {
if b, err := chromium.New(c.name, c.storage, c.profilePath, c.items); err == nil {
@ -53,10 +72,13 @@ func pickChromium(name string) []Browser {
return browsers
}
if c, ok := chromiumList[name]; ok {
b, err := chromium.New(c.name, c.storage, c.profilePath, c.items)
if profile == "" {
profile = c.profilePath
}
b, err := chromium.New(c.name, c.storage, profile, c.items)
if err != nil {
if strings.Contains(err.Error(), "profile path is not exist") {
fmt.Println(err.Error())
log.Error(err.Error())
} else {
panic(err)
}
@ -67,16 +89,21 @@ func pickChromium(name string) []Browser {
return nil
}
func pickFirefox(name string) []Browser {
func pickFirefox(name, profile string) []Browser {
var browsers []Browser
name = strings.ToLower(name)
if name == "all" || name == "firefox" {
for _, v := range firefoxList {
multiFirefox, err := firefox.New(v.name, v.storage, v.profilePath, v.items)
if profile == "" {
profile = v.profilePath
} else {
profile = fileutil.ParentDir(profile)
}
multiFirefox, err := firefox.New(v.name, v.storage, profile, v.items)
// TODO: Handle error
if err != nil {
if strings.Contains(err.Error(), "profile path is not exist") {
fmt.Println(err.Error())
log.Error(err.Error())
} else {
panic(err)
}

@ -89,16 +89,16 @@ var (
)
var (
chromeProfilePath = homeDir + "/Library/Application Support/Google/Chrome/"
chromeBetaProfilePath = homeDir + "/Library/Application Support/Google/Chrome Beta/"
chromiumProfilePath = homeDir + "/Library/Application Support/Chromium/"
edgeProfilePath = homeDir + "/Library/Application Support/Microsoft Edge/"
braveProfilePath = homeDir + "/Library/Application Support/BraveSoftware/Brave-Browser/"
operaProfilePath = homeDir + "/Library/Application Support/com.operasoftware.Opera/"
operaGXProfilePath = homeDir + "/Library/Application Support/com.operasoftware.OperaGX/"
vivaldiProfilePath = homeDir + "/Library/Application Support/Vivaldi/"
coccocProfilePath = homeDir + "/Library/Application Support/Coccoc/"
yandexProfilePath = homeDir + "/Library/Application Support/Yandex/YandexBrowser/"
chromeProfilePath = homeDir + "/Library/Application Support/Google/Chrome/Default/"
chromeBetaProfilePath = homeDir + "/Library/Application Support/Google/Chrome Beta/Default/"
chromiumProfilePath = homeDir + "/Library/Application Support/Chromium/Default/"
edgeProfilePath = homeDir + "/Library/Application Support/Microsoft Edge/Default/"
braveProfilePath = homeDir + "/Library/Application Support/BraveSoftware/Brave-Browser/Default/"
operaProfilePath = homeDir + "/Library/Application Support/com.operasoftware.Opera/Default/"
operaGXProfilePath = homeDir + "/Library/Application Support/com.operasoftware.OperaGX/Default/"
vivaldiProfilePath = homeDir + "/Library/Application Support/Vivaldi/Default/"
coccocProfilePath = homeDir + "/Library/Application Support/Coccoc/Default/"
yandexProfilePath = homeDir + "/Library/Application Support/Yandex/YandexBrowser/Default/"
firefoxProfilePath = homeDir + "/Library/Application Support/Firefox/Profiles/"
)

@ -72,13 +72,13 @@ var (
var (
firefoxProfilePath = homeDir + "/.mozilla/firefox/"
chromeProfilePath = homeDir + "/.config/google-chrome/"
chromiumProfilePath = homeDir + "/.config/chromium/"
edgeProfilePath = homeDir + "/.config/microsoft-edge*/"
braveProfilePath = homeDir + "/.config/BraveSoftware/Brave-Browser/"
chromeBetaProfilePath = homeDir + "/.config/google-chrome-beta/"
operaProfilePath = homeDir + "/.config/opera/"
vivaldiProfilePath = homeDir + "/.config/vivaldi/"
chromeProfilePath = homeDir + "/.config/google-chrome/Default/"
chromiumProfilePath = homeDir + "/.config/chromium/Default/"
edgeProfilePath = homeDir + "/.config/microsoft-edge*/Default/"
braveProfilePath = homeDir + "/.config/BraveSoftware/Brave-Browser/Default/"
chromeBetaProfilePath = homeDir + "/.config/google-chrome-beta/Default/"
operaProfilePath = homeDir + "/.config/opera/Default/"
vivaldiProfilePath = homeDir + "/.config/vivaldi/Default/"
)
const (

@ -89,18 +89,18 @@ var (
)
var (
chromeProfilePath = homeDir + "/AppData/Local/Google/Chrome/User Data/"
chromeBetaProfilePath = homeDir + "/AppData/Local/Google/Chrome Beta/User Data/"
chromiumProfilePath = homeDir + "/AppData/Local/Chromium/User Data/"
edgeProfilePath = homeDir + "/AppData/Local/Microsoft/Edge/User Data/"
braveProfilePath = homeDir + "/AppData/Local/BraveSoftware/Brave-Browser/User Data/"
speed360ProfilePath = homeDir + "/AppData/Local/360chrome/Chrome/User Data/"
qqBrowserProfilePath = homeDir + "/AppData/Local/Tencent/QQBrowser/User Data/"
operaProfilePath = homeDir + "/AppData/Roaming/Opera Software/Opera Stable/"
operaGXProfilePath = homeDir + "/AppData/Roaming/Opera Software/Opera GX Stable/"
vivaldiProfilePath = homeDir + "/AppData/Local/Vivaldi/User Data/"
coccocProfilePath = homeDir + "/AppData/Local/CocCoc/Browser/User Data/"
yandexProfilePath = homeDir + "/AppData/Local/Yandex/YandexBrowser/User Data/"
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/"
firefoxProfilePath = homeDir + "/AppData/Roaming/Mozilla/Firefox/Profiles/"
)

@ -84,11 +84,13 @@ func (c *chromium) copyItemToLocal() error {
func (c *chromium) getItemPath(profilePath string, items []item.Item) (map[item.Item]string, error) {
var itemPaths = make(map[item.Item]string)
err := filepath.Walk(profilePath, chromiumWalkFunc(items, itemPaths))
parentDir := fileutil.ParentDir(profilePath)
baseDir := fileutil.BaseDir(profilePath)
err := filepath.Walk(parentDir, chromiumWalkFunc(items, itemPaths, baseDir))
return itemPaths, err
}
func chromiumWalkFunc(items []item.Item, itemPaths map[item.Item]string) filepath.WalkFunc {
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 {
@ -96,8 +98,7 @@ func chromiumWalkFunc(items []item.Item, itemPaths map[item.Item]string) filepat
if it == item.ChromiumKey {
itemPaths[it] = path
}
// TODO: check file path is not in Default folder
if strings.Contains(path, "Default") {
if strings.Contains(path, baseDir) {
itemPaths[it] = path
}
}

@ -9,6 +9,7 @@ import (
"hack-browser-data/internal/browingdata"
"hack-browser-data/internal/item"
"hack-browser-data/internal/log"
"hack-browser-data/internal/utils/fileutil"
"hack-browser-data/internal/utils/typeutil"
)
@ -24,20 +25,19 @@ 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)
}
f := &firefox{
name: name,
storage: storage,
profilePath: profilePath,
items: items,
}
if !fileutil.FolderExists(profilePath) {
return nil, fmt.Errorf("%s profile path is not exist: %s", name, profilePath)
}
multiItemPaths, err := f.getMultiItemPath(f.profilePath, f.items)
if err != nil {
if strings.Contains(err.Error(), "profile path is not exist") {
fmt.Println(err)
log.Error(err)
return nil, nil
}
return nil, err
@ -55,7 +55,6 @@ 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)
err := filepath.Walk(profilePath, firefoxWalkFunc(items, multiItemPaths))
return multiItemPaths, err
}
@ -81,11 +80,11 @@ func firefoxWalkFunc(items []item.Item, multiItemPaths map[string]map[item.Item]
return func(path string, info fs.FileInfo, err error) error {
for _, v := range items {
if info.Name() == v.FileName() {
parentDir := getParentDir(path)
if _, exist := multiItemPaths[parentDir]; exist {
multiItemPaths[parentDir][v] = path
parentBaseDir := fileutil.ParentBaseDir(path)
if _, exist := multiItemPaths[parentBaseDir]; exist {
multiItemPaths[parentBaseDir][v] = path
} else {
multiItemPaths[parentDir] = map[item.Item]string{v: path}
multiItemPaths[parentBaseDir] = map[item.Item]string{v: path}
}
}
}
@ -93,10 +92,6 @@ func firefoxWalkFunc(items []item.Item, multiItemPaths map[string]map[item.Item]
}
}
func getParentDir(absPath string) string {
return filepath.Base(filepath.Dir(absPath))
}
func (f *firefox) GetMasterKey() ([]byte, error) {
return f.masterKey, nil
}

@ -17,7 +17,7 @@ var (
errSecurityKeyIsEmpty = errors.New("input [security find-generic-password -wa 'Chrome'] in terminal")
errPasswordIsEmpty = errors.New("password is empty")
errDecryptFailed = errors.New("decrypt encrypted value failed")
errDecodeASN1Failed = errors.New("decode ASN1 browingdata failed")
errDecodeASN1Failed = errors.New("decode ASN1 data failed")
errEncryptedLength = errors.New("length of encrypted password less than block size")
)

@ -1,11 +1,16 @@
package fileutil
import (
"archive/zip"
"bytes"
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
"hack-browser-data/internal/item"
"hack-browser-data/internal/log"
)
// FileExists checks if the file exists in the provided path
@ -55,3 +60,60 @@ func CopyItemToLocal(itemPaths map[item.Item]string) error {
}
return nil
}
func ParentDir(p string) string {
return filepath.Dir(p)
}
func BaseDir(p string) string {
return filepath.Base(p)
}
func ParentBaseDir(p string) string {
return BaseDir(ParentDir(p))
}
func CompressDir(dir string) error {
files, err := ioutil.ReadDir(dir)
if err != nil {
log.Error(err)
}
var b = new(bytes.Buffer)
zw := zip.NewWriter(b)
for _, f := range files {
fw, _ := zw.Create(f.Name())
fileName := path.Join(dir, f.Name())
fileContent, err := ioutil.ReadFile(fileName)
if err != nil {
zw.Close()
return err
}
_, err = fw.Write(fileContent)
if err != nil {
zw.Close()
return err
}
err = os.Remove(fileName)
if err != nil {
log.Error(err)
}
}
if err := zw.Close(); err != nil {
return err
}
filename := filepath.Join(dir, "archive.zip")
outFile, err := os.Create(filename)
if err != nil {
return err
}
_, err = b.WriteTo(outFile)
if err != nil {
return err
}
log.Debugf("Compress success, zip filename is %s", filename)
return nil
}
// func CleanProfilePath(p string) string {
//
// }

@ -1,20 +1,14 @@
package utils
import (
"archive/zip"
"bytes"
"fmt"
"io/ioutil"
"os"
"path"
"strings"
"time"
"hack-browser-data/internal/log"
)
const Prefix = "[x]: "
func IntToBool(a int) bool {
switch a {
case 0, -1:
@ -73,41 +67,3 @@ func MakeDir(dirName string) error {
}
return nil
}
func Compress(exportDir string) error {
files, err := ioutil.ReadDir(exportDir)
if err != nil {
log.Error(err)
}
var b = new(bytes.Buffer)
zw := zip.NewWriter(b)
for _, f := range files {
fw, _ := zw.Create(f.Name())
fileName := path.Join(exportDir, f.Name())
fileContent, err := ioutil.ReadFile(fileName)
if err != nil {
zw.Close()
return err
}
_, err = fw.Write(fileContent)
if err != nil {
zw.Close()
return err
}
err = os.Remove(fileName)
if err != nil {
log.Error(err)
}
}
if err := zw.Close(); err != nil {
return err
}
zipName := exportDir + `/archive.zip`
outFile, _ := os.Create(zipName)
_, err = b.WriteTo(outFile)
if err != nil {
return err
}
fmt.Printf("%s Compress success, zip filename is %s \n", Prefix, zipName)
return nil
}

Loading…
Cancel
Save