diff --git a/core/browser.go b/core/browser.go index 23ff152..2749a25 100644 --- a/core/browser.go +++ b/core/browser.go @@ -46,6 +46,7 @@ const ( cookie = "cookie" history = "history" bookmark = "bookmark" + download = "download" password = "password" creditcard = "creditcard" ) @@ -74,6 +75,10 @@ var ( mainFile: data.ChromeHistoryFile, newItem: data.NewHistoryData, }, + download: { + mainFile: data.ChromeDownloadFile, + newItem: data.NewDownloads, + }, password: { mainFile: data.ChromePasswordFile, newItem: data.NewCPasswords, diff --git a/core/data/output.go b/core/data/output.go index bc3559c..45b7a57 100644 --- a/core/data/output.go +++ b/core/data/output.go @@ -42,6 +42,16 @@ func (h *historyData) outPutJson(browser, dir string) error { return nil } +func (d *downloads) outPutJson(browser, dir string) error { + filename := utils.FormatFileName(dir, browser, "download", "json") + err := writeToJson(filename, d.downloads) + if err != nil { + return err + } + fmt.Printf("%s Get %d history, filename is %s \n", utils.Prefix, len(d.downloads), filename) + return nil +} + func (p *passwords) outPutJson(browser, dir string) error { filename := utils.FormatFileName(dir, browser, "password", "json") err := writeToJson(filename, p.logins) @@ -111,6 +121,15 @@ func (h *historyData) outPutCsv(browser, dir string) error { return nil } +func (d *downloads) outPutCsv(browser, dir string) error { + filename := utils.FormatFileName(dir, browser, "download", "csv") + if err := writeToCsv(filename, d.downloads); err != nil { + return err + } + fmt.Printf("%s Get %d download history, filename is %s \n", utils.Prefix, len(d.downloads), filename) + return nil +} + func (p *passwords) outPutCsv(browser, dir string) error { filename := utils.FormatFileName(dir, browser, "password", "csv") if err := writeToCsv(filename, p.logins); err != nil { @@ -186,6 +205,12 @@ func (h *historyData) outPutConsole() { } } +func (d *downloads) outPutConsole() { + for _, v := range d.downloads { + fmt.Printf("%+v\n", v) + } +} + func (p *passwords) outPutConsole() { for _, v := range p.logins { fmt.Printf("%+v\n", v) diff --git a/core/data/parse.go b/core/data/parse.go index 520aea5..b7756bd 100644 --- a/core/data/parse.go +++ b/core/data/parse.go @@ -39,6 +39,7 @@ const ( ChromeCreditFile = "Web Data" ChromePasswordFile = "Login Data" ChromeHistoryFile = "History" + ChromeDownloadFile = "History" ChromeCookieFile = "Cookies" ChromeBookmarkFile = "Bookmarks" FirefoxCookieFile = "cookies.sqlite" @@ -51,6 +52,7 @@ var ( queryChromiumCredit = `SELECT guid, name_on_card, expiration_month, expiration_year, card_number_encrypted FROM credit_cards` queryChromiumLogin = `SELECT origin_url, username_value, password_value, date_created FROM logins` queryChromiumHistory = `SELECT url, title, visit_count, last_visit_time FROM urls` + queryChromiumDownload = `SELECT target_path, tab_url, total_bytes, start_time, end_time, mime_type FROM downloads` queryChromiumCookie = `SELECT name, encrypted_value, host_key, path, creation_utc, expires_utc, is_secure, is_httponly, has_expires, is_persistent FROM cookies` queryFirefoxHistory = `SELECT id, url, last_visit_date, title, visit_count FROM moz_places` queryFirefoxBookMarks = `SELECT id, fk, type, dateAdded, title FROM moz_bookmarks` @@ -447,6 +449,82 @@ func (h *historyData) OutPut(format, browser, dir string) error { } } +type downloads struct { + mainPath string + downloads []download +} + +func NewDownloads(main, sub string) Item { + return &downloads{mainPath: main} +} + +func (d *downloads) ChromeParse(key []byte) error { + historyDB, err := sql.Open("sqlite3", ChromeDownloadFile) + if err != nil { + return err + } + defer func() { + if err := historyDB.Close(); err != nil { + log.Error(err) + } + }() + rows, err := historyDB.Query(queryChromiumDownload) + if err != nil { + return err + } + defer func() { + if err := rows.Close(); err != nil { + log.Error(err) + } + }() + for rows.Next() { + var ( + targetPath, tabUrl, mimeType string + totalBytes, startTime, endTime int64 + ) + err := rows.Scan(&targetPath, &tabUrl, &totalBytes, &startTime, &endTime, &mimeType) + data := download{ + TargetPath: targetPath, + Url: tabUrl, + TotalBytes: totalBytes, + StartTime: utils.TimeEpochFormat(startTime), + EndTime: utils.TimeEpochFormat(endTime), + MimiType: mimeType, + } + if err != nil { + log.Error(err) + } + d.downloads = append(d.downloads, data) + } + return nil +} + +func (d *downloads) FirefoxParse() error { + return nil +} + +func (d *downloads) CopyDB() error { + return copyToLocalPath(d.mainPath, filepath.Base(d.mainPath)) +} + +func (d *downloads) Release() error { + return os.Remove(filepath.Base(d.mainPath)) +} + +func (d *downloads) OutPut(format, browser, dir string) error { + switch format { + case "csv": + err := d.outPutCsv(browser, dir) + return err + case "console": + d.outPutConsole() + return nil + default: + err := d.outPutJson(browser, dir) + return err + } +} + type passwords struct { mainPath string subPath string @@ -806,6 +884,14 @@ type ( VisitCount int LastVisitTime time.Time } + download struct { + TargetPath string + Url string + TotalBytes int64 + StartTime time.Time + EndTime time.Time + MimiType string + } card struct { GUID string Name string @@ -827,6 +913,18 @@ func (p passwords) Swap(i, j int) { p.logins[i], p.logins[j] = p.logins[j], p.logins[i] } +func (d downloads) Len() int { + return len(d.downloads) +} + +func (d downloads) Less(i, j int) bool { + return d.downloads[i].StartTime.After(d.downloads[j].StartTime) +} + +func (d downloads) Swap(i, j int) { + d.downloads[i], d.downloads[j] = d.downloads[j], d.downloads[i] +} + func copyToLocalPath(src, dst string) error { locals, _ := filepath.Glob("*") for _, v := range locals {