19 package org.sleuthkit.autopsy.recentactivity;
22 import java.io.FileNotFoundException;
23 import java.io.IOException;
24 import java.nio.file.Path;
25 import java.nio.file.Paths;
26 import java.sql.ResultSet;
27 import java.sql.SQLException;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.Collection;
31 import java.util.HashMap;
32 import java.util.List;
33 import java.util.logging.Level;
35 import org.apache.commons.io.FilenameUtils;
36 import org.openide.modules.InstalledFileLocator;
37 import org.openide.util.NbBundle.Messages;
58 final class ExtractSru
extends Extract {
60 private static final Logger logger = Logger.getLogger(ExtractSru.class.getName());
62 private IngestJobContext context;
64 private static final String APPLICATION_USAGE_SOURCE_NAME =
"System Resource Usage - Application Usage";
65 private static final String NETWORK_USAGE_SOURCE_NAME =
"System Resource Usage - Network Usage";
68 private static final String MODULE_NAME =
"extractSRU";
70 private static final String SRU_TOOL_FOLDER =
"markmckinnon";
71 private static final String SRU_TOOL_NAME_WINDOWS_32 =
"Export_Srudb_32.exe";
72 private static final String SRU_TOOL_NAME_WINDOWS_64 =
"Export_Srudb_64.exe";
73 private static final String SRU_TOOL_NAME_LINUX =
"Export_Srudb_Linux.exe";
74 private static final String SRU_TOOL_NAME_MAC =
"Export_srudb_macos";
75 private static final String SRU_OUTPUT_FILE_NAME =
"Output.txt";
76 private static final String SRU_ERROR_FILE_NAME =
"Error.txt";
78 private static final Map<String, AbstractFile> applicationFilesFound =
new HashMap<>();
81 "ExtractSru_module_name=System Resource Usage Extractor"
84 super(Bundle.ExtractSru_module_name());
88 "ExtractSru_error_finding_export_srudb_program=Error finding export_srudb program",
89 "ExtractSru_process_error_executing_export_srudb_program=Error running export_srudb program"
93 void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) {
95 this.context = context;
97 String modOutPath = Case.getCurrentCase().getModuleDirectory() + File.separator +
"sru";
98 File dir =
new File(modOutPath);
99 if (dir.exists() ==
false) {
103 String tempDirPath = RAImageIngestModule.getRATempPath(Case.getCurrentCase(),
"sru", context.getJobId());
104 String softwareHiveFileName = getSoftwareHiveFile(dataSource, tempDirPath);
106 if (softwareHiveFileName == null) {
110 AbstractFile sruAbstractFile = getSruFile(dataSource, tempDirPath);
112 if (sruAbstractFile == null) {
116 final String sruDumper = getPathForSruDumper();
117 if (sruDumper == null) {
118 this.addErrorMessage(Bundle.ExtractSru_error_finding_export_srudb_program());
119 logger.log(Level.SEVERE,
"Error finding export_srudb program");
123 if (context.dataSourceIngestIsCancelled()) {
128 String modOutFile = modOutPath + File.separator + sruAbstractFile.getId() +
"_srudb.db3";
129 String sruFileName = tempDirPath + File.separator + sruAbstractFile.getId() +
"_" + sruAbstractFile.getName();
131 extractSruFiles(sruDumper, sruFileName, modOutFile, tempDirPath, softwareHiveFileName);
133 findSruExecutedFiles(modOutFile, dataSource);
135 createNetUsageArtifacts(modOutFile, sruAbstractFile);
136 createAppUsageArtifacts(modOutFile, sruAbstractFile);
137 }
catch (IOException ex) {
138 logger.log(Level.SEVERE,
"Error processing SRUDB.dat file", ex);
139 this.addErrorMessage(Bundle.ExtractSru_process_error_executing_export_srudb_program());
144 "ExtractSru_process_errormsg_find_software_hive=Unable to find SOFTWARE HIVE file",
145 "ExtractSru_process_errormsg_write_software_hive=Unable to write SOFTWARE HIVE file"
156 String getSoftwareHiveFile(Content dataSource, String tempDirPath) {
157 FileManager fileManager = Case.getCurrentCase().getServices().getFileManager();
159 List<AbstractFile> softwareHiveFiles;
162 softwareHiveFiles = fileManager.findFiles(dataSource,
"SOFTWARE");
163 }
catch (TskCoreException ex) {
164 this.addErrorMessage(Bundle.ExtractSru_process_errormsg_find_software_hive());
165 logger.log(Level.WARNING,
"Unable to find SOFTWARE HIVE file.", ex);
169 String softwareHiveFileName = null;
171 for (AbstractFile softwareFile : softwareHiveFiles) {
173 if (softwareFile.getParentPath().endsWith(
"/config/")) {
174 softwareHiveFileName = tempDirPath + File.separator + softwareFile.getId() +
"_" + softwareFile.getName();
177 ContentUtils.writeToFile(softwareFile,
new File(softwareHiveFileName));
178 }
catch (IOException ex) {
179 this.addErrorMessage(Bundle.ExtractSru_process_errormsg_find_software_hive());
180 logger.log(Level.WARNING, String.format(
"Unable to write %s to temp directory. File name: %s", softwareFile.getName(), softwareFile), ex);
185 return softwareHiveFileName;
189 "ExtractSru_process_errormsg_find_srudb_dat=Unable to find srudb.dat file",
190 "ExtractSru_process_errormsg_write_srudb_dat=Unable to write srudb.dat file"
200 AbstractFile getSruFile(Content dataSource, String tempDirPath) {
201 FileManager fileManager = Case.getCurrentCase().getServices().getFileManager();
203 List<AbstractFile> sruFiles;
206 sruFiles = fileManager.findFiles(dataSource,
"SRUDB.DAT");
207 }
catch (TskCoreException ex) {
208 this.addErrorMessage(Bundle.ExtractSru_process_errormsg_find_srudb_dat());
209 logger.log(Level.WARNING,
"Unable to find SRUDB.DAT file.", ex);
213 AbstractFile sruAbstractFile = null;
215 for (AbstractFile sruFile : sruFiles) {
217 String sruFileName = tempDirPath + File.separator + sruFile.getId() +
"_" + sruFile.getName();
218 sruAbstractFile = sruFile;
221 ContentUtils.writeToFile(sruFile,
new File(sruFileName));
222 }
catch (IOException ex) {
223 this.addErrorMessage(Bundle.ExtractSru_process_errormsg_write_srudb_dat());
224 logger.log(Level.WARNING, String.format(
"Unable to write %s to temp directory. File name: %s", sruFile.getName(), sruFile), ex);
229 return sruAbstractFile;
242 void extractSruFiles(String sruExePath, String sruFile, String tempOutFile, String tempOutPath, String softwareHiveFile)
throws IOException {
243 final Path outputFilePath = Paths.get(tempOutPath, SRU_OUTPUT_FILE_NAME);
244 final Path errFilePath = Paths.get(tempOutPath, SRU_ERROR_FILE_NAME);
246 List<String> commandLine =
new ArrayList<>();
247 commandLine.add(sruExePath);
248 commandLine.add(sruFile);
249 commandLine.add(softwareHiveFile);
250 commandLine.add(tempOutFile);
252 ProcessBuilder processBuilder =
new ProcessBuilder(commandLine);
253 processBuilder.redirectOutput(outputFilePath.toFile());
254 processBuilder.redirectError(errFilePath.toFile());
256 ExecUtil.execute(processBuilder,
new DataSourceIngestModuleProcessTerminator(context,
true));
259 private String getPathForSruDumper() {
261 if (PlatformUtil.isWindowsOS()) {
262 if (PlatformUtil.is64BitOS()) {
263 path = Paths.get(SRU_TOOL_FOLDER, SRU_TOOL_NAME_WINDOWS_64);
265 path = Paths.get(SRU_TOOL_FOLDER, SRU_TOOL_NAME_WINDOWS_32);
268 if (
"Linux".equals(PlatformUtil.getOSName())) {
269 path = Paths.get(SRU_TOOL_FOLDER, SRU_TOOL_NAME_LINUX);
271 path = Paths.get(SRU_TOOL_FOLDER, SRU_TOOL_NAME_MAC);
274 File sruToolFile = InstalledFileLocator.getDefault().locate(path.toString(),
275 ExtractSru.class.getPackage().getName(),
false);
276 if (sruToolFile != null) {
277 return sruToolFile.getAbsolutePath();
283 private void findSruExecutedFiles(String sruDb, Content dataSource) {
287 String sqlStatement =
"SELECT DISTINCT SUBSTR(LTRIM(IdBlob, '\\Device\\HarddiskVolume'), INSTR(LTRIM(IdBlob, '\\Device\\HarddiskVolume'), '\\')) "
288 +
" application_name, idBlob source_name FROM SruDbIdMapTable WHERE idType = 0 AND idBlob NOT LIKE '!!%'";
290 try (SQLiteDBConnect tempdbconnect =
new SQLiteDBConnect(
"org.sqlite.JDBC",
"jdbc:sqlite:" + sruDb);
291 ResultSet resultSet = tempdbconnect.executeQry(sqlStatement)) {
293 while (resultSet.next()) {
295 if (context.dataSourceIngestIsCancelled()) {
296 logger.log(Level.INFO,
"Cancelled SRU Artifact Creation.");
300 String applicationName = resultSet.getString(
"application_name");
301 String sourceName = resultSet.getString(
"source_name");
303 String normalizePathName = FilenameUtils.normalize(applicationName,
true);
304 String fileName = FilenameUtils.getName(normalizePathName);
305 String filePath = FilenameUtils.getPath(normalizePathName);
306 if (fileName.contains(
" [")) {
307 fileName = fileName.substring(0, fileName.indexOf(
" ["));
309 List<AbstractFile> sourceFiles;
311 sourceFiles = fileManager.
findFiles(dataSource, fileName, filePath);
312 for (AbstractFile sourceFile : sourceFiles) {
313 if (sourceFile.getParentPath().endsWith(filePath)) {
314 applicationFilesFound.put(sourceName.toLowerCase(), sourceFile);
318 }
catch (TskCoreException ex) {
319 logger.log(Level.WARNING, String.format(
"Error finding actual file %s. file may not exist", normalizePathName));
322 }
catch (SQLException ex) {
323 logger.log(Level.WARNING,
"Error while trying to read into a sqlite db.", ex);
328 private void createNetUsageArtifacts(String sruDb, AbstractFile sruAbstractFile) {
329 List<BlackboardArtifact> bba =
new ArrayList<>();
331 String sqlStatement =
"SELECT STRFTIME('%s', timestamp) ExecutionTime, a.application_name, b.Application_Name formatted_application_name, User_Name, "
332 +
" bytesSent, BytesRecvd FROM network_Usage a, SruDbIdMapTable, exe_to_app b "
333 +
" where appId = IdIndex and IdType = 0 and a.application_name = b.source_name order by ExecutionTime;";
335 try (SQLiteDBConnect tempdbconnect =
new SQLiteDBConnect(
"org.sqlite.JDBC",
"jdbc:sqlite:" + sruDb);
336 ResultSet resultSet = tempdbconnect.executeQry(sqlStatement)) {
338 while (resultSet.next()) {
340 if (context.dataSourceIngestIsCancelled()) {
341 logger.log(Level.INFO,
"Cancelled SRU Net Usage Artifact Creation.");
345 String applicationName = resultSet.getString(
"Application_Name");
346 String formattedApplicationName = resultSet.getString(
"formatted_Application_name");
347 Long executionTime = Long.valueOf(resultSet.getInt(
"ExecutionTime"));
348 Long bytesSent = Long.valueOf(resultSet.getInt(
"bytesSent"));
349 Long bytesRecvd = Long.valueOf(resultSet.getInt(
"BytesRecvd"));
350 String userName = resultSet.getString(
"User_Name");
352 Collection<BlackboardAttribute> bbattributes = Arrays.asList(
353 new BlackboardAttribute(
354 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, getName(),
355 formattedApplicationName),
356 new BlackboardAttribute(
357 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_NAME, getName(),
359 new BlackboardAttribute(
360 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, getName(),
362 new BlackboardAttribute(
363 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_BYTES_SENT, getName(), bytesSent),
364 new BlackboardAttribute(
365 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_BYTES_RECEIVED, getName(), bytesRecvd),
366 new BlackboardAttribute(
367 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, getName(), NETWORK_USAGE_SOURCE_NAME));
370 BlackboardArtifact bbart = createArtifactWithAttributes(BlackboardArtifact.ARTIFACT_TYPE.TSK_PROG_RUN, sruAbstractFile, bbattributes);
372 BlackboardArtifact associateBbArtifact = createAssociatedArtifact(applicationName.toLowerCase(), bbart);
373 if (associateBbArtifact != null) {
374 bba.add(associateBbArtifact);
376 }
catch (TskCoreException ex) {
377 logger.log(Level.SEVERE,
"Exception Adding Artifact.", ex);
381 }
catch (SQLException ex) {
382 logger.log(Level.SEVERE,
"Error while trying to read into a sqlite db.", ex);
385 if(!context.dataSourceIngestIsCancelled()) {
390 private void createAppUsageArtifacts(String sruDb, AbstractFile sruAbstractFile) {
391 List<BlackboardArtifact> bba =
new ArrayList<>();
393 String sqlStatement =
"SELECT STRFTIME('%s', timestamp) ExecutionTime, a.application_name, b.Application_Name formatted_application_name, User_Name "
394 +
" FROM Application_Resource_Usage a, SruDbIdMapTable, exe_to_app b WHERE "
395 +
" idType = 0 and idIndex = appId and a.application_name = b.source_name order by ExecutionTime;";
397 try (SQLiteDBConnect tempdbconnect =
new SQLiteDBConnect(
"org.sqlite.JDBC",
"jdbc:sqlite:" + sruDb);
398 ResultSet resultSet = tempdbconnect.executeQry(sqlStatement)) {
400 while (resultSet.next()) {
402 if (context.dataSourceIngestIsCancelled()) {
403 logger.log(Level.INFO,
"Cancelled SRU Net Usage Artifact Creation.");
407 String applicationName = resultSet.getString(
"Application_Name");
408 String formattedApplicationName = resultSet.getString(
"formatted_application_name");
409 Long executionTime = Long.valueOf(resultSet.getInt(
"ExecutionTime"));
410 String userName = resultSet.getString(
"User_Name");
412 Collection<BlackboardAttribute> bbattributes = Arrays.asList(
413 new BlackboardAttribute(
414 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, getName(),
415 formattedApplicationName),
416 new BlackboardAttribute(
417 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_NAME, getName(),
419 new BlackboardAttribute(
420 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, getName(),
422 new BlackboardAttribute(
423 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, getName(), APPLICATION_USAGE_SOURCE_NAME));
426 BlackboardArtifact bbart = createArtifactWithAttributes(BlackboardArtifact.ARTIFACT_TYPE.TSK_PROG_RUN, sruAbstractFile, bbattributes);
428 BlackboardArtifact associateBbArtifact = createAssociatedArtifact(applicationName.toLowerCase(), bbart);
429 if (associateBbArtifact != null) {
430 bba.add(associateBbArtifact);
432 }
catch (TskCoreException ex) {
433 logger.log(Level.SEVERE,
"Exception Adding Artifact.", ex);
437 }
catch (SQLException ex) {
438 logger.log(Level.SEVERE,
"Error while trying to read into a sqlite db.", ex);
441 if(!context.dataSourceIngestIsCancelled()) {
457 private BlackboardArtifact createAssociatedArtifact(String filePathName, BlackboardArtifact bba)
throws TskCoreException {
458 if (applicationFilesFound.containsKey(filePathName)) {
459 AbstractFile sourceFile = applicationFilesFound.get(filePathName);
460 return createAssociatedArtifact(sourceFile, bba);
List< AbstractFile > findFiles(String fileName)