23 package org.sleuthkit.autopsy.recentactivity;
25 import com.google.gson.JsonArray;
26 import com.google.gson.JsonElement;
27 import com.google.gson.JsonIOException;
28 import com.google.gson.JsonObject;
29 import com.google.gson.JsonParser;
30 import com.google.gson.JsonSyntaxException;
31 import org.openide.util.NbBundle;
34 import java.util.logging.Level;
37 import java.io.FileNotFoundException;
38 import java.io.FileReader;
39 import java.io.IOException;
56 class Chrome
extends Extract {
58 private static final String historyQuery =
"SELECT urls.url, urls.title, urls.visit_count, urls.typed_count, "
59 +
"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";
60 private static final String cookieQuery =
"SELECT name, value, host_key, expires_utc,last_access_utc, creation_utc FROM cookies";
61 private static final String downloadQuery =
"SELECT full_path, url, start_time, received_bytes FROM downloads";
62 private static final String downloadQueryVersion30 =
"SELECT current_path AS full_path, url, start_time, received_bytes FROM downloads, downloads_url_chains WHERE downloads.id=downloads_url_chains.id";
63 private static final String loginQuery =
"SELECT origin_url, username_value, signon_realm from logins";
69 moduleName = NbBundle.getMessage(Chrome.class,
"Chrome.moduleName");
74 this.dataSource = dataSource;
75 this.context = context;
87 private void getHistory() {
88 FileManager fileManager = currentCase.getServices().getFileManager();
89 List<AbstractFile> historyFiles;
91 historyFiles = fileManager.
findFiles(dataSource,
"History",
"Chrome");
93 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getHistory.errMsg.errGettingFiles");
94 logger.log(Level.SEVERE, msg, ex);
95 this.addErrorMessage(this.getName() +
": " + msg);
100 List<AbstractFile> allocatedHistoryFiles =
new ArrayList<>();
103 allocatedHistoryFiles.add(historyFile);
108 if (allocatedHistoryFiles.isEmpty()) {
109 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getHistory.errMsg.couldntFindAnyFiles");
110 logger.log(Level.INFO, msg);
115 Collection<BlackboardArtifact> bbartifacts =
new ArrayList<>();
117 while (j < historyFiles.size()) {
120 if (historyFile.
getSize() == 0) {
125 }
catch (IOException ex) {
126 logger.log(Level.SEVERE,
"Error writing temp sqlite db for Chrome web history artifacts.{0}", ex);
127 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getHistory.errMsg.errAnalyzingFile",
128 this.getName(), historyFile.
getName()));
131 File dbFile =
new File(temps);
136 List<HashMap<String, Object>> tempList;
137 tempList = this.dbConnect(temps, historyQuery);
138 logger.log(Level.INFO,
"{0}- Now getting history from {1} with {2}artifacts identified.",
new Object[]{moduleName, temps, tempList.size()});
139 for (HashMap<String, Object> result : tempList) {
140 Collection<BlackboardAttribute> bbattributes =
new ArrayList<BlackboardAttribute>();
142 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
143 ((result.get(
"url").toString() != null) ? result.get(
"url").toString() :
"")));
145 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
146 (Long.valueOf(result.get(
"last_visit_time").toString()) / 1000000) - Long.valueOf(
"11644473600")));
148 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
149 ((result.get(
"from_visit").toString() != null) ? result.get(
"from_visit").toString() :
"")));
151 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
152 ((result.get(
"title").toString() != null) ? result.get(
"title").toString() :
"")));
154 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
155 NbBundle.getMessage(
this.getClass(),
"Chrome.moduleName")));
157 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
158 (Util.extractDomain((result.get(
"url").toString() != null) ? result.get(
"url").toString() :
""))));
162 bbartifacts.add(bbart);
169 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
176 private void getBookmark() {
177 FileManager fileManager = currentCase.getServices().getFileManager();
178 List<AbstractFile> bookmarkFiles = null;
180 bookmarkFiles = fileManager.
findFiles(dataSource,
"Bookmarks",
"Chrome");
182 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getBookmark.errMsg.errGettingFiles");
183 logger.log(Level.SEVERE, msg, ex);
184 this.addErrorMessage(this.getName() +
": " + msg);
188 if (bookmarkFiles.isEmpty()) {
189 logger.log(Level.INFO,
"Didn't find any Chrome bookmark files.");
194 Collection<BlackboardArtifact> bbartifacts =
new ArrayList<>();
197 while (j < bookmarkFiles.size()) {
199 if (bookmarkFile.
getSize() == 0) {
205 }
catch (IOException ex) {
206 logger.log(Level.SEVERE,
"Error writing temp sqlite db for Chrome bookmark artifacts.{0}", ex);
207 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getBookmark.errMsg.errAnalyzingFile",
208 this.getName(), bookmarkFile.
getName()));
212 logger.log(Level.INFO,
"{0}- Now getting Bookmarks from {1}",
new Object[]{moduleName, temps});
213 File dbFile =
new File(temps);
219 FileReader tempReader;
221 tempReader =
new FileReader(temps);
222 }
catch (FileNotFoundException ex) {
223 logger.log(Level.SEVERE,
"Error while trying to read into the Bookmarks for Chrome.", ex);
224 this.addErrorMessage(
225 NbBundle.getMessage(
this.getClass(),
"Chrome.getBookmark.errMsg.errAnalyzeFile", this.getName(),
230 final JsonParser parser =
new JsonParser();
231 JsonElement jsonElement;
232 JsonObject jElement, jRoot, jBookmark;
233 JsonArray jBookmarkArray;
236 jsonElement = parser.parse(tempReader);
237 jElement = jsonElement.getAsJsonObject();
238 jRoot = jElement.get(
"roots").getAsJsonObject();
239 jBookmark = jRoot.get(
"bookmark_bar").getAsJsonObject();
240 jBookmarkArray = jBookmark.getAsJsonArray(
"children");
241 }
catch (JsonIOException | JsonSyntaxException | IllegalStateException ex) {
242 logger.log(Level.WARNING,
"Error parsing Json from Chrome Bookmark.", ex);
243 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getBookmark.errMsg.errAnalyzingFile3",
244 this.getName(), bookmarkFile.
getName()));
248 for (JsonElement result : jBookmarkArray) {
249 JsonObject address = result.getAsJsonObject();
250 if (address == null) {
253 JsonElement urlEl = address.get(
"url");
256 url = urlEl.getAsString();
261 JsonElement nameEl = address.get(
"name");
262 if (nameEl != null) {
263 name = nameEl.getAsString();
268 JsonElement dateEl = address.get(
"date_added");
269 if (dateEl != null) {
270 date = dateEl.getAsLong();
272 date = Long.valueOf(0);
274 String domain = Util.extractDomain(url);
277 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
280 NbBundle.getMessage(
this.getClass(),
281 "Chrome.parentModuleName"), url));
283 NbBundle.getMessage(
this.getClass(),
284 "Chrome.parentModuleName"), name));
286 NbBundle.getMessage(
this.getClass(),
287 "Chrome.parentModuleName"), (date / 1000000) - Long.valueOf(
"11644473600")));
289 NbBundle.getMessage(
this.getClass(),
290 "Chrome.parentModuleName"),
291 NbBundle.getMessage(
this.getClass(),
"Chrome.moduleName")));
293 NbBundle.getMessage(
this.getClass(),
294 "Chrome.parentModuleName"), domain));
298 this.indexArtifact(bbart);
299 bbartifacts.add(bbart);
301 logger.log(Level.SEVERE,
"Error while trying to insert Chrome bookmark artifact{0}", ex);
302 this.addErrorMessage(
303 NbBundle.getMessage(
this.getClass(),
"Chrome.getBookmark.errMsg.errAnalyzingFile4",
304 this.getName(), bookmarkFile.
getName()));
311 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
318 private void getCookie() {
320 FileManager fileManager = currentCase.getServices().getFileManager();
321 List<AbstractFile> cookiesFiles;
323 cookiesFiles = fileManager.
findFiles(dataSource,
"Cookies",
"Chrome");
325 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getCookie.errMsg.errGettingFiles");
326 logger.log(Level.SEVERE, msg, ex);
327 this.addErrorMessage(this.getName() +
": " + msg);
331 if (cookiesFiles.isEmpty()) {
332 logger.log(Level.INFO,
"Didn't find any Chrome cookies files.");
337 Collection<BlackboardArtifact> bbartifacts =
new ArrayList<>();
339 while (j < cookiesFiles.size()) {
341 if (cookiesFile.
getSize() == 0) {
347 }
catch (IOException ex) {
348 logger.log(Level.SEVERE,
"Error writing temp sqlite db for Chrome cookie artifacts.{0}", ex);
349 this.addErrorMessage(
350 NbBundle.getMessage(
this.getClass(),
"Chrome.getCookie.errMsg.errAnalyzeFile", this.getName(),
354 File dbFile =
new File(temps);
360 List<HashMap<String, Object>> tempList = this.dbConnect(temps, cookieQuery);
361 logger.log(Level.INFO,
"{0}- Now getting cookies from {1} with {2}artifacts identified.",
new Object[]{moduleName, temps, tempList.size()});
362 for (HashMap<String, Object> result : tempList) {
363 Collection<BlackboardAttribute> bbattributes =
new ArrayList<BlackboardAttribute>();
365 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
366 ((result.get(
"host_key").toString() != null) ? result.get(
"host_key").toString() :
"")));
368 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
369 (Long.valueOf(result.get(
"last_access_utc").toString()) / 1000000) - Long.valueOf(
"11644473600")));
372 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
373 ((result.get(
"name").toString() != null) ? result.get(
"name").toString() :
"")));
375 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
376 ((result.get(
"value").toString() != null) ? result.get(
"value").toString() :
"")));
378 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
379 NbBundle.getMessage(
this.getClass(),
"Chrome.moduleName")));
380 String domain = result.get(
"host_key").toString();
381 domain = domain.replaceFirst(
"^\\.+(?!$)",
"");
383 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"), domain));
387 bbartifacts.add(bbart);
395 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
402 private void getDownload() {
403 FileManager fileManager = currentCase.getServices().getFileManager();
404 List<AbstractFile> downloadFiles = null;
406 downloadFiles = fileManager.
findFiles(dataSource,
"History",
"Chrome");
408 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getDownload.errMsg.errGettingFiles");
409 logger.log(Level.SEVERE, msg, ex);
410 this.addErrorMessage(this.getName() +
": " + msg);
414 if (downloadFiles.isEmpty()) {
415 logger.log(Level.INFO,
"Didn't find any Chrome download files.");
420 Collection<BlackboardArtifact> bbartifacts =
new ArrayList<>();
422 while (j < downloadFiles.size()) {
424 if (downloadFile.
getSize() == 0) {
430 }
catch (IOException ex) {
431 logger.log(Level.SEVERE,
"Error writing temp sqlite db for Chrome download artifacts.{0}", ex);
432 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getDownload.errMsg.errAnalyzeFiles1",
433 this.getName(), downloadFile.
getName()));
436 File dbFile =
new File(temps);
442 List<HashMap<String, Object>> tempList;
444 if (isChromePreVersion30(temps)) {
445 tempList = this.dbConnect(temps, downloadQuery);
447 tempList = this.dbConnect(temps, downloadQueryVersion30);
450 logger.log(Level.INFO,
"{0}- Now getting downloads from {1} with {2}artifacts identified.",
new Object[]{moduleName, temps, tempList.size()});
451 for (HashMap<String, Object> result : tempList) {
452 Collection<BlackboardAttribute> bbattributes =
new ArrayList<BlackboardAttribute>();
454 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"), (result.get(
"full_path").toString())));
455 long pathID = Util.findID(dataSource, (result.get(
"full_path").toString()));
458 NbBundle.getMessage(
this.getClass(),
459 "Chrome.parentModuleName"), pathID));
462 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
463 ((result.get(
"url").toString() != null) ? result.get(
"url").toString() :
"")));
465 Long time = (Long.valueOf(result.get(
"start_time").toString()) / 1000000) - Long.valueOf(
"11644473600");
470 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"), time));
471 String domain = Util.extractDomain((result.get(
"url").toString() != null) ? result.get(
"url").toString() :
"");
473 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"), domain));
475 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
476 NbBundle.getMessage(
this.getClass(),
"Chrome.moduleName")));
480 bbartifacts.add(bbart);
488 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
495 private void getLogin() {
496 FileManager fileManager = currentCase.getServices().getFileManager();
497 List<AbstractFile> signonFiles;
499 signonFiles = fileManager.
findFiles(dataSource,
"signons.sqlite",
"Chrome");
501 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getLogin.errMsg.errGettingFiles");
502 logger.log(Level.SEVERE, msg, ex);
503 this.addErrorMessage(this.getName() +
": " + msg);
507 if (signonFiles.isEmpty()) {
508 logger.log(Level.INFO,
"Didn't find any Chrome signon files.");
513 Collection<BlackboardArtifact> bbartifacts =
new ArrayList<>();
515 while (j < signonFiles.size()) {
517 if (signonFile.
getSize() == 0) {
523 }
catch (IOException ex) {
524 logger.log(Level.SEVERE,
"Error writing temp sqlite db for Chrome login artifacts.{0}", ex);
525 this.addErrorMessage(
526 NbBundle.getMessage(
this.getClass(),
"Chrome.getLogin.errMsg.errAnalyzingFiles", this.getName(),
530 File dbFile =
new File(temps);
535 List<HashMap<String, Object>> tempList = this.dbConnect(temps, loginQuery);
536 logger.log(Level.INFO,
"{0}- Now getting login information from {1} with {2}artifacts identified.",
new Object[]{moduleName, temps, tempList.size()});
537 for (HashMap<String, Object> result : tempList) {
538 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
540 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
541 ((result.get(
"origin_url").toString() != null) ? result.get(
"origin_url").toString() :
"")));
546 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
547 (Long.valueOf(result.get(
"last_visit_time").toString()) / 1000000) - Long.valueOf(
"11644473600")));
549 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
550 ((result.get(
"from_visit").toString() != null) ? result.get(
"from_visit").toString() :
"")));
552 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
553 ((result.get(
"title").toString() != null) ? result.get(
"title").toString() :
"")));
555 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
556 NbBundle.getMessage(
this.getClass(),
"Chrome.moduleName")));
558 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
559 (Util.extractDomain((result.get(
"origin_url").toString() != null) ? result.get(
"url").toString() :
""))));
561 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
562 ((result.get(
"username_value").toString() != null) ? result.get(
"username_value").toString().replaceAll(
"'",
"''") :
"")));
564 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
565 result.get(
"signon_realm").toString()));
569 bbartifacts.add(bbart);
573 Collection<BlackboardAttribute> osAcctAttributes =
new ArrayList<>();
575 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
576 ((result.get(
"username_value").toString() != null) ? result.get(
"username_value").toString().replaceAll(
"'",
"''") :
"")));
584 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
588 private boolean isChromePreVersion30(String temps) {
589 String query =
"PRAGMA table_info(downloads)";
590 List<HashMap<String, Object>> columns = this.dbConnect(temps, query);
591 for (HashMap<String, Object> col : columns) {
592 if (col.get(
"name").equals(
"url")) {
void addAttributes(Collection< BlackboardAttribute > attributes)
static String getRATempPath(Case a_case, String mod)
static< T > long writeToFile(Content content, java.io.File outputFile, ProgressHandle progress, Future< T > worker, boolean source)
void fireModuleDataEvent(ModuleDataEvent moduleDataEvent)
boolean dataSourceIngestIsCancelled()
BlackboardArtifact newArtifact(int artifactTypeID)
synchronized List< AbstractFile > findFiles(String fileName)
synchronized static Logger getLogger(String name)
static synchronized IngestServices getInstance()