Autopsy  4.15.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
ExtractPrefetch.java
Go to the documentation of this file.
1 /*
2  *
3  * Autopsy Forensic Browser
4  *
5  * Copyright 2020 Basis Technology Corp.
6  *
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 package org.sleuthkit.autopsy.recentactivity;
21 
22 import java.io.File;
23 import java.io.FileNotFoundException;
24 import java.io.IOException;
25 import java.nio.file.Path;
26 import java.nio.file.Paths;
27 import java.sql.ResultSet;
28 import java.sql.SQLException;
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.Collection;
32 import java.util.List;
33 import java.util.logging.Level;
34 import org.openide.modules.InstalledFileLocator;
35 import org.openide.util.NbBundle.Messages;
46 import org.sleuthkit.datamodel.AbstractFile;
47 import org.sleuthkit.datamodel.Blackboard;
48 import org.sleuthkit.datamodel.BlackboardArtifact;
49 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT;
50 import org.sleuthkit.datamodel.BlackboardAttribute;
51 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT;
52 import org.sleuthkit.datamodel.Content;
53 import org.sleuthkit.datamodel.TskCoreException;
54 
59 final class ExtractPrefetch extends Extract {
60 
61  private static final Logger logger = Logger.getLogger(ExtractPrefetch.class.getName());
62 
63  private IngestJobContext context;
64 
65 
66  private static final String MODULE_NAME = "extractPREFETCH"; //NON-NLS
67 
68  private static final String PREFETCH_TSK_COMMENT = "Prefetch File";
69  private static final String PREFETCH_FILE_LOCATION = "/Windows/Prefetch";
70  private static final String PREFETCH_TOOL_FOLDER = "markmckinnon"; //NON-NLS
71  private static final String PREFETCH_TOOL_NAME_WINDOWS_64 = "parse_prefetch_x64.exe"; //NON-NLS
72  private static final String PREFETCH_TOOL_NAME_WINDOWS_32 = "parse_prefetch_x32.exe"; //NON-NLS
73  private static final String PREFETCH_TOOL_NAME_MACOS = "parse_prefetch_macos"; //NON-NLS
74  private static final String PREFETCH_TOOL_NAME_LINUX = "parse_prefetch_linux"; //NON-NLS
75  private static final String PREFETCH_OUTPUT_FILE_NAME = "Output.txt"; //NON-NLS
76  private static final String PREFETCH_ERROR_FILE_NAME = "Error.txt"; //NON-NLS
77  private static final String PREFETCH_PARSER_DB_FILE = "Autopsy_PF_DB.db3"; //NON-NLS
78  private static final String PREFETCH_DIR_NAME = "prefetch"; //NON-NLS
79 
80  @Messages({
81  "ExtractPrefetch_module_name=Windows Prefetch Extractor"
82  })
83  ExtractPrefetch() {
84  this.moduleName = Bundle.ExtractPrefetch_module_name();
85  }
86 
87  @Override
88  void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) {
89 
90  this.context = context;
91 
92  String modOutPath = Case.getCurrentCase().getModuleDirectory() + File.separator + PREFETCH_DIR_NAME;
93  File dir = new File(modOutPath);
94  if (dir.exists() == false) {
95  boolean dirMade = dir.mkdirs();
96  if (!dirMade) {
97  logger.log(Level.SEVERE, "Error creating directory to store prefetch output database"); //NON-NLS
98  return; //If we cannot create the directory then we need to exit
99 
100  }
101  }
102 
103  extractPrefetchFiles(dataSource);
104 
105  final String prefetchDumper = getPathForPrefetchDumper();
106  if (prefetchDumper == null) {
107  logger.log(Level.SEVERE, "Error finding parse_prefetch program"); //NON-NLS
108  return; //If we cannot find the parse_prefetch program we cannot proceed
109  }
110 
111  if (context.dataSourceIngestIsCancelled()) {
112  return;
113  }
114 
115  String modOutFile = modOutPath + File.separator + PREFETCH_PARSER_DB_FILE;
116  try {
117  String tempDirPath = RAImageIngestModule.getRATempPath(Case.getCurrentCase(), PREFETCH_DIR_NAME );
118  parsePrefetchFiles(prefetchDumper, tempDirPath, modOutFile, modOutPath);
119  createAppExecArtifacts(modOutFile, dataSource);
120  } catch (IOException ex) {
121  logger.log(Level.WARNING, "Error runing parse_prefetch or creating artifacts.", ex); //NON-NLS
122  }
123  }
124 
133  void extractPrefetchFiles(Content dataSource) {
134  List<AbstractFile> pFiles;
135 
136  FileManager fileManager = Case.getCurrentCase().getServices().getFileManager();
137 
138  try {
139  pFiles = fileManager.findFiles(dataSource, "%.pf"); //NON-NLS
140  } catch (TskCoreException ex) {
141  logger.log(Level.WARNING, "Unable to find prefetch files.", ex); //NON-NLS
142  return; // No need to continue
143  }
144 
145  for (AbstractFile pFile : pFiles) {
146 
147  if (context.dataSourceIngestIsCancelled()) {
148  return;
149  }
150 
151  String prefetchFile = RAImageIngestModule.getRATempPath(Case.getCurrentCase(), PREFETCH_DIR_NAME) + File.separator + pFile.getName();
152  if (pFile.getParentPath().contains(PREFETCH_FILE_LOCATION)) {
153  try {
154  ContentUtils.writeToFile(pFile, new File(prefetchFile));
155  } catch (IOException ex) {
156  logger.log(Level.WARNING, String.format("Unable to write %s to temp directory. File name: %s", pFile.getName(), prefetchFile), ex); //NON-NLS
157  }
158  }
159  }
160 
161  }
162 
174  void parsePrefetchFiles(String prefetchExePath, String prefetchDir, String tempOutFile, String tempOutPath) throws FileNotFoundException, IOException {
175  final Path outputFilePath = Paths.get(tempOutPath, PREFETCH_OUTPUT_FILE_NAME);
176  final Path errFilePath = Paths.get(tempOutPath, PREFETCH_ERROR_FILE_NAME);
177 
178  List<String> commandLine = new ArrayList<>();
179  commandLine.add(prefetchExePath);
180  commandLine.add(prefetchDir); //NON-NLS
181  commandLine.add(tempOutFile);
182 
183  ProcessBuilder processBuilder = new ProcessBuilder(commandLine);
184  processBuilder.redirectOutput(outputFilePath.toFile());
185  processBuilder.redirectError(errFilePath.toFile());
186 
187  ExecUtil.execute(processBuilder, new DataSourceIngestModuleProcessTerminator(context));
188  }
189 
198  private String getPathForPrefetchDumper() {
199  Path path = null;
200  if (PlatformUtil.isWindowsOS()) {
201  if (PlatformUtil.is64BitOS()) {
202  path = Paths.get(PREFETCH_TOOL_FOLDER, PREFETCH_TOOL_NAME_WINDOWS_64);
203  } else {
204  path = Paths.get(PREFETCH_TOOL_FOLDER, PREFETCH_TOOL_NAME_WINDOWS_32);
205  }
206  } else {
207  if ("Linux".equals(PlatformUtil.getOSName())) {
208  path = Paths.get(PREFETCH_TOOL_FOLDER, PREFETCH_TOOL_NAME_LINUX);
209  } else {
210  path = Paths.get(PREFETCH_TOOL_FOLDER, PREFETCH_TOOL_NAME_MACOS);
211  }
212  }
213  File prefetchToolFile = InstalledFileLocator.getDefault().locate(path.toString(),
214  ExtractPrefetch.class.getPackage().getName(), false);
215  if (prefetchToolFile != null) {
216  return prefetchToolFile.getAbsolutePath();
217  }
218 
219  return null;
220 
221  }
222 
231  private void createAppExecArtifacts(String prefetchDb, Content dataSource) {
232  List<BlackboardArtifact> blkBrdArtList = new ArrayList<>();
233 
234  String sqlStatement = "SELECT prefetch_File_Name, actual_File_Name, file_path, Number_time_file_run, Embeded_date_Time_Unix_1, " +
235  " Embeded_date_Time_Unix_2, Embeded_date_Time_Unix_3, Embeded_date_Time_Unix_4, Embeded_date_Time_Unix_5," +
236  " Embeded_date_Time_Unix_6, Embeded_date_Time_Unix_7, Embeded_date_Time_Unix_8 " +
237  " FROM prefetch_file_info;"; //NON-NLS
238 
239  try (SQLiteDBConnect tempdbconnect = new SQLiteDBConnect("org.sqlite.JDBC", "jdbc:sqlite:" + prefetchDb); //NON-NLS
240  ResultSet resultSet = tempdbconnect.executeQry(sqlStatement)) {
241 
242  while (resultSet.next()) {
243 
244  if (context.dataSourceIngestIsCancelled()) {
245  logger.log(Level.INFO, "Cancelled Prefetch Artifact Creation."); //NON-NLS
246  return;
247  }
248 
249  String prefetchFileName = resultSet.getString("prefetch_File_Name");
250  String applicationName = resultSet.getString("actual_File_Name"); //NON-NLS
251  List<Long> executionTimes = new ArrayList<>();
252  executionTimes.add(Long.valueOf(resultSet.getInt("Embeded_date_Time_Unix_1")));
253  executionTimes.add(Long.valueOf(resultSet.getInt("Embeded_date_Time_Unix_2")));
254  executionTimes.add(Long.valueOf(resultSet.getInt("Embeded_date_Time_Unix_3")));
255  executionTimes.add(Long.valueOf(resultSet.getInt("Embeded_date_Time_Unix_4")));
256  executionTimes.add(Long.valueOf(resultSet.getInt("Embeded_date_Time_Unix_5")));
257  executionTimes.add(Long.valueOf(resultSet.getInt("Embeded_date_Time_Unix_6")));
258  executionTimes.add(Long.valueOf(resultSet.getInt("Embeded_date_Time_Unix_7")));
259  executionTimes.add(Long.valueOf(resultSet.getInt("Embeded_date_Time_Unix_8")));
260  String timesProgramRun = resultSet.getString("Number_time_file_run");
261  String filePath = resultSet.getString("file_path");
262 
263  AbstractFile pfAbstractFile = getAbstractFile(prefetchFileName, PREFETCH_FILE_LOCATION, dataSource);
264 
265  List<Long> prefetchExecutionTimes = findNonZeroExecutionTimes(executionTimes);
266 
267  if (pfAbstractFile != null) {
268  for (Long executionTime : prefetchExecutionTimes) {
269 
270  // only add prefetch file entries that have an actual date associated with them
271  Collection<BlackboardAttribute> blkBrdAttributes = Arrays.asList(
272  new BlackboardAttribute(
273  BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, getName(),
274  applicationName),//NON-NLS
275  new BlackboardAttribute(
276  BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, getName(),
277  executionTime),
278  new BlackboardAttribute(
279  BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COUNT, getName(), Integer.valueOf(timesProgramRun)),
280  new BlackboardAttribute(
281  BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, getName(), PREFETCH_TSK_COMMENT));
282 
283  try {
284  BlackboardArtifact blkBrdArt = pfAbstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_PROG_RUN);
285  blkBrdArt.addAttributes(blkBrdAttributes);
286  blkBrdArtList.add(blkBrdArt);
287  BlackboardArtifact associatedBbArtifact = createAssociatedArtifact(applicationName.toLowerCase(), filePath, blkBrdArt, dataSource);
288  if (associatedBbArtifact != null) {
289  blkBrdArtList.add(associatedBbArtifact);
290  }
291  } catch (TskCoreException ex) {
292  logger.log(Level.SEVERE, "Exception Adding Artifact.", ex);//NON-NLS
293  }
294  }
295  } else {
296  logger.log(Level.SEVERE, "File has a null value " + prefetchFileName);//NON-NLS
297  }
298 
299  }
300  } catch (SQLException ex) {
301  logger.log(Level.SEVERE, "Error while trying to read into a sqlite db.", ex);//NON-NLS
302  }
303 
304  if (!blkBrdArtList.isEmpty()) {
305  try {
306  blackboard.postArtifacts(blkBrdArtList, MODULE_NAME);
307  } catch (Blackboard.BlackboardException ex) {
308  logger.log(Level.SEVERE, "Error Posting Artifact.", ex);//NON-NLS
309  }
310  }
311  }
312 
321  private List<Long> findNonZeroExecutionTimes(List<Long> executionTimes) {
322  List<Long> prefetchExecutionTimes = new ArrayList<>();
323  for (Long executionTime : executionTimes) { // only add prefetch file entries that have an actual date associated with them
324  if (executionTime > 0) {
325  prefetchExecutionTimes.add(executionTime);
326  }
327  }
328  return prefetchExecutionTimes;
329  }
340  private BlackboardArtifact createAssociatedArtifact(String fileName, String filePathName, BlackboardArtifact bba, Content dataSource) {
341  AbstractFile sourceFile = getAbstractFile(fileName, filePathName, dataSource);
342  if (sourceFile != null) {
343  Collection<BlackboardAttribute> bbattributes2 = new ArrayList<>();
344  bbattributes2.addAll(Arrays.asList(
345  new BlackboardAttribute(TSK_ASSOCIATED_ARTIFACT, this.getName(),
346  bba.getArtifactID())));
347 
348  BlackboardArtifact associatedObjectBba = createArtifactWithAttributes(TSK_ASSOCIATED_OBJECT, sourceFile, bbattributes2);
349  if (associatedObjectBba != null) {
350  return associatedObjectBba;
351  }
352  }
353 
354  return null;
355  }
356 
368  AbstractFile getAbstractFile(String fileName, String filePath, Content dataSource) {
369  List<AbstractFile> files;
370 
371  FileManager fileManager = Case.getCurrentCase().getServices().getFileManager();
372 
373  try {
374  files = fileManager.findFiles(dataSource, fileName, filePath); //NON-NLS
375  } catch (TskCoreException ex) {
376  logger.log(Level.WARNING, "Unable to find prefetch files.", ex); //NON-NLS
377  return null; // No need to continue
378  }
379 
380  if (!files.isEmpty()) {
381  return files.get(0);
382  } else {
383  return null;
384  }
385 
386  }
387 
388 }

Copyright © 2012-2020 Basis Technology. Generated on: Mon Jul 6 2020
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.