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

Copyright © 2012-2021 Basis Technology. Generated on: Tue Feb 22 2022
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.