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 static final String APPLICATION_USAGE_SOURCE_NAME =
"System Resource Usage - Application Usage";
63 private static final String NETWORK_USAGE_SOURCE_NAME =
"System Resource Usage - Network Usage";
64 private static final String SRU_TOOL_FOLDER =
"markmckinnon";
65 private static final String SRU_TOOL_NAME_WINDOWS =
"Export_Srudb.exe";
66 private static final String SRU_TOOL_NAME_LINUX =
"Export_Srudb_Linux.exe";
67 private static final String SRU_OUTPUT_FILE_NAME =
"Output.txt";
68 private static final String SRU_ERROR_FILE_NAME =
"Error.txt";
70 private static final Map<String, AbstractFile> applicationFilesFound =
new HashMap<>();
71 private final IngestJobContext context;
74 "ExtractSru_module_name=System Resource Usage Analyzer"
76 ExtractSru(IngestJobContext context) {
77 super(Bundle.ExtractSru_module_name(), context);
78 this.context = context;
82 "ExtractSru_error_finding_export_srudb_program=Error finding export_srudb program",
83 "ExtractSru_process_error_executing_export_srudb_program=Error running export_srudb program"
87 void process(Content dataSource, DataSourceIngestModuleProgress progressBar) {
89 String modOutPath = Case.getCurrentCase().getModuleDirectory() + File.separator +
"sru";
90 File dir =
new File(modOutPath);
91 if (dir.exists() ==
false) {
95 String tempDirPath = RAImageIngestModule.getRATempPath(Case.getCurrentCase(),
"sru", context.getJobId());
96 String softwareHiveFileName = getSoftwareHiveFile(dataSource, tempDirPath);
98 if (softwareHiveFileName == null) {
102 AbstractFile sruAbstractFile = getSruFile(dataSource, tempDirPath);
104 if (sruAbstractFile == null) {
108 final String sruDumper = getPathForSruDumper();
109 if (sruDumper == null) {
110 this.addErrorMessage(Bundle.ExtractSru_error_finding_export_srudb_program());
111 logger.log(Level.SEVERE,
"Error finding export_srudb program");
115 if (context.dataSourceIngestIsCancelled()) {
120 String modOutFile = modOutPath + File.separator + sruAbstractFile.getId() +
"_srudb.db3";
121 String sruFileName = tempDirPath + File.separator + sruAbstractFile.getId() +
"_" + sruAbstractFile.getName();
123 extractSruFiles(sruDumper, sruFileName, modOutFile, tempDirPath, softwareHiveFileName);
125 findSruExecutedFiles(modOutFile, dataSource);
127 createNetUsageArtifacts(modOutFile, sruAbstractFile);
128 createAppUsageArtifacts(modOutFile, sruAbstractFile);
129 }
catch (IOException ex) {
130 logger.log(Level.SEVERE,
"Error processing SRUDB.dat file", ex);
131 this.addErrorMessage(Bundle.ExtractSru_process_error_executing_export_srudb_program());
136 "ExtractSru_process_errormsg_find_software_hive=Unable to find SOFTWARE HIVE file",
137 "ExtractSru_process_errormsg_write_software_hive=Unable to write SOFTWARE HIVE file"
148 String getSoftwareHiveFile(Content dataSource, String tempDirPath) {
149 FileManager fileManager = Case.getCurrentCase().getServices().getFileManager();
151 List<AbstractFile> softwareHiveFiles;
154 softwareHiveFiles = fileManager.findFiles(dataSource,
"SOFTWARE");
155 }
catch (TskCoreException ex) {
156 this.addErrorMessage(Bundle.ExtractSru_process_errormsg_find_software_hive());
157 logger.log(Level.WARNING,
"Unable to find SOFTWARE HIVE file.", ex);
161 String softwareHiveFileName = null;
163 for (AbstractFile softwareFile : softwareHiveFiles) {
165 if (softwareFile.getParentPath().endsWith(
"/config/")) {
166 softwareHiveFileName = tempDirPath + File.separator + softwareFile.getId() +
"_" + softwareFile.getName();
169 ContentUtils.writeToFile(softwareFile,
new File(softwareHiveFileName));
170 }
catch (IOException ex) {
171 this.addErrorMessage(Bundle.ExtractSru_process_errormsg_find_software_hive());
172 logger.log(Level.WARNING, String.format(
"Unable to write %s to temp directory. File name: %s", softwareFile.getName(), softwareFile), ex);
177 return softwareHiveFileName;
181 "ExtractSru_process_errormsg_find_srudb_dat=Unable to find srudb.dat file",
182 "ExtractSru_process_errormsg_write_srudb_dat=Unable to write srudb.dat file"
192 AbstractFile getSruFile(Content dataSource, String tempDirPath) {
193 FileManager fileManager = Case.getCurrentCase().getServices().getFileManager();
195 List<AbstractFile> sruFiles;
198 sruFiles = fileManager.findFiles(dataSource,
"SRUDB.DAT");
199 }
catch (TskCoreException ex) {
200 this.addErrorMessage(Bundle.ExtractSru_process_errormsg_find_srudb_dat());
201 logger.log(Level.WARNING,
"Unable to find SRUDB.DAT file.", ex);
205 AbstractFile sruAbstractFile = null;
207 for (AbstractFile sruFile : sruFiles) {
209 String sruFileName = tempDirPath + File.separator + sruFile.getId() +
"_" + sruFile.getName();
210 sruAbstractFile = sruFile;
213 ContentUtils.writeToFile(sruFile,
new File(sruFileName));
214 }
catch (IOException ex) {
215 this.addErrorMessage(Bundle.ExtractSru_process_errormsg_write_srudb_dat());
216 logger.log(Level.WARNING, String.format(
"Unable to write %s to temp directory. File name: %s", sruFile.getName(), sruFile), ex);
221 return sruAbstractFile;
234 void extractSruFiles(String sruExePath, String sruFile, String tempOutFile, String tempOutPath, String softwareHiveFile)
throws IOException {
235 final Path outputFilePath = Paths.get(tempOutPath, SRU_OUTPUT_FILE_NAME);
236 final Path errFilePath = Paths.get(tempOutPath, SRU_ERROR_FILE_NAME);
238 List<String> commandLine =
new ArrayList<>();
239 commandLine.add(sruExePath);
240 commandLine.add(
"-sr");
241 commandLine.add(sruFile);
242 commandLine.add(
"-s");
243 commandLine.add(softwareHiveFile);
244 commandLine.add(
"-db");
245 commandLine.add(tempOutFile);
247 ProcessBuilder processBuilder =
new ProcessBuilder(commandLine);
248 processBuilder.redirectOutput(outputFilePath.toFile());
249 processBuilder.redirectError(errFilePath.toFile());
251 ExecUtil.execute(processBuilder,
new DataSourceIngestModuleProcessTerminator(context,
true));
254 private String getPathForSruDumper() {
256 if (PlatformUtil.isWindowsOS()) {
257 path = Paths.get(SRU_TOOL_FOLDER, SRU_TOOL_NAME_WINDOWS);
259 if (
"Linux".equals(PlatformUtil.getOSName())) {
260 path = Paths.get(SRU_TOOL_FOLDER, SRU_TOOL_NAME_LINUX);
263 File sruToolFile = InstalledFileLocator.getDefault().locate(path.toString(),
264 ExtractSru.class.getPackage().getName(),
false);
265 if (sruToolFile != null) {
266 return sruToolFile.getAbsolutePath();
272 private void findSruExecutedFiles(String sruDb, Content dataSource) {
276 String sqlStatement =
"SELECT DISTINCT SUBSTR(LTRIM(IdBlob, '\\Device\\HarddiskVolume'), INSTR(LTRIM(IdBlob, '\\Device\\HarddiskVolume'), '\\')) "
277 +
" application_name, idBlob source_name FROM SruDbIdMapTable WHERE idType = 0 AND idBlob NOT LIKE '!!%'";
279 try (SQLiteDBConnect tempdbconnect =
new SQLiteDBConnect(
"org.sqlite.JDBC",
"jdbc:sqlite:" + sruDb);
280 ResultSet resultSet = tempdbconnect.executeQry(sqlStatement)) {
282 while (resultSet.next()) {
284 if (context.dataSourceIngestIsCancelled()) {
285 logger.log(Level.INFO,
"Cancelled SRU Artifact Creation.");
289 String applicationName = resultSet.getString(
"application_name");
290 String sourceName = resultSet.getString(
"source_name");
292 String normalizePathName = FilenameUtils.normalize(applicationName,
true);
293 String fileName = FilenameUtils.getName(normalizePathName);
294 String filePath = FilenameUtils.getPath(normalizePathName);
295 if (fileName.contains(
" [")) {
296 fileName = fileName.substring(0, fileName.indexOf(
" ["));
298 List<AbstractFile> sourceFiles;
300 sourceFiles = fileManager.
findFiles(dataSource, fileName, filePath);
301 for (AbstractFile sourceFile : sourceFiles) {
302 if (sourceFile.getParentPath().endsWith(filePath)) {
303 applicationFilesFound.put(sourceName.toLowerCase(), sourceFile);
307 }
catch (TskCoreException ex) {
308 logger.log(Level.WARNING, String.format(
"Error finding actual file %s. file may not exist", normalizePathName));
311 }
catch (SQLException ex) {
312 logger.log(Level.WARNING,
"Error while trying to read into a sqlite db.", ex);
317 private void createNetUsageArtifacts(String sruDb, AbstractFile sruAbstractFile) {
318 List<BlackboardArtifact> bba =
new ArrayList<>();
320 String sqlStatement =
"SELECT STRFTIME('%s', timestamp) ExecutionTime, b.application_name, b.Application_Name formatted_application_name, username User_Name, \n" +
321 " bytesSent, BytesRecvd \n" +
322 " FROM network_Usage a, SruDbIdMapTable s, exe_to_app b, userNames u\n" +
323 " WHERE s.idType = 0 and s.idIndex = appId and idblob = b.source_name and u.idindex = userid \n" +
324 " order by ExecutionTime;";
326 try (SQLiteDBConnect tempdbconnect =
new SQLiteDBConnect(
"org.sqlite.JDBC",
"jdbc:sqlite:" + sruDb);
327 ResultSet resultSet = tempdbconnect.executeQry(sqlStatement)) {
329 while (resultSet.next()) {
331 if (context.dataSourceIngestIsCancelled()) {
332 logger.log(Level.INFO,
"Cancelled SRU Net Usage Artifact Creation.");
336 String applicationName = resultSet.getString(
"Application_Name");
337 String formattedApplicationName = resultSet.getString(
"formatted_Application_name");
338 Long executionTime = Long.valueOf(resultSet.getInt(
"ExecutionTime"));
339 Long bytesSent = Long.valueOf(resultSet.getInt(
"bytesSent"));
340 Long bytesRecvd = Long.valueOf(resultSet.getInt(
"BytesRecvd"));
341 String userName = resultSet.getString(
"User_Name");
343 Collection<BlackboardAttribute> bbattributes = Arrays.asList(
344 new BlackboardAttribute(
345 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, getDisplayName(),
346 formattedApplicationName),
347 new BlackboardAttribute(
348 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_NAME, getDisplayName(),
350 new BlackboardAttribute(
351 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, getDisplayName(),
353 new BlackboardAttribute(
354 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_BYTES_SENT, getDisplayName(), bytesSent),
355 new BlackboardAttribute(
356 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_BYTES_RECEIVED, getDisplayName(), bytesRecvd),
357 new BlackboardAttribute(
358 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, getDisplayName(), NETWORK_USAGE_SOURCE_NAME));
361 BlackboardArtifact bbart = createArtifactWithAttributes(BlackboardArtifact.Type.TSK_PROG_RUN, sruAbstractFile, bbattributes);
363 BlackboardArtifact associateBbArtifact = createAssociatedArtifact(applicationName.toLowerCase(), bbart);
364 if (associateBbArtifact != null) {
365 bba.add(associateBbArtifact);
367 }
catch (TskCoreException ex) {
368 logger.log(Level.SEVERE,
"Exception Adding Artifact.", ex);
372 }
catch (SQLException ex) {
373 logger.log(Level.SEVERE,
"Error while trying to read into a sqlite db.", ex);
376 if (!context.dataSourceIngestIsCancelled()) {
381 private void createAppUsageArtifacts(String sruDb, AbstractFile sruAbstractFile) {
382 List<BlackboardArtifact> bba =
new ArrayList<>();
384 String sqlStatement =
"SELECT STRFTIME('%s', timestamp) ExecutionTime, b.Application_Name \n" +
385 " formatted_application_name, username User_Name \n" +
386 " FROM Application_Resource_Usage a, SruDbIdMapTable s, exe_to_app b, userNames u \n" +
387 " WHERE s.idType = 0 and s.idIndex = appId and idblob = b.source_name and u.idindex = userid \n" +
388 " order by ExecutionTime;";
390 try (SQLiteDBConnect tempdbconnect =
new SQLiteDBConnect(
"org.sqlite.JDBC",
"jdbc:sqlite:" + sruDb);
391 ResultSet resultSet = tempdbconnect.executeQry(sqlStatement)) {
393 while (resultSet.next()) {
395 if (context.dataSourceIngestIsCancelled()) {
396 logger.log(Level.INFO,
"Cancelled SRU Net Usage Artifact Creation.");
400 String formattedApplicationName = resultSet.getString(
"formatted_application_name");
401 Long executionTime = Long.valueOf(resultSet.getInt(
"ExecutionTime"));
402 String userName = resultSet.getString(
"User_Name");
404 Collection<BlackboardAttribute> bbattributes = Arrays.asList(
405 new BlackboardAttribute(
406 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, getDisplayName(),
407 formattedApplicationName),
408 new BlackboardAttribute(
409 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_NAME, getDisplayName(),
411 new BlackboardAttribute(
412 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, getDisplayName(),
414 new BlackboardAttribute(
415 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, getDisplayName(), APPLICATION_USAGE_SOURCE_NAME));
418 BlackboardArtifact bbart = createArtifactWithAttributes(BlackboardArtifact.Type.TSK_PROG_RUN, sruAbstractFile, bbattributes);
420 BlackboardArtifact associateBbArtifact = createAssociatedArtifact(formattedApplicationName.toLowerCase(), bbart);
421 if (associateBbArtifact != null) {
422 bba.add(associateBbArtifact);
424 }
catch (TskCoreException ex) {
425 logger.log(Level.SEVERE,
"Exception Adding Artifact.", ex);
429 }
catch (SQLException ex) {
430 logger.log(Level.SEVERE,
"Error while trying to read into a sqlite db.", ex);
433 if (!context.dataSourceIngestIsCancelled()) {
449 private BlackboardArtifact createAssociatedArtifact(String filePathName, BlackboardArtifact bba)
throws TskCoreException {
450 if (applicationFilesFound.containsKey(filePathName)) {
451 AbstractFile sourceFile = applicationFilesFound.get(filePathName);
452 return createAssociatedArtifact(sourceFile, bba);
List< AbstractFile > findFiles(String fileName)