feat: support export extension info, Close #129

merge pull request #129 from moonD4rk/dev
pull/131/head
ᴍᴏᴏɴD4ʀᴋ 3 years ago committed by GitHub
commit f0e56b11a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      .gitignore
  2. 3
      cmd/hack-browser-data/main.go
  3. 5
      internal/browingdata/browsingdata.go
  4. 1
      internal/browingdata/cookie/cookie.go
  5. 75
      internal/browingdata/extension/extension.go
  6. 1
      internal/browingdata/history/history.go
  7. 1
      internal/browser/browser.go
  8. 23
      internal/browser/chromium/chromium.go
  9. 12
      internal/browser/firefox/firefox.go
  10. 4
      internal/item/filename.go
  11. 10
      internal/item/item.go
  12. 71
      internal/utils/fileutil/filetutil.go

3
.gitignore vendored

@ -188,3 +188,6 @@ History
#Firefox* #Firefox*
result/ result/
results/ results/
hack-browser-data
!/hack-browser-data

@ -29,7 +29,7 @@ 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]\nExport all browingdata(password/cookie/history/bookmark) from browser\nGithub Link: https://github.com/moonD4rk/HackBrowserData", UsageText: "[hack-browser-data -b chrome -f json -dir results -cc]\nExport all browingdata(password/cookie/history/bookmark) from browser\nGithub Link: https://github.com/moonD4rk/HackBrowserData",
Version: "0.4.1", Version: "0.4.2",
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{"zip"}, Destination: &compress, Value: false, Usage: "compress result to zip"}, &cli.BoolFlag{Name: "compress", Aliases: []string{"zip"}, Destination: &compress, Value: false, Usage: "compress result to zip"},
@ -65,6 +65,7 @@ func Execute() {
if err = fileutil.CompressDir(outputDir); err != nil { if err = fileutil.CompressDir(outputDir); err != nil {
log.Error(err) log.Error(err)
} }
log.Noticef("compress success")
} }
return nil return nil
}, },

@ -7,6 +7,7 @@ import (
"hack-browser-data/internal/browingdata/cookie" "hack-browser-data/internal/browingdata/cookie"
"hack-browser-data/internal/browingdata/creditcard" "hack-browser-data/internal/browingdata/creditcard"
"hack-browser-data/internal/browingdata/download" "hack-browser-data/internal/browingdata/download"
"hack-browser-data/internal/browingdata/extension"
"hack-browser-data/internal/browingdata/history" "hack-browser-data/internal/browingdata/history"
"hack-browser-data/internal/browingdata/localstorage" "hack-browser-data/internal/browingdata/localstorage"
"hack-browser-data/internal/browingdata/password" "hack-browser-data/internal/browingdata/password"
@ -78,6 +79,8 @@ func (d *Data) addSource(Sources []item.Item) {
d.sources[source] = &creditcard.ChromiumCreditCard{} d.sources[source] = &creditcard.ChromiumCreditCard{}
case item.ChromiumLocalStorage: case item.ChromiumLocalStorage:
d.sources[source] = &localstorage.ChromiumLocalStorage{} d.sources[source] = &localstorage.ChromiumLocalStorage{}
case item.ChromiumExtension:
d.sources[source] = &extension.ChromiumExtension{}
case item.YandexPassword: case item.YandexPassword:
d.sources[source] = &password.YandexPassword{} d.sources[source] = &password.YandexPassword{}
case item.YandexCreditCard: case item.YandexCreditCard:
@ -94,6 +97,8 @@ func (d *Data) addSource(Sources []item.Item) {
d.sources[source] = &download.FirefoxDownload{} d.sources[source] = &download.FirefoxDownload{}
case item.FirefoxLocalStorage: case item.FirefoxLocalStorage:
d.sources[source] = &localstorage.FirefoxLocalStorage{} d.sources[source] = &localstorage.FirefoxLocalStorage{}
case item.FirefoxExtension:
d.sources[source] = &extension.FirefoxExtension{}
} }
} }
} }

