Autopsy  4.18.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
Chromium.java
Go to the documentation of this file.
1 /*
2  *
3  * Autopsy Forensic Browser
4  *
5  * Copyright 2012-2021 Basis Technology Corp.
6  *
7  * Copyright 2012 42six Solutions.
8  *
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 com.google.common.collect.ImmutableMap;
26 import com.google.gson.JsonArray;
27 import com.google.gson.JsonElement;
28 import com.google.gson.JsonIOException;
29 import com.google.gson.JsonObject;
30 import com.google.gson.JsonParser;
31 import com.google.gson.JsonSyntaxException;
32 import org.openide.util.NbBundle;
34 import java.util.logging.Level;
35 import java.io.File;
36 import java.io.FileNotFoundException;
37 import java.io.FileReader;
38 import java.io.IOException;
39 import java.util.Collection;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.HashMap;
43 import java.util.ArrayList;
44 import java.util.Arrays;
45 import org.apache.commons.io.FilenameUtils;
46 import org.openide.util.NbBundle.Messages;
54 import org.sleuthkit.datamodel.AbstractFile;
55 import org.sleuthkit.datamodel.Blackboard;
56 import org.sleuthkit.datamodel.BlackboardArtifact;
57 import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
58 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK;
59 import org.sleuthkit.datamodel.BlackboardAttribute;
60 import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
61 import org.sleuthkit.datamodel.Content;
62 import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
63 import org.sleuthkit.datamodel.Score;
64 import org.sleuthkit.datamodel.TskCoreException;
65 import org.sleuthkit.datamodel.TskData;
66 import org.sleuthkit.datamodel.blackboardutils.WebBrowserArtifactsHelper;
67 
71 class Chromium extends Extract {
72 
73  private static final String HISTORY_QUERY = "SELECT urls.url, urls.title, urls.visit_count, urls.typed_count, " //NON-NLS
74  + "last_visit_time, urls.hidden, visits.visit_time, (SELECT urls.url FROM urls WHERE urls.id=visits.url) AS from_visit, visits.transition FROM urls, visits WHERE urls.id = visits.url"; //NON-NLS
75  private static final String COOKIE_QUERY = "SELECT name, value, host_key, expires_utc,last_access_utc, creation_utc FROM cookies"; //NON-NLS
76  private static final String DOWNLOAD_QUERY = "SELECT full_path, url, start_time, received_bytes FROM downloads"; //NON-NLS
77  private static final String DOWNLOAD_QUERY_V30 = "SELECT current_path AS full_path, url, start_time, received_bytes FROM downloads, downloads_url_chains WHERE downloads.id=downloads_url_chains.id"; //NON-NLS
78  private static final String LOGIN_QUERY = "SELECT origin_url, username_value, date_created, signon_realm from logins"; //NON-NLS
79  private static final String AUTOFILL_QUERY = "SELECT name, value, count, date_created "
80  + " FROM autofill, autofill_dates "
81  + " WHERE autofill.pair_id = autofill_dates.pair_id"; //NON-NLS
82  private static final String AUTOFILL_QUERY_V8X = "SELECT name, value, count, date_created, date_last_used from autofill"; //NON-NLS
83  private static final String WEBFORM_ADDRESS_QUERY = "SELECT first_name, middle_name, last_name, address_line_1, address_line_2, city, state, zipcode, country_code, number, email, date_modified "
84  + " FROM autofill_profiles, autofill_profile_names, autofill_profile_emails, autofill_profile_phones"
85  + " WHERE autofill_profiles.guid = autofill_profile_names.guid AND autofill_profiles.guid = autofill_profile_emails.guid AND autofill_profiles.guid = autofill_profile_phones.guid";
86 
87  private static final String WEBFORM_ADDRESS_QUERY_V8X = "SELECT first_name, middle_name, last_name, full_name, street_address, city, state, zipcode, country_code, number, email, date_modified, use_date, use_count"
88  + " FROM autofill_profiles, autofill_profile_names, autofill_profile_emails, autofill_profile_phones"
89  + " WHERE autofill_profiles.guid = autofill_profile_names.guid AND autofill_profiles.guid = autofill_profile_emails.guid AND autofill_profiles.guid = autofill_profile_phones.guid";
90  private static final String HISTORY_FILE_NAME = "History";
91  private static final String BOOKMARK_FILE_NAME = "Bookmarks";
92  private static final String COOKIE_FILE_NAME = "Cookies";
93  private static final String LOGIN_DATA_FILE_NAME = "Login Data";
94  private static final String WEB_DATA_FILE_NAME = "Web Data";
95  private static final String UC_BROWSER_NAME = "UC Browser";
96  private static final String ENCRYPTED_FIELD_MESSAGE = "The data was encrypted.";
97 
98  private Boolean databaseEncrypted = false;
99  private Boolean fieldEncrypted = false;
100 
101  private final Logger logger = Logger.getLogger(this.getClass().getName());
102  private Content dataSource;
103  private IngestJobContext context;
104 
105  private static final Map<String, String> BROWSERS_MAP = ImmutableMap.<String, String>builder()
106  .put("Microsoft Edge", "Microsoft/Edge/User Data/Default")
107  .put("Yandex", "YandexBrowser/User Data/Default")
108  .put("Opera", "Opera Software/Opera Stable")
109  .put("SalamWeb", "SalamWeb/User Data/Default")
110  .put("UC Browser", "UCBrowser/User Data%/Default")
111  .put("Brave", "BraveSoftware/Brave-Browser/User Data/Default")
112  .put("Google Chrome", "Chrome/User Data/Default")
113  .build();
114 
115  @Messages({"# {0} - browserName",
116  "Progress_Message_Chrome_History=Chrome History Browser {0}",
117  "# {0} - browserName",
118  "Progress_Message_Chrome_Bookmarks=Chrome Bookmarks Browser {0}",
119  "# {0} - browserName",
120  "Progress_Message_Chrome_Cookies=Chrome Cookies Browser {0}",
121  "# {0} - browserName",
122  "Progress_Message_Chrome_Downloads=Chrome Downloads Browser {0}",
123  "Progress_Message_Chrome_FormHistory=Chrome Form History",
124  "# {0} - browserName",
125  "Progress_Message_Chrome_AutoFill=Chrome Auto Fill Browser {0}",
126  "# {0} - browserName",
127  "Progress_Message_Chrome_Logins=Chrome Logins Browser {0}",
128  "Progress_Message_Chrome_Cache=Chrome Cache",})
129 
130  Chromium() {
131  super(NbBundle.getMessage(Chromium.class, "Chrome.moduleName"));
132  }
133 
134  @Override
135  public void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) {
136  this.dataSource = dataSource;
137  this.context = context;
138  dataFound = false;
139  long ingestJobId = context.getJobId();
140 
141  for (Map.Entry<String, String> browser : BROWSERS_MAP.entrySet()) {
142  String browserName = browser.getKey();
143  String browserLocation = browser.getValue();
144  progressBar.progress(NbBundle.getMessage(this.getClass(), "Progress_Message_Chrome_History", browserName));
145  this.getHistory(browser.getKey(), browser.getValue(), ingestJobId);
146  if (context.dataSourceIngestIsCancelled()) {
147  return;
148  }
149 
150  progressBar.progress(NbBundle.getMessage(this.getClass(), "Progress_Message_Chrome_Bookmarks", browserName));
151  this.getBookmark(browser.getKey(), browser.getValue(), ingestJobId);
152  if (context.dataSourceIngestIsCancelled()) {
153  return;
154  }
155 
156  progressBar.progress(NbBundle.getMessage(this.getClass(), "Progress_Message_Chrome_Cookies", browserName));
157  this.getCookie(browser.getKey(), browser.getValue(), ingestJobId);
158  if (context.dataSourceIngestIsCancelled()) {
159  return;
160  }
161 
162  progressBar.progress(NbBundle.getMessage(this.getClass(), "Progress_Message_Chrome_Logins", browserName));
163  this.getLogins(browser.getKey(), browser.getValue(), ingestJobId);
164  if (context.dataSourceIngestIsCancelled()) {
165  return;
166  }
167 
168  progressBar.progress(NbBundle.getMessage(this.getClass(), "Progress_Message_Chrome_AutoFill", browserName));
169  this.getAutofill(browser.getKey(), browser.getValue(), ingestJobId);
170  if (context.dataSourceIngestIsCancelled()) {
171  return;
172  }
173 
174  progressBar.progress(NbBundle.getMessage(this.getClass(), "Progress_Message_Chrome_Downloads", browserName));
175  this.getDownload(browser.getKey(), browser.getValue(), ingestJobId);
176  if (context.dataSourceIngestIsCancelled()) {
177  return;
178  }
179  }
180 
181  progressBar.progress(Bundle.Progress_Message_Chrome_Cache());
182  ChromeCacheExtractor chromeCacheExtractor = new ChromeCacheExtractor(dataSource, context, progressBar);
183  chromeCacheExtractor.processCaches();
184 
185  }
186 
193  private void getHistory(String browser, String browserLocation, long ingestJobId) {
194  FileManager fileManager = currentCase.getServices().getFileManager();
195  List<AbstractFile> historyFiles;
196  String historyFileName = HISTORY_FILE_NAME;
197  if (browser.equals(UC_BROWSER_NAME)) {
198  historyFileName = HISTORY_FILE_NAME + "%";
199  }
200  try {
201  historyFiles = fileManager.findFiles(dataSource, historyFileName, browserLocation); //NON-NLS
202  } catch (TskCoreException ex) {
203  String msg = NbBundle.getMessage(this.getClass(), "Chrome.getHistory.errMsg.errGettingFiles");
204  logger.log(Level.SEVERE, msg, ex);
205  this.addErrorMessage(this.getName() + ": " + msg);
206  return;
207  }
208 
209  // get only the allocated ones, for now
210  List<AbstractFile> allocatedHistoryFiles = new ArrayList<>();
211  for (AbstractFile historyFile : historyFiles) {
212  if (historyFile.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC)) {
213  allocatedHistoryFiles.add(historyFile);
214  }
215  }
216 
217  // log a message if we don't have any allocated history files
218  if (allocatedHistoryFiles.isEmpty()) {
219  String msg = NbBundle.getMessage(this.getClass(), "Chrome.getHistory.errMsg.couldntFindAnyFiles");
220  logger.log(Level.INFO, msg);
221  return;
222  }
223 
224  dataFound = true;
225  Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
226  int j = 0;
227  while (j < allocatedHistoryFiles.size()) {
228  String temps = RAImageIngestModule.getRATempPath(currentCase, browser, ingestJobId) + File.separator + allocatedHistoryFiles.get(j).getName() + j + ".db"; //NON-NLS
229  final AbstractFile historyFile = allocatedHistoryFiles.get(j++);
230  if ((historyFile.getSize() == 0) || (historyFile.getName().toLowerCase().contains("-slack"))
231  || (historyFile.getName().toLowerCase().contains("cache")) || (historyFile.getName().toLowerCase().contains("media"))
232  || (historyFile.getName().toLowerCase().contains("index"))) {
233  continue;
234  }
235  try {
236  ContentUtils.writeToFile(historyFile, new File(temps), context::dataSourceIngestIsCancelled);
237  } catch (ReadContentInputStreamException ex) {
238  logger.log(Level.WARNING, String.format("Error reading Chrome web history artifacts file '%s' (id=%d).",
239  historyFile.getName(), historyFile.getId()), ex); //NON-NLS
240  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getHistory.errMsg.errAnalyzingFile",
241  this.getName(), historyFile.getName()));
242  continue;
243  } catch (IOException ex) {
244  logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Chrome web history artifacts file '%s' (id=%d).",
245  temps, historyFile.getName(), historyFile.getId()), ex); //NON-NLS
246  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getHistory.errMsg.errAnalyzingFile",
247  this.getName(), historyFile.getName()));
248  continue;
249  }
250  File dbFile = new File(temps);
251  if (context.dataSourceIngestIsCancelled()) {
252  dbFile.delete();
253  break;
254  }
255  List<HashMap<String, Object>> tempList;
256  tempList = this.dbConnect(temps, HISTORY_QUERY);
257  logger.log(Level.INFO, "{0}- Now getting history from {1} with {2} artifacts identified.", new Object[]{getName(), temps, tempList.size()}); //NON-NLS
258  for (HashMap<String, Object> result : tempList) {
259  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
260  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
261  RecentActivityExtracterModuleFactory.getModuleName(),
262  ((result.get("url").toString() != null) ? result.get("url").toString() : ""))); //NON-NLS
263  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
264  RecentActivityExtracterModuleFactory.getModuleName(),
265  (Long.valueOf(result.get("last_visit_time").toString()) / 1000000) - Long.valueOf("11644473600"))); //NON-NLS
266  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER,
267  RecentActivityExtracterModuleFactory.getModuleName(),
268  ((result.get("from_visit").toString() != null) ? result.get("from_visit").toString() : ""))); //NON-NLS
269  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE,
270  RecentActivityExtracterModuleFactory.getModuleName(),
271  ((result.get("title").toString() != null) ? result.get("title").toString() : ""))); //NON-NLS
272  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
273  RecentActivityExtracterModuleFactory.getModuleName(), browser));
274  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
275  RecentActivityExtracterModuleFactory.getModuleName(),
276  (NetworkUtils.extractDomain((result.get("url").toString() != null) ? result.get("url").toString() : "")))); //NON-NLS
277 
278  try {
279  bbartifacts.add(createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_HISTORY, historyFile, bbattributes));
280  } catch (TskCoreException ex) {
281  logger.log(Level.SEVERE, String.format("Failed to create history artifact for file (%d)", historyFile.getId()), ex);
282  }
283  }
284  dbFile.delete();
285  }
286 
287  if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
288  postArtifacts(bbartifacts);
289  }
290  }
291 
298  private void getBookmark(String browser, String browserLocation, long ingestJobId) {
299  FileManager fileManager = currentCase.getServices().getFileManager();
300  List<AbstractFile> bookmarkFiles;
301  String bookmarkFileName = BOOKMARK_FILE_NAME;
302  if (browser.equals(UC_BROWSER_NAME)) {
303  bookmarkFileName = BOOKMARK_FILE_NAME + "%";
304  }
305  try {
306  bookmarkFiles = fileManager.findFiles(dataSource, bookmarkFileName, browserLocation); //NON-NLS
307  } catch (TskCoreException ex) {
308  String msg = NbBundle.getMessage(this.getClass(), "Chrome.getBookmark.errMsg.errGettingFiles");
309  logger.log(Level.SEVERE, msg, ex);
310  this.addErrorMessage(this.getName() + ": " + msg);
311  return;
312  }
313 
314  if (bookmarkFiles.isEmpty()) {
315  logger.log(Level.INFO, "Didn't find any Chrome bookmark files."); //NON-NLS
316  return;
317  }
318 
319  dataFound = true;
320  Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
321  int j = 0;
322 
323  while (j < bookmarkFiles.size()) {
324  AbstractFile bookmarkFile = bookmarkFiles.get(j++);
325  if ((bookmarkFile.getSize() == 0) || (bookmarkFile.getName().toLowerCase().contains("-slack"))
326  || (bookmarkFile.getName().toLowerCase().contains("extras")) || (bookmarkFile.getName().toLowerCase().contains("log"))
327  || (bookmarkFile.getName().toLowerCase().contains("backup")) || (bookmarkFile.getName().toLowerCase().contains("visualized"))
328  || (bookmarkFile.getName().toLowerCase().contains("bak")) || (bookmarkFile.getParentPath().toLowerCase().contains("backup"))) {
329  continue;
330  }
331  String temps = RAImageIngestModule.getRATempPath(currentCase, browser, ingestJobId) + File.separator + bookmarkFile.getName() + j + ".db"; //NON-NLS
332  try {
333  ContentUtils.writeToFile(bookmarkFile, new File(temps), context::dataSourceIngestIsCancelled);
334  } catch (ReadContentInputStreamException ex) {
335  logger.log(Level.WARNING, String.format("Error reading Chrome bookmark artifacts file '%s' (id=%d).",
336  bookmarkFile.getName(), bookmarkFile.getId()), ex); //NON-NLS
337  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getBookmark.errMsg.errAnalyzingFile",
338  this.getName(), bookmarkFile.getName()));
339  continue;
340  } catch (IOException ex) {
341  logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Chrome bookmark artifacts file '%s' (id=%d).",
342  temps, bookmarkFile.getName(), bookmarkFile.getId()), ex); //NON-NLS
343  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getBookmark.errMsg.errAnalyzingFile",
344  this.getName(), bookmarkFile.getName()));
345  continue;
346  }
347 
348  logger.log(Level.INFO, "{0}- Now getting Bookmarks from {1}", new Object[]{getName(), temps}); //NON-NLS
349  File dbFile = new File(temps);
350  if (context.dataSourceIngestIsCancelled()) {
351  dbFile.delete();
352  break;
353  }
354 
355  FileReader tempReader;
356  try {
357  tempReader = new FileReader(temps);
358  } catch (FileNotFoundException ex) {
359  logger.log(Level.WARNING, "Error while trying to read into the Bookmarks for Chrome.", ex); //NON-NLS
360  continue;
361  }
362 
363  final JsonParser parser = new JsonParser();
364  JsonElement jsonElement;
365  JsonObject jElement, jRoot, jBookmark;
366  JsonArray jBookmarkArray;
367 
368  try {
369  jsonElement = parser.parse(tempReader);
370  jElement = jsonElement.getAsJsonObject();
371  jRoot = jElement.get("roots").getAsJsonObject(); //NON-NLS
372  jBookmark = jRoot.get("bookmark_bar").getAsJsonObject(); //NON-NLS
373  jBookmarkArray = jBookmark.getAsJsonArray("children"); //NON-NLS
374  } catch (JsonIOException | JsonSyntaxException | IllegalStateException ex) {
375  logger.log(Level.WARNING, "Error parsing Json from Chrome Bookmark.", ex); //NON-NLS
376  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getBookmark.errMsg.errAnalyzingFile3",
377  this.getName(), bookmarkFile.getName()));
378  continue;
379  }
380 
381  for (JsonElement result : jBookmarkArray) {
382  JsonObject address = result.getAsJsonObject();
383  if (address == null) {
384  continue;
385  }
386  JsonElement urlEl = address.get("url"); //NON-NLS
387  String url;
388  if (urlEl != null) {
389  url = urlEl.getAsString();
390  } else {
391  url = "";
392  }
393  String name;
394  JsonElement nameEl = address.get("name"); //NON-NLS
395  if (nameEl != null) {
396  name = nameEl.getAsString();
397  } else {
398  name = "";
399  }
400  Long date;
401  JsonElement dateEl = address.get("date_added"); //NON-NLS
402  if (dateEl != null) {
403  date = dateEl.getAsLong();
404  } else {
405  date = Long.valueOf(0);
406  }
407  String domain = NetworkUtils.extractDomain(url);
408  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
409  //TODO Revisit usage of deprecated constructor as per TSK-583
410  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
411  RecentActivityExtracterModuleFactory.getModuleName(), url));
412  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE,
413  RecentActivityExtracterModuleFactory.getModuleName(), name));
414  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
415  RecentActivityExtracterModuleFactory.getModuleName(), (date / 1000000) - Long.valueOf("11644473600")));
416  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
417  RecentActivityExtracterModuleFactory.getModuleName(), browser));
418  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
419  RecentActivityExtracterModuleFactory.getModuleName(), domain));
420 
421  try {
422  bbartifacts.add(createArtifactWithAttributes(TSK_WEB_BOOKMARK, bookmarkFile, bbattributes));
423  } catch (TskCoreException ex) {
424  logger.log(Level.SEVERE, String.format("Failed to create bookmark artifact for file (%d)", bookmarkFile.getId()), ex);
425  }
426 
427  }
428 
429  if(!context.dataSourceIngestIsCancelled()) {
430  postArtifacts(bbartifacts);
431  }
432  bbartifacts.clear();
433  dbFile.delete();
434  }
435  }
436 
443  private void getCookie(String browser, String browserLocation, long ingestJobId) {
444 
445  FileManager fileManager = currentCase.getServices().getFileManager();
446  List<AbstractFile> cookiesFiles;
447  String cookieFileName = COOKIE_FILE_NAME;
448  if (browser.equals(UC_BROWSER_NAME)) {
449  // Wildcard on front and back of Cookies are there for Cookie files that start with something else
450  // ie: UC browser has "Extension Cookies.9" as well as Cookies.9
451  cookieFileName = "%" + COOKIE_FILE_NAME + "%";
452  }
453  try {
454  cookiesFiles = fileManager.findFiles(dataSource, cookieFileName, browserLocation); //NON-NLS
455  } catch (TskCoreException ex) {
456  String msg = NbBundle.getMessage(this.getClass(), "Chrome.getCookie.errMsg.errGettingFiles");
457  logger.log(Level.SEVERE, msg, ex);
458  this.addErrorMessage(this.getName() + ": " + msg);
459  return;
460  }
461 
462  if (cookiesFiles.isEmpty()) {
463  logger.log(Level.INFO, "Didn't find any Chrome cookies files."); //NON-NLS
464  return;
465  }
466 
467  dataFound = true;
468  Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
469  int j = 0;
470  while (j < cookiesFiles.size()) {
471  AbstractFile cookiesFile = cookiesFiles.get(j++);
472  if ((cookiesFile.getSize() == 0) || (cookiesFile.getName().toLowerCase().contains("-slack"))) {
473  continue;
474  }
475  String temps = RAImageIngestModule.getRATempPath(currentCase, browser, ingestJobId) + File.separator + cookiesFile.getName() + j + ".db"; //NON-NLS
476  try {
477  ContentUtils.writeToFile(cookiesFile, new File(temps), context::dataSourceIngestIsCancelled);
478  } catch (ReadContentInputStreamException ex) {
479  logger.log(Level.WARNING, String.format("Error reading Chrome cookie artifacts file '%s' (id=%d).",
480  cookiesFile.getName(), cookiesFile.getId()), ex); //NON-NLS
481  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getCookie.errMsg.errAnalyzeFile",
482  this.getName(), cookiesFile.getName()));
483  continue;
484  } catch (IOException ex) {
485  logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Chrome cookie artifacts file '%s' (id=%d).",
486  temps, cookiesFile.getName(), cookiesFile.getId()), ex); //NON-NLS
487  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getCookie.errMsg.errAnalyzeFile",
488  this.getName(), cookiesFile.getName()));
489  continue;
490  }
491  File dbFile = new File(temps);
492  if (context.dataSourceIngestIsCancelled()) {
493  dbFile.delete();
494  break;
495  }
496 
497  List<HashMap<String, Object>> tempList = this.dbConnect(temps, COOKIE_QUERY);
498  logger.log(Level.INFO, "{0}- Now getting cookies from {1} with {2} artifacts identified.", new Object[]{getName(), temps, tempList.size()}); //NON-NLS
499  for (HashMap<String, Object> result : tempList) {
500  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
501  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
502  RecentActivityExtracterModuleFactory.getModuleName(),
503  ((result.get("host_key").toString() != null) ? result.get("host_key").toString() : ""))); //NON-NLS
504  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
505  RecentActivityExtracterModuleFactory.getModuleName(),
506  (Long.valueOf(result.get("last_access_utc").toString()) / 1000000) - Long.valueOf("11644473600"))); //NON-NLS
507 
508  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
509  RecentActivityExtracterModuleFactory.getModuleName(),
510  ((result.get("name").toString() != null) ? result.get("name").toString() : ""))); //NON-NLS
511  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE,
512  RecentActivityExtracterModuleFactory.getModuleName(),
513  ((result.get("value").toString() != null) ? result.get("value").toString() : ""))); //NON-NLS
514  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
515  RecentActivityExtracterModuleFactory.getModuleName(), browser));
516  String domain = result.get("host_key").toString(); //NON-NLS
517  domain = domain.replaceFirst("^\\.+(?!$)", "");
518  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
519  RecentActivityExtracterModuleFactory.getModuleName(), domain));
520 
521  try {
522  bbartifacts.add(createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes));
523  } catch (TskCoreException ex) {
524  logger.log(Level.SEVERE, String.format("Failed to create cookie artifact for file (%d)", cookiesFile.getId()), ex);
525  }
526  }
527 
528  dbFile.delete();
529  }
530 
531  if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
532  postArtifacts(bbartifacts);
533  }
534  }
535 
542  private void getDownload(String browser, String browserLocation, long ingestJobId) {
543  FileManager fileManager = currentCase.getServices().getFileManager();
544  List<AbstractFile> downloadFiles;
545  String historyFileName = HISTORY_FILE_NAME;
546  if (browser.equals(UC_BROWSER_NAME)) {
547  historyFileName = HISTORY_FILE_NAME + "%";
548  }
549  try {
550  downloadFiles = fileManager.findFiles(dataSource, historyFileName, browserLocation); //NON-NLS
551  } catch (TskCoreException ex) {
552  String msg = NbBundle.getMessage(this.getClass(), "Chrome.getDownload.errMsg.errGettingFiles");
553  logger.log(Level.SEVERE, msg, ex);
554  this.addErrorMessage(this.getName() + ": " + msg);
555  return;
556  }
557 
558  if (downloadFiles.isEmpty()) {
559  logger.log(Level.INFO, "Didn't find any Chrome download files."); //NON-NLS
560  return;
561  }
562 
563  dataFound = true;
564  Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
565  int j = 0;
566  while (j < downloadFiles.size()) {
567  AbstractFile downloadFile = downloadFiles.get(j++);
568  if ((downloadFile.getSize() == 0) || (downloadFile.getName().toLowerCase().contains("-slack"))
569  || (downloadFile.getName().toLowerCase().contains("cache")) || (downloadFile.getName().toLowerCase().contains("index"))) {
570  continue;
571  }
572 
573  String temps = RAImageIngestModule.getRATempPath(currentCase, browser, ingestJobId) + File.separator + downloadFile.getName() + j + ".db"; //NON-NLS
574  try {
575  ContentUtils.writeToFile(downloadFile, new File(temps), context::dataSourceIngestIsCancelled);
576  } catch (ReadContentInputStreamException ex) {
577  logger.log(Level.WARNING, String.format("Error reading Chrome download artifacts file '%s' (id=%d).",
578  downloadFile.getName(), downloadFile.getId()), ex); //NON-NLS
579  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getDownload.errMsg.errAnalyzeFiles1",
580  this.getName(), downloadFile.getName()));
581  continue;
582  } catch (IOException ex) {
583  logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Chrome download artifacts file '%s' (id=%d).",
584  temps, downloadFile.getName(), downloadFile.getId()), ex); //NON-NLS
585  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getDownload.errMsg.errAnalyzeFiles1",
586  this.getName(), downloadFile.getName()));
587  continue;
588  }
589  File dbFile = new File(temps);
590  if (context.dataSourceIngestIsCancelled()) {
591  dbFile.delete();
592  break;
593  }
594 
595  List<HashMap<String, Object>> tempList;
596 
597  if (isChromePreVersion30(temps)) {
598  tempList = this.dbConnect(temps, DOWNLOAD_QUERY);
599  } else {
600  tempList = this.dbConnect(temps, DOWNLOAD_QUERY_V30);
601  }
602 
603  logger.log(Level.INFO, "{0}- Now getting downloads from {1} with {2} artifacts identified.", new Object[]{getName(), temps, tempList.size()}); //NON-NLS
604  for (HashMap<String, Object> result : tempList) {
605  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
606  String fullPath = result.get("full_path").toString(); //NON-NLS
607  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
608  RecentActivityExtracterModuleFactory.getModuleName(), fullPath));
609  long pathID = Util.findID(dataSource, fullPath);
610  if (pathID != -1) {
611  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID,
612  NbBundle.getMessage(this.getClass(),
613  "Chrome.parentModuleName"), pathID));
614  }
615  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
616  RecentActivityExtracterModuleFactory.getModuleName(),
617  ((result.get("url").toString() != null) ? result.get("url").toString() : ""))); //NON-NLS
618  //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", ((result.get("url").toString() != null) ? EscapeUtil.decodeURL(result.get("url").toString()) : "")));
619  Long time = (Long.valueOf(result.get("start_time").toString()) / 1000000) - Long.valueOf("11644473600"); //NON-NLS
620 
621  //TODO Revisit usage of deprecated constructor as per TSK-583
622  //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "Recent Activity", "Last Visited", time));
623  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
624  RecentActivityExtracterModuleFactory.getModuleName(), time));
625  String domain = NetworkUtils.extractDomain((result.get("url").toString() != null) ? result.get("url").toString() : ""); //NON-NLS
626  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
627  RecentActivityExtracterModuleFactory.getModuleName(), domain));
628  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
629  RecentActivityExtracterModuleFactory.getModuleName(), browser));
630 
631  // find the downloaded file and create a TSK_ASSOCIATED_OBJECT for it, associating it with the TSK_WEB_DOWNLOAD artifact.
632  try {
633  BlackboardArtifact webDownloadArtifact = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadFile, bbattributes);
634  bbartifacts.add(webDownloadArtifact);
635  String normalizedFullPath = FilenameUtils.normalize(fullPath, true);
636  for (AbstractFile downloadedFile : currentCase.getSleuthkitCase().getFileManager().findFilesExactNameExactPath(dataSource, FilenameUtils.getName(normalizedFullPath), FilenameUtils.getPath(normalizedFullPath))) {
637  bbartifacts.add(createAssociatedArtifact(downloadedFile, webDownloadArtifact));
638  break;
639  }
640  } catch (TskCoreException ex) {
641  logger.log(Level.SEVERE, String.format("Error creating associated object artifact for file '%s'", fullPath), ex); //NON-NLS
642  }
643  }
644 
645  dbFile.delete();
646  }
647 
648  if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
649  postArtifacts(bbartifacts);
650  }
651  }
652 
659  private void getLogins(String browser, String browserLocation, long ingestJobId) {
660 
661  FileManager fileManager = currentCase.getServices().getFileManager();
662  List<AbstractFile> loginDataFiles;
663  String loginDataFileName = LOGIN_DATA_FILE_NAME;
664  if (browser.equals(UC_BROWSER_NAME)) {
665  loginDataFileName = LOGIN_DATA_FILE_NAME + "%";
666  }
667 
668  try {
669  loginDataFiles = fileManager.findFiles(dataSource, loginDataFileName, browserLocation); //NON-NLS
670  } catch (TskCoreException ex) {
671  String msg = NbBundle.getMessage(this.getClass(), "Chrome.getLogin.errMsg.errGettingFiles");
672  logger.log(Level.SEVERE, msg, ex);
673  this.addErrorMessage(this.getName() + ": " + msg);
674  return;
675  }
676 
677  if (loginDataFiles.isEmpty()) {
678  logger.log(Level.INFO, "Didn't find any Chrome Login Data files."); //NON-NLS
679  return;
680  }
681 
682  dataFound = true;
683  Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
684  int j = 0;
685  while (j < loginDataFiles.size()) {
686  AbstractFile loginDataFile = loginDataFiles.get(j++);
687  if ((loginDataFile.getSize() == 0) || (loginDataFile.getName().toLowerCase().contains("-slack"))) {
688  continue;
689  }
690  String temps = RAImageIngestModule.getRATempPath(currentCase, browser, ingestJobId) + File.separator + loginDataFile.getName() + j + ".db"; //NON-NLS
691  try {
692  ContentUtils.writeToFile(loginDataFile, new File(temps), context::dataSourceIngestIsCancelled);
693  } catch (ReadContentInputStreamException ex) {
694  logger.log(Level.WARNING, String.format("Error reading Chrome login artifacts file '%s' (id=%d).",
695  loginDataFile.getName(), loginDataFile.getId()), ex); //NON-NLS
696  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getLogin.errMsg.errAnalyzingFiles",
697  this.getName(), loginDataFile.getName()));
698  continue;
699  } catch (IOException ex) {
700  logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Chrome login artifacts file '%s' (id=%d).",
701  temps, loginDataFile.getName(), loginDataFile.getId()), ex); //NON-NLS
702  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getLogin.errMsg.errAnalyzingFiles",
703  this.getName(), loginDataFile.getName()));
704  continue;
705  }
706  File dbFile = new File(temps);
707  if (context.dataSourceIngestIsCancelled()) {
708  dbFile.delete();
709  break;
710  }
711  List<HashMap<String, Object>> tempList = this.dbConnect(temps, LOGIN_QUERY);
712  logger.log(Level.INFO, "{0}- Now getting login information from {1} with {2} artifacts identified.", new Object[]{getName(), temps, tempList.size()}); //NON-NLS
713  for (HashMap<String, Object> result : tempList) {
714  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
715 
716  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
717  RecentActivityExtracterModuleFactory.getModuleName(),
718  ((result.get("origin_url").toString() != null) ? result.get("origin_url").toString() : ""))); //NON-NLS
719 
720  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
721  RecentActivityExtracterModuleFactory.getModuleName(),
722  (Long.valueOf(result.get("date_created").toString()) / 1000000) - Long.valueOf("11644473600"))); //NON-NLS
723 
724  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED,
725  RecentActivityExtracterModuleFactory.getModuleName(),
726  (NetworkUtils.extractDomain((result.get("origin_url").toString() != null) ? result.get("origin_url").toString() : "")))); //NON-NLS
727 
728  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
729  RecentActivityExtracterModuleFactory.getModuleName(),
730  ((result.get("username_value").toString() != null) ? result.get("username_value").toString().replaceAll("'", "''") : ""))); //NON-NLS
731 
732  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REALM,
733  RecentActivityExtracterModuleFactory.getModuleName(),
734  ((result.get("signon_realm") != null && result.get("signon_realm").toString() != null) ? result.get("signon_realm").toString() : ""))); //NON-NLS
735 
736  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
737  RecentActivityExtracterModuleFactory.getModuleName(),
738  result.containsKey("signon_realm") ? NetworkUtils.extractDomain(result.get("signon_realm").toString()) : "")); //NON-NLS
739 
740  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
741  RecentActivityExtracterModuleFactory.getModuleName(), browser));
742 
743  try {
744  bbartifacts.add(createArtifactWithAttributes(ARTIFACT_TYPE.TSK_SERVICE_ACCOUNT, loginDataFile, bbattributes));
745  } catch (TskCoreException ex) {
746  logger.log(Level.SEVERE, String.format("Failed to create service account artifact for file (%d)", loginDataFile.getId()), ex);
747  }
748  }
749 
750  dbFile.delete();
751  }
752 
753  if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
754  postArtifacts(bbartifacts);
755  }
756  }
757 
765  private void getAutofill(String browser, String browserLocation, long ingestJobId) {
766 
767  FileManager fileManager = currentCase.getServices().getFileManager();
768  List<AbstractFile> webDataFiles;
769  String webDataFileName = WEB_DATA_FILE_NAME;
770  if (browser.equals(UC_BROWSER_NAME)) {
771  webDataFileName = WEB_DATA_FILE_NAME + "%";
772  }
773 
774  try {
775  webDataFiles = fileManager.findFiles(dataSource, webDataFileName, browserLocation); //NON-NLS
776  } catch (TskCoreException ex) {
777  String msg = NbBundle.getMessage(this.getClass(), "Chrome.getAutofills.errMsg.errGettingFiles");
778  logger.log(Level.SEVERE, msg, ex);
779  this.addErrorMessage(this.getName() + ": " + msg);
780  return;
781  }
782 
783  if (webDataFiles.isEmpty()) {
784  logger.log(Level.INFO, "Didn't find any Chrome Web Data files."); //NON-NLS
785  return;
786  }
787 
788  dataFound = true;
789  Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
790  int j = 0;
791  while (j < webDataFiles.size()) {
792  databaseEncrypted = false;
793  AbstractFile webDataFile = webDataFiles.get(j++);
794  if ((webDataFile.getSize() == 0) || (webDataFile.getName().toLowerCase().contains("-slack"))) {
795  continue;
796  }
797  String tempFilePath = RAImageIngestModule.getRATempPath(currentCase, browser, ingestJobId) + File.separator + webDataFile.getName() + j + ".db"; //NON-NLS
798  try {
799  ContentUtils.writeToFile(webDataFile, new File(tempFilePath), context::dataSourceIngestIsCancelled);
800  } catch (ReadContentInputStreamException ex) {
801  logger.log(Level.WARNING, String.format("Error reading Chrome Autofill artifacts file '%s' (id=%d).",
802  webDataFile.getName(), webDataFile.getId()), ex); //NON-NLS
803  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getAutofill.errMsg.errAnalyzingFiles",
804  this.getName(), webDataFile.getName()));
805  continue;
806  } catch (IOException ex) {
807  logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Chrome Web data file '%s' (id=%d).",
808  tempFilePath, webDataFile.getName(), webDataFile.getId()), ex); //NON-NLS
809  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getLogin.errMsg.errAnalyzingFiles",
810  this.getName(), webDataFile.getName()));
811  continue;
812  }
813  File dbFile = new File(tempFilePath);
814  if (context.dataSourceIngestIsCancelled()) {
815  dbFile.delete();
816  break;
817  }
818 
819  // The DB schema is little different in schema version 8x vs older versions
820  boolean isSchemaV8X = Util.checkColumn("date_created", "autofill", tempFilePath);
821 
822  // get form autofill artifacts
823  bbartifacts.addAll(getFormAutofillArtifacts(webDataFile, tempFilePath, isSchemaV8X, browser));
824  try {
825  // get form address atifacts
826  getFormAddressArtifacts(webDataFile, tempFilePath, isSchemaV8X);
827  if (databaseEncrypted) {
828  String comment = String.format("%s Autofill Database Encryption Detected", browser);
829  Collection<BlackboardAttribute> bbattributes = Arrays.asList(
830  new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COMMENT,
831  RecentActivityExtracterModuleFactory.getModuleName(), comment));
832 
833  bbartifacts.add(
834  webDataFile.newAnalysisResult(
835  BlackboardArtifact.Type.TSK_ENCRYPTION_DETECTED, Score.SCORE_NOTABLE,
836  null, null, comment, bbattributes).getAnalysisResult());
837  }
838  } catch (NoCurrentCaseException | TskCoreException | Blackboard.BlackboardException ex) {
839  logger.log(Level.SEVERE, String.format("Error adding artifacts to the case database "
840  + "for chrome file %s [objId=%d]", webDataFile.getName(), webDataFile.getId()), ex);
841  }
842 
843  dbFile.delete();
844  }
845 
846  if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
847  postArtifacts(bbartifacts);
848  }
849  }
850 
861  private Collection<BlackboardArtifact> getFormAutofillArtifacts(AbstractFile webDataFile, String dbFilePath, boolean isSchemaV8X, String browser) {
862 
863  Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
864 
865  // The DB Schema is little different in version 8x vs older versions
866  String autoFillquery = (isSchemaV8X) ? AUTOFILL_QUERY_V8X
867  : AUTOFILL_QUERY;
868 
869  List<HashMap<String, Object>> autofills = this.dbConnect(dbFilePath, autoFillquery);
870  logger.log(Level.INFO, "{0}- Now getting Autofill information from {1} with {2} artifacts identified.", new Object[]{getName(), dbFilePath, autofills.size()}); //NON-NLS
871  for (HashMap<String, Object> result : autofills) {
872  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
873 
874  // extract all common attributes
875  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
876  NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
877  ((result.get("name").toString() != null) ? result.get("name").toString() : ""))); //NON-NLS
878 
879  fieldEncrypted = false;
880  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE,
881  RecentActivityExtracterModuleFactory.getModuleName(),
882  processFields(result.get("value")))); //NON-NLS
883 
884  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT,
885  RecentActivityExtracterModuleFactory.getModuleName(),
886  (Integer.valueOf(result.get("count").toString())))); //NON-NLS
887 
888  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
889  RecentActivityExtracterModuleFactory.getModuleName(),
890  Long.valueOf(result.get("date_created").toString()))); //NON-NLS
891 
892  // get schema version specific attributes
893  if (isSchemaV8X) {
894  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
895  RecentActivityExtracterModuleFactory.getModuleName(),
896  Long.valueOf(result.get("date_last_used").toString()))); //NON-NLS
897  }
898 
899  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
900  RecentActivityExtracterModuleFactory.getModuleName(), browser));
901  if (fieldEncrypted) {
902  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COMMENT,
903  RecentActivityExtracterModuleFactory.getModuleName(), ENCRYPTED_FIELD_MESSAGE));
904  }
905 
906  // Add an artifact
907  try {
908  bbartifacts.add(createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_FORM_AUTOFILL, webDataFile, bbattributes));
909  } catch (TskCoreException ex) {
910  logger.log(Level.SEVERE, String.format("Failed to create web form autopfill artifact for file (%d)", webDataFile.getId()), ex);
911  }
912  }
913 
914  // return all extracted artifacts
915  return bbartifacts;
916  }
917 
929  private void getFormAddressArtifacts(AbstractFile webDataFile, String dbFilePath, boolean isSchemaV8X) throws NoCurrentCaseException,
930  TskCoreException, Blackboard.BlackboardException {
931 
932  String webformAddressQuery = (isSchemaV8X) ? WEBFORM_ADDRESS_QUERY_V8X
933  : WEBFORM_ADDRESS_QUERY;
934 
935  // Helper to create web form address artifacts.
936  WebBrowserArtifactsHelper helper = new WebBrowserArtifactsHelper(
937  Case.getCurrentCaseThrows().getSleuthkitCase(),
938  NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
939  webDataFile
940  );
941 
942  // Get Web form addresses
943  List<HashMap<String, Object>> addresses = this.dbConnect(dbFilePath, webformAddressQuery);
944  logger.log(Level.INFO, "{0}- Now getting Web form addresses from {1} with {2} artifacts identified.", new Object[]{getName(), dbFilePath, addresses.size()}); //NON-NLS
945  for (HashMap<String, Object> result : addresses) {
946 
947  fieldEncrypted = false;
948 
949  String first_name = processFields(result.get("first_name"));
950  String middle_name = processFields(result.get("middle_name"));
951  String last_name = processFields(result.get("last_name"));
952 
953  // get email and phone
954  String email_Addr = processFields(result.get("email"));
955  String phone_number = processFields(result.get("number"));
956 
957  // Get the address fields
958  String city = processFields(result.get("city"));
959  String state = processFields(result.get("state"));
960  String zipcode = processFields(result.get("zipcode"));
961  String country_code = processFields(result.get("country_code"));
962 
963  // schema version specific fields
964  String full_name = "";
965  String street_address = "";
966  long date_modified = 0;
967  int use_count = 0;
968  long use_date = 0;
969 
970  if (isSchemaV8X) {
971 
972  full_name = processFields(result.get("full_name"));
973  street_address = processFields(result.get("street_address"));
974  date_modified = result.get("date_modified").toString() != null ? Long.valueOf(result.get("date_modified").toString()) : 0;
975  use_count = result.get("use_count").toString() != null ? Integer.valueOf(result.get("use_count").toString()) : 0;
976  use_date = result.get("use_date").toString() != null ? Long.valueOf(result.get("use_date").toString()) : 0;
977  } else {
978  String address_line_1 = processFields(result.get("address_line_1"));
979  String address_line_2 = processFields(result.get("address_line_2"));
980  street_address = String.join(" ", address_line_1, address_line_2);
981  }
982 
983  // Create atrributes from extracted fields
984  if (full_name == null || full_name.isEmpty()) {
985  full_name = String.join(" ", first_name, middle_name, last_name);
986  }
987 
988  String locationAddress = String.join(", ", street_address, city, state, zipcode, country_code);
989 
990  List<BlackboardAttribute> otherAttributes = new ArrayList<>();
991  if (date_modified > 0) {
992  otherAttributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_MODIFIED,
993  RecentActivityExtracterModuleFactory.getModuleName(),
994  date_modified)); //NON-NLS
995  if (fieldEncrypted) {
996  otherAttributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COMMENT,
997  RecentActivityExtracterModuleFactory.getModuleName(), ENCRYPTED_FIELD_MESSAGE)); //NON-NLS
998 
999  }
1000  }
1001 
1002  helper.addWebFormAddress(
1003  full_name, email_Addr, phone_number,
1004  locationAddress, 0, use_date,
1005  use_count, otherAttributes);
1006  }
1007  }
1008 
1015  private String processFields(Object dataValue) {
1016 
1017  if (dataValue instanceof byte[]) {
1018  fieldEncrypted = true;
1019  databaseEncrypted = true;
1020  }
1021 
1022  return dataValue.toString() != null ? dataValue.toString() : "";
1023 
1024  }
1025 
1026  private boolean isChromePreVersion30(String temps) {
1027  String query = "PRAGMA table_info(downloads)"; //NON-NLS
1028  List<HashMap<String, Object>> columns = this.dbConnect(temps, query);
1029  for (HashMap<String, Object> col : columns) {
1030  if (col.get("name").equals("url")) { //NON-NLS
1031  return true;
1032  }
1033  }
1034 
1035  return false;
1036  }
1037 }

Copyright © 2012-2021 Basis Technology. Generated on: Thu Jul 8 2021
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.