You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
HackBrowserData/browserdata/cookie.go

131 lines
3.3 KiB

package browserdata
import (
"database/sql"
"os"
"path/filepath"
"sort"
"time"
"github.com/moond4rk/hackbrowserdata/crypto"
"github.com/moond4rk/hackbrowserdata/log"
"github.com/moond4rk/hackbrowserdata/utils/fileutil"
"github.com/moond4rk/hackbrowserdata/utils/typeutil"
)
type CookieExtractor struct {
Data []Cookie
masterKey []byte
datafile string
}
func NewCookieExtractor(masterKey []byte, datafile string) *CookieExtractor {
return &CookieExtractor{masterKey: masterKey, datafile: datafile}
}
type Cookie struct {
Host string
Path string
KeyName string
encryptValue []byte
Value string
IsSecure bool
IsHTTPOnly bool
HasExpire bool
IsPersistent bool
CreateDate time.Time
ExpireDate time.Time
}
func ExportCookie(masterKey []byte, passwordPath string) ([]Cookie, error) {
tempPassFile := filepath.Join(os.TempDir(), filepath.Base(passwordPath))
if err := fileutil.CopyFile(passwordPath, tempPassFile); err != nil {
return nil, err
}
defer os.Remove(tempPassFile)
cookies, err := exportCookies(masterKey, "", tempPassFile)
if err != nil {
return nil, err
}
return cookies, err
}
func exportCookies(masterKey []byte, profile, dbFile string) ([]Cookie, error) {
data, err := exportData(masterKey, profile, dbFile, handlerCookie)
if err != nil {
return nil, err
}
cookies := make([]Cookie, 0, len(data))
for _, v := range data {
cookies = append(cookies, v.(Cookie))
}
sort.Slice(cookies, func(i, j int) bool {
return (cookies)[i].CreateDate.After((cookies)[j].CreateDate)
})
return cookies, nil
}
type rowHandlerFunc func(masterKey []byte, rows *sql.Rows) (interface{}, error)
func handlerCookie(masterKey []byte, rows *sql.Rows) (interface{}, error) {
var (
err error
key, host, path string
isSecure, isHTTPOnly, hasExpire, isPersistent int
createDate, expireDate int64
value, encryptValue []byte
)
if err = rows.Scan(&key, &encryptValue, &host, &path, &createDate, &expireDate, &isSecure, &isHTTPOnly, &hasExpire, &isPersistent); err != nil {
log.Warn(err)
}
cookie := Cookie{
KeyName: key,
Host: host,
Path: path,
encryptValue: encryptValue,
IsSecure: typeutil.IntToBool(isSecure),
IsHTTPOnly: typeutil.IntToBool(isHTTPOnly),
HasExpire: typeutil.IntToBool(hasExpire),
IsPersistent: typeutil.IntToBool(isPersistent),
CreateDate: typeutil.TimeEpoch(createDate),
ExpireDate: typeutil.TimeEpoch(expireDate),
}
if len(encryptValue) > 0 {
if len(masterKey) == 0 {
value, err = crypto.DPAPI(encryptValue)
} else {
value, err = crypto.DecryptPass(masterKey, encryptValue)
}
if err != nil {
log.Error(err)
}
}
cookie.Value = string(value)
return cookie, nil
}
func exportData(masterKey []byte, passFile string, query string, rowHandler rowHandlerFunc) ([]interface{}, error) {
db, err := sql.Open("sqlite3", passFile)
if err != nil {
return nil, err
}
defer db.Close()
rows, err := db.Query(query)
if err != nil {
return nil, err
}
defer rows.Close()
var data []interface{}
for rows.Next() {
item, err := rowHandler(masterKey, rows)
if err != nil {
log.Warn(err)
continue
}
data = append(data, item)
}
return data, nil
}