/** Search for the registry hives on the system. Mostly copied from RecentActivity */ private static List<AbstractFile> findRegistryFiles() throws TskCoreException { List<AbstractFile> registryFiles = new ArrayList<AbstractFile>(); org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = Case.getCurrentCase().getServices().getFileManager(); for (Content ds : Case.getCurrentCase().getDataSources()) { // find the user-specific ntuser-dat files registryFiles.addAll(fileManager.findFiles(ds, "ntuser.dat")); // NON-NLS // find the system hives String[] regFileNames = new String[] {"system", "software", "security", "sam"}; // NON-NLS for (String regFileName : regFileNames) { List<AbstractFile> allRegistryFiles = fileManager.findFiles(ds, regFileName, "/system32/config"); // NON-NLS for (AbstractFile regFile : allRegistryFiles) { // Don't want anything from regback if (!regFile.getParentPath().contains("RegBack")) { // NON-NLS registryFiles.add(regFile); } } } } return registryFiles; }
/** * Deletes the current opened case. * * @param e */ @Override public void actionPerformed(ActionEvent e) { Logger.noteAction(this.getClass()); Case currentCase = Case.getCurrentCase(); File configFile = new File(currentCase.getConfigFilePath()); File caseFolder = new File(configFile.getParent()); String caseName = currentCase.getName(); if (!caseFolder.exists()) { // throw an error logger.log( Level.WARNING, "Couldn't delete case.", new Exception("The case directory doesn't exist.")); } else { // show the confirmation first to close the current case and open the "New Case" wizard panel String closeCurrentCase = "Are you sure want to close and delete this case? \n Case Name: " + caseName + "\n Case Directory: " + caseFolder.getPath(); NotifyDescriptor d = new NotifyDescriptor.Confirmation( closeCurrentCase, "Warning: Closing the Current Case", NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE); d.setValue(NotifyDescriptor.NO_OPTION); Object res = DialogDisplayer.getDefault().notify(d); if (res != null && res == DialogDescriptor.YES_OPTION) { boolean success = false; try { Case.getCurrentCase().deleteCase(caseFolder); // delete the current case success = true; } catch (CaseActionException ex) { logger.log(Level.WARNING, "Could not delete the case folder: " + caseFolder); } // show notification whether the case has been deleted or it failed to delete... if (!success) { JOptionPane.showMessageDialog( caller, "The delete action can't be fully completed because the folder or file in it is open by another program.\n \nClose the folder and file and try again or you can delete the case manually.", "Error: Folder In Use", JOptionPane.ERROR_MESSAGE); // throw an error } else { CasePropertiesAction .closeCasePropertiesWindow(); // because the "Delete Case" button is in the // "CaseProperties" window, we have to close that window // when we delete the case. JOptionPane.showMessageDialog(caller, "Case " + caseName + " has been deleted."); } } } }
@SuppressWarnings("deprecation") protected void initialize() { followUpToggle.setOnAction( (ActionEvent t) -> { if (followUpToggle.isSelected() == true) { globalSelectionModel.clearAndSelect(fileID); try { AddDrawableTagAction.getInstance().addTag(TagUtils.getFollowUpTagName(), ""); } catch (TskCoreException ex) { LOGGER.log(Level.SEVERE, "Failed to add follow up tag. Could not load TagName.", ex); } } else { // TODO: convert this to an action! final ImageGalleryController controller = ImageGalleryController.getDefault(); try { // remove file from old category group controller .getGroupManager() .removeFromGroup( new GroupKey<TagName>(DrawableAttribute.TAGS, TagUtils.getFollowUpTagName()), fileID); List<ContentTag> contentTagsByContent = Case.getCurrentCase() .getServices() .getTagsManager() .getContentTagsByContent(file); for (ContentTag ct : contentTagsByContent) { if (ct.getName() .getDisplayName() .equals(TagUtils.getFollowUpTagName().getDisplayName())) { Case.getCurrentCase().getServices().getTagsManager().deleteContentTag(ct); } } IngestServices.getInstance() .fireModuleDataEvent( new ModuleDataEvent( "TagAction", BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE)); // NON-NLS controller .getGroupManager() .handleFileUpdate( FileUpdateEvent.newUpdateEvent( Collections.singleton(fileID), DrawableAttribute.TAGS)); } catch (TskCoreException ex) { LOGGER.log(Level.SEVERE, "Failed to delete follow up tag.", ex); } } }); }
/** * get the BlackboardArtifactTag that was added by its id * * @return BlackboardArtifactTag that was added * @throws IllegalStateException * @throws TskCoreException */ @Override BlackboardArtifactTag getTagByID() throws IllegalStateException, TskCoreException { return Case.getCurrentCase() .getServices() .getTagsManager() .getBlackboardArtifactTagByTagID(getTagID()); }
@Override public void startUp(IngestJobContext context) throws IngestModuleException { this.context = context; refCounter.incrementAndGet(context.getJobId()); synchronized (SampleFileIngestModule.class) { if (attrId == -1) { // For this sample, make a new attribute type to use to post // results to the blackboard. There are many standard blackboard // artifact and attribute types and you should use them instead // creating new ones to facilitate use of your results by other // modules. Case autopsyCase = Case.getCurrentCase(); SleuthkitCase sleuthkitCase = autopsyCase.getSleuthkitCase(); try { // See if the attribute type has already been defined. attrId = sleuthkitCase.getAttrTypeID("ATTR_SAMPLE"); if (attrId == -1) { attrId = sleuthkitCase.addAttrType("ATTR_SAMPLE", "Sample Attribute"); } } catch (TskCoreException ex) { IngestServices ingestServices = IngestServices.getInstance(); Logger logger = ingestServices.getLogger(SampleIngestModuleFactory.getModuleName()); logger.log(Level.SEVERE, "Failed to create blackboard attribute", ex); attrId = -1; throw new IngestModuleException(ex.getLocalizedMessage()); } } } }
/** * Copy all registry hives to the temp directory and return the list of created files. * * @return Paths to copied registry files. */ public static List<RegistryFileInfo> copyRegistryFiles() throws TskCoreException { // First get all the abstract files List<AbstractFile> regFilesAbstract = findRegistryFiles(); // List to hold all the extracted file names plus their abstract file List<RegistryFileInfo> regFilesLocal = new ArrayList<RegistryFileInfo>(); // Make the temp directory String tmpDir = Case.getCurrentCase().getTempDirectory() + File.separator + "STIX"; // NON-NLS File dir = new File(tmpDir); if (dir.exists() == false) { dir.mkdirs(); } long index = 1; for (AbstractFile regFile : regFilesAbstract) { String regFileName = regFile.getName(); String regFileNameLocal = tmpDir + File.separator + regFileName + "_" + index; File regFileNameLocalFile = new File(regFileNameLocal); try { // Don't save any unallocated versions if (regFile.getMetaFlagsAsString().contains("Allocated")) { // NON-NLS ContentUtils.writeToFile(regFile, regFileNameLocalFile); regFilesLocal.add(new EvalRegistryObj().new RegistryFileInfo(regFile, regFileNameLocal)); } } catch (IOException ex) { throw new TskCoreException(ex.getLocalizedMessage()); } index++; } return regFilesLocal; }
/** * Create a tag for an artifact with TSK_TAG_NAME as tagName. * * @param artifact to create tag for * @param tagName TSK_TAG_NAME * @param comment the tag comment or null if not present */ public static void createTag(BlackboardArtifact artifact, String tagName, String comment) { try { Case currentCase = Case.getCurrentCase(); SleuthkitCase skCase = currentCase.getSleuthkitCase(); AbstractFile file = skCase.getAbstractFileById(artifact.getObjectID()); final BlackboardArtifact bookArt = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT); List<BlackboardAttribute> attrs = new ArrayList<BlackboardAttribute>(); BlackboardAttribute attr1 = new BlackboardAttribute( BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TAG_NAME.getTypeID(), "", tagName); if (comment != null && !comment.isEmpty()) { BlackboardAttribute attr2 = new BlackboardAttribute( BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT.getTypeID(), "", comment); attrs.add(attr2); } BlackboardAttribute attr3 = new BlackboardAttribute( BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TAGGED_ARTIFACT.getTypeID(), "", artifact.getArtifactID()); attrs.add(attr1); attrs.add(attr3); bookArt.addAttributes(attrs); } catch (TskCoreException ex) { logger.log(Level.SEVERE, "Failed to create tag for artifact " + artifact.getArtifactID()); } }
@Override public boolean canClose() { return !Case.existsCurrentCase() || Case.getCurrentCase().hasData() == false; // only allow this window to be closed when there's no case opened or no image // in this case }
private void setMonitorDir() { String caseDir = Case.getCurrentCase().getCaseDirectory(); File curDir = new File(caseDir); File tempF = null; while ((tempF = curDir.getParentFile()) != null) { curDir = tempF; } root = curDir; logger.log(Level.INFO, "Monitoring disk space of case root: " + curDir.getAbsolutePath()); }
/** * Get a list of all the bookmarks. * * @return a list of all bookmark artifacts */ static List<BlackboardArtifact> getBookmarks() { try { Case currentCase = Case.getCurrentCase(); SleuthkitCase skCase = currentCase.getSleuthkitCase(); return skCase.getBlackboardArtifacts( BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TAG_NAME, Tags.BOOKMARK_TAG_NAME); } catch (TskCoreException ex) { logger.log(Level.SEVERE, "Failed to get list of artifacts from the case."); } return new ArrayList<BlackboardArtifact>(); }
@Override public void propertyChange(PropertyChangeEvent evt) { String eventType = evt.getPropertyName(); if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) { /** * Checking for a current case is a stop gap measure until a different way of * handling the closing of cases is worked out. Currently, remote events may be * received for a case that is already closed. */ try { // new file was added // @@@ could check the size here and only fire off updates if we know the file // meets the min size criteria Case.getCurrentCase(); update(); } catch (IllegalStateException notUsed) { /** Case is closed, do nothing. */ } } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString()) || eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) { /** * Checking for a current case is a stop gap measure until a different way of * handling the closing of cases is worked out. Currently, remote events may be * received for a case that is already closed. */ try { Case.getCurrentCase(); update(); } catch (IllegalStateException notUsed) { /** Case is closed, do nothing. */ } } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) { // case was closed. Remove listeners so that we don't get called with a stale case // handle if (evt.getNewValue() == null) { removeListeners(); } } }
/** * Initializes the service for new ingest run Sets up threads, timers, retrieves settings, keyword * lists to run on * * @param managerProxy */ @Override public void init(IngestManagerProxy managerProxy) { logger.log(Level.INFO, "init()"); initialized = false; caseHandle = Case.getCurrentCase().getSleuthkitCase(); this.managerProxy = managerProxy; Server solrServer = KeywordSearch.getServer(); ingester = solrServer.getIngester(); ingestStatus = new HashMap<Long, IngestStatus>(); keywords = new ArrayList<Keyword>(); keywordLists = new ArrayList<String>(); keywordToList = new HashMap<String, KeywordSearchList>(); initKeywords(); if (keywords.isEmpty() || keywordLists.isEmpty()) { managerProxy.postMessage( IngestMessage.createWarningMessage( ++messageID, instance, "No keywords in keyword list.", "Only indexing will be done and and keyword search will be skipped (it can be executed later again as ingest or using toolbar search feature).")); } processedFiles = false; finalSearcherDone = false; searcherDone = true; // make sure to start the initial currentSearcher // keeps track of all results per run not to repeat reporting the same hits currentResults = new HashMap<Keyword, List<ContentHit>>(); indexer = new Indexer(); final int updateIntervalMs = managerProxy.getUpdateFrequency() * 60 * 1000; logger.log(Level.INFO, "Using commit interval (ms): " + updateIntervalMs); logger.log(Level.INFO, "Using searcher interval (ms): " + updateIntervalMs); commitTimer = new Timer(updateIntervalMs, new CommitTimerAction()); searchTimer = new Timer(updateIntervalMs, new SearchTimerAction()); initialized = true; commitTimer.start(); searchTimer.start(); managerProxy.postMessage( IngestMessage.createMessage(++messageID, MessageType.INFO, this, "Started")); }
/** * Looks up the tag names associated with either a tagged artifact or a tag artifact. * * @param artifactID The ID of the artifact * @param artifactTypeID The ID of the artifact type * @return A set of unique tag names */ public static HashSet<String> getUniqueTagNames(long artifactID, int artifactTypeID) { HashSet<String> tagNames = new HashSet<>(); try { ArrayList<Long> tagArtifactIDs = new ArrayList<>(); if (artifactTypeID == ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID() || artifactTypeID == ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) { tagArtifactIDs.add(artifactID); } else { List<BlackboardArtifact> tags = Case.getCurrentCase() .getSleuthkitCase() .getBlackboardArtifacts(ATTRIBUTE_TYPE.TSK_TAGGED_ARTIFACT, artifactID); for (BlackboardArtifact tag : tags) { tagArtifactIDs.add(tag.getArtifactID()); } } for (Long tagArtifactID : tagArtifactIDs) { String whereClause = "WHERE artifact_id = " + tagArtifactID + " AND attribute_type_id = " + ATTRIBUTE_TYPE.TSK_TAG_NAME.getTypeID(); List<BlackboardAttribute> attributes = Case.getCurrentCase().getSleuthkitCase().getMatchingAttributes(whereClause); for (BlackboardAttribute attr : attributes) { tagNames.add(attr.getValueString()); } } } catch (TskCoreException ex) { logger.log(Level.SEVERE, "Failed to get tags for artifact " + artifactID, ex); } return tagNames; }
@Override public JComponent[] getMenuPresenters() { List<DataContentTopComponent> newWindowLists = DataContentTopComponent.getNewWindowList(); // Get DataContent provider to include in the menu int totalItems = newWindowLists.size() > 0 ? 2 : 1; JComponent[] comps = new JComponent[totalItems]; int counter = 0; TopComponent contentWin = DataContentTopComponent.findInstance(); JMenuItem defaultItem = new JMenuItem(contentWin.getName()); // set the main name defaultItem.addActionListener(new OpenTopComponentAction(contentWin)); if (!Case.isCaseOpen() || Case.getCurrentCase().hasData() == false) { defaultItem.setEnabled(false); // disable the menu items when no case is opened } else { defaultItem.setEnabled(true); // enable the menu items when there's a case opened / created } comps[counter++] = defaultItem; // add the submenu if (newWindowLists != null) { if (newWindowLists.size() > 0) { JMenu submenu = new JMenu( NbBundle.getMessage( this.getClass(), "DataContentDynamicMenu.menu.dataContentWin.text")); for (int i = 0; i < newWindowLists.size(); i++) { DataContentTopComponent dctc = newWindowLists.get(i); JMenuItem item = new JMenuItem(dctc.getName()); item.addActionListener(new OpenTopComponentAction(dctc)); submenu.add(item); } comps[counter++] = submenu; } } return comps; }
/** * Get a list of all the tag names. Uses a custom query for speed when dealing with thousands of * Tags. * * @return a list of all tag names. */ @SuppressWarnings("deprecation") public static List<String> getTagNames() { Case currentCase = Case.getCurrentCase(); SleuthkitCase skCase = currentCase.getSleuthkitCase(); List<String> names = new ArrayList<>(); ResultSet rs = null; try { rs = skCase.runQuery( "SELECT value_text" + " FROM blackboard_attributes" + " WHERE attribute_type_id = " + ATTRIBUTE_TYPE.TSK_TAG_NAME.getTypeID() + " GROUP BY value_text" + " ORDER BY value_text"); while (rs.next()) { names.add(rs.getString("value_text")); } } catch (SQLException ex) { logger.log(Level.SEVERE, "Failed to query the blackboard for tag names."); } finally { if (rs != null) { try { skCase.closeRunQuery(rs); } catch (SQLException ex) { logger.log(Level.SEVERE, "Failed to close the query for blackboard for tag names."); } } } // add the 'Bookmark' tag, if it's not already in the list if (!names.contains(BOOKMARK_TAG_NAME)) { names.add(BOOKMARK_TAG_NAME); } return names; }
/** * Get the artifact for a result tag. * * @param tagArtifactId artifact id of the tag * @return the tag's artifact */ static BlackboardArtifact getArtifactFromTag(long tagArtifactId) { try { Case currentCase = Case.getCurrentCase(); SleuthkitCase skCase = currentCase.getSleuthkitCase(); BlackboardArtifact artifact = skCase.getBlackboardArtifact(tagArtifactId); if (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID() || artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) { List<BlackboardAttribute> attributes = artifact.getAttributes(); for (BlackboardAttribute att : attributes) { if (att.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TAGGED_ARTIFACT.getTypeID()) { return skCase.getBlackboardArtifact(att.getValueLong()); } } } } catch (TskCoreException ex) { logger.log(Level.SEVERE, "Failed to get artifact " + tagArtifactId + " from case."); } return null; }
/** * Traverse the tree top-down after unzipping is done and create derived files for the entire * hierarchy */ void addDerivedFilesToCase() throws TskCoreException { final FileManager fileManager = Case.getCurrentCase().getServices().getFileManager(); for (UnpackedNode child : rootNode.children) { addDerivedFilesToCaseRec(child, fileManager); } }
/** @inheritDoc */ @Override @Messages({ "FilesIdentifierIngestModule.indexError.message=Failed to index interesting file hit artifact for keyword search." }) public ProcessResult process(AbstractFile file) { blackboard = Case.getCurrentCase().getServices().getBlackboard(); // See if the file belongs to any defined interesting files set. List<FilesSet> filesSets = FilesIdentifierIngestModule.interestingFileSetsByJob.get(this.context.getJobId()); for (FilesSet filesSet : filesSets) { String ruleSatisfied = filesSet.fileIsMemberOf(file); if (ruleSatisfied != null) { try { // Post an interesting files set hit artifact to the // blackboard. String moduleName = InterestingItemsIngestModuleFactory.getModuleName(); BlackboardArtifact artifact = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT); // Add a set name attribute to the artifact. This adds a // fair amount of redundant data to the attributes table // (i.e., rows that differ only in artifact id), but doing // otherwise would requires reworking the interesting files // set hit artifact. BlackboardAttribute setNameAttribute = new BlackboardAttribute( BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, moduleName, filesSet.getName()); artifact.addAttribute(setNameAttribute); // Add a category attribute to the artifact to record the // interesting files set membership rule that was satisfied. BlackboardAttribute ruleNameAttribute = new BlackboardAttribute( BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY, moduleName, ruleSatisfied); artifact.addAttribute(ruleNameAttribute); try { // index the artifact for keyword search blackboard.indexArtifact(artifact); } catch (Blackboard.BlackboardException ex) { logger.log( Level.SEVERE, "Unable to index blackboard artifact " + artifact.getArtifactID(), ex); // NON-NLS MessageNotifyUtil.Notify.error( Bundle.FilesIdentifierIngestModule_indexError_message(), artifact.getDisplayName()); } IngestServices.getInstance() .fireModuleDataEvent( new ModuleDataEvent( moduleName, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, Collections.singletonList(artifact))); } catch (TskCoreException ex) { FilesIdentifierIngestModule.logger.log( Level.SEVERE, "Error posting to the blackboard", ex); // NOI18N NON-NLS } } } return ProcessResult.OK; }
/** * Get the cached file of the content object with the given id. * * <p>The returned file may not exist. * * @param id * @return */ public static File getFile(long id) { return new File(Case.getCurrentCase().getCacheDirectory() + File.separator + id + ".png"); }
/** * Called only when top component was closed on all workspaces before and now is opened for the * first time on some workspace. The intent is to provide subclasses information about * TopComponent's life cycle across all existing workspaces. Subclasses will usually perform * initializing tasks here. */ @Override public void componentOpened() { // change the cursor to "waiting cursor" for this operation this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); try { if (Case.existsCurrentCase()) { Case currentCase = Case.getCurrentCase(); // close the top component if there's no image in this case if (currentCase.hasData() == false) { // this.close(); ((BeanTreeView) this.jScrollPane1).setRootVisible(false); // hide the root } else { // if there's at least one image, load the image and open the top component List<Object> items = new ArrayList<>(); final SleuthkitCase tskCase = currentCase.getSleuthkitCase(); items.add(new DataSources()); items.add(new Views(tskCase)); items.add(new Results(tskCase)); items.add(new Reports()); contentChildren = new RootContentChildren(items); Node root = new AbstractNode(contentChildren) { /** * to override the right click action in the white blank space area on the directory * tree window */ @Override public Action[] getActions(boolean popup) { return new Action[] {}; } // Overide the AbstractNode use of DefaultHandle to return // a handle which can be serialized without a parent @Override public Node.Handle getHandle() { return new Node.Handle() { @Override public Node getNode() throws IOException { return em.getRootContext(); } }; } }; root = new DirectoryTreeFilterNode(root, true); em.setRootContext(root); em.getRootContext().setName(currentCase.getName()); em.getRootContext().setDisplayName(currentCase.getName()); ((BeanTreeView) this.jScrollPane1).setRootVisible(false); // hide the root // Reset the forward and back lists because we're resetting the root context resetHistory(); Children childNodes = em.getRootContext().getChildren(); TreeView tree = getTree(); Node results = childNodes.findChild(ResultsNode.NAME); tree.expandNode(results); Children resultsChilds = results.getChildren(); tree.expandNode(resultsChilds.findChild(KeywordHits.NAME)); tree.expandNode(resultsChilds.findChild(ExtractedContent.NAME)); Node views = childNodes.findChild(ViewsNode.NAME); Children viewsChilds = views.getChildren(); for (Node n : viewsChilds.getNodes()) { tree.expandNode(n); } tree.collapseNode(views); // if the dataResult is not opened if (!dataResult.isOpened()) { dataResult .open(); // open the data result top component as well when the directory tree is // opened } // select the first image node, if there is one // (this has to happen after dataResult is opened, because the event // of changing the selected node fires a handler that tries to make // dataResult active) if (childNodes.getNodesCount() > 0) { try { em.setSelectedNodes(new Node[] {childNodes.getNodeAt(0)}); } catch (Exception ex) { logger.log(Level.SEVERE, "Error setting default selected node.", ex); // NON-NLS } } } } } finally { this.setCursor(null); } }
public abstract class Extract implements IngestModuleImage { protected Case currentCase = Case.getCurrentCase(); // get the most updated case protected SleuthkitCase tskCase = currentCase.getSleuthkitCase(); public final Logger logger = Logger.getLogger(this.getClass().getName()); protected final ArrayList<String> errorMessages = new ArrayList<String>(); protected String moduleName = ""; // hide public constructor to prevent from instantiation by ingest module loader Extract() {} List<String> getErrorMessages() { return errorMessages; } /** * Returns a List of FsContent objects from TSK based on sql query. * * @param image is a Image object that denotes which image to get the files from * @param query is a sql string query that is to be run * @return FFSqlitedb is a List of FsContent objects */ @SuppressWarnings("deprecation") public List<FsContent> extractFiles(Image image, String query) { Collection<FileSystem> imageFS = tskCase.getFileSystems(image); List<String> fsIds = new LinkedList<String>(); for (FileSystem img : imageFS) { Long tempID = img.getId(); fsIds.add(tempID.toString()); } String allFS = new String(); for (int i = 0; i < fsIds.size(); i++) { if (i == 0) { allFS += " AND (0"; } allFS += " OR fs_obj_id = '" + fsIds.get(i) + "'"; if (i == fsIds.size() - 1) { allFS += ")"; } } List<FsContent> FFSqlitedb = null; ResultSet rs = null; try { rs = tskCase.runQuery(query + allFS); FFSqlitedb = tskCase.resultSetToFsContents(rs); } catch (SQLException ex) { logger.log( Level.SEVERE, "Error while trying to extract files for:" + this.getClass().getName(), ex); this.addErrorMessage(this.getName() + ": Error while trying to extract files to analyze."); } finally { if (rs != null) { try { tskCase.closeRunQuery(rs); } catch (SQLException ex) { logger.log( Level.SEVERE, "Error while trying to close result set after extract files for:" + this.getClass().getName(), ex); } } } return FFSqlitedb; } /** * Generic method for adding a blackboard artifact to the blackboard * * @param type is a blackboard.artifact_type enum to determine which type the artifact should be * @param content is the FsContent object that needs to have the artifact added for it * @param bbattributes is the collection of blackboard attributes that need to be added to the * artifact after the artifact has been created */ public void addArtifact( BlackboardArtifact.ARTIFACT_TYPE type, FsContent content, Collection<BlackboardAttribute> bbattributes) { try { BlackboardArtifact bbart = content.newArtifact(type); bbart.addAttributes(bbattributes); } catch (TskException ex) { logger.log(Level.SEVERE, "Error while trying to add an artifact: " + ex); } } /** * Returns a List from a result set based on sql query. * * @param path is the string path to the sqlite db file * @param query is a sql string query that is to be run * @return list is the ArrayList that contains the resultset information in it that the query * obtained */ public List<HashMap<String, Object>> dbConnect(String path, String query) { ResultSet temprs = null; List<HashMap<String, Object>> list = new ArrayList<HashMap<String, Object>>(); String connectionString = "jdbc:sqlite:" + path; try { SQLiteDBConnect tempdbconnect = new SQLiteDBConnect("org.sqlite.JDBC", connectionString); temprs = tempdbconnect.executeQry(query); list = this.resultSetToArrayList(temprs); tempdbconnect.closeConnection(); } catch (SQLException ex) { logger.log( Level.SEVERE, "Error while trying to read into a sqlite db." + connectionString, ex); return Collections.<HashMap<String, Object>>emptyList(); } return list; } /** * Returns a List of FsContent objects from TSK based on sql query. * * @param rs is the resultset that needs to be converted to an arraylist * @return list returns the arraylist built from the converted resultset */ public List<HashMap<String, Object>> resultSetToArrayList(ResultSet rs) throws SQLException { ResultSetMetaData md = rs.getMetaData(); int columns = md.getColumnCount(); List<HashMap<String, Object>> list = new ArrayList<HashMap<String, Object>>(50); while (rs.next()) { HashMap<String, Object> row = new HashMap<String, Object>(columns); for (int i = 1; i <= columns; ++i) { if (rs.getObject(i) == null) { row.put(md.getColumnName(i), ""); } else { row.put(md.getColumnName(i), rs.getObject(i)); } } list.add(row); } return list; } /** * Returns a List of string error messages from the inheriting class * * @return errorMessages returns all error messages logged */ public ArrayList<String> getErrorMessage() { return errorMessages; } /** * Adds a string to the error message list * * @param message is an error message represented as a string */ public void addErrorMessage(String message) { errorMessages.add(message); } /** * Returns the name of the inheriting class * * @return Gets the moduleName set in the moduleName data member */ public String getName() { return moduleName; } }
@Override public synchronized ObservableResult evaluate() { setWarnings(""); if (obj.getAddressValue() == null) { return new ObservableResult( id, "AddressObject: No address value field found", // NON-NLS spacing, ObservableResult.ObservableState.INDETERMINATE, null); } String origAddressStr = obj.getAddressValue().getValue().toString(); // For now, we don't support "NONE" because it honestly doesn't seem like it // would ever appear in practice. if (((obj.getAddressValue().getApplyCondition() != null) && (obj.getAddressValue().getApplyCondition() == ConditionApplicationEnum.NONE))) { return new ObservableResult( id, "AddressObject: Can not process apply condition " + obj.getAddressValue().getApplyCondition().toString() // NON-NLS + " on Address object", spacing, ObservableResult.ObservableState.INDETERMINATE, null); // NON-NLS } // Set warnings for any unsupported fields setUnsupportedFieldWarnings(); Case case1 = Case.getCurrentCase(); SleuthkitCase sleuthkitCase = case1.getSleuthkitCase(); try { // Need to check that every part of the string had at least one match // in the AND case boolean everyPartMatched = true; List<BlackboardArtifact> combinedArts = new ArrayList<BlackboardArtifact>(); String searchString = ""; String[] parts = origAddressStr.split("##comma##"); // NON-NLS for (String addressStr : parts) { // Update the string to show in the results if (!searchString.isEmpty()) { if ((obj.getAddressValue().getApplyCondition() != null) && (obj.getAddressValue().getApplyCondition() == ConditionApplicationEnum.ALL)) { searchString += " AND "; // NON-NLS } else { searchString += " OR "; // NON-NLS } } searchString += addressStr; if ((obj.getAddressValue().getCondition() == null) || (obj.getAddressValue().getCondition() == ConditionTypeEnum.EQUALS)) { List<BlackboardArtifact> arts = sleuthkitCase.getBlackboardArtifacts( BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD, addressStr); if (arts.isEmpty()) { everyPartMatched = false; } else { combinedArts.addAll(arts); } } else { // This is inefficient, but the easiest way to do it. List<BlackboardArtifact> finalHits = new ArrayList<BlackboardArtifact>(); // Get all the URL artifacts List<BlackboardArtifact> artList = sleuthkitCase.getBlackboardArtifacts( BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT); for (BlackboardArtifact art : artList) { for (BlackboardAttribute attr : art.getAttributes()) { if (attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) { if (compareStringObject( addressStr, obj.getAddressValue().getCondition(), obj.getAddressValue().getApplyCondition(), attr.getValueString())) { finalHits.add(art); } } } } if (finalHits.isEmpty()) { everyPartMatched = false; } else { combinedArts.addAll(finalHits); } } } // If we're in the ALL case, make sure every piece matched if ((obj.getAddressValue().getApplyCondition() != null) && (obj.getAddressValue().getApplyCondition() == ConditionApplicationEnum.ALL) && (!everyPartMatched)) { return new ObservableResult( id, "AddressObject: No matches for " + searchString, // NON-NLS spacing, ObservableResult.ObservableState.FALSE, null); } if (!combinedArts.isEmpty()) { List<StixArtifactData> artData = new ArrayList<StixArtifactData>(); for (BlackboardArtifact a : combinedArts) { artData.add(new StixArtifactData(a.getObjectID(), id, "AddressObject")); // NON-NLS } return new ObservableResult( id, "AddressObject: Found a match for " + searchString, // NON-NLS spacing, ObservableResult.ObservableState.TRUE, artData); } return new ObservableResult( id, "AddressObject: Found no matches for " + searchString, // NON-NLS spacing, ObservableResult.ObservableState.FALSE, null); } catch (TskCoreException ex) { return new ObservableResult( id, "AddressObject: Exception during evaluation: " + ex.getLocalizedMessage(), // NON-NLS spacing, ObservableResult.ObservableState.INDETERMINATE, null); } }