From 9189ffa60a33dfa049da0399470ecde7d3f94fd2 Mon Sep 17 00:00:00 2001 From: Kelly Kelly <kelly@basistech.com> Date: Wed, 3 Feb 2021 14:38:39 -0500 Subject: [PATCH] Initial commit --- bindings/java/doxygen/artifact_catalog.dox | 1 + .../org/sleuthkit/datamodel/Bundle.properties | 17 ++- .../datamodel/Bundle.properties-MERGED | 17 ++- ...ineEventArtifactTypeSingleDescription.java | 2 +- .../datamodel/TimelineEventType.java | 105 ++++++++++++++++-- .../sleuthkit/datamodel/TimelineManager.java | 36 +++++- 6 files changed, 154 insertions(+), 24 deletions(-) diff --git a/bindings/java/doxygen/artifact_catalog.dox b/bindings/java/doxygen/artifact_catalog.dox index 39d548bf7..684e1e052 100644 --- a/bindings/java/doxygen/artifact_catalog.dox +++ b/bindings/java/doxygen/artifact_catalog.dox @@ -777,6 +777,7 @@ A Web cookie found. - TSK_VALUE (The Web cookie value attribute) ### OPTIONAL ATTRIBUTES +- TSK_DATETIME_ACCESSED (Datetime the Web Cookie was last accessed, in seconds since 1970-01-01T00:00:00Z) - TSK_DATETIME_CREATED (Datetime the Web cookie was created, in seconds since 1970-01-01T00:00:00Z) - TSK_DATETIME_START (Datetime the Web cookie session was started, in seconds since 1970-01-01T00:00:00Z) - TSK_DATETIME_END (Expiration datetime of the Web cookie, in seconds since 1970-01-01T00:00:00Z) diff --git a/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties b/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties index 1cfc1a623..43fa3fa38 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties +++ b/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties @@ -329,8 +329,10 @@ FileSystemTypes.fileChanged.name=File Changed MiscTypes.message.name=Messages MiscTypes.GPSRoutes.name=GPS Routes MiscTypes.GPSTrackpoint.name=GPS Trackpoint -MiscTypes.Calls.name=Calls -MiscTypes.Email.name=Email +MiscTypes.Calls.name=Call Start +MiscTypes.CallsEnd.name=Call End +MiscTypes.Email.name=Email Sent +MiscTypes.EmailRcvd.name=Email Received MiscTypes.recentDocuments.name=Recent Documents MiscTypes.installedPrograms.name=Installed Programs MiscTypes.exif.name=Exif @@ -347,12 +349,17 @@ MiscTypes.metadataCreated.name=Document Created MiscTypes.programexecuted.name=Program Execution RootEventType.eventTypes.name=Event Types WebTypes.webDownloads.name=Web Downloads -WebTypes.webCookies.name=Web Cookies +WebTypes.webCookies.name=Web Cookies Create +WebTypes.webCookiesAccessed.name=Web Cookies Accessed +WebTypes.webCookiesStart.name=Web Cookies Start +WebTypes.webCookiesEnd.name=Web Cookies End WebTypes.webBookmarks.name=Web Bookmarks WebTypes.webHistory.name=Web History WebTypes.webSearch.name=Web Searches -WebTypes.webFormAutoFill.name=Web Form Autofill -WebTypes.webFormAddress.name=Web Form Address +WebTypes.webFormAutoFill.name=Web Form Autofill Created +WebTypes.webFormAddress.name=Web Form Address Created +WebTypes.webFormAddressModified.name=Web Form Address Modified +WebTypes.webFormAutofillAccessed.name=Web Form Autofill Accessed CustomTypes.other.name=Standard Types CustomTypes.userCreated.name=Custom Types BaseTypes.customTypes.name=Other diff --git a/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties-MERGED b/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties-MERGED index 1cfc1a623..43fa3fa38 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties-MERGED +++ b/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties-MERGED @@ -329,8 +329,10 @@ FileSystemTypes.fileChanged.name=File Changed MiscTypes.message.name=Messages MiscTypes.GPSRoutes.name=GPS Routes MiscTypes.GPSTrackpoint.name=GPS Trackpoint -MiscTypes.Calls.name=Calls -MiscTypes.Email.name=Email +MiscTypes.Calls.name=Call Start +MiscTypes.CallsEnd.name=Call End +MiscTypes.Email.name=Email Sent +MiscTypes.EmailRcvd.name=Email Received MiscTypes.recentDocuments.name=Recent Documents MiscTypes.installedPrograms.name=Installed Programs MiscTypes.exif.name=Exif @@ -347,12 +349,17 @@ MiscTypes.metadataCreated.name=Document Created MiscTypes.programexecuted.name=Program Execution RootEventType.eventTypes.name=Event Types WebTypes.webDownloads.name=Web Downloads -WebTypes.webCookies.name=Web Cookies +WebTypes.webCookies.name=Web Cookies Create +WebTypes.webCookiesAccessed.name=Web Cookies Accessed +WebTypes.webCookiesStart.name=Web Cookies Start +WebTypes.webCookiesEnd.name=Web Cookies End WebTypes.webBookmarks.name=Web Bookmarks WebTypes.webHistory.name=Web History WebTypes.webSearch.name=Web Searches -WebTypes.webFormAutoFill.name=Web Form Autofill -WebTypes.webFormAddress.name=Web Form Address +WebTypes.webFormAutoFill.name=Web Form Autofill Created +WebTypes.webFormAddress.name=Web Form Address Created +WebTypes.webFormAddressModified.name=Web Form Address Modified +WebTypes.webFormAutofillAccessed.name=Web Form Autofill Accessed CustomTypes.other.name=Standard Types CustomTypes.userCreated.name=Custom Types BaseTypes.customTypes.name=Other diff --git a/bindings/java/src/org/sleuthkit/datamodel/TimelineEventArtifactTypeSingleDescription.java b/bindings/java/src/org/sleuthkit/datamodel/TimelineEventArtifactTypeSingleDescription.java index 84f71ba7d..f1c297f21 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/TimelineEventArtifactTypeSingleDescription.java +++ b/bindings/java/src/org/sleuthkit/datamodel/TimelineEventArtifactTypeSingleDescription.java @@ -44,7 +44,7 @@ public TimelineEventDescriptionWithTime makeEventDescription(BlackboardArtifact } long time = timeAttribute.getValueLong(); - return new TimelineEventDescriptionWithTime(time, null, null, description); + return new TimelineEventDescriptionWithTime(time, timeAttribute.getDisplayString(), null, description); } TimelineEventArtifactTypeSingleDescription(int typeID, String displayName, diff --git a/bindings/java/src/org/sleuthkit/datamodel/TimelineEventType.java b/bindings/java/src/org/sleuthkit/datamodel/TimelineEventType.java index 43f6749b4..8c188f6b4 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/TimelineEventType.java +++ b/bindings/java/src/org/sleuthkit/datamodel/TimelineEventType.java @@ -1,7 +1,7 @@ /* * Sleuth Kit Data Model * - * Copyright 2018-2019 Basis Technology Corp. + * Copyright 2018-2021 Basis Technology Corp. * Contact: carrier <at> sleuthkit <dot> org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -202,8 +202,12 @@ public SortedSet< TimelineEventType> getChildren() { HierarchyLevel.CATEGORY, ROOT_EVENT_TYPE) { @Override public SortedSet< TimelineEventType> getChildren() { - return ImmutableSortedSet.of(WEB_DOWNLOADS, WEB_COOKIE, WEB_BOOKMARK, - WEB_HISTORY, WEB_SEARCH, WEB_FORM_AUTOFILL, WEB_FORM_ADDRESSES); + return ImmutableSortedSet.of(WEB_DOWNLOADS, WEB_COOKIE, + WEB_COOKIE_ACCESSED, WEB_COOKIE_START, + WEB_COOKIE_END, WEB_BOOKMARK, + WEB_HISTORY, WEB_SEARCH, WEB_FORM_AUTOFILL, + WEB_FORM_ADDRESSES, WEB_FORM_ADDRESSES_MODIFIED, + WEB_FORM_AUTOFILL_ACCESSED); } }; @@ -221,7 +225,7 @@ public int compare(TimelineEventType o1, TimelineEventType o2) { } }); - builder.add(CALL_LOG, DEVICES_ATTACHED, EMAIL, + builder.add(CALL_LOG, CALL_LOG_END, DEVICES_ATTACHED, EMAIL, EMAIL_RCVD, EXIF, GPS_BOOKMARK, GPS_LAST_KNOWN_LOCATION, GPS_TRACKPOINT, GPS_ROUTE, GPS_SEARCH, GPS_TRACK, INSTALLED_PROGRAM, LOG_ENTRY, MESSAGE, METADATA_LAST_PRINTED, METADATA_LAST_SAVED, METADATA_CREATED, PROGRAM_EXECUTION, @@ -258,7 +262,7 @@ public int compare(TimelineEventType o1, TimelineEventType o2) { getBundle().getString("WebTypes.webCookies.name"),// NON-NLS WEB_ACTIVITY, new BlackboardArtifact.Type(TSK_WEB_COOKIE), - new Type(TSK_DATETIME), + new Type(TSK_DATETIME_CREATED), new Type(TSK_URL)); TimelineEventType WEB_BOOKMARK = new URLArtifactEventType(10, @@ -358,7 +362,7 @@ public int compare(TimelineEventType o1, TimelineEventType o2) { phoneNumber = getAttributeSafe(artf, new Type(TSK_PHONE_NUMBER_FROM)); } - return stringValueOf(phoneNumber); + return "Start: " + stringValueOf(phoneNumber); }, new AttributeExtractor(new Type(TSK_DIRECTION))); @@ -376,7 +380,7 @@ public int compare(TimelineEventType o1, TimelineEventType o2) { if (emailTo.length() > TimelineEventArtifactTypeImpl.EMAIL_TO_FROM_LENGTH_MAX) { emailTo = emailTo.substring(0, TimelineEventArtifactTypeImpl.EMAIL_TO_FROM_LENGTH_MAX); } - return emailFrom + " to " + emailTo; // NON-NLS + return "Sent from: " + emailFrom + "Sent to: " + emailTo; // NON-NLS }, new AttributeExtractor(new Type(TSK_SUBJECT)), artf -> { @@ -473,7 +477,7 @@ public SortedSet< TimelineEventType> getChildren() { final BlackboardAttribute name = getAttributeSafe(artf, new Type(TSK_NAME)); final BlackboardAttribute value = getAttributeSafe(artf, new Type(TSK_VALUE)); final BlackboardAttribute count = getAttributeSafe(artf, new Type(TSK_COUNT)); - return stringValueOf(name) + ":" + stringValueOf(value) + " count: " + stringValueOf(count); // NON-NLS + return stringValueOf(name) + ":" + stringValueOf(value); // NON-NLS }, new EmptyExtractor(), new EmptyExtractor()); TimelineEventType WEB_FORM_ADDRESSES = new URLArtifactEventType(28, @@ -569,6 +573,91 @@ public SortedSet< TimelineEventType> getChildren() { } return "";}, new AttributeExtractor(new Type(TSK_COMMENT))); + + TimelineEventType WEB_FORM_AUTOFILL_ACCESSED = new TimelineEventArtifactTypeImpl(37, + getBundle().getString("WebTypes.webFormAutofillAccessed.name"), + WEB_ACTIVITY, + new BlackboardArtifact.Type(TSK_WEB_FORM_AUTOFILL), + new Type(TSK_DATETIME_ACCESSED), + artf -> { + final BlackboardAttribute name = getAttributeSafe(artf, new Type(TSK_NAME)); + final BlackboardAttribute value = getAttributeSafe(artf, new Type(TSK_VALUE)); + final BlackboardAttribute count = getAttributeSafe(artf, new Type(TSK_COUNT)); + return stringValueOf(name) + ":" + stringValueOf(value) + " Access count: " + stringValueOf(count); // NON-NLS + }, new EmptyExtractor(), new EmptyExtractor()); + + TimelineEventType CALL_LOG_END = new TimelineEventArtifactTypeImpl(38, + getBundle().getString("MiscTypes.CallsEnd.name"), // NON-NLS + MISC_TYPES, + new BlackboardArtifact.Type(TSK_CALLLOG), + new Type(TSK_DATETIME_END), + new AttributeExtractor(new Type(TSK_NAME)), + artf -> { + BlackboardAttribute phoneNumber = getAttributeSafe(artf, new Type(TSK_PHONE_NUMBER)); + if (phoneNumber == null) { + phoneNumber = getAttributeSafe(artf, new Type(TSK_PHONE_NUMBER_TO)); + } + if (phoneNumber == null) { + phoneNumber = getAttributeSafe(artf, new Type(TSK_PHONE_NUMBER_FROM)); + } + + return "End: " + stringValueOf(phoneNumber); + }, + new AttributeExtractor(new Type(TSK_DIRECTION))); + + TimelineEventType EMAIL_RCVD = new TimelineEventArtifactTypeImpl(38, + getBundle().getString("MiscTypes.EmailRcvd.name"), // NON-NLS + MISC_TYPES, + new BlackboardArtifact.Type(TSK_EMAIL_MSG), + new Type(TSK_DATETIME_RCVD), + artf -> { + String emailFrom = stringValueOf(getAttributeSafe(artf, new Type(TSK_EMAIL_FROM))); + if (emailFrom.length() > TimelineEventArtifactTypeImpl.EMAIL_TO_FROM_LENGTH_MAX) { + emailFrom = emailFrom.substring(0, TimelineEventArtifactTypeImpl.EMAIL_TO_FROM_LENGTH_MAX); + } + String emailTo = stringValueOf(getAttributeSafe(artf, new Type(TSK_EMAIL_TO))); + if (emailTo.length() > TimelineEventArtifactTypeImpl.EMAIL_TO_FROM_LENGTH_MAX) { + emailTo = emailTo.substring(0, TimelineEventArtifactTypeImpl.EMAIL_TO_FROM_LENGTH_MAX); + } + return "Received from: " + emailFrom + " Received by: " + emailTo; // NON-NLS + }, + new AttributeExtractor(new Type(TSK_SUBJECT)), + artf -> { + final BlackboardAttribute msgAttribute = getAttributeSafe(artf, new Type(TSK_EMAIL_CONTENT_PLAIN)); + String msg = stringValueOf(msgAttribute); + if (msg.length() > TimelineEventArtifactTypeImpl.EMAIL_FULL_DESCRIPTION_LENGTH_MAX) { + msg = msg.substring(0, TimelineEventArtifactTypeImpl.EMAIL_FULL_DESCRIPTION_LENGTH_MAX); + } + return msg; + }); + + TimelineEventType WEB_FORM_ADDRESSES_MODIFIED = new URLArtifactEventType(39, + getBundle().getString("WebTypes.webFormAddressModified.name"),//NON-NLS + WEB_ACTIVITY, + new BlackboardArtifact.Type(TSK_WEB_FORM_ADDRESS), + new Type(TSK_DATETIME_MODIFIED), + new Type(TSK_EMAIL)); + + TimelineEventType WEB_COOKIE_ACCESSED = new URLArtifactEventType(40, + getBundle().getString("WebTypes.webCookiesAccessed.name"),// NON-NLS + WEB_ACTIVITY, + new BlackboardArtifact.Type(TSK_WEB_COOKIE), + new Type(TSK_DATETIME_ACCESSED), + new Type(TSK_URL)); + + TimelineEventType WEB_COOKIE_END = new URLArtifactEventType(41, + getBundle().getString("WebTypes.webCookiesEnd.name"),// NON-NLS + WEB_ACTIVITY, + new BlackboardArtifact.Type(TSK_WEB_COOKIE), + new Type(TSK_DATETIME_END), + new Type(TSK_URL)); + + TimelineEventType WEB_COOKIE_START = new URLArtifactEventType(42, + getBundle().getString("WebTypes.webCookiesStart.name"),// NON-NLS + WEB_ACTIVITY, + new BlackboardArtifact.Type(TSK_WEB_COOKIE), + new Type(TSK_DATETIME_START), + new Type(TSK_URL)); static SortedSet<? extends TimelineEventType> getCategoryTypes() { return ROOT_EVENT_TYPE.getChildren(); diff --git a/bindings/java/src/org/sleuthkit/datamodel/TimelineManager.java b/bindings/java/src/org/sleuthkit/datamodel/TimelineManager.java index a3771f382..b1d948e62 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/TimelineManager.java +++ b/bindings/java/src/org/sleuthkit/datamodel/TimelineManager.java @@ -495,11 +495,12 @@ private long addEventDescription(long dataSourceObjId, long fileObjId, Long arti // if no inserted rows, there is a conflict due to a duplicate event // description. If that happens, return null as no id was inserted. if (row < 1) { - throw new DuplicateException(String.format( - "An event description already exists for [fullDescription: %s, contentId: %d, artifactId: %s]", - fullDescription == null ? "<null>" : fullDescription, - fileObjId, - artifactID == null ? "<null>" : Long.toString(artifactID))); +// throw new DuplicateException(String.format( +// "An event description already exists for [fullDescription: %s, contentId: %d, artifactId: %s]", +// fullDescription == null ? "<null>" : fullDescription, +// fileObjId, +// artifactID == null ? "<null>" : Long.toString(artifactID))); + } try (ResultSet generatedKeys = insertDescriptionStmt.getGeneratedKeys()) { @@ -519,6 +520,31 @@ private long addEventDescription(long dataSourceObjId, long fileObjId, Long arti caseDB.releaseSingleUserCaseWriteLock(); } } + + private long getEventDescription(long dataSourceObjId, long fileObjId, Long artifactID, + String fullDescription, String medDescription, String shortDescription, CaseDbConnection connection) throws SQLException { + + String query = "SELECT event_description_id FROM tsk_event_descriptions " + + "WHERE data_source_obj_id = " + dataSourceObjId + + " AND content_obj_id = " + fileObjId + + " AND artifact_id = " + artifactID + + " AND full_description " + (fullDescription != null ? "= '" + fullDescription + "'" : "IS null") + + " AND med_description " + (medDescription != null ? "= '" + medDescription + "'" : "IS null") + + " AND short_description " + (shortDescription != null ? "= '" + shortDescription + "'" : "IS null"); + + caseDB.acquireSingleUserCaseReadLock(); + try(ResultSet resultSet = connection.createStatement().executeQuery(query)) { + + if(resultSet.next()) { + long id = resultSet.getLong(1); + return id; + } + } finally { + caseDB.releaseSingleUserCaseReadLock(); + } + + return -1; + } Collection<TimelineEvent> addEventsForNewFile(AbstractFile file, CaseDbConnection connection) throws TskCoreException { Set<TimelineEvent> events = addEventsForNewFileQuiet(file, connection); -- GitLab