From 147024cf3a1a6b67eed4f4bf5202cb615f5c8c96 Mon Sep 17 00:00:00 2001 From: attacus Date: Wed, 3 Dec 2025 20:19:22 +1100 Subject: [PATCH 1/3] adding support for the Comet browser --- filesystem/browsers/BrowserModule.swift | 7 +- filesystem/browsers/Comet.swift | 229 ++++++++++++++++++++++++ 2 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 filesystem/browsers/Comet.swift diff --git a/filesystem/browsers/BrowserModule.swift b/filesystem/browsers/BrowserModule.swift index 15de98b..7ac877b 100644 --- a/filesystem/browsers/BrowserModule.swift +++ b/filesystem/browsers/BrowserModule.swift @@ -23,6 +23,7 @@ class BrowserModule: AftermathModule, AMProto { let safariDir = self.createNewDir(dir: moduleDirRoot, dirname: "Safari") let arcDir = self.createNewDir(dir: moduleDirRoot, dirname: "Arc") let braveDir = self.createNewDir(dir: moduleDirRoot, dirname: "Brave") + let cometDir = self.createNewDir(dir: moduleDirRoot, dirname: "Comet") let writeFile = self.createNewCaseFile(dirUrl: moduleDirRoot, filename: "browsers.txt") self.log("Collecting browser information. Checking for open browsers. Closing any open browsers...") @@ -57,10 +58,14 @@ class BrowserModule: AftermathModule, AMProto { // Check if Brave is installed let brave = Brave(braveDir: braveDir, writeFile: writeFile) brave.run() + + // Check if Comet is installed + let comet = Comet(cometDir: cometDir, writeFile: writeFile) + comet.run() } func closeBrowsers() { - let browserData = ["/Applications/Microsoft Edge.app": "com.microsoft.edgemac", "/Applications/Firefox.app": "org.mozilla.firefox", "/Applications/Google Chrome.app": "com.google.Chrome", "/Applications/Safari.app": "com.apple.Safari", "/Applications/Arc.app": "company.thebrowser.Browser"] + let browserData = ["/Applications/Microsoft Edge.app": "com.microsoft.edgemac", "/Applications/Firefox.app": "org.mozilla.firefox", "/Applications/Google Chrome.app": "com.google.Chrome", "/Applications/Safari.app": "com.apple.Safari", "/Applications/Arc.app": "company.thebrowser.Browser", "/Applications/Comet.app": "ai.perplexity.comet"] for (key, value) in browserData { if filemanager.fileExists(atPath: key) { diff --git a/filesystem/browsers/Comet.swift b/filesystem/browsers/Comet.swift new file mode 100644 index 0000000..08834cb --- /dev/null +++ b/filesystem/browsers/Comet.swift @@ -0,0 +1,229 @@ +// +// Chrome.swift +// aftermath +// +// Copyright 2022 JAMF Software, LLC +// + +import Foundation +import SQLite3 + +class Chrome: BrowserModule { + + let chromeDir: URL + let writeFile: URL + + init(chromeDir: URL, writeFile: URL) { + self.chromeDir = chromeDir + self.writeFile = writeFile + } + + func gatherHistory() { + + let historyOutput = self.createNewCaseFile(dirUrl: self.chromeDir, filename: "history_output.csv") + self.addTextToFile(atUrl: historyOutput, text: "datetime,user,profile,url") + + for user in getBasicUsersOnSystem() { + for profile in getChromeProfilesForUser(user: user) { + + // Get the history file for the profile + var file: URL + if filemanager.fileExists(atPath: "\(user.homedir)/Library/Application Support/Google/Chrome/\(profile)/History") { + file = URL(fileURLWithPath: "\(user.homedir)/Library/Application Support/Google/Chrome/\(profile)/History") + self.copyFileToCase(fileToCopy: file, toLocation: self.chromeDir, newFileName: "history_and_downloads_\(user.username)_\(profile).db") + } else { continue } + + // Open the history file + var db: OpaquePointer? + if sqlite3_open(file.path, &db) == SQLITE_OK { + + // Query the history file + var queryStatement: OpaquePointer? = nil + let queryString = "SELECT datetime(((v.visit_time/1000000)-11644473600), 'unixepoch'), u.url FROM visits v INNER JOIN urls u ON u.id = v.url;" + + if sqlite3_prepare_v2(db, queryString, -1, &queryStatement, nil) == SQLITE_OK { + var dateTime: String = "" + var url: String = "" + + // write the results to the historyOutput file + while sqlite3_step(queryStatement) == SQLITE_ROW { + if let col1 = sqlite3_column_text(queryStatement, 0) { + let unformattedDatetime = String(cString: col1) + dateTime = Aftermath.standardizeMetadataTimestamp(timeStamp: unformattedDatetime) + } + + let col2 = sqlite3_column_text(queryStatement, 1) + if col2 != nil { + url = String(cString: col2!) + } + + self.addTextToFile(atUrl: historyOutput, text: "\(dateTime),\(user.username),\(profile),\(url)") + } + } else { self.log("Unable to query the database. Please ensure that Chrome is not running.") } + } else { self.log("Unable to open the database") } + } + } + } + + func dumpDownloads() { + self.addTextToFile(atUrl: self.writeFile, text: "----- Chrome Downloads: -----\n") + + let downlaodsRaw = self.createNewCaseFile(dirUrl: self.chromeDir, filename: "downloads_output.csv") + self.addTextToFile(atUrl: downlaodsRaw, text: "datetime,user,profile,url,target_path,danger_type,opened") + + for user in getBasicUsersOnSystem() { + for profile in getChromeProfilesForUser(user: user) { + var file: URL + if filemanager.fileExists(atPath: "\(user.homedir)/Library/Application Support/Google/Chrome/\(profile)/History") { + file = URL(fileURLWithPath: "\(user.homedir)/Library/Application Support/Google/Chrome/\(profile)/History") + } else { continue } + + var db: OpaquePointer? + if sqlite3_open(file.path, &db) == SQLITE_OK { + var queryStatement: OpaquePointer? = nil + let queryString = "SELECT datetime(d.start_time/1000000-11644473600, 'unixepoch'), dc.url, d.target_path, d.danger_type, d.opened FROM downloads d INNER JOIN downloads_url_chains dc ON dc.id = d.id;" + + if sqlite3_prepare_v2(db, queryString, -1, &queryStatement, nil) == SQLITE_OK { + var dateTime: String = "" + var url: String = "" + var targetPath: String = "" + var dangerType: String = "" + var opened: String = "" + + while sqlite3_step(queryStatement) == SQLITE_ROW { + if let col1 = sqlite3_column_text(queryStatement, 0) { + let unformattedDatetime = String(cString: col1) + dateTime = Aftermath.standardizeMetadataTimestamp(timeStamp: unformattedDatetime) + } + + let col2 = sqlite3_column_text(queryStatement, 1) + if let col2 = col2 { url = String(cString: col2) } + + let col3 = sqlite3_column_text(queryStatement, 2) + if let col3 = col3 { targetPath = String(cString: col3) } + + let col4 = sqlite3_column_text(queryStatement, 3) + if let col4 = col4 { dangerType = String(cString: col4) } + + let col5 = sqlite3_column_text(queryStatement, 4) + if let col5 = col5 { opened = String(cString: col5) } + + self.addTextToFile(atUrl: downlaodsRaw, text: " \(dateTime),\(user.username),\(profile),\(url),\(targetPath),\(dangerType),\(opened)") + } + } + } + } + } + + self.addTextToFile(atUrl: self.writeFile, text: "\n----- End of Chrome Downloads -----\n") + } + + func dumpPreferences() { + for user in getBasicUsersOnSystem() { + for profile in getChromeProfilesForUser(user: user) { + var file: URL + if filemanager.fileExists(atPath: "\(user.homedir)/Library/Application Support/Google/Chrome/\(profile)/Preferences") { + file = URL(fileURLWithPath: "\(user.homedir)/Library/Application Support/Google/Chrome/\(profile)/Preferences") + self.copyFileToCase(fileToCopy: file, toLocation: self.chromeDir, newFileName: "preferences_\(user.username)_\(profile)") + } else { continue } + + do { + let data = try Data(contentsOf: file, options: .mappedIfSafe) + if let json = try JSONSerialization.jsonObject(with: data, options: .mutableLeaves) as? [String: Any] { + self.addTextToFile(atUrl: writeFile, text: "\nChrome Preferences -----\n\(String(describing: json))\n ----- End of Chrome Preferences -----\n") + } + + } catch { self.log("Unable to capture Chrome Preferenes") } + } + } + } + + func dumpCookies() { + self.addTextToFile(atUrl: self.writeFile, text: "----- Chrome Cookies: -----\n") + + for user in getBasicUsersOnSystem() { + for profile in getChromeProfilesForUser(user: user) { + var file: URL + if filemanager.fileExists(atPath: "\(user.homedir)/Library/Application Support/Google/Chrome/\(profile)/Cookies") { + file = URL(fileURLWithPath: "\(user.homedir)/Library/Application Support/Google/Chrome/\(profile)/Cookies") + self.copyFileToCase(fileToCopy: file, toLocation: self.chromeDir, newFileName: "cookies_\(user.username)_\(profile).db") + } else { continue } + + var db: OpaquePointer? + if sqlite3_open(file.path, &db) == SQLITE_OK { + var queryStatement: OpaquePointer? = nil + let queryString = "select datetime(creation_utc/100000 -11644473600, 'unixepoch'), name, host_key, path, datetime(expires_utc/100000-11644473600, 'unixepoch') from cookies;" + + if sqlite3_prepare_v2(db, queryString, -1, &queryStatement, nil) == SQLITE_OK { + var dateTime: String = "" + var name: String = "" + var hostKey: String = "" + var path: String = "" + var expireTime: String = "" + + while sqlite3_step(queryStatement) == SQLITE_ROW { + if let col1 = sqlite3_column_text(queryStatement, 0) { + dateTime = String(cString: col1) + } + + if let col2 = sqlite3_column_text(queryStatement, 1) { + name = String(cString: col2) + } + + if let col3 = sqlite3_column_text(queryStatement, 2) { + hostKey = String(cString: col3) + } + + if let col4 = sqlite3_column_text(queryStatement, 3) { + path = String(cString: col4) + } + + if let col5 = sqlite3_column_text(queryStatement, 4) { + expireTime = String(cString: col5) + } + + self.addTextToFile(atUrl: self.writeFile, text: "DateTime: \(dateTime)\nUser: \(user.username)\nProfile: \(profile)\nName: \(name)\nHostKey: \(hostKey)\nPath:\(path)\nExpireTime: \(expireTime)\n\n") + } + } + } + } + } + self.addTextToFile(atUrl: self.writeFile, text: "\n----- End of Chrome Cookies -----\n") + } + + func captureExtensions() { + for user in getBasicUsersOnSystem() { + for profile in getChromeProfilesForUser(user: user) { + let chromeExtensionDir = self.createNewDir(dir: self.chromeDir, dirname: "extensions_\(user.username)_\(profile)") + let path = "\(user.homedir)/Library/Application Support/Google/Chrome/\(profile)/Extensions" + + for file in filemanager.filesInDirRecursive(path: path) { + self.copyFileToCase(fileToCopy: file, toLocation: chromeExtensionDir) + } + } + } + } + + func getChromeProfilesForUser(user: User) -> [String] { + var profiles: [String] = [] + // Get the directory name if it contains the string "Profile" + if filemanager.fileExists(atPath: "\(user.homedir)/Library/Application Support/Google/Chrome") { + for file in filemanager.filesInDir(path: "\(user.homedir)/Library/Application Support/Google/Chrome") { + if file.lastPathComponent.starts(with: "Profile") || file.lastPathComponent == "Default" { + profiles.append(file.lastPathComponent) + } + } + } + + return profiles + } + + override func run() { + self.log("Collecting Chrome browser information...") + gatherHistory() + dumpDownloads() + dumpPreferences() + dumpCookies() + captureExtensions() + } +} From a3cbfa820bc01a5c5cdbc3dde76d21e1f1f78e2d Mon Sep 17 00:00:00 2001 From: attacus Date: Wed, 3 Dec 2025 21:02:27 +1100 Subject: [PATCH 2/3] updating xcode info --- aftermath.xcodeproj/project.pbxproj | 4 ++ filesystem/browsers/Comet.swift | 76 ++++++++++++++--------------- 2 files changed, 42 insertions(+), 38 deletions(-) diff --git a/aftermath.xcodeproj/project.pbxproj b/aftermath.xcodeproj/project.pbxproj index 096accd..4d84dac 100644 --- a/aftermath.xcodeproj/project.pbxproj +++ b/aftermath.xcodeproj/project.pbxproj @@ -62,6 +62,7 @@ A190FFE328B8168400B9EF9A /* AftermathTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A190FFCF28B8084F00B9EF9A /* AftermathTests.swift */; }; A1E433D928B918FF00E2B510 /* Aftermath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8ABB9E302756D2B500C0ADD7 /* Aftermath.swift */; }; A1E433E528B9270800E2B510 /* dummyPlist.plist in Resources */ = {isa = PBXBuildFile; fileRef = A1E433E428B9270800E2B510 /* dummyPlist.plist */; }; + A202BE352EE03E6B006277CA /* Comet.swift in Sources */ = {isa = PBXBuildFile; fileRef = A202BE342EE03E6B006277CA /* Comet.swift */; }; A3046F8E27627DAC0069AA21 /* Module.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3046F8D27627DAC0069AA21 /* Module.swift */; }; A3046F902763AE5E0069AA21 /* CaseFiles.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3046F8F2763AE5E0069AA21 /* CaseFiles.swift */; }; A31009A42B9B838100068593 /* Network.swift in Sources */ = {isa = PBXBuildFile; fileRef = A31009A32B9B838100068593 /* Network.swift */; }; @@ -144,6 +145,7 @@ A190FFD528B80C3900B9EF9A /* MockFileManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockFileManager.swift; sourceTree = ""; }; A190FFDB28B8151300B9EF9A /* tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; A1E433E428B9270800E2B510 /* dummyPlist.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = dummyPlist.plist; sourceTree = ""; }; + A202BE342EE03E6B006277CA /* Comet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Comet.swift; sourceTree = ""; }; A3046F8D27627DAC0069AA21 /* Module.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Module.swift; sourceTree = ""; }; A3046F8F2763AE5E0069AA21 /* CaseFiles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CaseFiles.swift; sourceTree = ""; }; A31009A32B9B838100068593 /* Network.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Network.swift; sourceTree = ""; }; @@ -300,6 +302,7 @@ A0E1E3E7275EC720008D0DC6 /* browsers */ = { isa = PBXGroup; children = ( + A202BE342EE03E6B006277CA /* Comet.swift */, A0E1E3E8275EC736008D0DC6 /* BrowserModule.swift */, A0E1E3EA275EC800008D0DC6 /* Firefox.swift */, A0E1E3EC275EC809008D0DC6 /* Chrome.swift */, @@ -572,6 +575,7 @@ A374535D2757C1300074B65C /* FileManager.swift in Sources */, A09B239C2848F6050062D592 /* Periodic.swift in Sources */, A0DA61B028625E1D00224810 /* FileWalker.swift in Sources */, + A202BE352EE03E6B006277CA /* Comet.swift in Sources */, A0E1E3ED275EC809008D0DC6 /* Chrome.swift in Sources */, A3046F8E27627DAC0069AA21 /* Module.swift in Sources */, 8ABB9E2B27568EB700C0ADD7 /* UnifiedLogModule.swift in Sources */, diff --git a/filesystem/browsers/Comet.swift b/filesystem/browsers/Comet.swift index 08834cb..5897f0b 100644 --- a/filesystem/browsers/Comet.swift +++ b/filesystem/browsers/Comet.swift @@ -1,5 +1,5 @@ // -// Chrome.swift +// Comet.swift // aftermath // // Copyright 2022 JAMF Software, LLC @@ -8,29 +8,29 @@ import Foundation import SQLite3 -class Chrome: BrowserModule { +class Comet: BrowserModule { - let chromeDir: URL + let cometDir: URL let writeFile: URL - init(chromeDir: URL, writeFile: URL) { - self.chromeDir = chromeDir + init(cometDir: URL, writeFile: URL) { + self.cometDir = cometDir self.writeFile = writeFile } func gatherHistory() { - let historyOutput = self.createNewCaseFile(dirUrl: self.chromeDir, filename: "history_output.csv") + let historyOutput = self.createNewCaseFile(dirUrl: self.cometDir, filename: "history_output.csv") self.addTextToFile(atUrl: historyOutput, text: "datetime,user,profile,url") for user in getBasicUsersOnSystem() { - for profile in getChromeProfilesForUser(user: user) { + for profile in getCometProfilesForUser(user: user) { // Get the history file for the profile var file: URL - if filemanager.fileExists(atPath: "\(user.homedir)/Library/Application Support/Google/Chrome/\(profile)/History") { - file = URL(fileURLWithPath: "\(user.homedir)/Library/Application Support/Google/Chrome/\(profile)/History") - self.copyFileToCase(fileToCopy: file, toLocation: self.chromeDir, newFileName: "history_and_downloads_\(user.username)_\(profile).db") + if filemanager.fileExists(atPath: "\(user.homedir)/Library/Application Support/Comet/\(profile)/History") { + file = URL(fileURLWithPath: "\(user.homedir)/Library/Application Support/Comet/\(profile)/History") + self.copyFileToCase(fileToCopy: file, toLocation: self.cometDir, newFileName: "history_and_downloads_\(user.username)_\(profile).db") } else { continue } // Open the history file @@ -59,23 +59,23 @@ class Chrome: BrowserModule { self.addTextToFile(atUrl: historyOutput, text: "\(dateTime),\(user.username),\(profile),\(url)") } - } else { self.log("Unable to query the database. Please ensure that Chrome is not running.") } + } else { self.log("Unable to query the database. Please ensure that Comet is not running.") } } else { self.log("Unable to open the database") } } } } func dumpDownloads() { - self.addTextToFile(atUrl: self.writeFile, text: "----- Chrome Downloads: -----\n") + self.addTextToFile(atUrl: self.writeFile, text: "----- Comet Downloads: -----\n") - let downlaodsRaw = self.createNewCaseFile(dirUrl: self.chromeDir, filename: "downloads_output.csv") + let downlaodsRaw = self.createNewCaseFile(dirUrl: self.cometDir, filename: "downloads_output.csv") self.addTextToFile(atUrl: downlaodsRaw, text: "datetime,user,profile,url,target_path,danger_type,opened") for user in getBasicUsersOnSystem() { - for profile in getChromeProfilesForUser(user: user) { + for profile in getCometProfilesForUser(user: user) { var file: URL - if filemanager.fileExists(atPath: "\(user.homedir)/Library/Application Support/Google/Chrome/\(profile)/History") { - file = URL(fileURLWithPath: "\(user.homedir)/Library/Application Support/Google/Chrome/\(profile)/History") + if filemanager.fileExists(atPath: "\(user.homedir)/Library/Application Support/Comet/\(profile)/History") { + file = URL(fileURLWithPath: "\(user.homedir)/Library/Application Support/Comet/\(profile)/History") } else { continue } var db: OpaquePointer? @@ -115,38 +115,38 @@ class Chrome: BrowserModule { } } - self.addTextToFile(atUrl: self.writeFile, text: "\n----- End of Chrome Downloads -----\n") + self.addTextToFile(atUrl: self.writeFile, text: "\n----- End of Comet Downloads -----\n") } func dumpPreferences() { for user in getBasicUsersOnSystem() { - for profile in getChromeProfilesForUser(user: user) { + for profile in getCometProfilesForUser(user: user) { var file: URL - if filemanager.fileExists(atPath: "\(user.homedir)/Library/Application Support/Google/Chrome/\(profile)/Preferences") { - file = URL(fileURLWithPath: "\(user.homedir)/Library/Application Support/Google/Chrome/\(profile)/Preferences") - self.copyFileToCase(fileToCopy: file, toLocation: self.chromeDir, newFileName: "preferences_\(user.username)_\(profile)") + if filemanager.fileExists(atPath: "\(user.homedir)/Library/Application Support/Comet/\(profile)/Preferences") { + file = URL(fileURLWithPath: "\(user.homedir)/Library/Application Support/Comet/\(profile)/Preferences") + self.copyFileToCase(fileToCopy: file, toLocation: self.cometDir, newFileName: "preferences_\(user.username)_\(profile)") } else { continue } do { let data = try Data(contentsOf: file, options: .mappedIfSafe) if let json = try JSONSerialization.jsonObject(with: data, options: .mutableLeaves) as? [String: Any] { - self.addTextToFile(atUrl: writeFile, text: "\nChrome Preferences -----\n\(String(describing: json))\n ----- End of Chrome Preferences -----\n") + self.addTextToFile(atUrl: writeFile, text: "\nComet Preferences -----\n\(String(describing: json))\n ----- End of Comet Preferences -----\n") } - } catch { self.log("Unable to capture Chrome Preferenes") } + } catch { self.log("Unable to capture Comet Preferenes") } } } } func dumpCookies() { - self.addTextToFile(atUrl: self.writeFile, text: "----- Chrome Cookies: -----\n") + self.addTextToFile(atUrl: self.writeFile, text: "----- Comet Cookies: -----\n") for user in getBasicUsersOnSystem() { - for profile in getChromeProfilesForUser(user: user) { + for profile in getCometProfilesForUser(user: user) { var file: URL - if filemanager.fileExists(atPath: "\(user.homedir)/Library/Application Support/Google/Chrome/\(profile)/Cookies") { - file = URL(fileURLWithPath: "\(user.homedir)/Library/Application Support/Google/Chrome/\(profile)/Cookies") - self.copyFileToCase(fileToCopy: file, toLocation: self.chromeDir, newFileName: "cookies_\(user.username)_\(profile).db") + if filemanager.fileExists(atPath: "\(user.homedir)/Library/Application Support/Comet/\(profile)/Cookies") { + file = URL(fileURLWithPath: "\(user.homedir)/Library/Application Support/Comet/\(profile)/Cookies") + self.copyFileToCase(fileToCopy: file, toLocation: self.cometDir, newFileName: "cookies_\(user.username)_\(profile).db") } else { continue } var db: OpaquePointer? @@ -188,27 +188,27 @@ class Chrome: BrowserModule { } } } - self.addTextToFile(atUrl: self.writeFile, text: "\n----- End of Chrome Cookies -----\n") + self.addTextToFile(atUrl: self.writeFile, text: "\n----- End of Comet Cookies -----\n") } - func captureExtensions() { + func captureExtensions() { for user in getBasicUsersOnSystem() { - for profile in getChromeProfilesForUser(user: user) { - let chromeExtensionDir = self.createNewDir(dir: self.chromeDir, dirname: "extensions_\(user.username)_\(profile)") - let path = "\(user.homedir)/Library/Application Support/Google/Chrome/\(profile)/Extensions" + for profile in getCometProfilesForUser(user: user) { + let cometExtensionDir = self.createNewDir(dir: self.cometDir, dirname: "extensions_\(user.username)_\(profile)") + let path = "\(user.homedir)/Library/Application Support/Comet/\(profile)/Extensions" for file in filemanager.filesInDirRecursive(path: path) { - self.copyFileToCase(fileToCopy: file, toLocation: chromeExtensionDir) + self.copyFileToCase(fileToCopy: file, toLocation: cometExtensionDir) } } } } - func getChromeProfilesForUser(user: User) -> [String] { + func getCometProfilesForUser(user: User) -> [String] { var profiles: [String] = [] // Get the directory name if it contains the string "Profile" - if filemanager.fileExists(atPath: "\(user.homedir)/Library/Application Support/Google/Chrome") { - for file in filemanager.filesInDir(path: "\(user.homedir)/Library/Application Support/Google/Chrome") { + if filemanager.fileExists(atPath: "\(user.homedir)/Library/Application Support/Comet") { + for file in filemanager.filesInDir(path: "\(user.homedir)/Library/Application Support/Comet") { if file.lastPathComponent.starts(with: "Profile") || file.lastPathComponent == "Default" { profiles.append(file.lastPathComponent) } @@ -219,7 +219,7 @@ class Chrome: BrowserModule { } override func run() { - self.log("Collecting Chrome browser information...") + self.log("Collecting Comet browser information...") gatherHistory() dumpDownloads() dumpPreferences() From 19f77e93e9b1762fa9e8e17f8bd69714984798e4 Mon Sep 17 00:00:00 2001 From: attacus Date: Wed, 3 Dec 2025 21:57:49 +1100 Subject: [PATCH 3/3] updating readme to include Comet support and contributor info --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index cfe0811..de3ec49 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,7 @@ Because `eslogger` and `tcpdump` run on additional threads and the goal is to co - Arc - Brave - Chrome + - Comet - Edge - Firefox - Safari @@ -157,6 +158,7 @@ To uninstall the aftermath binary, run the `AftermathUninstaller.pkg` from the [ - Maggie Zirnhelt - Matt Benyo - Ferdous Saljooki +- Lilly Ryan ## Thank You This project leverages the open source [TrueTree](https://github.com/themittenmac/TrueTree) project, written and [licensed](https://github.com/themittenmac/TrueTree/blob/master/license.md) by Jaron Bradley.