@ -69,7 +69,6 @@ func (c *ChromiumCookie) Parse(masterKey []byte) error {
CreateDate: typeutil.TimeEpoch(createDate), CreateDate: typeutil.TimeEpoch(createDate),
ExpireDate: typeutil.TimeEpoch(expireDate), ExpireDate: typeutil.TimeEpoch(expireDate),
} }
// TODO: replace DPAPI
if len(encryptValue) > 0 { if len(encryptValue) > 0 {
var err error var err error
if masterKey == nil { if masterKey == nil {

@ -0,0 +1,75 @@
package extension
import (
"os"
"github.com/tidwall/gjson"
"hack-browser-data/internal/item"
"hack-browser-data/internal/log"
"hack-browser-data/internal/utils/fileutil"
)
type ChromiumExtension []*extension
type extension struct {
Name string
Description string
Version string
HomepageURL string
}
const (
manifest = "manifest.json"
)
func (c *ChromiumExtension) Parse(masterKey []byte) error {
files, err := fileutil.FilesInFolder(item.TempChromiumExtension, manifest)
if err != nil {
return err
}
defer os.RemoveAll(item.TempChromiumExtension)
for _, f := range files {
file, err := fileutil.ReadFile(f)
if err != nil {
log.Error("Failed to read file: %s", err)
continue
}
b := gjson.Parse(file)
*c = append(*c, &extension{
Name: b.Get("name").String(),
Description: b.Get("description").String(),
Version: b.Get("version").String(),
HomepageURL: b.Get("homepage_url").String(),
})
}
return nil
}
func (c *ChromiumExtension) Name() string {
return "extension"
}
type FirefoxExtension []*extension
func (f *FirefoxExtension) Parse(masterKey []byte) error {
s, err := fileutil.ReadFile(item.TempFirefoxExtension)
if err != nil {
return err
}
defer os.Remove(item.TempFirefoxExtension)
j := gjson.Parse(s)
for _, v := range j.Get("addons").Array() {
*f = append(*f, &extension{
Name: v.Get("defaultLocale.name").String(),
Description: v.Get("defaultLocale.description").String(),
Version: v.Get("version").String(),
HomepageURL: v.Get("defaultLocale.homepageURL").String(),
})
}
return nil
}
func (f *FirefoxExtension) Name() string {
return "extension"
}

@ -44,7 +44,6 @@ func (c *ChromiumHistory) Parse(masterKey []byte) error {
visitCount int visitCount int
lastVisitTime int64 lastVisitTime int64
) )
// TODO: handle rows error
if err := rows.Scan(&url, &title, &visitCount, &lastVisitTime); err != nil { if err := rows.Scan(&url, &title, &visitCount, &lastVisitTime); err != nil {
log.Warn(err) log.Warn(err)
} }

@ -40,7 +40,6 @@ func PickBrowser(name, profile string) ([]Browser, error) {
func pickChromium(name, profile string) []Browser { func pickChromium(name, profile string) []Browser {
var browsers []Browser var browsers []Browser
name = strings.ToLower(name) name = strings.ToLower(name)
// TODO: add support for 「all」 flag and set profilePath
if name == "all" { if name == "all" {
for _, v := range chromiumList { for _, v := range chromiumList {
if !fileutil.FolderExists(filepath.Clean(v.profilePath)) { if !fileutil.FolderExists(filepath.Clean(v.profilePath)) {

@ -1,7 +1,6 @@
package chromium package chromium
import ( import (
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
@ -63,23 +62,23 @@ func (c *chromium) BrowsingData() (*browingdata.Data, error) {
func (c *chromium) copyItemToLocal() error { func (c *chromium) copyItemToLocal() error {
for i, path := range c.itemPaths { for i, path := range c.itemPaths {
if fileutil.FolderExists(path) { filename := i.String()
if err := fileutil.CopyDir(path, i.String(), "lock"); err != nil { var err error
return err switch {
case fileutil.FolderExists(path):
if i == item.ChromiumLocalStorage {
err = fileutil.CopyDir(path, filename, "lock")
} }
} else { if i == item.ChromiumExtension {
var filename = i.String() err = fileutil.CopyDirContains(path, filename, "manifest.json")
// TODO: Handle read file error }
d, err := ioutil.ReadFile(path) default:
if err != nil { err = fileutil.CopyFile(path, filename)
return err
} }
err = ioutil.WriteFile(filename, d, 0777)
if err != nil { if err != nil {
return err return err
} }
} }
}
return nil return nil
} }

@ -4,7 +4,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"io/fs" "io/fs"
"io/ioutil"
"path/filepath" "path/filepath"
"hack-browser-data/internal/browingdata" "hack-browser-data/internal/browingdata"
@ -58,15 +57,8 @@ func (f *firefox) getMultiItemPath(profilePath string, items []item.Item) (map[s
func (f *firefox) copyItemToLocal() error { func (f *firefox) copyItemToLocal() error {
for i, path := range f.itemPaths { for i, path := range f.itemPaths {
// var dstFilename = item.TempName() filename := i.String()
var filename = i.String() if err := fileutil.CopyFile(path, filename); err != nil {
// TODO: Handle read file error
d, err := ioutil.ReadFile(path)
if err != nil {
return err
}
err = ioutil.WriteFile(filename, d, 0777)
if err != nil {
return err return err
} }
} }

@ -10,6 +10,7 @@ const (
fileChromiumCookie = "Cookies" fileChromiumCookie = "Cookies"
fileChromiumBookmark = "Bookmarks" fileChromiumBookmark = "Bookmarks"
fileChromiumLocalStorage = "Local Storage/leveldb" fileChromiumLocalStorage = "Local Storage/leveldb"
fileChromiumExtension = "Extensions"
fileYandexPassword = "Ya Passman Data" fileYandexPassword = "Ya Passman Data"
fileYandexCredit = "Ya Credit Cards" fileYandexCredit = "Ya Credit Cards"
@ -19,6 +20,7 @@ const (
fileFirefoxPassword = "logins.json" fileFirefoxPassword = "logins.json"
fileFirefoxData = "places.sqlite" fileFirefoxData = "places.sqlite"
fileFirefoxLocalStorage = "webappsstore.sqlite" fileFirefoxLocalStorage = "webappsstore.sqlite"
fileFirefoxExtension = "extensions.json"
) )
const ( const (
@ -48,5 +50,5 @@ const (
TempFirefoxDownload = "firefoxDownload" TempFirefoxDownload = "firefoxDownload"
TempFirefoxLocalStorage = "firefoxLocalStorage" TempFirefoxLocalStorage = "firefoxLocalStorage"
TempFirefoxCreditCard = "" TempFirefoxCreditCard = ""
TempFirefoxExtension = "" TempFirefoxExtension = "firefoxExtension"
) )

@ -44,7 +44,7 @@ func (i Item) FileName() string {
case ChromiumCreditCard: case ChromiumCreditCard:
return fileChromiumCredit return fileChromiumCredit
case ChromiumExtension: case ChromiumExtension:
return UnknownItem return fileChromiumExtension
case ChromiumHistory: case ChromiumHistory:
return fileChromiumHistory return fileChromiumHistory
case YandexPassword: case YandexPassword:
@ -63,11 +63,11 @@ func (i Item) FileName() string {
return fileFirefoxData return fileFirefoxData
case FirefoxLocalStorage: case FirefoxLocalStorage:
return fileFirefoxLocalStorage return fileFirefoxLocalStorage
case FirefoxCreditCard:
return UnsupportedItem
case FirefoxHistory: case FirefoxHistory:
return fileFirefoxData return fileFirefoxData
case FirefoxExtension: case FirefoxExtension:
return fileFirefoxExtension
case FirefoxCreditCard:
return UnsupportedItem return UnsupportedItem
default: default:
return UnknownItem return UnknownItem
@ -91,7 +91,7 @@ func (i Item) String() string {
case ChromiumCreditCard: case ChromiumCreditCard:
return TempChromiumCreditCard return TempChromiumCreditCard
case ChromiumExtension: case ChromiumExtension:
return UnsupportedItem return TempChromiumExtension
case ChromiumHistory: case ChromiumHistory:
return TempChromiumHistory return TempChromiumHistory
case YandexPassword: case YandexPassword:
@ -115,7 +115,7 @@ func (i Item) String() string {
case FirefoxCreditCard: case FirefoxCreditCard:
return UnsupportedItem return UnsupportedItem
case FirefoxExtension: case FirefoxExtension:
return UnsupportedItem return TempFirefoxExtension
default: default:
return UnknownItem return UnknownItem
} }

@ -3,6 +3,7 @@ package fileutil
import ( import (
"archive/zip" "archive/zip"
"bytes" "bytes"
"errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
@ -10,8 +11,6 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"hack-browser-data/internal/log"
cp "github.com/otiai10/copy" cp "github.com/otiai10/copy"
) )
@ -39,12 +38,29 @@ func FolderExists(foldername string) bool {
return info.IsDir() return info.IsDir()
} }
// FilesInFolder returns the files contains in the provided folder
func FilesInFolder(dir, filename string) ([]string, error) {
if !FolderExists(dir) {
return nil, errors.New(dir + " folder does not exist")
}
var files []string
err := filepath.Walk(dir, func(path string, f os.FileInfo, err error) error {
if !f.IsDir() && strings.Contains(path, filename) {
files = append(files, path)
}
return err
})
return files, err
}
// ReadFile reads the file from the provided path // ReadFile reads the file from the provided path
func ReadFile(filename string) (string, error) { func ReadFile(filename string) (string, error) {
s, err := ioutil.ReadFile(filename) s, err := ioutil.ReadFile(filename)
return string(s), err return string(s), err
} }
// CopyDir copies the directory from the source to the destination
// skip the file if you don't want to copy
func CopyDir(src, dst, skip string) error { func CopyDir(src, dst, skip string) error {
s := cp.Options{Skip: func(src string) (bool, error) { s := cp.Options{Skip: func(src string) (bool, error) {
return strings.Contains(strings.ToLower(src), skip), nil return strings.Contains(strings.ToLower(src), skip), nil
@ -52,27 +68,73 @@ func CopyDir(src, dst, skip string) error {
return cp.Copy(src, dst, s) return cp.Copy(src, dst, s)
} }
// CopyDirContains copies the directory from the source to the destination
// contain is the file if you want to copy
func CopyDirContains(src, dst, contain string) error {
var filelist []string
err := filepath.Walk(src, func(path string, f os.FileInfo, err error) error {
if !f.IsDir() && strings.Contains(strings.ToLower(f.Name()), contain) {
filelist = append(filelist, path)
}
return err
})
if err != nil {
return err
}
if err := os.MkdirAll(dst, 0755); err != nil {
return err
}
for index, file := range filelist {
// p = dir/index_file
p := fmt.Sprintf("%s/%d_%s", dst, index, BaseDir(file))
err = CopyFile(file, p)
if err != nil {
return err
}
}
return nil
}
// CopyFile copies the file from the source to the destination
func CopyFile(src, dst string) error {
// TODO: Handle read file error
d, err := ioutil.ReadFile(src)
if err != nil {
return err
}
err = ioutil.WriteFile(dst, d, 0777)
if err != nil {
return err
}
return nil
}
// Filename returns the filename from the provided path
func Filename(browser, item, ext string) string { func Filename(browser, item, ext string) string {
replace := strings.NewReplacer(" ", "_", ".", "_", "-", "_") replace := strings.NewReplacer(" ", "_", ".", "_", "-", "_")
return strings.ToLower(fmt.Sprintf("%s_%s.%s", replace.Replace(browser), item, ext)) return strings.ToLower(fmt.Sprintf("%s_%s.%s", replace.Replace(browser), item, ext))
} }
// ParentDir returns the parent directory of the provided path
func ParentDir(p string) string { func ParentDir(p string) string {
return filepath.Dir(filepath.Clean(p)) return filepath.Dir(filepath.Clean(p))
} }
// BaseDir returns the base directory of the provided path
func BaseDir(p string) string { func BaseDir(p string) string {
return filepath.Base(p) return filepath.Base(p)
} }
// ParentBaseDir returns the parent base directory of the provided path
func ParentBaseDir(p string) string { func ParentBaseDir(p string) string {
return BaseDir(ParentDir(p)) return BaseDir(ParentDir(p))
} }
// CompressDir compresses the directory into a zip file
func CompressDir(dir string) error { func CompressDir(dir string) error {
files, err := ioutil.ReadDir(dir) files, err := ioutil.ReadDir(dir)
if err != nil { if err != nil {
log.Error(err) return err
} }
var b = new(bytes.Buffer) var b = new(bytes.Buffer)
zw := zip.NewWriter(b) zw := zip.NewWriter(b)
@ -91,7 +153,7 @@ func CompressDir(dir string) error {
} }
err = os.Remove(fileName) err = os.Remove(fileName)
if err != nil { if err != nil {
log.Error(err) return err
} }
} }
if err := zw.Close(); err != nil { if err := zw.Close(); err != nil {
@ -106,6 +168,5 @@ func CompressDir(dir string) error {
if err != nil { if err != nil {
return err return err
} }
log.Noticef("compress success, zip filename is %s", filename)
return nil return nil
} }

Loading…
Cancel
Save