23 package org.sleuthkit.autopsy.recentactivity;
25 import java.io.BufferedReader;
27 import org.openide.util.NbBundle;
30 import java.io.FileInputStream;
31 import java.io.FileNotFoundException;
32 import java.io.IOException;
33 import java.io.InputStreamReader;
34 import java.text.ParseException;
35 import java.text.SimpleDateFormat;
36 import java.util.ArrayList;
37 import java.util.List;
39 import java.util.HashSet;
40 import java.util.logging.Level;
42 import java.util.Collection;
43 import java.util.Scanner;
44 import org.openide.modules.InstalledFileLocator;
50 import org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
52 import org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
63 class ExtractIE
extends Extract {
65 private static final Logger logger = Logger.getLogger(ExtractIE.class.getName());
66 private final IngestServices services = IngestServices.getInstance();
67 private final String moduleTempResultsDir;
68 private String PASCO_LIB_PATH;
69 private final String JAVA_PATH;
70 private static final SimpleDateFormat dateFormatter =
new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
71 private Content dataSource;
72 private IngestJobContext context;
75 moduleName = NbBundle.getMessage(ExtractIE.class,
"ExtractIE.moduleName.text");
76 moduleTempResultsDir = RAImageIngestModule.getRATempPath(Case.getCurrentCase(),
"IE") + File.separator +
"results";
77 JAVA_PATH = PlatformUtil.getJavaPath();
81 public void process(Content dataSource, IngestJobContext context) {
82 this.dataSource = dataSource;
83 this.context = context;
93 private void getBookmark() {
95 List<AbstractFile> favoritesFiles;
97 favoritesFiles = fileManager.
findFiles(dataSource,
"%.url",
"Favorites");
98 }
catch (TskCoreException ex) {
99 logger.log(Level.WARNING,
"Error fetching 'url' files for Internet Explorer bookmarks.", ex);
100 this.addErrorMessage(
101 NbBundle.getMessage(
this.getClass(),
"ExtractIE.getBookmark.errMsg.errGettingBookmarks",
106 if (favoritesFiles.isEmpty()) {
107 logger.log(Level.INFO,
"Didn't find any IE bookmark files.");
112 for (AbstractFile fav : favoritesFiles) {
113 if (fav.getSize() == 0) {
117 if (context.dataSourceIngestIsCancelled()) {
121 String url = getURLFromIEBookmarkFile(fav);
123 String name = fav.getName();
124 Long datetime = fav.getCrtime();
125 String Tempdate = datetime.toString();
126 datetime = Long.valueOf(Tempdate);
127 String domain = Util.extractDomain(url);
129 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
130 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
131 NbBundle.getMessage(
this.getClass(),
132 "ExtractIE.parentModuleName.noSpace"), url));
133 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE,
134 NbBundle.getMessage(
this.getClass(),
135 "ExtractIE.parentModuleName.noSpace"), name));
136 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
137 NbBundle.getMessage(
this.getClass(),
138 "ExtractIE.parentModuleName.noSpace"), datetime));
139 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
140 NbBundle.getMessage(
this.getClass(),
141 "ExtractIE.parentModuleName.noSpace"),
142 NbBundle.getMessage(
this.getClass(),
"ExtractIE.moduleName.text")));
143 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
144 NbBundle.getMessage(
this.getClass(),
145 "ExtractIE.parentModuleName.noSpace"), domain));
146 this.addArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK, fav, bbattributes);
148 services.fireModuleDataEvent(
new ModuleDataEvent(
149 NbBundle.getMessage(
this.getClass(),
"ExtractIE.parentModuleName"), BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK));
152 private String getURLFromIEBookmarkFile(AbstractFile fav) {
153 BufferedReader reader =
new BufferedReader(
new InputStreamReader(
new ReadContentInputStream(fav)));
154 String line, url =
"";
156 line = reader.readLine();
157 while (null != line) {
160 if (line.startsWith(
"URL")) {
161 url = line.substring(line.indexOf(
"=") + 1);
164 line = reader.readLine();
166 }
catch (IOException ex) {
167 logger.log(Level.WARNING,
"Failed to read from content: " + fav.getName(), ex);
168 this.addErrorMessage(
169 NbBundle.getMessage(
this.getClass(),
"ExtractIE.getURLFromIEBmkFile.errMsg", this.getName(),
171 }
catch (IndexOutOfBoundsException ex) {
172 logger.log(Level.WARNING,
"Failed while getting URL of IE bookmark. Unexpected format of the bookmark file: " + fav.getName(), ex);
173 this.addErrorMessage(
174 NbBundle.getMessage(
this.getClass(),
"ExtractIE.getURLFromIEBmkFile.errMsg2", this.getName(),
179 }
catch (IOException ex) {
180 logger.log(Level.WARNING,
"Failed to close reader.", ex);
190 private void getCookie() {
192 List<AbstractFile> cookiesFiles;
194 cookiesFiles = fileManager.
findFiles(dataSource,
"%.txt",
"Cookies");
195 }
catch (TskCoreException ex) {
196 logger.log(Level.WARNING,
"Error getting cookie files for IE");
197 this.addErrorMessage(
198 NbBundle.getMessage(
this.getClass(),
"ExtractIE.getCookie.errMsg.errGettingFile", this.getName()));
202 if (cookiesFiles.isEmpty()) {
203 logger.log(Level.INFO,
"Didn't find any IE cookies files.");
208 for (AbstractFile cookiesFile : cookiesFiles) {
209 if (context.dataSourceIngestIsCancelled()) {
212 if (cookiesFile.getSize() == 0) {
216 byte[] t =
new byte[(int) cookiesFile.getSize()];
218 final int bytesRead = cookiesFile.read(t, 0, cookiesFile.getSize());
219 }
catch (TskCoreException ex) {
220 logger.log(Level.WARNING,
"Error reading bytes of Internet Explorer cookie.", ex);
221 this.addErrorMessage(
222 NbBundle.getMessage(
this.getClass(),
"ExtractIE.getCookie.errMsg.errReadingIECookie",
223 this.getName(), cookiesFile.getName()));
226 String cookieString =
new String(t);
227 String[] values = cookieString.split(
"\n");
228 String url = values.length > 2 ? values[2] :
"";
229 String value = values.length > 1 ? values[1] :
"";
230 String name = values.length > 0 ? values[0] :
"";
231 Long datetime = cookiesFile.getCrtime();
232 String tempDate = datetime.toString();
233 datetime = Long.valueOf(tempDate);
234 String domain = Util.extractDomain(url);
236 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
237 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
238 NbBundle.getMessage(
this.getClass(),
239 "ExtractIE.parentModuleName.noSpace"), url));
240 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME,
241 NbBundle.getMessage(
this.getClass(),
242 "ExtractIE.parentModuleName.noSpace"), datetime));
243 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
244 NbBundle.getMessage(
this.getClass(),
245 "ExtractIE.parentModuleName.noSpace"), (name != null) ? name :
""));
246 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE,
247 NbBundle.getMessage(
this.getClass(),
248 "ExtractIE.parentModuleName.noSpace"), value));
249 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
250 NbBundle.getMessage(
this.getClass(),
251 "ExtractIE.parentModuleName.noSpace"),
252 NbBundle.getMessage(
this.getClass(),
"ExtractIE.moduleName.text")));
253 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
254 NbBundle.getMessage(
this.getClass(),
255 "ExtractIE.parentModuleName.noSpace"), domain));
256 this.addArtifact(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes);
258 services.fireModuleDataEvent(
new ModuleDataEvent(
259 NbBundle.getMessage(
this.getClass(),
"ExtractIE.parentModuleName"), BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE));
265 private void getHistory() {
266 logger.log(Level.INFO,
"Pasco results path: {0}", moduleTempResultsDir);
267 boolean foundHistory =
false;
269 final File pascoRoot = InstalledFileLocator.getDefault().locate(
"pasco2", ExtractIE.class.getPackage().getName(),
false);
270 if (pascoRoot == null) {
271 this.addErrorMessage(
272 NbBundle.getMessage(
this.getClass(),
"ExtractIE.getHistory.errMsg.unableToGetHist", this.getName()));
273 logger.log(Level.SEVERE,
"Error finding pasco program ");
277 final String pascoHome = pascoRoot.getAbsolutePath();
278 logger.log(Level.INFO,
"Pasco2 home: {0}", pascoHome);
280 PASCO_LIB_PATH = pascoHome + File.separator +
"pasco2.jar" + File.pathSeparator
281 + pascoHome + File.separator +
"*";
283 File resultsDir =
new File(moduleTempResultsDir);
288 List<AbstractFile> indexFiles;
290 indexFiles = fileManager.
findFiles(dataSource,
"index.dat");
291 }
catch (TskCoreException ex) {
292 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"ExtractIE.getHistory.errMsg.errGettingHistFiles",
294 logger.log(Level.WARNING,
"Error fetching 'index.data' files for Internet Explorer history.");
298 if (indexFiles.isEmpty()) {
299 String msg = NbBundle.getMessage(this.getClass(),
"ExtractIE.getHistory.errMsg.noHistFiles");
300 logger.log(Level.INFO, msg);
306 String indexFileName;
307 for (AbstractFile indexFile : indexFiles) {
313 indexFileName =
"index" + Integer.toString((
int) indexFile.getId()) +
".dat";
315 temps = RAImageIngestModule.getRATempPath(currentCase,
"IE") + File.separator + indexFileName;
316 File datFile =
new File(temps);
317 if (context.dataSourceIngestIsCancelled()) {
321 ContentUtils.writeToFile(indexFile, datFile, context::dataSourceIngestIsCancelled);
322 }
catch (IOException e) {
323 logger.log(Level.WARNING,
"Error while trying to write index.dat file " + datFile.getAbsolutePath(), e);
324 this.addErrorMessage(
325 NbBundle.getMessage(
this.getClass(),
"ExtractIE.getHistory.errMsg.errWriteFile", this.getName(),
326 datFile.getAbsolutePath()));
330 String filename =
"pasco2Result." + indexFile.getId() +
".txt";
331 boolean bPascProcSuccess = executePasco(temps, filename);
332 if (context.dataSourceIngestIsCancelled()) {
338 if (bPascProcSuccess) {
339 parsePascoOutput(indexFile, filename);
345 logger.log(Level.WARNING,
"pasco execution failed on: {0}",
this.getName());
346 this.addErrorMessage(
347 NbBundle.getMessage(
this.getClass(),
"ExtractIE.getHistory.errMsg.errProcHist", this.getName()));
352 services.fireModuleDataEvent(
new ModuleDataEvent(
353 NbBundle.getMessage(
this.getClass(),
"ExtractIE.parentModuleName"), BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY));
365 private boolean executePasco(String indexFilePath, String outputFileName) {
366 boolean success =
true;
368 final String outputFileFullPath = moduleTempResultsDir + File.separator + outputFileName;
369 final String errFileFullPath = moduleTempResultsDir + File.separator + outputFileName +
".err";
370 logger.log(Level.INFO,
"Writing pasco results to: {0}", outputFileFullPath);
371 List<String> commandLine =
new ArrayList<>();
372 commandLine.add(JAVA_PATH);
373 commandLine.add(
"-cp");
374 commandLine.add(PASCO_LIB_PATH);
375 commandLine.add(
"isi.pasco2.Main");
376 commandLine.add(
"-T");
377 commandLine.add(
"history");
378 commandLine.add(indexFilePath);
379 ProcessBuilder processBuilder =
new ProcessBuilder(commandLine);
380 processBuilder.redirectOutput(
new File(outputFileFullPath));
381 processBuilder.redirectError(
new File(errFileFullPath));
391 ExecUtil.execute(processBuilder,
new DataSourceIngestModuleProcessTerminator(context));
393 }
catch (IOException ex) {
395 logger.log(Level.SEVERE,
"Unable to execute Pasco to process Internet Explorer web history.", ex);
407 private void parsePascoOutput(AbstractFile origFile, String pascoOutputFileName) {
409 String fnAbs = moduleTempResultsDir + File.separator + pascoOutputFileName;
411 File file =
new File(fnAbs);
412 if (file.exists() ==
false) {
413 this.addErrorMessage(
414 NbBundle.getMessage(
this.getClass(),
"ExtractIE.parsePascoOutput.errMsg.notFound", this.getName(),
416 logger.log(Level.WARNING,
"Pasco Output not found: {0}", file.getPath());
422 if (file.length() == 0) {
428 fileScanner =
new Scanner(
new FileInputStream(file.toString()));
429 }
catch (FileNotFoundException ex) {
430 this.addErrorMessage(
431 NbBundle.getMessage(
this.getClass(),
"ExtractIE.parsePascoOutput.errMsg.errParsing", this.getName(),
433 logger.log(Level.WARNING,
"Unable to find the Pasco file at " + file.getPath(), ex);
438 Set<String> reportedUserAccounts =
new HashSet<>();
440 while (fileScanner.hasNext()) {
441 String line = fileScanner.nextLine();
442 if (!line.startsWith(
"URL")) {
446 String[] lineBuff = line.split(
"\\t");
448 if (lineBuff.length < 4) {
449 logger.log(Level.INFO,
"Found unrecognized IE history format.");
453 String actime = lineBuff[3];
454 Long ftime = (long) 0;
463 if (lineBuff[1].contains(
"@")) {
464 String url[] = lineBuff[1].split(
"@", 2);
466 user = user.replace(
"Visited:",
"");
467 user = user.replace(
":Host:",
"");
468 user = user.replaceAll(
"(:)(.*?)(:)",
"");
471 realurl = realurl.replace(
"Visited:",
"");
472 realurl = realurl.replaceAll(
":(.*?):",
"");
473 realurl = realurl.replace(
":Host:",
"");
474 realurl = realurl.trim();
477 realurl = lineBuff[1].trim();
480 domain = Util.extractDomain(realurl);
482 if (!actime.isEmpty()) {
484 Long epochtime = dateFormatter.parse(actime).getTime();
485 ftime = epochtime / 1000;
486 }
catch (ParseException e) {
487 this.addErrorMessage(
488 NbBundle.getMessage(
this.getClass(),
"ExtractIE.parsePascoOutput.errMsg.errParsingEntry",
490 logger.log(Level.WARNING, String.format(
"Error parsing Pasco results, may have partial processing of corrupt file (id=%d)", origFile.getId()), e);
495 BlackboardArtifact bbart = origFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY);
496 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
497 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
498 NbBundle.getMessage(
this.getClass(),
499 "ExtractIE.parentModuleName.noSpace"), realurl));
502 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
503 NbBundle.getMessage(
this.getClass(),
504 "ExtractIE.parentModuleName.noSpace"), ftime));
505 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER,
506 NbBundle.getMessage(
this.getClass(),
507 "ExtractIE.parentModuleName.noSpace"),
""));
509 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
510 NbBundle.getMessage(
this.getClass(),
511 "ExtractIE.parentModuleName.noSpace"),
512 NbBundle.getMessage(
this.getClass(),
513 "ExtractIE.moduleName.text")));
514 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
515 NbBundle.getMessage(
this.getClass(),
516 "ExtractIE.parentModuleName.noSpace"), domain));
517 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
518 NbBundle.getMessage(
this.getClass(),
519 "ExtractIE.parentModuleName.noSpace"), user));
520 bbart.addAttributes(bbattributes);
523 this.indexArtifact(bbart);
525 if ((!user.isEmpty()) && (!reportedUserAccounts.contains(user))) {
526 BlackboardArtifact osAttr = origFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
527 osAttr.addAttribute(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
528 NbBundle.getMessage(
this.getClass(),
"ExtractIE.parentModuleName.noSpace"), user));
531 this.indexArtifact(osAttr);
533 reportedUserAccounts.add(user);
535 }
catch (TskCoreException ex) {
536 logger.log(Level.SEVERE,
"Error writing Internet Explorer web history artifact to the blackboard.", ex);
synchronized List< AbstractFile > findFiles(String fileName)