Autopsy 4.22.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
ExtractSru.java
Go to the documentation of this file.
1/*
2 *
3 * Autopsy Forensic Browser
4 *
5 * Copyright 2020-2021 Basis Technology Corp.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19package org.sleuthkit.autopsy.recentactivity;
20
21import java.io.File;
22import java.io.FileNotFoundException;
23import java.io.IOException;
24import java.nio.file.Path;
25import java.nio.file.Paths;
26import java.sql.ResultSet;
27import java.sql.SQLException;
28import java.util.ArrayList;
29import java.util.Arrays;
30import java.util.Collection;
31import java.util.HashMap;
32import java.util.List;
33import java.util.logging.Level;
34import java.util.Map;
35import org.apache.commons.io.FilenameUtils;
36import org.openide.modules.InstalledFileLocator;
37import org.openide.util.NbBundle.Messages;
38import org.sleuthkit.autopsy.casemodule.Case;
39import org.sleuthkit.autopsy.casemodule.services.FileManager;
40import org.sleuthkit.autopsy.coreutils.ExecUtil;
41import org.sleuthkit.autopsy.coreutils.Logger;
42import org.sleuthkit.autopsy.coreutils.PlatformUtil;
43import org.sleuthkit.autopsy.coreutils.SQLiteDBConnect;
44import org.sleuthkit.autopsy.datamodel.ContentUtils;
45import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProcessTerminator;
46import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress;
47import org.sleuthkit.autopsy.ingest.IngestJobContext;
48import org.sleuthkit.datamodel.AbstractFile;
49import org.sleuthkit.datamodel.BlackboardArtifact;
50import org.sleuthkit.datamodel.BlackboardAttribute;
51import org.sleuthkit.datamodel.Content;
52import org.sleuthkit.datamodel.TskCoreException;
53
58final class ExtractSru extends Extract {
59
60 private static final Logger logger = Logger.getLogger(ExtractSru.class.getName());
61
62 private static final String APPLICATION_USAGE_SOURCE_NAME = "System Resource Usage - Application Usage"; //NON-NLS
63 private static final String NETWORK_USAGE_SOURCE_NAME = "System Resource Usage - Network Usage";
64 private static final String SRU_TOOL_FOLDER = "markmckinnon"; //NON-NLS
65 private static final String SRU_TOOL_NAME_X64_WINDOWS = "mm_artifact_parser_x64_win.exe"; //NON-NLS
66 private static final String SRU_TOOL_NAME_X64_LINUX = "mm_artifact_parser_x64_linux"; //NON-NLS
67 private static final String SRU_TOOL_NAME_X64_MACOS = "mm_artifact_parser_x64_macos"; //NON-NLS
68 private static final String SRU_TOOL_NAME_AARCH64_LINUX = "mm_artifact_parser_aarch64_linux"; //NON-NLS
69 private static final String SRU_TOOL_NAME_AARCH64_MACOS = "mm_artifact_parser_aarch64_macos"; //NON-NLS
70 private static final String SRU_OUTPUT_FILE_NAME = "Output.txt"; //NON-NLS
71 private static final String SRU_ERROR_FILE_NAME = "Error.txt"; //NON-NLS
72
73 private static final Map<String, AbstractFile> applicationFilesFound = new HashMap<>();
74 private final IngestJobContext context;
75
76 @Messages({
77 "ExtractSru_module_name=System Resource Usage Analyzer"
78 })
79 ExtractSru(IngestJobContext context) {
80 super(Bundle.ExtractSru_module_name(), context);
81 this.context = context;
82 }
83
84 @Messages({
85 "ExtractSru_error_finding_export_srudb_program=Error finding export_srudb program",
86 "ExtractSru_process_error_executing_export_srudb_program=Error running export_srudb program"
87 })
88
89 @Override
90 void process(Content dataSource, DataSourceIngestModuleProgress progressBar) {
91
92 String modOutPath = Case.getCurrentCase().getModuleDirectory() + File.separator + "sru";
93 File dir = new File(modOutPath);
94 if (dir.exists() == false) {
95 dir.mkdirs();
96 }
97
98 String tempDirPath = RAImageIngestModule.getRATempPath(Case.getCurrentCase(), "sru", context.getJobId()); //NON-NLS
99 String softwareHiveFileName = getSoftwareHiveFile(dataSource, tempDirPath);
100
101 if (softwareHiveFileName == null) {
102 return;
103 }
104
105 AbstractFile sruAbstractFile = getSruFile(dataSource, tempDirPath);
106
107 if (sruAbstractFile == null) {
108 return; //If we cannot find the srudb.dat file we cannot proceed which is ok
109 }
110
111 final String sruDumper = getPathForSruDumper();
112 if (sruDumper == null) {
113 this.addErrorMessage(Bundle.ExtractSru_error_finding_export_srudb_program());
114 logger.log(Level.SEVERE, "Error finding export_srudb program"); //NON-NLS
115 return; //If we cannot find the export_srudb program we cannot proceed
116 }
117
118 if (context.dataSourceIngestIsCancelled()) {
119 return;
120 }
121
122 try {
123 String modOutFile = modOutPath + File.separator + sruAbstractFile.getId() + "_srudb.db3";
124 String sruFileName = tempDirPath + File.separator + sruAbstractFile.getId() + "_" + sruAbstractFile.getName();
125
126 extractSruFiles(sruDumper, sruFileName, modOutFile, tempDirPath, softwareHiveFileName);
127
128 findSruExecutedFiles(modOutFile, dataSource);
129
130 createNetUsageArtifacts(modOutFile, sruAbstractFile);
131 createAppUsageArtifacts(modOutFile, sruAbstractFile);
132 } catch (IOException ex) {
133 logger.log(Level.SEVERE, "Error processing SRUDB.dat file", ex); //NON-NLS=
134 this.addErrorMessage(Bundle.ExtractSru_process_error_executing_export_srudb_program());
135 }
136 }
137
138 @Messages({
139 "ExtractSru_process_errormsg_find_software_hive=Unable to find SOFTWARE HIVE file",
140 "ExtractSru_process_errormsg_write_software_hive=Unable to write SOFTWARE HIVE file"
141 })
142
151 String getSoftwareHiveFile(Content dataSource, String tempDirPath) {
152 FileManager fileManager = Case.getCurrentCase().getServices().getFileManager();
153
154 List<AbstractFile> softwareHiveFiles;
155
156 try {
157 softwareHiveFiles = fileManager.findFiles(dataSource, "SOFTWARE"); //NON-NLS
158 } catch (TskCoreException ex) {
159 this.addErrorMessage(Bundle.ExtractSru_process_errormsg_find_software_hive());
160 logger.log(Level.WARNING, "Unable to find SOFTWARE HIVE file.", ex); //NON-NLS
161 return null; // No need to continue
162 }
163
164 String softwareHiveFileName = null;
165
166 for (AbstractFile softwareFile : softwareHiveFiles) {
167
168 if (softwareFile.getParentPath().endsWith("/config/")) {
169 softwareHiveFileName = tempDirPath + File.separator + softwareFile.getId() + "_" + softwareFile.getName();
170
171 try {
172 ContentUtils.writeToFile(softwareFile, new File(softwareHiveFileName));
173 } catch (IOException ex) {
174 this.addErrorMessage(Bundle.ExtractSru_process_errormsg_find_software_hive());
175 logger.log(Level.WARNING, String.format("Unable to write %s to temp directory. File name: %s", softwareFile.getName(), softwareFile), ex); //NON-NLS
176 return null;
177 }
178 }
179 }
180 return softwareHiveFileName;
181 }
182
183 @Messages({
184 "ExtractSru_process_errormsg_find_srudb_dat=Unable to find srudb.dat file",
185 "ExtractSru_process_errormsg_write_srudb_dat=Unable to write srudb.dat file"
186 })
195 AbstractFile getSruFile(Content dataSource, String tempDirPath) {
196 FileManager fileManager = Case.getCurrentCase().getServices().getFileManager();
197
198 List<AbstractFile> sruFiles;
199
200 try {
201 sruFiles = fileManager.findFiles(dataSource, "SRUDB.DAT"); //NON-NLS
202 } catch (TskCoreException ex) {
203 this.addErrorMessage(Bundle.ExtractSru_process_errormsg_find_srudb_dat());
204 logger.log(Level.WARNING, "Unable to find SRUDB.DAT file.", ex); //NON-NLS
205 return null; // No need to continue
206 }
207
208 AbstractFile sruAbstractFile = null;
209
210 for (AbstractFile sruFile : sruFiles) {
211
212 String sruFileName = tempDirPath + File.separator + sruFile.getId() + "_" + sruFile.getName();
213 sruAbstractFile = sruFile;
214
215 try {
216 ContentUtils.writeToFile(sruFile, new File(sruFileName));
217 } catch (IOException ex) {
218 this.addErrorMessage(Bundle.ExtractSru_process_errormsg_write_srudb_dat());
219 logger.log(Level.WARNING, String.format("Unable to write %s to temp directory. File name: %s", sruFile.getName(), sruFile), ex); //NON-NLS
220 return null;
221 }
222
223 }
224 return sruAbstractFile;
225 }
226
237 void extractSruFiles(String sruExePath, String sruFile, String tempOutFile, String tempOutPath, String softwareHiveFile) throws IOException {
238 final Path outputFilePath = Paths.get(tempOutPath, SRU_OUTPUT_FILE_NAME);
239 final Path errFilePath = Paths.get(tempOutPath, SRU_ERROR_FILE_NAME);
240
241 List<String> commandLine = new ArrayList<>();
242 commandLine.add(sruExePath);
243 commandLine.add("-a");
244 commandLine.add("sru");
245 commandLine.add("-sr");
246 commandLine.add(sruFile); //NON-NLS
247 commandLine.add("-sh");
248 commandLine.add(softwareHiveFile);
249 commandLine.add("-db");
250 commandLine.add(tempOutFile);
251
252 ProcessBuilder processBuilder = new ProcessBuilder(commandLine);
253 processBuilder.redirectOutput(outputFilePath.toFile());
254 processBuilder.redirectError(errFilePath.toFile());
255
256 ExecUtil.execute(processBuilder, new DataSourceIngestModuleProcessTerminator(context, true));
257 }
258
259 private String getPathForSruDumper() {
260 Path path = null;
261 if (PlatformUtil.isWindowsOS()) {
262 path = Paths.get(SRU_TOOL_FOLDER, SRU_TOOL_NAME_X64_WINDOWS);
263 } else if (PlatformUtil.isLinuxOS()) {
264 if ("aarch64".equals(PlatformUtil.getOSArch())) {
265 path = Paths.get(SRU_TOOL_FOLDER, SRU_TOOL_NAME_AARCH64_LINUX);
266 } else {
267 path = Paths.get(SRU_TOOL_FOLDER, SRU_TOOL_NAME_X64_LINUX);
268 }
269 } else if (PlatformUtil.isMacOS()) {
270 if ("aarch64".equals(PlatformUtil.getOSArch())) {
271 path = Paths.get(SRU_TOOL_FOLDER, SRU_TOOL_NAME_AARCH64_MACOS);
272 } else {
273 path = Paths.get(SRU_TOOL_FOLDER, SRU_TOOL_NAME_X64_MACOS);
274 }
275 }
276 File sruToolFile = InstalledFileLocator.getDefault().locate(path.toString(),
277 ExtractSru.class.getPackage().getName(), false);
278 if (sruToolFile != null) {
279 return sruToolFile.getAbsolutePath();
280 }
281
282 return null;
283 }
284
285 private void findSruExecutedFiles(String sruDb, Content dataSource) {
286
287 org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager();
288
289 String sqlStatement = "SELECT DISTINCT SUBSTR(LTRIM(IdBlob, '\\Device\\HarddiskVolume'), INSTR(LTRIM(IdBlob, '\\Device\\HarddiskVolume'), '\\')) "
290 + " application_name, idBlob source_name FROM SruDbIdMapTable WHERE idType = 0 AND idBlob NOT LIKE '!!%'"; //NON-NLS
291
292 try (SQLiteDBConnect tempdbconnect = new SQLiteDBConnect("org.sqlite.JDBC", "jdbc:sqlite:" + sruDb); //NON-NLS
293 ResultSet resultSet = tempdbconnect.executeQry(sqlStatement)) {
294
295 while (resultSet.next()) {
296
297 if (context.dataSourceIngestIsCancelled()) {
298 logger.log(Level.INFO, "Cancelled SRU Artifact Creation."); //NON-NLS
299 return;
300 }
301
302 String applicationName = resultSet.getString("application_name"); //NON-NLS
303 String sourceName = resultSet.getString("source_name"); //NON-NLS
304
305 String normalizePathName = FilenameUtils.normalize(applicationName, true);
306 String fileName = FilenameUtils.getName(normalizePathName);
307 String filePath = FilenameUtils.getPath(normalizePathName);
308 if (fileName.contains(" [")) {
309 fileName = fileName.substring(0, fileName.indexOf(" ["));
310 }
311 List<AbstractFile> sourceFiles;
312 try {
313 sourceFiles = fileManager.findFiles(dataSource, fileName, filePath); //NON-NLS
314 for (AbstractFile sourceFile : sourceFiles) {
315 if (sourceFile.getParentPath().endsWith(filePath)) {
316 applicationFilesFound.put(sourceName.toLowerCase(), sourceFile);
317 }
318 }
319
320 } catch (TskCoreException ex) {
321 logger.log(Level.WARNING, String.format("Error finding actual file %s. file may not exist", normalizePathName)); //NON-NLS
322 }
323 }
324 } catch (SQLException ex) {
325 logger.log(Level.WARNING, "Error while trying to read into a sqlite db.", ex);//NON-NLS
326 }
327
328 }
329
330 private void createNetUsageArtifacts(String sruDb, AbstractFile sruAbstractFile) {
331 List<BlackboardArtifact> bba = new ArrayList<>();
332
333 String sqlStatement = "SELECT STRFTIME('%s', timestamp) ExecutionTime, b.application_name, b.Application_Name formatted_application_name, username User_Name, \n" +
334 " bytesSent, BytesRecvd \n" +
335 " FROM network_Usage a, SruDbIdMapTable s, exe_to_app b, userNames u\n" +
336 " WHERE s.idType = 0 and s.idIndex = appId and idblob = b.source_name and u.idindex = userid \n" +
337 " order by ExecutionTime;"; //NON-NLS
338
339 try (SQLiteDBConnect tempdbconnect = new SQLiteDBConnect("org.sqlite.JDBC", "jdbc:sqlite:" + sruDb); //NON-NLS
340 ResultSet resultSet = tempdbconnect.executeQry(sqlStatement)) {
341
342 while (resultSet.next()) {
343
344 if (context.dataSourceIngestIsCancelled()) {
345 logger.log(Level.INFO, "Cancelled SRU Net Usage Artifact Creation."); //NON-NLS
346 return;
347 }
348
349 String applicationName = resultSet.getString("Application_Name"); //NON-NLS
350 String formattedApplicationName = resultSet.getString("formatted_Application_name");
351 Long executionTime = Long.valueOf(resultSet.getInt("ExecutionTime")); //NON-NLS
352 Long bytesSent = Long.valueOf(resultSet.getInt("bytesSent")); //NON-NLS
353 Long bytesRecvd = Long.valueOf(resultSet.getInt("BytesRecvd")); //NON-NLS
354 String userName = resultSet.getString("User_Name"); //NON-NLS
355
356 Collection<BlackboardAttribute> bbattributes = Arrays.asList(
357 new BlackboardAttribute(
358 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, getDisplayName(),
359 formattedApplicationName),//NON-NLS
360 new BlackboardAttribute(
361 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_NAME, getDisplayName(),
362 userName),
363 new BlackboardAttribute(
364 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, getDisplayName(),
365 executionTime),
366 new BlackboardAttribute(
367 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_BYTES_SENT, getDisplayName(), bytesSent),
368 new BlackboardAttribute(
369 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_BYTES_RECEIVED, getDisplayName(), bytesRecvd),
370 new BlackboardAttribute(
371 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, getDisplayName(), NETWORK_USAGE_SOURCE_NAME));
372
373 try {
374 BlackboardArtifact bbart = createArtifactWithAttributes(BlackboardArtifact.Type.TSK_PROG_RUN, sruAbstractFile, bbattributes);
375 bba.add(bbart);
376 BlackboardArtifact associateBbArtifact = createAssociatedArtifact(applicationName.toLowerCase(), bbart);
377 if (associateBbArtifact != null) {
378 bba.add(associateBbArtifact);
379 }
380 } catch (TskCoreException ex) {
381 logger.log(Level.SEVERE, "Exception Adding Artifact.", ex);//NON-NLS
382 }
383 }
384
385 } catch (SQLException ex) {
386 logger.log(Level.SEVERE, "Error while trying to read into a sqlite db.", ex);//NON-NLS
387 }
388
389 if (!context.dataSourceIngestIsCancelled()) {
390 postArtifacts(bba);
391 }
392 }
393
394 private void createAppUsageArtifacts(String sruDb, AbstractFile sruAbstractFile) {
395 List<BlackboardArtifact> bba = new ArrayList<>();
396
397 String sqlStatement = "SELECT STRFTIME('%s', timestamp) ExecutionTime, b.Application_Name \n" +
398 " formatted_application_name, username User_Name \n" +
399 " FROM Application_Resource_Usage a, SruDbIdMapTable s, exe_to_app b, userNames u \n" +
400 " WHERE s.idType = 0 and s.idIndex = appId and idblob = b.source_name and u.idindex = userid \n" +
401 " order by ExecutionTime;"; //NON-NLS
402
403 try (SQLiteDBConnect tempdbconnect = new SQLiteDBConnect("org.sqlite.JDBC", "jdbc:sqlite:" + sruDb); //NON-NLS
404 ResultSet resultSet = tempdbconnect.executeQry(sqlStatement)) {
405
406 while (resultSet.next()) {
407
408 if (context.dataSourceIngestIsCancelled()) {
409 logger.log(Level.INFO, "Cancelled SRU Net Usage Artifact Creation."); //NON-NLS
410 return;
411 }
412
413 String formattedApplicationName = resultSet.getString("formatted_application_name");
414 Long executionTime = Long.valueOf(resultSet.getInt("ExecutionTime")); //NON-NLS
415 String userName = resultSet.getString("User_Name");
416
417 Collection<BlackboardAttribute> bbattributes = Arrays.asList(
418 new BlackboardAttribute(
419 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, getDisplayName(),
420 formattedApplicationName),//NON-NLS
421 new BlackboardAttribute(
422 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_NAME, getDisplayName(),
423 userName),
424 new BlackboardAttribute(
425 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, getDisplayName(),
426 executionTime),
427 new BlackboardAttribute(
428 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, getDisplayName(), APPLICATION_USAGE_SOURCE_NAME));
429
430 try {
431 BlackboardArtifact bbart = createArtifactWithAttributes(BlackboardArtifact.Type.TSK_PROG_RUN, sruAbstractFile, bbattributes);
432 bba.add(bbart);
433 BlackboardArtifact associateBbArtifact = createAssociatedArtifact(formattedApplicationName.toLowerCase(), bbart);
434 if (associateBbArtifact != null) {
435 bba.add(associateBbArtifact);
436 }
437 } catch (TskCoreException ex) {
438 logger.log(Level.SEVERE, "Exception Adding Artifact.", ex);//NON-NLS
439 }
440 }
441
442 } catch (SQLException ex) {
443 logger.log(Level.SEVERE, "Error while trying to read into a sqlite db.", ex);//NON-NLS
444 }
445
446 if (!context.dataSourceIngestIsCancelled()) {
447 postArtifacts(bba);
448 }
449
450 }
451
462 private BlackboardArtifact createAssociatedArtifact(String filePathName, BlackboardArtifact bba) throws TskCoreException {
463 if (applicationFilesFound.containsKey(filePathName)) {
464 AbstractFile sourceFile = applicationFilesFound.get(filePathName);
465 return createAssociatedArtifact(sourceFile, bba);
466 }
467
468 return null;
469 }
470
471}
List< AbstractFile > findFiles(String fileName)

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.