feat: add copy file to local

pull/125/head
ᴍᴏᴏɴD4ʀᴋ 3 years ago
parent 46f2610a0a
commit dc06b1d69b
  1. 183
      cmd/cmd.go
  2. 2
      internal/browingdata/creditcard.go
  3. 4
      internal/browingdata/download.go
  4. 2
      internal/browingdata/history.go
  5. 2
      internal/browingdata/password.go
  6. 21
      internal/browser/browser.go
  7. 2
      internal/browser/browser_darwin.go
  8. 2
      internal/browser/browser_linux.go
  9. 43
      internal/browser/browser_test.go
  10. 2
      internal/browser/browser_windows.go
  11. 22
      internal/browser/chromium/chromium.go
  12. 12
      internal/browser/chromium/chromium_darwin.go
  13. 2
      internal/browser/firefox/firefox.go
  14. 2
      internal/item/item.go
  15. 2
      internal/outputter/outputter.go
  16. 4
      internal/outputter/outputter_test.go
  17. 21
      internal/utils/fileutil/filetutil.go
  18. 9
      main.go

@ -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)
// }
// }

@ -3,6 +3,7 @@ package browingdata
import ( import (
"database/sql" "database/sql"
"fmt" "fmt"
"os"
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
@ -17,6 +18,7 @@ func (c *ChromiumCreditCard) Parse(masterKey []byte) error {
if err != nil { if err != nil {
return err return err
} }
defer os.Remove(item.TempChromiumCreditCard)
defer creditDB.Close() defer creditDB.Close()
rows, err := creditDB.Query(queryChromiumCredit) rows, err := creditDB.Query(queryChromiumCredit)
if err != nil { if err != nil {

@ -3,6 +3,7 @@ package browingdata
import ( import (
"database/sql" "database/sql"
"fmt" "fmt"
"os"
"sort" "sort"
"strings" "strings"
@ -20,6 +21,7 @@ func (c *ChromiumDownload) Parse(masterKey []byte) error {
if err != nil { if err != nil {
return err return err
} }
defer os.Remove(item.TempChromiumDownload)
defer historyDB.Close() defer historyDB.Close()
rows, err := historyDB.Query(queryChromiumDownload) rows, err := historyDB.Query(queryChromiumDownload)
if err != nil { if err != nil {
@ -66,6 +68,8 @@ func (f *FirefoxDownload) Parse(masterKey []byte) error {
if err != nil { if err != nil {
return err return err
} }
defer os.Remove(item.TempFirefoxDownload)
defer keyDB.Close()
_, err = keyDB.Exec(closeJournalMode) _, err = keyDB.Exec(closeJournalMode)
if err != nil { if err != nil {
return err return err

@ -3,6 +3,7 @@ package browingdata
import ( import (
"database/sql" "database/sql"
"fmt" "fmt"
"os"
"sort" "sort"
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
@ -18,6 +19,7 @@ func (c *ChromiumHistory) Parse(masterKey []byte) error {
if err != nil { if err != nil {
return err return err
} }
defer os.Remove(item.TempChromiumHistory)
defer historyDB.Close() defer historyDB.Close()
rows, err := historyDB.Query(queryChromiumHistory) rows, err := historyDB.Query(queryChromiumHistory)
if err != nil { if err != nil {

@ -6,6 +6,7 @@ import (
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os"
"sort" "sort"
"time" "time"
@ -24,6 +25,7 @@ func (c *ChromiumPassword) Parse(masterKey []byte) error {
if err != nil { if err != nil {
return err return err
} }
defer os.Remove(item.TempChromiumPassword)
defer loginDB.Close() defer loginDB.Close()
rows, err := loginDB.Query(queryChromiumLogin) rows, err := loginDB.Query(queryChromiumLogin)
if err != nil { if err != nil {

@ -1,6 +1,7 @@
package browser package browser
import ( import (
"fmt"
"os" "os"
"strings" "strings"
@ -9,10 +10,10 @@ import (
) )
type Browser interface { type Browser interface {
GetName() string Name() string
GetMasterKey() ([]byte, error) GetMasterKey() ([]byte, error)
// GetBrowsingData returns the browsing data for the browser.
GetBrowsingData() (*browingdata.Data, error) GetBrowsingData() (*browingdata.Data, error)
} }
@ -52,8 +53,12 @@ func pickChromium(name string) []Browser {
if c, ok := chromiumList[name]; ok { if c, ok := chromiumList[name]; ok {
b, err := chromium.New(c.name, c.storage, c.profilePath, c.items) b, err := chromium.New(c.name, c.storage, c.profilePath, c.items)
if err != nil { if err != nil {
if strings.Contains(err.Error(), "profile path is not exist") {
fmt.Println(err.Error())
} else {
panic(err) panic(err)
} }
}
browsers = append(browsers, b) browsers = append(browsers, b)
return browsers return browsers
} }
@ -97,13 +102,13 @@ var (
const ( const (
chromeName = "Chrome" chromeName = "Chrome"
chromeBetaName = "Chrome Beta" chromeBetaName = "Chrome Beta"
chromiumName = "ChromiumBookmark" chromiumName = "Chromium"
edgeName = "Microsoft Edge" edgeName = "Microsoft Edge"
firefoxName = "FirefoxBookmark" firefoxName = "Firefox"
firefoxBetaName = "FirefoxBookmark Beta" firefoxBetaName = "Firefox Beta"
firefoxDevName = "FirefoxBookmark Dev" firefoxDevName = "Firefox Dev"
firefoxNightlyName = "FirefoxBookmark Nightly" firefoxNightlyName = "Firefox Nightly"
firefoxESRName = "FirefoxBookmark ESR" firefoxESRName = "Firefox ESR"
speed360Name = "360speed" speed360Name = "360speed"
qqBrowserName = "QQ" qqBrowserName = "QQ"
braveName = "Brave" braveName = "Brave"

@ -1,3 +1,5 @@
//go:build darwin
package browser package browser
import ( import (

@ -1 +1,3 @@
//go:build linux
package browser package browser

@ -10,38 +10,7 @@ import (
) )
func TestPickChromium(t *testing.T) { 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) { func TestGetChromiumItemAbsPath(t *testing.T) {
@ -55,7 +24,7 @@ func TestGetChromiumItemAbsPath(t *testing.T) {
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
output := outputter.NewOutPutter("json") output := outputter.New("json")
if err != nil { if err != nil {
t.Error(err) t.Error(err)
@ -74,18 +43,18 @@ func TestGetChromiumItemAbsPath(t *testing.T) {
func TestPickBrowsers(t *testing.T) { func TestPickBrowsers(t *testing.T) {
browsers := PickBrowser("all") browsers := PickBrowser("all")
for _, v := range browsers { for _, v := range browsers {
fmt.Println(v.GetName()) fmt.Println(v.Name())
} }
// filetype := "json" // filetype := "json"
// dir := "result" // dir := "result"
// output := outputter.NewOutPutter(filetype) // output := outputter.New(filetype)
} }
// func TestPickFirefox(t *testing.T) { // func TestPickFirefox(t *testing.T) {
// browsers := pickFirefox("all") // browsers := pickFirefox("all")
// filetype := "json" // filetype := "json"
// dir := "result" // dir := "result"
// output := outputter.NewOutPutter(filetype) // output := outputter.New(filetype)
// if err := output.MakeDir("result"); err != nil { // if err := output.MakeDir("result"); err != nil {
// panic(err) // panic(err)
// } // }
@ -98,7 +67,7 @@ func TestPickBrowsers(t *testing.T) {
// if err != nil { // if err != nil {
// fmt.Println(err) // fmt.Println(err)
// } // }
// browserName := b.GetName() // browserName := b.Name()
// multiData := b.GetBrowsingData() // multiData := b.GetBrowsingData()
// for _, data := range multiData { // for _, data := range multiData {
// if err := data.Parse(masterKey); err != nil { // if err := data.Parse(masterKey); err != nil {

@ -1,3 +1,5 @@
//go:build windows
package browser package browser
import ( import (

@ -32,30 +32,17 @@ func New(name, storage, profilePath string, items []item.Item) (*chromium, error
if !fileutil.FolderExists(profilePath) { if !fileutil.FolderExists(profilePath) {
return nil, fmt.Errorf("%s profile path is not exist: %s", name, 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) itemsPaths, err := c.getItemPath(profilePath, items)
if err != nil { if err != nil {
return nil, err return nil, err
} }
c.masterKey = masterKey
c.profilePath = profilePath c.profilePath = profilePath
c.itemPaths = itemsPaths c.itemPaths = itemsPaths
c.items = typeutil.Keys(itemsPaths) c.items = typeutil.Keys(itemsPaths)
return c, err return c, err
} }
func (c *chromium) GetItems() []item.Item { func (c *chromium) Name() string {
return c.items
}
func (c *chromium) GetItemPaths() map[item.Item]string {
return c.itemPaths
}
func (c *chromium) GetName() string {
return c.name return c.name
} }
@ -65,6 +52,13 @@ func (c *chromium) GetBrowsingData() (*browingdata.Data, error) {
if err := c.copyItemToLocal(); err != nil { if err := c.copyItemToLocal(); err != nil {
return nil, err return nil, err
} }
masterKey, err := c.GetMasterKey()
if err != nil {
return nil, err
}
c.masterKey = masterKey
if err := b.Recovery(c.masterKey); err != nil { if err := b.Recovery(c.masterKey); err != nil {
return nil, err return nil, err
} }

@ -4,13 +4,18 @@ import (
"bytes" "bytes"
"crypto/sha1" "crypto/sha1"
"errors" "errors"
"os"
"os/exec" "os/exec"
"strings"
"golang.org/x/crypto/pbkdf2" "golang.org/x/crypto/pbkdf2"
"hack-browser-data/internal/item"
) )
var ( 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) { func (c *chromium) GetMasterKey() ([]byte, error) {
@ -18,6 +23,10 @@ func (c *chromium) GetMasterKey() ([]byte, error) {
cmd *exec.Cmd cmd *exec.Cmd
stdout, stderr bytes.Buffer 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' // $ security find-generic-password -wa 'Chrome'
cmd = exec.Command("security", "find-generic-password", "-wa", c.storage) cmd = exec.Command("security", "find-generic-password", "-wa", c.storage)
cmd.Stdout = &stdout cmd.Stdout = &stdout
@ -27,6 +36,9 @@ func (c *chromium) GetMasterKey() ([]byte, error) {
return nil, err return nil, err
} }
if stderr.Len() > 0 { if stderr.Len() > 0 {
if strings.Contains(stderr.String(), "could not be found") {
return nil, ErrCouldNotFindInKeychain
}
return nil, errors.New(stderr.String()) return nil, errors.New(stderr.String())
} }
chromeSecret := bytes.TrimSpace(stdout.Bytes()) chromeSecret := bytes.TrimSpace(stdout.Bytes())

@ -100,7 +100,7 @@ package firefox
// return f.masterKey, nil // return f.masterKey, nil
// } // }
// //
// func (f *firefox) GetName() string { // func (f *firefox) Name() string {
// return f.name // return f.name
// } // }
// //

@ -93,7 +93,7 @@ func (i Item) String() string {
case ChromiumExtension: case ChromiumExtension:
return UnsupportedItem return UnsupportedItem
case ChromiumHistory: case ChromiumHistory:
return TempChromiumExtension return TempChromiumHistory
case YandexPassword: case YandexPassword:
return TempYandexPassword return TempYandexPassword
case YandexCreditCard: case YandexCreditCard:

@ -18,7 +18,7 @@ type outPutter struct {
csv bool csv bool
} }
func NewOutPutter(flag string) *outPutter { func New(flag string) *outPutter {
o := &outPutter{} o := &outPutter{}
if flag == "json" { if flag == "json" {
o.json = true o.json = true

@ -6,9 +6,9 @@ import (
) )
func TestNewOutPutter(t *testing.T) { func TestNewOutPutter(t *testing.T) {
out := NewOutPutter("json") out := New("json")
if out == nil { if out == nil {
t.Error("NewOutPutter() returned nil") t.Error("New() returned nil")
} }
f, err := out.CreateFile("results", "test.json") f, err := out.CreateFile("results", "test.json")
if err != nil { if err != nil {

@ -1,8 +1,11 @@
package fileutil package fileutil
import ( import (
"fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"hack-browser-data/internal/item"
) )
// FileExists checks if the file exists in the provided path // 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) s, err := ioutil.ReadFile(filename)
return string(s), err 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
}

@ -1,9 +0,0 @@
package main
import (
"hack-browser-data/cmd"
)
func main() {
cmd.Execute()
}
Loading…
Cancel
Save