diff --git a/.gitignore b/.gitignore index ef364b0..5ced80a 100644 --- a/.gitignore +++ b/.gitignore @@ -181,4 +181,7 @@ Cookies hack-browser-data History *.db +*.sqlite +*.sqlite-shm +*.sqlite-wal diff --git a/cmd/cmd.go b/cmd/cmd.go index b2137b6..e10ae2d 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -23,7 +23,7 @@ func Execute() { Name: "hack-browser-data", Usage: "Export passwords/cookies/history/bookmarks from browser", UsageText: "[hack-browser-data -b chrome -f json -dir results -e all]\n Get all data(password/cookie/history/bookmark) from chrome", - Version: "0.1.0", + Version: "0.1.7", Flags: []cli.Flag{ &cli.BoolFlag{Name: "verbose", Aliases: []string{"vv"}, Destination: &verbose, Value: false, Usage: "Verbose"}, &cli.StringFlag{Name: "browser", Aliases: []string{"b"}, Destination: &browser, Value: "all", Usage: "Available browsers: all|" + strings.Join(core.ListBrowser(), "|")}, diff --git a/core/common/output.go b/core/common/output.go index 4c9cef6..d5de39a 100644 --- a/core/common/output.go +++ b/core/common/output.go @@ -3,6 +3,7 @@ package common import ( "bytes" "encoding/json" + "errors" "fmt" "os" @@ -12,29 +13,16 @@ import ( "github.com/jszwec/csvutil" ) -var utf8Bom = []byte{239, 187, 191} +var ( + utf8Bom = []byte{239, 187, 191} + errWriteToFile = errors.New("write to file failed") +) func (b *Bookmarks) OutPutJson(browser, dir string) error { filename := utils.FormatFileName(dir, browser, "bookmark", "json") - file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC|os.O_APPEND, 0644) - defer func() { - if err := file.Close(); err != nil { - log.Error(err) - } - }() - - if err != nil { - log.Errorf("create file %s fail", filename) - return err - } - w := new(bytes.Buffer) - enc := json.NewEncoder(w) - enc.SetEscapeHTML(false) - enc.SetIndent("", "\t") - enc.Encode(b.bookmarks) - _, err = file.Write(w.Bytes()) + err := writeToJson(filename, b.bookmarks) if err != nil { - log.Error(err) + log.Error(errWriteToFile) return err } fmt.Printf("%s Get %d bookmarks, filename is %s \n", log.Prefix, len(b.bookmarks), filename) @@ -43,27 +31,9 @@ func (b *Bookmarks) OutPutJson(browser, dir string) error { func (h *History) OutPutJson(browser, dir string) error { filename := utils.FormatFileName(dir, browser, "history", "json") - file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC|os.O_APPEND, 0644) - defer func() { - if err := file.Close(); err != nil { - log.Error(err) - } - }() + err := writeToJson(filename, h.history) if err != nil { - log.Errorf("create file %s fail", filename) - return err - } - w := new(bytes.Buffer) - enc := json.NewEncoder(w) - enc.SetEscapeHTML(false) - enc.SetIndent("", "\t") - err = enc.Encode(h.history) - if err != nil { - log.Debug(err) - } - _, err = file.Write(w.Bytes()) - if err != nil { - log.Error(err) + log.Error(errWriteToFile) return err } fmt.Printf("%s Get %d history, filename is %s \n", log.Prefix, len(h.history), filename) @@ -72,27 +42,9 @@ func (h *History) OutPutJson(browser, dir string) error { func (l *Logins) OutPutJson(browser, dir string) error { filename := utils.FormatFileName(dir, browser, "password", "json") - file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC|os.O_APPEND, 0644) - defer func() { - if err := file.Close(); err != nil { - log.Error(err) - } - }() + err := writeToJson(filename, l.logins) if err != nil { - log.Errorf("create file %s fail", filename) - return err - } - w := new(bytes.Buffer) - enc := json.NewEncoder(w) - enc.SetEscapeHTML(false) - enc.SetIndent("", "\t") - err = enc.Encode(l.logins) - if err != nil { - log.Debug(err) - } - _, err = file.Write(w.Bytes()) - if err != nil { - log.Error(err) + log.Error(errWriteToFile) return err } fmt.Printf("%s Get %d passwords, filename is %s \n", log.Prefix, len(l.logins), filename) @@ -101,119 +53,111 @@ func (l *Logins) OutPutJson(browser, dir string) error { func (c *Cookies) OutPutJson(browser, dir string) error { filename := utils.FormatFileName(dir, browser, "cookie", "json") - file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC|os.O_APPEND, 0644) + err := writeToJson(filename, c.cookies) + if err != nil { + log.Error(errWriteToFile) + return err + } + fmt.Printf("%s Get %d cookies, filename is %s \n", log.Prefix, len(c.cookies), filename) + return nil +} + +func writeToJson(filename string, data interface{}) error { + f, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC|os.O_APPEND, 0644) + if err != nil { + return err + } defer func() { - if err := file.Close(); err != nil { + if err := f.Close(); err != nil { log.Error(err) } }() - if err != nil { - log.Errorf("create file %s fail", filename) - return err - } w := new(bytes.Buffer) enc := json.NewEncoder(w) enc.SetEscapeHTML(false) enc.SetIndent("", "\t") - err = enc.Encode(c.cookies) + err = enc.Encode(data) if err != nil { log.Debug(err) return err } - _, err = file.Write(w.Bytes()) + _, err = f.Write(w.Bytes()) if err != nil { log.Error(err) return err } - fmt.Printf("%s Get %d cookies, filename is %s \n", log.Prefix, len(c.cookies), filename) return nil } func (b *Bookmarks) OutPutCsv(browser, dir string) error { filename := utils.FormatFileName(dir, browser, "bookmark", "csv") - file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC|os.O_APPEND, 0644) - defer func() { - if err := file.Close(); err != nil { - log.Error(err) - } - }() - if err != nil { - log.Errorf("create file %s fail %s", filename, err) + if err := writeToCsv(filename, b.bookmarks); err != nil { + log.Error(errWriteToFile) return err } - file.Write(utf8Bom) - data, err := csvutil.Marshal(b.bookmarks) - if err != nil { - return err - } - file.Write(data) fmt.Printf("%s Get %d bookmarks, filename is %s \n", log.Prefix, len(b.bookmarks), filename) return nil } func (h *History) OutPutCsv(browser, dir string) error { filename := utils.FormatFileName(dir, browser, "history", "csv") - file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC|os.O_APPEND, 0644) - defer func() { - if err := file.Close(); err != nil { - log.Error(err) - } - }() - if err != nil { - log.Errorf("create file %s fail %s", filename, err) - return err - } - file.Write(utf8Bom) - data, err := csvutil.Marshal(h.history) - if err != nil { + if err := writeToCsv(filename, h.history); err != nil { + log.Error(errWriteToFile) return err } - file.Write(data) fmt.Printf("%s Get %d history, filename is %s \n", log.Prefix, len(h.history), filename) return nil } func (l *Logins) OutPutCsv(browser, dir string) error { filename := utils.FormatFileName(dir, browser, "password", "csv") - file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC|os.O_APPEND, 0644) - defer func() { - if err := file.Close(); err != nil { - log.Error(err) - } - }() - if err != nil { - log.Errorf("create file %s fail %s", filename, err) + if err := writeToCsv(filename, l.logins); err != nil { + log.Error(errWriteToFile) return err } - file.Write(utf8Bom) - data, err := csvutil.Marshal(l.logins) - if err != nil { - return err - } - file.Write(data) fmt.Printf("%s Get %d passwords, filename is %s \n", log.Prefix, len(l.logins), filename) return nil } func (c *Cookies) OutPutCsv(browser, dir string) error { filename := utils.FormatFileName(dir, browser, "cookie", "csv") - file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC|os.O_APPEND, 0644) + var tempSlice []cookies + for _, v := range c.cookies { + tempSlice = append(tempSlice, v...) + } + if err := writeToCsv(filename, tempSlice); err != nil { + log.Error(errWriteToFile) + return err + } + fmt.Printf("%s Get %d cookies, filename is %s \n", log.Prefix, len(c.cookies), filename) + return nil +} + +func writeToCsv(filename string, data interface{}) error { + var d []byte + f, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC|os.O_APPEND, 0644) + if err != nil { + log.Errorf("create file %s fail %s", filename, err) + return err + } defer func() { - if err := file.Close(); err != nil { + if err := f.Close(); err != nil { log.Error(err) } }() + _, err = f.Write(utf8Bom) if err != nil { - log.Errorf("create file %s fail", filename) + log.Error(err) return err } - var tempSlice []cookies - for _, v := range c.cookies { - tempSlice = append(tempSlice, v...) + d, err = csvutil.Marshal(data) + if err != nil { + return err + } + _, err = f.Write(d) + if err != nil { + log.Error(err) + return err } - file.Write(utf8Bom) - data, err := csvutil.Marshal(tempSlice) - file.Write(data) - fmt.Printf("%s Get %d cookies, filename is %s \n", log.Prefix, len(c.cookies), filename) return nil } diff --git a/core/common/parse.go b/core/common/parse.go index 694e10c..8e5df35 100644 --- a/core/common/parse.go +++ b/core/common/parse.go @@ -5,7 +5,6 @@ import ( "database/sql" "encoding/base64" "io/ioutil" - "os" "sort" "time" @@ -98,13 +97,8 @@ const ( func (b *Bookmarks) ChromeParse(key []byte) error { bookmarks, err := utils.ReadFile(ChromeBookmarks) - defer func() { - if err := os.Remove(ChromeBookmarks); err != nil { - log.Error(err) - } - }() if err != nil { - log.Debug(err) + log.Error(err) return err } r := gjson.Parse(bookmarks) @@ -119,22 +113,16 @@ func (b *Bookmarks) ChromeParse(key []byte) error { } func (l *Logins) ChromeParse(key []byte) error { - login := loginData{} loginDB, err := sql.Open("sqlite3", ChromePassword) - defer func() { - if err := os.Remove(ChromePassword); err != nil { - log.Error(err) - } - }() + if err != nil { + log.Error(err) + return err + } defer func() { if err := loginDB.Close(); err != nil { log.Debug(err) } }() - if err != nil { - log.Debug(err) - return err - } err = loginDB.Ping() var queryLogin = `SELECT origin_url, username_value, password_value, date_created FROM logins` rows, err := loginDB.Query(queryLogin) @@ -150,7 +138,7 @@ func (l *Logins) ChromeParse(key []byte) error { create int64 ) err = rows.Scan(&url, &username, &pwd, &create) - login = loginData{ + login := loginData{ UserName: username, encryptPass: pwd, LoginUrl: url, @@ -176,12 +164,13 @@ func (l *Logins) ChromeParse(key []byte) error { } func getBookmarkChildren(value gjson.Result, b *Bookmarks) (children gjson.Result) { - bm := bookmark{} - bm.ID = value.Get(bookmarkID).Int() nodeType := value.Get(bookmarkType) - bm.DateAdded = utils.TimeEpochFormat(value.Get(bookmarkAdded).Int()) - bm.URL = value.Get(bookmarkUrl).String() - bm.Name = value.Get(bookmarkName).String() + bm := bookmark{ + ID: value.Get(bookmarkID).Int(), + Name: value.Get(bookmarkName).String(), + URL: value.Get(bookmarkUrl).String(), + DateAdded: utils.TimeEpochFormat(value.Get(bookmarkAdded).Int()), + } children = value.Get(bookmarkChildren) if nodeType.Exists() { bm.Type = nodeType.String() @@ -196,22 +185,16 @@ func getBookmarkChildren(value gjson.Result, b *Bookmarks) (children gjson.Resul } func (h *History) ChromeParse(key []byte) error { - data := history{} historyDB, err := sql.Open("sqlite3", ChromeHistory) - defer func() { - if err := os.Remove(ChromeHistory); err != nil { - log.Error(err) - } - }() + if err != nil { + log.Error(err) + return err + } defer func() { if err := historyDB.Close(); err != nil { - log.Debug(err) + log.Error(err) } }() - if err != nil { - log.Debug(err) - return err - } err = historyDB.Ping() var queryHistory = `SELECT url, title, visit_count, last_visit_time FROM urls` rows, err := historyDB.Query(queryHistory) @@ -227,14 +210,14 @@ func (h *History) ChromeParse(key []byte) error { lastVisitTime int64 ) err := rows.Scan(&url, &title, &visitCount, &lastVisitTime) - data = history{ + data := history{ Url: url, Title: title, VisitCount: visitCount, LastVisitTime: utils.TimeEpochFormat(lastVisitTime), } if err != nil { - log.Debug(err) + log.Error(err) continue } h.history = append(h.history, data) @@ -243,26 +226,19 @@ func (h *History) ChromeParse(key []byte) error { } func (c *Cookies) ChromeParse(secretKey []byte) error { - cookie := cookies{} c.cookies = make(map[string][]cookies) cookieDB, err := sql.Open("sqlite3", ChromeCookies) - defer func() { - if err := os.Remove(ChromeCookies); err != nil { - log.Error(err) - } - }() + if err != nil { + log.Debug(err) + return err + } defer func() { if err := cookieDB.Close(); err != nil { log.Debug(err) } }() - if err != nil { - log.Debug(err) - return err - } err = cookieDB.Ping() var queryCookie = `SELECT name, encrypted_value, host_key, path, creation_utc, expires_utc, is_secure, is_httponly, has_expires, is_persistent FROM cookies` - rows, err := cookieDB.Query(queryCookie) defer func() { if err := rows.Close(); err != nil { @@ -277,7 +253,7 @@ func (c *Cookies) ChromeParse(secretKey []byte) error { value, encryptValue []byte ) err = rows.Scan(&key, &encryptValue, &host, &path, &createDate, &expireDate, &isSecure, &isHTTPOnly, &hasExpire, &isPersistent) - cookie = cookies{ + cookie := cookies{ KeyName: key, Host: host, Path: path, @@ -308,6 +284,7 @@ func (c *Cookies) ChromeParse(secretKey []byte) error { func (h *History) FirefoxParse() error { var queryFirefoxHistory = `SELECT id, url, title, last_visit_date, visit_count FROM moz_places` + var closeJournalMode = `PRAGMA journal_mode=off` var ( err error keyDB *sql.DB @@ -320,14 +297,12 @@ func (h *History) FirefoxParse() error { log.Error(err) return err } + _, err = keyDB.Exec(closeJournalMode) + if err != nil { + log.Error(err) + } defer func() { - if err := os.Remove(FirefoxData); err != nil { - log.Error(err) - } - }() - defer func() { - err := keyDB.Close() - if err != nil { + if err := keyDB.Close(); err != nil { log.Error(err) } }() @@ -360,6 +335,8 @@ func (h *History) FirefoxParse() error { } func (b *Bookmarks) FirefoxParse() error { + var queryFirefoxBookMarks = `SELECT id, fk, type, dateAdded, title FROM moz_bookmarks` + var closeJournalMode = `PRAGMA journal_mode=off` var ( err error keyDB *sql.DB @@ -367,17 +344,15 @@ func (b *Bookmarks) FirefoxParse() error { tempMap map[int64]string bookmarkUrl string ) - var queryFirefoxBookMarks = `SELECT id, fk, type, dateAdded, title FROM moz_bookmarks` keyDB, err = sql.Open("sqlite3", FirefoxData) if err != nil { log.Error(err) return err } - defer func() { - if err := os.Remove(FirefoxData); err != nil { - log.Error(err) - } - }() + _, err = keyDB.Exec(closeJournalMode) + if err != nil { + log.Error(err) + } bookmarkRows, err = keyDB.Query(queryFirefoxBookMarks) defer func() { if err := bookmarkRows.Close(); err != nil { @@ -414,11 +389,6 @@ func (c *Cookies) FirefoxParse() error { log.Debug(err) return err } - defer func() { - if err := os.Remove(FirefoxCookie); err != nil { - log.Debug(err) - } - }() defer func() { if err := cookieDB.Close(); err != nil { log.Debug(err) @@ -534,20 +504,16 @@ func getDecryptKey() (item1, item2, a11, a102 []byte, err error) { pwdRows *sql.Rows nssRows *sql.Rows ) - defer func() { - if err := os.Remove(FirefoxKey4DB); err != nil { - log.Error(err) - } - }() keyDB, err = sql.Open("sqlite3", FirefoxKey4DB) + if err != nil { + log.Error(err) + return nil, nil, nil, nil, err + } defer func() { if err := keyDB.Close(); err != nil { log.Error(err) } }() - if err != nil { - log.Debug(err) - } var queryPassword = `SELECT item1, item2 FROM metaData WHERE id = 'password'` var queryNssPrivate = `SELECT a11, a102 from nssPrivate` err = keyDB.Ping() @@ -585,11 +551,6 @@ func getLoginData() (l []loginData, err error) { if err != nil { return nil, err } - defer func() { - if err := os.Remove(FirefoxLoginData); err != nil { - log.Error(err) - } - }() h := gjson.GetBytes(s, "logins") if h.Exists() { for _, v := range h.Array() { diff --git a/utils/utils.go b/utils/utils.go index f1bb4a8..32e1144 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -82,8 +82,7 @@ func WriteFile(filename string, data []byte) error { } func FormatFileName(dir, browser, filename, format string) string { - r := strings.TrimSpace(strings.ToLower(browser)) - r = strings.Replace(browser, " ", "_", -1) + r := strings.Replace(strings.TrimSpace(strings.ToLower(browser)), " ", "_", -1) p := path.Join(dir, fmt.Sprintf("%s_%s.%s", r, filename, format)) return p }