def process(self, file): # Use blackboard class to index blackboard artifacts for keyword search blackboard = Case.getCurrentCase().getServices().getBlackboard() # Skip non-files if ((file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) or (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) or (file.isFile() == False)): return IngestModule.ProcessResult.OK # Look for files bigger than 10MB that are a multiple of 4096 if ((file.getSize() > 10485760) and ((file.getSize() % 4096) == 0)): # Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of # artifact. Refer to the developer docs for other examples. art = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT) att = BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID(), FindBigRoundFilesIngestModuleFactory.moduleName, "Big and Round Files") art.addAttribute(att) try: # index the artifact for keyword search blackboard.indexArtifact(art) except Blackboard.BlackboardException as e: self.log(Level.SEVERE, "Error indexing artifact " + art.getDisplayName()) # Fire an event to notify the UI and others that there is a new artifact IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent(FindBigRoundFilesIngestModuleFactory.moduleName, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, None)) return IngestModule.ProcessResult.OK
def process(self, file): # Skip non-files if ((file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) or (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) or (file.isFile() == False)): return IngestModule.ProcessResult.OK # Use blackboard class to index blackboard artifacts for keyword search blackboard = Case.getCurrentCase().getServices().getBlackboard() # For an example, we will flag files with .txt in the name and make a blackboard artifact. if file.getName().lower().endswith(".txt"): self.log(Level.INFO, "Found a text file: " + file.getName()) self.filesFound += 1 # Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of # artifact. Refer to the developer docs for other examples. art = file.newArtifact( BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT) att = BlackboardAttribute( BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, SampleJythonFileIngestModuleFactory.moduleName, "Text Files") art.addAttribute(att) try: # index the artifact for keyword search blackboard.indexArtifact(art) except Blackboard.BlackboardException as e: self.log(Level.SEVERE, "Error indexing artifact " + art.getDisplayName()) # Fire an event to notify the UI and others that there is a new artifact IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent( SampleJythonFileIngestModuleFactory.moduleName, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, None)) # For the example (this wouldn't be needed normally), we'll query the blackboard for data that was added # by other modules. We then iterate over its attributes. We'll just print them, but you would probably # want to do something with them. artifactList = file.getArtifacts( BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT) for artifact in artifactList: attributeList = artifact.getAttributes() for attrib in attributeList: self.log(Level.INFO, attrib.toString()) # To further the example, this code will read the contents of the file and count the number of bytes inputStream = ReadContentInputStream(file) buffer = jarray.zeros(1024, "b") totLen = 0 len = inputStream.read(buffer) while (len != -1): totLen = totLen + len len = inputStream.read(buffer) return IngestModule.ProcessResult.OK
def index_artifact(artifact, artifact_type): try: Case.getCurrentCase().getServices().getBlackboard().indexArtifact( artifact) except: logging.warning("Error indexing artifact type: " + artifact_type) IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent("Forensics Analyzer", artifact_type, None))
def process(self, file): skCase = Case.getCurrentCase().getSleuthkitCase() artID_ns_ss = skCase.getArtifactType("TSK_ART_NS_SCREENSHOTS") artID_ns_ss_id = skCase.getArtifactTypeID("TSK_ART_NS_SCREENSHOTS") attID_ns_gid = skCase.getAttributeType("TSK_ATT_NS_GAME") attID_ns_ts = skCase.getAttributeType("TSK_ATT_NS_TIMESTAMP") # Skip non-files if ((file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) or (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) or (file.isFile() is False)): return IngestModule.ProcessResult.OK # Flag files with .jpg in the name and make a blackboard artifact. if file.getName().lower().endswith(".jpg") or file.getName().lower().endswith(".mp4") or file.getName().lower().endswith(".png"): if re.match(r"[0-9]{16}-[0-9a-fA-F]{32}\.(jpg|png|mp4)", file.getName()): self.log(Level.INFO, "Found a Switch screenshot: " + file.getName()) self.filesFound += 1 self.path_to_data = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'game_hash_ids.json') if not os.path.exists(self.path_to_data): raise IngestModuleException("game_ids was not found in module folder") filename = file.getName().upper() timestamp = filename.split("-")[0] parsed_ts = datetime.strptime(timestamp, "%Y%m%d%H%M%S%f").strftime('%H:%M %d/%m/%Y') gameID = filename.split("-")[1].split(".")[0] with open(self.path_to_data, "r") as data_file: gids = json.load(data_file) if gameID in gids: game = gids[gameID] else: game = "Unknown gameID" # Don't add to blackboard if the artifact already exists artifactList = file.getArtifacts(artID_ns_ss_id) for artifact in artifactList: dupe_test = artifact.getAttribute(attID_ns_gid) if dupe_test: return IngestModule.ProcessResult.OK art = file.newArtifact(artID_ns_ss_id) art.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID(), FindScreenshotsIngestModuleFactory.moduleName, "Nintendo Switch - Screenshots")) art.addAttribute(BlackboardAttribute(attID_ns_gid, FindScreenshotsIngestModuleFactory.moduleName, game)) art.addAttribute(BlackboardAttribute(attID_ns_ts, FindScreenshotsIngestModuleFactory.moduleName, parsed_ts)) # Fire an event to notify the UI and others that there is a new artifact IngestServices.getInstance().fireModuleDataEvent(ModuleDataEvent(FindScreenshotsIngestModuleFactory.moduleName, artID_ns_ss, None)) return IngestModule.ProcessResult.OK
def process(self, file): def luhnChecksumIsValid(cardNumber): # check to make sure that the card passes a luhn mod-10 checksum total = 0 oddTotal = 0 evenTotal = 0 reversedCardNumber = cardNumber[::-1] oddDigits = reversedCardNumber[0::2] evenDigits = reversedCardNumber[1::2] for count in range(0, len(oddDigits)): oddTotal += int(oddDigits[count]) for count in range(0, len(evenDigits)): evenDigit = int(evenDigits[count]) evenDigit = evenDigit * 2 if evenDigit > 9: evenDigit = evenDigit - 9 evenTotal += evenDigit total = oddTotal + evenTotal return (total % 10 == 0) # Skip non-files if ((file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) or (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) or (file.isFile() == False)): return IngestModule.ProcessResult.OK inputStream = ReadContentInputStream(file) text = IOUtils.toString(inputStream, StandardCharsets.UTF_8) if self.skipBinaries: if b'\x00' in text: return IngestModule.ProcessResult.OK initialCCPattern = '[1-6](?:\d[ -]*?){13,23}' possibleCCs = re.findall(initialCCPattern, text, re.IGNORECASE) self.fileFlagged = 0 if possibleCCs: for cc in possibleCCs: delim_regex = "\D+" cc = re.sub(delim_regex, '', cc) if luhnChecksumIsValid(cc): if self.fileFlagged == 0: self.filesFound += 1 art = file.newArtifact( BlackboardArtifact.ARTIFACT_TYPE. TSK_INTERESTING_FILE_HIT) att = BlackboardAttribute( BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME. getTypeID(), PaymentCardFileIngestModuleFactory.moduleName, "Files With Possible Payment Card Numbers") art.addAttribute(att) IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent( PaymentCardFileIngestModuleFactory.moduleName, BlackboardArtifact.ARTIFACT_TYPE. TSK_INTERESTING_FILE_HIT, None)) self.fileFlagged = 1 return IngestModule.ProcessResult.OK
def index_artifact(self, blackboard, artifact, artifact_type): try: # Index the artifact for keyword search blackboard.indexArtifact(artifact) except Blackboard.BlackboardException as e: self.log(Level.INFO, "Error indexing artifact " + artifact.getDisplayName() + " " +str(e)) # Fire an event to notify the UI and others that there is a new log artifact IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent(NotificationAnalyzerDataSourceIngestModuleFactory.moduleName, artifact_type, None))
def process(self, file): skCase = Case.getCurrentCase().getSleuthkitCase() ARTID_NS_TV = skCase.getArtifactTypeID(self.ARTIFACTTYPENAME_NS_TV) names = [] skCase = Case.getCurrentCase().getSleuthkitCase() # Skip non-files if ((file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) or (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) or (file.isFile() is False)): return IngestModule.ProcessResult.OK blackboard = Case.getCurrentCase().getServices().getBlackboard() if file.getName() == "80000000000000d1": artifactList = file.getArtifacts(ARTID_NS_TV) self.log(Level.INFO, "Found the file" + file.getName()) self.filesFound += 1 inputStream = ReadContentInputStream(file) buffer = jarray.zeros(2048, "b") totLen = 0 lengthofbuffer = inputStream.read(buffer) while lengthofbuffer != -1: totLen = totLen + lengthofbuffer lengthofbuffer = inputStream.read(buffer) currentBuffer = buffer.tostring() names = names + re.findall("EdidBlock.*?\\\\xfc\\\\x00(.*?)\\\\n.*?EdidExtensionBlock", repr(currentBuffer)) noduplicatesnames = list(set(names)) for tvname in noduplicatesnames: # Don't add to blackboard if the artifact already exists for artifact in artifactList: artifactName = artifact.getAttribute(self.NS_DISPLAY_ATTRIBUTES["Name"][3]) if artifactName.getValueString() == tvname: return IngestModule.ProcessResult.OK art = file.newArtifact(ARTID_NS_TV) art.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID(), ConnectedDisplayIngestModuleFactory.moduleName, "Nintendo Switch - Connected TV")) for attribute in self.NS_DISPLAY_ATTRIBUTES.keys(): art.addAttribute(BlackboardAttribute(self.NS_DISPLAY_ATTRIBUTES[attribute][3], ConnectedDisplayIngestModuleFactory.moduleName, str(tvname))) try: # index the artifact for keyword search blackboard.indexArtifact(art) except Blackboard.BlackboardException: self.log(Level.SEVERE, "Error indexing artifact " + art.getDisplayName()) IngestServices.getInstance().fireModuleDataEvent(ModuleDataEvent(ConnectedDisplayIngestModuleFactory.moduleName, skCase.getArtifactType(self.ARTIFACTTYPENAME_NS_TV), None)) return IngestModule.ProcessResult.OK
def addInterestingFileHitAttribute(artifact, moduleName, attributeName): attribute = BlackboardAttribute( BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID(), moduleName, attributeName) artifact.addAttribute(attribute) IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent( moduleName, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, None))
def process(self, file): # Skip non-files if ((file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) or (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) or (not file.isFile())): return IngestModule.ProcessResult.OK def getBlackboardAtt(label, value): return BlackboardAttribute( BlackboardAttribute.ATTRIBUTE_TYPE.fromLabel( label).getTypeID(), GeolocationBlackvue.moduleName, value) if file.getName().lower().endswith(".mp4"): self.log( Level.INFO, "Found a mp4 file, possibly a BlackVue dashcam recording: " + file.getName()) platform_suffix = '.exe' if hasattr(platform, 'win32_ver') else '' # get an input buffer filesize = file.getSize() buffer = jarray.zeros(filesize, 'b') file.read(buffer, 0, filesize) file.close() temporary = tempfile.NamedTemporaryFile() temporary.write(buffer) # call our "binary" and supply our temporary file # TODO pipe our file in instead of making a temporary copy output = subprocess.check_output( os.path.join(os.path.dirname(os.path.realpath(__file__)), 'dist', 'parse_mp4') + platform_suffix + ' ' + temporary.name) locations = json.loads(output) for unix, lat, lon in locations: art = file.newArtifact( BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT) lat = getBlackboardAtt("TSK_GEO_LATITUDE", lat) lon = getBlackboardAtt("TSK_GEO_LONGITUDE", lon) art.addAttributes([lat, lon]) IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent( GeolocationBlackvue.moduleName, BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT, None)) return IngestModule.ProcessResult.OK
def addInterestingFileHitAttributes(artifact, moduleName, attributesDict): attributesList = [] for m in range(0, len(attributesDict)): attribute = BlackboardAttribute( list(attributesDict.values())[m].getTypeID(), moduleName, list(attributesDict)[m]) attributesList.append(attribute) artifact.addAttributes(attributesList) IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent( moduleName, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, None))
def process(self, file): skCase = Case.getCurrentCase().getSleuthkitCase() artID_ns_lboot = skCase.getArtifactType("TSK_ART_NS_LBOOT") artID_ns_lboot_id = skCase.getArtifactTypeID("TSK_ART_NS_LBOOT") attID_ns_lboot = skCase.getAttributeType("TSK_ATT_NS_LBOOT") if ((file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) or (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) or (file.isFile() is False)): return IngestModule.ProcessResult.OK if file.getName().upper() == "8000000000000060": self.log(Level.INFO, "Found a Bootup timestamp: " + file.getName()) self.filesFound += 1 timestamp = file.getMtimeAsDate() # Lets not add to blackboard if the artifact already exists artifactList = file.getArtifacts(artID_ns_lboot_id) for artifact in artifactList: dupe_test = artifact.getAttribute(attID_ns_lboot) if dupe_test: return IngestModule.ProcessResult.OK art = file.newArtifact(artID_ns_lboot_id) art.addAttribute( BlackboardAttribute( BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID( ), FindLastBootIngestModuleFactory.moduleName, "Nintendo Switch - Last Boot Time")) art.addAttribute( BlackboardAttribute(attID_ns_lboot, FindLastBootIngestModuleFactory.moduleName, timestamp)) # Fire an event to notify the UI and others that there is a new artifact IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent(FindLastBootIngestModuleFactory.moduleName, artID_ns_lboot, None)) return IngestModule.ProcessResult.OK
def create_an_artifact(self, blackboard, file, title): art = file.newArtifact( BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT) att = BlackboardAttribute( BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID(), AutopsyImageClassificationModuleFactory.moduleName, title) art.addAttribute(att) try: # index the artifact for keyword search blackboard.indexArtifact(art) except Blackboard.BlackboardException as e: self.log(Level.SEVERE, "Error indexing artifact " + art.getDisplayName()) # Fire an event to notify the UI and others that there is a new artifact IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent( AutopsyImageClassificationModuleFactory.moduleName, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT))
def addNewMetadataAttribute(blackboard, artifact, artId, moduleName, metadataAttributeName, metadataAttribute): attId = blackboard.getOrAddAttributeType( "TSK_" + metadataAttributeName, BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, metadataAttributeName) attribute = BlackboardAttribute(attId, moduleName, metadataAttribute) # Adding the Attribute to the Artifact artifact.addAttribute(attribute) # Error Test #artifact.addAttribute(None) blackboard.indexArtifact(artifact) # Fires an event to notify the UI and others that there is a new artifact # So that the UI updates and refreshes with the new artifacts when the module is executed IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent(moduleName, artId, None))
def process(self, file): # Use blackboard class to index blackboard artifacts for keyword search blackboard = Case.getCurrentCase().getServices().getBlackboard() # Skip non-files. In production you'll probable see that this can be added to in order to skip obvious false positives (ie small files). Kept this up here because it (for some reason) makes everything go faster if ((file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) or (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) or (file.isFile() == False)): return IngestModule.ProcessResult.OK # Make the file name passed by Autopsy lowercase and check if it matches a 'known' naming convention: # List 'knowns' can be updated to add more search criteria. knowns = ["segwit", "mainnet", "wallet", "spv", "bech", "bc1"] if any(x in file.getName().lower() for x in knowns): # Filter the obvious flase positives. You can continue to add to this condition using this format if ((file.getName().endswith("-slack") == True) or (file.getName().endswith("-journal") == True) or (file.getName().endswith("==-0") == True)): return IngestModule.ProcessResult.OK # Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of # artifact. Refer to the developer docs for other examples. # We used the generic type due to the limitations of creating our own artifact documented in the Sleuth Kit dev docs. art = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT) att = BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID(), FindCryptoWalletFilesIngestModuleFactory.moduleName, "Wallet Related Files") art.addAttribute(att) try: # index the artifact for keyword search blackboard.indexArtifact(art) except Blackboard.BlackboardException as e: self.log(Level.SEVERE, "Error indexing artifact " + art.getDisplayName()) # Fire an event to notify the UI and others that there is a new artifact IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent(FindCryptoWalletFilesIngestModuleFactory.moduleName, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, None)) return IngestModule.ProcessResult.OK
def process(self, file): try: if (filename): dbConn = DriverManager.getConnection("jdbc:sqlite:%s" % filename) stmt = dbConn.createStatement() path = file.getParentPath() + file.getName() resultSet = stmt.executeQuery( "SELECT * FROM META WHERE Path == '%s'" % path) if (resultSet.next()): temp = "Future Improvement" else: art = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE. TSK_INTERESTING_FILE_HIT) att = BlackboardAttribute( BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME. getTypeID(), MatchMetaInfoIngestModuleFactory.moduleName, "Unknown Meta") art.addAttribute(att) IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent( MatchMetaInfoIngestModuleFactory.moduleName, BlackboardArtifact.ARTIFACT_TYPE. TSK_INTERESTING_FILE_HIT, None)) stmt.close() dbConn.close() except: pass return IngestModule.ProcessResult.OK
def process(self, file): # Skip non-files if ((file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) or (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) or (file.isFile() == False)): return IngestModule.ProcessResult.OK # Look for files bigger than 10MB that are a multiple of 4096 if ((file.getSize() > 10485760) and ((file.getSize() % 4096) == 0)): # Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of # artifact. Refer to the developer docs for other examples. art = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT) att = BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID(), FindBigRoundFilesIngestModuleFactory.moduleName, "Big and Round Files") art.addAttribute(att) # Fire an event to notify the UI and others that there is a new artifact IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent(FindBigRoundFilesIngestModuleFactory.moduleName, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, None)); return IngestModule.ProcessResult.OK
def process(self, file): # Skip non-files if ((file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) or (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) or (file.isFile() == False)): return IngestModule.ProcessResult.OK # Look for files with extension docx, ,doc, pdf and txt extensions = ['docx','doc','pdf','txt','csv', 'ppt','pptx','rtf','html'] if (file.getNameExtension() in extensions): # Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of # artifact. Refer to the developer docs for other examples. art = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT) att = BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID(), FindTextFilesModuleFactory.moduleName, "Find text Files") # Create find text directory in module output directory, if it exists then continue on processing outpuDir = Case.getCurrentCase().getModulesOutputDirAbsPath() + "\TextFiles" self.log(Level.INFO, "create Directory " + outpuDir) try: os.mkdir(outpuDir) except: self.log(Level.INFO, "Find Text Directory already exists " + outpuDir) configFilesPath = os.path.join(outpuDir, str(file.getName())) ContentUtils.writeToFile(file, File(configFilesPath)) art.addAttribute(att) IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent(FindTextFilesModuleFactory.moduleName, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, None)); return IngestModule.ProcessResult.OK
def process(self, file): if ((file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) or (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) or (file.isFile() == False)): return IngestModule.ProcessResult.OK # Flags files with .pcap extensions and makes a blackboard artifact. if file.getName().lower().endswith(".pcap"): self.log(Level.INFO, "Found a pcap file: " + file.getName()) self.filesFound+=1 # Makes an artifact on the blackboard. art = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT) att = BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, NetArchaeologist.moduleName, "Text Files") art.addAttribute(att) try: # Indexes the artifact for keyword search. blackboard.indexArtifact(art) except Blackboard.BlackboardException as e: self.log(Level.SEVERE, "Error indexing artifact " + art.getDisplayName()) # Notifies user that there is a new artifact. IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent(NetArchaeologist.moduleName, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, None)); artifactList = file.getArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT) for artifact in artifactList: attributeList = artifact.getAttributes(); for attrib in attributeList: self.log(Level.INFO, attrib.toString()) return IngestModule.ProcessResult.OK
def process(self, dataSource, progressBar): # we don't know how much work there is yet progressBar.switchToIndeterminate() # Use blackboard class to index blackboard artifacts for keyword search blackboard = Case.getCurrentCase().getServices().getBlackboard() # Find files named contacts.db, regardless of parent path fileManager = Case.getCurrentCase().getServices().getFileManager() files = fileManager.findFiles(dataSource, "contacts.db") numFiles = len(files) progressBar.switchToDeterminate(numFiles) fileCount = 0 for file in files: # Check if the user pressed cancel while we were busy if self.context.isJobCancelled(): return IngestModule.ProcessResult.OK self.log(Level.INFO, "Processing file: " + file.getName()) fileCount += 1 # Save the DB locally in the temp folder. use file id as name to reduce collisions lclDbPath = os.path.join(Case.getCurrentCase().getTempDirectory(), str(file.getId()) + ".db") ContentUtils.writeToFile(file, File(lclDbPath)) # Open the DB using JDBC try: Class.forName("org.sqlite.JDBC").newInstance() dbConn = DriverManager.getConnection("jdbc:sqlite:%s" % lclDbPath) except SQLException as e: self.log( Level.INFO, "Could not open database file (not SQLite) " + file.getName() + " (" + e.getMessage() + ")") return IngestModule.ProcessResult.OK # Query the contacts table in the database and get all columns. try: stmt = dbConn.createStatement() resultSet = stmt.executeQuery("SELECT * FROM contacts") except SQLException as e: self.log( Level.INFO, "Error querying database for contacts table (" + e.getMessage() + ")") return IngestModule.ProcessResult.OK # Cycle through each row and create artifacts while resultSet.next(): try: name = resultSet.getString("name") email = resultSet.getString("email") phone = resultSet.getString("phone") except SQLException as e: self.log( Level.INFO, "Error getting values from contacts table (" + e.getMessage() + ")") # Make an artifact on the blackboard, TSK_CONTACT and give it attributes for each of the fields art = file.newArtifact( BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT) art.addAttribute( BlackboardAttribute( BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME_PERSON. getTypeID(), ContactsDbIngestModuleFactory.moduleName, name)) art.addAttribute( BlackboardAttribute( BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL.getTypeID( ), ContactsDbIngestModuleFactory.moduleName, email)) art.addAttribute( BlackboardAttribute( BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER. getTypeID(), ContactsDbIngestModuleFactory.moduleName, phone)) try: # index the artifact for keyword search blackboard.indexArtifact(art) except Blackboard.BlackboardException as e: self.log(Level.SEVERE, "Error indexing artifact " + art.getDisplayName()) # Fire an event to notify the UI and others that there are new artifacts IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent(ContactsDbIngestModuleFactory.moduleName, BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT, None)) # Clean up stmt.close() dbConn.close() os.remove(lclDbPath) # After all databases, post a message to the ingest messages in box. message = IngestMessage.createMessage(IngestMessage.MessageType.DATA, "ContactsDb Analyzer", "Found %d files" % fileCount) IngestServices.getInstance().postMessage(message) return IngestModule.ProcessResult.OK
def process(self, file): skCase = Case.getCurrentCase().getSleuthkitCase() artID_ns_rgh_id = skCase.getArtifactTypeID("TSK_ART_NS_RGH") artID_ns_rgh = skCase.getArtifactType("TSK_ART_NS_RGH") attID_ns_rgh_gid = skCase.getAttributeType("TSK_ATT_NS_RGH_GAME") attID_ns_rgh_ts = skCase.getAttributeType("TSK_ATT_NS_RGS_TS") attID_ns_rgh_e = skCase.getAttributeType("TSK_ATT_NS_RGS_E") # Skip non-files if ((file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) or (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) or (file.isFile() == False)): return IngestModule.ProcessResult.OK if (file.getParentPath().upper() == "/SAVE/") and (file.getName().upper() == "80000000000000A2"): self.log(Level.INFO, "Found game history") self.filesFound += 1 buf = zeros(file.getSize(), 'b') file.read(buf, 0, file.getSize()) entries = re.findall("sys_info.*sequence", buf) for entry in entries: app_id = binascii.hexlify( re.search("app_id.{2}(?P<app>.{8}).*?type", entry).group('app')).upper() if app_id in self.gids: game = self.gids[app_id] event = re.search("digital.event.(?P<event>.*?).sequence", entry) if not event: event_group = "N/A" else: event_group = event.group('event') timestamp = re.search("nc_recorded_at.(?P<ts>.*?).nsa_id", entry).group('ts') art = file.newArtifact(artID_ns_rgh_id) art.addAttribute( BlackboardAttribute( BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME. getTypeID(), GameHistoryIngestModuleFactory.moduleName, "Nintendo Switch - Game Save")) art.addAttribute( BlackboardAttribute( attID_ns_rgh_gid, GameHistoryIngestModuleFactory.moduleName, game)) art.addAttribute( BlackboardAttribute( attID_ns_rgh_ts, GameHistoryIngestModuleFactory.moduleName, timestamp)) art.addAttribute( BlackboardAttribute( attID_ns_rgh_e, GameHistoryIngestModuleFactory.moduleName, event_group)) # Fire an event to notify the UI and others that there is a new artifact IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent(GameHistoryIngestModuleFactory.moduleName, artID_ns_rgh, None)) return IngestModule.ProcessResult.OK
#---------------------------------------- # End timer of last stage #---------------------------------------- last_stage_time = time.time() - start_last_stage_time Log_S = "Last stage took %f secs" % (last_stage_time) self.log(Level.INFO, Log_S) if C_COMPUTE_HASHES: Log_S = "hashes took: MD5=%f secs; SHA1=%f secs; SHA256=%f secs" %\ (self.needed_time_MD5, self.needed_time_SHA1, self.needed_time_SHA256) else: Log_S = "hashes NOT computed" self.log(Level.INFO, Log_S) IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent(FDRIModuleFactory.moduleName, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, None)) # Should we delete the IMG files? (user's configuration) if self.deleteAfter: Msg_S = "Going to delete image files (as required by the user)" self.log(Level.INFO,Msg_S) dir_to_del = os.path.join(output_dir,dataSource.getName()) self.deleteFiles(dir_to_del) # End time measurement FDRIModuleFactory.g_elapsed_time_secs = time.time() -\ FDRIModuleFactory.g_start_time #------------------------------------------------------------
def process(self, dataSource, progressBar): # we don't know how much work there is yet progressBar.switchToIndeterminate() # Use blackboard class to index blackboard artifacts for keyword search # blackboard = Case.getCurrentCase().getServices().getBlackboard() #we're not using indexing # Get case case = Case.getCurrentCase().getSleuthkitCase() # For our example, we will use FileManager to get all # files with the word "test" # in the name and then count and read them # FileManager API: http://sleuthkit.org/autopsy/docs/api-docs/4.4/classorg_1_1sleuthkit_1_1autopsy_1_1casemodule_1_1services_1_1_file_manager.html fileManager = Case.getCurrentCase().getServices().getFileManager() swisscom_settings_file = fileManager.findFiles(dataSource, "com.swisscom.internetbox_preferences.xml") if self.local_settings.get_parse_settings() else [] qbee_settings_file = fileManager.findFiles(dataSource, "com.vestiacom.qbeecamera_preferences.xml") if self.local_settings.get_parse_settings() else [] num_files = len(qbee_settings_file) + len(swisscom_settings_file) self.log(Level.INFO, "found " + str(num_files) + " files") progressBar.switchToDeterminate(num_files) file_count = 0 # Settings tmp_dir = Case.getCurrentCase().getTempDirectory() out_dir = Case.getCurrentCase().getModuleDirectory() if self.local_settings.get_parse_settings(): # Settings File for Qbee App for file in qbee_settings_file: # Check if the user pressed cancel while we were busy if self.context.isJobCancelled(): return IngestModule.ProcessResult.OK self.log(Level.INFO, "Processing file: " + file.getName()) file_count += 1 # Write to file (any way to contour this?) lcl_setting_path = os.path.join(tmp_dir, str(file.getId()) + ".xml") ContentUtils.writeToFile(file, File(lcl_setting_path)) out_file_name = file.getName() + "_decrypted.json" dest_json_path = os.path.join(out_dir, out_file_name) pipe = Popen([self.path_to_exe, lcl_setting_path, dest_json_path], stdout=PIPE, stderr=PIPE) out_text = pipe.communicate()[0] self.log(Level.INFO, "Output from run is ==> " + out_text) with open(dest_json_path) as json_file: settings_clear = json.load(json_file) self.log(Level.INFO, "Settings: " + str(settings_clear)) try: settings_clear = settings_clear['decrypted_settings'][0] except KeyError: raise KeyError("JSON File format unknown") except IndexError: self.log(Level.INFO, "Error: No AES key candidates found while decrypting settings file.") continue json_info = os.stat(dest_json_path) print json_info.st_mtime encoding = TskData.EncodingType.valueOf(0) dest_json_rel_path = os.path.relpath(dest_json_path, Case.getCurrentCase().getCaseDirectory()) json_file = fileManager.addDerivedFile(out_file_name, dest_json_rel_path, int(json_info.st_size), int(json_info.st_ctime), int(json_info.st_ctime), int(json_info.st_atime), int(json_info.st_mtime), True, file, "QBee Module", "Qbee Module", "0.1", "", encoding) art_type_id = case.getArtifactTypeID("ESC_GENERIC_LOGIN") art_type = case.getArtifactType("ESC_GENERIC_LOGIN") # Make an artifact on the blackboard. # Set the DB file as an "interesting file" : TSK_INTERESTING_FILE_HIT is a generic type of # artifact. Refer to the developer docs for other examples. art = json_file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT) att = BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, QBeeIngestModuleFactory.moduleName, "QBee") art.addAttribute(att) # Artifact art = file.newArtifact(art_type_id) # Attributes att_login_username_id = case.getAttributeType("ESC_GENERIC_LOGIN_USERNAME") att_login_secret_id = case.getAttributeType("ESC_GENERIC_LOGIN_SECRET") att_login_secret_type_id = case.getAttributeType("ESC_GENERIC_LOGIN_SECRET_TYPE") att_login_service_id = case.getAttributeType("ESC_GENERIC_LOGIN_SERVICE") att_login_username = BlackboardAttribute(att_login_username_id, QBeeIngestModuleFactory.moduleName, settings_clear['qbeeUser']) att_login_secret = BlackboardAttribute(att_login_secret_id, QBeeIngestModuleFactory.moduleName, settings_clear['qbeePassword']) att_login_secret_type = BlackboardAttribute(att_login_secret_type_id, QBeeIngestModuleFactory.moduleName, "Password") att_login_service = BlackboardAttribute(att_login_service_id, QBeeIngestModuleFactory.moduleName, "QBee") art.addAttribute(att_login_username) art.addAttribute(att_login_secret) art.addAttribute(att_login_secret_type) art.addAttribute(att_login_service) IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent(QBeeIngestModuleFactory.moduleName, art_type, None)) progressBar.progress(file_count) # Settings File for Swisscom Home App for file in swisscom_settings_file: # Check if the user pressed cancel while we were busy if self.context.isJobCancelled(): return IngestModule.ProcessResult.OK self.log(Level.INFO, "Processing file: " + file.getName()) file_count += 1 # Write to file (any way to contour this?) lcl_setting_path = os.path.join(tmp_dir, str(file.getId()) + ".xml") ContentUtils.writeToFile(file, File(lcl_setting_path)) out_file_name = file.getName() + "_decrypted.json" dest_json_path = os.path.join(out_dir, out_file_name) pipe = Popen([self.path_to_exe, lcl_setting_path, dest_json_path], stdout=PIPE, stderr=PIPE) out_text = pipe.communicate()[0] self.log(Level.INFO, "Output from run is ==> " + out_text) with open(dest_json_path) as json_file: settings_clear = json.load(json_file) self.log(Level.INFO, "Settings: " + str(settings_clear)) try: settings_clear = settings_clear['decrypted_settings'][0] except KeyError: raise KeyError("JSON File format unknown") except IndexError: self.log(Level.INFO, "Error: No AES key candidates found while decrypting settings file.") continue json_info = os.stat(dest_json_path) print json_info.st_mtime encoding = TskData.EncodingType.valueOf(0) dest_json_rel_path = os.path.relpath(dest_json_path, Case.getCurrentCase().getCaseDirectory()) json_file = fileManager.addDerivedFile(out_file_name, dest_json_rel_path, int(json_info.st_size), int(json_info.st_ctime), int(json_info.st_ctime), int(json_info.st_atime), int(json_info.st_mtime), True, file, "QBee Module", "Qbee Module", "0.1", "", encoding) # Make an artifact on the blackboard. # Set the DB file as an "interesting file" : TSK_INTERESTING_FILE_HIT is a generic type of # artifact. Refer to the developer docs for other examples. art = json_file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT) att = BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, QBeeIngestModuleFactory.moduleName, "Swisscom Home App") art.addAttribute(att) progressBar.progress(file_count) # FINISHED! # Post a message to the ingest messages in box. message = IngestMessage.createMessage(IngestMessage.MessageType.DATA, "QBee Analysis", "Found %d files" % file_count) IngestServices.getInstance().postMessage(message) return IngestModule.ProcessResult.OK
def process(self, file): skCase = Case.getCurrentCase().getSleuthkitCase() artID_ns_mph = skCase.getArtifactType("TSK_ART_NS_MPH") artID_ns_mph_id = skCase.getArtifactTypeID("TSK_ART_NS_MPH") attID_ns_cd_mph_user = skCase.getAttributeType("TSK_ATT_MPH_USER") attID_ns_cd_mph_game = skCase.getAttributeType("TSK_ATT_MPH_GAME") # Not implemented. # attID_ns_cd_mph_ts = skCase.getAttributeType("TSK_ATT_MPH_TS") # Skip non-files if ((file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) or (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) or (file.isFile() is False)): return IngestModule.ProcessResult.OK if (file.getParentPath().upper() == "/SAVE/") and (file.getName().upper() == "0000000000000001"): self.log(Level.INFO, "Found MP user history save") self.filesFound += 1 buf = zeros(file.getSize(), 'b') file.read(buf, 0, file.getSize()) tmp_file_path = os.path.join(self.tmp_path, file.getName()) with open(tmp_file_path, 'wb+') as tmp_file: tmp_file.write(buf) hac_cmd = [ self.hac_path, "-t", "save", "--outdir", self.tmp_path, tmp_file_path ] subprocess.call(hac_cmd) mp_hist_file = os.path.join(self.tmp_path, "history.bin") users = [] with open(mp_hist_file, "rb") as hist_file: while True: chunk = binascii.hexlify(hist_file.read(256)) if not chunk: break user = {} user["block_a"] = chunk[:48] user["block_b"] = chunk[48:64] user["block_c"] = chunk[64:80] user["block_d"] = chunk[80:192] user["block_e"] = chunk[192:224] user["block_f"] = chunk[224:-1] user["username"] = binascii.unhexlify( user["block_d"]).split("\x00")[0] user["game_id"] = "".join( reversed([ user["block_b"][i:i + 2] for i in range(0, len(user["block_b"]), 2) ])).upper() if user["game_id"] in self.gids: user["game"] = self.gids[user["game_id"]] users.append(user) # Don't add to blackboard if already exists - TODO improve when timestamp is implemented artifactList = file.getArtifacts(artID_ns_mph_id) seen_users = [] for artifact in artifactList: seen_users.append( artifact.getAttribute( attID_ns_cd_mph_user).getValueString()) for u in seen_users: self.log( Level.INFO, "Ingest MP User - Online multiplayer user found: %s" % u) for user in users: # Don't add to blackboard if already exists - TODO improve when timestamp is implemented if user["username"] in seen_users: return IngestModule.ProcessResult.OK art = file.newArtifact(artID_ns_mph_id) art.addAttribute( BlackboardAttribute( BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME. getTypeID(), MpUserHistoryIngestModuleFactory.moduleName, "Nintendo Switch - MP User History")) art.addAttribute( BlackboardAttribute( attID_ns_cd_mph_user, MpUserHistoryIngestModuleFactory.moduleName, user["username"])) if "game" in user: art.addAttribute( BlackboardAttribute( attID_ns_cd_mph_game, MpUserHistoryIngestModuleFactory.moduleName, user["game"])) # Fire an event to notify the UI and others that there is a new artifact IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent( MpUserHistoryIngestModuleFactory.moduleName, artID_ns_mph, None)) return IngestModule.ProcessResult.OK
def process(self, dataSource, progressBar): PostBoard = IngestServices.getInstance() progressBar.switchToIndeterminate() #Current case ccase = Case.getCurrentCase().getSleuthkitCase() blackboard = Case.getCurrentCase().getServices().getBlackboard() fileManager = Case.getCurrentCase().getServices().getFileManager() files = fileManager.findFiles(dataSource, "msapplication.xml") numFiles = len(files) message = IngestMessage.createMessage( IngestMessage.MessageType.DATA, "IE Tiles Analyzer", "About to analyze " + str(numFiles) + " files") PostBoard.postMessage(message) progressBar.switchToDeterminate(numFiles) try: #Try adding the Articaft Type artifact_name = "TSK_IETILES" artifact_desc = "IE Tiles Analyzer" artID_tiles = ccase.addArtifactType(artifact_name, artifact_desc) artID_tiles_evt = ccase.getArtifactType(artifact_name) attribute_name = "TSK_TILES_SITE" attribute_name2 = "TSK_TILES_DATE" attribute_name3 = "TSK_TILES_ACCESSDATE" attID_ex1 = ccase.addArtifactAttributeType( attribute_name, BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Site") attID_ex2 = ccase.addArtifactAttributeType( attribute_name2, BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Date") attID_ex3 = ccase.addArtifactAttributeType( attribute_name3, BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Access Date") except: message = IngestMessage.createMessage( IngestMessage.MessageType.DATA, "IE Tiles Analyzer", "Already created?") PostBoard.postMessage(message) fileCount = 0 for file in files: fileCount += 1 progressBar.progress(fileCount) progressBar.progress("IE Tiles Analyzer") if self.context.isJobCancelled(): return IngestModule.ProcessResult.OK self.log(Level.INFO, "++++++Processing file: " + file.getName()) self.log(Level.INFO, "File count:" + str(fileCount)) lclXMLPath = os.path.join(Case.getCurrentCase().getTempDirectory(), str(file.getId()) + ".xml") ContentUtils.writeToFile(file, File(lclXMLPath)) message = IngestMessage.createMessage( IngestMessage.MessageType.DATA, "IE Tiles Analyzer", lclXMLPath) #PostBoard.postMessage(message) try: tree = ET.ElementTree(file=lclXMLPath) root = tree.getroot() for config in root.iter('site'): site = config.attrib.get('src') message = IngestMessage.createMessage( IngestMessage.MessageType.DATA, "IE Tiles Analyzer", site) PostBoard.postMessage(message) for dates in root.iter('accdate'): accessD = dates.text.split(",") AloValue = accessD[0] AhiValue = accessD[1] accessdate = CalculateTime(AloValue, AhiValue) for dates in root.iter('date'): createD = dates.text.split(",") CloValue = createD[0] ChiValue = createD[1] normaldate = CalculateTime(CloValue, ChiValue) if len(site) > 0: artifact_name = "TSK_IETILES" artifact_desc = "IE Tiles Analyzer" artID_tiles_evt = ccase.getArtifactType(artifact_name) artID_tiles = ccase.getArtifactTypeID(artifact_name) art = file.newArtifact(artID_tiles) attID_ex1 = ccase.getAttributeType("TSK_TILES_SITE") art.addAttribute( BlackboardAttribute( attID_ex1, IETilesIngestModuleFactory.moduleName, site)) attID_ex1 = ccase.getAttributeType("TSK_TILES_DATE") art.addAttribute( BlackboardAttribute( attID_ex1, IETilesIngestModuleFactory.moduleName, normaldate)) attID_ex1 = ccase.getAttributeType("TSK_TILES_ACCESSDATE") art.addAttribute( BlackboardAttribute( attID_ex1, IETilesIngestModuleFactory.moduleName, accessdate)) PostBoard.fireModuleDataEvent(ModuleDataEvent(IETilesIngestModuleFactory.moduleName, \ artID_tiles_evt, None)) else: message = IngestMessage.createMessage( IngestMessage.MessageType.DATA, "IE Tiles Analyzer", "No sites found: " + lclXMLPath) PostBoard.postMessage(message) except: message = IngestMessage.createMessage( IngestMessage.MessageType.DATA, "IE Tiles Analyzer", "SOMETHING WENT WRONG") PostBoard.postMessage(message) # Clean up os.remove(lclXMLPath) # After all XML files, post a message to the ingest messages in box. if numFiles == 0: message = IngestMessage.createMessage( IngestMessage.MessageType.DATA, "IE Tiles Analyzer", "Nothing to analyze ") PostBoard.postMessage(message) else: message = IngestMessage.createMessage( IngestMessage.MessageType.DATA, "IE Tiles Analyzer", "Analyzed %d files" % fileCount) PostBoard.postMessage(message) return IngestModule.ProcessResult.OK
def process(self, dataSource, progressBar): self.log( Level.INFO, "Starting to process, Just before call to parse_safari_history") # we don't know how much work there is yet progressBar.switchToIndeterminate() self.log( Level.INFO, "Starting 2 to process, Just before call to parse_safari_history") skCase = Case.getCurrentCase().getSleuthkitCase() head, tail = os.path.split(os.path.abspath(__file__)) settings_db = head + "\\alexa_db.db3" #Start to process based on version of OS try: Class.forName("org.sqlite.JDBC").newInstance() dbConn = DriverManager.getConnection("jdbc:sqlite:%s" % settings_db) except SQLException as e: self.log( Level.INFO, "Could not open database file (not SQLite) macos_recents.db3 (" + e.getMessage() + ")") return IngestModule.ProcessResult.OK # Query the database table for unique file names try: stmt = dbConn.createStatement() process_data_sql = "Select distinct file_name from alexa_databases" self.log(Level.INFO, process_data_sql) resultSet = stmt.executeQuery(process_data_sql) self.log(Level.INFO, "Query Database table for unique file names") except SQLException as e: self.log(Level.INFO, "Error querying database for unique file names") return IngestModule.ProcessResult.OK # Process all the artifacts based on version of the OS while resultSet.next(): fileManager = Case.getCurrentCase().getServices().getFileManager() files = fileManager.findFiles(dataSource, resultSet.getString("file_name")) numFiles = len(files) self.log( Level.INFO, "found " + str(numFiles) + " files for file_name ==> " + resultSet.getString("file_name")) progressBar.switchToDeterminate(numFiles) fileCount = 0 for file in files: # Open the DB using JDBC #lclDbPath = os.path.join(Case.getCurrentCase().getTempDirectory(), SQLite_DB) lclDbPath = os.path.join( Case.getCurrentCase().getTempDirectory(), file.getName() + "-" + str(file.getId())) ContentUtils.writeToFile(file, File(lclDbPath)) #self.log(Level.INFO, "Path the prefetch database file created ==> " + lclDbPath) try: Class.forName("org.sqlite.JDBC").newInstance() dbConn_x = DriverManager.getConnection("jdbc:sqlite:%s" % lclDbPath) self.log(Level.INFO, "Database ==> " + file.getName()) except SQLException as e: self.log( Level.INFO, "Could not open database file (not SQLite) " + file.getName() + "-" + str(file.getId()) + " (" + e.getMessage() + ")") #return IngestModule.ProcessResult.OK try: stmt_sql = dbConn.createStatement() process_stmt_sql = "select artifact_name, artifact_description, sql_to_run from alexa_databases where file_name = '" + resultSet.getString( "file_name") + "';" self.log(Level.INFO, process_stmt_sql) resultSet_sql = stmt_sql.executeQuery(process_stmt_sql) self.log(Level.INFO, "Query Database table for sql statements") except SQLException as e: self.log( Level.INFO, "Error querying database for sql_statements for file " + resultSet.getString("file_name")) # return IngestModule.ProcessResult.OK # Process all the artifacts based on version of the OS while resultSet_sql.next(): try: stmt_1 = dbConn_x.createStatement() sql_to_run = resultSet_sql.getString("sql_to_run") self.log(Level.INFO, sql_to_run) resultSet_3 = stmt_1.executeQuery(sql_to_run) self.log(Level.INFO, "query " + sql_to_run) except SQLException as e: self.log( Level.INFO, "Error querying database for " + resultSet.getString("file_name")) continue # return IngestModule.ProcessResult.OK try: #self.log(Level.INFO, "Begin Create New Artifacts") artID_sql = skCase.addArtifactType( resultSet_sql.getString("artifact_name"), resultSet_sql.getString("artifact_description")) except: self.log( Level.INFO, "Artifacts Creation Error, for artifact. ==> " + resultSet_sql.getString("artifact_name")) artID_hst = skCase.getArtifactTypeID( resultSet_sql.getString("artifact_name")) artID_hst_evt = skCase.getArtifactType( resultSet_sql.getString("artifact_name")) meta = resultSet_3.getMetaData() columncount = meta.getColumnCount() column_names = [] self.log( Level.INFO, "Number of Columns in the table ==> " + str(columncount)) for x in range(1, columncount + 1): self.log(Level.INFO, "Column Name ==> " + meta.getColumnLabel(x)) try: attID_ex1 = skCase.addArtifactAttributeType( "TSK_ALEXA_" + meta.getColumnLabel(x).upper(), BlackboardAttribute. TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, meta.getColumnLabel(x)) except: self.log( Level.INFO, "Attributes Creation Error, " + "TSK_ALEXA_" + meta.getColumnLabel(x) + " ==> ") column_names.append(meta.getColumnLabel(x)) self.log(Level.INFO, "All Columns ==> " + str(column_names)) # Cycle through each row and create artifacts while resultSet_3.next(): try: #self.log(Level.INFO, SQL_String_1) self.log(Level.INFO, "Artifact Is ==> " + str(artID_hst)) art = file.newArtifact(artID_hst) self.log(Level.INFO, "Inserting attribute URL") for col_name in column_names: attID_ex1 = skCase.getAttributeType( "TSK_ALEXA_" + col_name.upper()) self.log( Level.INFO, "Inserting attribute ==> " + str(attID_ex1)) self.log( Level.INFO, "Attribute Type ==> " + str(attID_ex1.getValueType())) if attID_ex1.getValueType( ) == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING: try: art.addAttribute( BlackboardAttribute( attID_ex1, Alexa_DB_ParseIngestModuleFactory .moduleName, resultSet_3.getString( col_name))) except: self.log( Level.INFO, "Attributes String Creation Error, " + col_name + " ==> ") elif attID_ex1.getValueType( ) == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.INTEGER: try: art.addAttribute( BlackboardAttribute( attID_ex1, Alexa_DB_ParseIngestModuleFactory .moduleName, resultSet_3.getInt(col_name))) except: self.log( Level.INFO, "Attributes Integer Creation Error, " + col_name + " ==> ") elif attID_ex1.getValueType( ) == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.LONG: try: art.addAttribute( BlackboardAttribute( attID_ex1, Alexa_DB_ParseIngestModuleFactory .moduleName, resultSet_3.getInt(col_name))) except: self.log( Level.INFO, "Attributes Long Creation Error, " + col_name + " ==> ") elif attID_ex1.getValueType( ) == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DOUBLE: try: art.addAttribute( BlackboardAttribute( attID_ex1, Alexa_DB_ParseIngestModuleFactory .moduleName, resultSet_3.getInt(col_name))) except: self.log( Level.INFO, "Attributes Double Creation Error, " + col_name + " ==> ") elif attID_ex1.getValueType( ) == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.BYTE: try: art.addAttribute( BlackboardAttribute( attID_ex1, Alexa_DB_ParseIngestModuleFactory .moduleName, resultSet_3.getString( col_name))) except: self.log( Level.INFO, "Attributes Byte Creation Error, " + col_name + " ==> ") else: try: art.addAttribute( BlackboardAttribute( attID_ex1, Alexa_DB_ParseIngestModuleFactory .moduleName, resultSet_3.getReal(col_name))) except: self.log( Level.INFO, "Attributes Datatime Creation Error, " + col_name + " ==> ") except SQLException as e: self.log( Level.INFO, "Error getting values from sql statement ==> " + resultSet_sql.getString("artifact_name")) IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent( Alexa_DB_ParseIngestModuleFactory.moduleName, artID_hst_evt, None)) stmt_1.close() stmt_sql.close() dbConn_x.close() # After all databases, post a message to the ingest messages in box. message = IngestMessage.createMessage( IngestMessage.MessageType.DATA, "Mac OS Recent Artifacts", " Mac OS Recents Artifacts Have Been Analyzed ") IngestServices.getInstance().postMessage(message) return IngestModule.ProcessResult.OK
def process(self, dataSource, progressBar): self.log(Level.INFO, "Starting to process, Just before call to parse_safari_history") # we don't know how much work there is yet progressBar.switchToIndeterminate() skCase = Case.getCurrentCase().getSleuthkitCase(); self.log(Level.INFO, "Starting Processing of Image") image_names = dataSource.getPaths() self.log(Level.INFO, "Image names ==> " + str(image_names[0])) image_name = str(image_names[0]) # Create VSS directory in ModuleOutput directory, if it exists then continue on processing Mod_Dir = Case.getCurrentCase().getModulesOutputDirAbsPath() Temp_Dir = Case.getCurrentCase().getTempDirectory() self.log(Level.INFO, "create Directory " + Temp_Dir) vss_output = os.path.join(Mod_Dir, "vss") try: os.mkdir(vss_output) except: self.log(Level.INFO, "Vss already exists " + Temp_Dir) lclDbPath = os.path.join(vss_output, "vss_extract_info.db3") vss_error_log = os.path.join(vss_output, "bad_files.log") # Run the Processing/Extraction process self.log(Level.INFO, "Running prog ==> " + self.path_to_exe_vss + " " + image_name + " " + lclDbPath + " " + vss_output + " " + vss_error_log) pipe = Popen([self.path_to_exe_vss, image_name, lclDbPath, vss_output, vss_error_log], stdout=PIPE, stderr=PIPE) out_text = pipe.communicate()[0] self.log(Level.INFO, "Output from run is ==> " + out_text) try: attID_vs_fn = skCase.addArtifactAttributeType("TSK_VSS_MFT_NUMBER", BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "MFT Number") except: self.log(Level.INFO, "Attributes Creation Error, MFT Number. ==> ") try: attID_vs_ct = skCase.addArtifactAttributeType("TSK_VSS_DATETIME_CHANGED", BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME, "Recovered Record") except: self.log(Level.INFO, "Attributes Creation Error, changed time. ==> ") try: attID_vs_sz = skCase.addArtifactAttributeType("TSK_VSS_FILE_SIZE", BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.LONG, "File Size") except: self.log(Level.INFO, "Attributes Creation Error, Computer Name. ==> ") try: Class.forName("org.sqlite.JDBC").newInstance() dbConn = DriverManager.getConnection("jdbc:sqlite:%s" % lclDbPath) except SQLException as e: self.log(Level.INFO, "Could not open database file (not SQLite) " +" (" + e.getMessage() + ")") return IngestModule.ProcessResult.OK try: stmt = dbConn.createStatement() SQL_Statement = "select ' - '||vss_identifier||' - '||DATETIME((SUBSTR(vss_create_dttm,1,11)-11644473600),'UNIXEPOCH') 'VOL_NAME', " + \ " vss_num, volume_id, vss_identifier from vss_info;" self.log(Level.INFO, "SQL Statement " + SQL_Statement + " <<=====") resultSet = stmt.executeQuery(SQL_Statement) except SQLException as e: self.log(Level.INFO, "Error querying database for EventLogs table (" + e.getMessage() + ")") return IngestModule.ProcessResult.OK # Cycle through each row and create artifacts while resultSet.next(): dir_list = [] vss_identifier = resultSet.getString("vss_identifier") vss_num = int(resultSet.getString("vss_num")) - 1 dir_list.append(vss_output + "\\vss" + str(vss_num)) services = IngestServices.getInstance() progress_updater = ProgressUpdater() newDataSources = [] # skCase = Case.getCurrentCase().getSleuthkitCase(); fileManager = Case.getCurrentCase().getServices().getFileManager() skcase_data = Case.getCurrentCase() # Get a Unique device id using uuid device_id = UUID.randomUUID() self.log(Level.INFO, "device id: ==> " + str(device_id)) skcase_data.notifyAddingDataSource(device_id) # Add data source with files newDataSource = fileManager.addLocalFilesDataSource(str(device_id), "vss" + str(vss_num) + resultSet.getString("VOL_NAME"), "", dir_list, progress_updater) newDataSources.append(newDataSource.getRootDirectory()) # Get the files that were added files_added = progress_updater.getFiles() #self.log(Level.INFO, "Fire Module1: ==> " + str(files_added)) for file_added in files_added: skcase_data.notifyDataSourceAdded(file_added, device_id) #self.log(Level.INFO, "Fire Module1: ==> " + str(file_added)) #skcase.notifyDataSourceAdded(device_id) skCse = Case.getCurrentCase().getSleuthkitCase() vss_fileManager = Case.getCurrentCase().getServices().getFileManager() vss_files = fileManager.findFiles(dataSource, "%" + vss_identifier + "%", "System Volume Information") vss_numFiles = len(vss_files) #self.log(Level.INFO, "Number of VSS FIles is ==> " + str(vss_numFiles) + " <<= FIle Name is ++> " + str(vss_files)) for vs in vss_files: if vs.getName() in "-slack": pass try: self.log(Level.INFO, "Begin Create New Artifacts") artID_vss = skCase.addArtifactType( "TSK_VS_VOLUME_" + str(vss_num), "vss" + str(vss_num) + resultSet.getString("VOL_NAME") + " Files") except: self.log(Level.INFO, "Artifacts Creation Error, some artifacts may not exist now. ==> ") artID_vss = skCase.getArtifactTypeID("TSK_VS_VOLUME_" + str(vss_num)) artID_vss = skCase.getArtifactTypeID("TSK_VS_VOLUME_" + str(vss_num)) artID_vss_evt = skCase.getArtifactType("TSK_VS_VOLUME_" + str(vss_num)) attID_vs_fn = skCase.getAttributeType("TSK_VSS_MFT_NUMBER") attID_vs_ct = skCase.getAttributeType("TSK_VSS_DATETIME_CHANGED") attID_vs_sz = skCase.getAttributeType("TSK_VSS_FILE_SIZE") attID_vs_nm = skCase.getAttributeType("TSK_NAME") attID_vs_pa = skCase.getAttributeType("TSK_PATH") attID_vs_md = skCase.getAttributeType("TSK_DATETIME_MODIFIED") attID_vs_ad = skCase.getAttributeType("TSK_DATETIME_ACCESSED") attID_vs_cr = skCase.getAttributeType("TSK_DATETIME_CREATED") for vs_file in vss_files: if "-slack" in vs_file.getName(): pass else: self.log(Level.INFO, "VSS FIles is ==> " + str(vs_file)) try: stmt_1 = dbConn.createStatement() SQL_Statement_1 = "select file_name, inode, directory, ctime, mtime, atime, crtime, size " + \ " from vss1_diff where lower(f_type) <> 'dir';" self.log(Level.INFO, "SQL Statement " + SQL_Statement_1 + " <<=====") resultSet_1 = stmt_1.executeQuery(SQL_Statement_1) except SQLException as e: self.log(Level.INFO, "Error querying database for vss diff tables (" + e.getMessage() + ")") return IngestModule.ProcessResult.OK # Cycle through each row and create artifacts while resultSet_1.next(): try: File_Name = resultSet_1.getString("file_name") Path_Name = resultSet_1.getString("directory") MFT_Number = resultSet_1.getString("inode") Ctime = resultSet_1.getInt("ctime") Mtime = resultSet_1.getInt("mtime") Atime = resultSet_1.getInt("atime") Crtime = resultSet_1.getInt("crtime") File_Size = resultSet_1.getInt("size") except SQLException as e: self.log(Level.INFO, "Error getting values from vss diff table (" + e.getMessage() + ")") # Make an artifact on the blackboard, TSK_PROG_RUN and give it attributes for each of the fields # Make artifact for TSK_EVTX_LOGS art = vs_file.newArtifact(artID_vss) art.addAttributes(((BlackboardAttribute(attID_vs_nm, VSSIngesttModuleFactory.moduleName, File_Name)), \ (BlackboardAttribute(attID_vs_fn, VSSIngesttModuleFactory.moduleName, MFT_Number)), \ (BlackboardAttribute(attID_vs_pa, VSSIngesttModuleFactory.moduleName, Path_Name)), \ (BlackboardAttribute(attID_vs_cr, VSSIngesttModuleFactory.moduleName, Crtime)), \ (BlackboardAttribute(attID_vs_md, VSSIngesttModuleFactory.moduleName, Mtime)), \ (BlackboardAttribute(attID_vs_ad, VSSIngesttModuleFactory.moduleName, Atime)), \ (BlackboardAttribute(attID_vs_ct, VSSIngesttModuleFactory.moduleName, Ctime)), (BlackboardAttribute(attID_vs_sz, VSSIngesttModuleFactory.moduleName, File_Size)))) # Fire an event to notify the UI and others that there are new artifacts IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent(VSSIngesttModuleFactory.moduleName, artID_vss_evt, None)) message = IngestMessage.createMessage(IngestMessage.MessageType.DATA, "Process/Extract VS", " Volume Shadow has been analyzed " ) IngestServices.getInstance().postMessage(message) return IngestModule.ProcessResult.OK
def __findContactsInDB(self, databasePath, abstractFile): if not databasePath: return bbartifacts = list() try: Class.forName("org.sqlite.JDBC") # load JDBC driver connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath) statement = connection.createStatement() except (ClassNotFoundException, SQLException) as ex: self._logger.log(Level.SEVERE, "Error opening database", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) return try: # get display_name, mimetype(email or phone number) and data1 (phonenumber or email address depending on mimetype) # sorted by name, so phonenumber/email would be consecutive for a person if they exist. # check if contacts.name_raw_contact_id exists. Modify the query accordingly. columnFound = False metadata = connection.getMetaData() columnListResultSet = metadata.getColumns(None, None, "contacts", None) while columnListResultSet.next(): if columnListResultSet.getString( "COLUMN_NAME") == "name_raw_contact_id": columnFound = True break if columnFound: resultSet = statement.executeQuery( "SELECT mimetype, data1, name_raw_contact.display_name AS display_name \n" + "FROM raw_contacts JOIN contacts ON (raw_contacts.contact_id=contacts._id) \n" + "JOIN raw_contacts AS name_raw_contact ON(name_raw_contact_id=name_raw_contact._id) " + "LEFT OUTER JOIN data ON (data.raw_contact_id=raw_contacts._id) \n" + "LEFT OUTER JOIN mimetypes ON (data.mimetype_id=mimetypes._id) \n" + "WHERE mimetype = 'vnd.android.cursor.item/phone_v2' OR mimetype = 'vnd.android.cursor.item/email_v2'\n" + "ORDER BY name_raw_contact.display_name ASC;") else: resultSet = statement.executeQuery( "SELECT mimetype, data1, raw_contacts.display_name AS display_name \n" + "FROM raw_contacts JOIN contacts ON (raw_contacts.contact_id=contacts._id) \n" + "LEFT OUTER JOIN data ON (data.raw_contact_id=raw_contacts._id) \n" + "LEFT OUTER JOIN mimetypes ON (data.mimetype_id=mimetypes._id) \n" + "WHERE mimetype = 'vnd.android.cursor.item/phone_v2' OR mimetype = 'vnd.android.cursor.item/email_v2'\n" + "ORDER BY raw_contacts.display_name ASC;") artifact = abstractFile.newArtifact( BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT) oldName = "" while resultSet.next(): name = resultSet.getString("display_name") data1 = resultSet.getString( "data1") # the phone number or email mimetype = resultSet.getString( "mimetype") # either phone or email if name != oldName: artifact = abstractFile.newArtifact( BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT) artifact.addAttribute( BlackboardAttribute( BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, general.MODULE_NAME, name)) if mimetype == "vnd.android.cursor.item/phone_v2": artifact.addAttribute( BlackboardAttribute( BlackboardAttribute.ATTRIBUTE_TYPE. TSK_PHONE_NUMBER, general.MODULE_NAME, data1)) else: artifact.addAttribute( BlackboardAttribute( BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL, general.MODULE_NAME, data1)) oldName = name bbartifacts.append(artifact) try: # index the artifact for keyword search blackboard = Case.getCurrentCase().getServices( ).getBlackboard() blackboard.indexArtifact(artifact) except Blackboard.BlackboardException as ex: self._logger.log( Level.SEVERE, "Unable to index blackboard artifact " + artifact.getArtifactID(), ex) self._logger.log(Level.SEVERE, traceback.format_exc()) MessageNotifyUtil.Notify.error( "Failed to index contact artifact for keyword search.", artifact.getDisplayName()) except SQLException as ex: self._logger.log( Level.WARNING, "Unable to execute contacts SQL query against {0} : {1}", [databasePath, ex]) except TskCoreException as ex: self._logger.log(Level.SEVERE, "Error posting to blackboard", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) finally: if bbartifacts: IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent( general.MODULE_NAME, BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT, bbartifacts)) try: if resultSet is not None: resultSet.close() statement.close() connection.close() except Exception as ex: self._logger.log(Level.SEVERE, "Error closing database", ex) self._logger.log(Level.SEVERE, traceback.format_exc())
def process(self, dataSource, progressBar): #Check to see if event logs were selected, if not then send message and error out else process events selected self.log( Level.INFO, "List Of Events ==> " + str(self.List_Of_Events) + " <== Number of Events ==> " + str(len(self.List_Of_Events))) if len(self.List_Of_Events) < 1: message = IngestMessage.createMessage( IngestMessage.MessageType.DATA, "ParseEvtx", " No Event Logs Selected to Parse ") IngestServices.getInstance().postMessage(message) return IngestModule.ProcessResult.ERROR else: # Check to see if the artifacts exist and if not then create it, also check to see if the attributes # exist and if not then create them skCase = Case.getCurrentCase().getSleuthkitCase() skCase_Tran = skCase.beginTransaction() try: self.log(Level.INFO, "Begin Create New Artifacts") artID_evtx = skCase.addArtifactType("TSK_EVTX_LOGS", "Windows Event Logs") except: self.log( Level.INFO, "Artifacts Creation Error, some artifacts may not exist now. ==> " ) artID_evtx = skCase.getArtifactTypeID("TSK_EVTX_LOGS") try: self.log(Level.INFO, "Begin Create New Artifacts") artID_evtx_Long = skCase.addArtifactType( "TSK_EVTX_LOGS_BY_ID", "Windows Event Logs By Event Id") except: self.log( Level.INFO, "Artifacts Creation Error, some artifacts may not exist now. ==> " ) artID_evtx_Long = skCase.getArtifactTypeID( "TSK_EVTX_LOGS_BY_ID") try: attID_ev_fn = skCase.addArtifactAttributeType( "TSK_EVTX_FILE_NAME", BlackboardAttribute. TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Event Log File Name") except: self.log( Level.INFO, "Attributes Creation Error, Event Log File Name. ==> ") try: attID_ev_rc = skCase.addArtifactAttributeType( "TSK_EVTX_RECOVERED_RECORD", BlackboardAttribute. TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Recovered Record") except: self.log(Level.INFO, "Attributes Creation Error, Recovered Record. ==> ") try: attID_ev_cn = skCase.addArtifactAttributeType( "TSK_EVTX_COMPUTER_NAME", BlackboardAttribute. TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Computer Name") except: self.log(Level.INFO, "Attributes Creation Error, Computer Name. ==> ") try: attID_ev_ei = skCase.addArtifactAttributeType( "TSK_EVTX_EVENT_IDENTIFIER", BlackboardAttribute. TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.LONG, "Event Identiifier") except: self.log( Level.INFO, "Attributes Creation Error, Event Log File Name. ==> ") try: attID_ev_eiq = skCase.addArtifactAttributeType( "TSK_EVTX_EVENT_IDENTIFIER_QUALIFERS", BlackboardAttribute. TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Event Identifier Qualifiers") except: self.log( Level.INFO, "Attributes Creation Error, Event Identifier Qualifiers. ==> " ) try: attID_ev_el = skCase.addArtifactAttributeType( "TSK_EVTX_EVENT_LEVEL", BlackboardAttribute. TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Event Level") except: self.log(Level.INFO, "Attributes Creation Error, Event Level. ==> ") try: attID_ev_oif = skCase.addArtifactAttributeType( "TSK_EVTX_OFFSET_IN_FILE", BlackboardAttribute. TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Event Offset In File") except: self.log( Level.INFO, "Attributes Creation Error, Event Offset In File. ==> ") try: attID_ev_id = skCase.addArtifactAttributeType( "TSK_EVTX_IDENTIFIER", BlackboardAttribute. TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Identifier") except: self.log(Level.INFO, "Attributes Creation Error, Identifier. ==> ") try: attID_ev_sn = skCase.addArtifactAttributeType( "TSK_EVTX_SOURCE_NAME", BlackboardAttribute. TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Source Name") except: self.log(Level.INFO, "Attributes Creation Error, Source Name. ==> ") try: attID_ev_usi = skCase.addArtifactAttributeType( "TSK_EVTX_USER_SECURITY_ID", BlackboardAttribute. TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "User Security ID") except: self.log(Level.INFO, "Attributes Creation Error, User Security ID. ==> ") try: attID_ev_et = skCase.addArtifactAttributeType( "TSK_EVTX_EVENT_TIME", BlackboardAttribute. TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Event Time") except: self.log(Level.INFO, "Attributes Creation Error, Event Time. ==> ") try: attID_ev_ete = skCase.addArtifactAttributeType( "TSK_EVTX_EVENT_TIME_EPOCH", BlackboardAttribute. TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Event Time Epoch") except: self.log(Level.INFO, "Attributes Creation Error, Identifier. ==> ") try: attID_ev_dt = skCase.addArtifactAttributeType( "TSK_EVTX_EVENT_DETAIL_TEXT", BlackboardAttribute. TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Event Detail") except: self.log(Level.INFO, "Attributes Creation Error, Event Detail. ==> ") try: attID_ev_cnt = skCase.addArtifactAttributeType( "TSK_EVTX_EVENT_ID_COUNT", BlackboardAttribute. TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.LONG, "Event Id Count") except: self.log(Level.INFO, "Attributes Creation Error, Event ID Count. ==> ") #self.log(Level.INFO, "Get Artifacts after they were created.") # Get the new artifacts and attributes that were just created artID_evtx = skCase.getArtifactTypeID("TSK_EVTX_LOGS") artID_evtx_evt = skCase.getArtifactType("TSK_EVTX_LOGS") artID_evtx_Long = skCase.getArtifactTypeID("TSK_EVTX_LOGS_BY_ID") artID_evtx_Long_evt = skCase.getArtifactType("TSK_EVTX_LOGS_BY_ID") attID_ev_fn = skCase.getAttributeType("TSK_EVTX_FILE_NAME") attID_ev_rc = skCase.getAttributeType("TSK_EVTX_RECOVERED_RECORD") attID_ev_cn = skCase.getAttributeType("TSK_EVTX_COMPUTER_NAME") attID_ev_ei = skCase.getAttributeType("TSK_EVTX_EVENT_IDENTIFIER") attID_ev_eiq = skCase.getAttributeType( "TSK_EVTX_EVENT_IDENTIFIER_QUALIFERS") attID_ev_el = skCase.getAttributeType("TSK_EVTX_EVENT_LEVEL") attID_ev_oif = skCase.getAttributeType("TSK_EVTX_OFFSET_IN_FILE") attID_ev_id = skCase.getAttributeType("TSK_EVTX_IDENTIFIER") attID_ev_sn = skCase.getAttributeType("TSK_EVTX_SOURCE_NAME") attID_ev_usi = skCase.getAttributeType("TSK_EVTX_USER_SECURITY_ID") attID_ev_et = skCase.getAttributeType("TSK_EVTX_EVENT_TIME") attID_ev_ete = skCase.getAttributeType("TSK_EVTX_EVENT_TIME_EPOCH") attID_ev_dt = skCase.getAttributeType("TSK_EVTX_EVENT_DETAIL_TEXT") attID_ev_cnt = skCase.getAttributeType("TSK_EVTX_EVENT_ID_COUNT") # we don't know how much work there is yet progressBar.switchToIndeterminate() # Find the Windows Event Log Files files = [] fileManager = Case.getCurrentCase().getServices().getFileManager() files = fileManager.findFiles(dataSource, "%.evtx") # if self.List_Of_Events[0] == 'ALL': # files = fileManager.findFiles(dataSource, "%.evtx") # else: # for eventlog in self.List_Of_Events: # file_name = fileManager.findFiles(dataSource, eventlog) # files.extend(file_name) #self.log(Level.INFO, "found " + str(file_name) + " files") #self.log(Level.INFO, "found " + str(files) + " files") numFiles = len(files) self.log(Level.INFO, "found " + str(numFiles) + " files") progressBar.switchToDeterminate(numFiles) fileCount = 0 # Create Event Log directory in temp directory, if it exists then continue on processing Temp_Dir = Case.getCurrentCase().getTempDirectory() self.log(Level.INFO, "create Directory " + Temp_Dir) temp_dir = os.path.join(Temp_Dir, "EventLogs") try: os.mkdir(temp_dir) except: self.log(Level.INFO, "Event Log Directory already exists " + temp_dir) # Write out each Event Log file to the temp directory for file in files: # Check if the user pressed cancel while we were busy if self.context.isJobCancelled(): return IngestModule.ProcessResult.OK #self.log(Level.INFO, "Processing file: " + file.getName()) fileCount += 1 # Save the DB locally in the temp folder. use file id as name to reduce collisions lclDbPath = os.path.join(temp_dir, file.getName()) ContentUtils.writeToFile(file, File(lclDbPath)) # Run the EXE, saving output to a sqlite database self.log( Level.INFO, "Running program on data source " + self.path_to_exe + " parm 1 ==> " + temp_dir + " Parm 2 ==> " + os.path.join(Temp_Dir, "\EventLogs.db3")) subprocess.Popen([ self.path_to_exe, temp_dir, os.path.join(Temp_Dir, "EventLogs.db3") ]).communicate()[0] # Set the database to be read to the one created by the Event_EVTX program lclDbPath = os.path.join(Case.getCurrentCase().getTempDirectory(), "EventLogs.db3") self.log( Level.INFO, "Path to the Eventlogs database file created ==> " + lclDbPath) # Open the DB using JDBC try: Class.forName("org.sqlite.JDBC").newInstance() dbConn = DriverManager.getConnection("jdbc:sqlite:%s" % lclDbPath) except SQLException as e: self.log( Level.INFO, "Could not open database file (not SQLite) " + file.getName() + " (" + e.getMessage() + ")") return IngestModule.ProcessResult.OK # files = [] # fileManager = Case.getCurrentCase().getServices().getFileManager() # if self.List_Of_Events[0] == 'ALL': # files = fileManager.findFiles(dataSource, "%.evtx") # else: # for eventlog in self.List_Of_Events: # file_name = fileManager.findFiles(dataSource, eventlog) # files.extend(file_name) for file in files: file_name = file.getName() self.log(Level.INFO, "File To process in SQL " + file_name + " <<=====") # Query the contacts table in the database and get all columns. if self.List_Of_Events[0] != 'ALL': try: stmt = dbConn.createStatement() SQL_Statement = "SELECT File_Name, Recovered_Record, Computer_name, Event_Identifier, " + \ " Event_Identifier_Qualifiers, Event_Level, Event_offset, Identifier, " + \ " Event_source_Name, Event_User_Security_Identifier, Event_Time, " + \ " Event_Time_Epoch, Event_Detail_Text FROM Event_Logs where upper(File_Name) = upper('" + file_name + "')" + \ " and Event_Identifier in ('" + self.Event_Id_List + "');" self.log( Level.INFO, "SQL Statement " + SQL_Statement + " <<=====") resultSet = stmt.executeQuery(SQL_Statement) except SQLException as e: self.log( Level.INFO, "Error querying database for EventLogs table (" + e.getMessage() + ")") return IngestModule.ProcessResult.OK # Cycle through each row and create artifacts while resultSet.next(): try: #File_Name = resultSet.getString("File_Name") #Recovered_Record = resultSet.getString("Recovered_Record") Computer_Name = resultSet.getString( "Computer_Name") Event_Identifier = resultSet.getInt( "Event_Identifier") #Event_Identifier_Qualifiers = resultSet.getString("Event_Identifier_Qualifiers") Event_Level = resultSet.getString("Event_Level") #Event_Offset = resultSet.getString("Event_Offset") #Identifier = resultSet.getString("Identifier") Event_Source_Name = resultSet.getString( "Event_Source_Name") Event_User_Security_Identifier = resultSet.getString( "Event_User_Security_Identifier") Event_Time = resultSet.getString("Event_Time") #Event_Time_Epoch = resultSet.getString("Event_Time_Epoch") Event_Detail_Text = resultSet.getString( "Event_Detail_Text") except SQLException as e: self.log( Level.INFO, "Error getting values from contacts table (" + e.getMessage() + ")") # Make an artifact on the blackboard, TSK_PROG_RUN and give it attributes for each of the fields # Make artifact for TSK_EVTX_LOGS art = file.newArtifact(artID_evtx) art.addAttributes(((BlackboardAttribute(attID_ev_cn, ParseEvtxByEventIDIngestModuleFactory.moduleName, Computer_Name)), \ (BlackboardAttribute(attID_ev_ei, ParseEvtxByEventIDIngestModuleFactory.moduleName, Event_Identifier)), \ (BlackboardAttribute(attID_ev_el, ParseEvtxByEventIDIngestModuleFactory.moduleName, Event_Level)), \ (BlackboardAttribute(attID_ev_sn, ParseEvtxByEventIDIngestModuleFactory.moduleName, Event_Source_Name)), \ (BlackboardAttribute(attID_ev_usi, ParseEvtxByEventIDIngestModuleFactory.moduleName, Event_User_Security_Identifier)), \ (BlackboardAttribute(attID_ev_et, ParseEvtxByEventIDIngestModuleFactory.moduleName, Event_Time)), \ (BlackboardAttribute(attID_ev_dt, ParseEvtxByEventIDIngestModuleFactory.moduleName, Event_Detail_Text)))) # These attributes may also be added in the future #art.addAttribute(BlackboardAttribute(attID_ev_fn, ParseEvtxByEventIDIngestModuleFactory.moduleName, File_Name)) #art.addAttribute(BlackboardAttribute(attID_ev_rc, ParseEvtxByEventIDIngestModuleFactory.moduleName, Recovered_Record)) #art.addAttribute(BlackboardAttribute(attID_ev_eiq, ParseEvtxByEventIDIngestModuleFactory.moduleName, Event_Identifier_Qualifiers)) #art.addAttribute(BlackboardAttribute(attID_ev_oif, ParseEvtxByEventIDIngestModuleFactory.moduleName, Event_Offset)) #art.addAttribute(BlackboardAttribute(attID_ev_id, ParseEvtxByEventIDIngestModuleFactory.moduleName, Identifier)) #art.addAttribute(BlackboardAttribute(attID_ev_ete, ParseEvtxByEventIDIngestModuleFactory.moduleName, Event_Time_Epoch)) else: try: stmt_1 = dbConn.createStatement() SQL_Statement_1 = "select event_identifier, file_name, count(*) 'Number_Of_Events' " + \ " FROM Event_Logs where upper(File_Name) = upper('" + file_name + "')" + \ " group by event_identifier, file_name order by 3;" self.log( Level.INFO, "SQL Statement " + SQL_Statement_1 + " <<=====") resultSet_1 = stmt_1.executeQuery(SQL_Statement_1) except SQLException as e: self.log( Level.INFO, "Error querying database for EventLogs table (" + e.getMessage() + ")") return IngestModule.ProcessResult.OK self.log(Level.INFO, "This is the to see what the FU is") # Cycle through each row and create artifacts while resultSet_1.next(): try: self.log(Level.INFO, "This is the to see what the FU is 2") #File_Name = resultSet.getString("File_Name") #Recovered_Record = resultSet.getString("Recovered_Record") Event_Identifier = resultSet_1.getInt( "Event_Identifier") Event_ID_Count = resultSet_1.getInt( "Number_Of_Events") except SQLException as e: self.log( Level.INFO, "Error getting values from contacts table (" + e.getMessage() + ")") self.log(Level.INFO, "This is the to see what the FU is 3") # Make an artifact on the blackboard, TSK_PROG_RUN and give it attributes for each of the fields # Make artifact for TSK_EVTX_LOGS art_1 = file.newArtifact(artID_evtx_Long) self.log( Level.INFO, "Type of Object is ==> " + str(type(Event_ID_Count))) art_1.addAttributes(((BlackboardAttribute(attID_ev_ei, ParseEvtxByEventIDIngestModuleFactory.moduleName, Event_Identifier)), \ (BlackboardAttribute(attID_ev_cnt, ParseEvtxByEventIDIngestModuleFactory.moduleName, Event_ID_Count)))) # Fire an event to notify the UI and others that there are new artifacts IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent( ParseEvtxByEventIDIngestModuleFactory.moduleName, artID_evtx_evt, None)) IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent( ParseEvtxByEventIDIngestModuleFactory.moduleName, artID_evtx_Long_evt, None)) # Clean up try: if self.List_Of_Events[0] != 'ALL': stmt.close() else: stmt_1.close() dbConn.close() os.remove(lclDbPath) except: self.log( Level.INFO, "Error closing the statment, closing the database or removing the file" ) #Clean up EventLog directory and files for file in files: try: os.remove(os.path.join(temp_dir, file.getName())) except: self.log( Level.INFO, "removal of Event Log file failed " + Temp_Dir + "\\" + file.getName()) try: os.rmdir(temp_dir) except: self.log(Level.INFO, "removal of Event Logs directory failed " + Temp_Dir) # Fire an event to notify the UI and others that there are new artifacts IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent( ParseEvtxByEventIDIngestModuleFactory.moduleName, artID_evtx_evt, None)) # After all databases, post a message to the ingest messages in box. message = IngestMessage.createMessage( IngestMessage.MessageType.DATA, "ParseEvtx", " Event Logs have been parsed ") IngestServices.getInstance().postMessage(message) # Fire an event to notify the UI and others that there are new artifacts IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent( ParseEvtxByEventIDIngestModuleFactory.moduleName, artID_evtx_evt, None)) return IngestModule.ProcessResult.OK
def process(self, dataSource, progressBar): if len(self.List_Of_tables) < 1: message = IngestMessage.createMessage(IngestMessage.MessageType.DATA, self.moduleName, " Can't find my tables " ) IngestServices.getInstance().postMessage(message) return IngestModule.ProcessResult.ERROR # Check if this is Windows if not PlatformUtil.isWindowsOS(): self.log(Level.INFO, "Ignoring data source. Not running on Windows") return IngestModule.ProcessResult.OK # we don't know how much work there is yet progressBar.switchToIndeterminate() skCase = Case.getCurrentCase().getSleuthkitCase(); fileManager = Case.getCurrentCase().getServices().getFileManager() files = fileManager.findFiles(dataSource, "Amcache.hve") numFiles = len(files) self.log(Level.INFO, "found " + str(numFiles) + " files") fileCount = 0; Temp_Dir = Case.getCurrentCase().getTempDirectory() self.log(Level.INFO, "Found temporary directory: " + Temp_Dir) message = IngestMessage.createMessage(IngestMessage.MessageType.DATA, "Amcache Scan", " Parsing Amcache.Hve " ) IngestServices.getInstance().postMessage(message) # Dump Amcache.hve files in the temp directory for file in files: # Check if the user pressed cancel while we were busy if self.context.isJobCancelled(): return IngestModule.ProcessResult.OK self.log(Level.INFO, "Processing file: " + file.getName()) fileCount += 1 # Save the DB locally in the temp folder. use file id as name to reduce collisions lclDbPath = os.path.join(Temp_Dir, str(file.getId()) + '-amcache.hve') ContentUtils.writeToFile(file, File(lclDbPath)) mydb = Temp_Dir + "\\" + str(file.getId()) + "-myAmcache.db3" # Parse some keys self.log(Level.INFO, "[Executable #1] Parsing Amcache.Hve: \"" + self.my_exe + "\" -r " + lclDbPath + " -d " + mydb) subprocess.Popen([self.my_exe, '-r', lclDbPath, '-d', mydb]).communicate()[0] try: Class.forName("org.sqlite.JDBC").newInstance() dbConn = DriverManager.getConnection("jdbc:sqlite:%s" % mydb) except SQLException as e: self.log(Level.INFO, "Could not open database file (not SQLite) " + mydb + " (" + e.getMessage() + ")") return IngestModule.ProcessResult.OK for am_table_name in self.List_Of_tables: if am_table_name == 'root_file_virustotal_scan': # <-- because we haven't run the executable these tables yet continue if am_table_name == 'inventory_application_file_virustotal_scan': continue try: stmt = dbConn.createStatement() resultSet = stmt.executeQuery("Select tbl_name from SQLITE_MASTER where lower(tbl_name) in ('" + am_table_name + "'); ") self.log(Level.INFO, "query SQLite Master table for " + am_table_name) except SQLException as e: self.log(Level.INFO, "Error querying database for table " + am_table_name + " (" + e.getMessage() + ")") return IngestModule.ProcessResult.OK # Cycle through each row and create artifacts while resultSet.next(): try: self.log(Level.INFO, "Result (" + resultSet.getString("tbl_name") + ")") table_name = resultSet.getString("tbl_name") SQL_String_1 = "Select * from " + table_name + ";" SQL_String_2 = "PRAGMA table_info('" + table_name + "')" artifact_name = "TSK_" + table_name.upper() artifact_desc = "Amcache " + table_name.upper() try: self.log(Level.INFO, "Begin Create New Artifacts") artID_amc = skCase.addArtifactType( artifact_name, artifact_desc) except: self.log(Level.INFO, "Artifacts Creation Error, some artifacts may not exist now. ==> ") artID_amc = skCase.getArtifactTypeID(artifact_name) artID_amc_evt = skCase.getArtifactType(artifact_name) Column_Names = [] Column_Types = [] resultSet2 = stmt.executeQuery(SQL_String_2) while resultSet2.next(): Column_Names.append(resultSet2.getString("name").upper()) Column_Types.append(resultSet2.getString("type").upper()) if resultSet2.getString("type").upper() == "TEXT": try: attID_ex1 = skCase.addArtifactAttributeType("TSK_" + resultSet2.getString("name").upper(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, resultSet2.getString("name")) except: self.log(Level.INFO, "Attributes Creation Error (string), " + resultSet2.getString("name") + " ==> ") elif resultSet2.getString("type").upper() == "": try: attID_ex1 = skCase.addArtifactAttributeType("TSK_" + resultSet2.getString("name").upper(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, resultSet2.getString("name")) except: self.log(Level.INFO, "Attributes Creation Error (string2), " + resultSet2.getString("name") + " ==> ") else: try: attID_ex1 = skCase.addArtifactAttributeType("TSK_" + resultSet2.getString("name").upper(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.LONG, resultSet2.getString("name")) except: self.log(Level.INFO, "Attributes Creation Error (long), " + resultSet2.getString("name") + " ==> ") resultSet3 = stmt.executeQuery(SQL_String_1) while resultSet3.next(): art = file.newArtifact(artID_amc) Column_Number = 1 for col_name in Column_Names: c_name = "TSK_" + col_name attID_ex1 = skCase.getAttributeType(c_name) if Column_Types[Column_Number - 1] == "TEXT": art.addAttribute(BlackboardAttribute(attID_ex1, AmcacheScanIngestModuleFactory.moduleName, resultSet3.getString(Column_Number))) elif Column_Types[Column_Number - 1] == "": art.addAttribute(BlackboardAttribute(attID_ex1, AmcacheScanIngestModuleFactory.moduleName, resultSet3.getString(Column_Number))) else: art.addAttribute(BlackboardAttribute(attID_ex1, AmcacheScanIngestModuleFactory.moduleName, long(resultSet3.getInt(Column_Number)))) Column_Number = Column_Number + 1 IngestServices.getInstance().fireModuleDataEvent(ModuleDataEvent(AmcacheScanIngestModuleFactory.moduleName, artID_amc_evt, None)) except SQLException as e: self.log(Level.INFO, "Error getting values from contacts table (" + e.getMessage() + ")") stmt.close() dbConn.close() message = IngestMessage.createMessage(IngestMessage.MessageType.DATA, "Amcache Scan", " Amcache Keys Have Been Parsed " ) IngestServices.getInstance().postMessage(message) message = IngestMessage.createMessage(IngestMessage.MessageType.DATA, "Amcache Scan", " Beginning VirusTotal Scan " ) IngestServices.getInstance().postMessage(message) for file in files: # Check if the user pressed cancel while we were busy if self.context.isJobCancelled(): return IngestModule.ProcessResult.OK self.log(Level.INFO, "Processing file: " + file.getName()) fileCount += 1 # Save the DB locally in the temp folder. use file id as name to reduce collisions mydb = Temp_Dir + "\\" + str(file.getId()) + "-myAmcache.db3" try: Class.forName("org.sqlite.JDBC").newInstance() dbConn = DriverManager.getConnection("jdbc:sqlite:%s" % mydb) except SQLException as e: self.Error_Message.setText("Error Opening Settings") # First check that the 'root_file' table exists try: stmt = dbConn.createStatement() SQL_Statement = 'SELECT COUNT(*) as count FROM sqlite_master WHERE type = "table" AND name = "root_file";' resultSet = stmt.executeQuery(SQL_Statement) self.root_file_exists = int(resultSet.getString("count")) except: self.log(Level.INFO, "LOOK HERE: it's not working.") # If it does, count the number of rows in the table if self.root_file_exists: self.log(Level.INFO, "root_file table exists. Counting rows.") try: stmt = dbConn.createStatement() SQL_Statement = 'SELECT count(*) AS count FROM root_file;' resultSet = stmt.executeQuery(SQL_Statement) self.root_file_count = int(resultSet.getString("count")) except: self.log(Level.INFO, "LOOK HERE: it's not working.") # Now check that the 'inventory_application_file' table exists try: stmt = dbConn.createStatement() SQL_Statement = 'SELECT COUNT(*) as count FROM sqlite_master WHERE type = "table" AND name = "inventory_application_file";' resultSet = stmt.executeQuery(SQL_Statement) self.inventory_application_file_exists = int(resultSet.getString("count")) except: self.log(Level.INFO, "LOOK HERE: it's not working.") # If it does, count the number of rows in the table if self.inventory_application_file_exists: self.log(Level.INFO, "inventory_application_file table exists. Counting rows.") try: stmt = dbConn.createStatement() SQL_Statement = 'SELECT count(*) AS count FROM inventory_application_file;' resultSet = stmt.executeQuery(SQL_Statement) self.inventory_application_file_count = int(resultSet.getString("count")) except: self.log(Level.INFO, "LOOK HERE: it's not working.") stmt.close() dbConn.close() # Now we know how many files we need to scan # Use the sum, to give the user a progress bar self.sum = self.root_file_count + self.inventory_application_file_count progressBar.switchToDeterminate(self.sum) artifact_name = "TSK_" + 'root_file_virustotal_scan'.upper() artifact_desc = "Amcache " + 'root_file_virustotal_scan'.upper() try: self.log(Level.INFO, "Begin creating root_file_virustotal_scan Artifacts") artID_amc = skCase.addArtifactType(artifact_name, artifact_desc) except: self.log(Level.INFO, "ARTIFACTS CREATION ERROR: root_file_virustotal_scan") artID_typeID = skCase.getArtifactTypeID(artifact_name) artID_type = skCase.getArtifactType(artifact_name) Column_Names = ["p_key","file","sha1","vt_positives","vt_ratio","vt_report_link"] Column_Types = ["int","text","text","int","text","text"] # A public VirusTotal API key only allows for 4 requests a minute (1/15 seconds) # Use this to track how much time has passed current_time = time.time() # start scanning root_file SHA1 hashes for i in range(0, self.root_file_count): subprocess.Popen([self.my_exe,'-d', mydb, '-a', self.API_Key, '-t', 'root_file', '-k', str(i + 1)]).communicate()[0] try: Class.forName("org.sqlite.JDBC").newInstance() dbConn = DriverManager.getConnection("jdbc:sqlite:%s" % mydb) except SQLException as e: self.log(Level.INFO, "Could not open database file (not SQLite) " + mydb + " (" + e.getMessage() + ")") return IngestModule.ProcessResult.OK if i == 0: try: stmt = dbConn.createStatement() resultSet = stmt.executeQuery('SELECT COUNT(*) as count FROM sqlite_master WHERE type = "table" AND name = "root_file_virustotal_scan";') self.log(Level.INFO, "query SQLite Master table for root_file_virustotal_scan") except SQLException as e: self.log(Level.INFO, "Error querying database for table root_file_virustotal_scan (" + e.getMessage() + ")") if int(resultSet.getString("count")): self.log(Level.INFO, "root_file_virustotal_scan found") for j in range(0,len(Column_Names)): if Column_Types[j].upper() == "TEXT": try: attID_ex1 = skCase.addArtifactAttributeType("TSK_" + Column_Names[j].upper(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, Column_Names[j]) except: self.log(Level.INFO, "Attributes Creation Error, " + Column_Names[j] + " ==> ") else: try: attID_ex1 = skCase.addArtifactAttributeType("TSK_" + Column_Names[j].upper(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.LONG, Column_Names[j]) except: self.log(Level.INFO, "Attributes Creation Error, " + Column_Names[j] + " ==> ") stmt.close() SQL_String_1 = 'SELECT "p_key","file","sha1","vt_positives","vt_ratio","vt_report_link" from "root_file_virustotal_scan" WHERE p_key = ' + str(i + 1) + ';' stmt = dbConn.createStatement() resultSet3 = stmt.executeQuery(SQL_String_1) while resultSet3.next(): art = file.newArtifact(artID_typeID) Column_Number = 1 for col_name in Column_Names: c_name = "TSK_" + col_name.upper() attID_ex1 = skCase.getAttributeType(c_name) if Column_Types[Column_Number - 1].upper() == "TEXT": art.addAttribute(BlackboardAttribute(attID_ex1, AmcacheScanIngestModuleFactory.moduleName, resultSet3.getString(col_name))) elif Column_Types[Column_Number - 1] == "": art.addAttribute(BlackboardAttribute(attID_ex1, AmcacheScanIngestModuleFactory.moduleName, resultSet3.getString(col_name))) else: art.addAttribute(BlackboardAttribute(attID_ex1, AmcacheScanIngestModuleFactory.moduleName, long(resultSet3.getInt(col_name)))) Column_Number = Column_Number + 1 IngestServices.getInstance().fireModuleDataEvent(ModuleDataEvent(AmcacheScanIngestModuleFactory.moduleName, artID_type, None)) stmt.close() dbConn.close() if not self.Private: after_time = time.time() diff = current_time - after_time time.sleep(15 - diff) current_time = time.time() if self.context.isJobCancelled(): return IngestModule.ProcessResult.OK self.count += 1 progressBar.progress(self.count) artifact_name = "TSK_" + 'inventory_application_file_virustotal_scan'.upper() artifact_desc = "Amcache " + 'inventory_application_file_virustotal_scan'.upper() try: self.log(Level.INFO, "Begin creating inventory_application_file_virustotal_scan Artifacts") artID_amc = skCase.addArtifactType(artifact_name, artifact_desc) except: self.log(Level.INFO, "ARTIFACTS CREATION ERROR: inventory_application_file_virustotal_scan") artID_typeID = skCase.getArtifactTypeID(artifact_name) artID_type = skCase.getArtifactType(artifact_name) # start scanning 'inventory_application_file' SHA1 hashes for i in range(0, self.inventory_application_file_count): subprocess.Popen([self.my_exe,'-d', mydb, '-a', self.API_Key, '-t', 'inventory_application_file', '-k', str(i + 1)]).communicate()[0] try: Class.forName("org.sqlite.JDBC").newInstance() dbConn = DriverManager.getConnection("jdbc:sqlite:%s" % mydb) except SQLException as e: self.log(Level.INFO, "Could not open database file (not SQLite) " + mydb + " (" + e.getMessage() + ")") return IngestModule.ProcessResult.OK if i == 0: try: stmt = dbConn.createStatement() resultSet = stmt.executeQuery('SELECT COUNT(*) as count FROM sqlite_master WHERE type = "table" AND name = "inventory_application_file_virustotal_scan";') self.log(Level.INFO, "query SQLite Master table for inventory_application_file_virustotal_scan") except SQLException as e: self.log(Level.INFO, "Error querying database for table inventory_application_file_virustotal_scan (" + e.getMessage() + ")") if int(resultSet.getString("count")): self.log(Level.INFO, "inventory_application_file_virustotal_scan found") for j in range(0,len(Column_Names)): if Column_Types[j].upper() == "TEXT": try: attID_ex1 = skCase.addArtifactAttributeType("TSK_" + Column_Names[j].upper(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, Column_Names[j]) except: self.log(Level.INFO, "Attributes Creation Error, " + Column_Names[j] + " ==> ") else: try: attID_ex1 = skCase.addArtifactAttributeType("TSK_" + Column_Names[j].upper(), BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.LONG, Column_Names[j]) except: self.log(Level.INFO, "Attributes Creation Error, " + Column_Names[j] + " ==> ") stmt.close() SQL_String_1 = 'SELECT "p_key","file","sha1","vt_positives","vt_ratio","vt_report_link" from "inventory_application_file_virustotal_scan" WHERE p_key = ' + str(i + 1) + ';' stmt = dbConn.createStatement() resultSet3 = stmt.executeQuery(SQL_String_1) while resultSet3.next(): art = file.newArtifact(artID_typeID) Column_Number = 1 for col_name in Column_Names: c_name = "TSK_" + col_name.upper() attID_ex1 = skCase.getAttributeType(c_name) if Column_Types[Column_Number - 1].upper() == "TEXT": art.addAttribute(BlackboardAttribute(attID_ex1, AmcacheScanIngestModuleFactory.moduleName, resultSet3.getString(col_name))) elif Column_Types[Column_Number - 1] == "": art.addAttribute(BlackboardAttribute(attID_ex1, AmcacheScanIngestModuleFactory.moduleName, resultSet3.getString(col_name))) else: art.addAttribute(BlackboardAttribute(attID_ex1, AmcacheScanIngestModuleFactory.moduleName, long(resultSet3.getInt(col_name)))) Column_Number = Column_Number + 1 IngestServices.getInstance().fireModuleDataEvent(ModuleDataEvent(AmcacheScanIngestModuleFactory.moduleName, artID_type, None)) stmt.close() dbConn.close() if not self.Private: after_time = time.time() diff = current_time - after_time time.sleep(15 - diff) if self.context.isJobCancelled(): return IngestModule.ProcessResult.OK current_time = time.time() self.count += 1 progressBar.progress(self.count) message = IngestMessage.createMessage(IngestMessage.MessageType.DATA, "Amcache Scan", " VirusTotal Scan Complete " ) IngestServices.getInstance().postMessage(message) return IngestModule.ProcessResult.OK
def process(self, dataSource, progressBar): self.log( Level.INFO, "Starting to process, Just before call to parse_safari_history") # we don't know how much work there is yet progressBar.switchToIndeterminate() # Get the temp directory and create the sub directory Temp_Dir = Case.getCurrentCase().getTempDirectory() try: os.mkdir(Temp_Dir + "\MacFSEvents") except: self.log(Level.INFO, "FSEvents Directory already exists " + Temp_Dir) # Set the database to be read to the once created by the prefetch parser program skCase = Case.getCurrentCase().getSleuthkitCase() fileManager = Case.getCurrentCase().getServices().getFileManager() files = fileManager.findFiles(dataSource, "%", ".fseventsd") numFiles = len(files) for file in files: #self.log(Level.INFO, "Files ==> " + file.getName()) if (file.getName() == "..") or (file.getName() == '.') or (file.getName() == 'fseventsd-uuid'): pass #self.log(Level.INFO, "Files ==> " + str(file)) else: # Check if the user pressed cancel while we were busy if self.context.isJobCancelled(): return IngestModule.ProcessResult.OK # Save the DB locally in the temp folder. use file id as name to reduce collisions filePath = os.path.join(Temp_Dir + "\MacFSEvents", file.getName()) ContentUtils.writeToFile(file, File(filePath)) self.log(Level.INFO, "Number of files to process ==> " + str(numFiles)) self.log(Level.INFO, "Running program ==> " + self.MacFSEvents_Executable + " -c Autopsy " + "-o " + Temp_Dir + \ " -s " + Temp_Dir + "\MacFSEvents") pipe = Popen([ self.MacFSEvents_Executable, "-c", "Autopsy", "-o", Temp_Dir, "-s", Temp_Dir + "\MacFSEvents" ], stdout=PIPE, stderr=PIPE) out_text = pipe.communicate()[0] self.log(Level.INFO, "Output from run is ==> " + out_text) try: self.log(Level.INFO, "Begin Create New Artifacts") artID_fse = skCase.addArtifactType("TSK_MACOS_FSEVENTS", "FSEvents") except: self.log( Level.INFO, "Artifacts Creation Error, some artifacts may not exist now. ==> " ) artID_fse = skCase.getArtifactTypeID("TSK_MACOS_FSEVENTS") # Create the attribute type, if it exists then catch the error try: attID_fse_fn = skCase.addArtifactAttributeType( "TSK_FSEVENTS_FILE_NAME", BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "File Name") except: self.log(Level.INFO, "Attributes Creation Error, File Name. ==> ") try: attID_fse_msk = skCase.addArtifactAttributeType( "TSK_FSEVENTS_FILE_MASK", BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Mask") except: self.log(Level.INFO, "Attributes Creation Error, Mask. ==> ") try: attID_fse_src = skCase.addArtifactAttributeType( "TSK_FSEVENTS_SOURCE", BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Source File") except: self.log(Level.INFO, "Attributes Creation Error, Mask. ==> ") try: attID_fse_dte = skCase.addArtifactAttributeType( "TSK_FSEVENTS_DATES", BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Date(s)") except: self.log(Level.INFO, "Attributes Creation Error, Mask. ==> ") try: Class.forName("org.sqlite.JDBC").newInstance() dbConn = DriverManager.getConnection( "jdbc:sqlite:%s" % Temp_Dir + "\\autopsy_FSEvents-Parsed_Records_DB.sqlite") except SQLException as e: self.log( Level.INFO, "Could not open database file (not SQLite) " + database_file + " (" + e.getMessage() + ")") return IngestModule.ProcessResult.OK artID_fse = skCase.getArtifactTypeID("TSK_MACOS_FSEVENTS") artID_fse_evt = skCase.getArtifactType("TSK_MACOS_FSEVENTS") attID_fse_fn = skCase.getAttributeType("TSK_FSEVENTS_FILE_NAME") attID_fse_msk = skCase.getAttributeType("TSK_FSEVENTS_FILE_MASK") attID_fse_src = skCase.getAttributeType("TSK_FSEVENTS_SOURCE") attID_fse_dte = skCase.getAttributeType("TSK_FSEVENTS_DATES") # Query the database for file in files: if ('slack' in file.getName()): pass elif (file.getName() == '..') or (file.getName() == '.'): pass else: try: stmt = dbConn.createStatement() sql_statement = "select filename, mask, source, " + \ " case other_dates when 'UNKNOWN' then NULL else other_dates end 'OTHER_DATES' " + \ " from fsevents where source = '" + file.getName() + "';" #self.log(Level.INFO, "SQL Statement ==> " + sql_statement) resultSet = stmt.executeQuery(sql_statement) #self.log(Level.INFO, "query SQLite Master table ==> " ) #self.log(Level.INFO, "query " + str(resultSet)) # Cycle through each row and create artifact while resultSet.next(): # Add the attributes to the artifact. art = file.newArtifact(artID_fse) #self.log(Level.INFO, "Result ==> " + resultSet.getString("mask") + ' <==> ' + resultSet.getString("source")) art.addAttributes(((BlackboardAttribute(attID_fse_fn, MacFSEventsIngestModuleFactory.moduleName, resultSet.getString("filename"))), \ (BlackboardAttribute(attID_fse_msk, MacFSEventsIngestModuleFactory.moduleName, resultSet.getString("mask"))), \ (BlackboardAttribute(attID_fse_src, MacFSEventsIngestModuleFactory.moduleName, resultSet.getString("source"))), \ (BlackboardAttribute(attID_fse_dte, MacFSEventsIngestModuleFactory.moduleName, resultSet.getString("OTHER_DATES"))))) #try: # index the artifact for keyword search #blackboard.indexArtifact(art) #except: #self.log(Level.INFO, "Error indexing artifact " + art.getDisplayName()) except SQLException as e: self.log( Level.INFO, "Could not open database file (not SQLite) " + database_file + " (" + e.getMessage() + ")") return IngestModule.ProcessResult.OK try: stmt.close() except: self.log(Level.INFO, "Error closing statement for " + file.getName()) # Fire an event to notify the UI and others that there are new artifacts IngestServices.getInstance().fireModuleDataEvent( ModuleDataEvent(MacFSEventsIngestModuleFactory.moduleName, artID_fse_evt, None)) try: stmt.close() dbConn.close() os.remove(Temp_Dir + "\Autopsy_FSEvents-EXCEPTIONS_LOG.txt") os.remove(Temp_Dir + "\Autopsy_FSEvents-Parsed_Records.txt") os.remove(Temp_Dir + "\Autopsy_FSEvents-Parsed_Records_DB.sqlite") shutil.rmtree(Temp_Dir + "\MacFSEvents") except: self.log( Level.INFO, "removal of MacFSEvents imageinfo database failed " + Temp_Dir) # After all databases, post a message to the ingest messages in box. message = IngestMessage.createMessage( IngestMessage.MessageType.DATA, "MacFSEventsSettings", " MacFSEventsSettings Has Been Analyzed ") IngestServices.getInstance().postMessage(message) return IngestModule.ProcessResult.OK