refactor: format code with interface Closes #13

This commit is contained in:
ᴍᴏᴏɴD4ʀᴋ
2020-07-22 15:49:31 +08:00
parent 3c9c105195
commit 07149e20b4
15 changed files with 1419 additions and 840 deletions
+4 -19
View File
@@ -5,7 +5,6 @@ import (
"crypto/cipher"
"crypto/des"
"encoding/asn1"
"errors"
"fmt"
"hack-browser-data/log"
"io/ioutil"
@@ -16,13 +15,6 @@ import (
"time"
)
var (
errPasswordIsEmpty = errors.New("decrypt failed, password is empty")
errBrowserNotSupported = errors.New("browser not supported")
errKeyIsEmpty = errors.New("input [security find-generic-password -wa 'Chrome'] in terminal")
VersionUnder80 bool
)
type DecryptError struct {
err error
msg string
@@ -53,13 +45,6 @@ const (
FirefoxKey3DB = "key3.db"
)
func ListBrowser() []string {
var l []string
for k := range browserList {
l = append(l, k)
}
return l
}
func GetDBPath(dir string, dbName ...string) (dbFile []string) {
for _, v := range dbName {
@@ -122,7 +107,7 @@ func TimeStampFormat(stamp int64) time.Time {
func TimeEpochFormat(epoch int64) time.Time {
maxTime := int64(99633311740000000)
if epoch > maxTime {
epoch = maxTime
return time.Date(2049, 1, 1, 1, 1, 1, 1, time.Local)
}
t := time.Date(1601, 1, 1, 0, 0, 0, 0, time.UTC)
d := time.Duration(epoch)
@@ -156,9 +141,9 @@ func WriteFile(filename string, data []byte) error {
}
func FormatFileName(dir, browser, filename, format string) string {
r := strings.TrimSpace(strings.ToLower(filename))
r = strings.Replace(r, " ", "_", -1)
p := path.Join(dir, fmt.Sprintf("%s_%s.%s", r, browser, format))
r := strings.TrimSpace(strings.ToLower(browser))
r = strings.Replace(browser, " ", "_", -1)
p := path.Join(dir, fmt.Sprintf("%s_%s.%s", r, filename, format))
return p
}
-190
View File
@@ -1,190 +0,0 @@
package utils
import (
"bytes"
"crypto/hmac"
"crypto/sha1"
"encoding/asn1"
"encoding/hex"
"errors"
"hack-browser-data/log"
"os/exec"
"strings"
"golang.org/x/crypto/pbkdf2"
)
const (
chromeProfilePath = "/Users/*/Library/Application Support/Google/Chrome/*/"
chromeCommand = "Chrome"
edgeProfilePath = "/Users/*/Library/Application Support/Microsoft Edge/*/"
edgeCommand = "Microsoft Edge"
fireFoxProfilePath = "/Users/*/Library/Application Support/Firefox/Profiles/*.default-release/"
fireFoxCommand = ""
)
var (
iv = []byte{32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}
command = []string{"security", "find-generic-password", "-wa"}
chromeSalt = []byte("saltysalt")
chromeKey []byte
browserList = map[string]struct {
ProfilePath string
Command string
}{
"chrome": {
chromeProfilePath,
chromeCommand,
},
"edge": {
edgeProfilePath,
edgeCommand,
},
"firefox": {
fireFoxProfilePath,
fireFoxCommand,
},
}
)
func DecryptStringWithDPAPI(data []byte) (string, error) {
return string(data), nil
}
func PickBrowser(name string) (browserDir, command string, err error) {
name = strings.ToLower(name)
if choice, ok := browserList[name]; ok {
return choice.ProfilePath, choice.Command, err
}
return "", "", errBrowserNotSupported
}
func InitKey(key string) error {
var (
cmd *exec.Cmd
stdout, stderr bytes.Buffer
)
cmd = exec.Command(command[0], command[1], command[2], key)
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
log.Error(err)
return err
}
if stderr.Len() > 0 {
err = errors.New(stderr.String())
log.Error(err)
}
temp := stdout.Bytes()
chromePass := temp[:len(temp)-1]
decryptChromeKey(chromePass)
return err
}
func decryptChromeKey(chromePass []byte) {
chromeKey = pbkdf2.Key(chromePass, chromeSalt, 1003, 16, sha1.New)
}
func DecryptChromePass(encryptPass []byte) (string, error) {
if len(encryptPass) > 3 {
if len(chromeKey) == 0 {
return "", errKeyIsEmpty
}
m, err := aes128CBCDecrypt(chromeKey, iv, encryptPass[3:])
return string(m), err
} else {
return "", &DecryptError{
err: errPasswordIsEmpty,
}
}
}
/*
SEQUENCE (2 elem)
SEQUENCE (2 elem)
OBJECT IDENTIFIER
SEQUENCE (2 elem)
OCTET STRING (20 byte)
INTEGER 1
OCTET STRING (16 byte)
*/
type NssPBE struct {
SequenceA
Encrypted []byte
}
type MetaPBE struct {
SequenceA
Encrypted []byte
}
type SequenceA struct {
DecryptMethod asn1.ObjectIdentifier
SequenceB
}
type SequenceB struct {
EntrySalt []byte
Len int
}
func DecodeMeta(metaBytes []byte) (pbe MetaPBE, err error) {
log.Debug(hex.EncodeToString(metaBytes))
_, err = asn1.Unmarshal(metaBytes, &pbe)
if err != nil {
log.Error(err)
return
}
return
}
func DecodeNss(nssA11Bytes []byte) (pbe NssPBE, err error) {
log.Debug(hex.EncodeToString(nssA11Bytes))
_, err = asn1.Unmarshal(nssA11Bytes, &pbe)
if err != nil {
log.Error(err)
return
}
return
}
func DecryptMeta(globalSalt, masterPwd []byte, pbe MetaPBE) ([]byte, error) {
return decryptPBE(globalSalt, masterPwd, pbe.EntrySalt, pbe.Encrypted)
}
func DecryptNss(globalSalt, masterPwd []byte, pbe NssPBE) ([]byte, error) {
return decryptPBE(globalSalt, masterPwd, pbe.EntrySalt, pbe.Encrypted)
}
func decryptPBE(globalSalt, masterPwd, entrySalt, encrypted []byte) ([]byte, error) {
//byte[] GLMP; // GlobalSalt + MasterPassword
//byte[] HP; // SHA1(GLMP)
//byte[] HPES; // HP + EntrySalt
//byte[] CHP; // SHA1(HPES)
//byte[] PES; // EntrySalt completed to 20 bytes by zero
//byte[] PESES; // PES + EntrySalt
//byte[] k1;
//byte[] tk;
//byte[] k2;
//byte[] k; // final value conytaining key and iv
glmp := append(globalSalt, masterPwd...)
hp := sha1.Sum(glmp)
s := append(hp[:], entrySalt...)
chp := sha1.Sum(s)
pes := PaddingZero(entrySalt, 20)
tk := hmac.New(sha1.New, chp[:])
tk.Write(pes)
pes = append(pes, entrySalt...)
k1 := hmac.New(sha1.New, chp[:])
k1.Write(pes)
tkPlus := append(tk.Sum(nil), entrySalt...)
k2 := hmac.New(sha1.New, chp[:])
k2.Write(tkPlus)
k := append(k1.Sum(nil), k2.Sum(nil)...)
iv := k[len(k)-8:]
key := k[:24]
log.Warnf("key=%s iv=%s", hex.EncodeToString(key), hex.EncodeToString(iv))
return Des3Decrypt(key, iv, encrypted)
}
-204
View File
@@ -1,204 +0,0 @@
package utils
import (
"crypto/hmac"
"crypto/sha1"
"crypto/sha256"
"encoding/asn1"
"encoding/hex"
"hack-browser-data/log"
"strings"
"golang.org/x/crypto/pbkdf2"
)
const (
fireFoxProfilePath = "/home/*/.mozilla/firefox/*.default-release/"
fireFoxCommand = ""
)
var (
iv = []byte{32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}
command = []string{"security", "find-generic-password", "-wa"}
chromeSalt = []byte("saltysalt")
chromeKey []byte
browserList = map[string]struct {
ProfilePath string
Command string
}{
"firefox": {
fireFoxProfilePath,
fireFoxCommand,
},
}
)
func InitKey(string) error {
return nil
}
func DecryptStringWithDPAPI(data []byte) (string, error) {
return string(data), nil
}
func PickBrowser(name string) (browserDir, command string, err error) {
name = strings.ToLower(name)
if choice, ok := browserList[name]; ok {
return choice.ProfilePath, choice.Command, err
}
return "", "", errBrowserNotSupported
}
func decryptChromeKey(chromePass []byte) {
chromeKey = pbkdf2.Key(chromePass, chromeSalt, 1003, 16, sha1.New)
}
func DecryptChromePass(encryptPass []byte) (string, error) {
if len(encryptPass) > 3 {
if len(chromeKey) == 0 {
return "", errKeyIsEmpty
}
m, err := aes128CBCDecrypt(chromeKey, iv, encryptPass[3:])
return string(m), err
} else {
return "", &DecryptError{
err: errPasswordIsEmpty,
}
}
}
/*
SEQUENCE (2 elem)
SEQUENCE (2 elem)
OBJECT IDENTIFIER
SEQUENCE (2 elem)
OCTET STRING (20 byte)
INTEGER 1
OCTET STRING (16 byte)
*/
type MetaPBE struct {
SequenceA
Encrypted []byte
}
type SequenceA struct {
DecryptMethod asn1.ObjectIdentifier
SequenceB
}
type SequenceB struct {
EntrySalt []byte
Len int
}
type NssPBE struct {
SequenceNSSA
Encrypted []byte
}
type SequenceNSSA struct {
PKCS5PBES2 asn1.ObjectIdentifier
SequenceNSSB
}
type SequenceNSSB struct {
SequenceC
SequenceD
}
type SequenceC struct {
PKCS5PBKDF2 asn1.ObjectIdentifier
SequenceE
}
type SequenceD struct {
AES256CBC asn1.ObjectIdentifier
IV []byte
}
type SequenceE struct {
EntrySalt []byte
IterationCount int
KeySize int
SequenceF
}
type SequenceF struct {
HMACWithSHA256 asn1.ObjectIdentifier
}
func DecodeMeta(decodeItem []byte) (pbe MetaPBE, err error) {
_, err = asn1.Unmarshal(decodeItem, &pbe)
if err != nil {
log.Error(err)
return
}
return
}
func DecodeNss(nssA11Bytes []byte) (pbe NssPBE, err error) {
log.Debug(hex.EncodeToString(nssA11Bytes))
_, err = asn1.Unmarshal(nssA11Bytes, &pbe)
if err != nil {
log.Error(err)
return
}
return
}
func DecryptMeta(globalSalt, masterPwd []byte, pbe MetaPBE) ([]byte, error) {
return decryptMeta(globalSalt, masterPwd, pbe.EntrySalt, pbe.Encrypted)
}
func DecryptNss(globalSalt, masterPwd []byte, pbe NssPBE) ([]byte, error) {
return decryptNss(globalSalt, masterPwd, pbe.IV, pbe.EntrySalt, pbe.Encrypted, pbe.IterationCount, pbe.KeySize)
}
func decryptMeta(globalSalt, masterPwd, entrySalt, encrypted []byte) ([]byte, error) {
//byte[] GLMP; // GlobalSalt + MasterPassword
//byte[] HP; // SHA1(GLMP)
//byte[] HPES; // HP + EntrySalt
//byte[] CHP; // SHA1(HPES)
//byte[] PES; // EntrySalt completed to 20 bytes by zero
//byte[] PESES; // PES + EntrySalt
//byte[] k1;
//byte[] tk;
//byte[] k2;
//byte[] k; // final value conytaining key and iv
glmp := append(globalSalt, masterPwd...)
hp := sha1.Sum(glmp)
s := append(hp[:], entrySalt...)
chp := sha1.Sum(s)
pes := PaddingZero(entrySalt, 20)
tk := hmac.New(sha1.New, chp[:])
tk.Write(pes)
pes = append(pes, entrySalt...)
k1 := hmac.New(sha1.New, chp[:])
k1.Write(pes)
tkPlus := append(tk.Sum(nil), entrySalt...)
k2 := hmac.New(sha1.New, chp[:])
k2.Write(tkPlus)
k := append(k1.Sum(nil), k2.Sum(nil)...)
iv := k[len(k)-8:]
key := k[:24]
log.Warnf("key=%s iv=%s", hex.EncodeToString(key), hex.EncodeToString(iv))
return Des3Decrypt(key, iv, encrypted)
}
func decryptNss(globalSalt, masterPwd, nssIv, entrySalt, encrypted []byte, iter, keySize int) ([]byte, error) {
k := sha1.Sum(globalSalt)
log.Println(hex.EncodeToString(k[:]))
key := pbkdf2.Key(k[:], entrySalt, iter, keySize, sha256.New)
log.Println(hex.EncodeToString(key))
i, err := hex.DecodeString("040e")
if err != nil {
log.Println(err)
}
// @https://hg.mozilla.org/projects/nss/rev/fc636973ad06392d11597620b602779b4af312f6#l6.49
iv := append(i, nssIv...)
dst, err := aes128CBCDecrypt(key, iv, encrypted)
if err != nil {
log.Println(err)
}
return dst, err
}
-260
View File
@@ -1,260 +0,0 @@
package utils
import (
"crypto/aes"
"crypto/cipher"
"crypto/sha1"
"crypto/sha256"
"encoding/asn1"
"encoding/base64"
"encoding/hex"
"errors"
"hack-browser-data/log"
"os"
"strings"
"syscall"
"unsafe"
"golang.org/x/crypto/pbkdf2"
"github.com/tidwall/gjson"
)
const (
chromeProfilePath = "/AppData/Local/Google/Chrome/User Data/*/"
chromeKeyPath = "/AppData/Local/Google/Chrome/User Data/Local State"
edgeProfilePath = "/AppData/Local/Microsoft/Edge/User Data/*/"
edgeKeyPath = "/AppData/Local/Microsoft/Edge/User Data/Local State"
speed360ProfilePath = "/AppData/Local/360chrome/Chrome/User Data/*/"
speed360KeyPath = ""
qqBrowserProfilePath = "/AppData/Local/Tencent/QQBrowser/User Data/*/"
qqBrowserKeyPath = ""
firefoxProfilePath = "/AppData/Roaming/Mozilla/Firefox/Profiles/*.default-release/"
firefoxKeyPath = ""
)
var (
chromeKey []byte
browserList = map[string]struct {
ProfilePath string
KeyPath string
}{
"chrome": {
chromeProfilePath,
chromeKeyPath,
},
"edge": {
edgeProfilePath,
edgeKeyPath,
},
"360speed": {
speed360ProfilePath,
speed360KeyPath,
},
"qq": {
qqBrowserProfilePath,
qqBrowserKeyPath,
},
"firefox": {
firefoxProfilePath,
"",
},
}
)
func PickBrowser(name string) (browserDir, key string, err error) {
name = strings.ToLower(name)
if choice, ok := browserList[name]; ok {
if choice.KeyPath != "" {
return os.Getenv("USERPROFILE") + choice.ProfilePath, os.Getenv("USERPROFILE") + choice.KeyPath, nil
} else {
return os.Getenv("USERPROFILE") + choice.ProfilePath, "", nil
}
}
return "", "", errBrowserNotSupported
}
var (
errBase64DecodeFailed = errors.New("decode base64 failed")
)
func InitKey(key string) error {
if key == "" {
VersionUnder80 = true
return nil
}
keyFile, err := ReadFile(key)
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
}
chromeKey, err = decryptStringWithDPAPI(pureKey[5:])
return nil
} else {
VersionUnder80 = true
return nil
}
}
func DecryptChromePass(encryptPass []byte) (string, error) {
if len(encryptPass) > 15 {
// remove prefix 'v10'
return aesGCMDecrypt(encryptPass[15:], chromeKey, encryptPass[3:15])
} else {
return "", errPasswordIsEmpty
}
}
// 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 "", err
}
blockMode, err := cipher.NewGCM(block)
origData, err := blockMode.Open(nil, nounce, crypted, 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
}
defer procLocalFree.Call(uintptr(unsafe.Pointer(outBlob.pbData)))
return outBlob.ToByteArray(), nil
}
func DecryptStringWithDPAPI(data []byte) (string, 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 "", err
}
defer procLocalFree.Call(uintptr(unsafe.Pointer(outBlob.pbData)))
return string(outBlob.ToByteArray()), nil
}
type NssPBE struct {
SequenceA
Encrypted []byte
}
type MetaPBE struct {
SequenceA
Encrypted []byte
}
type SequenceA struct {
PKCS5PBES2 asn1.ObjectIdentifier
SequenceB
}
type SequenceB struct {
SequenceC
SequenceD
}
type SequenceC struct {
PKCS5PBKDF2 asn1.ObjectIdentifier
SequenceE
}
type SequenceD struct {
AES256CBC asn1.ObjectIdentifier
IV []byte
}
type SequenceE struct {
EntrySalt []byte
IterationCount int
KeySize int
SequenceF
}
type SequenceF struct {
HMACWithSHA256 asn1.ObjectIdentifier
}
func DecodeMeta(decodeItem []byte) (pbe MetaPBE, err error) {
_, err = asn1.Unmarshal(decodeItem, &pbe)
if err != nil {
log.Error(err)
return
}
return
}
func DecodeNss(nssA11Bytes []byte) (pbe NssPBE, err error) {
log.Debug(hex.EncodeToString(nssA11Bytes))
_, err = asn1.Unmarshal(nssA11Bytes, &pbe)
if err != nil {
log.Error(err)
return
}
return
}
func DecryptMeta(globalSalt, masterPwd []byte, pbe MetaPBE) ([]byte, error) {
return decryptMeta(globalSalt, masterPwd, pbe.IV, pbe.EntrySalt, pbe.Encrypted, pbe.IterationCount, pbe.KeySize)
}
func DecryptNss(globalSalt, masterPwd []byte, pbe NssPBE) ([]byte, error) {
return decryptMeta(globalSalt, masterPwd, pbe.IV, pbe.EntrySalt, pbe.Encrypted, pbe.IterationCount, pbe.KeySize)
}
func decryptMeta(globalSalt, masterPwd, nssIv, entrySalt, encrypted []byte, iter, keySize int) ([]byte, error) {
k := sha1.Sum(globalSalt)
log.Println(hex.EncodeToString(k[:]))
key := pbkdf2.Key(k[:], entrySalt, iter, keySize, sha256.New)
log.Println(hex.EncodeToString(key))
i, err := hex.DecodeString("040e")
if err != nil {
log.Println(err)
}
// @https://hg.mozilla.org/projects/nss/rev/fc636973ad06392d11597620b602779b4af312f6#l6.49
iv := append(i, nssIv...)
dst, err := aes128CBCDecrypt(key, iv, encrypted)
if err != nil {
log.Println(err)
}
return dst, err
}