20 package org.sleuthkit.autopsy.recentactivity;
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.HashSet;
33 import java.util.List;
35 import java.util.logging.Level;
36 import org.openide.modules.InstalledFileLocator;
37 import org.openide.util.NbBundle.Messages;
52 import static org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT;
54 import static org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT;
63 final class ExtractPrefetch
extends Extract {
65 private static final Logger logger = Logger.getLogger(ExtractPrefetch.class.getName());
67 private IngestJobContext context;
69 private static final String MODULE_NAME =
"extractPREFETCH";
71 private static final String PREFETCH_TSK_COMMENT =
"Prefetch File";
72 private static final String PREFETCH_FILE_LOCATION =
"/windows/prefetch";
73 private static final String PREFETCH_TOOL_FOLDER =
"markmckinnon";
74 private static final String PREFETCH_TOOL_NAME_WINDOWS_64 =
"parse_prefetch_x64.exe";
75 private static final String PREFETCH_TOOL_NAME_WINDOWS_32 =
"parse_prefetch_x32.exe";
76 private static final String PREFETCH_TOOL_NAME_MACOS =
"parse_prefetch_macos";
77 private static final String PREFETCH_TOOL_NAME_LINUX =
"parse_prefetch_linux";
78 private static final String PREFETCH_OUTPUT_FILE_NAME =
"Output.txt";
79 private static final String PREFETCH_ERROR_FILE_NAME =
"Error.txt";
80 private static final String PREFETCH_PARSER_DB_FILE =
"Autopsy_PF_DB.db3";
81 private static final String PREFETCH_DIR_NAME =
"prefetch";
84 "ExtractPrefetch_module_name=Windows Prefetch Extractor",
85 "# {0} - sub module name",
86 "ExtractPrefetch_errMsg_prefetchParsingFailed={0}: Error analyzing prefetch files"
89 this.moduleName = Bundle.ExtractPrefetch_module_name();
93 void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) {
95 this.context = context;
97 String modOutPath = Case.getCurrentCase().getModuleDirectory() + File.separator + PREFETCH_DIR_NAME;
98 File dir =
new File(modOutPath);
99 if (dir.exists() ==
false) {
100 boolean dirMade = dir.mkdirs();
102 logger.log(Level.SEVERE,
"Error creating directory to store prefetch output database");
107 extractPrefetchFiles(dataSource);
109 final String prefetchDumper = getPathForPrefetchDumper();
110 if (prefetchDumper == null) {
111 logger.log(Level.SEVERE,
"Error finding parse_prefetch program");
115 if (context.dataSourceIngestIsCancelled()) {
119 String modOutFile = modOutPath + File.separator + dataSource.getName() +
"-" + PREFETCH_PARSER_DB_FILE;
121 String tempDirPath = RAImageIngestModule.getRATempPath(Case.getCurrentCase(), dataSource.getName() +
"-" + PREFETCH_DIR_NAME);
122 parsePrefetchFiles(prefetchDumper, tempDirPath, modOutFile, modOutPath);
123 createAppExecArtifacts(modOutFile, dataSource);
124 }
catch (IOException ex) {
125 logger.log(Level.SEVERE,
"Error parsing prefetch files", ex);
126 addErrorMessage(Bundle.ExtractPrefetch_errMsg_prefetchParsingFailed(Bundle.ExtractPrefetch_module_name()));
136 void extractPrefetchFiles(Content dataSource) {
137 List<AbstractFile> pFiles;
139 FileManager fileManager = Case.getCurrentCase().getServices().getFileManager();
142 pFiles = fileManager.findFiles(dataSource,
"%.pf");
143 }
catch (TskCoreException ex) {
144 logger.log(Level.WARNING,
"Unable to find prefetch files.", ex);
148 for (AbstractFile pFile : pFiles) {
150 if (context.dataSourceIngestIsCancelled()) {
154 String prefetchFile = RAImageIngestModule.getRATempPath(Case.getCurrentCase(), dataSource.getName() +
"-" + PREFETCH_DIR_NAME) + File.separator + pFile.getName();
155 if (pFile.getParentPath().toLowerCase().contains(PREFETCH_FILE_LOCATION.toLowerCase())) {
157 ContentUtils.writeToFile(pFile,
new File(prefetchFile));
158 }
catch (IOException ex) {
159 logger.log(Level.WARNING, String.format(
"Unable to write %s to temp directory. File name: %s", pFile.getName(), prefetchFile), ex);
178 void parsePrefetchFiles(String prefetchExePath, String prefetchDir, String tempOutFile, String tempOutPath)
throws FileNotFoundException, IOException {
179 final Path outputFilePath = Paths.get(tempOutPath, PREFETCH_OUTPUT_FILE_NAME);
180 final Path errFilePath = Paths.get(tempOutPath, PREFETCH_ERROR_FILE_NAME);
182 List<String> commandLine =
new ArrayList<>();
183 commandLine.add(prefetchExePath);
184 commandLine.add(prefetchDir);
185 commandLine.add(tempOutFile);
187 ProcessBuilder processBuilder =
new ProcessBuilder(commandLine);
188 processBuilder.redirectOutput(outputFilePath.toFile());
189 processBuilder.redirectError(errFilePath.toFile());
191 ExecUtil.execute(processBuilder,
new DataSourceIngestModuleProcessTerminator(context,
true));
201 private String getPathForPrefetchDumper() {
203 if (PlatformUtil.isWindowsOS()) {
204 if (PlatformUtil.is64BitOS()) {
205 path = Paths.get(PREFETCH_TOOL_FOLDER, PREFETCH_TOOL_NAME_WINDOWS_64);
207 path = Paths.get(PREFETCH_TOOL_FOLDER, PREFETCH_TOOL_NAME_WINDOWS_32);
210 if (
"Linux".equals(PlatformUtil.getOSName())) {
211 path = Paths.get(PREFETCH_TOOL_FOLDER, PREFETCH_TOOL_NAME_LINUX);
213 path = Paths.get(PREFETCH_TOOL_FOLDER, PREFETCH_TOOL_NAME_MACOS);
216 File prefetchToolFile = InstalledFileLocator.getDefault().locate(path.toString(),
217 ExtractPrefetch.class.getPackage().getName(),
false);
218 if (prefetchToolFile != null) {
219 return prefetchToolFile.getAbsolutePath();
234 private void createAppExecArtifacts(String prefetchDb, Content dataSource) {
235 List<BlackboardArtifact> blkBrdArtList =
new ArrayList<>();
237 String sqlStatement =
"SELECT prefetch_File_Name, actual_File_Name, file_path, Number_time_file_run, Embeded_date_Time_Unix_1, "
238 +
" Embeded_date_Time_Unix_2, Embeded_date_Time_Unix_3, Embeded_date_Time_Unix_4, Embeded_date_Time_Unix_5,"
239 +
" Embeded_date_Time_Unix_6, Embeded_date_Time_Unix_7, Embeded_date_Time_Unix_8 "
240 +
" FROM prefetch_file_info;";
242 try (SQLiteDBConnect tempdbconnect =
new SQLiteDBConnect(
"org.sqlite.JDBC",
"jdbc:sqlite:" + prefetchDb);
243 ResultSet resultSet = tempdbconnect.executeQry(sqlStatement)) {
245 while (resultSet.next()) {
247 if (context.dataSourceIngestIsCancelled()) {
248 logger.log(Level.INFO,
"Cancelled Prefetch Artifact Creation.");
252 String prefetchFileName = resultSet.getString(
"prefetch_File_Name");
253 String applicationName = resultSet.getString(
"actual_File_Name");
254 List<Long> executionTimes =
new ArrayList<>();
255 executionTimes.add(Long.valueOf(resultSet.getInt(
"Embeded_date_Time_Unix_1")));
256 executionTimes.add(Long.valueOf(resultSet.getInt(
"Embeded_date_Time_Unix_2")));
257 executionTimes.add(Long.valueOf(resultSet.getInt(
"Embeded_date_Time_Unix_3")));
258 executionTimes.add(Long.valueOf(resultSet.getInt(
"Embeded_date_Time_Unix_4")));
259 executionTimes.add(Long.valueOf(resultSet.getInt(
"Embeded_date_Time_Unix_5")));
260 executionTimes.add(Long.valueOf(resultSet.getInt(
"Embeded_date_Time_Unix_6")));
261 executionTimes.add(Long.valueOf(resultSet.getInt(
"Embeded_date_Time_Unix_7")));
262 executionTimes.add(Long.valueOf(resultSet.getInt(
"Embeded_date_Time_Unix_8")));
263 String timesProgramRun = resultSet.getString(
"Number_time_file_run");
264 String filePath = resultSet.getString(
"file_path");
266 AbstractFile pfAbstractFile = getAbstractFile(prefetchFileName, PREFETCH_FILE_LOCATION, dataSource);
268 Set<Long> prefetchExecutionTimes = findNonZeroExecutionTimes(executionTimes);
270 if (pfAbstractFile != null) {
271 for (Long executionTime : prefetchExecutionTimes) {
274 Collection<BlackboardAttribute> blkBrdAttributes = Arrays.asList(
275 new BlackboardAttribute(
276 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, getName(),
278 new BlackboardAttribute(
279 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH, getName(), filePath),
280 new BlackboardAttribute(
281 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, getName(),
283 new BlackboardAttribute(
284 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COUNT, getName(), Integer.valueOf(timesProgramRun)),
285 new BlackboardAttribute(
286 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, getName(), PREFETCH_TSK_COMMENT));
289 BlackboardArtifact blkBrdArt = pfAbstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_PROG_RUN);
290 blkBrdArt.addAttributes(blkBrdAttributes);
291 blkBrdArtList.add(blkBrdArt);
292 BlackboardArtifact associatedBbArtifact = createAssociatedArtifact(applicationName.toLowerCase(), filePath, blkBrdArt, dataSource);
293 if (associatedBbArtifact != null) {
294 blkBrdArtList.add(associatedBbArtifact);
296 }
catch (TskCoreException ex) {
297 logger.log(Level.SEVERE,
"Exception Adding Artifact.", ex);
301 logger.log(Level.WARNING,
"File has a null value " + prefetchFileName);
305 }
catch (SQLException ex) {
306 logger.log(Level.SEVERE,
"Error while trying to read into a sqlite db.", ex);
309 if (!blkBrdArtList.isEmpty()) {
311 blackboard.postArtifacts(blkBrdArtList, MODULE_NAME);
312 }
catch (Blackboard.BlackboardException ex) {
313 logger.log(Level.SEVERE,
"Error Posting Artifact.", ex);
327 private Set<Long> findNonZeroExecutionTimes(List<Long> executionTimes) {
328 Set<Long> prefetchExecutionTimes =
new HashSet<>();
329 for (Long executionTime : executionTimes) {
330 if (executionTime > 0) {
331 prefetchExecutionTimes.add(executionTime);
334 return prefetchExecutionTimes;
348 private BlackboardArtifact createAssociatedArtifact(String fileName, String filePathName, BlackboardArtifact bba, Content dataSource) {
349 AbstractFile sourceFile = getAbstractFile(fileName, filePathName, dataSource);
350 if (sourceFile != null) {
351 Collection<BlackboardAttribute> bbattributes2 =
new ArrayList<>();
352 bbattributes2.addAll(Arrays.asList(
353 new BlackboardAttribute(TSK_ASSOCIATED_ARTIFACT, this.getName(),
354 bba.getArtifactID())));
356 BlackboardArtifact associatedObjectBba = createArtifactWithAttributes(TSK_ASSOCIATED_OBJECT, sourceFile, bbattributes2);
357 if (associatedObjectBba != null) {
358 return associatedObjectBba;
375 AbstractFile getAbstractFile(String fileName, String filePath, Content dataSource) {
376 List<AbstractFile> files;
378 FileManager fileManager = Case.getCurrentCase().getServices().getFileManager();
381 files = fileManager.findFiles(dataSource, fileName);
383 }
catch (TskCoreException ex) {
384 logger.log(Level.WARNING,
"Unable to find prefetch files.", ex);
388 for (AbstractFile pFile : files) {
390 if (pFile.getParentPath().toLowerCase().endsWith(filePath.toLowerCase() +
'/')) {