Autopsy  4.0
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.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;
38 import java.util.Set;
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;
49 import org.sleuthkit.datamodel.BlackboardArtifact;
50 import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
51 import org.sleuthkit.datamodel.BlackboardAttribute;
52 import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
53 import org.sleuthkit.datamodel.Content;
57 import org.sleuthkit.datamodel.*;
58 
63 class ExtractIE extends Extract {
64 
65  private static final Logger logger = Logger.getLogger(ExtractIE.class.getName());
66  private IngestServices services = IngestServices.getInstance();
67  private String moduleTempResultsDir;
68  private String PASCO_LIB_PATH;
69  private 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;
73 
74  ExtractIE() {
75  moduleName = NbBundle.getMessage(ExtractIE.class, "ExtractIE.moduleName.text");
76  moduleTempResultsDir = RAImageIngestModule.getRATempPath(Case.getCurrentCase(), "IE") + File.separator + "results"; //NON-NLS
77  JAVA_PATH = PlatformUtil.getJavaPath();
78  }
79 
80  @Override
81  public void process(Content dataSource, IngestJobContext context) {
82  this.dataSource = dataSource;
83  this.context = context;
84  dataFound = false;
85  this.getBookmark();
86  this.getCookie();
87  this.getHistory();
88  }
89 
93  private void getBookmark() {
94  org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager();
95  List<AbstractFile> favoritesFiles;
96  try {
97  favoritesFiles = fileManager.findFiles(dataSource, "%.url", "Favorites"); //NON-NLS
98  } catch (TskCoreException ex) {
99  logger.log(Level.WARNING, "Error fetching 'url' files for Internet Explorer bookmarks.", ex); //NON-NLS
100  this.addErrorMessage(
101  NbBundle.getMessage(this.getClass(), "ExtractIE.getBookmark.errMsg.errGettingBookmarks",
102  this.getName()));
103  return;
104  }
105 
106  if (favoritesFiles.isEmpty()) {
107  logger.log(Level.INFO, "Didn't find any IE bookmark files."); //NON-NLS
108  return;
109  }
110 
111  dataFound = true;
112  for (AbstractFile fav : favoritesFiles) {
113  if (fav.getSize() == 0) {
114  continue;
115  }
116 
117  if (context.dataSourceIngestIsCancelled()) {
118  break;
119  }
120 
121  String url = getURLFromIEBookmarkFile(fav);
122 
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);
128 
129  Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>();
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);
147  }
148  services.fireModuleDataEvent(new ModuleDataEvent(
149  NbBundle.getMessage(this.getClass(), "ExtractIE.parentModuleName"), BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK));
150  }
151 
152  private String getURLFromIEBookmarkFile(AbstractFile fav) {
153  BufferedReader reader = new BufferedReader(new InputStreamReader(new ReadContentInputStream(fav)));
154  String line, url = "";
155  try {
156  while ((line = reader.readLine()) != null) {
157  // The actual shortcut line we are interested in is of the
158  // form URL=http://path/to/website
159  if (line.startsWith("URL")) { //NON-NLS
160  url = line.substring(line.indexOf("=") + 1);
161  break;
162  }
163  }
164  } catch (IOException ex) {
165  logger.log(Level.WARNING, "Failed to read from content: " + fav.getName(), ex); //NON-NLS
166  this.addErrorMessage(
167  NbBundle.getMessage(this.getClass(), "ExtractIE.getURLFromIEBmkFile.errMsg", this.getName(),
168  fav.getName()));
169  } catch (IndexOutOfBoundsException ex) {
170  logger.log(Level.WARNING, "Failed while getting URL of IE bookmark. Unexpected format of the bookmark file: " + fav.getName(), ex); //NON-NLS
171  this.addErrorMessage(
172  NbBundle.getMessage(this.getClass(), "ExtractIE.getURLFromIEBmkFile.errMsg2", this.getName(),
173  fav.getName()));
174  } finally {
175  try {
176  reader.close();
177  } catch (IOException ex) {
178  logger.log(Level.WARNING, "Failed to close reader.", ex); //NON-NLS
179  }
180  }
181 
182  return url;
183  }
184 
188  private void getCookie() {
189  org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager();
190  List<AbstractFile> cookiesFiles;
191  try {
192  cookiesFiles = fileManager.findFiles(dataSource, "%.txt", "Cookies"); //NON-NLS
193  } catch (TskCoreException ex) {
194  logger.log(Level.WARNING, "Error getting cookie files for IE"); //NON-NLS
195  this.addErrorMessage(
196  NbBundle.getMessage(this.getClass(), "ExtractIE.getCookie.errMsg.errGettingFile", this.getName()));
197  return;
198  }
199 
200  if (cookiesFiles.isEmpty()) {
201  logger.log(Level.INFO, "Didn't find any IE cookies files."); //NON-NLS
202  return;
203  }
204 
205  dataFound = true;
206  for (AbstractFile cookiesFile : cookiesFiles) {
207  if (context.dataSourceIngestIsCancelled()) {
208  break;
209  }
210  if (cookiesFile.getSize() == 0) {
211  continue;
212  }
213 
214  byte[] t = new byte[(int) cookiesFile.getSize()];
215  try {
216  final int bytesRead = cookiesFile.read(t, 0, cookiesFile.getSize());
217  } catch (TskCoreException ex) {
218  logger.log(Level.SEVERE, "Error reading bytes of Internet Explorer cookie.", ex); //NON-NLS
219  this.addErrorMessage(
220  NbBundle.getMessage(this.getClass(), "ExtractIE.getCookie.errMsg.errReadingIECookie",
221  this.getName(), cookiesFile.getName()));
222  continue;
223  }
224  String cookieString = new String(t);
225  String[] values = cookieString.split("\n");
226  String url = values.length > 2 ? values[2] : "";
227  String value = values.length > 1 ? values[1] : "";
228  String name = values.length > 0 ? values[0] : "";
229  Long datetime = cookiesFile.getCrtime();
230  String tempDate = datetime.toString();
231  datetime = Long.valueOf(tempDate);
232  String domain = Util.extractDomain(url);
233 
234  Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>();
235  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
236  NbBundle.getMessage(this.getClass(),
237  "ExtractIE.parentModuleName.noSpace"), url));
238  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME,
239  NbBundle.getMessage(this.getClass(),
240  "ExtractIE.parentModuleName.noSpace"), datetime));
241  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
242  NbBundle.getMessage(this.getClass(),
243  "ExtractIE.parentModuleName.noSpace"), (name != null) ? name : ""));
244  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE,
245  NbBundle.getMessage(this.getClass(),
246  "ExtractIE.parentModuleName.noSpace"), value));
247  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
248  NbBundle.getMessage(this.getClass(),
249  "ExtractIE.parentModuleName.noSpace"),
250  NbBundle.getMessage(this.getClass(), "ExtractIE.moduleName.text")));
251  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
252  NbBundle.getMessage(this.getClass(),
253  "ExtractIE.parentModuleName.noSpace"), domain));
254  this.addArtifact(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes);
255  }
256  services.fireModuleDataEvent(new ModuleDataEvent(
257  NbBundle.getMessage(this.getClass(), "ExtractIE.parentModuleName"), BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE));
258  }
259 
263  private void getHistory() {
264  logger.log(Level.INFO, "Pasco results path: {0}", moduleTempResultsDir); //NON-NLS
265  boolean foundHistory = false;
266 
267  final File pascoRoot = InstalledFileLocator.getDefault().locate("pasco2", ExtractIE.class.getPackage().getName(), false); //NON-NLS
268  if (pascoRoot == null) {
269  this.addErrorMessage(
270  NbBundle.getMessage(this.getClass(), "ExtractIE.getHistory.errMsg.unableToGetHist", this.getName()));
271  logger.log(Level.SEVERE, "Error finding pasco program "); //NON-NLS
272  return;
273  }
274 
275  final String pascoHome = pascoRoot.getAbsolutePath();
276  logger.log(Level.INFO, "Pasco2 home: {0}", pascoHome); //NON-NLS
277 
278  PASCO_LIB_PATH = pascoHome + File.separator + "pasco2.jar" + File.pathSeparator //NON-NLS
279  + pascoHome + File.separator + "*";
280 
281  File resultsDir = new File(moduleTempResultsDir);
282  resultsDir.mkdirs();
283 
284  // get index.dat files
285  org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager();
286  List<AbstractFile> indexFiles;
287  try {
288  indexFiles = fileManager.findFiles(dataSource, "index.dat"); //NON-NLS
289  } catch (TskCoreException ex) {
290  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "ExtractIE.getHistory.errMsg.errGettingHistFiles",
291  this.getName()));
292  logger.log(Level.WARNING, "Error fetching 'index.data' files for Internet Explorer history."); //NON-NLS
293  return;
294  }
295 
296  if (indexFiles.isEmpty()) {
297  String msg = NbBundle.getMessage(this.getClass(), "ExtractIE.getHistory.errMsg.noHistFiles");
298  logger.log(Level.INFO, msg);
299  return;
300  }
301 
302  dataFound = true;
303  String temps;
304  String indexFileName;
305  for (AbstractFile indexFile : indexFiles) {
306  // Since each result represent an index.dat file,
307  // just create these files with the following notation:
308  // index<Number>.dat (i.e. index0.dat, index1.dat,..., indexN.dat)
309  // Write each index.dat file to a temp directory.
310  //BlackboardArtifact bbart = fsc.newArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY);
311  indexFileName = "index" + Integer.toString((int) indexFile.getId()) + ".dat"; //NON-NLS
312  //indexFileName = "index" + Long.toString(bbart.getArtifactID()) + ".dat";
313  temps = RAImageIngestModule.getRATempPath(currentCase, "IE") + File.separator + indexFileName; //NON-NLS
314  File datFile = new File(temps);
315  if (context.dataSourceIngestIsCancelled()) {
316  break;
317  }
318  try {
319  ContentUtils.writeToFile(indexFile, datFile);
320  } catch (IOException e) {
321  logger.log(Level.SEVERE, "Error while trying to write index.dat file " + datFile.getAbsolutePath(), e); //NON-NLS
322  this.addErrorMessage(
323  NbBundle.getMessage(this.getClass(), "ExtractIE.getHistory.errMsg.errWriteFile", this.getName(),
324  datFile.getAbsolutePath()));
325  continue;
326  }
327 
328  String filename = "pasco2Result." + indexFile.getId() + ".txt"; //NON-NLS
329  boolean bPascProcSuccess = executePasco(temps, filename);
330  if (context.dataSourceIngestIsCancelled()) {
331  return;
332  }
333 
334  //At this point pasco2 proccessed the index files.
335  //Now fetch the results, parse them and the delete the files.
336  if (bPascProcSuccess) {
337  parsePascoOutput(indexFile, filename);
338  foundHistory = true;
339 
340  //Delete index<n>.dat file since it was succcessfully by Pasco
341  datFile.delete();
342  } else {
343  logger.log(Level.WARNING, "pasco execution failed on: {0}", this.getName()); //NON-NLS
344  this.addErrorMessage(
345  NbBundle.getMessage(this.getClass(), "ExtractIE.getHistory.errMsg.errProcHist", this.getName()));
346  }
347  }
348 
349  if (foundHistory) {
350  services.fireModuleDataEvent(new ModuleDataEvent(
351  NbBundle.getMessage(this.getClass(), "ExtractIE.parentModuleName"), BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY));
352  }
353  }
354 
363  private boolean executePasco(String indexFilePath, String outputFileName) {
364  boolean success = true;
365  try {
366  final String outputFileFullPath = moduleTempResultsDir + File.separator + outputFileName;
367  final String errFileFullPath = moduleTempResultsDir + File.separator + outputFileName + ".err"; //NON-NLS
368  logger.log(Level.INFO, "Writing pasco results to: {0}", outputFileFullPath); //NON-NLS
369  List<String> commandLine = new ArrayList<>();
370  commandLine.add(JAVA_PATH);
371  commandLine.add("-cp"); //NON-NLS
372  commandLine.add(PASCO_LIB_PATH);
373  commandLine.add("isi.pasco2.Main"); //NON-NLS
374  commandLine.add("-T"); //NON-NLS
375  commandLine.add("history"); //NON-NLS
376  commandLine.add(indexFilePath);
377  ProcessBuilder processBuilder = new ProcessBuilder(commandLine);
378  processBuilder.redirectOutput(new File(outputFileFullPath));
379  processBuilder.redirectError(new File(errFileFullPath));
380  ExecUtil.execute(processBuilder, new DataSourceIngestModuleProcessTerminator(context));
381  // @@@ Investigate use of history versus cache as type.
382  } catch (IOException ex) {
383  success = false;
384  logger.log(Level.SEVERE, "Unable to execute Pasco to process Internet Explorer web history.", ex); //NON-NLS
385  }
386  return success;
387  }
388 
396  private void parsePascoOutput(AbstractFile origFile, String pascoOutputFileName) {
397 
398  String fnAbs = moduleTempResultsDir + File.separator + pascoOutputFileName;
399 
400  File file = new File(fnAbs);
401  if (file.exists() == false) {
402  this.addErrorMessage(
403  NbBundle.getMessage(this.getClass(), "ExtractIE.parsePascoOutput.errMsg.notFound", this.getName(),
404  file.getName()));
405  logger.log(Level.WARNING, "Pasco Output not found: {0}", file.getPath()); //NON-NLS
406  return;
407  }
408 
409  // Make sure the file the is not empty or the Scanner will
410  // throw a "No Line found" Exception
411  if (file.length() == 0) {
412  return;
413  }
414 
415  Scanner fileScanner;
416  try {
417  fileScanner = new Scanner(new FileInputStream(file.toString()));
418  } catch (FileNotFoundException ex) {
419  this.addErrorMessage(
420  NbBundle.getMessage(this.getClass(), "ExtractIE.parsePascoOutput.errMsg.errParsing", this.getName(),
421  file.getName()));
422  logger.log(Level.WARNING, "Unable to find the Pasco file at " + file.getPath(), ex); //NON-NLS
423  return;
424  }
425 
426  // Keep a list of reported user accounts to avoid repeats
427  Set<String> reportedUserAccounts = new HashSet<String>();
428 
429  while (fileScanner.hasNext()) {
430  String line = fileScanner.nextLine();
431  if (!line.startsWith("URL")) { //NON-NLS
432  continue;
433  }
434 
435  String[] lineBuff = line.split("\\t"); //NON-NLS
436 
437  if (lineBuff.length < 4) {
438  logger.log(Level.INFO, "Found unrecognized IE history format."); //NON-NLS
439  continue;
440  }
441 
442  String ddtime = lineBuff[2];
443  String actime = lineBuff[3];
444  Long ftime = (long) 0;
445  String user = "";
446  String realurl = "";
447  String domain = "";
448 
449  /*
450  * We've seen two types of lines: URL http://XYZ.com .... URL
451  * Visited: Joe@http://XYZ.com ....
452  */
453  if (lineBuff[1].contains("@")) {
454  String url[] = lineBuff[1].split("@", 2);
455  user = url[0];
456  user = user.replace("Visited:", ""); //NON-NLS
457  user = user.replace(":Host:", ""); //NON-NLS
458  user = user.replaceAll("(:)(.*?)(:)", "");
459  user = user.trim();
460  realurl = url[1];
461  realurl = realurl.replace("Visited:", ""); //NON-NLS
462  realurl = realurl.replaceAll(":(.*?):", "");
463  realurl = realurl.replace(":Host:", ""); //NON-NLS
464  realurl = realurl.trim();
465  } else {
466  user = "";
467  realurl = lineBuff[1].trim();
468  }
469 
470  domain = Util.extractDomain(realurl);
471 
472  if (!ddtime.isEmpty()) {
473  ddtime = ddtime.replace("T", " "); //NON-NLS
474  ddtime = ddtime.substring(ddtime.length() - 5);
475  }
476 
477  if (!actime.isEmpty()) {
478  try {
479  Long epochtime = dateFormatter.parse(actime).getTime();
480  ftime = epochtime.longValue();
481  ftime = ftime / 1000;
482  } catch (ParseException e) {
483  this.addErrorMessage(
484  NbBundle.getMessage(this.getClass(), "ExtractIE.parsePascoOutput.errMsg.errParsingEntry",
485  this.getName()));
486  logger.log(Level.SEVERE, "Error parsing Pasco results.", e); //NON-NLS
487  }
488  }
489 
490  try {
491  BlackboardArtifact bbart = origFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY);
492  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
493  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
494  NbBundle.getMessage(this.getClass(),
495  "ExtractIE.parentModuleName.noSpace"), realurl));
496  //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", EscapeUtil.decodeURL(realurl)));
497 
498  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
499  NbBundle.getMessage(this.getClass(),
500  "ExtractIE.parentModuleName.noSpace"), ftime));
501  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER,
502  NbBundle.getMessage(this.getClass(),
503  "ExtractIE.parentModuleName.noSpace"), ""));
504  // @@@ NOte that other browser modules are adding TITLE in hre for the title
505  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
506  NbBundle.getMessage(this.getClass(),
507  "ExtractIE.parentModuleName.noSpace"),
508  NbBundle.getMessage(this.getClass(),
509  "ExtractIE.moduleName.text")));
510  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
511  NbBundle.getMessage(this.getClass(),
512  "ExtractIE.parentModuleName.noSpace"), domain));
513  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
514  NbBundle.getMessage(this.getClass(),
515  "ExtractIE.parentModuleName.noSpace"), user));
516  bbart.addAttributes(bbattributes);
517 
518  // index the artifact for keyword search
519  this.indexArtifact(bbart);
520 
521  if ((!user.isEmpty()) && (!reportedUserAccounts.contains(user))) {
522  BlackboardArtifact osAttr = origFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
523  osAttr.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
524  NbBundle.getMessage(this.getClass(), "ExtractIE.parentModuleName.noSpace"), user));
525 
526  // index the artifact for keyword search
527  this.indexArtifact(osAttr);
528 
529  reportedUserAccounts.add(user);
530  }
531  } catch (TskCoreException ex) {
532  logger.log(Level.SEVERE, "Error writing Internet Explorer web history artifact to the blackboard.", ex); //NON-NLS
533  }
534  }
535  fileScanner.close();
536  }
537 }
synchronized List< AbstractFile > findFiles(String fileName)

Copyright © 2012-2015 Basis Technology. Generated on: Wed Apr 6 2016
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.