23 package org.sleuthkit.autopsy.recentactivity;
25 import java.io.BufferedReader;
27 import java.io.FileInputStream;
28 import java.io.FileNotFoundException;
29 import java.io.FileReader;
30 import java.io.FileWriter;
31 import java.io.IOException;
32 import java.io.StringReader;
33 import java.text.ParseException;
34 import java.text.SimpleDateFormat;
35 import java.util.logging.Level;
36 import javax.xml.parsers.DocumentBuilder;
37 import javax.xml.parsers.DocumentBuilderFactory;
38 import javax.xml.parsers.ParserConfigurationException;
39 import org.apache.commons.io.FilenameUtils;
40 import org.openide.modules.InstalledFileLocator;
41 import org.openide.util.NbBundle;
49 import org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
50 import org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
51 import org.w3c.dom.Document;
52 import org.w3c.dom.Element;
53 import org.w3c.dom.Node;
54 import org.w3c.dom.NodeList;
55 import org.xml.sax.InputSource;
56 import org.xml.sax.SAXException;
57 import java.nio.file.Path;
58 import java.util.AbstractMap;
59 import java.util.ArrayList;
60 import java.util.Arrays;
61 import java.util.List;
62 import java.util.Collection;
63 import java.util.Date;
64 import java.util.HashMap;
66 import java.util.Scanner;
68 import java.util.HashSet;
69 import static java.util.Locale.US;
70 import static java.util.TimeZone.getTimeZone;
71 import org.openide.util.Lookup;
81 import static org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT;
83 import static org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT;
84 import static org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT;
85 import static org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED;
86 import static org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED;
87 import static org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_MODIFIED;
88 import static org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH;
90 import org.
sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
102 "RegRipperNotFound=Autopsy RegRipper executable not found.",
103 "RegRipperFullNotFound=Full version RegRipper executable not found.",
104 "Progress_Message_Analyze_Registry=Analyzing Registry Files",
105 "Shellbag_Artifact_Display_Name=Shell Bags",
106 "Shellbag_Key_Attribute_Display_Name=Key",
107 "Shellbag_Last_Write_Attribute_Display_Name=Last Write",
108 "Recently_Used_Artifacts_Office_Trustrecords=Stored in TrustRecords because Office security exception was granted",
109 "Recently_Used_Artifacts_ArcHistory=Recently opened by 7Zip",
110 "Recently_Used_Artifacts_Applets=Recently opened according to Applets registry key",
111 "Recently_Used_Artifacts_Mmc=Recently opened according to Windows Management Console MRU",
112 "Recently_Used_Artifacts_Winrar=Recently opened according to WinRAR MRU",
113 "Recently_Used_Artifacts_Officedocs=Recently opened according to Office MRU",
114 "Recently_Used_Artifacts_Adobe=Recently opened according to Adobe MRU",
115 "Recently_Used_Artifacts_Mediaplayer=Recently opened according to Media Player MRU"
117 class ExtractRegistry extends Extract {
119 private static final String USERNAME_KEY =
"Username";
120 private static final String SID_KEY =
"SID";
121 private static final String RID_KEY =
"RID";
122 private static final String ACCOUNT_CREATED_KEY =
"Account Created";
123 private static final String LAST_LOGIN_KEY =
"Last Login Date";
124 private static final String LOGIN_COUNT_KEY =
"Login Count";
125 private static final String FULL_NAME_KEY =
"Full Name";
126 private static final String USER_COMMENT_KEY =
"User Comment";
127 private static final String ACCOUNT_TYPE_KEY =
"Account Type";
128 private static final String NAME_KEY =
"Name";
129 private static final String PWD_RESET_KEY =
"Pwd Rest Date";
130 private static final String PWD_FAILE_KEY =
"Pwd Fail Date";
131 private static final String INTERNET_NAME_KEY =
"InternetName";
132 private static final String PWD_DOES_NOT_EXPIRE_KEY =
"Password does not expire";
133 private static final String ACCOUNT_DISABLED_KEY =
"Account Disabled";
134 private static final String PWD_NOT_REQUIRED_KEY =
"Password not required";
135 private static final String NORMAL_ACCOUNT_KEY =
"Normal user account";
136 private static final String HOME_DIRECTORY_REQUIRED_KEY =
"Home directory required";
137 private static final String TEMPORARY_DUPLICATE_ACCOUNT =
"Temporary duplicate account";
138 private static final String MNS_LOGON_ACCOUNT_KEY =
"MNS logon user account";
139 private static final String INTERDOMAIN_TRUST_ACCOUNT_KEY =
"Interdomain trust account";
140 private static final String WORKSTATION_TRUST_ACCOUNT =
"Workstation trust account";
141 private static final String SERVER_TRUST_ACCOUNT =
"Server trust account";
142 private static final String ACCOUNT_AUTO_LOCKED =
"Account auto locked";
143 private static final String PASSWORD_HINT =
"Password Hint";
145 private static final String[] PASSWORD_SETTINGS_FLAGS = {PWD_DOES_NOT_EXPIRE_KEY, PWD_NOT_REQUIRED_KEY};
146 private static final String[] ACCOUNT_SETTINGS_FLAGS = {ACCOUNT_AUTO_LOCKED, HOME_DIRECTORY_REQUIRED_KEY, ACCOUNT_DISABLED_KEY};
147 private static final String[] ACCOUNT_TYPE_FLAGS = {NORMAL_ACCOUNT_KEY, SERVER_TRUST_ACCOUNT, WORKSTATION_TRUST_ACCOUNT, INTERDOMAIN_TRUST_ACCOUNT_KEY, MNS_LOGON_ACCOUNT_KEY, TEMPORARY_DUPLICATE_ACCOUNT};
149 final private static UsbDeviceIdMapper USB_MAPPER =
new UsbDeviceIdMapper();
150 final private static String RIP_EXE =
"rip.exe";
151 final private static String RIP_PL =
"rip.pl";
152 final private static String RIP_PL_INCLUDE_FLAG =
"-I";
153 final private static int MS_IN_SEC = 1000;
154 final private static String NEVER_DATE =
"Never";
155 final private static String SECTION_DIVIDER =
"-------------------------";
156 final private static Logger logger = Logger.getLogger(ExtractRegistry.class.getName());
157 private final List<String> rrCmd =
new ArrayList<>();
158 private final List<String> rrFullCmd =
new ArrayList<>();
159 private final Path rrHome;
160 private final Path rrFullHome;
161 private Content dataSource;
162 private IngestJobContext context;
164 private static final String SHELLBAG_ARTIFACT_NAME =
"RA_SHELL_BAG";
165 private static final String SHELLBAG_ATTRIBUTE_LAST_WRITE =
"RA_SHELL_BAG_LAST_WRITE";
166 private static final String SHELLBAG_ATTRIBUTE_KEY=
"RA_SHELL_BAG_KEY";
168 BlackboardArtifact.Type shellBagArtifactType = null;
169 BlackboardAttribute.Type shellBagKeyAttributeType = null;
170 BlackboardAttribute.Type shellBagLastWriteAttributeType = null;
172 ExtractRegistry() throws IngestModuleException {
173 moduleName = NbBundle.getMessage(ExtractIE.class,
"ExtractRegistry.moduleName.text");
175 final File rrRoot = InstalledFileLocator.getDefault().locate(
"rr", ExtractRegistry.class.getPackage().getName(),
false);
176 if (rrRoot == null) {
177 throw new IngestModuleException(Bundle.RegRipperNotFound());
180 final File rrFullRoot = InstalledFileLocator.getDefault().locate(
"rr-full", ExtractRegistry.class.getPackage().getName(),
false);
181 if (rrFullRoot == null) {
182 throw new IngestModuleException(Bundle.RegRipperFullNotFound());
185 String executableToRun = RIP_EXE;
186 if (!PlatformUtil.isWindowsOS()) {
187 executableToRun = RIP_PL;
189 rrHome = rrRoot.toPath();
190 String rrPath = rrHome.resolve(executableToRun).toString();
191 rrFullHome = rrFullRoot.toPath();
193 if (!(
new File(rrPath).exists())) {
194 throw new IngestModuleException(Bundle.RegRipperNotFound());
196 String rrFullPath = rrFullHome.resolve(executableToRun).toString();
197 if (!(
new File(rrFullPath).exists())) {
198 throw new IngestModuleException(Bundle.RegRipperFullNotFound());
200 if (PlatformUtil.isWindowsOS()) {
202 rrFullCmd.add(rrFullPath);
205 File usrBin =
new File(
"/usr/bin/perl");
206 File usrLocalBin =
new File(
"/usr/local/bin/perl");
207 if (usrBin.canExecute() && usrBin.exists() && !usrBin.isDirectory()) {
208 perl =
"/usr/bin/perl";
209 }
else if (usrLocalBin.canExecute() && usrLocalBin.exists() && !usrLocalBin.isDirectory()) {
210 perl =
"/usr/local/bin/perl";
212 throw new IngestModuleException(
"perl not found in your system");
215 rrCmd.add(RIP_PL_INCLUDE_FLAG);
216 rrCmd.add(rrHome.toString());
219 rrFullCmd.add(RIP_PL_INCLUDE_FLAG);
220 rrFullCmd.add(rrFullHome.toString());
221 rrFullCmd.add(rrFullPath);
228 private List<AbstractFile> findRegistryFiles() {
229 List<AbstractFile> allRegistryFiles =
new ArrayList<>();
234 allRegistryFiles.addAll(fileManager.findFiles(dataSource,
"ntuser.dat"));
235 }
catch (TskCoreException ex) {
236 logger.log(Level.WARNING,
"Error fetching 'ntuser.dat' file.");
241 allRegistryFiles.addAll(fileManager.findFiles(dataSource,
"usrclass.dat"));
242 }
catch (TskCoreException ex) {
243 logger.log(Level.WARNING, String.format(
"Error finding 'usrclass.dat' files."), ex);
247 String[] regFileNames =
new String[]{
"system",
"software",
"security",
"sam"};
248 for (String regFileName : regFileNames) {
250 allRegistryFiles.addAll(fileManager.findFiles(dataSource, regFileName,
"/system32/config"));
251 }
catch (TskCoreException ex) {
252 String msg = NbBundle.getMessage(this.getClass(),
253 "ExtractRegistry.findRegFiles.errMsg.errReadingFile", regFileName);
254 logger.log(Level.WARNING, msg, ex);
255 this.addErrorMessage(this.getName() +
": " + msg);
258 return allRegistryFiles;
265 private void analyzeRegistryFiles() {
266 List<AbstractFile> allRegistryFiles = findRegistryFiles();
269 FileWriter logFile = null;
271 logFile =
new FileWriter(RAImageIngestModule.getRAOutputPath(currentCase,
"reg") + File.separator +
"regripper-info.txt");
272 }
catch (IOException ex) {
273 logger.log(Level.SEVERE, null, ex);
276 for (AbstractFile regFile : allRegistryFiles) {
277 String regFileName = regFile.getName();
278 long regFileId = regFile.getId();
279 String regFileNameLocal = RAImageIngestModule.getRATempPath(currentCase,
"reg") + File.separator + regFileName;
280 String outputPathBase = RAImageIngestModule.getRAOutputPath(currentCase,
"reg") + File.separator + regFileName +
"-regripper-" + Long.toString(regFileId);
281 File regFileNameLocalFile =
new File(regFileNameLocal);
283 ContentUtils.writeToFile(regFile, regFileNameLocalFile, context::dataSourceIngestIsCancelled);
284 }
catch (ReadContentInputStreamException ex) {
285 logger.log(Level.WARNING, String.format(
"Error reading registry file '%s' (id=%d).",
286 regFile.getName(), regFileId), ex);
287 this.addErrorMessage(
288 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
289 this.getName(), regFileName));
291 }
catch (IOException ex) {
292 logger.log(Level.SEVERE, String.format(
"Error writing temp registry file '%s' for registry file '%s' (id=%d).",
293 regFileNameLocal, regFile.getName(), regFileId), ex);
294 this.addErrorMessage(
295 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
296 this.getName(), regFileName));
300 if (context.dataSourceIngestIsCancelled()) {
305 if (logFile != null) {
306 logFile.write(Long.toString(regFileId) +
"\t" + regFile.getUniquePath() +
"\n");
308 }
catch (TskCoreException | IOException ex) {
309 logger.log(Level.SEVERE, null, ex);
312 logger.log(Level.INFO,
"{0}- Now getting registry information from {1}",
new Object[]{moduleName, regFileNameLocal});
313 RegOutputFiles regOutputFiles = ripRegistryFile(regFileNameLocal, outputPathBase);
314 if (context.dataSourceIngestIsCancelled()) {
319 if (regOutputFiles.autopsyPlugins.isEmpty() ==
false && parseAutopsyPluginOutput(regOutputFiles.autopsyPlugins, regFile) ==
false) {
320 this.addErrorMessage(
321 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.analyzeRegFiles.failedParsingResults",
322 this.getName(), regFileName));
326 if (!regOutputFiles.fullPlugins.isEmpty()) {
328 if (regFileNameLocal.toLowerCase().contains(
"sam") && parseSamPluginOutput(regOutputFiles.fullPlugins, regFile) ==
false) {
329 this.addErrorMessage(
330 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.analyzeRegFiles.failedParsingResults",
331 this.getName(), regFileName));
332 }
else if (regFileNameLocal.toLowerCase().contains(
"ntuser") || regFileNameLocal.toLowerCase().contains(
"usrclass")) {
334 List<ShellBag> shellbags = ShellBagParser.parseShellbagOutput(regOutputFiles.fullPlugins);
335 createShellBagArtifacts(regFile, shellbags);
336 createRecentlyUsedArtifacts(regOutputFiles.fullPlugins, regFile);
337 }
catch (IOException | TskCoreException ex) {
338 logger.log(Level.WARNING, String.format(
"Unable to get shell bags from file %s", regOutputFiles.fullPlugins), ex);
342 Report report = currentCase.addReport(regOutputFiles.fullPlugins,
343 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.parentModuleName.noSpace"),
344 "RegRipper " + regFile.getUniquePath(), regFile);
347 KeywordSearchService searchService = Lookup.getDefault().lookup(KeywordSearchService.class);
348 if (null == searchService) {
349 logger.log(Level.WARNING,
"Keyword search service not found. Report will not be indexed");
351 searchService.index(report);
354 }
catch (TskCoreException e) {
355 this.addErrorMessage(
"Error adding regripper output as Autopsy report: " + e.getLocalizedMessage());
359 regFileNameLocalFile.delete();
363 if (logFile != null) {
366 }
catch (IOException ex) {
367 logger.log(Level.SEVERE, null, ex);
378 private RegOutputFiles ripRegistryFile(String regFilePath, String outFilePathBase) {
379 String autopsyType =
"";
382 RegOutputFiles regOutputFiles =
new RegOutputFiles();
384 if (regFilePath.toLowerCase().contains(
"system")) {
385 autopsyType =
"autopsysystem";
387 }
else if (regFilePath.toLowerCase().contains(
"software")) {
388 autopsyType =
"autopsysoftware";
389 fullType =
"software";
390 }
else if (regFilePath.toLowerCase().contains(
"ntuser")) {
391 autopsyType =
"autopsyntuser";
393 }
else if (regFilePath.toLowerCase().contains(
"sam")) {
396 }
else if (regFilePath.toLowerCase().contains(
"security")) {
397 fullType =
"security";
398 }
else if (regFilePath.toLowerCase().contains(
"usrclass")) {
399 fullType =
"usrclass";
401 return regOutputFiles;
405 if (!autopsyType.isEmpty()) {
406 regOutputFiles.autopsyPlugins = outFilePathBase +
"-autopsy.txt";
407 String errFilePath = outFilePathBase +
"-autopsy.err.txt";
408 logger.log(Level.INFO,
"Writing RegRipper results to: {0}", regOutputFiles.autopsyPlugins);
409 executeRegRipper(rrCmd, rrHome, regFilePath, autopsyType, regOutputFiles.autopsyPlugins, errFilePath);
411 if (context.dataSourceIngestIsCancelled()) {
412 return regOutputFiles;
416 if (!fullType.isEmpty()) {
417 regOutputFiles.fullPlugins = outFilePathBase +
"-full.txt";
418 String errFilePath = outFilePathBase +
"-full.err.txt";
419 logger.log(Level.INFO,
"Writing Full RegRipper results to: {0}", regOutputFiles.fullPlugins);
420 executeRegRipper(rrFullCmd, rrFullHome, regFilePath, fullType, regOutputFiles.fullPlugins, errFilePath);
422 return regOutputFiles;
425 private void executeRegRipper(List<String> regRipperPath, Path regRipperHomeDir, String hiveFilePath, String hiveFileType, String outputFile, String errFile) {
427 List<String> commandLine =
new ArrayList<>();
428 for (String cmd : regRipperPath) {
429 commandLine.add(cmd);
431 commandLine.add(
"-r");
432 commandLine.add(hiveFilePath);
433 commandLine.add(
"-f");
434 commandLine.add(hiveFileType);
436 ProcessBuilder processBuilder =
new ProcessBuilder(commandLine);
437 processBuilder.directory(regRipperHomeDir.toFile());
438 processBuilder.redirectOutput(
new File(outputFile));
439 processBuilder.redirectError(
new File(errFile));
440 ExecUtil.execute(processBuilder,
new DataSourceIngestModuleProcessTerminator(context));
441 }
catch (IOException ex) {
442 logger.log(Level.SEVERE,
"Unable to run RegRipper", ex);
443 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.execRegRip.errMsg.failedAnalyzeRegFile", this.getName()));
456 private boolean parseAutopsyPluginOutput(String regFilePath, AbstractFile regFile) {
457 FileInputStream fstream = null;
458 List<BlackboardArtifact> newArtifacts =
new ArrayList<>();
461 File regfile =
new File(regFilePath);
462 fstream =
new FileInputStream(regfile);
463 String regString =
new Scanner(fstream,
"UTF-8").useDelimiter(
"\\Z").next();
464 String startdoc =
"<?xml version=\"1.0\"?><document>";
465 String result = regString.replaceAll(
"----------------------------------------",
"");
466 result = result.replaceAll(
"\\n",
"");
467 result = result.replaceAll(
"\\r",
"");
468 result = result.replaceAll(
"'",
"'");
469 result = result.replaceAll(
"&",
"&");
470 result = result.replace(
'\0',
' ');
471 String enddoc =
"</document>";
472 String stringdoc = startdoc + result + enddoc;
473 DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
474 Document doc = builder.parse(
new InputSource(
new StringReader(stringdoc)));
477 Element oroot = doc.getDocumentElement();
478 NodeList children = oroot.getChildNodes();
479 int len = children.getLength();
480 for (
int i = 0; i < len; i++) {
482 if (context.dataSourceIngestIsCancelled()) {
486 Element tempnode = (Element) children.item(i);
488 String dataType = tempnode.getNodeName();
489 NodeList timenodes = tempnode.getElementsByTagName(
"mtime");
491 if (timenodes.getLength() > 0) {
492 Element timenode = (Element) timenodes.item(0);
493 String etime = timenode.getTextContent();
495 if (etime != null && !etime.isEmpty()) {
497 mtime =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy").parse(etime).getTime();
498 String Tempdate = mtime.toString();
499 mtime = Long.valueOf(Tempdate) / MS_IN_SEC;
500 }
catch (ParseException ex) {
501 logger.log(Level.WARNING,
"Failed to parse epoch time when parsing the registry.", ex);
506 NodeList artroots = tempnode.getElementsByTagName(
"artifacts");
507 if (artroots.getLength() == 0) {
512 Element artroot = (Element) artroots.item(0);
513 NodeList myartlist = artroot.getChildNodes();
514 String parentModuleName = RecentActivityExtracterModuleFactory.getModuleName();
520 String systemRoot =
"";
521 String productId =
"";
522 String regOwner =
"";
524 Long installtime = null;
525 for (
int j = 0; j < myartlist.getLength(); j++) {
526 Node artchild = myartlist.item(j);
528 if (artchild.hasAttributes()) {
529 Element artnode = (Element) artchild;
531 String value = artnode.getTextContent();
533 value = value.trim();
535 String name = artnode.getAttribute(
"name");
545 version = version +
" " + value;
553 case "RegisteredOwner":
556 case "RegisteredOrganization":
560 if (value != null && !value.isEmpty()) {
562 installtime =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy").parse(value).getTime();
563 String Tempdate = installtime.toString();
564 installtime = Long.valueOf(Tempdate) / MS_IN_SEC;
565 }
catch (ParseException e) {
566 logger.log(Level.WARNING,
"RegRipper::Conversion on DateTime -> ", e);
576 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
577 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, version));
578 if (installtime != null) {
579 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, installtime));
581 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, parentModuleName, systemRoot));
582 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PRODUCT_ID, parentModuleName, productId));
583 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_OWNER, parentModuleName, regOwner));
584 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ORGANIZATION, parentModuleName, regOrg));
587 ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
588 if (results.isEmpty()) {
589 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
590 bbart.addAttributes(bbattributes);
592 newArtifacts.add(bbart);
594 results.get(0).addAttributes(bbattributes);
597 }
catch (TskCoreException ex) {
598 logger.log(Level.SEVERE,
"Error adding installed program artifact to blackboard.");
603 String procArch =
"";
605 for (
int j = 0; j < myartlist.getLength(); j++) {
606 Node artchild = myartlist.item(j);
608 if (artchild.hasAttributes()) {
609 Element artnode = (Element) artchild;
611 String value = artnode.getTextContent().trim();
612 String name = artnode.getAttribute(
"name");
617 case "PROCESSOR_ARCHITECTURE":
620 case "PROCESSOR_IDENTIFIER":
631 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
632 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VERSION, parentModuleName, os));
633 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE, parentModuleName, procArch));
634 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TEMP_DIR, parentModuleName, tempDir));
637 ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
638 if (results.isEmpty()) {
639 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
640 bbart.addAttributes(bbattributes);
642 newArtifacts.add(bbart);
644 results.get(0).addAttributes(bbattributes);
646 }
catch (TskCoreException ex) {
647 logger.log(Level.SEVERE,
"Error adding os info artifact to blackboard.");
651 String compName =
"";
653 for (
int j = 0; j < myartlist.getLength(); j++) {
654 Node artchild = myartlist.item(j);
656 if (artchild.hasAttributes()) {
657 Element artnode = (Element) artchild;
659 String value = artnode.getTextContent().trim();
660 String name = artnode.getAttribute(
"name");
662 if (name.equals(
"ComputerName")) {
664 }
else if (name.equals(
"Domain")) {
670 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
671 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, compName));
672 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, parentModuleName, domain));
675 ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
676 if (results.isEmpty()) {
677 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
678 bbart.addAttributes(bbattributes);
680 newArtifacts.add(bbart);
682 results.get(0).addAttributes(bbattributes);
684 }
catch (TskCoreException ex) {
685 logger.log(Level.SEVERE,
"Error adding os info artifact to blackboard.", ex);
689 for (
int j = 0; j < myartlist.getLength(); j++) {
690 Node artchild = myartlist.item(j);
692 if (artchild.hasAttributes()) {
693 Element artnode = (Element) artchild;
695 String value = artnode.getTextContent().trim();
696 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
709 Long usbMtime = Long.parseLong(artnode.getAttribute(
"mtime"));
710 usbMtime = Long.valueOf(usbMtime.toString());
712 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED);
713 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, usbMtime));
714 String dev = artnode.getAttribute(
"dev");
717 if (dev.toLowerCase().contains(
"vid")) {
718 USBInfo info = USB_MAPPER.parseAndLookup(dev);
719 if (info.getVendor() != null) {
720 make = info.getVendor();
722 if (info.getProduct() != null) {
723 model = info.getProduct();
726 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE, parentModuleName, make));
727 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL, parentModuleName, model));
728 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, value));
729 bbart.addAttributes(bbattributes);
731 newArtifacts.add(bbart);
732 }
catch (TskCoreException ex) {
733 logger.log(Level.SEVERE,
"Error adding device attached artifact to blackboard.", ex);
737 Long itemMtime = null;
739 String mTimeAttr = artnode.getAttribute(
"mtime");
740 if (mTimeAttr != null && !mTimeAttr.isEmpty()) {
741 itemMtime =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy").parse(mTimeAttr).getTime();
742 itemMtime /= MS_IN_SEC;
744 }
catch (ParseException ex) {
745 logger.log(Level.SEVERE,
"Failed to parse epoch time for installed program artifact.", ex);
749 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, value));
750 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, itemMtime));
751 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_INSTALLED_PROG);
752 bbart.addAttributes(bbattributes);
754 newArtifacts.add(bbart);
755 }
catch (TskCoreException ex) {
756 logger.log(Level.SEVERE,
"Error adding installed program artifact to blackboard.", ex);
760 String officeName = artnode.getAttribute(
"name");
763 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT);
766 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, parentModuleName, mtime));
768 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, officeName));
769 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE, parentModuleName, value));
770 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, artnode.getNodeName()));
771 bbart.addAttributes(bbattributes);
773 newArtifacts.add(bbart);
774 }
catch (TskCoreException ex) {
775 logger.log(Level.SEVERE,
"Error adding recent object artifact to blackboard.", ex);
779 case "ProcessorArchitecture":
796 String homeDir = value;
797 String sid = artnode.getAttribute(
"sid");
798 String username = artnode.getAttribute(
"username");
799 BlackboardArtifact bbart = null;
802 ArrayList<BlackboardArtifact> existingArtifacts = currentCase.getSleuthkitCase().getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
803 for (BlackboardArtifact artifact : existingArtifacts) {
804 if (artifact.getDataSource().getId() == regFile.getDataSourceObjectId()) {
805 BlackboardAttribute attribute = artifact.getAttribute(
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID));
806 if (attribute != null && attribute.getValueString().equals(sid)) {
812 }
catch (TskCoreException ex) {
813 logger.log(Level.SEVERE,
"Error getting existing os account artifact", ex);
817 bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
818 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
819 parentModuleName, username));
820 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID,
821 parentModuleName, sid));
822 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
823 parentModuleName, homeDir));
826 BlackboardAttribute bbattr = bbart.getAttribute(
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_NAME));
828 if (bbattr == null) {
829 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
830 parentModuleName, username));
832 bbattr = bbart.getAttribute(
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH));
833 if (bbattr == null) {
834 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
835 parentModuleName, homeDir));
838 bbart.addAttributes(bbattributes);
839 newArtifacts.add(bbart);
840 }
catch (TskCoreException ex) {
841 logger.log(Level.SEVERE,
"Error adding account artifact to blackboard.", ex);
845 case "NtuserNetwork":
847 String localPath = artnode.getAttribute(
"localPath");
848 String remoteName = value;
849 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_REMOTE_DRIVE);
850 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCAL_PATH,
851 parentModuleName, localPath));
852 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REMOTE_PATH,
853 parentModuleName, remoteName));
854 bbart.addAttributes(bbattributes);
855 newArtifacts.add(bbart);
856 }
catch (TskCoreException ex) {
857 logger.log(Level.SEVERE,
"Error adding network artifact to blackboard.", ex);
861 String adapter = artnode.getAttribute(
"adapter");
863 Long lastWriteTime = Long.parseLong(artnode.getAttribute(
"writeTime"));
864 lastWriteTime = Long.valueOf(lastWriteTime.toString());
865 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SSID, parentModuleName, value));
866 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, lastWriteTime));
867 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, adapter));
868 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_WIFI_NETWORK);
869 bbart.addAttributes(bbattributes);
870 newArtifacts.add(bbart);
871 }
catch (TskCoreException ex) {
872 logger.log(Level.SEVERE,
"Error adding SSID artifact to blackboard.", ex);
882 logger.log(Level.SEVERE,
"Unrecognized node name: {0}", dataType);
891 }
catch (FileNotFoundException ex) {
892 logger.log(Level.WARNING, String.format(
"Error finding the registry file: %s", regFilePath), ex);
893 }
catch (SAXException ex) {
894 logger.log(Level.WARNING, String.format(
"Error parsing the registry XML: %s", regFilePath), ex);
895 }
catch (IOException ex) {
896 logger.log(Level.WARNING, String.format(
"Error building the document parser: %s", regFilePath), ex);
897 }
catch (ParserConfigurationException ex) {
898 logger.log(Level.WARNING, String.format(
"Error configuring the registry parser: %s", regFilePath), ex);
901 if (fstream != null) {
904 }
catch (IOException ex) {
907 postArtifacts(newArtifacts);
921 private boolean parseSamPluginOutput(String regFilePath, AbstractFile regAbstractFile) {
922 File regfile =
new File(regFilePath);
923 List<BlackboardArtifact> newArtifacts =
new ArrayList<>();
924 try (BufferedReader bufferedReader =
new BufferedReader(
new FileReader(regfile))) {
926 String userInfoSection =
"User Information";
927 String previousLine = null;
928 String line = bufferedReader.readLine();
929 Set<Map<String, String>> userSet =
new HashSet<>();
930 Map<String, List<String>> groupMap = null;
931 while (line != null) {
932 if (line.contains(SECTION_DIVIDER) && previousLine != null && previousLine.contains(userInfoSection)) {
933 readUsers(bufferedReader, userSet);
936 if (line.contains(SECTION_DIVIDER) && previousLine != null && previousLine.contains(
"Group Membership Information")) {
937 groupMap = readGroups(bufferedReader);
941 line = bufferedReader.readLine();
943 Map<String, Map<String, String>> userInfoMap =
new HashMap<>();
945 for (Map<String, String> userInfo : userSet) {
946 userInfoMap.put(userInfo.get(SID_KEY), userInfo);
949 List<BlackboardArtifact> existingOsAccounts = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
950 for (BlackboardArtifact osAccount : existingOsAccounts) {
952 if (osAccount.getDataSource().getId() == regAbstractFile.getDataSourceObjectId()) {
953 BlackboardAttribute existingUserId = osAccount.getAttribute(
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID));
954 if (existingUserId != null) {
955 String userID = existingUserId.getValueString().trim();
956 Map<String, String> userInfo = userInfoMap.remove(userID);
958 if (userInfo != null) {
959 osAccount.addAttributes(getAttributesForAccount(userInfo, groupMap.get(userID),
true, regAbstractFile));
966 for (Map<String, String> userInfo : userInfoMap.values()) {
967 BlackboardArtifact bbart = regAbstractFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
968 bbart.addAttributes(getAttributesForAccount(userInfo, groupMap.get(userInfo.get(SID_KEY)),
false, regAbstractFile));
970 newArtifacts.add(bbart);
973 }
catch (FileNotFoundException ex) {
974 logger.log(Level.WARNING,
"Error finding the registry file.", ex);
975 }
catch (IOException ex) {
976 logger.log(Level.WARNING,
"Error building the document parser: {0}", ex);
977 }
catch (ParseException ex) {
978 logger.log(Level.WARNING,
"Error parsing the the date from the registry file", ex);
979 }
catch (TskCoreException ex) {
980 logger.log(Level.WARNING,
"Error updating TSK_OS_ACCOUNT artifacts to include newly parsed data.", ex);
982 postArtifacts(newArtifacts);
998 Collection<BlackboardAttribute> getAttributesForAccount(Map<String, String> userInfo, List<String> groupList,
boolean existingUser, AbstractFile regAbstractFile)
throws ParseException {
999 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
1001 SimpleDateFormat regRipperTimeFormat =
new SimpleDateFormat(
"EEE MMM dd HH:mm:ss yyyy 'Z'");
1002 regRipperTimeFormat.setTimeZone(getTimeZone(
"GMT"));
1004 if (!existingUser) {
1005 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID,
1006 getRAModuleName(), userInfo.get(SID_KEY)));
1008 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
1009 this.moduleName, userInfo.get(USERNAME_KEY)));
1012 String value = userInfo.get(ACCOUNT_CREATED_KEY);
1013 if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
1014 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
1015 getRAModuleName(), regRipperTimeFormat.parse(value).getTime() / MS_IN_SEC));
1018 value = userInfo.get(LAST_LOGIN_KEY);
1019 if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
1020 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
1021 getRAModuleName(), regRipperTimeFormat.parse(value).getTime() / MS_IN_SEC));
1024 value = userInfo.get(LOGIN_COUNT_KEY);
1025 if (value != null && !value.isEmpty()) {
1026 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT,
1027 getRAModuleName(), Integer.parseInt(value)));
1030 value = userInfo.get(ACCOUNT_TYPE_KEY);
1031 if (value != null && !value.isEmpty()) {
1032 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE,
1033 getRAModuleName(), value));
1036 value = userInfo.get(USER_COMMENT_KEY);
1037 if (value != null && !value.isEmpty()) {
1038 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DESCRIPTION,
1039 getRAModuleName(), value));
1042 value = userInfo.get(NAME_KEY);
1043 if (value != null && !value.isEmpty()) {
1044 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
1045 getRAModuleName(), value));
1048 value = userInfo.get(INTERNET_NAME_KEY);
1049 if (value != null && !value.isEmpty()) {
1052 Case.getCurrentCaseThrows()
1054 .getCommunicationsManager()
1055 .createAccountFileInstance(Account.Type.EMAIL,
1056 value, getRAModuleName(), regAbstractFile);
1057 }
catch (NoCurrentCaseException | TskCoreException ex) {
1058 logger.log(Level.SEVERE,
1059 String.format(
"Error adding email account with value "
1060 +
"%s, to the case database for file %s [objId=%d]",
1061 value, regAbstractFile.getName(), regAbstractFile.getId()), ex);
1064 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_EMAIL,
1065 getRAModuleName(), value));
1068 value = userInfo.get(FULL_NAME_KEY);
1069 if (value != null && !value.isEmpty()) {
1070 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DISPLAY_NAME,
1071 getRAModuleName(), value));
1074 value = userInfo.get(PWD_RESET_KEY);
1075 if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
1076 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_PASSWORD_RESET,
1077 getRAModuleName(), regRipperTimeFormat.parse(value).getTime() / MS_IN_SEC));
1080 value = userInfo.get(PASSWORD_HINT);
1081 if (value != null && !value.isEmpty()) {
1082 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PASSWORD_HINT,
1083 getRAModuleName(), value));
1086 value = userInfo.get(PWD_FAILE_KEY);
1087 if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
1088 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_PASSWORD_FAIL,
1089 getRAModuleName(), regRipperTimeFormat.parse(value).getTime() / MS_IN_SEC));
1092 String settingString =
"";
1093 for (String setting : PASSWORD_SETTINGS_FLAGS) {
1094 if (userInfo.containsKey(setting)) {
1095 settingString += setting +
", ";
1099 if (!settingString.isEmpty()) {
1100 settingString = settingString.substring(0, settingString.length() - 2);
1101 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PASSWORD_SETTINGS,
1102 getRAModuleName(), settingString));
1106 for (String setting : ACCOUNT_SETTINGS_FLAGS) {
1107 if (userInfo.containsKey(setting)) {
1108 settingString += setting +
", ";
1112 if (!settingString.isEmpty()) {
1113 settingString = settingString.substring(0, settingString.length() - 2);
1114 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ACCOUNT_SETTINGS,
1115 getRAModuleName(), settingString));
1119 for (String setting : ACCOUNT_TYPE_FLAGS) {
1120 if (userInfo.containsKey(setting)) {
1121 settingString += setting +
", ";
1125 if (!settingString.isEmpty()) {
1126 settingString = settingString.substring(0, settingString.length() - 2);
1127 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_FLAG,
1128 getRAModuleName(), settingString));
1131 if (groupList != null && groupList.isEmpty()) {
1133 for (String group : groupList) {
1134 groups += group +
", ";
1137 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_GROUPS,
1138 getRAModuleName(), groups.substring(0, groups.length() - 2)));
1141 return bbattributes;
1155 private void readUsers(BufferedReader bufferedReader, Set<Map<String, String>> users) throws IOException {
1156 String line = bufferedReader.readLine();
1158 String userName =
"";
1159 String user_rid =
"";
1160 while (line != null && !line.contains(SECTION_DIVIDER)) {
1162 if (line.contains(USERNAME_KEY)) {
1163 String regx = USERNAME_KEY +
"\\s*?:";
1164 String userNameAndIdString = line.replaceAll(regx,
"");
1165 userName = userNameAndIdString.substring(0, userNameAndIdString.lastIndexOf(
'[')).trim();
1166 user_rid = userNameAndIdString.substring(userNameAndIdString.lastIndexOf(
'['), userNameAndIdString.lastIndexOf(
']'));
1167 }
else if (line.contains(SID_KEY) && !userName.isEmpty()) {
1168 Map.Entry<String, String> entry = getSAMKeyValue(line);
1170 HashMap<String, String> userInfo =
new HashMap<>();
1171 userInfo.put(USERNAME_KEY, userName);
1172 userInfo.put(RID_KEY, user_rid);
1173 userInfo.put(entry.getKey(), entry.getValue());
1176 line = bufferedReader.readLine();
1177 while (line != null && !line.isEmpty()) {
1178 entry = getSAMKeyValue(line);
1179 if (entry != null) {
1180 userInfo.put(entry.getKey(), entry.getValue());
1182 line = bufferedReader.readLine();
1184 users.add(userInfo);
1188 line = bufferedReader.readLine();
1201 private void createRecentlyUsedArtifacts(String regFileName, AbstractFile regFile)
throws FileNotFoundException, IOException {
1202 File regfile =
new File(regFileName);
1203 try (BufferedReader reader =
new BufferedReader(
new FileReader(regfile))) {
1204 String line = reader.readLine();
1205 while (line != null) {
1208 if (line.matches(
"^adoberdr v.*")) {
1209 parseAdobeMRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Adobe());
1210 }
else if (line.matches(
"^mpmru v.*")) {
1211 parseMediaPlayerMRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Mediaplayer());
1212 }
else if (line.matches(
"^trustrecords v.*")) {
1213 parseOfficeTrustRecords(regFile, reader, Bundle.Recently_Used_Artifacts_Office_Trustrecords());
1214 }
else if (line.matches(
"^ArcHistory:")) {
1215 parse7ZipMRU(regFile, reader, Bundle.Recently_Used_Artifacts_ArcHistory());
1216 }
else if (line.matches(
"^applets v.*")) {
1217 parseGenericMRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Applets());
1218 }
else if (line.matches(
"^mmc v.*")) {
1219 parseGenericMRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Mmc());
1220 }
else if (line.matches(
"^winrar v.*")) {
1221 parseWinRARMRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Winrar());
1222 }
else if (line.matches(
"^officedocs2010 v.*")) {
1223 parseOfficeDocs2010MRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Officedocs());
1225 line = reader.readLine();
1241 private void parseAdobeMRUList(AbstractFile regFile, BufferedReader reader, String comment)
throws FileNotFoundException, IOException {
1242 List<BlackboardArtifact> bbartifacts =
new ArrayList<>();
1243 String line = reader.readLine();
1244 SimpleDateFormat adobePluginDateFormat =
new SimpleDateFormat(
"yyyyMMddHHmmssZ", US);
1245 Long adobeUsedTime = Long.valueOf(0);
1246 while (!line.contains(SECTION_DIVIDER)) {
1247 line = reader.readLine();
1249 if (line.matches(
"^Key name,file name,sDate,uFileSize,uPageCount")) {
1250 line = reader.readLine();
1253 while (!line.contains(SECTION_DIVIDER)) {
1256 String tokens[] = line.split(
",(?=([^\"]*\"[^\"]*\")*[^\"]*$)");
1257 String fileName = tokens[1].substring(0, tokens[1].length() -1);
1258 fileName = fileName.replace(
"\"",
"");
1259 if (fileName.charAt(0) ==
'/') {
1260 fileName = fileName.substring(1,fileName.length() - 1);
1261 fileName = fileName.replaceFirst(
"/",
":/");
1264 if (tokens.length > 2) {
1267 String fileUsedTime = tokens[2].replaceAll(
"'",
"");
1268 Date usedDate = adobePluginDateFormat.parse(fileUsedTime);
1269 adobeUsedTime = usedDate.getTime()/1000;
1270 }
catch (ParseException ex) {
1273 logger.log(Level.WARNING, String.format(
"Failed to parse date/time %s for adobe file artifact.", tokens[2]), ex);
1276 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
1277 attributes.add(
new BlackboardAttribute(TSK_PATH, getName(), fileName));
1278 attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, getName(), adobeUsedTime));
1279 attributes.add(
new BlackboardAttribute(TSK_COMMENT, getName(), comment));
1280 BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes);
1282 bbartifacts.add(bba);
1283 fileName = fileName.replace(
"\0",
"");
1284 bba = createAssociatedArtifact(FilenameUtils.normalize(fileName,
true), bba);
1286 bbartifacts.add(bba);
1289 line = reader.readLine();
1294 if (!bbartifacts.isEmpty()) {
1295 postArtifacts(bbartifacts);
1310 private void parseMediaPlayerMRUList(AbstractFile regFile, BufferedReader reader, String comment)
throws FileNotFoundException, IOException {
1311 List<BlackboardArtifact> bbartifacts =
new ArrayList<>();
1312 String line = reader.readLine();
1313 while (!line.contains(SECTION_DIVIDER)) {
1314 line = reader.readLine();
1316 if (line.contains(
"LastWrite")) {
1317 line = reader.readLine();
1320 while (!line.contains(SECTION_DIVIDER) && !line.contains(
"RecentFileList has no values.")) {
1322 String tokens[] = line.split(
"> ");
1323 String fileName = tokens[1];
1324 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
1325 attributes.add(
new BlackboardAttribute(TSK_PATH, getName(), fileName));
1326 attributes.add(
new BlackboardAttribute(TSK_COMMENT, getName(), comment));
1327 BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes);
1329 bbartifacts.add(bba);
1330 bba = createAssociatedArtifact(fileName, bba);
1332 bbartifacts.add(bba);
1333 bba = createAssociatedArtifact(FilenameUtils.normalize(fileName,
true), bba);
1335 bbartifacts.add(bba);
1339 line = reader.readLine();
1344 if (!bbartifacts.isEmpty()) {
1345 postArtifacts(bbartifacts);
1360 private void parseGenericMRUList(AbstractFile regFile, BufferedReader reader, String comment)
throws FileNotFoundException, IOException {
1361 List<BlackboardArtifact> bbartifacts =
new ArrayList<>();
1362 String line = reader.readLine();
1363 while (!line.contains(SECTION_DIVIDER)) {
1364 line = reader.readLine();
1366 if (line.contains(
"LastWrite")) {
1367 line = reader.readLine();
1370 while (!line.contains(SECTION_DIVIDER) && !line.isEmpty() && !line.contains(
"Applets")) {
1372 String tokens[] = line.split(
"> ");
1373 String fileName = tokens[1];
1374 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
1375 attributes.add(
new BlackboardAttribute(TSK_PATH, getName(), fileName));
1376 attributes.add(
new BlackboardAttribute(TSK_COMMENT, getName(), comment));
1377 BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes);
1379 bbartifacts.add(bba);
1380 bba = createAssociatedArtifact(FilenameUtils.normalize(fileName,
true), bba);
1382 bbartifacts.add(bba);
1385 line = reader.readLine();
1390 if (!bbartifacts.isEmpty()) {
1391 postArtifacts(bbartifacts);
1406 private void parseWinRARMRUList(AbstractFile regFile, BufferedReader reader, String comment)
throws FileNotFoundException, IOException {
1407 List<BlackboardArtifact> bbartifacts =
new ArrayList<>();
1408 String line = reader.readLine();
1409 while (!line.contains(SECTION_DIVIDER)) {
1410 line = reader.readLine();
1412 if (line.contains(
"LastWrite")) {
1413 line = reader.readLine();
1416 if (!line.isEmpty()) {
1417 while (!line.contains(SECTION_DIVIDER)) {
1419 String tokens[] = line.split(
"> ");
1420 String fileName = tokens[1];
1421 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
1422 attributes.add(
new BlackboardAttribute(TSK_PATH, getName(), fileName));
1423 attributes.add(
new BlackboardAttribute(TSK_COMMENT, getName(), comment));
1424 BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes);
1426 bbartifacts.add(bba);
1427 bba = createAssociatedArtifact(FilenameUtils.normalize(fileName,
true), bba);
1429 bbartifacts.add(bba);
1432 line = reader.readLine();
1438 if (!bbartifacts.isEmpty()) {
1439 postArtifacts(bbartifacts);
1454 private void parse7ZipMRU(AbstractFile regFile, BufferedReader reader, String comment)
throws FileNotFoundException, IOException {
1455 List<BlackboardArtifact> bbartifacts =
new ArrayList<>();
1456 String line = reader.readLine();
1458 if (!line.contains(
"PathHistory:")) {
1459 while (!line.contains(
"PathHistory:") && !line.isEmpty()) {
1462 String fileName = line;
1463 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
1464 attributes.add(
new BlackboardAttribute(TSK_PATH, getName(), fileName));
1465 attributes.add(
new BlackboardAttribute(TSK_COMMENT, getName(), comment));
1466 BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes);
1468 bbartifacts.add(bba);
1469 bba = createAssociatedArtifact(FilenameUtils.normalize(fileName,
true), bba);
1471 bbartifacts.add(bba);
1474 line = reader.readLine();
1478 if (!bbartifacts.isEmpty()) {
1479 postArtifacts(bbartifacts);
1494 private void parseOfficeDocs2010MRUList(AbstractFile regFile, BufferedReader reader, String comment)
throws FileNotFoundException, IOException {
1495 List<BlackboardArtifact> bbartifacts =
new ArrayList<>();
1496 String line = reader.readLine();
1500 while (!line.contains(SECTION_DIVIDER)) {
1501 line = reader.readLine();
1503 line = reader.readLine();
1504 while (!line.contains(SECTION_DIVIDER)) {
1507 String tokens[] = line.split(
"\\|");
1508 Long docDate = Long.valueOf(tokens[0]);
1509 String fileNameTokens[] = tokens[4].split(
" - ");
1510 String fileName = fileNameTokens[1];
1511 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
1512 attributes.add(
new BlackboardAttribute(TSK_PATH, getName(), fileName));
1513 attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, getName(), docDate));
1514 attributes.add(
new BlackboardAttribute(TSK_COMMENT, getName(), comment));
1515 BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes);
1517 bbartifacts.add(bba);
1518 bba = createAssociatedArtifact(FilenameUtils.normalize(fileName,
true), bba);
1520 bbartifacts.add(bba);
1523 line = reader.readLine();
1526 if (!bbartifacts.isEmpty()) {
1527 postArtifacts(bbartifacts);
1542 private void parseOfficeTrustRecords(AbstractFile regFile, BufferedReader reader, String comment)
throws FileNotFoundException, IOException {
1543 String userProfile = regFile.getParentPath();
1544 userProfile = userProfile.substring(0, userProfile.length() - 1);
1545 List<BlackboardArtifact> bbartifacts =
new ArrayList<>();
1546 SimpleDateFormat pluginDateFormat =
new SimpleDateFormat(
"EEE MMM dd HH:mm:ss yyyy", US);
1547 Long usedTime = Long.valueOf(0);
1548 String line = reader.readLine();
1549 while (!line.contains(SECTION_DIVIDER)) {
1550 line = reader.readLine();
1552 usedTime = Long.valueOf(0);
1553 if (!line.contains(
"**") && !line.contains(
"----------") && !line.contains(
"LastWrite")
1554 && !line.contains(SECTION_DIVIDER) && !line.isEmpty()) {
1558 String fileName = null;
1559 String tokens[] = line.split(
" : ");
1560 fileName = tokens[1];
1561 fileName = fileName.replace(
"%USERPROFILE%", userProfile);
1564 String fileUsedTime = tokens[0].replaceAll(
" Z",
"");
1565 Date usedDate = pluginDateFormat.parse(fileUsedTime);
1566 usedTime = usedDate.getTime()/1000;
1567 }
catch (ParseException ex) {
1570 logger.log(Level.WARNING, String.format(
"Failed to parse date/time %s for TrustRecords artifact.", tokens[0]), ex);
1572 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
1573 attributes.add(
new BlackboardAttribute(TSK_PATH, getName(), fileName));
1574 attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, getName(), usedTime));
1575 attributes.add(
new BlackboardAttribute(TSK_COMMENT, getName(), comment));
1576 BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes);
1578 bbartifacts.add(bba);
1579 bba = createAssociatedArtifact(FilenameUtils.normalize(fileName,
true), bba);
1581 bbartifacts.add(bba);
1587 if (!bbartifacts.isEmpty()) {
1588 postArtifacts(bbartifacts);
1601 private BlackboardArtifact createAssociatedArtifact(String filePathName, BlackboardArtifact bba) {
1603 String fileName = FilenameUtils.getName(filePathName);
1604 String filePath = FilenameUtils.getPath(filePathName);
1605 List<AbstractFile> sourceFiles;
1607 sourceFiles = fileManager.
findFiles(dataSource, fileName, filePath);
1608 if (!sourceFiles.isEmpty()) {
1609 for (AbstractFile sourceFile : sourceFiles) {
1610 if (sourceFile.getParentPath().endsWith(filePath)) {
1611 Collection<BlackboardAttribute> bbattributes2 =
new ArrayList<>();
1612 bbattributes2.addAll(Arrays.asList(
1613 new BlackboardAttribute(TSK_ASSOCIATED_ARTIFACT, this.getName(),
1614 bba.getArtifactID())));
1616 BlackboardArtifact associatedObjectBba = createArtifactWithAttributes(TSK_ASSOCIATED_OBJECT, sourceFile, bbattributes2);
1617 if (associatedObjectBba != null) {
1618 return associatedObjectBba;
1623 }
catch (TskCoreException ex) {
1626 logger.log(Level.WARNING, String.format(
"Error finding actual file %s. file may not exist", filePathName));
1640 void createShellBagArtifacts(AbstractFile regFile, List<ShellBag> shellbags)
throws TskCoreException {
1641 List<BlackboardArtifact> artifacts =
new ArrayList<>();
1643 for (ShellBag bag : shellbags) {
1644 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
1645 BlackboardArtifact artifact = regFile.newArtifact(getShellBagArtifact().getTypeID());
1646 attributes.add(
new BlackboardAttribute(TSK_PATH, getName(), bag.getResource()));
1647 attributes.add(
new BlackboardAttribute(getKeyAttribute(), getName(), bag.getKey()));
1650 time = bag.getLastWrite();
1652 attributes.add(
new BlackboardAttribute(getLastWriteAttribute(), getName(), time));
1655 time = bag.getModified();
1657 attributes.add(
new BlackboardAttribute(TSK_DATETIME_MODIFIED, getName(), time));
1660 time = bag.getCreated();
1662 attributes.add(
new BlackboardAttribute(TSK_DATETIME_CREATED, getName(), time));
1665 time = bag.getAccessed();
1667 attributes.add(
new BlackboardAttribute(TSK_DATETIME_ACCESSED, getName(), time));
1670 artifact.addAttributes(attributes);
1672 artifacts.add(artifact);
1675 postArtifacts(artifacts);
1687 private BlackboardArtifact.Type getShellBagArtifact() throws TskCoreException {
1688 if (shellBagArtifactType == null) {
1689 shellBagArtifactType = tskCase.getArtifactType(SHELLBAG_ARTIFACT_NAME);
1691 if(shellBagArtifactType == null) {
1693 tskCase.addBlackboardArtifactType(SHELLBAG_ARTIFACT_NAME, Bundle.Shellbag_Artifact_Display_Name());
1694 }
catch (TskDataException ex) {
1696 logger.log(Level.INFO, String.format(
"%s may have already been defined for this case", SHELLBAG_ARTIFACT_NAME));
1699 shellBagArtifactType = tskCase.getArtifactType(SHELLBAG_ARTIFACT_NAME);
1703 return shellBagArtifactType;
1714 private BlackboardAttribute.Type getLastWriteAttribute() throws TskCoreException {
1715 if (shellBagLastWriteAttributeType == null) {
1717 shellBagLastWriteAttributeType = tskCase.addArtifactAttributeType(SHELLBAG_ATTRIBUTE_LAST_WRITE,
1718 BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME,
1719 Bundle.Shellbag_Last_Write_Attribute_Display_Name());
1720 }
catch (TskDataException ex) {
1722 shellBagLastWriteAttributeType = tskCase.getAttributeType(SHELLBAG_ATTRIBUTE_LAST_WRITE);
1725 return shellBagLastWriteAttributeType;
1736 private BlackboardAttribute.Type getKeyAttribute() throws TskCoreException {
1737 if (shellBagKeyAttributeType == null) {
1739 shellBagKeyAttributeType = tskCase.addArtifactAttributeType(SHELLBAG_ATTRIBUTE_KEY,
1740 BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING,
1741 Bundle.Shellbag_Key_Attribute_Display_Name());
1742 }
catch (TskDataException ex) {
1744 shellBagKeyAttributeType = tskCase.getAttributeType(SHELLBAG_ATTRIBUTE_KEY);
1747 return shellBagKeyAttributeType;
1759 Map<String, List<String>> readGroups(BufferedReader bufferedReader)
throws IOException {
1760 Map<String, List<String>> groupMap =
new HashMap<>();
1762 String line = bufferedReader.readLine();
1765 String groupName = null;
1767 while (line != null && !line.contains(SECTION_DIVIDER)) {
1769 if (line.contains(
"Group Name")) {
1770 String value = line.replaceAll(
"Group Name\\s*?:",
"").trim();
1771 groupName = (value.replaceAll(
"\\[\\d*?\\]",
"")).trim();
1772 int startIndex = value.indexOf(
'[');
1773 int endIndex = value.indexOf(
']');
1775 if (startIndex != -1 && endIndex != -1) {
1776 String countStr = value.substring(startIndex + 1, endIndex);
1777 userCount = Integer.parseInt(countStr);
1779 }
else if (line.matches(
"Users\\s*?:")) {
1780 for (
int i = 0; i < userCount; i++) {
1781 line = bufferedReader.readLine();
1783 String sid = line.trim();
1784 List<String> groupList = groupMap.get(sid);
1785 if (groupList == null) {
1786 groupList =
new ArrayList<>();
1787 groupMap.put(sid, groupList);
1789 groupList.add(groupName);
1794 line = bufferedReader.readLine();
1808 private Map.Entry<String, String> getSAMKeyValue(String line) {
1809 int index = line.indexOf(
':');
1810 Map.Entry<String, String> returnValue = null;
1812 String value = null;
1815 key = line.substring(0, index).trim();
1816 if (index + 1 < line.length()) {
1817 value = line.substring(index + 1).trim();
1822 }
else if (line.contains(
"-->")) {
1823 key = line.replace(
"-->",
"").trim();
1828 returnValue =
new AbstractMap.SimpleEntry<>(key, value);
1835 public void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) {
1836 this.dataSource = dataSource;
1837 this.context = context;
1839 progressBar.progress(Bundle.Progress_Message_Analyze_Registry());
1840 analyzeRegistryFiles();
1849 public String autopsyPlugins =
"";
1850 public String fullPlugins =
"";
synchronized List< AbstractFile > findFiles(String fileName)