From 77545627e3608140b331837d29a703eb9b30727c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=B4=8D=E1=B4=8F=E1=B4=8F=C9=B4D4=CA=80=E1=B4=8B?= Date: Mon, 11 Apr 2022 19:57:40 +0800 Subject: [PATCH] feat: add copy file to local --- cmd/cmd.go | 183 ------------------- internal/browingdata/creditcard.go | 2 + internal/browingdata/download.go | 4 + internal/browingdata/history.go | 2 + internal/browingdata/password.go | 2 + internal/browser/browser.go | 23 ++- internal/browser/browser_darwin.go | 2 + internal/browser/browser_linux.go | 2 + internal/browser/browser_test.go | 43 +---- internal/browser/browser_windows.go | 2 + internal/browser/chromium/chromium.go | 22 +-- internal/browser/chromium/chromium_darwin.go | 14 +- internal/browser/firefox/firefox.go | 2 +- internal/item/item.go | 2 +- internal/outputter/outputter.go | 2 +- internal/outputter/outputter_test.go | 4 +- internal/utils/fileutil/filetutil.go | 21 +++ main.go | 9 - 18 files changed, 83 insertions(+), 258 deletions(-) delete mode 100644 cmd/cmd.go delete mode 100644 main.go diff --git a/cmd/cmd.go b/cmd/cmd.go deleted file mode 100644 index 62aec3f..0000000 --- a/cmd/cmd.go +++ /dev/null @@ -1,183 +0,0 @@ -package cmd - -import ( - "fmt" - "os" - "strings" - - "github.com/urfave/cli/v2" - - "hack-browser-data/internal/browser" - "hack-browser-data/internal/log" - "hack-browser-data/internal/outputter" -) - -var ( - browserName string - exportDir string - outputFormat string - verbose bool - compress bool - customProfilePath string -) - -func Execute() { - app := &cli.App{ - Name: "hack-browser-browingdata", - Usage: "Export passwords/cookies/history/bookmarks from browser", - UsageText: "[hack-browser-browingdata -b chrome -f json -dir results -cc]\n Get all browingdata(password/cookie/history/bookmark) from chrome", - 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: "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"}, - }, - HideHelpCommand: true, - Action: func(ctx *cli.Context) error { - var ( - browsers []browser.Browser - err error - ) - if verbose { - log.InitLog("debug") - } else { - log.InitLog("error") - } - browsers = browser.PickBrowser(browserName) - - output := outputter.NewOutPutter(outputFormat) - if err := output.MakeDir(exportDir); err != nil { - panic(err) - } - for _, b := range browsers { - fmt.Printf("%+v\n", b) - if err := b.CopyItemFileToLocal(); err != nil { - panic(err) - } - masterKey, err := b.GetMasterKey() - if err != nil { - fmt.Println(err) - } - browserName := b.GetName() - multiData := b.GetBrowsingData() - for _, data := range multiData { - if err := data.Parse(masterKey); err != nil { - fmt.Println(err) - } - filename := fmt.Sprintf("%s_%s.%s", browserName, data.Name(), outputFormat) - file, err := output.CreateFile(exportDir, filename) - if err != nil { - panic(err) - } - if err := output.Write(data, file); err != nil { - panic(err) - } - } - } - return err - }, - } - err := app.Run(os.Args) - if err != nil { - log.Error(err) - } -} - -// func Execute() { -// app := &cli.App{ -// Name: "hack-browser-browingdata", -// Usage: "Export passwords/cookies/history/bookmarks from browser", -// UsageText: "[hack-browser-browingdata -b chrome -f json -dir results -cc]\n Get all browingdata(password/cookie/history/bookmark) from chrome", -// Version: "0.3.7", -// 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(core.ListBrowser(), "|")}, -// &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: "profile-dir-path", Aliases: []string{"p"}, Destination: &customProfilePath, Value: "", Usage: "custom profile dir path, get with chrome://version"}, -// }, -// HideHelpCommand: true, -// Action: func(c *cli.Context) error { -// var ( -// browsers []core.Browser -// err error -// ) -// if verbose { -// log.InitLog("debug") -// } else { -// log.InitLog("error") -// } -// if customProfilePath != "" { -// browsers, err = core.PickCustomBrowser(browserName, customProfilePath, customKeyPath) -// if err != nil { -// log.Error(err) -// } -// } else { -// // default select all browsers -// browsers, err = core.PickBrowser(browserName) -// if err != nil { -// log.Error(err) -// } -// } -// err = utils.MakeDir(exportDir) -// if err != nil { -// log.Error(err) -// } -// for _, browser := range browsers { -// err := browser.InitSecretKey() -// if err != nil { -// log.Error(err) -// } -// // default select all items -// // you can get single item with browser.GetItem(itemName) -// items, err := browser.GetAllItems() -// if err != nil { -// log.Error(err) -// } -// name := browser.GetName() -// key := browser.GetSecretKey() -// for _, item := range items { -// err := item.CopyDB() -// if err != nil { -// log.Error(err) -// } -// switch browser.(type) { -// case *core.Chromium: -// err := item.ChromeParse(key) -// if err != nil { -// log.Error(err) -// } -// case *core.Firefox: -// err := item.FirefoxParse() -// if err != nil { -// log.Error(err) -// } -// } -// err = item.Release() -// if err != nil { -// log.Error(err) -// } -// err = item.OutPut(outputFormat, name, exportDir) -// if err != nil { -// log.Error(err) -// } -// } -// } -// if compress { -// err = utils.Compress(exportDir) -// if err != nil { -// log.Error(err) -// } -// } -// return nil -// }, -// } -// err := app.Run(os.Args) -// if err != nil { -// log.Error(err) -// } -// } diff --git a/internal/browingdata/creditcard.go b/internal/browingdata/creditcard.go index 2c19a8e..4c0c9b8 100644 --- a/internal/browingdata/creditcard.go +++ b/internal/browingdata/creditcard.go @@ -3,6 +3,7 @@ package browingdata import ( "database/sql" "fmt" + "os" _ "github.com/mattn/go-sqlite3" @@ -17,6 +18,7 @@ func (c *ChromiumCreditCard) Parse(masterKey []byte) error { if err != nil { return err } + defer os.Remove(item.TempChromiumCreditCard) defer creditDB.Close() rows, err := creditDB.Query(queryChromiumCredit) if err != nil { diff --git a/internal/browingdata/download.go b/internal/browingdata/download.go index f421be6..50ab81b 100644 --- a/internal/browingdata/download.go +++ b/internal/browingdata/download.go @@ -3,6 +3,7 @@ package browingdata import ( "database/sql" "fmt" + "os" "sort" "strings" @@ -20,6 +21,7 @@ func (c *ChromiumDownload) Parse(masterKey []byte) error { if err != nil { return err } + defer os.Remove(item.TempChromiumDownload) defer historyDB.Close() rows, err := historyDB.Query(queryChromiumDownload) if err != nil { @@ -66,6 +68,8 @@ func (f *FirefoxDownload) Parse(masterKey []byte) error { if err != nil { return err } + defer os.Remove(item.TempFirefoxDownload) + defer keyDB.Close() _, err = keyDB.Exec(closeJournalMode) if err != nil { return err diff --git a/internal/browingdata/history.go b/internal/browingdata/history.go index 5c96309..ed60ad8 100644 --- a/internal/browingdata/history.go +++ b/internal/browingdata/history.go @@ -3,6 +3,7 @@ package browingdata import ( "database/sql" "fmt" + "os" "sort" _ "github.com/mattn/go-sqlite3" @@ -18,6 +19,7 @@ func (c *ChromiumHistory) Parse(masterKey []byte) error { if err != nil { return err } + defer os.Remove(item.TempChromiumHistory) defer historyDB.Close() rows, err := historyDB.Query(queryChromiumHistory) if err != nil { diff --git a/internal/browingdata/password.go b/internal/browingdata/password.go index 8fc017a..63fc473 100644 --- a/internal/browingdata/password.go +++ b/internal/browingdata/password.go @@ -6,6 +6,7 @@ import ( "encoding/base64" "fmt" "io/ioutil" + "os" "sort" "time" @@ -24,6 +25,7 @@ func (c *ChromiumPassword) Parse(masterKey []byte) error { if err != nil { return err } + defer os.Remove(item.TempChromiumPassword) defer loginDB.Close() rows, err := loginDB.Query(queryChromiumLogin) if err != nil { diff --git a/internal/browser/browser.go b/internal/browser/browser.go index aa115c0..9eee6c1 100644 --- a/internal/browser/browser.go +++ b/internal/browser/browser.go @@ -1,6 +1,7 @@ package browser import ( + "fmt" "os" "strings" @@ -9,10 +10,10 @@ import ( ) type Browser interface { - GetName() string + Name() string GetMasterKey() ([]byte, error) - + // GetBrowsingData returns the browsing data for the browser. GetBrowsingData() (*browingdata.Data, error) } @@ -52,7 +53,11 @@ func pickChromium(name string) []Browser { if c, ok := chromiumList[name]; ok { b, err := chromium.New(c.name, c.storage, c.profilePath, c.items) if err != nil { - panic(err) + if strings.Contains(err.Error(), "profile path is not exist") { + fmt.Println(err.Error()) + } else { + panic(err) + } } browsers = append(browsers, b) return browsers @@ -97,13 +102,13 @@ var ( const ( chromeName = "Chrome" chromeBetaName = "Chrome Beta" - chromiumName = "ChromiumBookmark" + chromiumName = "Chromium" edgeName = "Microsoft Edge" - firefoxName = "FirefoxBookmark" - firefoxBetaName = "FirefoxBookmark Beta" - firefoxDevName = "FirefoxBookmark Dev" - firefoxNightlyName = "FirefoxBookmark Nightly" - firefoxESRName = "FirefoxBookmark ESR" + firefoxName = "Firefox" + firefoxBetaName = "Firefox Beta" + firefoxDevName = "Firefox Dev" + firefoxNightlyName = "Firefox Nightly" + firefoxESRName = "Firefox ESR" speed360Name = "360speed" qqBrowserName = "QQ" braveName = "Brave" diff --git a/internal/browser/browser_darwin.go b/internal/browser/browser_darwin.go index 29a1e48..2b3af00 100644 --- a/internal/browser/browser_darwin.go +++ b/internal/browser/browser_darwin.go @@ -1,3 +1,5 @@ +//go:build darwin + package browser import ( diff --git a/internal/browser/browser_linux.go b/internal/browser/browser_linux.go index 199464e..c8d3c13 100644 --- a/internal/browser/browser_linux.go +++ b/internal/browser/browser_linux.go @@ -1 +1,3 @@ +//go:build linux + package browser diff --git a/internal/browser/browser_test.go b/internal/browser/browser_test.go index f261abd..5046ca0 100644 --- a/internal/browser/browser_test.go +++ b/internal/browser/browser_test.go @@ -10,38 +10,7 @@ import ( ) func TestPickChromium(t *testing.T) { - // browsers := pickChromium("chrome") - // log.InitLog("debug") - // filetype := "json" - // // dir := "result" - // output := outputter.NewOutPutter(filetype) - // _ = output - // for _, b := range browsers { - // fmt.Printf("%+v\n", b) - // if err := b.CopyItemFileToLocal(); err != nil { - // panic(err) - // } - // _, err := b.GetMasterKey() - // if err != nil { - // fmt.Println(err) - // } - // // browserName := b.GetName() - // data, err := b.GetBrowsingData() - // fmt.Println(data) - // // for _, data := range multiData { - // // if err := data.Parse(masterKey); err != nil { - // // fmt.Println(err) - // // } - // // filename := fmt.Sprintf("%s_%s.%s", browserName, data.Name(), filetype) - // // file, err := output.CreateFile(dir, filename) - // // if err != nil { - // // panic(err) - // // } - // // if err := output.Write(data, file); err != nil { - // // panic(err) - // // } - // // } - // } + } func TestGetChromiumItemAbsPath(t *testing.T) { @@ -55,7 +24,7 @@ func TestGetChromiumItemAbsPath(t *testing.T) { if err != nil { t.Error(err) } - output := outputter.NewOutPutter("json") + output := outputter.New("json") if err != nil { t.Error(err) @@ -74,18 +43,18 @@ func TestGetChromiumItemAbsPath(t *testing.T) { func TestPickBrowsers(t *testing.T) { browsers := PickBrowser("all") for _, v := range browsers { - fmt.Println(v.GetName()) + fmt.Println(v.Name()) } // filetype := "json" // dir := "result" - // output := outputter.NewOutPutter(filetype) + // output := outputter.New(filetype) } // func TestPickFirefox(t *testing.T) { // browsers := pickFirefox("all") // filetype := "json" // dir := "result" -// output := outputter.NewOutPutter(filetype) +// output := outputter.New(filetype) // if err := output.MakeDir("result"); err != nil { // panic(err) // } @@ -98,7 +67,7 @@ func TestPickBrowsers(t *testing.T) { // if err != nil { // fmt.Println(err) // } -// browserName := b.GetName() +// browserName := b.Name() // multiData := b.GetBrowsingData() // for _, data := range multiData { // if err := data.Parse(masterKey); err != nil { diff --git a/internal/browser/browser_windows.go b/internal/browser/browser_windows.go index 03bb126..4e3fb5a 100644 --- a/internal/browser/browser_windows.go +++ b/internal/browser/browser_windows.go @@ -1,3 +1,5 @@ +//go:build windows + package browser import ( diff --git a/internal/browser/chromium/chromium.go b/internal/browser/chromium/chromium.go index 05a46e9..3a02770 100644 --- a/internal/browser/chromium/chromium.go +++ b/internal/browser/chromium/chromium.go @@ -32,30 +32,17 @@ func New(name, storage, profilePath string, items []item.Item) (*chromium, error if !fileutil.FolderExists(profilePath) { return nil, fmt.Errorf("%s profile path is not exist: %s", name, profilePath) } - masterKey, err := c.GetMasterKey() - if err != nil { - return nil, err - } itemsPaths, err := c.getItemPath(profilePath, items) if err != nil { return nil, err } - c.masterKey = masterKey c.profilePath = profilePath c.itemPaths = itemsPaths c.items = typeutil.Keys(itemsPaths) return c, err } -func (c *chromium) GetItems() []item.Item { - return c.items -} - -func (c *chromium) GetItemPaths() map[item.Item]string { - return c.itemPaths -} - -func (c *chromium) GetName() string { +func (c *chromium) Name() string { return c.name } @@ -65,6 +52,13 @@ func (c *chromium) GetBrowsingData() (*browingdata.Data, error) { if err := c.copyItemToLocal(); err != nil { return nil, err } + + masterKey, err := c.GetMasterKey() + if err != nil { + return nil, err + } + + c.masterKey = masterKey if err := b.Recovery(c.masterKey); err != nil { return nil, err } diff --git a/internal/browser/chromium/chromium_darwin.go b/internal/browser/chromium/chromium_darwin.go index 72cb485..3fc247f 100644 --- a/internal/browser/chromium/chromium_darwin.go +++ b/internal/browser/chromium/chromium_darwin.go @@ -4,13 +4,18 @@ import ( "bytes" "crypto/sha1" "errors" + "os" "os/exec" + "strings" "golang.org/x/crypto/pbkdf2" + + "hack-browser-data/internal/item" ) var ( - ErrWrongSecurityCommand = errors.New("macOS wrong security command") + ErrWrongSecurityCommand = errors.New("macOS wrong security command") + ErrCouldNotFindInKeychain = errors.New("macOS could not find in keychain") ) func (c *chromium) GetMasterKey() ([]byte, error) { @@ -18,6 +23,10 @@ func (c *chromium) GetMasterKey() ([]byte, error) { cmd *exec.Cmd stdout, stderr bytes.Buffer ) + // don't need chromium key file for macOS + defer os.Remove(item.TempChromiumKey) + // 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", c.storage) cmd.Stdout = &stdout @@ -27,6 +36,9 @@ func (c *chromium) GetMasterKey() ([]byte, error) { return nil, err } 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()) diff --git a/internal/browser/firefox/firefox.go b/internal/browser/firefox/firefox.go index 7345c06..171d8d5 100644 --- a/internal/browser/firefox/firefox.go +++ b/internal/browser/firefox/firefox.go @@ -100,7 +100,7 @@ package firefox // return f.masterKey, nil // } // -// func (f *firefox) GetName() string { +// func (f *firefox) Name() string { // return f.name // } // diff --git a/internal/item/item.go b/internal/item/item.go index 0db919b..33dddba 100644 --- a/internal/item/item.go +++ b/internal/item/item.go @@ -93,7 +93,7 @@ func (i Item) String() string { case ChromiumExtension: return UnsupportedItem case ChromiumHistory: - return TempChromiumExtension + return TempChromiumHistory case YandexPassword: return TempYandexPassword case YandexCreditCard: diff --git a/internal/outputter/outputter.go b/internal/outputter/outputter.go index ece26f0..7548d7d 100644 --- a/internal/outputter/outputter.go +++ b/internal/outputter/outputter.go @@ -18,7 +18,7 @@ type outPutter struct { csv bool } -func NewOutPutter(flag string) *outPutter { +func New(flag string) *outPutter { o := &outPutter{} if flag == "json" { o.json = true diff --git a/internal/outputter/outputter_test.go b/internal/outputter/outputter_test.go index ed37e85..e0785c4 100644 --- a/internal/outputter/outputter_test.go +++ b/internal/outputter/outputter_test.go @@ -6,9 +6,9 @@ import ( ) func TestNewOutPutter(t *testing.T) { - out := NewOutPutter("json") + out := New("json") if out == nil { - t.Error("NewOutPutter() returned nil") + t.Error("New() returned nil") } f, err := out.CreateFile("results", "test.json") if err != nil { diff --git a/internal/utils/fileutil/filetutil.go b/internal/utils/fileutil/filetutil.go index 87f30e5..e97262e 100644 --- a/internal/utils/fileutil/filetutil.go +++ b/internal/utils/fileutil/filetutil.go @@ -1,8 +1,11 @@ package fileutil import ( + "fmt" "io/ioutil" "os" + + "hack-browser-data/internal/item" ) // FileExists checks if the file exists in the provided path @@ -34,3 +37,21 @@ func ReadFile(filename string) (string, error) { s, err := ioutil.ReadFile(filename) return string(s), err } + +// CopyItemToLocal copies the file from the provided path to the local path +func CopyItemToLocal(itemPaths map[item.Item]string) error { + for i, path := range itemPaths { + // var dstFilename = item.TempName() + var filename = i.String() + // TODO: Handle read file error + d, err := ioutil.ReadFile(path) + if err != nil { + fmt.Println(err.Error()) + } + err = ioutil.WriteFile(filename, d, 0777) + if err != nil { + return err + } + } + return nil +} diff --git a/main.go b/main.go deleted file mode 100644 index a8c3b94..0000000 --- a/main.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import ( - "hack-browser-data/cmd" -) - -func main() { - cmd.Execute() -}