From 3e526c59dcbd278153b583d9e4481828c416e91b Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Thu, 3 Sep 2020 12:00:13 -0400 Subject: [PATCH 1/8] Fix bugs in ExecUtil --- .../sleuthkit/autopsy/coreutils/ExecUtil.java | 236 +++++++++++++----- 1 file changed, 174 insertions(+), 62 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java b/Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java index fc02b0e9f4..77a463ca17 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-2019 Basis Technology Corp. + * Copyright 2013-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,28 +31,31 @@ import java.util.logging.Level; import org.sleuthkit.autopsy.core.UserPreferences; /** - * Executes a command line using an operating system process with a configurable - * timeout and pluggable logic to kill or continue the process on timeout. + * Executes a command line using an operating system process with pluggable + * logic to terminate the process under certain conditions. */ public final class ExecUtil { private static final Logger logger = Logger.getLogger(ExecUtil.class.getName()); - private static final long DEFAULT_CHECK_INTERVAL = 5; - private static final TimeUnit DEFAULT_CHECK_INTERVAL_UNITS = TimeUnit.SECONDS; + private static final long DEFAULT_TERMINATION_CHECK_INTERVAL = 5; + private static final TimeUnit DEFAULT_TERMINATION_CHECK_INTERVAL_UNITS = TimeUnit.SECONDS; + private static final long MAX_WAIT_FOR_TERMINATION = 1; + private static final TimeUnit MAX_WAIT_FOR_TERMINATION_UNITS = TimeUnit.MINUTES; /** - * The execute() methods do a wait() with a timeout on the executing process - * and query a process terminator each time the timeout expires to determine - * whether or not to kill the process. See + * An interface for defining the conditions under which an operating system + * process spawned by an ExecUtil method should be terminated. + * + * Some existing implementations: TimedProcessTerminator, + * InterruptedThreadProcessTerminator, * DataSourceIngestModuleProcessTerminator and - * FileIngestModuleProcessTerminator as examples of ProcessTerminator - * implementations. + * FileIngestModuleProcessTerminator. */ public interface ProcessTerminator { /** - * Decides whether or not to terminate a process being run by a - * ExcUtil.execute() methods. + * Decides whether or not to terminate a process being run by an + * ExecUtil method. * * @return True or false. */ @@ -82,7 +85,7 @@ public final class ExecUtil { /** * Creates a process terminator that can be used to kill a process after - * it has run for a given period of time. + * it exceeds a maximum allowable run time. * * @param maxRunTimeInSeconds The maximum allowable run time in seconds. */ @@ -93,17 +96,14 @@ public final class ExecUtil { /** * Creates a process terminator that can be used to kill a process after - * it has run for a given period of time. Maximum allowable run time is - * set via Autopsy Options panel. If the process termination - * functionality is disabled then the maximum allowable time is set to - * MAX_INT seconds. + * it exceeds a global maximum allowable run time specified as a user + * preference. If the user preference is disabled then the maximum + * allowable run time for this terminator is set to MAX_INT seconds. */ public TimedProcessTerminator() { if (UserPreferences.getIsTimeOutEnabled() && UserPreferences.getProcessTimeOutHrs() > 0) { - // user specified time out this.maxRunTimeInSeconds = UserPreferences.getProcessTimeOutHrs() * 3600; } else { - // never time out this.maxRunTimeInSeconds = Long.MAX_VALUE; } this.startTimeInSeconds = (new Date().getTime()) / 1000; @@ -117,8 +117,16 @@ public final class ExecUtil { } /** - * Runs a process without a termination check interval or process - * terminator. + * Runs a process without a process terminator. This method should be used + * with caution because there is nothing to stop the process from running + * forever. + * + * IMPORTANT: This method blocks while the process is running. For legacy + * API reasons, if there is an interrupt the InterruptedException is wrapped + * in an IOException instead of being thrown. Callers that need to know + * about interrupts to detect backgound task cancellation can call + * Thread.isInterrupted() or, if the thread's interrupt flag should be + * cleared, Thread.interrupted(). * * @param processBuilder A process builder used to configure and construct * the process to be run. @@ -127,7 +135,8 @@ public final class ExecUtil { * * @throws SecurityException If a security manager exists and vetoes any * aspect of running the process. - * @throws IOException If an I/O error occurs. + * @throws IOException If an error occurs while executing or + * terminating the process. */ public static int execute(ProcessBuilder processBuilder) throws SecurityException, IOException { return ExecUtil.execute(processBuilder, 30, TimeUnit.DAYS, new ProcessTerminator() { @@ -142,6 +151,13 @@ public final class ExecUtil { * Runs a process using the default termination check interval and a process * terminator. * + * IMPORTANT: This method blocks while the process is running. For legacy + * API reasons, if there is an interrupt the InterruptedException is wrapped + * in an IOException instead of being thrown. Callers that need to know + * about interrupts to detect backgound task cancellation can call + * Thread.isInterrupted() or, if the thread's interrupt flag should be + * cleared, Thread.interrupted(). + * * @param processBuilder A process builder used to configure and construct * the process to be run. * @param terminator The terminator. @@ -150,16 +166,24 @@ public final class ExecUtil { * * @throws SecurityException If a security manager exists and vetoes any * aspect of running the process. - * @throws IOException If an I/O error occurs. + * @throws IOException If an error occurs while executing or + * terminating the process. */ public static int execute(ProcessBuilder processBuilder, ProcessTerminator terminator) throws SecurityException, IOException { - return ExecUtil.execute(processBuilder, ExecUtil.DEFAULT_CHECK_INTERVAL, ExecUtil.DEFAULT_CHECK_INTERVAL_UNITS, terminator); + return ExecUtil.execute(processBuilder, ExecUtil.DEFAULT_TERMINATION_CHECK_INTERVAL, ExecUtil.DEFAULT_TERMINATION_CHECK_INTERVAL_UNITS, terminator); } /** * Runs a process using a custom termination check interval and a process * terminator. * + * IMPORTANT: This method blocks while the process is running. For legacy + * API reasons, if there is an interrupt the InterruptedException is wrapped + * in an IOException instead of being thrown. Callers that need to know + * about interrupts to detect backgound task cancellation can call + * Thread.isInterrupted() or, if the thread's interrupt flag should be + * cleared, Thread.interrupted(). + * * @param processBuilder A process builder used to configure and * construct the process to be run. * @param terminationCheckInterval The interval at which to query the @@ -173,12 +197,52 @@ public final class ExecUtil { * * @throws SecurityException If a security manager exists and vetoes any * aspect of running the process. - * @throws IOException If an I/O error occurs. + * @throws IOException If an error occurs while executing or + * terminating the process. */ public static int execute(ProcessBuilder processBuilder, long terminationCheckInterval, TimeUnit units, ProcessTerminator terminator) throws SecurityException, IOException { return waitForTermination(processBuilder.command().get(0), processBuilder.start(), terminationCheckInterval, units, terminator); } + /** + * Waits for an existing process to finish, using a custom termination check + * interval and a process terminator. + * + * IMPORTANT: This method blocks while the process is running. For legacy + * API reasons, if there is an interrupt the InterruptedException is wrapped + * in an IOException instead of being thrown. Callers that need to know + * about interrupts to detect backgound task cancellation can call + * Thread.isInterrupted() or, if the thread's interrupt flag should be + * cleared, Thread.interrupted(). + * + * @param processName The name of the process, for logging + * purposes. + * @param process The process. + * @param terminationCheckInterval The interval at which to query the + * process terminator to see if the process + * should be killed. + * @param units The units for the termination check + * interval. + * @param terminator The process terminator. + * + * @return The exit value of the process. + * + * @throws IOException If an error occurs while executing or terminating the + * process. + */ + public static int waitForTermination(String processName, Process process, long terminationCheckInterval, TimeUnit units, ProcessTerminator terminator) throws IOException { + try { + return waitForProcess(processName, process, terminationCheckInterval, units, terminator); + } catch (InterruptedException ex) { + /* + * Reset the interrupted flag and wrap the exception in an + * IOException for backwards compatibility. + */ + Thread.currentThread().interrupt(); + throw new IOException(String.format("Interrupted executing %s", processName), ex); //NON-NLS + } + } + /** * Waits for an existing process to finish, using a custom termination check * interval and a process terminator. @@ -195,67 +259,114 @@ public final class ExecUtil { * * @return The exit value of the process. * - * @throws SecurityException If a security manager exists and vetoes any - * aspect of running the process. - * @throws IOException If an I/O error occurs. + * @throws IOException If an error occurs while executing or + * terminating the process. + * @throws InterruptedException If the thread running this code is + * interrupted while the process is running. */ - public static int waitForTermination(String processName, Process process, long terminationCheckInterval, TimeUnit units, ProcessTerminator terminator) throws SecurityException, IOException { - try { - do { - process.waitFor(terminationCheckInterval, units); - if (process.isAlive() && terminator.shouldTerminateProcess()) { - killProcess(process); - try { - process.waitFor(); - } catch (InterruptedException ex) { - logger.log(Level.WARNING, String.format("Thread running %s was interrupted before the process completed", processName), ex); - } - } - } while (process.isAlive()); - } catch (InterruptedException ex) { - if (process.isAlive()) { - killProcess(process); - } + private static int waitForProcess(String processName, Process process, long terminationCheckInterval, TimeUnit units, ProcessTerminator terminator) throws IOException, InterruptedException { + do { try { - process.waitFor(); //waiting to help ensure process is shutdown before calling interrupt() or returning - } catch (InterruptedException exx) { - logger.log(Level.WARNING, String.format("Thread running %s was interrupted before the process completed", processName), exx); + process.waitFor(terminationCheckInterval, units); + } catch (InterruptedException ex) { + logger.log(Level.WARNING, String.format("Interrupted executing %s", processName), ex); //NON-NLS + Thread.currentThread().interrupt(); + terminateProcess(processName, process); + /* + * Note that if the preceding call to terminateProcess() throws + * an IOException, the caller will get that exception instead of + * this InterruptedException, which is arguably preferable. If + * terminateProcess() does not throw an IOException, then its + * call to waitFor() will throw a fresh InterruptedException, + * which is fine. + */ + throw ex; } - logger.log(Level.WARNING, String.format("Thread running %s was interrupted before the process completed", processName), ex); - Thread.currentThread().interrupt(); - } + if (process.isAlive() && terminator.shouldTerminateProcess()) { + terminateProcess(processName, process); + } + } while (process.isAlive()); + + /* + * Careful: Process.exitValue() throws an IllegalStateException if the + * process is still alive when the method is called. This code is set up + * so that the only way Process.exitValue() can be called is when it has + * not been bypassed by an exception and the preceding loop has + * terminated with Process.isA;ive == false. + */ return process.exitValue(); } /** - * Kills a process and its children + * Terminates a process and its children, waiting with a time out to try to + * ensure the process is no longer alive before returning. * - * @param process The parent process to kill + * IMPORTANT: This method blocks while the process is running. For legacy + * API reasons, if there is an interrupt the InterruptedException is wrapped + * in an IOException instead of being thrown. Callers that need to know + * about interrupts to detect backgound task cancellation can call + * Thread.isInterrupted() or, if the thread's interrupt flag should be + * cleared, Thread.interrupted(). + * + * @param process The process. */ public static void killProcess(Process process) { - if (process == null) { + String processName = process.toString(); + try { + terminateProcess(processName, process); + } catch (IOException ex) { + logger.log(Level.WARNING, String.format("Error occured executing %s", processName), ex); //NON-NLS + } catch (InterruptedException ex) { + logger.log(Level.WARNING, String.format("Interrupted executing %s", processName), ex); //NON-NLS + Thread.currentThread().interrupt(); + } + } + + /** + * Terminates a process and its children, waiting with a time out to try to + * ensure the process is no longer alive before returning. + * + * @param processName The name of the process, for logging purposes. + * @param process The process. + * + * @throws IOException If an error occurs while trying to terminate + * the process. + * @throws InterruptedException If the thread running this code is + * interrupted while waiting for the process to + * terminate. + */ + private static void terminateProcess(String processName, Process process) throws IOException, InterruptedException { + if (process == null || !process.isAlive()) { return; } - try { - if (PlatformUtil.isWindows()) { + if (PlatformUtil.isWindows()) { + try { Win32Process parentProcess = new Win32Process(process); List children = parentProcess.getChildren(); - children.stream().forEach((child) -> { child.terminate(); }); parentProcess.terminate(); - } else { - process.destroyForcibly(); + } catch (Exception ex) { + /* + * Wrap whatever exception was thrown from Windows in an + * exception that is appropriate for this API. + */ + throw new IOException(String.format("Error occured terminating %s", processName), ex); //NON-NLS } - } catch (Exception ex) { - logger.log(Level.WARNING, "Error occurred when attempting to kill process: {0}", ex.getMessage()); // NON-NLS + } else { + process.destroyForcibly(); + } + + if (!process.waitFor(MAX_WAIT_FOR_TERMINATION, MAX_WAIT_FOR_TERMINATION_UNITS)) { + throw new IOException(String.format("Failed to terminate %s after %d %s", processName, MAX_WAIT_FOR_TERMINATION, MAX_WAIT_FOR_TERMINATION_UNITS)); //NON-NLS } } /* - * Used by deprecated methods. + * Fields used by deprecated methods that require instantiation of an + * ExecUtil object. */ private Process proc = null; private ExecUtil.StreamToStringRedirect errorStringRedirect = null; @@ -534,4 +645,5 @@ public final class ExecUtil { doRun = false; } } + } From 080cbc153d1f6c8a7275bb942e6811469fc92da0 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Thu, 3 Sep 2020 12:11:45 -0400 Subject: [PATCH 2/8] Fix bugs in ExecUtil --- Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java b/Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java index 77a463ca17..22d4899c7b 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java @@ -292,7 +292,7 @@ public final class ExecUtil { * process is still alive when the method is called. This code is set up * so that the only way Process.exitValue() can be called is when it has * not been bypassed by an exception and the preceding loop has - * terminated with Process.isA;ive == false. + * terminated with Process.isAlive == false. */ return process.exitValue(); } From 0b4bb5ebdb261937c742d840b5867f76c9a0dd70 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Thu, 3 Sep 2020 12:19:01 -0400 Subject: [PATCH 3/8] Fix bugs in ExecUtil --- Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java | 4 ++-- .../org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java b/Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java index 22d4899c7b..08e63bf6e1 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java @@ -302,8 +302,8 @@ public final class ExecUtil { * ensure the process is no longer alive before returning. * * IMPORTANT: This method blocks while the process is running. For legacy - * API reasons, if there is an interrupt the InterruptedException is wrapped - * in an IOException instead of being thrown. Callers that need to know + * API reasons, if there is an interrupt (or any other exception) the + * exception is logged instead of being thrown. Callers that need to know * about interrupts to detect backgound task cancellation can call * Thread.isInterrupted() or, if the thread's interrupt flag should be * cleared, Thread.interrupted(). diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java index 20acab7a87..ffaed2996a 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java @@ -483,7 +483,7 @@ class ExtractRegistry extends Extract { processBuilder.redirectError(new File(errFile)); ExecUtil.execute(processBuilder, new DataSourceIngestModuleProcessTerminator(context)); } catch (IOException ex) { - logger.log(Level.SEVERE, "Unable to run RegRipper", ex); //NON-NLS + logger.log(Level.SEVERE, String.format("Running RegRipper on %s encountered an error or was incomplete", hiveFilePath), ex); //NON-NLS this.addErrorMessage(NbBundle.getMessage(this.getClass(), "ExtractRegistry.execRegRip.errMsg.failedAnalyzeRegFile", this.getName())); } } From afcb1b5bb06201c963bb6a59347e39d7b9080860 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Thu, 3 Sep 2020 12:21:01 -0400 Subject: [PATCH 4/8] Fix bugs in ExecUtil --- Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java | 1 - 1 file changed, 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java b/Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java index 08e63bf6e1..68a1ceda1e 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java @@ -645,5 +645,4 @@ public final class ExecUtil { doRun = false; } } - } From 626fa16c66793b53cce3ee8abe7777812489a4b2 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Thu, 3 Sep 2020 17:28:59 -0400 Subject: [PATCH 5/8] Fix bugs in ExecUtil --- .../sleuthkit/autopsy/coreutils/ExecUtil.java | 18 +++++++++++------- .../recentactivity/ExtractRegistry.java | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java b/Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java index 68a1ceda1e..a7fc958f16 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/ExecUtil.java @@ -81,7 +81,7 @@ public final class ExecUtil { public static class TimedProcessTerminator implements ProcessTerminator { private final long startTimeInSeconds; - private final long maxRunTimeInSeconds; + private final Long maxRunTimeInSeconds; /** * Creates a process terminator that can be used to kill a process after @@ -97,22 +97,26 @@ public final class ExecUtil { /** * Creates a process terminator that can be used to kill a process after * it exceeds a global maximum allowable run time specified as a user - * preference. If the user preference is disabled then the maximum - * allowable run time for this terminator is set to MAX_INT seconds. + * preference. If the user preference is not set, this terminator has no + * effect. */ public TimedProcessTerminator() { if (UserPreferences.getIsTimeOutEnabled() && UserPreferences.getProcessTimeOutHrs() > 0) { - this.maxRunTimeInSeconds = UserPreferences.getProcessTimeOutHrs() * 3600; + this.maxRunTimeInSeconds = (long) UserPreferences.getProcessTimeOutHrs() * 3600; } else { - this.maxRunTimeInSeconds = Long.MAX_VALUE; + this.maxRunTimeInSeconds = null; } this.startTimeInSeconds = (new Date().getTime()) / 1000; } @Override public boolean shouldTerminateProcess() { - long currentTimeInSeconds = (new Date().getTime()) / 1000; - return (currentTimeInSeconds - this.startTimeInSeconds) > this.maxRunTimeInSeconds; + if (maxRunTimeInSeconds != null) { + long currentTimeInSeconds = (new Date().getTime()) / 1000; + return (currentTimeInSeconds - this.startTimeInSeconds) > this.maxRunTimeInSeconds; + } else { + return false; + } } } diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java index ffaed2996a..ab6f38bc23 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java @@ -481,7 +481,7 @@ class ExtractRegistry extends Extract { processBuilder.directory(regRipperHomeDir.toFile()); // RegRipper 2.8 has to be run from its own directory processBuilder.redirectOutput(new File(outputFile)); processBuilder.redirectError(new File(errFile)); - ExecUtil.execute(processBuilder, new DataSourceIngestModuleProcessTerminator(context)); + ExecUtil.execute(processBuilder, new DataSourceIngestModuleProcessTerminator(context, true)); } catch (IOException ex) { logger.log(Level.SEVERE, String.format("Running RegRipper on %s encountered an error or was incomplete", hiveFilePath), ex); //NON-NLS this.addErrorMessage(NbBundle.getMessage(this.getClass(), "ExtractRegistry.execRegRip.errMsg.failedAnalyzeRegFile", this.getName())); From 93ba7af709d734fe0a9ff81fde921eed6a6d37a6 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Thu, 3 Sep 2020 17:56:37 -0400 Subject: [PATCH 6/8] Fix bugs in ExecUtil --- .../org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java index ab6f38bc23..ffaed2996a 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java @@ -481,7 +481,7 @@ class ExtractRegistry extends Extract { processBuilder.directory(regRipperHomeDir.toFile()); // RegRipper 2.8 has to be run from its own directory processBuilder.redirectOutput(new File(outputFile)); processBuilder.redirectError(new File(errFile)); - ExecUtil.execute(processBuilder, new DataSourceIngestModuleProcessTerminator(context, true)); + ExecUtil.execute(processBuilder, new DataSourceIngestModuleProcessTerminator(context)); } catch (IOException ex) { logger.log(Level.SEVERE, String.format("Running RegRipper on %s encountered an error or was incomplete", hiveFilePath), ex); //NON-NLS this.addErrorMessage(NbBundle.getMessage(this.getClass(), "ExtractRegistry.execRegRip.errMsg.failedAnalyzeRegFile", this.getName())); From 84713a5d883f1b75983b57d653cc035030ff6139 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Thu, 3 Sep 2020 17:58:37 -0400 Subject: [PATCH 7/8] Fix bugs in ExecUtil --- .../recentactivity/ExtractRegistry.java | 592 +++++++++--------- 1 file changed, 297 insertions(+), 295 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java index ffaed2996a..96175408b5 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java @@ -168,11 +168,11 @@ class ExtractRegistry extends Extract { private Content dataSource; private IngestJobContext context; private Map userNameMap; - + private static final String SHELLBAG_ARTIFACT_NAME = "RA_SHELL_BAG"; //NON-NLS private static final String SHELLBAG_ATTRIBUTE_LAST_WRITE = "RA_SHELL_BAG_LAST_WRITE"; //NON-NLS - private static final String SHELLBAG_ATTRIBUTE_KEY= "RA_SHELL_BAG_KEY"; //NON-NLS - + private static final String SHELLBAG_ATTRIBUTE_KEY = "RA_SHELL_BAG_KEY"; //NON-NLS + BlackboardArtifact.Type shellBagArtifactType = null; BlackboardAttribute.Type shellBagKeyAttributeType = null; BlackboardAttribute.Type shellBagLastWriteAttributeType = null; @@ -246,15 +246,14 @@ class ExtractRegistry extends Extract { logger.log(Level.WARNING, msg, ex); this.addErrorMessage(this.getName() + ": " + msg); } - - + // find the user-specific ntuser-dat files try { allRegistryFiles.addAll(fileManager.findFiles(dataSource, "ntuser.dat")); //NON-NLS } catch (TskCoreException ex) { logger.log(Level.WARNING, "Error fetching 'ntuser.dat' file."); //NON-NLS } - + // find the user-specific ntuser-dat files try { allRegistryFiles.addAll(fileManager.findFiles(dataSource, "usrclass.dat")); //NON-NLS @@ -418,7 +417,7 @@ class ExtractRegistry extends Extract { fullType = "sam"; //NON-NLS } else if (regFilePath.toLowerCase().contains("security")) { //NON-NLS fullType = "security"; //NON-NLS - }else if (regFilePath.toLowerCase().contains("usrclass")) { //NON-NLS + } else if (regFilePath.toLowerCase().contains("usrclass")) { //NON-NLS fullType = "usrclass"; //NON-NLS } else { return regOutputFiles; @@ -444,9 +443,9 @@ class ExtractRegistry extends Extract { try { scanErrorLogs(errFilePath); } catch (IOException ex) { - logger.log(Level.SEVERE, "Unable to run RegRipper", ex); //NON-NLS - this.addErrorMessage(NbBundle.getMessage(this.getClass(), "ExtractRegistry.execRegRip.errMsg.failedAnalyzeRegFile", this.getName())); - } + logger.log(Level.SEVERE, "Unable to run RegRipper", ex); //NON-NLS + this.addErrorMessage(NbBundle.getMessage(this.getClass(), "ExtractRegistry.execRegRip.errMsg.failedAnalyzeRegFile", this.getName())); + } } return regOutputFiles; } @@ -458,14 +457,14 @@ class ExtractRegistry extends Extract { while (line != null) { line = line.trim(); if (line.toLowerCase().contains("error") || line.toLowerCase().contains("@inc")) { - logger.log(Level.WARNING, "Regripper file {0} contains errors from run", errFilePath); //NON-NLS - + logger.log(Level.WARNING, "Regripper file {0} contains errors from run", errFilePath); //NON-NLS + } line = reader.readLine(); } } } - + private void executeRegRipper(List regRipperPath, Path regRipperHomeDir, String hiveFilePath, String hiveFileType, String outputFile, String errFile) { try { List commandLine = new ArrayList<>(); @@ -483,7 +482,7 @@ class ExtractRegistry extends Extract { processBuilder.redirectError(new File(errFile)); ExecUtil.execute(processBuilder, new DataSourceIngestModuleProcessTerminator(context)); } catch (IOException ex) { - logger.log(Level.SEVERE, String.format("Running RegRipper on %s encountered an error or was incomplete", hiveFilePath), ex); //NON-NLS + logger.log(Level.SEVERE, "Unable to run RegRipper", ex); //NON-NLS this.addErrorMessage(NbBundle.getMessage(this.getClass(), "ExtractRegistry.execRegRip.errMsg.failedAnalyzeRegFile", this.getName())); } } @@ -516,7 +515,7 @@ class ExtractRegistry extends Extract { String stringdoc = startdoc + result + enddoc; DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document doc = builder.parse(new InputSource(new StringReader(stringdoc))); - + // cycle through the elements in the doc Element oroot = doc.getDocumentElement(); NodeList children = oroot.getChildNodes(); @@ -750,33 +749,33 @@ class ExtractRegistry extends Extract { break; case "usb": //NON-NLS try { - Long usbMtime = Long.parseLong(artnode.getAttribute("mtime")); //NON-NLS - usbMtime = Long.valueOf(usbMtime.toString()); + Long usbMtime = Long.parseLong(artnode.getAttribute("mtime")); //NON-NLS + usbMtime = Long.valueOf(usbMtime.toString()); - BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, usbMtime)); - String dev = artnode.getAttribute("dev"); //NON-NLS - String make = ""; - String model = dev; - if (dev.toLowerCase().contains("vid")) { //NON-NLS - USBInfo info = USB_MAPPER.parseAndLookup(dev); - if (info.getVendor() != null) { - make = info.getVendor(); - } - if (info.getProduct() != null) { - model = info.getProduct(); - } + BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, usbMtime)); + String dev = artnode.getAttribute("dev"); //NON-NLS + String make = ""; + String model = dev; + if (dev.toLowerCase().contains("vid")) { //NON-NLS + USBInfo info = USB_MAPPER.parseAndLookup(dev); + if (info.getVendor() != null) { + make = info.getVendor(); + } + if (info.getProduct() != null) { + model = info.getProduct(); } - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE, parentModuleName, make)); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL, parentModuleName, model)); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, value)); - bbart.addAttributes(bbattributes); - - newArtifacts.add(bbart); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error adding device attached artifact to blackboard.", ex); //NON-NLS } - break; + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE, parentModuleName, make)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL, parentModuleName, model)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, value)); + bbart.addAttributes(bbattributes); + + newArtifacts.add(bbart); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error adding device attached artifact to blackboard.", ex); //NON-NLS + } + break; case "uninstall": //NON-NLS Long itemMtime = null; try { @@ -837,70 +836,70 @@ class ExtractRegistry extends Extract { case "ProfileList": //NON-NLS try { - String homeDir = value; - String sid = artnode.getAttribute("sid"); //NON-NLS - String username = artnode.getAttribute("username"); //NON-NLS - BlackboardArtifact bbart = null; - try { - //check if any of the existing artifacts match this username - ArrayList existingArtifacts = currentCase.getSleuthkitCase().getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_ACCOUNT); - for (BlackboardArtifact artifact : existingArtifacts) { - if (artifact.getDataSource().getId() == regFile.getDataSourceObjectId()) { - BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID)); - if (attribute != null && attribute.getValueString().equals(sid)) { - bbart = artifact; - break; - } + String homeDir = value; + String sid = artnode.getAttribute("sid"); //NON-NLS + String username = artnode.getAttribute("username"); //NON-NLS + BlackboardArtifact bbart = null; + try { + //check if any of the existing artifacts match this username + ArrayList existingArtifacts = currentCase.getSleuthkitCase().getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_ACCOUNT); + for (BlackboardArtifact artifact : existingArtifacts) { + if (artifact.getDataSource().getId() == regFile.getDataSourceObjectId()) { + BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID)); + if (attribute != null && attribute.getValueString().equals(sid)) { + bbart = artifact; + break; } } - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error getting existing os account artifact", ex); } - if (bbart == null) { - //create new artifact - bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error getting existing os account artifact", ex); + } + if (bbart == null) { + //create new artifact + bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME, + parentModuleName, username)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID, + parentModuleName, sid)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, + parentModuleName, homeDir)); + } else { + //add attributes to existing artifact + BlackboardAttribute bbattr = bbart.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_NAME)); + + if (bbattr == null) { bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME, parentModuleName, username)); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID, - parentModuleName, sid)); + } + bbattr = bbart.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH)); + if (bbattr == null) { bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, parentModuleName, homeDir)); - } else { - //add attributes to existing artifact - BlackboardAttribute bbattr = bbart.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_NAME)); - - if (bbattr == null) { - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME, - parentModuleName, username)); - } - bbattr = bbart.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH)); - if (bbattr == null) { - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, - parentModuleName, homeDir)); - } } - bbart.addAttributes(bbattributes); - newArtifacts.add(bbart); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error adding account artifact to blackboard.", ex); //NON-NLS } - break; + bbart.addAttributes(bbattributes); + newArtifacts.add(bbart); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error adding account artifact to blackboard.", ex); //NON-NLS + } + break; case "NtuserNetwork": // NON-NLS try { - String localPath = artnode.getAttribute("localPath"); //NON-NLS - String remoteName = value; - BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_REMOTE_DRIVE); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCAL_PATH, - parentModuleName, localPath)); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REMOTE_PATH, - parentModuleName, remoteName)); - bbart.addAttributes(bbattributes); - newArtifacts.add(bbart); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error adding network artifact to blackboard.", ex); //NON-NLS - } - break; + String localPath = artnode.getAttribute("localPath"); //NON-NLS + String remoteName = value; + BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_REMOTE_DRIVE); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCAL_PATH, + parentModuleName, localPath)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REMOTE_PATH, + parentModuleName, remoteName)); + bbart.addAttributes(bbattributes); + newArtifacts.add(bbart); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error adding network artifact to blackboard.", ex); //NON-NLS + } + break; case "SSID": // NON-NLS String adapter = artnode.getAttribute("adapter"); //NON-NLS try { @@ -947,13 +946,12 @@ class ExtractRegistry extends Extract { } } catch (IOException ex) { } - + postArtifacts(newArtifacts); } return false; } - private boolean parseSystemPluginOutput(String regfilePath, AbstractFile regAbstractFile) { File regfile = new File(regfilePath); try (BufferedReader reader = new BufferedReader(new FileReader(regfile))) { @@ -965,7 +963,7 @@ class ExtractRegistry extends Extract { parseBamKey(regAbstractFile, reader, Bundle.Registry_System_Bam()); } else if (line.toLowerCase().matches("^bthport v..*")) { parseBlueToothDevices(regAbstractFile, reader); - } + } line = reader.readLine(); } return true; @@ -974,21 +972,21 @@ class ExtractRegistry extends Extract { } catch (IOException ex) { logger.log(Level.WARNING, "Error reading the system hive: {0}", ex); //NON-NLS } - + return false; - + } - + /** - * Create recently used artifacts to parse the regripper plugin output, this + * Create recently used artifacts to parse the regripper plugin output, this * format is used in several diffent plugins - * + * * @param regFile registry file the artifact is associated with - * - * @param reader buffered reader to parse adobemru records - * + * + * @param reader buffered reader to parse adobemru records + * * @param comment string that will populate attribute TSK_COMMENT - * + * * @throws FileNotFound and IOException */ private void parseBlueToothDevices(AbstractFile regFile, BufferedReader reader) throws FileNotFoundException, IOException { @@ -996,11 +994,11 @@ class ExtractRegistry extends Extract { String line = reader.readLine(); while ((line != null) && (!line.contains(SECTION_DIVIDER))) { line = reader.readLine(); - + if (line != null) { line = line.trim(); } - + if ((line != null) && (line.toLowerCase().contains("device unique id"))) { // Columns are seperated by colons : // Data : Values @@ -1018,14 +1016,14 @@ class ExtractRegistry extends Extract { line = reader.readLine(); addBlueToothAttribute(line, attributes, TSK_DATETIME_ACCESSED); BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_BLUETOOTH_PAIRING, regFile, attributes); - if(bba != null) { - bbartifacts.add(bba); + if (bba != null) { + bbartifacts.add(bba); } // Read blank line between records then next read line is start of next block reader.readLine(); line = reader.readLine(); } - + if (line != null) { line = line.trim(); } @@ -1036,14 +1034,13 @@ class ExtractRegistry extends Extract { } } - private void addBlueToothAttribute(String line, Collection attributes, ATTRIBUTE_TYPE attributeType) { - if (line == null) { - return; - } - - String tokens[] = line.split(": "); - if (tokens.length > 1 && !tokens[1].isEmpty()) { + if (line == null) { + return; + } + + String tokens[] = line.split(": "); + if (tokens.length > 1 && !tokens[1].isEmpty()) { String tokenString = tokens[1]; if (attributeType.getDisplayName().toLowerCase().contains("date")) { String dateString = tokenString.toLowerCase().replace(" z", ""); @@ -1052,20 +1049,19 @@ class ExtractRegistry extends Extract { Long dateLong = Long.valueOf(0); try { Date newDate = dateFormat.parse(dateString); - dateLong = newDate.getTime()/1000; + dateLong = newDate.getTime() / 1000; } catch (ParseException ex) { // catching error and displaying date that could not be parsed // we set the timestamp to 0 and continue on processing logger.log(Level.WARNING, String.format("Failed to parse date/time %s for Bluetooth Last Seen attribute.", dateString), ex); //NON-NLS } - attributes.add(new BlackboardAttribute(attributeType, getName(), dateLong)); + attributes.add(new BlackboardAttribute(attributeType, getName(), dateLong)); } else { - attributes.add(new BlackboardAttribute(attributeType, getName(), tokenString)); + attributes.add(new BlackboardAttribute(attributeType, getName(), tokenString)); } - } -} + } + } - /** * Parse the output of the SAM regripper plugin to get additional Account * information @@ -1118,7 +1114,7 @@ class ExtractRegistry extends Extract { } } } - + //add remaining userinfos as accounts; for (Map userInfo : userInfoMap.values()) { BlackboardArtifact bbart = regAbstractFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT); @@ -1153,14 +1149,14 @@ class ExtractRegistry extends Extract { /** * Creates the attribute list for the given user information and group list. - * - * @param userInfo Map of key\value pairs of user information - * @param groupList List of the groups that user belongs + * + * @param userInfo Map of key\value pairs of user information + * @param groupList List of the groups that user belongs * @param existingUser - * - * @return List - * - * @throws ParseException + * + * @return List + * + * @throws ParseException */ Collection getAttributesForAccount(Map userInfo, List groupList, boolean existingUser, AbstractFile regAbstractFile) throws ParseException { Collection bbattributes = new ArrayList<>(); @@ -1222,12 +1218,12 @@ class ExtractRegistry extends Extract { .createAccountFileInstance(Account.Type.EMAIL, value, getRAModuleName(), regAbstractFile); } catch (NoCurrentCaseException | TskCoreException ex) { - logger.log(Level.SEVERE, + logger.log(Level.SEVERE, String.format("Error adding email account with value " - + "%s, to the case database for file %s [objId=%d]", + + "%s, to the case database for file %s [objId=%d]", value, regAbstractFile.getName(), regAbstractFile.getId()), ex); } - + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_EMAIL, getRAModuleName(), value)); } @@ -1307,7 +1303,7 @@ class ExtractRegistry extends Extract { return bbattributes; } - + /** * Read the User Information section of the SAM regripper plugin's output * and collect user account information from the file. @@ -1355,14 +1351,14 @@ class ExtractRegistry extends Extract { line = bufferedReader.readLine(); } } - + /** * Create recently used artifacts from NTUSER regripper files - * + * * @param regFileName name of the regripper output file - * - * @param regFile registry file the artifact is associated with - * + * + * @param regFile registry file the artifact is associated with + * * @throws FileNotFound and IOException */ private void createRecentlyUsedArtifacts(String regFileName, AbstractFile regFile) throws FileNotFoundException, IOException { @@ -1388,21 +1384,21 @@ class ExtractRegistry extends Extract { parseWinRARMRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Winrar()); } else if (line.matches("^officedocs2010 v.*")) { parseOfficeDocs2010MRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Officedocs()); - } + } line = reader.readLine(); } - } + } } - - /** + + /** * Create artifacts from BAM Regripper Plugin records - * + * * @param regFile registry file the artifact is associated with - * - * @param reader buffered reader to parse adobemru records - * + * + * @param reader buffered reader to parse adobemru records + * * @param comment string that will populate attribute TSK_COMMENT - * + * * @throws FileNotFound and IOException */ private void parseBamKey(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException { @@ -1419,7 +1415,7 @@ class ExtractRegistry extends Extract { // Split the line into it parts based on delimiter of "|" // 1570493613|BAM|||\Device\HarddiskVolume3\Program Files\TechSmith\Snagit 2018\Snagit32.exe (S-1-5-21-3042408413-2583535980-1301764466-1001) String tokens[] = line.split("\\|"); - Long progRunDateTime = Long.valueOf(tokens[0]); + Long progRunDateTime = Long.valueOf(tokens[0]); // Split on " (S-" as this signifies a User SID, if S- not used then may have issues becuase of (x86) in path is valid. // We can add the S- back to the string that we split on since S- is a valid beginning of a User SID String fileNameSid[] = tokens[4].split("\\s+\\(S-"); @@ -1454,16 +1450,16 @@ class ExtractRegistry extends Extract { postArtifacts(bbartifacts); } } - + /** * Create recently used artifacts from adobemru Regripper Plugin records - * + * * @param regFile registry file the artifact is associated with - * - * @param reader buffered reader to parse adobemru records - * + * + * @param reader buffered reader to parse adobemru records + * * @param comment string that will populate attribute TSK_COMMENT - * + * * @throws FileNotFound and IOException */ private void parseAdobeMRUList(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException { @@ -1482,22 +1478,22 @@ class ExtractRegistry extends Extract { // Split csv line, handles double quotes around individual file names // since file names can contain commas String tokens[] = line.split(",(?=([^\"]*\"[^\"]*\")*[^\"]*$)"); - String fileName = tokens[1].substring(0, tokens[1].length() -1); + String fileName = tokens[1].substring(0, tokens[1].length() - 1); fileName = fileName.replace("\"", ""); if (fileName.charAt(0) == '/') { - fileName = fileName.substring(1,fileName.length() - 1); + fileName = fileName.substring(1, fileName.length() - 1); fileName = fileName.replaceFirst("/", ":/"); } // Check to see if more then 2 tokens, Date may not be populated, will default to 0 if (tokens.length > 2) { // Time in the format of 20200131104456-05'00' try { - String fileUsedTime = tokens[2].replaceAll("'",""); + String fileUsedTime = tokens[2].replaceAll("'", ""); Date usedDate = adobePluginDateFormat.parse(fileUsedTime); - adobeUsedTime = usedDate.getTime()/1000; + adobeUsedTime = usedDate.getTime() / 1000; } catch (ParseException ex) { - // catching error and displaying date that could not be parsed - // we set the timestamp to 0 and continue on processing + // catching error and displaying date that could not be parsed + // we set the timestamp to 0 and continue on processing logger.log(Level.WARNING, String.format("Failed to parse date/time %s for adobe file artifact.", tokens[2]), ex); //NON-NLS } } @@ -1506,13 +1502,13 @@ class ExtractRegistry extends Extract { attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, getName(), adobeUsedTime)); attributes.add(new BlackboardAttribute(TSK_COMMENT, getName(), comment)); BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); - if(bba != null) { - bbartifacts.add(bba); - fileName = fileName.replace("\0", ""); - bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); - if (bba != null) { - bbartifacts.add(bba); - } + if (bba != null) { + bbartifacts.add(bba); + fileName = fileName.replace("\0", ""); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } } line = reader.readLine(); } @@ -1523,16 +1519,17 @@ class ExtractRegistry extends Extract { postArtifacts(bbartifacts); } } - - /** - * Create recently used artifacts to parse the Media Player MRU regripper (mpmru) records - * + + /** + * Create recently used artifacts to parse the Media Player MRU regripper + * (mpmru) records + * * @param regFile registry file the artifact is associated with - * - * @param reader buffered reader to parse adobemru records - * + * + * @param reader buffered reader to parse adobemru records + * * @param comment string that will populate attribute TSK_COMMENT - * + * * @throws FileNotFound and IOException */ private void parseMediaPlayerMRUList(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException { @@ -1553,16 +1550,16 @@ class ExtractRegistry extends Extract { attributes.add(new BlackboardAttribute(TSK_PATH, getName(), fileName)); attributes.add(new BlackboardAttribute(TSK_COMMENT, getName(), comment)); BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); - if(bba != null) { - bbartifacts.add(bba); - bba = createAssociatedArtifact(fileName, bba); - if (bba != null) { - bbartifacts.add(bba); - bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); - if (bba != null) { - bbartifacts.add(bba); - } - } + if (bba != null) { + bbartifacts.add(bba); + bba = createAssociatedArtifact(fileName, bba); + if (bba != null) { + bbartifacts.add(bba); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } + } } line = reader.readLine(); } @@ -1573,16 +1570,17 @@ class ExtractRegistry extends Extract { postArtifacts(bbartifacts); } } - - /** - * Create recently used artifacts to parse the regripper plugin output, this format is used in several diffent plugins - * + + /** + * Create recently used artifacts to parse the regripper plugin output, this + * format is used in several diffent plugins + * * @param regFile registry file the artifact is associated with - * - * @param reader buffered reader to parse adobemru records - * + * + * @param reader buffered reader to parse adobemru records + * * @param comment string that will populate attribute TSK_COMMENT - * + * * @throws FileNotFound and IOException */ private void parseGenericMRUList(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException { @@ -1604,12 +1602,12 @@ class ExtractRegistry extends Extract { attributes.add(new BlackboardAttribute(TSK_PATH, getName(), fileName)); attributes.add(new BlackboardAttribute(TSK_COMMENT, getName(), comment)); BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); - if(bba != null) { - bbartifacts.add(bba); - bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); - if (bba != null) { - bbartifacts.add(bba); - } + if (bba != null) { + bbartifacts.add(bba); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } } line = reader.readLine(); } @@ -1620,16 +1618,17 @@ class ExtractRegistry extends Extract { postArtifacts(bbartifacts); } } - - /** - * Create recently used artifacts to parse the WinRAR Regripper plugin output - * + + /** + * Create recently used artifacts to parse the WinRAR Regripper plugin + * output + * * @param regFile registry file the artifact is associated with - * - * @param reader buffered reader to parse adobemru records - * + * + * @param reader buffered reader to parse adobemru records + * * @param comment string that will populate attribute TSK_COMMENT - * + * * @throws FileNotFound and IOException */ private void parseWinRARMRUList(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException { @@ -1651,12 +1650,12 @@ class ExtractRegistry extends Extract { attributes.add(new BlackboardAttribute(TSK_PATH, getName(), fileName)); attributes.add(new BlackboardAttribute(TSK_COMMENT, getName(), comment)); BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); - if(bba != null) { - bbartifacts.add(bba); - bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); - if (bba != null) { - bbartifacts.add(bba); - } + if (bba != null) { + bbartifacts.add(bba); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } } line = reader.readLine(); } @@ -1668,16 +1667,17 @@ class ExtractRegistry extends Extract { postArtifacts(bbartifacts); } } - - /** - * Create recently used artifacts to parse the runmru ArcHistory (7Zip) regripper plugin records - * + + /** + * Create recently used artifacts to parse the runmru ArcHistory (7Zip) + * regripper plugin records + * * @param regFile registry file the artifact is associated with - * - * @param reader buffered reader to parse adobemru records - * + * + * @param reader buffered reader to parse adobemru records + * * @param comment string that will populate attribute TSK_COMMENT - * + * * @throws FileNotFound and IOException */ private void parse7ZipMRU(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException { @@ -1694,11 +1694,11 @@ class ExtractRegistry extends Extract { attributes.add(new BlackboardAttribute(TSK_COMMENT, getName(), comment)); BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); if (bba != null) { - bbartifacts.add(bba); - bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); - if (bba != null) { - bbartifacts.add(bba); - } + bbartifacts.add(bba); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } } line = reader.readLine(); line = line.trim(); @@ -1708,16 +1708,17 @@ class ExtractRegistry extends Extract { postArtifacts(bbartifacts); } } - - /** - * Create recently used artifacts to parse the Office Documents 2010 records Regripper Plugin output - * + + /** + * Create recently used artifacts to parse the Office Documents 2010 records + * Regripper Plugin output + * * @param regFile registry file the artifact is associated with - * - * @param reader buffered reader to parse adobemru records - * + * + * @param reader buffered reader to parse adobemru records + * * @param comment string that will populate attribute TSK_COMMENT - * + * * @throws FileNotFound and IOException */ private void parseOfficeDocs2010MRUList(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException { @@ -1734,7 +1735,7 @@ class ExtractRegistry extends Extract { // record has the following format // 1294283922|REG|||OfficeDocs2010 - F:\Windows_time_Rules_xp.doc String tokens[] = line.split("\\|"); - Long docDate = Long.valueOf(tokens[0]); + Long docDate = Long.valueOf(tokens[0]); String fileNameTokens[] = tokens[4].split(" - "); String fileName = fileNameTokens[1]; Collection attributes = new ArrayList<>(); @@ -1742,12 +1743,12 @@ class ExtractRegistry extends Extract { attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, getName(), docDate)); attributes.add(new BlackboardAttribute(TSK_COMMENT, getName(), comment)); BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); - if(bba != null) { - bbartifacts.add(bba); - bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); - if (bba != null) { - bbartifacts.add(bba); - } + if (bba != null) { + bbartifacts.add(bba); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } } line = reader.readLine(); line = line.trim(); @@ -1756,16 +1757,17 @@ class ExtractRegistry extends Extract { postArtifacts(bbartifacts); } } - + /** - * Create recently used artifacts to parse the Office trust records (trustrecords) Regipper plugin records - * + * Create recently used artifacts to parse the Office trust records + * (trustrecords) Regipper plugin records + * * @param regFile registry file the artifact is associated with - * - * @param reader buffered reader to parse adobemru records - * + * + * @param reader buffered reader to parse adobemru records + * * @param comment string that will populate attribute TSK_COMMENT - * + * * @throws FileNotFound and IOException */ private void parseOfficeTrustRecords(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException { @@ -1779,8 +1781,8 @@ class ExtractRegistry extends Extract { line = reader.readLine(); line = line.trim(); usedTime = Long.valueOf(0); - if (!line.contains("**") && !line.contains("----------") && !line.contains("LastWrite") - && !line.contains(SECTION_DIVIDER) && !line.isEmpty() && !line.contains("TrustRecords")) { + if (!line.contains("**") && !line.contains("----------") && !line.contains("LastWrite") + && !line.contains(SECTION_DIVIDER) && !line.isEmpty() && !line.contains("TrustRecords")) { // Columns are // Date : / // Split line on " : " which is the record delimiter between position and file @@ -1790,12 +1792,12 @@ class ExtractRegistry extends Extract { fileName = fileName.replace("%USERPROFILE%", userProfile); // Time in the format of Wed May 31 14:33:03 2017 Z try { - String fileUsedTime = tokens[0].replaceAll(" Z",""); + String fileUsedTime = tokens[0].replaceAll(" Z", ""); Date usedDate = pluginDateFormat.parse(fileUsedTime); - usedTime = usedDate.getTime()/1000; + usedTime = usedDate.getTime() / 1000; } catch (ParseException ex) { - // catching error and displaying date that could not be parsed - // we set the timestamp to 0 and continue on processing + // catching error and displaying date that could not be parsed + // we set the timestamp to 0 and continue on processing logger.log(Level.WARNING, String.format("Failed to parse date/time %s for TrustRecords artifact.", tokens[0]), ex); //NON-NLS } Collection attributes = new ArrayList<>(); @@ -1803,12 +1805,12 @@ class ExtractRegistry extends Extract { attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, getName(), usedTime)); attributes.add(new BlackboardAttribute(TSK_COMMENT, getName(), comment)); BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); - if(bba != null) { - bbartifacts.add(bba); - bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); - if (bba != null) { - bbartifacts.add(bba); - } + if (bba != null) { + bbartifacts.add(bba); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } } line = line.trim(); } @@ -1819,14 +1821,15 @@ class ExtractRegistry extends Extract { } /** - * Create associated artifacts using file name and path and the artifact it associates with - * + * Create associated artifacts using file name and path and the artifact it + * associates with + * * @param filePathName file and path of object being associated with - * - * @param bba blackboard artifact to associate with - * - * @returnv BlackboardArtifact or a null value - */ + * + * @param bba blackboard artifact to associate with + * + * @returnv BlackboardArtifact or a null value + */ private BlackboardArtifact createAssociatedArtifact(String filePathName, BlackboardArtifact bba) { org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager(); String fileName = FilenameUtils.getName(filePathName); @@ -1838,9 +1841,9 @@ class ExtractRegistry extends Extract { for (AbstractFile sourceFile : sourceFiles) { if (sourceFile.getParentPath().endsWith(filePath)) { Collection bbattributes2 = new ArrayList<>(); - bbattributes2.addAll(Arrays.asList( - new BlackboardAttribute(TSK_ASSOCIATED_ARTIFACT, this.getName(), - bba.getArtifactID()))); + bbattributes2.addAll(Arrays.asList( + new BlackboardAttribute(TSK_ASSOCIATED_ARTIFACT, this.getName(), + bba.getArtifactID()))); BlackboardArtifact associatedObjectBba = createArtifactWithAttributes(TSK_ASSOCIATED_OBJECT, sourceFile, bbattributes2); if (associatedObjectBba != null) { @@ -1854,16 +1857,16 @@ class ExtractRegistry extends Extract { // system anymore logger.log(Level.WARNING, String.format("Error finding actual file %s. file may not exist", filePathName)); //NON-NLS } - + return null; } - + /** * Create a map of userids to usernames from the OS Accounts. * * @param dataSource * - * @return A Map of userIDs and userNames + * @return A Map of userIDs and userNames * * @throws TskCoreException */ @@ -1883,10 +1886,10 @@ class ExtractRegistry extends Extract { userNameMap.put(userID, userName); } } - + return userNameMap; } - + /** * Gets the attribute for the given type from the given artifact. * @@ -1911,7 +1914,7 @@ class ExtractRegistry extends Extract { */ void createShellBagArtifacts(AbstractFile regFile, List shellbags) throws TskCoreException { List artifacts = new ArrayList<>(); - try{ + try { for (ShellBag bag : shellbags) { Collection attributes = new ArrayList<>(); BlackboardArtifact artifact = regFile.newArtifact(getShellBagArtifact().getTypeID()); @@ -1959,8 +1962,8 @@ class ExtractRegistry extends Extract { private BlackboardArtifact.Type getShellBagArtifact() throws TskCoreException { if (shellBagArtifactType == null) { shellBagArtifactType = tskCase.getArtifactType(SHELLBAG_ARTIFACT_NAME); - - if(shellBagArtifactType == null) { + + if (shellBagArtifactType == null) { try { tskCase.addBlackboardArtifactType(SHELLBAG_ARTIFACT_NAME, Bundle.Shellbag_Artifact_Display_Name()); //NON-NLS } catch (TskDataException ex) { @@ -1986,9 +1989,9 @@ class ExtractRegistry extends Extract { private BlackboardAttribute.Type getLastWriteAttribute() throws TskCoreException { if (shellBagLastWriteAttributeType == null) { try { - shellBagLastWriteAttributeType = tskCase.addArtifactAttributeType(SHELLBAG_ATTRIBUTE_LAST_WRITE, - BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME, - Bundle.Shellbag_Last_Write_Attribute_Display_Name()); + shellBagLastWriteAttributeType = tskCase.addArtifactAttributeType(SHELLBAG_ATTRIBUTE_LAST_WRITE, + BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME, + Bundle.Shellbag_Last_Write_Attribute_Display_Name()); } catch (TskDataException ex) { // Attribute already exists get it from the case shellBagLastWriteAttributeType = tskCase.getAttributeType(SHELLBAG_ATTRIBUTE_LAST_WRITE); @@ -2008,9 +2011,9 @@ class ExtractRegistry extends Extract { private BlackboardAttribute.Type getKeyAttribute() throws TskCoreException { if (shellBagKeyAttributeType == null) { try { - shellBagKeyAttributeType = tskCase.addArtifactAttributeType(SHELLBAG_ATTRIBUTE_KEY, - BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, - Bundle.Shellbag_Key_Attribute_Display_Name()); + shellBagKeyAttributeType = tskCase.addArtifactAttributeType(SHELLBAG_ATTRIBUTE_KEY, + BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, + Bundle.Shellbag_Key_Attribute_Display_Name()); } catch (TskDataException ex) { // The attribute already exists get it from the case shellBagKeyAttributeType = tskCase.getAttributeType(SHELLBAG_ATTRIBUTE_KEY); @@ -2018,15 +2021,15 @@ class ExtractRegistry extends Extract { } return shellBagKeyAttributeType; } - - /** + + /** * Maps the user groups to the sid that are a part of them. - * + * * @param bufferedReader - * + * * @return A map if sid and the groups they map too - * - * @throws IOException + * + * @throws IOException */ Map> readGroups(BufferedReader bufferedReader) throws IOException { Map> groupMap = new HashMap<>(); @@ -2069,12 +2072,11 @@ class ExtractRegistry extends Extract { } /** - * Gets the key value from user account strings of the format - * key:value or + * Gets the key value from user account strings of the format key:value or * --> value - * + * * @param line String to parse - * + * * @return key value pair */ private Map.Entry getSAMKeyValue(String line) { @@ -2102,7 +2104,7 @@ class ExtractRegistry extends Extract { return returnValue; } - + @Override public void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) { this.dataSource = dataSource; From a83563799bef6f7dacb4c0b34dc12124705e9e5c Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Thu, 3 Sep 2020 18:03:35 -0400 Subject: [PATCH 8/8] Fix bugs in ExecUtil --- .../recentactivity/ExtractRegistry.java | 590 +++++++++--------- 1 file changed, 294 insertions(+), 296 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java index 96175408b5..20acab7a87 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java @@ -168,11 +168,11 @@ class ExtractRegistry extends Extract { private Content dataSource; private IngestJobContext context; private Map userNameMap; - + private static final String SHELLBAG_ARTIFACT_NAME = "RA_SHELL_BAG"; //NON-NLS private static final String SHELLBAG_ATTRIBUTE_LAST_WRITE = "RA_SHELL_BAG_LAST_WRITE"; //NON-NLS - private static final String SHELLBAG_ATTRIBUTE_KEY = "RA_SHELL_BAG_KEY"; //NON-NLS - + private static final String SHELLBAG_ATTRIBUTE_KEY= "RA_SHELL_BAG_KEY"; //NON-NLS + BlackboardArtifact.Type shellBagArtifactType = null; BlackboardAttribute.Type shellBagKeyAttributeType = null; BlackboardAttribute.Type shellBagLastWriteAttributeType = null; @@ -246,14 +246,15 @@ class ExtractRegistry extends Extract { logger.log(Level.WARNING, msg, ex); this.addErrorMessage(this.getName() + ": " + msg); } - + + // find the user-specific ntuser-dat files try { allRegistryFiles.addAll(fileManager.findFiles(dataSource, "ntuser.dat")); //NON-NLS } catch (TskCoreException ex) { logger.log(Level.WARNING, "Error fetching 'ntuser.dat' file."); //NON-NLS } - + // find the user-specific ntuser-dat files try { allRegistryFiles.addAll(fileManager.findFiles(dataSource, "usrclass.dat")); //NON-NLS @@ -417,7 +418,7 @@ class ExtractRegistry extends Extract { fullType = "sam"; //NON-NLS } else if (regFilePath.toLowerCase().contains("security")) { //NON-NLS fullType = "security"; //NON-NLS - } else if (regFilePath.toLowerCase().contains("usrclass")) { //NON-NLS + }else if (regFilePath.toLowerCase().contains("usrclass")) { //NON-NLS fullType = "usrclass"; //NON-NLS } else { return regOutputFiles; @@ -443,9 +444,9 @@ class ExtractRegistry extends Extract { try { scanErrorLogs(errFilePath); } catch (IOException ex) { - logger.log(Level.SEVERE, "Unable to run RegRipper", ex); //NON-NLS - this.addErrorMessage(NbBundle.getMessage(this.getClass(), "ExtractRegistry.execRegRip.errMsg.failedAnalyzeRegFile", this.getName())); - } + logger.log(Level.SEVERE, "Unable to run RegRipper", ex); //NON-NLS + this.addErrorMessage(NbBundle.getMessage(this.getClass(), "ExtractRegistry.execRegRip.errMsg.failedAnalyzeRegFile", this.getName())); + } } return regOutputFiles; } @@ -457,14 +458,14 @@ class ExtractRegistry extends Extract { while (line != null) { line = line.trim(); if (line.toLowerCase().contains("error") || line.toLowerCase().contains("@inc")) { - logger.log(Level.WARNING, "Regripper file {0} contains errors from run", errFilePath); //NON-NLS - + logger.log(Level.WARNING, "Regripper file {0} contains errors from run", errFilePath); //NON-NLS + } line = reader.readLine(); } } } - + private void executeRegRipper(List regRipperPath, Path regRipperHomeDir, String hiveFilePath, String hiveFileType, String outputFile, String errFile) { try { List commandLine = new ArrayList<>(); @@ -515,7 +516,7 @@ class ExtractRegistry extends Extract { String stringdoc = startdoc + result + enddoc; DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document doc = builder.parse(new InputSource(new StringReader(stringdoc))); - + // cycle through the elements in the doc Element oroot = doc.getDocumentElement(); NodeList children = oroot.getChildNodes(); @@ -749,33 +750,33 @@ class ExtractRegistry extends Extract { break; case "usb": //NON-NLS try { - Long usbMtime = Long.parseLong(artnode.getAttribute("mtime")); //NON-NLS - usbMtime = Long.valueOf(usbMtime.toString()); + Long usbMtime = Long.parseLong(artnode.getAttribute("mtime")); //NON-NLS + usbMtime = Long.valueOf(usbMtime.toString()); - BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, usbMtime)); - String dev = artnode.getAttribute("dev"); //NON-NLS - String make = ""; - String model = dev; - if (dev.toLowerCase().contains("vid")) { //NON-NLS - USBInfo info = USB_MAPPER.parseAndLookup(dev); - if (info.getVendor() != null) { - make = info.getVendor(); - } - if (info.getProduct() != null) { - model = info.getProduct(); + BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, usbMtime)); + String dev = artnode.getAttribute("dev"); //NON-NLS + String make = ""; + String model = dev; + if (dev.toLowerCase().contains("vid")) { //NON-NLS + USBInfo info = USB_MAPPER.parseAndLookup(dev); + if (info.getVendor() != null) { + make = info.getVendor(); + } + if (info.getProduct() != null) { + model = info.getProduct(); + } } + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE, parentModuleName, make)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL, parentModuleName, model)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, value)); + bbart.addAttributes(bbattributes); + + newArtifacts.add(bbart); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error adding device attached artifact to blackboard.", ex); //NON-NLS } - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE, parentModuleName, make)); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL, parentModuleName, model)); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, value)); - bbart.addAttributes(bbattributes); - - newArtifacts.add(bbart); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error adding device attached artifact to blackboard.", ex); //NON-NLS - } - break; + break; case "uninstall": //NON-NLS Long itemMtime = null; try { @@ -836,70 +837,70 @@ class ExtractRegistry extends Extract { case "ProfileList": //NON-NLS try { - String homeDir = value; - String sid = artnode.getAttribute("sid"); //NON-NLS - String username = artnode.getAttribute("username"); //NON-NLS - BlackboardArtifact bbart = null; - try { - //check if any of the existing artifacts match this username - ArrayList existingArtifacts = currentCase.getSleuthkitCase().getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_ACCOUNT); - for (BlackboardArtifact artifact : existingArtifacts) { - if (artifact.getDataSource().getId() == regFile.getDataSourceObjectId()) { - BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID)); - if (attribute != null && attribute.getValueString().equals(sid)) { - bbart = artifact; - break; + String homeDir = value; + String sid = artnode.getAttribute("sid"); //NON-NLS + String username = artnode.getAttribute("username"); //NON-NLS + BlackboardArtifact bbart = null; + try { + //check if any of the existing artifacts match this username + ArrayList existingArtifacts = currentCase.getSleuthkitCase().getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_ACCOUNT); + for (BlackboardArtifact artifact : existingArtifacts) { + if (artifact.getDataSource().getId() == regFile.getDataSourceObjectId()) { + BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID)); + if (attribute != null && attribute.getValueString().equals(sid)) { + bbart = artifact; + break; + } } } + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error getting existing os account artifact", ex); } - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error getting existing os account artifact", ex); - } - if (bbart == null) { - //create new artifact - bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME, - parentModuleName, username)); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID, - parentModuleName, sid)); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, - parentModuleName, homeDir)); - } else { - //add attributes to existing artifact - BlackboardAttribute bbattr = bbart.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_NAME)); - - if (bbattr == null) { + if (bbart == null) { + //create new artifact + bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME, parentModuleName, username)); - } - bbattr = bbart.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH)); - if (bbattr == null) { + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID, + parentModuleName, sid)); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, parentModuleName, homeDir)); + } else { + //add attributes to existing artifact + BlackboardAttribute bbattr = bbart.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_NAME)); + + if (bbattr == null) { + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME, + parentModuleName, username)); + } + bbattr = bbart.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH)); + if (bbattr == null) { + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, + parentModuleName, homeDir)); + } } + bbart.addAttributes(bbattributes); + newArtifacts.add(bbart); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error adding account artifact to blackboard.", ex); //NON-NLS } - bbart.addAttributes(bbattributes); - newArtifacts.add(bbart); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error adding account artifact to blackboard.", ex); //NON-NLS - } - break; + break; case "NtuserNetwork": // NON-NLS try { - String localPath = artnode.getAttribute("localPath"); //NON-NLS - String remoteName = value; - BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_REMOTE_DRIVE); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCAL_PATH, - parentModuleName, localPath)); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REMOTE_PATH, - parentModuleName, remoteName)); - bbart.addAttributes(bbattributes); - newArtifacts.add(bbart); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error adding network artifact to blackboard.", ex); //NON-NLS - } - break; + String localPath = artnode.getAttribute("localPath"); //NON-NLS + String remoteName = value; + BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_REMOTE_DRIVE); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCAL_PATH, + parentModuleName, localPath)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REMOTE_PATH, + parentModuleName, remoteName)); + bbart.addAttributes(bbattributes); + newArtifacts.add(bbart); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error adding network artifact to blackboard.", ex); //NON-NLS + } + break; case "SSID": // NON-NLS String adapter = artnode.getAttribute("adapter"); //NON-NLS try { @@ -946,12 +947,13 @@ class ExtractRegistry extends Extract { } } catch (IOException ex) { } - + postArtifacts(newArtifacts); } return false; } + private boolean parseSystemPluginOutput(String regfilePath, AbstractFile regAbstractFile) { File regfile = new File(regfilePath); try (BufferedReader reader = new BufferedReader(new FileReader(regfile))) { @@ -963,7 +965,7 @@ class ExtractRegistry extends Extract { parseBamKey(regAbstractFile, reader, Bundle.Registry_System_Bam()); } else if (line.toLowerCase().matches("^bthport v..*")) { parseBlueToothDevices(regAbstractFile, reader); - } + } line = reader.readLine(); } return true; @@ -972,21 +974,21 @@ class ExtractRegistry extends Extract { } catch (IOException ex) { logger.log(Level.WARNING, "Error reading the system hive: {0}", ex); //NON-NLS } - + return false; - + } - + /** - * Create recently used artifacts to parse the regripper plugin output, this + * Create recently used artifacts to parse the regripper plugin output, this * format is used in several diffent plugins - * + * * @param regFile registry file the artifact is associated with - * - * @param reader buffered reader to parse adobemru records - * + * + * @param reader buffered reader to parse adobemru records + * * @param comment string that will populate attribute TSK_COMMENT - * + * * @throws FileNotFound and IOException */ private void parseBlueToothDevices(AbstractFile regFile, BufferedReader reader) throws FileNotFoundException, IOException { @@ -994,11 +996,11 @@ class ExtractRegistry extends Extract { String line = reader.readLine(); while ((line != null) && (!line.contains(SECTION_DIVIDER))) { line = reader.readLine(); - + if (line != null) { line = line.trim(); } - + if ((line != null) && (line.toLowerCase().contains("device unique id"))) { // Columns are seperated by colons : // Data : Values @@ -1016,14 +1018,14 @@ class ExtractRegistry extends Extract { line = reader.readLine(); addBlueToothAttribute(line, attributes, TSK_DATETIME_ACCESSED); BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_BLUETOOTH_PAIRING, regFile, attributes); - if (bba != null) { - bbartifacts.add(bba); + if(bba != null) { + bbartifacts.add(bba); } // Read blank line between records then next read line is start of next block reader.readLine(); line = reader.readLine(); } - + if (line != null) { line = line.trim(); } @@ -1034,13 +1036,14 @@ class ExtractRegistry extends Extract { } } - private void addBlueToothAttribute(String line, Collection attributes, ATTRIBUTE_TYPE attributeType) { - if (line == null) { - return; - } - String tokens[] = line.split(": "); - if (tokens.length > 1 && !tokens[1].isEmpty()) { + private void addBlueToothAttribute(String line, Collection attributes, ATTRIBUTE_TYPE attributeType) { + if (line == null) { + return; + } + + String tokens[] = line.split(": "); + if (tokens.length > 1 && !tokens[1].isEmpty()) { String tokenString = tokens[1]; if (attributeType.getDisplayName().toLowerCase().contains("date")) { String dateString = tokenString.toLowerCase().replace(" z", ""); @@ -1049,19 +1052,20 @@ class ExtractRegistry extends Extract { Long dateLong = Long.valueOf(0); try { Date newDate = dateFormat.parse(dateString); - dateLong = newDate.getTime() / 1000; + dateLong = newDate.getTime()/1000; } catch (ParseException ex) { // catching error and displaying date that could not be parsed // we set the timestamp to 0 and continue on processing logger.log(Level.WARNING, String.format("Failed to parse date/time %s for Bluetooth Last Seen attribute.", dateString), ex); //NON-NLS } - attributes.add(new BlackboardAttribute(attributeType, getName(), dateLong)); + attributes.add(new BlackboardAttribute(attributeType, getName(), dateLong)); } else { - attributes.add(new BlackboardAttribute(attributeType, getName(), tokenString)); + attributes.add(new BlackboardAttribute(attributeType, getName(), tokenString)); } - } - } + } +} + /** * Parse the output of the SAM regripper plugin to get additional Account * information @@ -1114,7 +1118,7 @@ class ExtractRegistry extends Extract { } } } - + //add remaining userinfos as accounts; for (Map userInfo : userInfoMap.values()) { BlackboardArtifact bbart = regAbstractFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT); @@ -1149,14 +1153,14 @@ class ExtractRegistry extends Extract { /** * Creates the attribute list for the given user information and group list. - * - * @param userInfo Map of key\value pairs of user information - * @param groupList List of the groups that user belongs + * + * @param userInfo Map of key\value pairs of user information + * @param groupList List of the groups that user belongs * @param existingUser - * - * @return List - * - * @throws ParseException + * + * @return List + * + * @throws ParseException */ Collection getAttributesForAccount(Map userInfo, List groupList, boolean existingUser, AbstractFile regAbstractFile) throws ParseException { Collection bbattributes = new ArrayList<>(); @@ -1218,12 +1222,12 @@ class ExtractRegistry extends Extract { .createAccountFileInstance(Account.Type.EMAIL, value, getRAModuleName(), regAbstractFile); } catch (NoCurrentCaseException | TskCoreException ex) { - logger.log(Level.SEVERE, + logger.log(Level.SEVERE, String.format("Error adding email account with value " - + "%s, to the case database for file %s [objId=%d]", + + "%s, to the case database for file %s [objId=%d]", value, regAbstractFile.getName(), regAbstractFile.getId()), ex); } - + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_EMAIL, getRAModuleName(), value)); } @@ -1303,7 +1307,7 @@ class ExtractRegistry extends Extract { return bbattributes; } - + /** * Read the User Information section of the SAM regripper plugin's output * and collect user account information from the file. @@ -1351,14 +1355,14 @@ class ExtractRegistry extends Extract { line = bufferedReader.readLine(); } } - + /** * Create recently used artifacts from NTUSER regripper files - * + * * @param regFileName name of the regripper output file - * - * @param regFile registry file the artifact is associated with - * + * + * @param regFile registry file the artifact is associated with + * * @throws FileNotFound and IOException */ private void createRecentlyUsedArtifacts(String regFileName, AbstractFile regFile) throws FileNotFoundException, IOException { @@ -1384,21 +1388,21 @@ class ExtractRegistry extends Extract { parseWinRARMRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Winrar()); } else if (line.matches("^officedocs2010 v.*")) { parseOfficeDocs2010MRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Officedocs()); - } + } line = reader.readLine(); } - } + } } - - /** + + /** * Create artifacts from BAM Regripper Plugin records - * + * * @param regFile registry file the artifact is associated with - * - * @param reader buffered reader to parse adobemru records - * + * + * @param reader buffered reader to parse adobemru records + * * @param comment string that will populate attribute TSK_COMMENT - * + * * @throws FileNotFound and IOException */ private void parseBamKey(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException { @@ -1415,7 +1419,7 @@ class ExtractRegistry extends Extract { // Split the line into it parts based on delimiter of "|" // 1570493613|BAM|||\Device\HarddiskVolume3\Program Files\TechSmith\Snagit 2018\Snagit32.exe (S-1-5-21-3042408413-2583535980-1301764466-1001) String tokens[] = line.split("\\|"); - Long progRunDateTime = Long.valueOf(tokens[0]); + Long progRunDateTime = Long.valueOf(tokens[0]); // Split on " (S-" as this signifies a User SID, if S- not used then may have issues becuase of (x86) in path is valid. // We can add the S- back to the string that we split on since S- is a valid beginning of a User SID String fileNameSid[] = tokens[4].split("\\s+\\(S-"); @@ -1450,16 +1454,16 @@ class ExtractRegistry extends Extract { postArtifacts(bbartifacts); } } - + /** * Create recently used artifacts from adobemru Regripper Plugin records - * + * * @param regFile registry file the artifact is associated with - * - * @param reader buffered reader to parse adobemru records - * + * + * @param reader buffered reader to parse adobemru records + * * @param comment string that will populate attribute TSK_COMMENT - * + * * @throws FileNotFound and IOException */ private void parseAdobeMRUList(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException { @@ -1478,22 +1482,22 @@ class ExtractRegistry extends Extract { // Split csv line, handles double quotes around individual file names // since file names can contain commas String tokens[] = line.split(",(?=([^\"]*\"[^\"]*\")*[^\"]*$)"); - String fileName = tokens[1].substring(0, tokens[1].length() - 1); + String fileName = tokens[1].substring(0, tokens[1].length() -1); fileName = fileName.replace("\"", ""); if (fileName.charAt(0) == '/') { - fileName = fileName.substring(1, fileName.length() - 1); + fileName = fileName.substring(1,fileName.length() - 1); fileName = fileName.replaceFirst("/", ":/"); } // Check to see if more then 2 tokens, Date may not be populated, will default to 0 if (tokens.length > 2) { // Time in the format of 20200131104456-05'00' try { - String fileUsedTime = tokens[2].replaceAll("'", ""); + String fileUsedTime = tokens[2].replaceAll("'",""); Date usedDate = adobePluginDateFormat.parse(fileUsedTime); - adobeUsedTime = usedDate.getTime() / 1000; + adobeUsedTime = usedDate.getTime()/1000; } catch (ParseException ex) { - // catching error and displaying date that could not be parsed - // we set the timestamp to 0 and continue on processing + // catching error and displaying date that could not be parsed + // we set the timestamp to 0 and continue on processing logger.log(Level.WARNING, String.format("Failed to parse date/time %s for adobe file artifact.", tokens[2]), ex); //NON-NLS } } @@ -1502,13 +1506,13 @@ class ExtractRegistry extends Extract { attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, getName(), adobeUsedTime)); attributes.add(new BlackboardAttribute(TSK_COMMENT, getName(), comment)); BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); - if (bba != null) { - bbartifacts.add(bba); - fileName = fileName.replace("\0", ""); - bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); - if (bba != null) { - bbartifacts.add(bba); - } + if(bba != null) { + bbartifacts.add(bba); + fileName = fileName.replace("\0", ""); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } } line = reader.readLine(); } @@ -1519,17 +1523,16 @@ class ExtractRegistry extends Extract { postArtifacts(bbartifacts); } } - - /** - * Create recently used artifacts to parse the Media Player MRU regripper - * (mpmru) records - * + + /** + * Create recently used artifacts to parse the Media Player MRU regripper (mpmru) records + * * @param regFile registry file the artifact is associated with - * - * @param reader buffered reader to parse adobemru records - * + * + * @param reader buffered reader to parse adobemru records + * * @param comment string that will populate attribute TSK_COMMENT - * + * * @throws FileNotFound and IOException */ private void parseMediaPlayerMRUList(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException { @@ -1550,16 +1553,16 @@ class ExtractRegistry extends Extract { attributes.add(new BlackboardAttribute(TSK_PATH, getName(), fileName)); attributes.add(new BlackboardAttribute(TSK_COMMENT, getName(), comment)); BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); - if (bba != null) { - bbartifacts.add(bba); - bba = createAssociatedArtifact(fileName, bba); - if (bba != null) { - bbartifacts.add(bba); - bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); - if (bba != null) { - bbartifacts.add(bba); - } - } + if(bba != null) { + bbartifacts.add(bba); + bba = createAssociatedArtifact(fileName, bba); + if (bba != null) { + bbartifacts.add(bba); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } + } } line = reader.readLine(); } @@ -1570,17 +1573,16 @@ class ExtractRegistry extends Extract { postArtifacts(bbartifacts); } } - - /** - * Create recently used artifacts to parse the regripper plugin output, this - * format is used in several diffent plugins - * + + /** + * Create recently used artifacts to parse the regripper plugin output, this format is used in several diffent plugins + * * @param regFile registry file the artifact is associated with - * - * @param reader buffered reader to parse adobemru records - * + * + * @param reader buffered reader to parse adobemru records + * * @param comment string that will populate attribute TSK_COMMENT - * + * * @throws FileNotFound and IOException */ private void parseGenericMRUList(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException { @@ -1602,12 +1604,12 @@ class ExtractRegistry extends Extract { attributes.add(new BlackboardAttribute(TSK_PATH, getName(), fileName)); attributes.add(new BlackboardAttribute(TSK_COMMENT, getName(), comment)); BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); - if (bba != null) { - bbartifacts.add(bba); - bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); - if (bba != null) { - bbartifacts.add(bba); - } + if(bba != null) { + bbartifacts.add(bba); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } } line = reader.readLine(); } @@ -1618,17 +1620,16 @@ class ExtractRegistry extends Extract { postArtifacts(bbartifacts); } } - - /** - * Create recently used artifacts to parse the WinRAR Regripper plugin - * output - * + + /** + * Create recently used artifacts to parse the WinRAR Regripper plugin output + * * @param regFile registry file the artifact is associated with - * - * @param reader buffered reader to parse adobemru records - * + * + * @param reader buffered reader to parse adobemru records + * * @param comment string that will populate attribute TSK_COMMENT - * + * * @throws FileNotFound and IOException */ private void parseWinRARMRUList(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException { @@ -1650,12 +1651,12 @@ class ExtractRegistry extends Extract { attributes.add(new BlackboardAttribute(TSK_PATH, getName(), fileName)); attributes.add(new BlackboardAttribute(TSK_COMMENT, getName(), comment)); BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); - if (bba != null) { - bbartifacts.add(bba); - bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); - if (bba != null) { - bbartifacts.add(bba); - } + if(bba != null) { + bbartifacts.add(bba); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } } line = reader.readLine(); } @@ -1667,17 +1668,16 @@ class ExtractRegistry extends Extract { postArtifacts(bbartifacts); } } - - /** - * Create recently used artifacts to parse the runmru ArcHistory (7Zip) - * regripper plugin records - * + + /** + * Create recently used artifacts to parse the runmru ArcHistory (7Zip) regripper plugin records + * * @param regFile registry file the artifact is associated with - * - * @param reader buffered reader to parse adobemru records - * + * + * @param reader buffered reader to parse adobemru records + * * @param comment string that will populate attribute TSK_COMMENT - * + * * @throws FileNotFound and IOException */ private void parse7ZipMRU(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException { @@ -1694,11 +1694,11 @@ class ExtractRegistry extends Extract { attributes.add(new BlackboardAttribute(TSK_COMMENT, getName(), comment)); BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); if (bba != null) { - bbartifacts.add(bba); - bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); - if (bba != null) { - bbartifacts.add(bba); - } + bbartifacts.add(bba); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } } line = reader.readLine(); line = line.trim(); @@ -1708,17 +1708,16 @@ class ExtractRegistry extends Extract { postArtifacts(bbartifacts); } } - - /** - * Create recently used artifacts to parse the Office Documents 2010 records - * Regripper Plugin output - * + + /** + * Create recently used artifacts to parse the Office Documents 2010 records Regripper Plugin output + * * @param regFile registry file the artifact is associated with - * - * @param reader buffered reader to parse adobemru records - * + * + * @param reader buffered reader to parse adobemru records + * * @param comment string that will populate attribute TSK_COMMENT - * + * * @throws FileNotFound and IOException */ private void parseOfficeDocs2010MRUList(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException { @@ -1735,7 +1734,7 @@ class ExtractRegistry extends Extract { // record has the following format // 1294283922|REG|||OfficeDocs2010 - F:\Windows_time_Rules_xp.doc String tokens[] = line.split("\\|"); - Long docDate = Long.valueOf(tokens[0]); + Long docDate = Long.valueOf(tokens[0]); String fileNameTokens[] = tokens[4].split(" - "); String fileName = fileNameTokens[1]; Collection attributes = new ArrayList<>(); @@ -1743,12 +1742,12 @@ class ExtractRegistry extends Extract { attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, getName(), docDate)); attributes.add(new BlackboardAttribute(TSK_COMMENT, getName(), comment)); BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); - if (bba != null) { - bbartifacts.add(bba); - bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); - if (bba != null) { - bbartifacts.add(bba); - } + if(bba != null) { + bbartifacts.add(bba); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } } line = reader.readLine(); line = line.trim(); @@ -1757,17 +1756,16 @@ class ExtractRegistry extends Extract { postArtifacts(bbartifacts); } } - + /** - * Create recently used artifacts to parse the Office trust records - * (trustrecords) Regipper plugin records - * + * Create recently used artifacts to parse the Office trust records (trustrecords) Regipper plugin records + * * @param regFile registry file the artifact is associated with - * - * @param reader buffered reader to parse adobemru records - * + * + * @param reader buffered reader to parse adobemru records + * * @param comment string that will populate attribute TSK_COMMENT - * + * * @throws FileNotFound and IOException */ private void parseOfficeTrustRecords(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException { @@ -1781,8 +1779,8 @@ class ExtractRegistry extends Extract { line = reader.readLine(); line = line.trim(); usedTime = Long.valueOf(0); - if (!line.contains("**") && !line.contains("----------") && !line.contains("LastWrite") - && !line.contains(SECTION_DIVIDER) && !line.isEmpty() && !line.contains("TrustRecords")) { + if (!line.contains("**") && !line.contains("----------") && !line.contains("LastWrite") + && !line.contains(SECTION_DIVIDER) && !line.isEmpty() && !line.contains("TrustRecords")) { // Columns are // Date : / // Split line on " : " which is the record delimiter between position and file @@ -1792,12 +1790,12 @@ class ExtractRegistry extends Extract { fileName = fileName.replace("%USERPROFILE%", userProfile); // Time in the format of Wed May 31 14:33:03 2017 Z try { - String fileUsedTime = tokens[0].replaceAll(" Z", ""); + String fileUsedTime = tokens[0].replaceAll(" Z",""); Date usedDate = pluginDateFormat.parse(fileUsedTime); - usedTime = usedDate.getTime() / 1000; + usedTime = usedDate.getTime()/1000; } catch (ParseException ex) { - // catching error and displaying date that could not be parsed - // we set the timestamp to 0 and continue on processing + // catching error and displaying date that could not be parsed + // we set the timestamp to 0 and continue on processing logger.log(Level.WARNING, String.format("Failed to parse date/time %s for TrustRecords artifact.", tokens[0]), ex); //NON-NLS } Collection attributes = new ArrayList<>(); @@ -1805,12 +1803,12 @@ class ExtractRegistry extends Extract { attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, getName(), usedTime)); attributes.add(new BlackboardAttribute(TSK_COMMENT, getName(), comment)); BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); - if (bba != null) { - bbartifacts.add(bba); - bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); - if (bba != null) { - bbartifacts.add(bba); - } + if(bba != null) { + bbartifacts.add(bba); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } } line = line.trim(); } @@ -1821,15 +1819,14 @@ class ExtractRegistry extends Extract { } /** - * Create associated artifacts using file name and path and the artifact it - * associates with - * + * Create associated artifacts using file name and path and the artifact it associates with + * * @param filePathName file and path of object being associated with - * - * @param bba blackboard artifact to associate with - * - * @returnv BlackboardArtifact or a null value - */ + * + * @param bba blackboard artifact to associate with + * + * @returnv BlackboardArtifact or a null value + */ private BlackboardArtifact createAssociatedArtifact(String filePathName, BlackboardArtifact bba) { org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager(); String fileName = FilenameUtils.getName(filePathName); @@ -1841,9 +1838,9 @@ class ExtractRegistry extends Extract { for (AbstractFile sourceFile : sourceFiles) { if (sourceFile.getParentPath().endsWith(filePath)) { Collection bbattributes2 = new ArrayList<>(); - bbattributes2.addAll(Arrays.asList( - new BlackboardAttribute(TSK_ASSOCIATED_ARTIFACT, this.getName(), - bba.getArtifactID()))); + bbattributes2.addAll(Arrays.asList( + new BlackboardAttribute(TSK_ASSOCIATED_ARTIFACT, this.getName(), + bba.getArtifactID()))); BlackboardArtifact associatedObjectBba = createArtifactWithAttributes(TSK_ASSOCIATED_OBJECT, sourceFile, bbattributes2); if (associatedObjectBba != null) { @@ -1857,16 +1854,16 @@ class ExtractRegistry extends Extract { // system anymore logger.log(Level.WARNING, String.format("Error finding actual file %s. file may not exist", filePathName)); //NON-NLS } - + return null; } - + /** * Create a map of userids to usernames from the OS Accounts. * * @param dataSource * - * @return A Map of userIDs and userNames + * @return A Map of userIDs and userNames * * @throws TskCoreException */ @@ -1886,10 +1883,10 @@ class ExtractRegistry extends Extract { userNameMap.put(userID, userName); } } - + return userNameMap; } - + /** * Gets the attribute for the given type from the given artifact. * @@ -1914,7 +1911,7 @@ class ExtractRegistry extends Extract { */ void createShellBagArtifacts(AbstractFile regFile, List shellbags) throws TskCoreException { List artifacts = new ArrayList<>(); - try { + try{ for (ShellBag bag : shellbags) { Collection attributes = new ArrayList<>(); BlackboardArtifact artifact = regFile.newArtifact(getShellBagArtifact().getTypeID()); @@ -1962,8 +1959,8 @@ class ExtractRegistry extends Extract { private BlackboardArtifact.Type getShellBagArtifact() throws TskCoreException { if (shellBagArtifactType == null) { shellBagArtifactType = tskCase.getArtifactType(SHELLBAG_ARTIFACT_NAME); - - if (shellBagArtifactType == null) { + + if(shellBagArtifactType == null) { try { tskCase.addBlackboardArtifactType(SHELLBAG_ARTIFACT_NAME, Bundle.Shellbag_Artifact_Display_Name()); //NON-NLS } catch (TskDataException ex) { @@ -1989,9 +1986,9 @@ class ExtractRegistry extends Extract { private BlackboardAttribute.Type getLastWriteAttribute() throws TskCoreException { if (shellBagLastWriteAttributeType == null) { try { - shellBagLastWriteAttributeType = tskCase.addArtifactAttributeType(SHELLBAG_ATTRIBUTE_LAST_WRITE, - BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME, - Bundle.Shellbag_Last_Write_Attribute_Display_Name()); + shellBagLastWriteAttributeType = tskCase.addArtifactAttributeType(SHELLBAG_ATTRIBUTE_LAST_WRITE, + BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME, + Bundle.Shellbag_Last_Write_Attribute_Display_Name()); } catch (TskDataException ex) { // Attribute already exists get it from the case shellBagLastWriteAttributeType = tskCase.getAttributeType(SHELLBAG_ATTRIBUTE_LAST_WRITE); @@ -2011,9 +2008,9 @@ class ExtractRegistry extends Extract { private BlackboardAttribute.Type getKeyAttribute() throws TskCoreException { if (shellBagKeyAttributeType == null) { try { - shellBagKeyAttributeType = tskCase.addArtifactAttributeType(SHELLBAG_ATTRIBUTE_KEY, - BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, - Bundle.Shellbag_Key_Attribute_Display_Name()); + shellBagKeyAttributeType = tskCase.addArtifactAttributeType(SHELLBAG_ATTRIBUTE_KEY, + BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, + Bundle.Shellbag_Key_Attribute_Display_Name()); } catch (TskDataException ex) { // The attribute already exists get it from the case shellBagKeyAttributeType = tskCase.getAttributeType(SHELLBAG_ATTRIBUTE_KEY); @@ -2021,15 +2018,15 @@ class ExtractRegistry extends Extract { } return shellBagKeyAttributeType; } - - /** + + /** * Maps the user groups to the sid that are a part of them. - * + * * @param bufferedReader - * + * * @return A map if sid and the groups they map too - * - * @throws IOException + * + * @throws IOException */ Map> readGroups(BufferedReader bufferedReader) throws IOException { Map> groupMap = new HashMap<>(); @@ -2072,11 +2069,12 @@ class ExtractRegistry extends Extract { } /** - * Gets the key value from user account strings of the format key:value or + * Gets the key value from user account strings of the format + * key:value or * --> value - * + * * @param line String to parse - * + * * @return key value pair */ private Map.Entry getSAMKeyValue(String line) { @@ -2104,7 +2102,7 @@ class ExtractRegistry extends Extract { return returnValue; } - + @Override public void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) { this.dataSource = dataSource;