Autopsy  3.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
ExtractIE.java
Go to the documentation of this file.
1  /*
2  *
3  * Autopsy Forensic Browser
4  *
5  * Copyright 2012-2014 Basis Technology Corp.
6  *
7  * Copyright 2012 42six Solutions.
8  * Contact: aebadirad <at> 42six <dot> com
9  * Project Contact/Architect: carrier <at> sleuthkit <dot> org
10  *
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  * http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  */
23 package org.sleuthkit.autopsy.recentactivity;
24 
25 import java.io.BufferedReader;
26 
27 import org.openide.util.NbBundle;
29 import java.io.File;
30 import java.io.FileInputStream;
31 import java.io.FileNotFoundException;
32 import java.io.FileWriter;
33 import java.io.IOException;
34 import java.io.InputStreamReader;
35 import java.io.Writer;
36 import java.text.ParseException;
37 import java.text.SimpleDateFormat;
38 import java.util.ArrayList;
39 import java.util.List;
40 import java.util.Set;
41 import java.util.HashSet;
42 import java.util.logging.Level;
44 import java.util.Collection;
45 import java.util.Scanner;
46 import org.openide.modules.InstalledFileLocator;
59 import org.sleuthkit.datamodel.*;
60 
65 class ExtractIE extends Extract {
66 
67  private static final Logger logger = Logger.getLogger(ExtractIE.class.getName());
68  private IngestServices services = IngestServices.getInstance();
69  private String moduleTempResultsDir;
70  private String PASCO_LIB_PATH;
71  private String JAVA_PATH;
72  private static final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
73  private Content dataSource;
74  private IngestJobContext context;
75 
76  ExtractIE() {
77  moduleName = NbBundle.getMessage(ExtractIE.class, "ExtractIE.moduleName.text");
78  moduleTempResultsDir = RAImageIngestModule.getRATempPath(Case.getCurrentCase(), "IE") + File.separator + "results"; //NON-NLS
79  JAVA_PATH = PlatformUtil.getJavaPath();
80  }
81 
82  @Override
83  public void process(Content dataSource, IngestJobContext context) {
84  this.dataSource = dataSource;
85  this.context = context;
86  dataFound = false;
87  this.getBookmark();
88  this.getCookie();
89  this.getHistory();
90  }
91 
95  private void getBookmark() {
96  org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager();
97  List<AbstractFile> favoritesFiles;
98  try {
99  favoritesFiles = fileManager.findFiles(dataSource, "%.url", "Favorites"); //NON-NLS
100  } catch (TskCoreException ex) {
101  logger.log(Level.WARNING, "Error fetching 'url' files for Internet Explorer bookmarks.", ex); //NON-NLS
102  this.addErrorMessage(
103  NbBundle.getMessage(this.getClass(), "ExtractIE.getBookmark.errMsg.errGettingBookmarks",
104  this.getName()));
105  return;
106  }
107 
108  if (favoritesFiles.isEmpty()) {
109  logger.log(Level.INFO, "Didn't find any IE bookmark files."); //NON-NLS
110  return;
111  }
112 
113  dataFound = true;
114  for (AbstractFile fav : favoritesFiles) {
115  if (fav.getSize() == 0) {
116  continue;
117  }
118 
119  if (context.dataSourceIngestIsCancelled()) {
120  break;
121  }
122 
123  String url = getURLFromIEBookmarkFile(fav);
124 
125  String name = fav.getName();
126  Long datetime = fav.getCrtime();
127  String Tempdate = datetime.toString();
128  datetime = Long.valueOf(Tempdate);
129  String domain = Util.extractDomain(url);
130 
131  Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>();
132  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(),
133  NbBundle.getMessage(this.getClass(),
134  "ExtractIE.parentModuleName.noSpace"), url));
135  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE.getTypeID(),
136  NbBundle.getMessage(this.getClass(),
137  "ExtractIE.parentModuleName.noSpace"), name));
138  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID(),
139  NbBundle.getMessage(this.getClass(),
140  "ExtractIE.parentModuleName.noSpace"), datetime));
141  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(),
142  NbBundle.getMessage(this.getClass(),
143  "ExtractIE.parentModuleName.noSpace"),
144  NbBundle.getMessage(this.getClass(), "ExtractIE.moduleName.text")));
145  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(),
146  NbBundle.getMessage(this.getClass(),
147  "ExtractIE.parentModuleName.noSpace"), domain));
148  this.addArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK, fav, bbattributes);
149  }
150  services.fireModuleDataEvent(new ModuleDataEvent(
151  NbBundle.getMessage(this.getClass(), "ExtractIE.parentModuleName"), BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK));
152  }
153 
154  private String getURLFromIEBookmarkFile(AbstractFile fav) {
155  BufferedReader reader = new BufferedReader(new InputStreamReader(new ReadContentInputStream(fav)));
156  String line, url = "";
157  try {
158  while ((line = reader.readLine()) != null) {
159  // The actual shortcut line we are interested in is of the
160  // form URL=http://path/to/website
161  if (line.startsWith("URL")) { //NON-NLS
162  url = line.substring(line.indexOf("=") + 1);
163  break;
164  }
165  }
166  } catch (IOException ex) {
167  logger.log(Level.WARNING, "Failed to read from content: " + fav.getName(), ex); //NON-NLS
168  this.addErrorMessage(
169  NbBundle.getMessage(this.getClass(), "ExtractIE.getURLFromIEBmkFile.errMsg", this.getName(),
170  fav.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); //NON-NLS
173  this.addErrorMessage(
174  NbBundle.getMessage(this.getClass(), "ExtractIE.getURLFromIEBmkFile.errMsg2", this.getName(),
175  fav.getName()));
176  } finally {
177  try {
178  reader.close();
179  } catch (IOException ex) {
180  logger.log(Level.WARNING, "Failed to close reader.", ex); //NON-NLS
181  }
182  }
183 
184  return url;
185  }
186 
190  private void getCookie() {
191  org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager();
192  List<AbstractFile> cookiesFiles;
193  try {
194  cookiesFiles = fileManager.findFiles(dataSource, "%.txt", "Cookies"); //NON-NLS
195  } catch (TskCoreException ex) {
196  logger.log(Level.WARNING, "Error getting cookie files for IE"); //NON-NLS
197  this.addErrorMessage(
198  NbBundle.getMessage(this.getClass(), "ExtractIE.getCookie.errMsg.errGettingFile", this.getName()));
199  return;
200  }
201 
202  if (cookiesFiles.isEmpty()) {
203  logger.log(Level.INFO, "Didn't find any IE cookies files."); //NON-NLS
204  return;
205  }
206 
207  dataFound = true;
208  for (AbstractFile cookiesFile : cookiesFiles) {
209  if (context.dataSourceIngestIsCancelled()) {
210  break;
211  }
212  if (cookiesFile.getSize() == 0) {
213  continue;
214  }
215 
216  byte[] t = new byte[(int) cookiesFile.getSize()];
217  try {
218  final int bytesRead = cookiesFile.read(t, 0, cookiesFile.getSize());
219  } catch (TskCoreException ex) {
220  logger.log(Level.SEVERE, "Error reading bytes of Internet Explorer cookie.", ex); //NON-NLS
221  this.addErrorMessage(
222  NbBundle.getMessage(this.getClass(), "ExtractIE.getCookie.errMsg.errReadingIECookie",
223  this.getName(), cookiesFile.getName()));
224  continue;
225  }
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);
235 
236  Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>();
237  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(),
238  NbBundle.getMessage(this.getClass(),
239  "ExtractIE.parentModuleName.noSpace"), url));
240  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(),
241  NbBundle.getMessage(this.getClass(),
242  "ExtractIE.parentModuleName.noSpace"), datetime));
243  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(),
244  NbBundle.getMessage(this.getClass(),
245  "ExtractIE.parentModuleName.noSpace"), (name != null) ? name : ""));
246  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(),
247  NbBundle.getMessage(this.getClass(),
248  "ExtractIE.parentModuleName.noSpace"), value));
249  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(),
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.getTypeID(),
254  NbBundle.getMessage(this.getClass(),
255  "ExtractIE.parentModuleName.noSpace"), domain));
256  this.addArtifact(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes);
257  }
258  services.fireModuleDataEvent(new ModuleDataEvent(
259  NbBundle.getMessage(this.getClass(), "ExtractIE.parentModuleName"), BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE));
260  }
261 
265  private void getHistory() {
266  logger.log(Level.INFO, "Pasco results path: {0}", moduleTempResultsDir); //NON-NLS
267  boolean foundHistory = false;
268 
269  final File pascoRoot = InstalledFileLocator.getDefault().locate("pasco2", ExtractIE.class.getPackage().getName(), false); //NON-NLS
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 "); //NON-NLS
274  return;
275  }
276 
277  final String pascoHome = pascoRoot.getAbsolutePath();
278  logger.log(Level.INFO, "Pasco2 home: {0}", pascoHome); //NON-NLS
279 
280  PASCO_LIB_PATH = pascoHome + File.separator + "pasco2.jar" + File.pathSeparator //NON-NLS
281  + pascoHome + File.separator + "*";
282 
283  File resultsDir = new File(moduleTempResultsDir);
284  resultsDir.mkdirs();
285 
286  // get index.dat files
287  org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager();
288  List<AbstractFile> indexFiles;
289  try {
290  indexFiles = fileManager.findFiles(dataSource, "index.dat"); //NON-NLS
291  } catch (TskCoreException ex) {
292  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "ExtractIE.getHistory.errMsg.errGettingHistFiles",
293  this.getName()));
294  logger.log(Level.WARNING, "Error fetching 'index.data' files for Internet Explorer history."); //NON-NLS
295  return;
296  }
297 
298  if (indexFiles.isEmpty()) {
299  String msg = NbBundle.getMessage(this.getClass(), "ExtractIE.getHistory.errMsg.noHistFiles");
300  logger.log(Level.INFO, msg);
301  return;
302  }
303 
304  dataFound = true;
305  String temps;
306  String indexFileName;
307  for (AbstractFile indexFile : indexFiles) {
308  // Since each result represent an index.dat file,
309  // just create these files with the following notation:
310  // index<Number>.dat (i.e. index0.dat, index1.dat,..., indexN.dat)
311  // Write each index.dat file to a temp directory.
312  //BlackboardArtifact bbart = fsc.newArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY);
313  indexFileName = "index" + Integer.toString((int) indexFile.getId()) + ".dat"; //NON-NLS
314  //indexFileName = "index" + Long.toString(bbart.getArtifactID()) + ".dat";
315  temps = RAImageIngestModule.getRATempPath(currentCase, "IE") + File.separator + indexFileName; //NON-NLS
316  File datFile = new File(temps);
317  if (context.dataSourceIngestIsCancelled()) {
318  break;
319  }
320  try {
321  ContentUtils.writeToFile(indexFile, datFile);
322  } catch (IOException e) {
323  logger.log(Level.SEVERE, "Error while trying to write index.dat file " + datFile.getAbsolutePath(), e); //NON-NLS
324  this.addErrorMessage(
325  NbBundle.getMessage(this.getClass(), "ExtractIE.getHistory.errMsg.errWriteFile", this.getName(),
326  datFile.getAbsolutePath()));
327  continue;
328  }
329 
330  String filename = "pasco2Result." + indexFile.getId() + ".txt"; //NON-NLS
331  boolean bPascProcSuccess = executePasco(temps, filename);
332  if (context.dataSourceIngestIsCancelled()) {
333  return;
334  }
335 
336  //At this point pasco2 proccessed the index files.
337  //Now fetch the results, parse them and the delete the files.
338  if (bPascProcSuccess) {
339  parsePascoOutput(indexFile, filename);
340  foundHistory = true;
341 
342  //Delete index<n>.dat file since it was succcessfully by Pasco
343  datFile.delete();
344  } else {
345  logger.log(Level.WARNING, "pasco execution failed on: {0}", this.getName()); //NON-NLS
346  this.addErrorMessage(
347  NbBundle.getMessage(this.getClass(), "ExtractIE.getHistory.errMsg.errProcHist", this.getName()));
348  }
349  }
350 
351  if (foundHistory) {
352  services.fireModuleDataEvent(new ModuleDataEvent(
353  NbBundle.getMessage(this.getClass(), "ExtractIE.parentModuleName"), BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY));
354  }
355  }
356 
364  private boolean executePasco(String indexFilePath, String outputFileName) {
365  boolean success = true;
366  try {
367  final String outputFileFullPath = moduleTempResultsDir + File.separator + outputFileName;
368  final String errFileFullPath = moduleTempResultsDir + File.separator + outputFileName + ".err"; //NON-NLS
369  logger.log(Level.INFO, "Writing pasco results to: {0}", outputFileFullPath); //NON-NLS
370  List<String> commandLine = new ArrayList<>();
371  commandLine.add(JAVA_PATH);
372  commandLine.add("-cp"); //NON-NLS
373  commandLine.add(PASCO_LIB_PATH);
374  commandLine.add("isi.pasco2.Main"); //NON-NLS
375  commandLine.add("-T"); //NON-NLS
376  commandLine.add("history"); //NON-NLS
377  commandLine.add(indexFilePath);
378  ProcessBuilder processBuilder = new ProcessBuilder(commandLine);
379  processBuilder.redirectOutput(new File(outputFileFullPath));
380  processBuilder.redirectError(new File(errFileFullPath));
381  ExecUtil.execute(processBuilder, new DataSourceIngestModuleProcessTerminator(context));
382  // @@@ Investigate use of history versus cache as type.
383  } catch (IOException ex) {
384  success = false;
385  logger.log(Level.SEVERE, "Unable to execute Pasco to process Internet Explorer web history.", ex); //NON-NLS
386  }
387  return success;
388  }
389 
397  private void parsePascoOutput(AbstractFile origFile, String pascoOutputFileName) {
398 
399  String fnAbs = moduleTempResultsDir + File.separator + pascoOutputFileName;
400 
401  File file = new File(fnAbs);
402  if (file.exists() == false) {
403  this.addErrorMessage(
404  NbBundle.getMessage(this.getClass(), "ExtractIE.parsePascoOutput.errMsg.notFound", this.getName(),
405  file.getName()));
406  logger.log(Level.WARNING, "Pasco Output not found: {0}", file.getPath()); //NON-NLS
407  return;
408  }
409 
410  // Make sure the file the is not empty or the Scanner will
411  // throw a "No Line found" Exception
412  if (file.length() == 0) {
413  return;
414  }
415 
416  Scanner fileScanner;
417  try {
418  fileScanner = new Scanner(new FileInputStream(file.toString()));
419  } catch (FileNotFoundException ex) {
420  this.addErrorMessage(
421  NbBundle.getMessage(this.getClass(), "ExtractIE.parsePascoOutput.errMsg.errParsing", this.getName(),
422  file.getName()));
423  logger.log(Level.WARNING, "Unable to find the Pasco file at " + file.getPath(), ex); //NON-NLS
424  return;
425  }
426 
427  // Keep a list of reported user accounts to avoid repeats
428  Set<String> reportedUserAccounts = new HashSet<String>();
429 
430  while (fileScanner.hasNext()) {
431  String line = fileScanner.nextLine();
432  if (!line.startsWith("URL")) { //NON-NLS
433  continue;
434  }
435 
436  String[] lineBuff = line.split("\\t"); //NON-NLS
437 
438  if (lineBuff.length < 4) {
439  logger.log(Level.INFO, "Found unrecognized IE history format."); //NON-NLS
440  continue;
441  }
442 
443  String ddtime = lineBuff[2];
444  String actime = lineBuff[3];
445  Long ftime = (long) 0;
446  String user = "";
447  String realurl = "";
448  String domain = "";
449 
450  /* We've seen two types of lines:
451  * URL http://XYZ.com ....
452  * URL Visited: Joe@http://XYZ.com ....
453  */
454  if (lineBuff[1].contains("@")) {
455  String url[] = lineBuff[1].split("@", 2);
456  user = url[0];
457  user = user.replace("Visited:", ""); //NON-NLS
458  user = user.replace(":Host:", ""); //NON-NLS
459  user = user.replaceAll("(:)(.*?)(:)", "");
460  user = user.trim();
461  realurl = url[1];
462  realurl = realurl.replace("Visited:", ""); //NON-NLS
463  realurl = realurl.replaceAll(":(.*?):", "");
464  realurl = realurl.replace(":Host:", ""); //NON-NLS
465  realurl = realurl.trim();
466  } else {
467  user = "";
468  realurl = lineBuff[1].trim();
469  }
470 
471  domain = Util.extractDomain(realurl);
472 
473  if (!ddtime.isEmpty()) {
474  ddtime = ddtime.replace("T", " "); //NON-NLS
475  ddtime = ddtime.substring(ddtime.length() - 5);
476  }
477 
478  if (!actime.isEmpty()) {
479  try {
480  Long epochtime = dateFormatter.parse(actime).getTime();
481  ftime = epochtime.longValue();
482  ftime = ftime / 1000;
483  } catch (ParseException e) {
484  this.addErrorMessage(
485  NbBundle.getMessage(this.getClass(), "ExtractIE.parsePascoOutput.errMsg.errParsingEntry",
486  this.getName()));
487  logger.log(Level.SEVERE, "Error parsing Pasco results.", e); //NON-NLS
488  }
489  }
490 
491  try {
492  BlackboardArtifact bbart = origFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY);
493  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
494  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(),
495  NbBundle.getMessage(this.getClass(),
496  "ExtractIE.parentModuleName.noSpace"), realurl));
497  //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", EscapeUtil.decodeURL(realurl)));
498 
499  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(),
500  NbBundle.getMessage(this.getClass(),
501  "ExtractIE.parentModuleName.noSpace"), ftime));
502  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER.getTypeID(),
503  NbBundle.getMessage(this.getClass(),
504  "ExtractIE.parentModuleName.noSpace"), ""));
505  // @@@ NOte that other browser modules are adding TITLE in hre for the title
506  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(),
507  NbBundle.getMessage(this.getClass(),
508  "ExtractIE.parentModuleName.noSpace"),
509  NbBundle.getMessage(this.getClass(),
510  "ExtractIE.moduleName.text")));
511  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(),
512  NbBundle.getMessage(this.getClass(),
513  "ExtractIE.parentModuleName.noSpace"), domain));
514  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME.getTypeID(),
515  NbBundle.getMessage(this.getClass(),
516  "ExtractIE.parentModuleName.noSpace"), user));
517  bbart.addAttributes(bbattributes);
518 
519  if ((!user.isEmpty()) && (!reportedUserAccounts.contains(user))) {
520  BlackboardArtifact osAttr = origFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
521  osAttr.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME.getTypeID(),
522  NbBundle.getMessage(this.getClass(), "ExtractIE.parentModuleName.noSpace"), user));
523  reportedUserAccounts.add(user);
524  }
525  } catch (TskCoreException ex) {
526  logger.log(Level.SEVERE, "Error writing Internet Explorer web history artifact to the blackboard.", ex); //NON-NLS
527  }
528  }
529  fileScanner.close();
530  }
531 }
void addAttributes(Collection< BlackboardAttribute > attributes)
synchronized List< AbstractFile > findFiles(Content dataSource, String fileName)
void addAttribute(BlackboardAttribute attr)
BlackboardArtifact newArtifact(int artifactTypeID)
String toString(boolean preserveState)

Copyright © 2012-2015 Basis Technology. Generated on: Mon Oct 19 2015
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.