diff --git a/aftermath.xcodeproj/project.pbxproj b/aftermath.xcodeproj/project.pbxproj index 89a2075..952e27f 100644 --- a/aftermath.xcodeproj/project.pbxproj +++ b/aftermath.xcodeproj/project.pbxproj @@ -16,6 +16,9 @@ A076742C27555FC100ED7066 /* PersistenceModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = A076742B27555FC100ED7066 /* PersistenceModule.swift */; }; A076742F2755798F00ED7066 /* ArtifactsModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = A076742E2755798F00ED7066 /* ArtifactsModule.swift */; }; A0879957275AD2DC00E885BC /* SystemConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0879956275AD2DC00E885BC /* SystemConfig.swift */; }; + A0D6D54327F76C58002BB3C8 /* Cron.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0D6D54227F76C58002BB3C8 /* Cron.swift */; }; + A0D6D54727FE147D002BB3C8 /* Overrides.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0D6D54627FE147D002BB3C8 /* Overrides.swift */; }; + A0D6D54927FE52C1002BB3C8 /* SystemExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0D6D54827FE52C1002BB3C8 /* SystemExtensions.swift */; }; A0E1E3E4275EC3D2008D0DC6 /* Swap.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0E1E3E3275EC3D2008D0DC6 /* Swap.swift */; }; A0E1E3E6275EC433008D0DC6 /* MemoryModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0E1E3E5275EC433008D0DC6 /* MemoryModule.swift */; }; A0E1E3E9275EC736008D0DC6 /* BrowserModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0E1E3E8275EC736008D0DC6 /* BrowserModule.swift */; }; @@ -57,6 +60,9 @@ A076742B27555FC100ED7066 /* PersistenceModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PersistenceModule.swift; sourceTree = ""; }; A076742E2755798F00ED7066 /* ArtifactsModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArtifactsModule.swift; sourceTree = ""; }; A0879956275AD2DC00E885BC /* SystemConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SystemConfig.swift; sourceTree = ""; }; + A0D6D54227F76C58002BB3C8 /* Cron.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Cron.swift; sourceTree = ""; }; + A0D6D54627FE147D002BB3C8 /* Overrides.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Overrides.swift; sourceTree = ""; }; + A0D6D54827FE52C1002BB3C8 /* SystemExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SystemExtensions.swift; sourceTree = ""; }; A0E1E3E3275EC3D2008D0DC6 /* Swap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Swap.swift; sourceTree = ""; }; A0E1E3E5275EC433008D0DC6 /* MemoryModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryModule.swift; sourceTree = ""; }; A0E1E3E8275EC736008D0DC6 /* BrowserModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserModule.swift; sourceTree = ""; }; @@ -123,6 +129,9 @@ A076742B27555FC100ED7066 /* PersistenceModule.swift */, A3745357275730870074B65C /* LaunchItems.swift */, A3745359275735B40074B65C /* LoginHooks.swift */, + A0D6D54227F76C58002BB3C8 /* Cron.swift */, + A0D6D54627FE147D002BB3C8 /* Overrides.swift */, + A0D6D54827FE52C1002BB3C8 /* SystemExtensions.swift */, ); path = persistence; sourceTree = ""; @@ -294,7 +303,10 @@ A0759135275985170006766F /* TCC.swift in Sources */, A0E1E3F6275ED2E4008D0DC6 /* NetworkModule.swift in Sources */, A076742C27555FC100ED7066 /* PersistenceModule.swift in Sources */, + A0D6D54727FE147D002BB3C8 /* Overrides.swift in Sources */, A0E1E3E4275EC3D2008D0DC6 /* Swap.swift in Sources */, + A0D6D54927FE52C1002BB3C8 /* SystemExtensions.swift in Sources */, + A0D6D54327F76C58002BB3C8 /* Cron.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/aftermath/Module.swift b/aftermath/Module.swift index 9746148..e3dcdf3 100644 --- a/aftermath/Module.swift +++ b/aftermath/Module.swift @@ -45,16 +45,26 @@ class AftermathModule { if !filename.hasPrefix("_") { let username = file.deletingPathExtension().lastPathComponent if let homedir = NSHomeDirectoryForUser(username) { - let user = User(username:username, homedir: homedir) - users.append(user) + let user = User(username:username, homedir: homedir) + users.append(user) + } } } } - } - return users } + func getBasicUsersOnSystem() -> [User] { + var basicUsers = [User]() + if let users = self.users { + for user in users { + if SystemUsers.allCases.contains(where: {$0.rawValue == user.username}) { continue } + basicUsers.append(user) + } + } + return basicUsers + } + func createNewDirInRoot(dirName: String) -> URL { let newUrl = CaseFiles.caseDir.appendingPathComponent(dirName) @@ -153,4 +163,9 @@ class AftermathModule { addTextToFile(atUrl: CaseFiles.logFile, text: entry) } } + + enum SystemUsers: String, CaseIterable { + case nobody = "nobody" + case daemon = "daemon" + } } diff --git a/artifacts/ShellHistoryAndProfiles.swift b/artifacts/ShellHistoryAndProfiles.swift index 9d86c9a..854bf79 100644 --- a/artifacts/ShellHistoryAndProfiles.swift +++ b/artifacts/ShellHistoryAndProfiles.swift @@ -26,24 +26,29 @@ class BashProfiles: ArtifactsModule { let globalFiles = ["/etc/profile", "/etc/zshenv", "/etc/zprofile", "/etc/zshrc", "/etc/zlogin", "/etc/zlogout"] // for each user, copy the shell historys and profiles - if let users = self.users { - for user in users { - for filename in userFiles { - let path = URL(fileURLWithPath: "\(user.homedir)/\(filename)") + for user in getUsersOnSystem() { + for filename in userFiles { + let path = URL(fileURLWithPath: "\(user.homedir)/\(filename)") + if (filemanager.fileExists(atPath: path.path)) { let newFileName = "\(user.username)_\(filename)" self.copyFileToCase(fileToCopy: path, toLocation: self.profilesDir, newFileName: newFileName) } + } } + // Copy all the global files for file in globalFiles { let fileUrl = URL(fileURLWithPath: file) - let filename = fileUrl.lastPathComponent - let newFileName = "etc_\(filename)" - self.copyFileToCase(fileToCopy: fileUrl, toLocation: self.profilesDir, newFileName: newFileName) + if (filemanager.fileExists(atPath: fileUrl.path)) { + let filename = fileUrl.lastPathComponent + let newFileName = "etc_\(filename)" + self.copyFileToCase(fileToCopy: fileUrl, toLocation: self.profilesDir, newFileName: newFileName) + } } + self.log("Finished collecting shell history and profile information...") } } diff --git a/artifacts/TCC.swift b/artifacts/TCC.swift index eadbe55..8f210ce 100644 --- a/artifacts/TCC.swift +++ b/artifacts/TCC.swift @@ -16,65 +16,76 @@ class TCC: ArtifactsModule { } func getTCC() { - let fileURL = try! filemanager.url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent("com.apple.TCC/TCC.db") - self.copyFileToCase(fileToCopy: fileURL, toLocation: tccDir) let capturedTCC = self.createNewCaseFile(dirUrl: self.moduleDirRoot, filename: "tccItems.txt") - var db : OpaquePointer? - if sqlite3_open(fileURL.path, &db) == SQLITE_OK { - var queryStatement: OpaquePointer? = nil - let queryString = "select client, auth_value, auth_reason, service from access" + for user in getBasicUsersOnSystem() { + + let tcc_path = URL(fileURLWithPath:"\(user.homedir)/Library/Application Support/com.apple.TCC/TCC.db") + + if !filemanager.fileExists(atPath: tcc_path.relativePath) { continue } + + + self.copyFileToCase(fileToCopy: tcc_path, toLocation: tccDir, newFileName: "tcc_\(user.username)") - if sqlite3_prepare_v2(db, queryString, -1, &queryStatement, nil) == SQLITE_OK { - var client: String = "" - var authValue: String = "" - var authReason: String = "" - var service: String = "" + + var db : OpaquePointer? + + if sqlite3_open(tcc_path.path, &db) == SQLITE_OK { + var queryStatement: OpaquePointer? = nil + let queryString = "select client, auth_value, auth_reason, service from access" - while sqlite3_step(queryStatement) == SQLITE_ROW { - let col1 = sqlite3_column_text(queryStatement, 0) - if col1 != nil{ - client = String(cString: col1!) - } + if sqlite3_prepare_v2(db, queryString, -1, &queryStatement, nil) == SQLITE_OK { + var client: String = "" + var authValue: String = "" + var authReason: String = "" + var service: String = "" - let col2 = sqlite3_column_text(queryStatement, 1) - if col2 != nil { - authValue = String(cString: col2!) - for item in TCCAuthValue.allCases { - if authValue == String(item.rawValue) { - authValue = String(describing: item) + while sqlite3_step(queryStatement) == SQLITE_ROW { + + let col1 = sqlite3_column_text(queryStatement, 0) + if let col1 = col1 { client = String(cString: col1) } + + let col2 = sqlite3_column_text(queryStatement, 1) + if let col2 = col2 { + authValue = String(cString: col2) + for item in TCCAuthValue.allCases { + if authValue == String(item.rawValue) { + authValue = String(describing: item) + } } } - } - - let col3 = sqlite3_column_text(queryStatement, 2) - if col3 != nil { - authReason = String(cString: col3!) - for item in TCCAuthReason.allCases { - if authReason == String(item.rawValue) { - authReason = String(describing: item) + + let col3 = sqlite3_column_text(queryStatement, 2) + if let col3 = col3 { + authReason = String(cString: col3) + for item in TCCAuthReason.allCases { + if authReason == String(item.rawValue) { + authReason = String(describing: item) + } + } } - } - } - - let col4 = sqlite3_column_text(queryStatement, 3) - if col4 != nil { - service = String(cString: col4!) - for item in TCCService.allCases { - if service == String(item.rawValue) { - service = String(describing: item) + + let col4 = sqlite3_column_text(queryStatement, 3) + if let col4 = col4 { + service = String(cString: col4) + for item in TCCService.allCases { + if service == String(item.rawValue) { + service = String(describing: item) + } + } } - } + + self.addTextToFile(atUrl: capturedTCC, text: "TCC Data for \(user.username)") + self.addTextToFile(atUrl: capturedTCC, text: "Name: \(client)\nRequested Service: \(service)\nAuth Value: \(authValue)\nAuth Reason: \(authReason)\n") } - - self.addTextToFile(atUrl: capturedTCC, text: "Name: \(client)\nRequested Service: \(service)\nAuth Value: \(authValue)\nAuth Reason: \(authReason)\n") } + self.log("Finished capturing TCC data for \(user.username)") + } else { + self.log("An error occurred when attempting to query the TCC database for user \(user.username)...") } - self.log("Finished capturing TCC data") - } else { - self.log("An error occurred when attempting to query the TCC database...") } + self.log("Finished querying TCC") } override func run() { diff --git a/filesystem/browsers/Brave.swift b/filesystem/browsers/Brave.swift index 37634fb..2a3a36a 100644 --- a/filesystem/browsers/Brave.swift +++ b/filesystem/browsers/Brave.swift @@ -18,13 +18,14 @@ class Brave: BrowserModule { } func getContents() { - let username = NSUserName() - let path = "/Users/\(username)/Library/Application Support/BraveSoftware/Brave-Browser/Default" - let files = filemanager.filesInDirRecursive(path: path) - - for file in files { - if file.lastPathComponent == "" { - dumpHistory(file: file) + for user in getBasicUsersOnSystem() { + let path = "\(user.homedir)/Library/Application Support/BraveSoftware/Brave-Browser/Default" + let files = filemanager.filesInDirRecursive(path: path) + + for file in files { + if file.lastPathComponent == "" { + dumpHistory(file: file) + } } } } @@ -32,82 +33,68 @@ class Brave: BrowserModule { func dumpHistory(file: URL) { self.addTextToFile(atUrl: self.writeFile, text: "\n----- Brave History -----\n") - var db: OpaquePointer? - if sqlite3_open(file.path, &db) == SQLITE_OK { - var queryStatement: OpaquePointer? = nil - let queryString = "select datetime(vi.visit_time/1000000, 'unixepoch') as dt, urls.url FROM visits vi INNER join urls on vi.id = urls.id;" - - if sqlite3_prepare_v2(db, queryString, -1, &queryStatement, nil) == SQLITE_OK { - var dateTime: String = "" - var url: String = "" + var db: OpaquePointer? + if sqlite3_open(file.path, &db) == SQLITE_OK { + var queryStatement: OpaquePointer? = nil + let queryString = "select datetime(vi.visit_time/1000000, 'unixepoch') as dt, urls.url FROM visits vi INNER join urls on vi.id = urls.id;" - while sqlite3_step(queryStatement) == SQLITE_ROW { - let col1 = sqlite3_column_text(queryStatement, 0) - if col1 != nil { - dateTime = String(cString: col1!) - } + if sqlite3_prepare_v2(db, queryString, -1, &queryStatement, nil) == SQLITE_OK { + var dateTime: String = "" + var url: String = "" - let col2 = sqlite3_column_text(queryStatement, 1) - if col2 != nil { - url = String(cString: col2!) + while sqlite3_step(queryStatement) == SQLITE_ROW { + let col1 = sqlite3_column_text(queryStatement, 0) + if let col1 = col1 { dateTime = String(cString: col1) } + + let col2 = sqlite3_column_text(queryStatement, 1) + if let col2 = col2 { url = String(cString: col2) } + + self.addTextToFile(atUrl: self.writeFile, text: "DateTime: \(dateTime)\nURL: \(url)\n") } - - self.addTextToFile(atUrl: self.writeFile, text: "DateTime: \(dateTime)\nURL: \(url)\n") } } - } self.addTextToFile(atUrl: self.writeFile, text: "----- End of Brave History -----\n") } func dumpCookies() { - let username = NSUserName() - let file = URL(fileURLWithPath: "/Users/\(username)/Library/Application Support/BraveSoftware/Brave-Browser/Default/Cookies") - self.addTextToFile(atUrl: self.writeFile, text: "----- Brave Cookies: -----\n") - var db: OpaquePointer? - if sqlite3_open(file.path, &db) == SQLITE_OK { - var queryStatement: OpaquePointer? = nil - let queryString = "select datetime(creation_utc/1000000-11644473600, 'unixepoch'), name, host_key, path, datetime(expires_utc/1000000-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 { - let col1 = sqlite3_column_text(queryStatement, 0) - if col1 != nil { - dateTime = String(cString: col1!) - } - - let col2 = sqlite3_column_text(queryStatement, 1) - if col2 != nil { - name = String(cString: col2!) - } - - let col3 = sqlite3_column_text(queryStatement, 2) - if col3 != nil { - hostKey = String(cString: col1!) - } - - let col4 = sqlite3_column_text(queryStatement, 3) - if col4 != nil { - path = String(cString: col2!) - } + for user in getBasicUsersOnSystem() { + let file = URL(fileURLWithPath: "\(user.homedir)/Library/Application Support/BraveSoftware/Brave-Browser/Default/Cookies") + + var db: OpaquePointer? + if sqlite3_open(file.path, &db) == SQLITE_OK { + var queryStatement: OpaquePointer? = nil + let queryString = "select datetime(creation_utc/1000000-11644473600, 'unixepoch'), name, host_key, path, datetime(expires_utc/1000000-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 = "" - let col5 = sqlite3_column_text(queryStatement, 4) - if col5 != nil { - expireTime = String(cString: col1!) + while sqlite3_step(queryStatement) == SQLITE_ROW { + let col1 = sqlite3_column_text(queryStatement, 0) + if let col1 = col1 { dateTime = String(cString: col1) } + + let col2 = sqlite3_column_text(queryStatement, 1) + if let col2 = col2 { name = String(cString: col2) } + + let col3 = sqlite3_column_text(queryStatement, 2) + if let col3 = col3 { hostKey = String(cString: col3) } + + let col4 = sqlite3_column_text(queryStatement, 3) + if let col4 = col4 { path = String(cString: col4) } + + let col5 = sqlite3_column_text(queryStatement, 4) + if let col5 = col5 { expireTime = String(cString: col5) } + + self.addTextToFile(atUrl: self.writeFile, text: "DateTime: \(dateTime)\nName: \(name)\nHostKey: \(hostKey)\nPath:\(path)\nExpireTime: \(expireTime)\n\n") } - - self.addTextToFile(atUrl: self.writeFile, text: "DateTime: \(dateTime)\nName: \(name)\nHostKey: \(hostKey)\nPath:\(path)\nExpireTime: \(expireTime)\n\n") } } } - self.addTextToFile(atUrl: self.writeFile, text: "\n----- End of Brave Cookies -----\n") } diff --git a/filesystem/browsers/Chrome.swift b/filesystem/browsers/Chrome.swift index d3c193b..d1f4a65 100644 --- a/filesystem/browsers/Chrome.swift +++ b/filesystem/browsers/Chrome.swift @@ -18,84 +18,77 @@ class Chrome: BrowserModule { } func gatherHistory() { - let username = NSUserName() - let file = URL(fileURLWithPath: "/Users/\(username)/Library/Application Support/Google/Chrome/Default/History") - - self.addTextToFile(atUrl: self.writeFile, text: "\n----- Chrome History: -----\n") - - var db: OpaquePointer? - if sqlite3_open(file.path, &db) == SQLITE_OK { - 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 = "" - - while sqlite3_step(queryStatement) == SQLITE_ROW { - let col1 = sqlite3_column_text(queryStatement, 0) - if col1 != nil { - dateTime = String(cString: col1!) - } + for user in getBasicUsersOnSystem() { + + let file = URL(fileURLWithPath: "\(user.homedir)/Library/Application Support/Google/Chrome/Default/History") + + self.addTextToFile(atUrl: self.writeFile, text: "\n----- Chrome History: -----\n") + + var db: OpaquePointer? + if sqlite3_open(file.path, &db) == SQLITE_OK { + 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 = "" - let col2 = sqlite3_column_text(queryStatement, 1) - if col2 != nil { - url = String(cString: col2!) + while sqlite3_step(queryStatement) == SQLITE_ROW { + let col1 = sqlite3_column_text(queryStatement, 0) + if col1 != nil { + dateTime = String(cString: col1!) + } + + let col2 = sqlite3_column_text(queryStatement, 1) + if col2 != nil { + url = String(cString: col2!) + } + + self.addTextToFile(atUrl: self.writeFile, text: "DateTime: \(dateTime)\nURL: \(url)\n\n") } - - self.addTextToFile(atUrl: self.writeFile, text: "DateTime: \(dateTime)\nURL: \(url)\n\n") } } } - self.addTextToFile(atUrl: self.writeFile, text: "----- End of Chrome History -----\n") } func dumpDownloads() { - let username = NSUserName() - let file = URL(fileURLWithPath: "/Users/\(username)/Library/Application Support/Google/Chrome/Default/History") - self.addTextToFile(atUrl: self.writeFile, text: "----- Chrome Downloads: -----\n") - 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;" + for user in getBasicUsersOnSystem() { - 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 { - let col1 = sqlite3_column_text(queryStatement, 0) - if col1 != nil { - dateTime = String(cString: col1!) - } - - let col2 = sqlite3_column_text(queryStatement, 1) - if col2 != nil { - url = String(cString: col2!) - } - - let col3 = sqlite3_column_text(queryStatement, 2) - if col3 != nil { - targetPath = String(cString: col1!) - } - - let col4 = sqlite3_column_text(queryStatement, 3) - if col4 != nil { - dangerType = String(cString: col2!) - } + let file = URL(fileURLWithPath: "\(user.homedir)/Library/Application Support/Google/Chrome/Default/History") + + 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 = "" - let col5 = sqlite3_column_text(queryStatement, 4) - if col5 != nil { - opened = String(cString: col1!) + while sqlite3_step(queryStatement) == SQLITE_ROW { + let col1 = sqlite3_column_text(queryStatement, 0) + if let col1 = col1 { dateTime = String(cString: col1) } + + 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: self.writeFile, text: "DateTime: \(dateTime)\nURL: \(url)\nTargetPath: \(targetPath)\nDangerType:\(dangerType)\nOpened: \(opened)\n\n") } - - self.addTextToFile(atUrl: self.writeFile, text: "DateTime: \(dateTime)\nURL: \(url)\nTargetPath: \(targetPath)\nDangerType:\(dangerType)\nOpened: \(opened)\n\n") } } } @@ -105,77 +98,82 @@ class Chrome: BrowserModule { // TODO - this needs to be tuned more func captureExtensions() { - let username = NSUserName() - let exdir = "/Users/\(username)/Library/Application Support/Google/Chrome/Default/Extensions" - let _ = filemanager.filesInDirRecursive(path: exdir) + for user in getBasicUsersOnSystem() { + + let exdir = "\(user.homedir)/Library/Application Support/Google/Chrome/Default/Extensions" + let _ = filemanager.filesInDirRecursive(path: exdir) // // for file in files { // self.caseHandler.copyFileToCase(fileToCopy: file, toLocation: self.chromeDir) // } + } } func dumpPreferences() { - let username = NSUserName() - let file = URL(fileURLWithPath: "/Users/\(username)/Library/Application Support/Google/Chrome/Default/Preferences") - - 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") - } + for user in getBasicUsersOnSystem() { - } catch { self.log("Unable to capture Chrome Preferenes") } + let file = URL(fileURLWithPath: "\(user.homedir)/Library/Application Support/Google/Chrome/Default/Preferences") + + 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() { - let username = NSUserName() - let file = URL(fileURLWithPath: "/Users/\(username)/Library/Application Support/Google/Chrome/Default/Cookies") - self.addTextToFile(atUrl: self.writeFile, text: "----- Chrome Cookies: -----\n") + + for user in getBasicUsersOnSystem() { - 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 { - let col1 = sqlite3_column_text(queryStatement, 0) - if col1 != nil { - dateTime = String(cString: col1!) - } - - let col2 = sqlite3_column_text(queryStatement, 1) - if col2 != nil { - name = String(cString: col2!) - } - - let col3 = sqlite3_column_text(queryStatement, 2) - if col3 != nil { - hostKey = String(cString: col1!) - } - - let col4 = sqlite3_column_text(queryStatement, 3) - if col4 != nil { - path = String(cString: col2!) - } + let file = URL(fileURLWithPath: "\(user.homedir)/Library/Application Support/Google/Chrome/Default/Cookies") + + 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 = "" - let col5 = sqlite3_column_text(queryStatement, 4) - if col5 != nil { - expireTime = String(cString: col1!) + while sqlite3_step(queryStatement) == SQLITE_ROW { + let col1 = sqlite3_column_text(queryStatement, 0) + if col1 != nil { + dateTime = String(cString: col1!) + } + + let col2 = sqlite3_column_text(queryStatement, 1) + if col2 != nil { + name = String(cString: col2!) + } + + let col3 = sqlite3_column_text(queryStatement, 2) + if col3 != nil { + hostKey = String(cString: col1!) + } + + let col4 = sqlite3_column_text(queryStatement, 3) + if col4 != nil { + path = String(cString: col2!) + } + + let col5 = sqlite3_column_text(queryStatement, 4) + if col5 != nil { + expireTime = String(cString: col1!) + } + + self.addTextToFile(atUrl: self.writeFile, text: "DateTime: \(dateTime)\nName: \(name)\nHostKey: \(hostKey)\nPath:\(path)\nExpireTime: \(expireTime)\n\n") } - - self.addTextToFile(atUrl: self.writeFile, text: "DateTime: \(dateTime)\nName: \(name)\nHostKey: \(hostKey)\nPath:\(path)\nExpireTime: \(expireTime)\n\n") } } } - self.addTextToFile(atUrl: self.writeFile, text: "\n----- End of Chrome Cookies -----\n") } diff --git a/filesystem/browsers/Firefox.swift b/filesystem/browsers/Firefox.swift index d564787..913c040 100644 --- a/filesystem/browsers/Firefox.swift +++ b/filesystem/browsers/Firefox.swift @@ -19,20 +19,22 @@ class Firefox: BrowserModule { } func getContent() { - let username = NSUserName() - let profiles = "/Users/\(username)/Library/Application Support/Firefox/Profiles" - let files = filemanager.filesInDirRecursive(path: profiles) - - for file in files { - if file.lastPathComponent == "places.sqlite" { - dumpHistory(file: file) - dumpDownloads(file: file) - } - if file.lastPathComponent == "cookies.sqlite" { - dumpCookies(file: file) - } - if file.lastPathComponent == "extensions.json" { - dumpExtensions(file: file) + for user in getBasicUsersOnSystem() { + + let profiles = "\(user.homedir)/Library/Application Support/Firefox/Profiles" + let files = filemanager.filesInDirRecursive(path: profiles) + + for file in files { + if file.lastPathComponent == "places.sqlite" { + dumpHistory(file: file) + dumpDownloads(file: file) + } + if file.lastPathComponent == "cookies.sqlite" { + dumpCookies(file: file) + } + if file.lastPathComponent == "extensions.json" { + dumpExtensions(file: file) + } } } } @@ -104,54 +106,45 @@ class Firefox: BrowserModule { } func dumpCookies(file: URL) { - let username = NSUserName() - let file = URL(fileURLWithPath: "/Users/\(username)/Library/Application Support/BraveSoftware/Brave-Browser/Default/Cookies") - self.addTextToFile(atUrl: self.writeFile, text: "----- Brave Cookies: -----\n") + + for user in getBasicUsersOnSystem() { - var db: OpaquePointer? - if sqlite3_open(file.path, &db) == SQLITE_OK { - var queryStatement: OpaquePointer? = nil - let queryString = "select datetime(creation_utc/1000000-11644473600, 'unixepoch'), name, host_key, path, datetime(expires_utc/1000000-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 { - let col1 = sqlite3_column_text(queryStatement, 0) - if col1 != nil { - dateTime = String(cString: col1!) - } - - let col2 = sqlite3_column_text(queryStatement, 1) - if col2 != nil { - name = String(cString: col2!) - } - - let col3 = sqlite3_column_text(queryStatement, 2) - if col3 != nil { - hostKey = String(cString: col1!) - } - - let col4 = sqlite3_column_text(queryStatement, 3) - if col4 != nil { - path = String(cString: col2!) - } + let file = URL(fileURLWithPath: "\(user.homedir)/Library/Application Support/BraveSoftware/Brave-Browser/Default/Cookies") + + var db: OpaquePointer? + if sqlite3_open(file.path, &db) == SQLITE_OK { + var queryStatement: OpaquePointer? = nil + let queryString = "select datetime(creation_utc/1000000-11644473600, 'unixepoch'), name, host_key, path, datetime(expires_utc/1000000-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 = "" - let col5 = sqlite3_column_text(queryStatement, 4) - if col5 != nil { - expireTime = String(cString: col1!) + while sqlite3_step(queryStatement) == SQLITE_ROW { + let col1 = sqlite3_column_text(queryStatement, 0) + if let col1 = col1 { dateTime = String(cString: col1) } + + let col2 = sqlite3_column_text(queryStatement, 1) + if let col2 = col2 { name = String(cString: col2) } + + let col3 = sqlite3_column_text(queryStatement, 2) + if let col3 = col3 { hostKey = String(cString: col3) } + + let col4 = sqlite3_column_text(queryStatement, 3) + if let col4 = col4 { path = String(cString: col4) } + + let col5 = sqlite3_column_text(queryStatement, 4) + if let col5 = col5 { expireTime = String(cString: col5) } + + self.addTextToFile(atUrl: self.writeFile, text: "DateTime: \(dateTime)\nName: \(name)\nHostKey: \(hostKey)\nPath:\(path)\nExpireTime: \(expireTime)\n\n") } - - self.addTextToFile(atUrl: self.writeFile, text: "DateTime: \(dateTime)\nName: \(name)\nHostKey: \(hostKey)\nPath:\(path)\nExpireTime: \(expireTime)\n\n") } } } - self.addTextToFile(atUrl: self.writeFile, text: "\n----- End of Brave Cookies -----\n") } diff --git a/filesystem/browsers/Opera.swift b/filesystem/browsers/Opera.swift index 6032e6a..b2924e5 100644 --- a/filesystem/browsers/Opera.swift +++ b/filesystem/browsers/Opera.swift @@ -18,43 +18,38 @@ class Opera: BrowserModule { } func gatherHistory() { - let username = NSUserName() - let file = URL(fileURLWithPath: "/Users/\(username)/Library/Application Support/Opera/com.operasoftware.Opera/History") - self.addTextToFile(atUrl: self.writeFile, text: "----- Opera History: -----\n") - var db: OpaquePointer? - if sqlite3_open(file.path, &db) == SQLITE_OK { - var queryStatement: OpaquePointer? = nil - let queryString = "SELECT start_time, current_path FROM downloads;" - - if sqlite3_prepare_v2(db, queryString, -1, &queryStatement, nil) == SQLITE_OK { - var dateTime: String = "" - var currentPath: String = "" - var url: String = "" - - while sqlite3_step(queryStatement) == SQLITE_ROW { - let col1 = sqlite3_column_text(queryStatement, 0) - if col1 != nil { - dateTime = String(cString: col1!) - } - - let col2 = sqlite3_column_text(queryStatement, 1) - if col2 != nil { - currentPath = String(cString: col2!) - } + for user in getBasicUsersOnSystem() { + let file = URL(fileURLWithPath: "\(user.homedir)/Library/Application Support/Opera/com.operasoftware.Opera/History") + + var db: OpaquePointer? + if sqlite3_open(file.path, &db) == SQLITE_OK { + var queryStatement: OpaquePointer? = nil + let queryString = "SELECT start_time, current_path FROM downloads;" + + if sqlite3_prepare_v2(db, queryString, -1, &queryStatement, nil) == SQLITE_OK { + var dateTime: String = "" + var currentPath: String = "" + var url: String = "" - let col3 = sqlite3_column_text(queryStatement, 2) - if col3 != nil { - url = String(cString: col3!) + while sqlite3_step(queryStatement) == SQLITE_ROW { + let col1 = sqlite3_column_text(queryStatement, 0) + if let col1 = col1 { dateTime = String(cString: col1) } + + let col2 = sqlite3_column_text(queryStatement, 1) + if let col2 = col2 { currentPath = String(cString: col2) } + + let col3 = sqlite3_column_text(queryStatement, 2) + if let col3 = col3 { url = String(cString: col3) } + + self.addTextToFile(atUrl: self.writeFile, text: "DateTime: \(dateTime)\nURL: \(url)\nContent: \(currentPath)\n") } - - self.addTextToFile(atUrl: self.writeFile, text: "DateTime: \(dateTime)\nURL: \(url)\nContent: \(currentPath)\n") } } } - self.addTextToFile(atUrl: self.writeFile, text: "----- End of Opera Downloads -----") + } override func run() { diff --git a/filesystem/browsers/Safari.swift b/filesystem/browsers/Safari.swift index bab96ab..ccf1dfa 100644 --- a/filesystem/browsers/Safari.swift +++ b/filesystem/browsers/Safari.swift @@ -18,53 +18,59 @@ class Safari: BrowserModule { } func getHistory() { - let username = NSUserName() - let file = URL(fileURLWithPath: "/Users/\(username)/Library/Safari/History") - self.addTextToFile(atUrl: self.writeFile, text: "\n----- Safari History -----\n") - - var db: OpaquePointer? - if sqlite3_open(file.path, &db) == SQLITE_OK { - var queryStatement: OpaquePointer? = nil - let queryString = "SELECT h.visit_time, i.url FROM history_visits h INNER JOIN history_items i ON h.history_item = i.id;" + for user in getBasicUsersOnSystem() { + var file: URL + if filemanager.fileExists(atPath: "\(user.homedir)/Library/Safari/History") { + file = URL(fileURLWithPath: "\(user.homedir)/Library/Safari/History") } else { continue } + + + + self.addTextToFile(atUrl: self.writeFile, text: "\n----- Safari History -----\n") - if sqlite3_prepare_v2(db, queryString, -1, &queryStatement, nil) == SQLITE_OK { - var dateTime: String = "" - var url: String = "" + var db: OpaquePointer? + if sqlite3_open(file.path, &db) == SQLITE_OK { + var queryStatement: OpaquePointer? = nil + let queryString = "SELECT h.visit_time, i.url FROM history_visits h INNER JOIN history_items i ON h.history_item = i.id;" - while sqlite3_step(queryStatement) == SQLITE_ROW { - let col1 = sqlite3_column_text(queryStatement, 0) - if col1 != nil { - dateTime = String(cString: col1!) - } + if sqlite3_prepare_v2(db, queryString, -1, &queryStatement, nil) == SQLITE_OK { + var dateTime: String = "" + var url: String = "" - let col2 = sqlite3_column_text(queryStatement, 1) - if col2 != nil { - url = String(cString: col2!) + while sqlite3_step(queryStatement) == SQLITE_ROW { + let col1 = sqlite3_column_text(queryStatement, 0) + if let col1 = col1 { dateTime = String(cString: col1) } + + let col2 = sqlite3_column_text(queryStatement, 1) + if let col2 = col2 { url = String(cString: col2) } + + self.addTextToFile(atUrl: self.writeFile, text: "DateTime: \(dateTime)\nURL: \(url)\n") } - - self.addTextToFile(atUrl: self.writeFile, text: "DateTime: \(dateTime)\nURL: \(url)\n") } } + + self.addTextToFile(atUrl: self.writeFile, text: "----- End of Safari History -----\n") } - - self.addTextToFile(atUrl: self.writeFile, text: "----- End of Safari History -----\n") } func dumpImportantPlists() { - let username = NSUserName() - let files: [URL] = [URL(fileURLWithPath: "/Users/\(username)/Library/Safari/Bookmarks.plist"), URL(fileURLWithPath: "/Users/\(username)/Library/Safari/Downloads.plist"), URL(fileURLWithPath: "/Users/\(username)/Library/Safari/UserNotificationPermissions.plist"), URL(fileURLWithPath: "/Users/\(username)/Library/Safari/LastSession.plist")] - - for file in files { - let plistDict = Aftermath.getPlistAsDict(atUrl: file) - self.addTextToFile(atUrl: self.writeFile, text: "\nFile Name:\n----- \(file) -----\n\n\(plistDict.description)\n----- End of \(file) -----\n") + for user in getBasicUsersOnSystem() { + + let files: [URL] = [URL(fileURLWithPath: "\(user.homedir)/Library/Safari/Bookmarks.plist"), URL(fileURLWithPath: "\(user.homedir)/Library/Safari/Downloads.plist"), URL(fileURLWithPath: "\(user.homedir)/Library/Safari/UserNotificationPermissions.plist"), URL(fileURLWithPath: "\(user.homedir)/Library/Safari/LastSession.plist")] - self.copyFileToCase(fileToCopy: file, toLocation: self.safariDir) + for file in files { + if filemanager.fileExists(atPath: file.absoluteString) { + let plistDict = Aftermath.getPlistAsDict(atUrl: file) + self.addTextToFile(atUrl: self.writeFile, text: "\nFile Name:\n----- \(file) -----\n\n\(plistDict.description)\n----- End of \(file) -----\n") + + self.copyFileToCase(fileToCopy: file, toLocation: self.safariDir) + } + } } } override func run() { - self.log("Collecting safari browser information...") + self.log("Collecting Safari browser information...") getHistory() dumpImportantPlists() } diff --git a/persistence/Cron.swift b/persistence/Cron.swift new file mode 100644 index 0000000..8effd41 --- /dev/null +++ b/persistence/Cron.swift @@ -0,0 +1,42 @@ +// +// Cron.swift +// aftermath +// +// +import Foundation + + +class Cron: PersistenceModule { + + let saveToRawDir: URL + + init(saveToRawDir: URL) { + self.saveToRawDir = saveToRawDir + } + + func captureCronJobs(urlLocations: [URL], rawLoc: URL, captured: URL) { + for url in urlLocations { + // copy the files to the persistence directory + do { + self.copyFileToCase(fileToCopy: url, toLocation: rawLoc) + self.addTextToFile(atUrl: captured, text: "/n ----- \(url) -----/n") + let contents = try String(contentsOf: url) + self.addTextToFile(atUrl: captured, text: contents) + } catch { + self.log("Unable to copy crontabs file") + } + + } + } + + override func run() { + let cronRawDir = self.createNewDir(dir: self.saveToRawDir, dirname: "cron_dump") + + let capturedCronJobs = self.createNewCaseFile(dirUrl: moduleDirRoot, filename: "crontabs.txt") + + let cronjobsPath = "/usr/lib/cron/tabs/" + let cronjobs = filemanager.filesInDirRecursive(path: cronjobsPath) + + captureCronJobs(urlLocations: cronjobs, rawLoc: cronRawDir, captured: capturedCronJobs) + } +} diff --git a/persistence/LoginHooks.swift b/persistence/LoginHooks.swift index c31660b..fdeb884 100644 --- a/persistence/LoginHooks.swift +++ b/persistence/LoginHooks.swift @@ -27,7 +27,7 @@ class LoginHooks: PersistenceModule { } else { parsedHooks = hook } - } else { continue } + } } return parsedHooks diff --git a/persistence/Overrides.swift b/persistence/Overrides.swift new file mode 100644 index 0000000..487102b --- /dev/null +++ b/persistence/Overrides.swift @@ -0,0 +1,36 @@ +// +// Overrides.swift +// aftermath +// +// Created by Stuart Ashenbrenner on 4/6/22. +// + +import Foundation + +class Overrides: PersistenceModule { + + let saveToRawDir: URL + + init(saveToRawDir: URL) { + self.saveToRawDir = saveToRawDir + } + + func collectOverrides(urlLocations: [URL], capturedFile: URL) { + for url in urlLocations { + let plistDict = Aftermath.getPlistAsDict(atUrl: url) + + self.copyFileToCase(fileToCopy: url, toLocation: self.saveToRawDir) + self.addTextToFile(atUrl: capturedFile, text: "\n----- \(url) -----\n") + self.addTextToFile(atUrl: capturedFile, text: plistDict.description) + } + } + + override func run() { + let capturedOverridesFile = self.createNewCaseFile(dirUrl: moduleDirRoot, filename: "overrides.txt") + + let overrides = filemanager.filesInDirRecursive(path: "/var/db/launchd.db/com.apple.launchd/") + + collectOverrides(urlLocations: overrides, capturedFile: capturedOverridesFile) + + } +} diff --git a/persistence/PersistenceModule.swift b/persistence/PersistenceModule.swift index 37ab304..ea3b9bb 100644 --- a/persistence/PersistenceModule.swift +++ b/persistence/PersistenceModule.swift @@ -26,5 +26,17 @@ class PersistenceModule: AftermathModule, AMProto { self.log("Collecting login hooks...") let hooks = LoginHooks(saveToRawDir: persistenceRawDir) hooks.run() + + self.log("Collecting cron jobs...") + let cron = Cron(saveToRawDir: persistenceRawDir) + cron.run() + + self.log("Collecting overrides...") + let overrides = Overrides(saveToRawDir: persistenceRawDir) + overrides.run() + + self.log("Writing system extension urls...") + let systemExtensions = SystemExtensions(saveToRawDir: persistenceRawDir) + systemExtensions.run() } } diff --git a/persistence/SystemExtensions.swift b/persistence/SystemExtensions.swift new file mode 100644 index 0000000..02d0c4a --- /dev/null +++ b/persistence/SystemExtensions.swift @@ -0,0 +1,33 @@ +// +// SystemExtensions.swift +// aftermath +// +// Created by Stuart Ashenbrenner on 4/6/22. +// + +import Foundation + +class SystemExtensions: PersistenceModule { + + let saveToRawDir: URL + + init(saveToRawDir: URL) { + self.saveToRawDir = saveToRawDir + } + + func captureSysExtensions(urlLocations: [URL], rawLoc: URL) { + let capturedSystemExtensions = self.createNewCaseFile(dirUrl: self.moduleDirRoot, filename: "systemExtensions.txt") + self.addTextToFile(atUrl: capturedSystemExtensions, text: "System Extension URLs\n-----\n\n") + for url in urlLocations { + self.addTextToFile(atUrl: capturedSystemExtensions, text: "\(url.absoluteString)\n") + } + } + + override func run() { + let sysExtensionsRaw = self.createNewDir(dir: self.saveToRawDir, dirname: "systemExtensions_dump") + + let sysExtensions = filemanager.filesInDirRecursive(path: "/Library/SystemExtensions/") + + captureSysExtensions(urlLocations: sysExtensions, rawLoc: sysExtensionsRaw) + } +}