parent
86d8e7e16e
commit
31419dc003
@ -0,0 +1 @@ |
|||||||
|
package utils |
@ -1,26 +1,118 @@ |
|||||||
package utils |
package utils |
||||||
|
|
||||||
|
import ( |
||||||
|
"crypto/aes" |
||||||
|
"crypto/cipher" |
||||||
|
"encoding/base64" |
||||||
|
"hack-browser-data/log" |
||||||
|
"os" |
||||||
|
"path/filepath" |
||||||
|
"syscall" |
||||||
|
"unsafe" |
||||||
|
|
||||||
|
"github.com/tidwall/gjson" |
||||||
|
) |
||||||
|
|
||||||
const ( |
const ( |
||||||
winChromeDir = "/Users/*/Library/Application Support/Google/Chrome/*/" |
winChromeKeyDir = "/AppData/Local/Google/Chrome/User Data/Local State" |
||||||
|
winChromeDir = "/AppData/Local/Google/Chrome/User Data/*/" |
||||||
|
) |
||||||
|
|
||||||
|
var ( |
||||||
|
chromeKey []byte |
||||||
) |
) |
||||||
|
|
||||||
func GetDBPath(dbName string) string { |
func InitChromeKey() error { |
||||||
s, err := filepath.Glob(winChromeDir + dbName) |
chromeKeyPath := os.Getenv("USERPROFILE") + winChromeKeyDir |
||||||
|
keyFile, err := ReadFile(chromeKeyPath) |
||||||
|
if err != nil { |
||||||
|
log.Error(err) |
||||||
|
return err |
||||||
|
} |
||||||
|
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 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 { |
if err != nil && len(s) == 0 { |
||||||
panic(err) |
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 |
||||||
} |
} |
||||||
return s[0] |
|
||||||
} |
} |
||||||
|
|
||||||
func AesGCMDecrypt(crypted, key, nounce []byte) ([]byte, error) { |
// 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) |
block, err := aes.NewCipher(key) |
||||||
if err != nil { |
if err != nil { |
||||||
return nil, err |
return "", err |
||||||
} |
} |
||||||
blockMode, _ := cipher.NewGCM(block) |
blockMode, _ := cipher.NewGCM(block) |
||||||
origData, err := blockMode.Open(nil, nounce, crypted, nil) |
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 nil, err |
||||||
} |
} |
||||||
return origData, nil |
defer procLocalFree.Call(uintptr(unsafe.Pointer(outBlob.pbData))) |
||||||
|
return outBlob.ToByteArray(), nil |
||||||
} |
} |
||||||
|
Loading…
Reference in new issue