From 59f0afb95ff3667f942573953df575fa1a4acd68 Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Tue, 11 Jul 2023 14:37:06 -0400 Subject: [PATCH 01/94] Update NEWS.txt Add updates for version 4.21.0 --- NEWS.txt | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/NEWS.txt b/NEWS.txt index 11c56f01c8..83f6bae954 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -1,3 +1,31 @@ +---------------- VERSION 4.21.0 -------------- +General +- Update Java to version 17 + +Recent Activity Updates: +- Check For Malicious Chrome Extensions + +Ingest Module Updates: +- Inline Keyword Search +- Update aLeapp/iLeapp executables. + +GUI Updates: +- Add "has attachments" flag for email's +- Add ability to delete a logical file/path from logical file + from the DSP before it is run. +- Add ability to add timestamps when adding localfiles as a data source +- Add Score to tree view + +Bugs: +- Fix path for lnk files +- Fix exporting of CSV files + +Misc: +- Update JNA Version +- Update SQLite library version +- Add export for Pasco +- Cyber Triage intergration + ---------------- VERSION 4.20.0 -------------- Recent Activity Updates: - Added Favicons, Profiles and Extensions to Chromium Browsers From 47898d6b8de9d39aa2ee8eaa33393f7fdf772d53 Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Tue, 11 Jul 2023 15:04:09 -0400 Subject: [PATCH 02/94] Update NEWS.txt Fix --- NEWS.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.txt b/NEWS.txt index 83f6bae954..351f0e84e9 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -12,7 +12,7 @@ Ingest Module Updates: GUI Updates: - Add "has attachments" flag for email's - Add ability to delete a logical file/path from logical file - from the DSP before it is run. + DSP panel before it is run. - Add ability to add timestamps when adding localfiles as a data source - Add Score to tree view From 5b0fbaf41f9e1e4abda4ad3fcc03dcd6bccfeef2 Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Fri, 14 Jul 2023 09:56:02 -0400 Subject: [PATCH 03/94] Update NEWS.txt Add cve mention --- NEWS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.txt b/NEWS.txt index 351f0e84e9..5a2bd33b57 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -25,6 +25,7 @@ Misc: - Update SQLite library version - Add export for Pasco - Cyber Triage intergration +- Updated 3rd party libraries that have known CVE's ---------------- VERSION 4.20.0 -------------- Recent Activity Updates: From a689f7dae85e6a9fb6e77ae550cb5a227b020d6e Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 19 Jul 2023 21:34:31 -0400 Subject: [PATCH 04/94] fix so module output goes to case db directory --- Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java index c9170b1e68..8e41aa0778 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java @@ -258,7 +258,10 @@ public final class CaseMetadata { * @return The case directory. */ public String getCaseDirectory() { - return metadataFilePath.getParent().toString(); + File caseDatabaseNameFile = new File(caseDatabaseName); + return (caseDatabaseNameFile.isAbsolute()) + ? caseDatabaseNameFile.getParent() + : metadataFilePath.getParent().toString(); } /** From b2945c113970cea72b83f4ccbacf6e34c32c486e Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 20 Jul 2023 09:00:24 -0400 Subject: [PATCH 05/94] rely on abs path in xml --- .../sleuthkit/autopsy/casemodule/Case.java | 7 +----- .../autopsy/casemodule/CaseMetadata.java | 23 +++++-------------- 2 files changed, 7 insertions(+), 23 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 6ece795e35..aed519c694 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -2739,12 +2739,7 @@ public class Case { ContentStreamProvider contentProvider = loadContentProvider(metadata.getContentProviderName()); if (CaseType.SINGLE_USER_CASE == metadata.getCaseType()) { - // only prefix with metadata directory if databaseName is a relative path - String fullDatabasePath = (new File(databaseName).isAbsolute()) - ? databaseName - : Paths.get(metadata.getCaseDirectory(), databaseName).toString(); - - caseDb = SleuthkitCase.openCase(fullDatabasePath, contentProvider); + caseDb = SleuthkitCase.openCase(metadata.getCaseDatabasePath(), contentProvider); } else if (UserPreferences.getIsMultiUserModeEnabled()) { caseDb = SleuthkitCase.openCase(databaseName, UserPreferences.getDatabaseConnectionInfo(), metadata.getCaseDirectory(), contentProvider); } else { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java index 8e41aa0778..029290ae98 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java @@ -29,16 +29,8 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.text.DateFormat; import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; import java.util.Date; -import java.util.HashMap; -import java.util.List; import java.util.Locale; -import java.util.Map; -import java.util.Map.Entry; -import java.util.stream.Collectors; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -51,13 +43,10 @@ import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.tuple.Pair; -import org.openide.util.Lookup; import org.sleuthkit.autopsy.coreutils.Version; import org.sleuthkit.autopsy.coreutils.XMLUtil; import org.w3c.dom.Document; import org.w3c.dom.Element; -import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; @@ -121,7 +110,6 @@ public final class CaseMetadata { private static final String SCHEMA_VERSION_SIX = "6.0"; private final static String CONTENT_PROVIDER_ELEMENT_NAME = "ContentProvider"; private final static String CONTENT_PROVIDER_NAME_ELEMENT_NAME = "Name"; - private final static String CONTENT_PROVIDER_ARG_DEFAULT_KEY = "DEFAULT"; /* * Unread fields, regenerated on save. @@ -136,7 +124,7 @@ public final class CaseMetadata { private String caseName; private CaseDetails caseDetails; private String caseDatabaseName; - private String caseDatabasePath; // Legacy + private String caseDatabasePath; private String textIndexName; // Legacy private String createdDate; private String createdByVersion; @@ -640,6 +628,7 @@ public final class CaseMetadata { this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_ELEMENT, false); break; default: + this.caseDatabasePath = getElementTextContent(caseElement, CASE_DB_ABSOLUTE_PATH_ELEMENT_NAME, false); this.caseDatabaseName = getElementTextContent(caseElement, CASE_DB_NAME_RELATIVE_ELEMENT_NAME, true); this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_ELEMENT, false); break; @@ -653,7 +642,7 @@ public final class CaseMetadata { */ Path possibleAbsoluteCaseDbPath = Paths.get(this.caseDatabaseName); Path caseDirectoryPath = Paths.get(getCaseDirectory()); - if (possibleAbsoluteCaseDbPath.getNameCount() > 1) { + if (possibleAbsoluteCaseDbPath.toFile().isAbsolute()) { this.caseDatabasePath = this.caseDatabaseName; this.caseDatabaseName = caseDirectoryPath.relativize(possibleAbsoluteCaseDbPath).toString(); } else { @@ -722,12 +711,12 @@ public final class CaseMetadata { * @return The full path to the case database file for a single-user case. * * @throws UnsupportedOperationException If called for a multi-user case. - * @deprecated Do not use. */ - @Deprecated public String getCaseDatabasePath() throws UnsupportedOperationException { if (Case.CaseType.SINGLE_USER_CASE == caseType) { - return Paths.get(getCaseDirectory(), caseDatabaseName).toString(); + return StringUtils.isBlank(this.caseDatabasePath) + ? this.metadataFilePath.resolve(this.caseDatabaseName).toString() + : this.caseDatabasePath; } else { throw new UnsupportedOperationException(); } From 139aaa944bc3b606eb77bea3042f80b08c349b9d Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 20 Jul 2023 09:18:19 -0400 Subject: [PATCH 06/94] bug fix --- .../org/sleuthkit/autopsy/casemodule/CaseMetadata.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java index 029290ae98..8cb0509cbd 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java @@ -246,10 +246,9 @@ public final class CaseMetadata { * @return The case directory. */ public String getCaseDirectory() { - File caseDatabaseNameFile = new File(caseDatabaseName); - return (caseDatabaseNameFile.isAbsolute()) - ? caseDatabaseNameFile.getParent() - : metadataFilePath.getParent().toString(); + return StringUtils.isBlank(this.caseDatabasePath) + ? metadataFilePath.getParent().toString() + : Paths.get(this.caseDatabasePath).getParent().toString(); } /** @@ -645,8 +644,6 @@ public final class CaseMetadata { if (possibleAbsoluteCaseDbPath.toFile().isAbsolute()) { this.caseDatabasePath = this.caseDatabaseName; this.caseDatabaseName = caseDirectoryPath.relativize(possibleAbsoluteCaseDbPath).toString(); - } else { - this.caseDatabasePath = caseDirectoryPath.resolve(caseDatabaseName).toAbsolutePath().toString(); } } catch (ParserConfigurationException | SAXException | IOException ex) { From a245a0ebf705cf50e71b1b0024f5bdd2ff98202b Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 20 Jul 2023 11:46:52 -0400 Subject: [PATCH 07/94] only open case if provider is valid --- Core/src/org/sleuthkit/autopsy/casemodule/Case.java | 4 ++++ Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index aed519c694..61e6897393 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -2729,6 +2729,7 @@ public class Case { "Case.progressMessage.openingCaseDatabase=Opening case database...", "# {0} - exception message", "Case.exceptionMessage.couldNotOpenCaseDatabase=Failed to open case database:\n{0}.", "# {0} - exception message", "Case.exceptionMessage.unsupportedSchemaVersionMessage=Unsupported case database schema version:\n{0}.", + "Case.exceptionMessage.contentProviderCouldNotBeFound=Content provider was specified for the case but could not be loaded.", "Case.open.exception.multiUserCaseNotEnabled=Cannot open a multi-user case if multi-user cases are not enabled. See Tools, Options, Multi-User." }) private void openCaseDataBase(ProgressIndicator progressIndicator) throws CaseActionException { @@ -2737,6 +2738,9 @@ public class Case { String databaseName = metadata.getCaseDatabaseName(); ContentStreamProvider contentProvider = loadContentProvider(metadata.getContentProviderName()); + if (StringUtils.isNotBlank(metadata.getContentProviderName()) && contentProvider == null) { + throw new CaseActionException(Bundle.Case_exceptionMessage_contentProviderCouldNotBeFound()); + } if (CaseType.SINGLE_USER_CASE == metadata.getCaseType()) { caseDb = SleuthkitCase.openCase(metadata.getCaseDatabasePath(), contentProvider); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java index 8cb0509cbd..91566a01bb 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java @@ -712,7 +712,7 @@ public final class CaseMetadata { public String getCaseDatabasePath() throws UnsupportedOperationException { if (Case.CaseType.SINGLE_USER_CASE == caseType) { return StringUtils.isBlank(this.caseDatabasePath) - ? this.metadataFilePath.resolve(this.caseDatabaseName).toString() + ? this.metadataFilePath.getParent().resolve(this.caseDatabaseName).toString() : this.caseDatabasePath; } else { throw new UnsupportedOperationException(); From e347c53f3df39976f4525b85a0b7bbcf9e7c4c7e Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 20 Jul 2023 13:28:39 -0400 Subject: [PATCH 08/94] add bundle message --- .../org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED | 1 + 1 file changed, 1 insertion(+) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED index b671940118..dc96292d9a 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED @@ -16,6 +16,7 @@ Case.exceptionMessage.cannotDeleteCurrentCase=Cannot delete current case, it mus Case.exceptionMessage.cannotGetLockToDeleteCase=Cannot delete case because it is open for another user or host. Case.exceptionMessage.cannotLocateMainWindow=Cannot locate main application window Case.exceptionMessage.cannotOpenMultiUserCaseNoSettings=Multi-user settings are missing (see Tools, Options, Multi-user tab), cannot open a multi-user case. +Case.exceptionMessage.contentProviderCouldNotBeFound=Content provider was specified for the case but could not be loaded. # {0} - exception message Case.exceptionMessage.couldNotCreatCollaborationMonitor=Failed to create collaboration monitor:\n{0}. # {0} - exception message From 8809569567646343bded7eb8aadb6c4e71d2c0f6 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 24 Jul 2023 09:34:15 -0400 Subject: [PATCH 09/94] file upload --- .../autopsy/ctapi/CTCloudHttpClient.java | 60 +++++++--- .../cybertriage/autopsy/ctapi/CtApiDAO.java | 18 ++- .../ctapi/json/MetadataUploadRequest.java | 109 ++++++++++++++++++ .../autopsy/malwarescan/FileUpload.java | 78 +++++++++++++ 4 files changed, 249 insertions(+), 16 deletions(-) create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/MetadataUploadRequest.java create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/FileUpload.java diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java index d774ff1661..0fa9feda54 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java @@ -21,17 +21,13 @@ package com.basistech.df.cybertriage.autopsy.ctapi; import com.basistech.df.cybertriage.autopsy.ctapi.util.ObjectMapperUtil; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; +import java.io.InputStream; import java.net.Authenticator; import java.net.InetAddress; import java.net.PasswordAuthentication; import java.net.URI; import java.net.URISyntaxException; import java.net.UnknownHostException; -import java.security.KeyManagementException; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.security.UnrecoverableKeyException; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; @@ -41,13 +37,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Objects; import java.util.logging.Level; -import javax.net.ssl.KeyManager; -import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509TrustManager; -import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpEntity; @@ -64,7 +54,9 @@ import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.util.EntityUtils; import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; +import org.apache.http.entity.mime.MultipartEntityBuilder; import org.sleuthkit.autopsy.coreutils.Logger; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; @@ -175,10 +167,14 @@ public class CTCloudHttpClient { if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { LOGGER.log(Level.INFO, "Response Received. - Status OK"); // Parse Response - HttpEntity entity = response.getEntity(); - String entityStr = EntityUtils.toString(entity); - O respObj = mapper.readValue(entityStr, classType); - return respObj; + if (classType != null) { + HttpEntity entity = response.getEntity(); + String entityStr = EntityUtils.toString(entity); + O respObj = mapper.readValue(entityStr, classType); + return respObj; + } else { + return null; + } } else { LOGGER.log(Level.WARNING, "Response Received. - Status Error {}", response.getStatusLine()); handleNonOKResponse(response, ""); @@ -198,6 +194,40 @@ public class CTCloudHttpClient { return null; } + + public void doFileUploadPost(String urlPath, String fileName, InputStream fileIs) throws CTCloudException { + + try (CloseableHttpClient httpclient = createConnection(getProxySettings(), sslContext)) { + HttpPost post = new HttpPost(urlPath); + configureRequestTimeout(post); + + post.addHeader("Connection", "keep-alive"); + + MultipartEntityBuilder builder = MultipartEntityBuilder.create(); + builder.addBinaryBody( + "file", + fileIs, + ContentType.APPLICATION_OCTET_STREAM, + fileName + ); + + HttpEntity multipart = builder.build(); + post.setEntity(multipart); + + try (CloseableHttpResponse response = httpclient.execute(post)) { + int statusCode = response.getStatusLine().getStatusCode(); + if (statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_NO_CONTENT) { + LOGGER.log(Level.INFO, "Response Received. - Status OK"); + } else { + LOGGER.log(Level.WARNING, MessageFormat.format("Response Received. - Status Error {0}", response.getStatusLine())); + handleNonOKResponse(response, fileName); + } + } + } catch (IOException ex) { + LOGGER.log(Level.WARNING, "IO Exception raised when connecting to Reversing Labs for file content upload ", ex); + throw new CTCloudException(CTCloudException.ErrorCode.NETWORK_ERROR, ex); + } + } /** * A generic way to handle the HTTP response - when the response code is NOT diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CtApiDAO.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CtApiDAO.java index 899af5545b..927cc10cbe 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CtApiDAO.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CtApiDAO.java @@ -27,7 +27,9 @@ import com.basistech.df.cybertriage.autopsy.ctapi.json.DecryptedLicenseResponse; import com.basistech.df.cybertriage.autopsy.ctapi.json.FileReputationRequest; import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseRequest; import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseResponse; +import com.basistech.df.cybertriage.autopsy.ctapi.json.MetadataUploadRequest; import com.basistech.df.cybertriage.autopsy.ctapi.util.CTHostIDGenerationUtil; +import java.io.InputStream; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -44,6 +46,8 @@ public class CTApiDAO { private static final String LICENSE_REQUEST_PATH = "/_ah/api/license/v1/activate"; private static final String AUTH_TOKEN_REQUEST_PATH = "/_ah/api/auth/v2/generate_token"; private static final String CTCLOUD_SERVER_HASH_PATH = "/_ah/api/reputation/v1/query/file/hash/md5?query_types=CORRELATION,MALWARE"; + private static final String CTCLOUD_UPLOAD_FILE_METADATA_PATH = "/_ah/api/reputation/v1/upload/meta"; + private static final String AUTOPSY_PRODUCT = "AUTOPSY"; private static final CTApiDAO instance = new CTApiDAO(); @@ -72,15 +76,27 @@ public class CTApiDAO { } public AuthTokenResponse getAuthToken(DecryptedLicenseResponse decrypted) throws CTCloudException { + return getAuthToken(decrypted, false); + } + + public AuthTokenResponse getAuthToken(DecryptedLicenseResponse decrypted, boolean fileUpload) throws CTCloudException { AuthTokenRequest authTokenRequest = new AuthTokenRequest() .setAutopsyVersion(getAppVersion()) - .setRequestFileUpload(false) + .setRequestFileUpload(fileUpload) .setBoostLicenseId(decrypted.getBoostLicenseId()) .setHostId(decrypted.getLicenseHostId()); return httpClient.doPost(AUTH_TOKEN_REQUEST_PATH, authTokenRequest, AuthTokenResponse.class); } + public void uploadFile(String url, String fileName, InputStream fileIs) throws CTCloudException { + httpClient.doFileUploadPost(url, fileName, fileIs); + } + + public void uploadMeta(AuthenticatedRequestData authenticatedRequestData, MetadataUploadRequest metaRequest) throws CTCloudException { + httpClient.doPost(AUTH_TOKEN_REQUEST_PATH, getAuthParams(authenticatedRequestData), metaRequest, null); + } + private static Map getAuthParams(AuthenticatedRequestData authenticatedRequestData) { return new HashMap() { { diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/MetadataUploadRequest.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/MetadataUploadRequest.java new file mode 100644 index 0000000000..57d59c3faa --- /dev/null +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/MetadataUploadRequest.java @@ -0,0 +1,109 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2023 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.basistech.df.cybertriage.autopsy.ctapi.json; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class MetadataUploadRequest { + + @JsonProperty("file_upload_url") + private String fileUploadUrl; + + @JsonProperty("sha1") + private String sha1; + + @JsonProperty("sha256") + private String sha256; + + @JsonProperty("md5") + private String md5; + + @JsonProperty("filePath") + private String filePath; + + @JsonProperty("fileSize") + private long fileSizeBytes; + + @JsonProperty("createdDate") + private long createdDate; + + public String getFileUploadUrl() { + return fileUploadUrl; + } + + public MetadataUploadRequest setFileUploadUrl(String fileUploadUrl) { + this.fileUploadUrl = fileUploadUrl; + return this; + } + + public String getSha1() { + return sha1; + } + + public MetadataUploadRequest setSha1(String sha1) { + this.sha1 = sha1; + return this; + } + + public String getSha256() { + return sha256; + } + + public MetadataUploadRequest setSha256(String sha256) { + this.sha256 = sha256; + return this; + } + + public String getMd5() { + return md5; + } + + public MetadataUploadRequest setMd5(String md5) { + this.md5 = md5; + return this; + } + + public String getFilePath() { + return filePath; + } + + public MetadataUploadRequest setFilePath(String filePath) { + this.filePath = filePath; + return this; + } + + public long getFileSizeBytes() { + return fileSizeBytes; + } + + public MetadataUploadRequest setFileSizeBytes(long fileSizeBytes) { + this.fileSizeBytes = fileSizeBytes; + return this; + } + + public long getCreatedDate() { + return createdDate; + } + + public MetadataUploadRequest setCreatedDate(long createdDate) { + this.createdDate = createdDate; + return this; + } + +} diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/FileUpload.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/FileUpload.java new file mode 100644 index 0000000000..64fb36f2a1 --- /dev/null +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/FileUpload.java @@ -0,0 +1,78 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2023 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.basistech.df.cybertriage.autopsy.malwarescan; + +import com.basistech.df.cybertriage.autopsy.ctapi.CTApiDAO; +import com.basistech.df.cybertriage.autopsy.ctapi.CTCloudException; +import com.basistech.df.cybertriage.autopsy.ctapi.json.AuthTokenResponse; +import com.basistech.df.cybertriage.autopsy.ctapi.json.AuthenticatedRequestData; +import com.basistech.df.cybertriage.autopsy.ctapi.json.CTCloudBean; +import com.basistech.df.cybertriage.autopsy.ctapi.json.DecryptedLicenseResponse; +import com.basistech.df.cybertriage.autopsy.ctapi.json.MetadataUploadRequest; +import org.apache.commons.lang3.StringUtils; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.ReadContentInputStream; +import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * Handles uploading of files that are unknown. + */ +public class FileUpload { + + private final CTApiDAO ctApiDAO = CTApiDAO.getInstance(); + + private boolean isUnknown(CTCloudBean cloudBean) { + + } + + private boolean isUploadable(AbstractFile af) { + + } + + public boolean tryUpload(SleuthkitCase skCase, CTCloudBean cloudBean, long objId) { + + } + + private boolean upload(DecryptedLicenseResponse decrypted, AbstractFile af) throws CTCloudException, TskCoreException { + // get auth token / file upload url + AuthTokenResponse authTokenResponse = ctApiDAO.getAuthToken(decrypted, true); + if (StringUtils.isBlank(authTokenResponse.getFileUploadUrl())) { + throw new CTCloudException(CTCloudException.ErrorCode.NETWORK_ERROR); + } + + // upload bytes + ReadContentInputStream fileInputStream = new ReadContentInputStream(af); + ctApiDAO.uploadFile(authTokenResponse.getFileUploadUrl(), af.getName(), fileInputStream); + + // upload metadata + MetadataUploadRequest metaRequest = new MetadataUploadRequest() + .setCreatedDate(af.getCrtime()) + .setFilePath(af.getUniquePath()) + .setFileSizeBytes(af.getSize()) + .setFileUploadUrl(authTokenResponse.getFileUploadUrl()) + .setMd5(af.getMd5Hash()) + .setSha1(af.getSha1Hash()) + .setSha256(af.getSha256Hash()); + + ctApiDAO.uploadMeta(new AuthenticatedRequestData(decrypted, authTokenResponse), metaRequest); + return true; + } + +} From 418fdb2be3585f94394b550c39b72e0b7a932a0f Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 24 Jul 2023 11:08:40 -0400 Subject: [PATCH 10/94] updates --- .../autopsy/malwarescan/FileUpload.java | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/FileUpload.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/FileUpload.java index 64fb36f2a1..73d99ee114 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/FileUpload.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/FileUpload.java @@ -24,6 +24,7 @@ import com.basistech.df.cybertriage.autopsy.ctapi.json.AuthTokenResponse; import com.basistech.df.cybertriage.autopsy.ctapi.json.AuthenticatedRequestData; import com.basistech.df.cybertriage.autopsy.ctapi.json.CTCloudBean; import com.basistech.df.cybertriage.autopsy.ctapi.json.DecryptedLicenseResponse; +import com.basistech.df.cybertriage.autopsy.ctapi.json.MalwareResultBean.Status; import com.basistech.df.cybertriage.autopsy.ctapi.json.MetadataUploadRequest; import org.apache.commons.lang3.StringUtils; import org.sleuthkit.datamodel.AbstractFile; @@ -35,19 +36,37 @@ import org.sleuthkit.datamodel.TskCoreException; * Handles uploading of files that are unknown. */ public class FileUpload { + private static final long MIN_SIZE = 1; + private static final long MAX_SIZE = 1_000_000_000; private final CTApiDAO ctApiDAO = CTApiDAO.getInstance(); private boolean isUnknown(CTCloudBean cloudBean) { - + return cloudBean != null + && cloudBean.getMalwareResult() != null + && cloudBean.getMalwareResult().getStatus() == Status.NOT_FOUND; } private boolean isUploadable(AbstractFile af) { - + long size = af.getSize(); + return size >= MIN_SIZE && size <= MAX_SIZE; } - public boolean tryUpload(SleuthkitCase skCase, CTCloudBean cloudBean, long objId) { - + public boolean tryUpload(SleuthkitCase skCase, CTCloudBean cloudBean, long objId) throws TskCoreException { + if (!isUnknown(cloudBean)) { + return false; + } + + AbstractFile af = skCase.getAbstractFileById(objId); + if (af == null) { + return false; + } + + if (!isUploadable(af)) { + return false; + } + + } private boolean upload(DecryptedLicenseResponse decrypted, AbstractFile af) throws CTCloudException, TskCoreException { From 08a649b01c13854f10e7f0232678daef8d1bed4f Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 24 Jul 2023 11:41:19 -0400 Subject: [PATCH 11/94] file upload updates --- .../ctoptions/ctcloud/Bundle.properties | 2 + .../ctcloud/CTMalwareScannerOptionsPanel.form | 49 +++++++++++++++ .../ctcloud/CTMalwareScannerOptionsPanel.java | 38 ++++++++++++ .../autopsy/malwarescan/FileUpload.java | 12 ++-- .../malwarescan/MalwareScanIngestModule.java | 62 ++++++++++++++++++- 5 files changed, 153 insertions(+), 10 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties index bd06716288..979010bb23 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties @@ -24,3 +24,5 @@ CTMalwareScannerOptionsPanel.licenseInfoUserLabel.text= EULADialog.cancelButton.text=Cancel EULADialog.acceptButton.text=Accept EULADialog.title=Cyber Triage End User License Agreement +CTMalwareScannerOptionsPanel.fileUploadCheckbox.text=Upload executable if executable is unknown +CTMalwareScannerOptionsPanel.fileUploadPanel.border.title=File Upload diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form index 77361419b6..8f5020d9b9 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form @@ -195,5 +195,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java index d68168c3b6..94ba8fb948 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java @@ -214,6 +214,8 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { countersResetLabel = new javax.swing.JLabel(); hashLookupsRemainingLabel = new javax.swing.JLabel(); fileUploadsRemainingLabel = new javax.swing.JLabel(); + javax.swing.JPanel fileUploadPanel = new javax.swing.JPanel(); + fileUploadCheckbox = new javax.swing.JCheckBox(); setLayout(new java.awt.GridBagLayout()); @@ -346,6 +348,37 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.weightx = 1.0; add(malwareScansPanel, gridBagConstraints); + + fileUploadPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.fileUploadPanel.border.title"))); // NOI18N + fileUploadPanel.setLayout(new java.awt.GridBagLayout()); + + fileUploadCheckbox.setSelected(true); + org.openide.awt.Mnemonics.setLocalizedText(fileUploadCheckbox, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.fileUploadCheckbox.text")); // NOI18N + fileUploadCheckbox.setMaximumSize(new java.awt.Dimension(32767, 32767)); + fileUploadCheckbox.setMinimumSize(new java.awt.Dimension(255, 50)); + fileUploadCheckbox.setPreferredSize(new java.awt.Dimension(255, 50)); + fileUploadCheckbox.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + fileUploadCheckboxActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); + fileUploadPanel.add(fileUploadCheckbox, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + add(fileUploadPanel, gridBagConstraints); }// //GEN-END:initComponents @Messages({ @@ -377,6 +410,10 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { } }//GEN-LAST:event_licenseInfoAddButtonActionPerformed + private void fileUploadCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fileUploadCheckboxActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_fileUploadCheckboxActionPerformed + @NbBundle.Messages({ "# {0} - userName", "# {1} - email", @@ -588,6 +625,7 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel countersResetLabel; + private javax.swing.JCheckBox fileUploadCheckbox; private javax.swing.JLabel fileUploadsRemainingLabel; private javax.swing.JLabel hashLookupsRemainingLabel; private javax.swing.JButton licenseInfoAddButton; diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/FileUpload.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/FileUpload.java index 73d99ee114..4803793514 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/FileUpload.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/FileUpload.java @@ -36,8 +36,8 @@ import org.sleuthkit.datamodel.TskCoreException; * Handles uploading of files that are unknown. */ public class FileUpload { - private static final long MIN_SIZE = 1; - private static final long MAX_SIZE = 1_000_000_000; + private static final long MIN_UPLOAD_SIZE = 1; + private static final long MAX_UPLOAD_SIZE = 1_000_000_000; private final CTApiDAO ctApiDAO = CTApiDAO.getInstance(); @@ -49,10 +49,10 @@ public class FileUpload { private boolean isUploadable(AbstractFile af) { long size = af.getSize(); - return size >= MIN_SIZE && size <= MAX_SIZE; + return size >= MIN_UPLOAD_SIZE && size <= MAX_UPLOAD_SIZE; } - public boolean tryUpload(SleuthkitCase skCase, CTCloudBean cloudBean, long objId) throws TskCoreException { + private boolean upload(SleuthkitCase skCase, DecryptedLicenseResponse decrypted, CTCloudBean cloudBean, long objId) throws CTCloudException, TskCoreException { if (!isUnknown(cloudBean)) { return false; } @@ -66,10 +66,6 @@ public class FileUpload { return false; } - - } - - private boolean upload(DecryptedLicenseResponse decrypted, AbstractFile af) throws CTCloudException, TskCoreException { // get auth token / file upload url AuthTokenResponse authTokenResponse = ctApiDAO.getAuthToken(decrypted, true); if (StringUtils.isBlank(authTokenResponse.getFileUploadUrl())) { diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java index beffd8e594..dd8e45a085 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java @@ -19,10 +19,14 @@ package com.basistech.df.cybertriage.autopsy.malwarescan; import com.basistech.df.cybertriage.autopsy.ctapi.CTApiDAO; +import com.basistech.df.cybertriage.autopsy.ctapi.CTCloudException; import com.basistech.df.cybertriage.autopsy.ctapi.json.AuthTokenResponse; import com.basistech.df.cybertriage.autopsy.ctapi.json.AuthenticatedRequestData; import com.basistech.df.cybertriage.autopsy.ctapi.json.CTCloudBean; +import com.basistech.df.cybertriage.autopsy.ctapi.json.DecryptedLicenseResponse; import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseInfo; +import com.basistech.df.cybertriage.autopsy.ctapi.json.MalwareResultBean; +import com.basistech.df.cybertriage.autopsy.ctapi.json.MetadataUploadRequest; import com.basistech.df.cybertriage.autopsy.ctoptions.ctcloud.CTLicensePersistence; import java.util.ArrayList; import java.util.Collections; @@ -48,8 +52,10 @@ import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AnalysisResult; import org.sleuthkit.datamodel.Blackboard; import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.ReadContentInputStream; import org.sleuthkit.datamodel.Score; import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; /** @@ -88,6 +94,9 @@ public class MalwareScanIngestModule implements FileIngestModule { //minimum lookups left before issuing warning private static final long LOW_LOOKUPS_REMAINING = 250; + private static final long MIN_UPLOAD_SIZE = 1; + private static final long MAX_UPLOAD_SIZE = 1_000_000_000; + private static final Set EXECUTABLE_MIME_TYPES = Stream.of( "application/x-bat",//NON-NLS "application/x-dosexec",//NON-NLS @@ -112,7 +121,7 @@ public class MalwareScanIngestModule implements FileIngestModule { private final CTApiDAO ctApiDAO = CTApiDAO.getInstance(); private RunState runState = null; - + private SleuthkitCase tskCase = null; private FileTypeDetector fileTypeDetector = null; private LicenseInfo licenseInfo = null; @@ -192,6 +201,55 @@ public class MalwareScanIngestModule implements FileIngestModule { return limit - used; } + private boolean isUnknown(CTCloudBean cloudBean) { + return cloudBean != null + && cloudBean.getMalwareResult() != null + && cloudBean.getMalwareResult().getStatus() == MalwareResultBean.Status.NOT_FOUND; + } + + private boolean isUploadable(AbstractFile af) { + long size = af.getSize(); + return size >= MIN_UPLOAD_SIZE && size <= MAX_UPLOAD_SIZE; + } + + private boolean uploadFile(SleuthkitCase skCase, DecryptedLicenseResponse decrypted, CTCloudBean cloudBean, long objId) throws CTCloudException, TskCoreException { + if (!isUnknown(cloudBean)) { + return false; + } + + AbstractFile af = skCase.getAbstractFileById(objId); + if (af == null) { + return false; + } + + if (!isUploadable(af)) { + return false; + } + + // get auth token / file upload url + AuthTokenResponse authTokenResponse = ctApiDAO.getAuthToken(decrypted, true); + if (StringUtils.isBlank(authTokenResponse.getFileUploadUrl())) { + throw new CTCloudException(CTCloudException.ErrorCode.NETWORK_ERROR); + } + + // upload bytes + ReadContentInputStream fileInputStream = new ReadContentInputStream(af); + ctApiDAO.uploadFile(authTokenResponse.getFileUploadUrl(), af.getName(), fileInputStream); + + // upload metadata + MetadataUploadRequest metaRequest = new MetadataUploadRequest() + .setCreatedDate(af.getCrtime()) + .setFilePath(af.getUniquePath()) + .setFileSizeBytes(af.getSize()) + .setFileUploadUrl(authTokenResponse.getFileUploadUrl()) + .setMd5(af.getMd5Hash()) + .setSha1(af.getSha1Hash()) + .setSha256(af.getSha256Hash()); + + ctApiDAO.uploadMeta(new AuthenticatedRequestData(decrypted, authTokenResponse), metaRequest); + return true; + } + @Messages({ "MalwareScanIngestModule_ShareProcessing_batchTimeout_title=Batch Processing Timeout", "MalwareScanIngestModule_ShareProcessing_batchTimeout_desc=Batch processing timed out" @@ -310,7 +368,7 @@ public class MalwareScanIngestModule implements FileIngestModule { if (!CollectionUtils.isEmpty(createdArtifacts)) { tskCase.getBlackboard().postArtifacts(createdArtifacts, Bundle.MalwareScanIngestModuleFactory_displayName(), ingestJobId); } - + // if we only processed part of the batch, after processing, notify that we are out of scans. if (exceededScanLimit) { runState = RunState.DISABLED; From c94a1fe867ac1b957239edf0713d3ed7fb26509e Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 24 Jul 2023 11:51:41 -0400 Subject: [PATCH 12/94] updates --- .../ctcloud/CTLicensePersistence.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicensePersistence.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicensePersistence.java index 784e15234b..65e9f25773 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicensePersistence.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicensePersistence.java @@ -40,6 +40,7 @@ public class CTLicensePersistence { private static final String CT_SETTINGS_DIR = "CyberTriage"; private static final String CT_LICENSE_FILENAME = "CyberTriageLicense.json"; + private static final String MALWARE_INGEST_SETTINGS_FILENAME = "MalwareIngestSettings.json"; private static final Logger logger = Logger.getLogger(CTLicensePersistence.class.getName()); @@ -95,7 +96,44 @@ public class CTLicensePersistence { }); } + public synchronized boolean saveMalwareSettings(MalwareIngestSettings malwareIngestSettings) { + if (malwareIngestSettings != null) { + File settingsFile = getMalwareIngestFile(); + try { + settingsFile.getParentFile().mkdirs(); + if (licenseResponse != null) { + objectMapper.writeValue(licenseFile, licenseResponse); + } else if (licenseFile.exists()) { + Files.delete(licenseFile.toPath()); + } + return true; + } catch (IOException ex) { + logger.log(Level.WARNING, "There was an error writing CyberTriage license to file: " + licenseFile.getAbsolutePath(), ex); + } + } + + return false; + } + + public synchronized MalwareIngestSettings loadMalwareIngestSettings() { + Optional toRet = Optional.empty(); + File licenseFile = getCTLicenseFile(); + if (licenseFile.exists() && licenseFile.isFile()) { + try { + toRet = Optional.ofNullable(objectMapper.readValue(licenseFile, LicenseResponse.class)); + } catch (IOException ex) { + logger.log(Level.WARNING, "There was an error reading CyberTriage license to file: " + licenseFile.getAbsolutePath(), ex); + } + } + + return toRet; + } + private File getCTLicenseFile() { return Paths.get(PlatformUtil.getModuleConfigDirectory(), CT_SETTINGS_DIR, CT_LICENSE_FILENAME).toFile(); } + + private File getMalwareIngestFile() { + return Paths.get(PlatformUtil.getModuleConfigDirectory(), CT_SETTINGS_DIR, MALWARE_INGEST_SETTINGS_FILENAME).toFile(); + } } From 2484f75d3c09ef12842dc1e57a3e6a57fa1fe2a1 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 24 Jul 2023 11:52:04 -0400 Subject: [PATCH 13/94] updates --- .../ctcloud/MalwareIngestSettings.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/MalwareIngestSettings.java diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/MalwareIngestSettings.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/MalwareIngestSettings.java new file mode 100644 index 0000000000..11e671d561 --- /dev/null +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/MalwareIngestSettings.java @@ -0,0 +1,37 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2023 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.basistech.df.cybertriage.autopsy.ctoptions.ctcloud; + +/** + * Settings for the malware ingest module. + */ +public class MalwareIngestSettings { + + private boolean uploadFiles = true; + + public boolean isUploadFiles() { + return uploadFiles; + } + + public MalwareIngestSettings setUploadFiles(boolean uploadFiles) { + this.uploadFiles = uploadFiles; + return this; + } + +} From fe26a6e00ff938d74ef6b7dbabc4f276f577a36c Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 24 Jul 2023 13:31:10 -0400 Subject: [PATCH 14/94] updates --- .../ctcloud/CTLicensePersistence.java | 28 ++-- .../ctcloud/CTMalwareScannerOptionsPanel.java | 18 ++- .../malwarescan/MalwareScanIngestModule.java | 131 +++++++++++------- 3 files changed, 113 insertions(+), 64 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicensePersistence.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicensePersistence.java index 67f1920110..e95d9e7279 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicensePersistence.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicensePersistence.java @@ -92,19 +92,15 @@ public class CTLicensePersistence { }); } - public synchronized boolean saveMalwareSettings(MalwareIngestSettings malwareIngestSettings) { + public synchronized boolean saveMalwareSettings(MalwareIngestSettings malwareIngestSettings) { if (malwareIngestSettings != null) { File settingsFile = getMalwareIngestFile(); try { settingsFile.getParentFile().mkdirs(); - if (licenseResponse != null) { - objectMapper.writeValue(licenseFile, licenseResponse); - } else if (licenseFile.exists()) { - Files.delete(licenseFile.toPath()); - } + objectMapper.writeValue(settingsFile, malwareIngestSettings); return true; } catch (IOException ex) { - logger.log(Level.WARNING, "There was an error writing CyberTriage license to file: " + licenseFile.getAbsolutePath(), ex); + logger.log(Level.WARNING, "There was an error writing malware ingest settings to file: " + settingsFile.getAbsolutePath(), ex); } } @@ -112,19 +108,23 @@ public class CTLicensePersistence { } public synchronized MalwareIngestSettings loadMalwareIngestSettings() { - Optional toRet = Optional.empty(); - File licenseFile = getCTLicenseFile(); - if (licenseFile.exists() && licenseFile.isFile()) { + MalwareIngestSettings settings = null; + File settingsFile = getMalwareIngestFile(); + if (settingsFile.exists() && settingsFile.isFile()) { try { - toRet = Optional.ofNullable(objectMapper.readValue(licenseFile, LicenseResponse.class)); + settings = objectMapper.readValue(settingsFile, MalwareIngestSettings.class); } catch (IOException ex) { - logger.log(Level.WARNING, "There was an error reading CyberTriage license to file: " + licenseFile.getAbsolutePath(), ex); + logger.log(Level.WARNING, "There was an error reading malware ingest settings from file: " + settingsFile.getAbsolutePath(), ex); } } + + if (settings == null) { + settings = new MalwareIngestSettings(); + } - return toRet; + return settings; } - + private File getCTLicenseFile() { return Paths.get(PlatformUtil.getModuleConfigDirectory(), CT_SETTINGS_DIR, CT_LICENSE_FILENAME).toFile(); } diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java index 94ba8fb948..b380dded42 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java @@ -111,6 +111,7 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { @Override public synchronized void saveSettings() { ctPersistence.saveLicenseResponse(getLicenseInfo()); + ctPersistence.saveMalwareSettings(getIngestSettings()); } @Override @@ -127,11 +128,26 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { if (licenseInfo != null) { loadMalwareScansInfo(licenseInfo); } + + MalwareIngestSettings ingestSettings = ctPersistence.loadMalwareIngestSettings(); + setIngestSettings(ingestSettings); } private synchronized LicenseResponse getLicenseInfo() { return this.licenseInfo == null ? null : this.licenseInfo.getLicenseResponse(); } + + private MalwareIngestSettings getIngestSettings() { + return new MalwareIngestSettings() + .setUploadFiles(this.fileUploadCheckbox.isSelected()); + } + + private void setIngestSettings(MalwareIngestSettings ingestSettings) { + if (ingestSettings == null) { + ingestSettings = new MalwareIngestSettings(); + } + this.fileUploadCheckbox.setSelected(ingestSettings.isUploadFiles()); + } private synchronized void setLicenseDisplay(LicenseInfo licenseInfo, String licenseMessage) { this.licenseInfo = licenseInfo; @@ -411,7 +427,7 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { }//GEN-LAST:event_licenseInfoAddButtonActionPerformed private void fileUploadCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fileUploadCheckboxActionPerformed - // TODO add your handling code here: + this.firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); }//GEN-LAST:event_fileUploadCheckboxActionPerformed @NbBundle.Messages({ diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java index dd8e45a085..a509310391 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java @@ -40,6 +40,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.curator.shaded.com.google.common.collect.Lists; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; @@ -96,6 +97,9 @@ public class MalwareScanIngestModule implements FileIngestModule { private static final long MIN_UPLOAD_SIZE = 1; private static final long MAX_UPLOAD_SIZE = 1_000_000_000; + private static final int NUM_FILE_UPLOAD_RETRIES = 60 * 5; + private static final long FILE_UPLOAD_RETRY_SLEEP_MILLIS = 60 * 1000; + private static final Set EXECUTABLE_MIME_TYPES = Stream.of( "application/x-bat",//NON-NLS @@ -128,6 +132,7 @@ public class MalwareScanIngestModule implements FileIngestModule { private BlackboardArtifact.Type malwareType = null; private long dsId = 0; private long ingestJobId = 0; + private boolean uploadUnknownFiles = false; @Messages({ "MalwareScanIngestModule_ShareProcessing_lowLimitWarning_title=Hash Lookups Low", @@ -186,6 +191,7 @@ public class MalwareScanIngestModule implements FileIngestModule { dsId = context.getDataSource().getId(); ingestJobId = context.getJobId(); licenseInfo = licenseInfoOpt.get(); + uploadUnknownFiles = ctSettingsPersistence.loadMalwareIngestSettings().isUploadFiles(); // set run state to initialized runState = RunState.STARTED_UP; @@ -201,55 +207,6 @@ public class MalwareScanIngestModule implements FileIngestModule { return limit - used; } - private boolean isUnknown(CTCloudBean cloudBean) { - return cloudBean != null - && cloudBean.getMalwareResult() != null - && cloudBean.getMalwareResult().getStatus() == MalwareResultBean.Status.NOT_FOUND; - } - - private boolean isUploadable(AbstractFile af) { - long size = af.getSize(); - return size >= MIN_UPLOAD_SIZE && size <= MAX_UPLOAD_SIZE; - } - - private boolean uploadFile(SleuthkitCase skCase, DecryptedLicenseResponse decrypted, CTCloudBean cloudBean, long objId) throws CTCloudException, TskCoreException { - if (!isUnknown(cloudBean)) { - return false; - } - - AbstractFile af = skCase.getAbstractFileById(objId); - if (af == null) { - return false; - } - - if (!isUploadable(af)) { - return false; - } - - // get auth token / file upload url - AuthTokenResponse authTokenResponse = ctApiDAO.getAuthToken(decrypted, true); - if (StringUtils.isBlank(authTokenResponse.getFileUploadUrl())) { - throw new CTCloudException(CTCloudException.ErrorCode.NETWORK_ERROR); - } - - // upload bytes - ReadContentInputStream fileInputStream = new ReadContentInputStream(af); - ctApiDAO.uploadFile(authTokenResponse.getFileUploadUrl(), af.getName(), fileInputStream); - - // upload metadata - MetadataUploadRequest metaRequest = new MetadataUploadRequest() - .setCreatedDate(af.getCrtime()) - .setFilePath(af.getUniquePath()) - .setFileSizeBytes(af.getSize()) - .setFileUploadUrl(authTokenResponse.getFileUploadUrl()) - .setMd5(af.getMd5Hash()) - .setSha1(af.getSha1Hash()) - .setSha256(af.getSha256Hash()); - - ctApiDAO.uploadMeta(new AuthenticatedRequestData(decrypted, authTokenResponse), metaRequest); - return true; - } - @Messages({ "MalwareScanIngestModule_ShareProcessing_batchTimeout_title=Batch Processing Timeout", "MalwareScanIngestModule_ShareProcessing_batchTimeout_desc=Batch processing timed out" @@ -391,6 +348,82 @@ public class MalwareScanIngestModule implements FileIngestModule { return StringUtils.defaultString(orig).trim().toLowerCase(); } + private boolean isUnknown(CTCloudBean cloudBean) { + return cloudBean != null + && cloudBean.getMalwareResult() != null + && cloudBean.getMalwareResult().getStatus() == MalwareResultBean.Status.NOT_FOUND; + } + + private boolean isUploadable(AbstractFile af) { + long size = af.getSize(); + return size >= MIN_UPLOAD_SIZE && size <= MAX_UPLOAD_SIZE; + } + + private boolean uploadFile(CTCloudBean cloudBean, long objId) throws CTCloudException, TskCoreException { + if (!uploadUnknownFiles) { + return false; + } + + if (!isUnknown(cloudBean)) { + return false; + } + + AbstractFile af = skCase.getAbstractFileById(objId); + if (af == null) { + return false; + } + + if (!isUploadable(af)) { + return false; + } + + // get auth token / file upload url + AuthTokenResponse authTokenResponse = ctApiDAO.getAuthToken(decrypted, true); + if (StringUtils.isBlank(authTokenResponse.getFileUploadUrl())) { + throw new CTCloudException(CTCloudException.ErrorCode.NETWORK_ERROR); + } else if (remaining(authTokenResponse.getFileUploadLimit(), authTokenResponse.getFileUploadCount()) <= 0) { + // don't proceed with upload if reached limit + uploadUnknownFiles = false; + return false; + } + + // upload bytes + ReadContentInputStream fileInputStream = new ReadContentInputStream(af); + ctApiDAO.uploadFile(authTokenResponse.getFileUploadUrl(), af.getName(), fileInputStream); + + // upload metadata + MetadataUploadRequest metaRequest = new MetadataUploadRequest() + .setCreatedDate(af.getCrtime()) + .setFilePath(af.getUniquePath()) + .setFileSizeBytes(af.getSize()) + .setFileUploadUrl(authTokenResponse.getFileUploadUrl()) + .setMd5(af.getMd5Hash()) + .setSha1(af.getSha1Hash()) + .setSha256(af.getSha256Hash()); + + ctApiDAO.uploadMeta(new AuthenticatedRequestData(decrypted, authTokenResponse), metaRequest); + return true; + } + + private boolean getUploadedFileResults(Map> md5objIdMapping) { + Map> remaining = new HashMap<>(md5objIdMapping); + + for (int retry = 0; retry < NUM_FILE_UPLOAD_RETRIES; retry++) { + List> md5Batches = Lists.partition(new ArrayList<>(remaining.keySet()), BATCH_SIZE); + for (List batch : md5Batches) { + // TODO query and capture still unknown + } + + if (remaining.isEmpty()) { + return true; + } + + + Thread.sleep(FILE_UPLOAD_RETRY_SLEEP_MILLIS); + } + + } + @Messages({ "MalwareScanIngestModule_SharedProcessing_createAnalysisResult_Yes=YES", "MalwareScanIngestModule_SharedProcessing_createAnalysisResult_No=NO" From 2e8d7be572f490872d371390a2fea1fdfd7b3785 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 25 Jul 2023 13:03:51 -0400 Subject: [PATCH 15/94] dialog for missing CT provider --- .../df/cybertriage/autopsy/Bundle.properties | 10 ++ .../autopsy/Bundle.properties-MERGED | 7 + .../autopsy/CTIntegrationMissingDialog.form | 144 +++++++++++++++ .../autopsy/CTIntegrationMissingDialog.java | 165 ++++++++++++++++++ 4 files changed, 326 insertions(+) create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/Bundle.properties create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/Bundle.properties-MERGED create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/CTIntegrationMissingDialog.form create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/CTIntegrationMissingDialog.java diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/Bundle.properties b/Core/src/com/basistech/df/cybertriage/autopsy/Bundle.properties new file mode 100644 index 0000000000..4d7a376395 --- /dev/null +++ b/Core/src/com/basistech/df/cybertriage/autopsy/Bundle.properties @@ -0,0 +1,10 @@ + +# Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license +# Click nbfs://nbhost/SystemFileSystem/Templates/Other/properties.properties to edit this template + + +CTIntegrationMissingDialog.title=Cyber Triage Importer Module Required +CTIntegrationMissingDialog.descriptionLabel.text=

The Cyber Triage Importer Module is required to open this case.

To open this case:

  • Extract the module from the Integrations tab in the Cyber Triage options panel.
  • Select the 'Plugins' option from the 'Tools' menu, and go to the 'Downloaded' tab.
  • Click 'Add Plugins...' and select the path of the plugin.
  • Press 'Install' to finish the installation.
+CTIntegrationMissingDialog.link.text=http://docs.cybertriage.com +CTIntegrationMissingDialog.docsLabel.text=For more information, refer to the Cyber Triage Users Guide +CTIntegrationMissingDialog.okButton.text=OK diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/Bundle.properties-MERGED b/Core/src/com/basistech/df/cybertriage/autopsy/Bundle.properties-MERGED new file mode 100644 index 0000000000..a9a4571ed2 --- /dev/null +++ b/Core/src/com/basistech/df/cybertriage/autopsy/Bundle.properties-MERGED @@ -0,0 +1,7 @@ + +# Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license +# Click nbfs://nbhost/SystemFileSystem/Templates/Other/properties.properties to edit this template + + +CTIntegrationMissingDialog.title=Cyber Triage Importer Module Required +CTIntegrationMissingDialog.descriptionLabel.text=jLabel1 diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/CTIntegrationMissingDialog.form b/Core/src/com/basistech/df/cybertriage/autopsy/CTIntegrationMissingDialog.form new file mode 100644 index 0000000000..6005c35acc --- /dev/null +++ b/Core/src/com/basistech/df/cybertriage/autopsy/CTIntegrationMissingDialog.form @@ -0,0 +1,144 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/CTIntegrationMissingDialog.java b/Core/src/com/basistech/df/cybertriage/autopsy/CTIntegrationMissingDialog.java new file mode 100644 index 0000000000..dbac6f9f55 --- /dev/null +++ b/Core/src/com/basistech/df/cybertriage/autopsy/CTIntegrationMissingDialog.java @@ -0,0 +1,165 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2023 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.basistech.df.cybertriage.autopsy; + +import java.awt.Desktop; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.logging.Level; +import javax.swing.JComponent; +import org.sleuthkit.autopsy.coreutils.Logger; + +/** + * Provides directions with how to enable CT integration with Autopsy when + * trying to open a CT exported case. + */ +public class CTIntegrationMissingDialog extends javax.swing.JDialog { + + private static final String DOCS_PAGE_URL = "http://docs.cybertriage.com"; + + private static final Logger LOGGER = Logger.getLogger(CTIntegrationMissingDialog.class.getName()); + + /** + * Creates new form CTIntegrationMissingDialog + */ + public CTIntegrationMissingDialog(java.awt.Frame parent, boolean modal) { + super(parent, modal); + initComponents(); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + java.awt.GridBagConstraints gridBagConstraints; + + javax.swing.JLabel descriptionLabel = new javax.swing.JLabel(); + javax.swing.JLabel docsLabel = new javax.swing.JLabel(); + javax.swing.JLabel link = new javax.swing.JLabel(); + javax.swing.JPanel paddingPanel = new javax.swing.JPanel(); + javax.swing.JButton okButton = new javax.swing.JButton(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + setTitle(org.openide.util.NbBundle.getMessage(CTIntegrationMissingDialog.class, "CTIntegrationMissingDialog.title")); // NOI18N + setAlwaysOnTop(true); + setMaximumSize(new java.awt.Dimension(500, 190)); + setMinimumSize(new java.awt.Dimension(500, 190)); + setPreferredSize(new java.awt.Dimension(500, 190)); + setResizable(false); + setSize(new java.awt.Dimension(500, 190)); + getContentPane().setLayout(new java.awt.GridBagLayout()); + + org.openide.awt.Mnemonics.setLocalizedText(descriptionLabel, org.openide.util.NbBundle.getMessage(CTIntegrationMissingDialog.class, "CTIntegrationMissingDialog.descriptionLabel.text")); // NOI18N + descriptionLabel.setMinimumSize(new java.awt.Dimension(123, 116)); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); + getContentPane().add(descriptionLabel, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(docsLabel, org.openide.util.NbBundle.getMessage(CTIntegrationMissingDialog.class, "CTIntegrationMissingDialog.docsLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 0); + getContentPane().add(docsLabel, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(link, org.openide.util.NbBundle.getMessage(CTIntegrationMissingDialog.class, "CTIntegrationMissingDialog.link.text")); // NOI18N + link.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR)); + link.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent evt) { + linkMouseClicked(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); + getContentPane().add(link, gridBagConstraints); + + javax.swing.GroupLayout paddingPanelLayout = new javax.swing.GroupLayout(paddingPanel); + paddingPanel.setLayout(paddingPanelLayout); + paddingPanelLayout.setHorizontalGroup( + paddingPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 0, Short.MAX_VALUE) + ); + paddingPanelLayout.setVerticalGroup( + paddingPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 0, Short.MAX_VALUE) + ); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 2; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.weighty = 1.0; + getContentPane().add(paddingPanel, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(okButton, org.openide.util.NbBundle.getMessage(CTIntegrationMissingDialog.class, "CTIntegrationMissingDialog.okButton.text")); // NOI18N + okButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + okButtonActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST; + gridBagConstraints.insets = new java.awt.Insets(10, 5, 5, 5); + getContentPane().add(okButton, gridBagConstraints); + + pack(); + }// //GEN-END:initComponents + + private void linkMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_linkMouseClicked + if (Desktop.isDesktopSupported()) { + try { + Desktop.getDesktop().browse(new URI(DOCS_PAGE_URL)); + } catch (IOException | URISyntaxException e) { + LOGGER.log(Level.SEVERE, "Error opening link to: " + DOCS_PAGE_URL, e); + } + } else { + LOGGER.log(Level.WARNING, "Desktop API is not supported. Link cannot be opened."); + } + }//GEN-LAST:event_linkMouseClicked + + private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed + dispose(); + }//GEN-LAST:event_okButtonActionPerformed + + public void showDialog(JComponent parentComp) { + setLocationRelativeTo(parentComp); + setVisible(true); + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables +} From f12361ed43b2ea66cec78b9a120afd622af9b1e7 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 25 Jul 2023 13:45:21 -0400 Subject: [PATCH 16/94] CT missing dialog --- .../autopsy/Bundle.properties-MERGED | 5 ++++- .../autopsy/CTIntegrationMissingDialog.form | 21 ++++++------------- .../autopsy/CTIntegrationMissingDialog.java | 15 +++++++------ .../sleuthkit/autopsy/casemodule/Case.java | 5 +++++ 4 files changed, 22 insertions(+), 24 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/Bundle.properties-MERGED b/Core/src/com/basistech/df/cybertriage/autopsy/Bundle.properties-MERGED index a9a4571ed2..4d7a376395 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/Bundle.properties-MERGED +++ b/Core/src/com/basistech/df/cybertriage/autopsy/Bundle.properties-MERGED @@ -4,4 +4,7 @@ CTIntegrationMissingDialog.title=Cyber Triage Importer Module Required -CTIntegrationMissingDialog.descriptionLabel.text=jLabel1 +CTIntegrationMissingDialog.descriptionLabel.text=

The Cyber Triage Importer Module is required to open this case.

To open this case:

  • Extract the module from the Integrations tab in the Cyber Triage options panel.
  • Select the 'Plugins' option from the 'Tools' menu, and go to the 'Downloaded' tab.
  • Click 'Add Plugins...' and select the path of the plugin.
  • Press 'Install' to finish the installation.
+CTIntegrationMissingDialog.link.text=http://docs.cybertriage.com +CTIntegrationMissingDialog.docsLabel.text=For more information, refer to the Cyber Triage Users Guide +CTIntegrationMissingDialog.okButton.text=OK diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/CTIntegrationMissingDialog.form b/Core/src/com/basistech/df/cybertriage/autopsy/CTIntegrationMissingDialog.form index 6005c35acc..59955cb3dd 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/CTIntegrationMissingDialog.form +++ b/Core/src/com/basistech/df/cybertriage/autopsy/CTIntegrationMissingDialog.form @@ -7,19 +7,7 @@ - - - - - - - - - - - - @@ -35,7 +23,7 @@ - + @@ -46,7 +34,7 @@ - + @@ -64,6 +52,9 @@ + + + @@ -93,7 +84,7 @@ - + diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/CTIntegrationMissingDialog.java b/Core/src/com/basistech/df/cybertriage/autopsy/CTIntegrationMissingDialog.java index dbac6f9f55..98690ced57 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/CTIntegrationMissingDialog.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/CTIntegrationMissingDialog.java @@ -33,9 +33,9 @@ import org.sleuthkit.autopsy.coreutils.Logger; public class CTIntegrationMissingDialog extends javax.swing.JDialog { private static final String DOCS_PAGE_URL = "http://docs.cybertriage.com"; - + private static final Logger LOGGER = Logger.getLogger(CTIntegrationMissingDialog.class.getName()); - + /** * Creates new form CTIntegrationMissingDialog */ @@ -63,15 +63,11 @@ public class CTIntegrationMissingDialog extends javax.swing.JDialog { setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); setTitle(org.openide.util.NbBundle.getMessage(CTIntegrationMissingDialog.class, "CTIntegrationMissingDialog.title")); // NOI18N setAlwaysOnTop(true); - setMaximumSize(new java.awt.Dimension(500, 190)); - setMinimumSize(new java.awt.Dimension(500, 190)); - setPreferredSize(new java.awt.Dimension(500, 190)); setResizable(false); - setSize(new java.awt.Dimension(500, 190)); getContentPane().setLayout(new java.awt.GridBagLayout()); org.openide.awt.Mnemonics.setLocalizedText(descriptionLabel, org.openide.util.NbBundle.getMessage(CTIntegrationMissingDialog.class, "CTIntegrationMissingDialog.descriptionLabel.text")); // NOI18N - descriptionLabel.setMinimumSize(new java.awt.Dimension(123, 116)); + descriptionLabel.setMinimumSize(new java.awt.Dimension(483, 116)); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; @@ -83,6 +79,7 @@ public class CTIntegrationMissingDialog extends javax.swing.JDialog { getContentPane().add(descriptionLabel, gridBagConstraints); org.openide.awt.Mnemonics.setLocalizedText(docsLabel, org.openide.util.NbBundle.getMessage(CTIntegrationMissingDialog.class, "CTIntegrationMissingDialog.docsLabel.text")); // NOI18N + docsLabel.setMinimumSize(new java.awt.Dimension(312, 16)); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 1; @@ -102,6 +99,7 @@ public class CTIntegrationMissingDialog extends javax.swing.JDialog { gridBagConstraints.gridy = 1; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); getContentPane().add(link, gridBagConstraints); @@ -156,7 +154,8 @@ public class CTIntegrationMissingDialog extends javax.swing.JDialog { }//GEN-LAST:event_okButtonActionPerformed public void showDialog(JComponent parentComp) { - setLocationRelativeTo(parentComp); + setLocationRelativeTo(parentComp == null ? getParent() : parentComp); + pack(); setVisible(true); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 61e6897393..45a4d6dff6 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.casemodule; +import com.basistech.df.cybertriage.autopsy.CTIntegrationMissingDialog; import org.sleuthkit.autopsy.featureaccess.FeatureAccessUtils; import com.google.common.annotations.Beta; import com.google.common.eventbus.Subscribe; @@ -177,6 +178,7 @@ public class Case { private static final String CASE_ACTION_THREAD_NAME = "%s-case-action"; private static final String CASE_RESOURCES_THREAD_NAME = "%s-manage-case-resources"; private static final String NO_NODE_ERROR_MSG_FRAGMENT = "KeeperErrorCode = NoNode"; + private static final String CT_PROVIDER_PREFIX = "CTCustomContentProvider_"; private static final Logger logger = Logger.getLogger(Case.class.getName()); private static final AutopsyEventPublisher eventPublisher = new AutopsyEventPublisher(); private static final Object caseActionSerializationLock = new Object(); @@ -2739,6 +2741,9 @@ public class Case { ContentStreamProvider contentProvider = loadContentProvider(metadata.getContentProviderName()); if (StringUtils.isNotBlank(metadata.getContentProviderName()) && contentProvider == null) { + if (metadata.getContentProviderName().trim().toUpperCase().startsWith(CT_PROVIDER_PREFIX.toUpperCase())) { + new CTIntegrationMissingDialog(WindowManager.getDefault().getMainWindow(), true).showDialog(null); + } throw new CaseActionException(Bundle.Case_exceptionMessage_contentProviderCouldNotBeFound()); } From 032993c858f8f88a32788d8756493d59d0f4170c Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 25 Jul 2023 19:07:32 -0400 Subject: [PATCH 17/94] updates --- .../malwarescan/MalwareScanIngestModule.java | 146 ++++++++++-------- 1 file changed, 82 insertions(+), 64 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java index e249b487d5..2a67b46792 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java @@ -26,6 +26,7 @@ import com.basistech.df.cybertriage.autopsy.ctapi.json.CTCloudBean; import com.basistech.df.cybertriage.autopsy.ctapi.json.DecryptedLicenseResponse; import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseInfo; import com.basistech.df.cybertriage.autopsy.ctapi.json.MalwareResultBean; +import com.basistech.df.cybertriage.autopsy.ctapi.json.MalwareResultBean.Status; import com.basistech.df.cybertriage.autopsy.ctapi.json.MetadataUploadRequest; import com.basistech.df.cybertriage.autopsy.ctoptions.ctcloud.CTLicensePersistence; import java.text.MessageFormat; @@ -103,7 +104,6 @@ public class MalwareScanIngestModule implements FileIngestModule { private static final long MAX_UPLOAD_SIZE = 1_000_000_000; private static final int NUM_FILE_UPLOAD_RETRIES = 60 * 5; private static final long FILE_UPLOAD_RETRY_SLEEP_MILLIS = 60 * 1000; - private static final Set EXECUTABLE_MIME_TYPES = Stream.of( "application/x-bat",//NON-NLS @@ -128,6 +128,7 @@ public class MalwareScanIngestModule implements FileIngestModule { private final CTLicensePersistence ctSettingsPersistence = CTLicensePersistence.getInstance(); private final CTApiDAO ctApiDAO = CTApiDAO.getInstance(); + // TODO minimize state private RunState runState = null; private SleuthkitCase tskCase = null; @@ -137,6 +138,7 @@ public class MalwareScanIngestModule implements FileIngestModule { private long dsId = 0; private long ingestJobId = 0; private boolean uploadUnknownFiles = false; + private Map> unidentifiedHashes = null; @Messages({ "MalwareScanIngestModule_ShareProcessing_lowLimitWarning_title=Hash Lookups Low", @@ -196,7 +198,8 @@ public class MalwareScanIngestModule implements FileIngestModule { ingestJobId = context.getJobId(); licenseInfo = licenseInfoOpt.get(); uploadUnknownFiles = ctSettingsPersistence.loadMalwareIngestSettings().isUploadFiles(); - + unidentifiedHashes = new HashMap<>(); + // set run state to initialized runState = RunState.STARTED_UP; } catch (Exception ex) { @@ -306,60 +309,14 @@ public class MalwareScanIngestModule implements FileIngestModule { } try { - // get an auth token with the license - AuthTokenResponse authTokenResponse = ctApiDAO.getAuthToken(licenseInfo.getDecryptedLicense()); - - // make sure we are in bounds for the remaining scans - long remainingScans = remaining(authTokenResponse.getHashLookupLimit(), authTokenResponse.getHashLookupCount()); - if (remainingScans <= 0) { - runState = RunState.DISABLED; - notifyWarning( - Bundle.MalwareScanIngestModule_SharedProcessing_exhaustedHashLookups_title(), - Bundle.MalwareScanIngestModule_SharedProcessing_exhaustedHashLookups_desc(), - null); - return; - } - - // using auth token, get results - List repResult = ctApiDAO.getReputationResults( - new AuthenticatedRequestData(licenseInfo.getDecryptedLicense(), authTokenResponse), - md5Hashes - ); - - List createdArtifacts = new ArrayList<>(); - if (!CollectionUtils.isEmpty(repResult)) { - SleuthkitCase.CaseDbTransaction trans = null; - try { - trans = tskCase.beginTransaction(); - for (CTCloudBean result : repResult) { - String sanitizedMd5 = sanitizedMd5(result.getMd5HashValue()); - List objIds = md5ToObjId.remove(sanitizedMd5); - if (objIds == null || objIds.isEmpty()) { - continue; - } - - for (Long objId : objIds) { - AnalysisResult res = createAnalysisResult(objId, result, trans); - if (res != null) { - createdArtifacts.add(res); - } - } - } - - trans.commit(); - trans = null; - } finally { - if (trans != null) { - trans.rollback(); - createdArtifacts.clear(); - trans = null; - } - } - - if (!CollectionUtils.isEmpty(createdArtifacts)) { - tskCase.getBlackboard().postArtifacts(createdArtifacts, Bundle.MalwareScanIngestModuleFactory_displayName(), ingestJobId); - } - } + List repResult = getHashLookupResults(md5Hashes); + Map> partitioned = repResult.stream() + .filter(bean -> bean.getMalwareResult() != null) + .collect(Collectors.partitioningBy(bean -> bean.getMalwareResult().getStatus() == Status.FOUND)); + + // TODO handle caching list and creating new items + + createArtifacts(repResult, md5ToObjId); } catch (Exception ex) { notifyWarning( Bundle.MalwareScanIngestModule_SharedProcessing_generalProcessingError_title(), @@ -368,6 +325,65 @@ public class MalwareScanIngestModule implements FileIngestModule { } } + private void createArtifacts(List repResult, Map> md5ToObjId) throws Blackboard.BlackboardException, TskCoreException { + List createdArtifacts = new ArrayList<>(); + if (!CollectionUtils.isEmpty(repResult)) { + SleuthkitCase.CaseDbTransaction trans = null; + try { + trans = tskCase.beginTransaction(); + for (CTCloudBean result : repResult) { + String sanitizedMd5 = sanitizedMd5(result.getMd5HashValue()); + List objIds = md5ToObjId.remove(sanitizedMd5); + if (objIds == null || objIds.isEmpty()) { + continue; + } + + for (Long objId : objIds) { + AnalysisResult res = createAnalysisResult(objId, result, trans); + if (res != null) { + createdArtifacts.add(res); + } + } + } + + trans.commit(); + trans = null; + } finally { + if (trans != null) { + trans.rollback(); + createdArtifacts.clear(); + trans = null; + } + } + + if (!CollectionUtils.isEmpty(createdArtifacts)) { + tskCase.getBlackboard().postArtifacts(createdArtifacts, Bundle.MalwareScanIngestModuleFactory_displayName(), ingestJobId); + } + } + } + + private List getHashLookupResults(List md5Hashes) throws CTCloudException { + // get an auth token with the license + AuthTokenResponse authTokenResponse = ctApiDAO.getAuthToken(licenseInfo.getDecryptedLicense()); + + // make sure we are in bounds for the remaining scans + long remainingScans = remaining(authTokenResponse.getHashLookupLimit(), authTokenResponse.getHashLookupCount()); + if (remainingScans <= 0) { + runState = RunState.DISABLED; + notifyWarning( + Bundle.MalwareScanIngestModule_SharedProcessing_exhaustedHashLookups_title(), + Bundle.MalwareScanIngestModule_SharedProcessing_exhaustedHashLookups_desc(), + null); + return Collections.emptyList(); + } + + // using auth token, get results + return ctApiDAO.getReputationResults( + new AuthenticatedRequestData(licenseInfo.getDecryptedLicense(), authTokenResponse), + md5Hashes + ); + } + private String sanitizedMd5(String orig) { return StringUtils.defaultString(orig).trim().toLowerCase(); } @@ -392,7 +408,7 @@ public class MalwareScanIngestModule implements FileIngestModule { return false; } - AbstractFile af = skCase.getAbstractFileById(objId); + AbstractFile af = tskCase.getAbstractFileById(objId); if (af == null) { return false; } @@ -402,7 +418,7 @@ public class MalwareScanIngestModule implements FileIngestModule { } // get auth token / file upload url - AuthTokenResponse authTokenResponse = ctApiDAO.getAuthToken(decrypted, true); + AuthTokenResponse authTokenResponse = ctApiDAO.getAuthToken(licenseInfo.getDecryptedLicense(), true); if (StringUtils.isBlank(authTokenResponse.getFileUploadUrl())) { throw new CTCloudException(CTCloudException.ErrorCode.NETWORK_ERROR); } else if (remaining(authTokenResponse.getFileUploadLimit(), authTokenResponse.getFileUploadCount()) <= 0) { @@ -425,27 +441,29 @@ public class MalwareScanIngestModule implements FileIngestModule { .setSha1(af.getSha1Hash()) .setSha256(af.getSha256Hash()); - ctApiDAO.uploadMeta(new AuthenticatedRequestData(decrypted, authTokenResponse), metaRequest); + ctApiDAO.uploadMeta(new AuthenticatedRequestData(licenseInfo.getDecryptedLicense(), authTokenResponse), metaRequest); return true; } - private boolean getUploadedFileResults(Map> md5objIdMapping) { + private boolean getUploadedFileResults(Map> md5objIdMapping) throws InterruptedException, CTCloudException, Blackboard.BlackboardException, TskCoreException { + // TODO integrate this Map> remaining = new HashMap<>(md5objIdMapping); for (int retry = 0; retry < NUM_FILE_UPLOAD_RETRIES; retry++) { List> md5Batches = Lists.partition(new ArrayList<>(remaining.keySet()), BATCH_SIZE); for (List batch : md5Batches) { - // TODO query and capture still unknown + List repResult = getHashLookupResults(batch); + createArtifacts(repResult, remaining); } - + if (remaining.isEmpty()) { return true; } - - + Thread.sleep(FILE_UPLOAD_RETRY_SLEEP_MILLIS); } + return false; } @Messages({ From 5128468a9e1ebbb6fd8832974741b3d4fddc1a38 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 26 Jul 2023 08:36:03 -0400 Subject: [PATCH 18/94] work in ingest module --- .../malwarescan/MalwareScanIngestModule.java | 97 +++++++++++++++---- 1 file changed, 79 insertions(+), 18 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java index 2a67b46792..b7ba39c0b7 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java @@ -31,6 +31,7 @@ import com.basistech.df.cybertriage.autopsy.ctapi.json.MetadataUploadRequest; import com.basistech.df.cybertriage.autopsy.ctoptions.ctcloud.CTLicensePersistence; import java.text.MessageFormat; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -100,6 +101,9 @@ public class MalwareScanIngestModule implements FileIngestModule { //minimum lookups left before issuing warning private static final long LOW_LOOKUPS_REMAINING = 250; + //minimum file uploads left before issuing warning + private static final long LOW_UPLOADS_REMAINING = 25; + private static final long MIN_UPLOAD_SIZE = 1; private static final long MAX_UPLOAD_SIZE = 1_000_000_000; private static final int NUM_FILE_UPLOAD_RETRIES = 60 * 5; @@ -123,8 +127,8 @@ public class MalwareScanIngestModule implements FileIngestModule { private static final String MALWARE_CONFIG = "Cyber Triage Cloud"; private static final Logger logger = Logger.getLogger(MalwareScanIngestModule.class.getName()); - private final BatchProcessor batchProcessor = new BatchProcessor(BATCH_SIZE, FLUSH_SECS_TIMEOUT, this::handleBatch); + private final BatchProcessor batchProcessor = new BatchProcessor(BATCH_SIZE, FLUSH_SECS_TIMEOUT, this::handleBatch); private final CTLicensePersistence ctSettingsPersistence = CTLicensePersistence.getInstance(); private final CTApiDAO ctApiDAO = CTApiDAO.getInstance(); @@ -137,19 +141,24 @@ public class MalwareScanIngestModule implements FileIngestModule { private BlackboardArtifact.Type malwareType = null; private long dsId = 0; private long ingestJobId = 0; + private boolean uploadUnknownFiles = false; private Map> unidentifiedHashes = null; @Messages({ - "MalwareScanIngestModule_ShareProcessing_lowLimitWarning_title=Hash Lookups Low", - "# {0} - remainingLookups", - "MalwareScanIngestModule_ShareProcessing_lowLimitWarning_desc=This license only has {0} lookups remaining", "MalwareScanIngestModule_malwareTypeDisplayName=Malware", "MalwareScanIngestModule_ShareProcessing_noLicense_title=No Cyber Triage License", "MalwareScanIngestModule_ShareProcessing_noLicense_desc=No Cyber Triage license could be loaded. Cyber Triage processing will be disabled.", - "MalwareScanIngestModule_ShareProcessing_noRemaining_title=No remaining lookups", - "MalwareScanIngestModule_ShareProcessing_noRemaining_desc=There are no more remaining hash lookups for this license at this time. Cyber Triage processing will be disabled." - }) + "MalwareScanIngestModule_ShareProcessing_noLookupsRemaining_title=No remaining lookups", + "MalwareScanIngestModule_ShareProcessing_noLookupsRemaining_desc=There are no more remaining hash lookups for this license at this time. Cyber Triage processing will be disabled.", + "MalwareScanIngestModule_ShareProcessing_lowLookupsLimitWarning_title=Hash Lookups Low", + "# {0} - remainingLookups", + "MalwareScanIngestModule_ShareProcessing_lowLookupsLimitWarning_desc=This license only has {0} lookups remaining.", + "MalwareScanIngestModule_ShareProcessing_noUploadsRemaining_title=No remaining file uploads", + "MalwareScanIngestModule_ShareProcessing_noUploadsRemaining_desc=There are no more remaining file uploads for this license at this time. File uploading will be disabled.", + "MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_title=File Uploads Limit Low", + "# {0} - remainingUploads", + "MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_desc=This license only has {0} file uploads remaining.",}) synchronized void startUp(IngestJobContext context) throws IngestModuleException { // only run this code once per startup if (runState == RunState.STARTED_UP || runState == RunState.DISABLED) { @@ -175,18 +184,36 @@ public class MalwareScanIngestModule implements FileIngestModule { long lookupsRemaining = remaining(authTokenResponse.getHashLookupLimit(), authTokenResponse.getHashLookupCount()); if (lookupsRemaining <= 0) { notifyWarning( - Bundle.MalwareScanIngestModule_ShareProcessing_noRemaining_title(), - Bundle.MalwareScanIngestModule_ShareProcessing_noRemaining_desc(), + Bundle.MalwareScanIngestModule_ShareProcessing_noLookupsRemaining_title(), + Bundle.MalwareScanIngestModule_ShareProcessing_noLookupsRemaining_desc(), null); runState = RunState.DISABLED; return; } else if (lookupsRemaining < LOW_LOOKUPS_REMAINING) { notifyWarning( - Bundle.MalwareScanIngestModule_ShareProcessing_lowLimitWarning_title(), - Bundle.MalwareScanIngestModule_ShareProcessing_lowLimitWarning_desc(lookupsRemaining), + Bundle.MalwareScanIngestModule_ShareProcessing_lowLookupsLimitWarning_title(), + Bundle.MalwareScanIngestModule_ShareProcessing_lowLookupsLimitWarning_desc(lookupsRemaining), null); } + // determine lookups remaining + boolean uploadFiles = ctSettingsPersistence.loadMalwareIngestSettings().isUploadFiles(); + if (uploadFiles) { + long uploadsRemaining = remaining(authTokenResponse.getFileUploadLimit(), authTokenResponse.getFileUploadCount()); + if (uploadsRemaining <= 0) { + notifyWarning( + Bundle.MalwareScanIngestModule_ShareProcessing_noUploadsRemaining_title(), + Bundle.MalwareScanIngestModule_ShareProcessing_noUploadsRemaining_desc(), + null); + uploadFiles = false; + } else if (lookupsRemaining < LOW_UPLOADS_REMAINING) { + notifyWarning( + Bundle.MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_title(), + Bundle.MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_desc(lookupsRemaining), + null); + } + } + // setup necessary variables for processing tskCase = Case.getCurrentCaseThrows().getSleuthkitCase(); malwareType = tskCase.getBlackboard().getOrAddArtifactType( @@ -197,9 +224,9 @@ public class MalwareScanIngestModule implements FileIngestModule { dsId = context.getDataSource().getId(); ingestJobId = context.getJobId(); licenseInfo = licenseInfoOpt.get(); - uploadUnknownFiles = ctSettingsPersistence.loadMalwareIngestSettings().isUploadFiles(); + uploadUnknownFiles = uploadFiles; unidentifiedHashes = new HashMap<>(); - + // set run state to initialized runState = RunState.STARTED_UP; } catch (Exception ex) { @@ -310,13 +337,28 @@ public class MalwareScanIngestModule implements FileIngestModule { try { List repResult = getHashLookupResults(md5Hashes); - Map> partitioned = repResult.stream() + Map> statusGroupings = repResult.stream() .filter(bean -> bean.getMalwareResult() != null) - .collect(Collectors.partitioningBy(bean -> bean.getMalwareResult().getStatus() == Status.FOUND)); - - // TODO handle caching list and creating new items - + .collect(Collectors.groupingBy(bean -> bean.getMalwareResult().getStatus())); + + List found = statusGroupings.get(Status.FOUND); createArtifacts(repResult, md5ToObjId); + + // if being scanned, check list to run later + List beingScannedList = statusGroupings.get(Status.BEING_SCANNED); + + // if not found, try upload + List notFound = statusGroupings.get(Status.NOT_FOUND); + + if (CollectionUtils.isNotEmpty(statusGroupings.get(Status.ERROR))) { + + } + + if (CollectionUtils.isNotEmpty(statusGroupings.get(Status.LIMITS_EXCEEDED))) { + + } + // TODO handle caching list and creating new items + } catch (Exception ex) { notifyWarning( Bundle.MalwareScanIngestModule_SharedProcessing_generalProcessingError_title(), @@ -325,6 +367,25 @@ public class MalwareScanIngestModule implements FileIngestModule { } } + private void processMissing(Collection results, Map> md5ToObjId, boolean doFileUpload) throws CTCloudException { + for (CTCloudBean beingScanned : CollectionUtils.emptyIfNull(results)) { + + String sanitizedMd5 = sanitizedMd5(beingScanned.getMd5HashValue()); + if (StringUtils.isBlank(sanitizedMd5)) { + continue; + } + List correspondingObjIds = md5ToObjId.get(sanitizedMd5); + if (CollectionUtils.isEmpty(correspondingObjIds)) { + continue; + } + + if (doFileUpload) { + uploadFile(beingScanned, correspondingObjIds.get(0)); + } + this.unidentifiedHashes.put(sanitizedMd5, correspondingObjIds); + } + } + private void createArtifacts(List repResult, Map> md5ToObjId) throws Blackboard.BlackboardException, TskCoreException { List createdArtifacts = new ArrayList<>(); if (!CollectionUtils.isEmpty(repResult)) { From 10ae3411ac376c9d48fc6bd6b6f5ece606519403 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 26 Jul 2023 16:02:43 -0400 Subject: [PATCH 19/94] refactoring --- .../malwarescan/MalwareScanIngestModule.java | 166 ++++++++++++++---- 1 file changed, 127 insertions(+), 39 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java index b7ba39c0b7..13877d701d 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java @@ -43,9 +43,11 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; import org.apache.curator.shaded.com.google.common.collect.Lists; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.ingest.FileIngestModule; @@ -133,17 +135,8 @@ public class MalwareScanIngestModule implements FileIngestModule { private final CTApiDAO ctApiDAO = CTApiDAO.getInstance(); // TODO minimize state - private RunState runState = null; - - private SleuthkitCase tskCase = null; - private FileTypeDetector fileTypeDetector = null; - private LicenseInfo licenseInfo = null; - private BlackboardArtifact.Type malwareType = null; - private long dsId = 0; - private long ingestJobId = 0; - - private boolean uploadUnknownFiles = false; - private Map> unidentifiedHashes = null; +// private RunState runState = null; +// private IngestJobState ingestJobState = null; @Messages({ "MalwareScanIngestModule_malwareTypeDisplayName=Malware", @@ -166,15 +159,30 @@ public class MalwareScanIngestModule implements FileIngestModule { } try { - // get saved license + Pair jobStateResult = getNewJobState(context); + runState = jobStateResult.getLeft(); + ingestJobState = jobStateResult.getRight(); + } catch (Exception ex) { + runState = RunState.DISABLED; + throw new IngestModuleException("An exception occurred on MalwareScanIngestModule startup", ex); + } + } + + /** + * Sets up the state necessary for a new ingest job. + * @param context The ingest job context. + * @return A pair of the runtime state (i.e. started up, disabled) and parameters required for the job. + * @throws Exception + */ + private Pair getNewJobState(IngestJobContext context) throws Exception { + // get saved license Optional licenseInfoOpt = ctSettingsPersistence.loadLicenseInfo(); if (licenseInfoOpt.isEmpty() || licenseInfoOpt.get().getDecryptedLicense() == null) { notifyWarning( Bundle.MalwareScanIngestModule_ShareProcessing_noLicense_title(), Bundle.MalwareScanIngestModule_ShareProcessing_noLicense_desc(), null); - runState = RunState.DISABLED; - return; + return Pair.of(RunState.DISABLED, null); } AuthTokenResponse authTokenResponse = ctApiDAO.getAuthToken(licenseInfoOpt.get().getDecryptedLicense()); @@ -187,8 +195,7 @@ public class MalwareScanIngestModule implements FileIngestModule { Bundle.MalwareScanIngestModule_ShareProcessing_noLookupsRemaining_title(), Bundle.MalwareScanIngestModule_ShareProcessing_noLookupsRemaining_desc(), null); - runState = RunState.DISABLED; - return; + return Pair.of(RunState.DISABLED, null); } else if (lookupsRemaining < LOW_LOOKUPS_REMAINING) { notifyWarning( Bundle.MalwareScanIngestModule_ShareProcessing_lowLookupsLimitWarning_title(), @@ -215,33 +222,42 @@ public class MalwareScanIngestModule implements FileIngestModule { } // setup necessary variables for processing - tskCase = Case.getCurrentCaseThrows().getSleuthkitCase(); - malwareType = tskCase.getBlackboard().getOrAddArtifactType( + SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase(); + BlackboardArtifact.Type malwareType = tskCase.getBlackboard().getOrAddArtifactType( MALWARE_TYPE_NAME, Bundle.MalwareScanIngestModule_malwareTypeDisplayName(), BlackboardArtifact.Category.ANALYSIS_RESULT); - fileTypeDetector = new FileTypeDetector(); - dsId = context.getDataSource().getId(); - ingestJobId = context.getJobId(); - licenseInfo = licenseInfoOpt.get(); - uploadUnknownFiles = uploadFiles; - unidentifiedHashes = new HashMap<>(); - - // set run state to initialized - runState = RunState.STARTED_UP; - } catch (Exception ex) { - runState = RunState.DISABLED; - throw new IngestModuleException("An exception occurred on MalwareScanIngestModule startup", ex); - } + + IngestJobState ingestJobState = new IngestJobState( + tskCase, + new FileTypeDetector(), + licenseInfoOpt.get(), + malwareType, + context.getDataSource().getId(), + context.getJobId(), + uploadFiles); + + return Pair.of(RunState.STARTED_UP, ingestJobState); } + /** + * Determines remaining given a possibly null limit and used count. + * @param limit The limit (can be null). + * @param used The number used (can be null). + * @return The remaining amount. + */ private static long remaining(Long limit, Long used) { limit = limit == null ? 0 : limit; used = used == null ? 0 : used; return limit - used; } - private String getOrCalcHash(AbstractFile af) { + /** + * Gets the md5 hash from the abstract file or calculates it. + * @param af The abstract file. + * @return The md5 hash (or null if could not be determined). + */ + private static String getOrCalcHash(AbstractFile af) { if (StringUtils.isNotBlank(af.getMd5Hash())) { return af.getMd5Hash(); } @@ -342,22 +358,29 @@ public class MalwareScanIngestModule implements FileIngestModule { .collect(Collectors.groupingBy(bean -> bean.getMalwareResult().getStatus())); List found = statusGroupings.get(Status.FOUND); - createArtifacts(repResult, md5ToObjId); + createArtifacts(found, md5ToObjId); // if being scanned, check list to run later List beingScannedList = statusGroupings.get(Status.BEING_SCANNED); - + processMissing(beingScannedList, md5ToObjId, false); + // if not found, try upload List notFound = statusGroupings.get(Status.NOT_FOUND); + processMissing(notFound, md5ToObjId, true); if (CollectionUtils.isNotEmpty(statusGroupings.get(Status.ERROR))) { - + notifyWarning( + Bundle.MalwareScanIngestModule_SharedProcessing_generalProcessingError_title(), + Bundle.MalwareScanIngestModule_SharedProcessing_generalProcessingError_desc(), + null); } if (CollectionUtils.isNotEmpty(statusGroupings.get(Status.LIMITS_EXCEEDED))) { - + notifyWarning( + Bundle.MalwareScanIngestModule_SharedProcessing_exhaustedHashLookups_title(), + Bundle.MalwareScanIngestModule_SharedProcessing_exhaustedHashLookups_desc(), + null); } - // TODO handle caching list and creating new items } catch (Exception ex) { notifyWarning( @@ -367,7 +390,7 @@ public class MalwareScanIngestModule implements FileIngestModule { } } - private void processMissing(Collection results, Map> md5ToObjId, boolean doFileUpload) throws CTCloudException { + private static void processMissing(Collection results, Map> md5ToObjId, boolean doFileUpload) throws CTCloudException, TskCoreException { for (CTCloudBean beingScanned : CollectionUtils.emptyIfNull(results)) { String sanitizedMd5 = sanitizedMd5(beingScanned.getMd5HashValue()); @@ -507,7 +530,6 @@ public class MalwareScanIngestModule implements FileIngestModule { } private boolean getUploadedFileResults(Map> md5objIdMapping) throws InterruptedException, CTCloudException, Blackboard.BlackboardException, TskCoreException { - // TODO integrate this Map> remaining = new HashMap<>(md5objIdMapping); for (int retry = 0; retry < NUM_FILE_UPLOAD_RETRIES; retry++) { @@ -571,11 +593,18 @@ public class MalwareScanIngestModule implements FileIngestModule { // flush any remaining items try { batchProcessor.flushAndReset(); + + getUploadedFileResults(this.unidentifiedHashes); } catch (InterruptedException ex) { notifyWarning( Bundle.MalwareScanIngestModule_SharedProcessing_flushTimeout_title(), Bundle.MalwareScanIngestModule_SharedProcessing_flushTimeout_desc(), ex); + } catch (Exception ex) { + notifyWarning( + Bundle.MalwareScanIngestModule_SharedProcessing_generalProcessingError_title(), + Bundle.MalwareScanIngestModule_SharedProcessing_generalProcessingError_desc(), + ex); } finally { // set state to shut down and clear any remaining runState = RunState.SHUT_DOWN; @@ -610,5 +639,64 @@ public class MalwareScanIngestModule implements FileIngestModule { } } + + class IngestJobState { + private final SleuthkitCase tskCase; + private final FileTypeDetector fileTypeDetector; + private final LicenseInfo licenseInfo; + private final BlackboardArtifact.Type malwareType; + private final long dsId; + private final long ingestJobId; + private final Map> unidentifiedHashes = new HashMap<>(); + + // this can change mid run + private boolean uploadUnknownFiles; + + IngestJobState(SleuthkitCase tskCase, FileTypeDetector fileTypeDetector, LicenseInfo licenseInfo, BlackboardArtifact.Type malwareType, long dsId, long ingestJobId, boolean uploadUnknownFiles) { + this.tskCase = tskCase; + this.fileTypeDetector = fileTypeDetector; + this.licenseInfo = licenseInfo; + this.malwareType = malwareType; + this.dsId = dsId; + this.ingestJobId = ingestJobId; + this.uploadUnknownFiles = uploadUnknownFiles; + } + + SleuthkitCase getTskCase() { + return tskCase; + } + + FileTypeDetector getFileTypeDetector() { + return fileTypeDetector; + } + + LicenseInfo getLicenseInfo() { + return licenseInfo; + } + + BlackboardArtifact.Type getMalwareType() { + return malwareType; + } + + long getDsId() { + return dsId; + } + + long getIngestJobId() { + return ingestJobId; + } + + Map> getUnidentifiedHashes() { + return unidentifiedHashes; + } + + boolean uploadUnknownFiles() { + return uploadUnknownFiles; + } + + void setUploadUnknownFiles(boolean uploadUnknownFiles) { + this.uploadUnknownFiles = uploadUnknownFiles; + } + } } } From 19385ef3f82f8ed7f8fa7d3822fab54038b2f5ae Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 26 Jul 2023 20:42:37 -0400 Subject: [PATCH 20/94] refactoring and commenting --- .../malwarescan/MalwareScanIngestModule.java | 309 +++++++++++------- 1 file changed, 192 insertions(+), 117 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java index 13877d701d..c982220e8b 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java @@ -62,6 +62,7 @@ import org.sleuthkit.datamodel.ReadContentInputStream; import org.sleuthkit.datamodel.HashUtility; import org.sleuthkit.datamodel.HashUtility.HashResult; import org.sleuthkit.datamodel.HashUtility.HashType; +import org.sleuthkit.datamodel.IngestJobInfo; import org.sleuthkit.datamodel.Score; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; @@ -137,7 +138,6 @@ public class MalwareScanIngestModule implements FileIngestModule { // TODO minimize state // private RunState runState = null; // private IngestJobState ingestJobState = null; - @Messages({ "MalwareScanIngestModule_malwareTypeDisplayName=Malware", "MalwareScanIngestModule_ShareProcessing_noLicense_title=No Cyber Triage License", @@ -167,81 +167,84 @@ public class MalwareScanIngestModule implements FileIngestModule { throw new IngestModuleException("An exception occurred on MalwareScanIngestModule startup", ex); } } - + /** * Sets up the state necessary for a new ingest job. + * * @param context The ingest job context. - * @return A pair of the runtime state (i.e. started up, disabled) and parameters required for the job. - * @throws Exception + * @return A pair of the runtime state (i.e. started up, disabled) and + * parameters required for the job. + * @throws Exception */ private Pair getNewJobState(IngestJobContext context) throws Exception { - // get saved license - Optional licenseInfoOpt = ctSettingsPersistence.loadLicenseInfo(); - if (licenseInfoOpt.isEmpty() || licenseInfoOpt.get().getDecryptedLicense() == null) { - notifyWarning( - Bundle.MalwareScanIngestModule_ShareProcessing_noLicense_title(), - Bundle.MalwareScanIngestModule_ShareProcessing_noLicense_desc(), - null); - return Pair.of(RunState.DISABLED, null); - } + // get saved license + Optional licenseInfoOpt = ctSettingsPersistence.loadLicenseInfo(); + if (licenseInfoOpt.isEmpty() || licenseInfoOpt.get().getDecryptedLicense() == null) { + notifyWarning( + Bundle.MalwareScanIngestModule_ShareProcessing_noLicense_title(), + Bundle.MalwareScanIngestModule_ShareProcessing_noLicense_desc(), + null); + return Pair.of(RunState.DISABLED, null); + } - AuthTokenResponse authTokenResponse = ctApiDAO.getAuthToken(licenseInfoOpt.get().getDecryptedLicense()); - // syncronously fetch malware scans info + AuthTokenResponse authTokenResponse = ctApiDAO.getAuthToken(licenseInfoOpt.get().getDecryptedLicense()); + // syncronously fetch malware scans info - // determine lookups remaining - long lookupsRemaining = remaining(authTokenResponse.getHashLookupLimit(), authTokenResponse.getHashLookupCount()); - if (lookupsRemaining <= 0) { + // determine lookups remaining + long lookupsRemaining = remaining(authTokenResponse.getHashLookupLimit(), authTokenResponse.getHashLookupCount()); + if (lookupsRemaining <= 0) { + notifyWarning( + Bundle.MalwareScanIngestModule_ShareProcessing_noLookupsRemaining_title(), + Bundle.MalwareScanIngestModule_ShareProcessing_noLookupsRemaining_desc(), + null); + return Pair.of(RunState.DISABLED, null); + } else if (lookupsRemaining < LOW_LOOKUPS_REMAINING) { + notifyWarning( + Bundle.MalwareScanIngestModule_ShareProcessing_lowLookupsLimitWarning_title(), + Bundle.MalwareScanIngestModule_ShareProcessing_lowLookupsLimitWarning_desc(lookupsRemaining), + null); + } + + // determine lookups remaining + boolean uploadFiles = ctSettingsPersistence.loadMalwareIngestSettings().isUploadFiles(); + if (uploadFiles) { + long uploadsRemaining = remaining(authTokenResponse.getFileUploadLimit(), authTokenResponse.getFileUploadCount()); + if (uploadsRemaining <= 0) { notifyWarning( - Bundle.MalwareScanIngestModule_ShareProcessing_noLookupsRemaining_title(), - Bundle.MalwareScanIngestModule_ShareProcessing_noLookupsRemaining_desc(), + Bundle.MalwareScanIngestModule_ShareProcessing_noUploadsRemaining_title(), + Bundle.MalwareScanIngestModule_ShareProcessing_noUploadsRemaining_desc(), null); - return Pair.of(RunState.DISABLED, null); - } else if (lookupsRemaining < LOW_LOOKUPS_REMAINING) { + uploadFiles = false; + } else if (lookupsRemaining < LOW_UPLOADS_REMAINING) { notifyWarning( - Bundle.MalwareScanIngestModule_ShareProcessing_lowLookupsLimitWarning_title(), - Bundle.MalwareScanIngestModule_ShareProcessing_lowLookupsLimitWarning_desc(lookupsRemaining), + Bundle.MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_title(), + Bundle.MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_desc(lookupsRemaining), null); } + } - // determine lookups remaining - boolean uploadFiles = ctSettingsPersistence.loadMalwareIngestSettings().isUploadFiles(); - if (uploadFiles) { - long uploadsRemaining = remaining(authTokenResponse.getFileUploadLimit(), authTokenResponse.getFileUploadCount()); - if (uploadsRemaining <= 0) { - notifyWarning( - Bundle.MalwareScanIngestModule_ShareProcessing_noUploadsRemaining_title(), - Bundle.MalwareScanIngestModule_ShareProcessing_noUploadsRemaining_desc(), - null); - uploadFiles = false; - } else if (lookupsRemaining < LOW_UPLOADS_REMAINING) { - notifyWarning( - Bundle.MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_title(), - Bundle.MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_desc(lookupsRemaining), - null); - } - } + // setup necessary variables for processing + SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase(); + BlackboardArtifact.Type malwareType = tskCase.getBlackboard().getOrAddArtifactType( + MALWARE_TYPE_NAME, + Bundle.MalwareScanIngestModule_malwareTypeDisplayName(), + BlackboardArtifact.Category.ANALYSIS_RESULT); - // setup necessary variables for processing - SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase(); - BlackboardArtifact.Type malwareType = tskCase.getBlackboard().getOrAddArtifactType( - MALWARE_TYPE_NAME, - Bundle.MalwareScanIngestModule_malwareTypeDisplayName(), - BlackboardArtifact.Category.ANALYSIS_RESULT); - - IngestJobState ingestJobState = new IngestJobState( - tskCase, - new FileTypeDetector(), - licenseInfoOpt.get(), - malwareType, - context.getDataSource().getId(), - context.getJobId(), - uploadFiles); - - return Pair.of(RunState.STARTED_UP, ingestJobState); + IngestJobState ingestJobState = new IngestJobState( + tskCase, + new FileTypeDetector(), + licenseInfoOpt.get(), + malwareType, + context.getDataSource().getId(), + context.getJobId(), + uploadFiles); + + return Pair.of(RunState.STARTED_UP, ingestJobState); } /** * Determines remaining given a possibly null limit and used count. + * * @param limit The limit (can be null). * @param used The number used (can be null). * @return The remaining amount. @@ -254,6 +257,7 @@ public class MalwareScanIngestModule implements FileIngestModule { /** * Gets the md5 hash from the abstract file or calculates it. + * * @param af The abstract file. * @return The md5 hash (or null if could not be determined). */ @@ -282,6 +286,7 @@ public class MalwareScanIngestModule implements FileIngestModule { return null; } + // TODO return to this @Messages({ "MalwareScanIngestModule_ShareProcessing_batchTimeout_title=Batch Processing Timeout", "MalwareScanIngestModule_ShareProcessing_batchTimeout_desc=Batch processing timed out" @@ -314,6 +319,7 @@ public class MalwareScanIngestModule implements FileIngestModule { } } + // TODO return to this @Messages({ "MalwareScanIngestModule_SharedProcessing_authTokenResponseError_title=Authentication API error", "# {0} - errorResponse", @@ -338,7 +344,7 @@ public class MalwareScanIngestModule implements FileIngestModule { continue; } - String sanitizedMd5 = sanitizedMd5(fr.getMd5hash()); + String sanitizedMd5 = normalizedMd5(fr.getMd5hash()); md5ToObjId .computeIfAbsent(sanitizedMd5, (k) -> new ArrayList<>()) .add(fr.getObjId()); @@ -363,7 +369,7 @@ public class MalwareScanIngestModule implements FileIngestModule { // if being scanned, check list to run later List beingScannedList = statusGroupings.get(Status.BEING_SCANNED); processMissing(beingScannedList, md5ToObjId, false); - + // if not found, try upload List notFound = statusGroupings.get(Status.NOT_FOUND); processMissing(notFound, md5ToObjId, true); @@ -390,10 +396,11 @@ public class MalwareScanIngestModule implements FileIngestModule { } } - private static void processMissing(Collection results, Map> md5ToObjId, boolean doFileUpload) throws CTCloudException, TskCoreException { + // TODO return to this + private void processMissing(Collection results, Map> md5ToObjId, boolean doFileUpload) throws CTCloudException, TskCoreException { for (CTCloudBean beingScanned : CollectionUtils.emptyIfNull(results)) { - String sanitizedMd5 = sanitizedMd5(beingScanned.getMd5HashValue()); + String sanitizedMd5 = normalizedMd5(beingScanned.getMd5HashValue()); if (StringUtils.isBlank(sanitizedMd5)) { continue; } @@ -409,43 +416,7 @@ public class MalwareScanIngestModule implements FileIngestModule { } } - private void createArtifacts(List repResult, Map> md5ToObjId) throws Blackboard.BlackboardException, TskCoreException { - List createdArtifacts = new ArrayList<>(); - if (!CollectionUtils.isEmpty(repResult)) { - SleuthkitCase.CaseDbTransaction trans = null; - try { - trans = tskCase.beginTransaction(); - for (CTCloudBean result : repResult) { - String sanitizedMd5 = sanitizedMd5(result.getMd5HashValue()); - List objIds = md5ToObjId.remove(sanitizedMd5); - if (objIds == null || objIds.isEmpty()) { - continue; - } - - for (Long objId : objIds) { - AnalysisResult res = createAnalysisResult(objId, result, trans); - if (res != null) { - createdArtifacts.add(res); - } - } - } - - trans.commit(); - trans = null; - } finally { - if (trans != null) { - trans.rollback(); - createdArtifacts.clear(); - trans = null; - } - } - - if (!CollectionUtils.isEmpty(createdArtifacts)) { - tskCase.getBlackboard().postArtifacts(createdArtifacts, Bundle.MalwareScanIngestModuleFactory_displayName(), ingestJobId); - } - } - } - + // TODO return to this private List getHashLookupResults(List md5Hashes) throws CTCloudException { // get an auth token with the license AuthTokenResponse authTokenResponse = ctApiDAO.getAuthToken(licenseInfo.getDecryptedLicense()); @@ -468,23 +439,43 @@ public class MalwareScanIngestModule implements FileIngestModule { ); } - private String sanitizedMd5(String orig) { + /** + * Normalizes an md5 string for the purposes of lookup in a map. + * @param orig The original value. + * @return The normalized value + */ + private static String normalizedMd5(String orig) { return StringUtils.defaultString(orig).trim().toLowerCase(); } - private boolean isUnknown(CTCloudBean cloudBean) { + /** + * Returns true if the cloud bean indicates that the file is not + * currently known by CT cloud. + * + * @param cloudBean The cloud bean. + * @return True if not known by CT cloud. + */ + private static boolean isUnknown(CTCloudBean cloudBean) { return cloudBean != null && cloudBean.getMalwareResult() != null && cloudBean.getMalwareResult().getStatus() == MalwareResultBean.Status.NOT_FOUND; } - private boolean isUploadable(AbstractFile af) { + /** + * Whether or not an abstract file meets the requirements to be + * uploaded. + * + * @param af The abstract file. + * @return True if can be uploaded. + */ + private static boolean isUploadable(AbstractFile af) { long size = af.getSize(); return size >= MIN_UPLOAD_SIZE && size <= MAX_UPLOAD_SIZE; } - private boolean uploadFile(CTCloudBean cloudBean, long objId) throws CTCloudException, TskCoreException { - if (!uploadUnknownFiles) { + // TODO return to this + private boolean uploadFile(IngestJobState ingestJobState, CTCloudBean cloudBean, long objId) throws CTCloudException, TskCoreException { + if (!ingestJobState.uploadUnknownFiles()) { return false; } @@ -492,7 +483,7 @@ public class MalwareScanIngestModule implements FileIngestModule { return false; } - AbstractFile af = tskCase.getAbstractFileById(objId); + AbstractFile af = ingestJobState.getTskCase().getAbstractFileById(objId); if (af == null) { return false; } @@ -502,12 +493,12 @@ public class MalwareScanIngestModule implements FileIngestModule { } // get auth token / file upload url - AuthTokenResponse authTokenResponse = ctApiDAO.getAuthToken(licenseInfo.getDecryptedLicense(), true); + AuthTokenResponse authTokenResponse = ctApiDAO.getAuthToken(ingestJobState.getLicenseInfo().getDecryptedLicense(), true); if (StringUtils.isBlank(authTokenResponse.getFileUploadUrl())) { throw new CTCloudException(CTCloudException.ErrorCode.NETWORK_ERROR); } else if (remaining(authTokenResponse.getFileUploadLimit(), authTokenResponse.getFileUploadCount()) <= 0) { // don't proceed with upload if reached limit - uploadUnknownFiles = false; + ingestJobState.setUploadUnknownFiles(false); return false; } @@ -525,10 +516,11 @@ public class MalwareScanIngestModule implements FileIngestModule { .setSha1(af.getSha1Hash()) .setSha256(af.getSha256Hash()); - ctApiDAO.uploadMeta(new AuthenticatedRequestData(licenseInfo.getDecryptedLicense(), authTokenResponse), metaRequest); + ctApiDAO.uploadMeta(new AuthenticatedRequestData(ingestJobState.getLicenseInfo().getDecryptedLicense(), authTokenResponse), metaRequest); return true; } + // TODO return to this private boolean getUploadedFileResults(Map> md5objIdMapping) throws InterruptedException, CTCloudException, Blackboard.BlackboardException, TskCoreException { Map> remaining = new HashMap<>(md5objIdMapping); @@ -549,12 +541,83 @@ public class MalwareScanIngestModule implements FileIngestModule { return false; } + /** + * Creates TSK_MALWARE analysis results based on a list of cloud beans + * received from the CT cloud api. + * + * @param ingestJobState The ingest job state. + * @param repResult The list of cloud beans. Only cloud beans with a + * malware status + * @param md5ToObjId + * @throws org.sleuthkit.datamodel.Blackboard.BlackboardException + * @throws TskCoreException + */ + private void createAnalysisResults(IngestJobState ingestJobState, List repResult, Map> md5ToObjId) throws Blackboard.BlackboardException, TskCoreException { + List createdArtifacts = new ArrayList<>(); + if (!CollectionUtils.isEmpty(repResult)) { + SleuthkitCase.CaseDbTransaction trans = null; + try { + trans = ingestJobState.getTskCase().beginTransaction(); + for (CTCloudBean result : repResult) { + String sanitizedMd5 = normalizedMd5(result.getMd5HashValue()); + List objIds = md5ToObjId.remove(sanitizedMd5); + if (objIds == null || objIds.isEmpty()) { + continue; + } + + for (Long objId : objIds) { + AnalysisResult res = createAnalysisResult(ingestJobState, trans, result, objId); + if (res != null) { + createdArtifacts.add(res); + } + } + } + + trans.commit(); + trans = null; + } finally { + if (trans != null) { + trans.rollback(); + createdArtifacts.clear(); + trans = null; + } + } + + if (!CollectionUtils.isEmpty(createdArtifacts)) { + ingestJobState.getTskCase().getBlackboard().postArtifacts( + createdArtifacts, + Bundle.MalwareScanIngestModuleFactory_displayName(), + ingestJobState.getIngestJobId() + ); + } + } + } + + /** + * Creates an analysis result for the given information. + * + * @param ingestJobState The state of the ingest job. + * @param trans The case database transaction to use. + * @param cloudBean The bean indicating the malware result. + * @param objId The object id of the corresponding file that will + * receive the analysis result. + * @return The created analysis result or null if none created. + * @throws org.sleuthkit.datamodel.Blackboard.BlackboardException + */ @Messages({ "MalwareScanIngestModule_SharedProcessing_createAnalysisResult_Yes=YES", "MalwareScanIngestModule_SharedProcessing_createAnalysisResult_No=NO" }) - private AnalysisResult createAnalysisResult(Long objId, CTCloudBean cloudBean, SleuthkitCase.CaseDbTransaction trans) throws Blackboard.BlackboardException { - if (objId == null || cloudBean == null || cloudBean.getMalwareResult() == null) { + private AnalysisResult createAnalysisResult(IngestJobState ingestJobState, SleuthkitCase.CaseDbTransaction trans, CTCloudBean cloudBean, Long objId) throws Blackboard.BlackboardException { + if (objId == null || cloudBean == null || cloudBean.getMalwareResult() == null || cloudBean.getMalwareResult().getStatus() != Status.FOUND) { + logger.log(Level.WARNING, MessageFormat.format("Attempting to create analysis result with invalid parameters [objId: {0}, cloud bean status: {1}]", + objId == null + ? "" + : objId, + (cloudBean == null || cloudBean.getMalwareResult() == null || cloudBean.getMalwareResult().getStatus() == null) + ? "" + : cloudBean.getMalwareResult().getStatus().name() + )); return null; } @@ -568,10 +631,10 @@ public class MalwareScanIngestModule implements FileIngestModule { String justification = cloudBean.getMalwareResult().getStatusDescription(); - return tskCase.getBlackboard().newAnalysisResult( - malwareType, + return ingestJobState.getTskCase().getBlackboard().newAnalysisResult( + ingestJobState.getMalwareType(), objId, - dsId, + ingestJobState.getDsId(), score, conclusion, MALWARE_CONFIG, @@ -580,6 +643,9 @@ public class MalwareScanIngestModule implements FileIngestModule { trans).getAnalysisResult(); } + /** + * Called when ingest should shut down. + */ @Messages({ "MalwareScanIngestModule_SharedProcessing_flushTimeout_title=Processing Timeout", "MalwareScanIngestModule_SharedProcessing_flushTimeout_desc=A timeout occurred while finishing processing" @@ -593,7 +659,7 @@ public class MalwareScanIngestModule implements FileIngestModule { // flush any remaining items try { batchProcessor.flushAndReset(); - + getUploadedFileResults(this.unidentifiedHashes); } catch (InterruptedException ex) { notifyWarning( @@ -611,7 +677,15 @@ public class MalwareScanIngestModule implements FileIngestModule { } } - private void notifyWarning(String title, String message, Exception ex) { + /** + * Creates a warning notification to display in the lower right corner + * and a corresponding log message. + * + * @param title The title of the warning. + * @param message The message of the warning. + * @param ex The corresponding exception (or null if none). + */ + private static void notifyWarning(String title, String message, Exception ex) { MessageNotifyUtil.Notify.warn(title, message); logger.log(Level.WARNING, message, ex); } @@ -639,8 +713,9 @@ public class MalwareScanIngestModule implements FileIngestModule { } } - + class IngestJobState { + private final SleuthkitCase tskCase; private final FileTypeDetector fileTypeDetector; private final LicenseInfo licenseInfo; @@ -648,7 +723,7 @@ public class MalwareScanIngestModule implements FileIngestModule { private final long dsId; private final long ingestJobId; private final Map> unidentifiedHashes = new HashMap<>(); - + // this can change mid run private boolean uploadUnknownFiles; From 9ca09c5acfe95d515a69de2f9d4ac607a6909a24 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 27 Jul 2023 12:28:50 -0400 Subject: [PATCH 21/94] revamp of malware ingest module --- .../malwarescan/MalwareScanIngestModule.java | 434 +++++++++++------- 1 file changed, 275 insertions(+), 159 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java index c982220e8b..8db2ba70e8 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java @@ -23,15 +23,12 @@ import com.basistech.df.cybertriage.autopsy.ctapi.CTCloudException; import com.basistech.df.cybertriage.autopsy.ctapi.json.AuthTokenResponse; import com.basistech.df.cybertriage.autopsy.ctapi.json.AuthenticatedRequestData; import com.basistech.df.cybertriage.autopsy.ctapi.json.CTCloudBean; -import com.basistech.df.cybertriage.autopsy.ctapi.json.DecryptedLicenseResponse; import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseInfo; -import com.basistech.df.cybertriage.autopsy.ctapi.json.MalwareResultBean; import com.basistech.df.cybertriage.autopsy.ctapi.json.MalwareResultBean.Status; import com.basistech.df.cybertriage.autopsy.ctapi.json.MetadataUploadRequest; import com.basistech.df.cybertriage.autopsy.ctoptions.ctcloud.CTLicensePersistence; import java.text.MessageFormat; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -42,12 +39,11 @@ import java.util.logging.Level; import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.tuple.Pair; import org.apache.curator.shaded.com.google.common.collect.Lists; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.ingest.FileIngestModule; @@ -62,7 +58,6 @@ import org.sleuthkit.datamodel.ReadContentInputStream; import org.sleuthkit.datamodel.HashUtility; import org.sleuthkit.datamodel.HashUtility.HashResult; import org.sleuthkit.datamodel.HashUtility.HashType; -import org.sleuthkit.datamodel.IngestJobInfo; import org.sleuthkit.datamodel.Score; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; @@ -109,7 +104,7 @@ public class MalwareScanIngestModule implements FileIngestModule { private static final long MIN_UPLOAD_SIZE = 1; private static final long MAX_UPLOAD_SIZE = 1_000_000_000; - private static final int NUM_FILE_UPLOAD_RETRIES = 60 * 5; + private static final int NUM_FILE_UPLOAD_RETRIES = 7; private static final long FILE_UPLOAD_RETRY_SLEEP_MILLIS = 60 * 1000; private static final Set EXECUTABLE_MIME_TYPES = Stream.of( @@ -131,13 +126,16 @@ public class MalwareScanIngestModule implements FileIngestModule { private static final Logger logger = Logger.getLogger(MalwareScanIngestModule.class.getName()); - private final BatchProcessor batchProcessor = new BatchProcessor(BATCH_SIZE, FLUSH_SECS_TIMEOUT, this::handleBatch); + private final BatchProcessor batchProcessor = new BatchProcessor( + BATCH_SIZE, + FLUSH_SECS_TIMEOUT, + (lst) -> SharedProcessing.this.handleBatch(SharedProcessing.this.ingestJobState, lst)); + private final CTLicensePersistence ctSettingsPersistence = CTLicensePersistence.getInstance(); private final CTApiDAO ctApiDAO = CTApiDAO.getInstance(); - // TODO minimize state -// private RunState runState = null; -// private IngestJobState ingestJobState = null; + private IngestJobState ingestJobState = null; + @Messages({ "MalwareScanIngestModule_malwareTypeDisplayName=Malware", "MalwareScanIngestModule_ShareProcessing_noLicense_title=No Cyber Triage License", @@ -154,16 +152,14 @@ public class MalwareScanIngestModule implements FileIngestModule { "MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_desc=This license only has {0} file uploads remaining.",}) synchronized void startUp(IngestJobContext context) throws IngestModuleException { // only run this code once per startup - if (runState == RunState.STARTED_UP || runState == RunState.DISABLED) { + if (ingestJobState != null) { return; } try { - Pair jobStateResult = getNewJobState(context); - runState = jobStateResult.getLeft(); - ingestJobState = jobStateResult.getRight(); + ingestJobState = getNewJobState(context); } catch (Exception ex) { - runState = RunState.DISABLED; + ingestJobState = IngestJobState.DISABLED; throw new IngestModuleException("An exception occurred on MalwareScanIngestModule startup", ex); } } @@ -176,7 +172,7 @@ public class MalwareScanIngestModule implements FileIngestModule { * parameters required for the job. * @throws Exception */ - private Pair getNewJobState(IngestJobContext context) throws Exception { + private IngestJobState getNewJobState(IngestJobContext context) throws Exception { // get saved license Optional licenseInfoOpt = ctSettingsPersistence.loadLicenseInfo(); if (licenseInfoOpt.isEmpty() || licenseInfoOpt.get().getDecryptedLicense() == null) { @@ -184,7 +180,8 @@ public class MalwareScanIngestModule implements FileIngestModule { Bundle.MalwareScanIngestModule_ShareProcessing_noLicense_title(), Bundle.MalwareScanIngestModule_ShareProcessing_noLicense_desc(), null); - return Pair.of(RunState.DISABLED, null); + + return IngestJobState.DISABLED; } AuthTokenResponse authTokenResponse = ctApiDAO.getAuthToken(licenseInfoOpt.get().getDecryptedLicense()); @@ -197,7 +194,8 @@ public class MalwareScanIngestModule implements FileIngestModule { Bundle.MalwareScanIngestModule_ShareProcessing_noLookupsRemaining_title(), Bundle.MalwareScanIngestModule_ShareProcessing_noLookupsRemaining_desc(), null); - return Pair.of(RunState.DISABLED, null); + + return IngestJobState.DISABLED; } else if (lookupsRemaining < LOW_LOOKUPS_REMAINING) { notifyWarning( Bundle.MalwareScanIngestModule_ShareProcessing_lowLookupsLimitWarning_title(), @@ -230,16 +228,16 @@ public class MalwareScanIngestModule implements FileIngestModule { Bundle.MalwareScanIngestModule_malwareTypeDisplayName(), BlackboardArtifact.Category.ANALYSIS_RESULT); - IngestJobState ingestJobState = new IngestJobState( + return new IngestJobState( tskCase, new FileTypeDetector(), licenseInfoOpt.get(), malwareType, context.getDataSource().getId(), context.getJobId(), - uploadFiles); - - return Pair.of(RunState.STARTED_UP, ingestJobState); + uploadFiles, + true + ); } /** @@ -286,17 +284,26 @@ public class MalwareScanIngestModule implements FileIngestModule { return null; } - // TODO return to this + /** + * Processes a file. The file goes through the lookup process if the + * file meets acceptable criteria: 1) not FileKnown.KNOWN 2) is + * executable 3) does not have any pre-existing TSK_MALWARE results 4) + * file lookup has not been disabled. + * + * @param af The file. + * @return OK or ERROR. + */ @Messages({ "MalwareScanIngestModule_ShareProcessing_batchTimeout_title=Batch Processing Timeout", "MalwareScanIngestModule_ShareProcessing_batchTimeout_desc=Batch processing timed out" }) IngestModule.ProcessResult process(AbstractFile af) { try { - if (runState == RunState.STARTED_UP + if (ingestJobState != null + && ingestJobState.isDoFileLookups() && af.getKnown() != TskData.FileKnown.KNOWN - && EXECUTABLE_MIME_TYPES.contains(StringUtils.defaultString(fileTypeDetector.getMIMEType(af)).trim().toLowerCase()) - && CollectionUtils.isEmpty(af.getAnalysisResults(malwareType))) { + && EXECUTABLE_MIME_TYPES.contains(StringUtils.defaultString(ingestJobState.getFileTypeDetector().getMIMEType(af)).trim().toLowerCase()) + && CollectionUtils.isEmpty(af.getAnalysisResults(ingestJobState.getMalwareType()))) { String md5 = getOrCalcHash(af); if (StringUtils.isNotBlank(md5)) { @@ -319,7 +326,13 @@ public class MalwareScanIngestModule implements FileIngestModule { } } - // TODO return to this + /** + * Handles a batch of files to be sent to CT file lookup for results. + * + * @param ingestJobState The current state of operation for the ingest + * job. + * @param fileRecords The file records to be uploaded. + */ @Messages({ "MalwareScanIngestModule_SharedProcessing_authTokenResponseError_title=Authentication API error", "# {0} - errorResponse", @@ -331,8 +344,8 @@ public class MalwareScanIngestModule implements FileIngestModule { "MalwareScanIngestModule_SharedProcessing_exhaustedHashLookups_desc=The remaining hash lookups for this license have been exhausted", "MalwareScanIngestModule_SharedProcessing_generalProcessingError_title=Hash Lookup Error", "MalwareScanIngestModule_SharedProcessing_generalProcessingError_desc=An error occurred while processing hash lookup results",}) - private void handleBatch(List fileRecords) { - if (runState != RunState.STARTED_UP || fileRecords == null || fileRecords.isEmpty()) { + private void handleBatch(IngestJobState ingestJobState, List fileRecords) { + if (ingestJobState == null || !ingestJobState.isDoFileLookups() || fileRecords == null || fileRecords.isEmpty()) { return; } @@ -348,7 +361,6 @@ public class MalwareScanIngestModule implements FileIngestModule { md5ToObjId .computeIfAbsent(sanitizedMd5, (k) -> new ArrayList<>()) .add(fr.getObjId()); - } List md5Hashes = new ArrayList<>(md5ToObjId.keySet()); @@ -358,36 +370,8 @@ public class MalwareScanIngestModule implements FileIngestModule { } try { - List repResult = getHashLookupResults(md5Hashes); - Map> statusGroupings = repResult.stream() - .filter(bean -> bean.getMalwareResult() != null) - .collect(Collectors.groupingBy(bean -> bean.getMalwareResult().getStatus())); - - List found = statusGroupings.get(Status.FOUND); - createArtifacts(found, md5ToObjId); - - // if being scanned, check list to run later - List beingScannedList = statusGroupings.get(Status.BEING_SCANNED); - processMissing(beingScannedList, md5ToObjId, false); - - // if not found, try upload - List notFound = statusGroupings.get(Status.NOT_FOUND); - processMissing(notFound, md5ToObjId, true); - - if (CollectionUtils.isNotEmpty(statusGroupings.get(Status.ERROR))) { - notifyWarning( - Bundle.MalwareScanIngestModule_SharedProcessing_generalProcessingError_title(), - Bundle.MalwareScanIngestModule_SharedProcessing_generalProcessingError_desc(), - null); - } - - if (CollectionUtils.isNotEmpty(statusGroupings.get(Status.LIMITS_EXCEEDED))) { - notifyWarning( - Bundle.MalwareScanIngestModule_SharedProcessing_exhaustedHashLookups_title(), - Bundle.MalwareScanIngestModule_SharedProcessing_exhaustedHashLookups_desc(), - null); - } - + List repResult = getHashLookupResults(ingestJobState, md5Hashes); + handleLookupResults(ingestJobState, md5ToObjId, repResult); } catch (Exception ex) { notifyWarning( Bundle.MalwareScanIngestModule_SharedProcessing_generalProcessingError_title(), @@ -396,35 +380,110 @@ public class MalwareScanIngestModule implements FileIngestModule { } } - // TODO return to this - private void processMissing(Collection results, Map> md5ToObjId, boolean doFileUpload) throws CTCloudException, TskCoreException { - for (CTCloudBean beingScanned : CollectionUtils.emptyIfNull(results)) { + /** + * Handles results received from CT Cloud. + * + * @param ingestJobState The current state of operations of the ingest + * module. + * @param md5ToObjId The mapping of md5 to a list of object ids. + * @param repResult The ct cloud results. + * @throws org.sleuthkit.datamodel.Blackboard.BlackboardException + * @throws TskCoreException + * @throws TskCoreException + */ + @Messages({ + "MalwareScanIngestModule_SharedProcessing_exhaustedResultsHashLookups_title=Some Lookup Results Not Processed", + "MalwareScanIngestModule_SharedProcessing_exhaustedResultsHashLookups_desc=Some lookup results were not processed due to exceeding limits. Please try again later.",}) + private void handleLookupResults(IngestJobState ingestJobState, Map> md5ToObjId, List repResult) throws Blackboard.BlackboardException, TskCoreException, TskCoreException, CTCloudException { + if (CollectionUtils.isEmpty(repResult)) { + return; + } - String sanitizedMd5 = normalizedMd5(beingScanned.getMd5HashValue()); - if (StringUtils.isBlank(sanitizedMd5)) { - continue; - } - List correspondingObjIds = md5ToObjId.get(sanitizedMd5); - if (CollectionUtils.isEmpty(correspondingObjIds)) { - continue; - } + Map> statusGroupings = repResult.stream() + .filter(bean -> bean.getMalwareResult() != null) + .collect(Collectors.groupingBy(bean -> bean.getMalwareResult().getStatus())); - if (doFileUpload) { - uploadFile(beingScanned, correspondingObjIds.get(0)); - } - this.unidentifiedHashes.put(sanitizedMd5, correspondingObjIds); + // for all found items, create analysis results + List found = statusGroupings.get(Status.FOUND); + createAnalysisResults(ingestJobState, found, md5ToObjId); + + // if being scanned, check list to run later + handleNonFoundResults(ingestJobState, md5ToObjId, statusGroupings.get(Status.BEING_SCANNED), false); + + // if not found, try upload + handleNonFoundResults(ingestJobState, md5ToObjId, statusGroupings.get(Status.NOT_FOUND), true); + + // indicate a general error if some result in an error + if (CollectionUtils.isNotEmpty(statusGroupings.get(Status.ERROR))) { + notifyWarning( + Bundle.MalwareScanIngestModule_SharedProcessing_generalProcessingError_title(), + Bundle.MalwareScanIngestModule_SharedProcessing_generalProcessingError_desc(), + null); + } + + // indicate some results were not processed if limits exceeded in results + if (CollectionUtils.isNotEmpty(statusGroupings.get(Status.LIMITS_EXCEEDED))) { + notifyWarning( + Bundle.MalwareScanIngestModule_SharedProcessing_exhaustedResultsHashLookups_title(), + Bundle.MalwareScanIngestModule_SharedProcessing_exhaustedResultsHashLookups_desc(), + null); } } - // TODO return to this - private List getHashLookupResults(List md5Hashes) throws CTCloudException { + /** + * Handles a CT cloud response objects that have a status that isn't + * FOUND but still are queryable (i.e. NOT_FOUND, BEING_SCANNED). + * + * @param ingestJobState The current state of operations of the ingest + * module. + * @param md5ToObjId The mapping of md5 to a list of object ids. + * @param results The ct cloud results. + * @param performFileUpload True if the class of results warrants file + * upload (i.e. NOT_FOUND) + */ + private void handleNonFoundResults(IngestJobState ingestJobState, Map> md5ToObjId, List results, boolean performFileUpload) throws CTCloudException, TskCoreException { + if (CollectionUtils.isNotEmpty(results) + && ingestJobState.isDoFileLookups() + && ((performFileUpload && ingestJobState.isUploadUnknownFiles()) || (!performFileUpload && ingestJobState.isQueryForMissing()))) { + + for (CTCloudBean beingScanned : CollectionUtils.emptyIfNull(results)) { + + String sanitizedMd5 = normalizedMd5(beingScanned.getMd5HashValue()); + if (StringUtils.isBlank(sanitizedMd5)) { + continue; + } + List correspondingObjIds = md5ToObjId.get(sanitizedMd5); + if (CollectionUtils.isEmpty(correspondingObjIds)) { + continue; + } + + if (performFileUpload) { + uploadFile(ingestJobState, correspondingObjIds.get(0)); + } + + ingestJobState.getUnidentifiedHashes().put(sanitizedMd5, correspondingObjIds); + } + } + } + + /** + * Makes CT Cloud REST API query for results regarding the status of a + * list of md5 hashes for executables. + * + * @param ingestJobState The current state of operations of the ingest + * module. + * @param md5Hashes The md5 hashes to check. + * @return The results from CT Cloud. + * @throws CTCloudException + */ + private List getHashLookupResults(IngestJobState ingestJobState, List md5Hashes) throws CTCloudException { // get an auth token with the license - AuthTokenResponse authTokenResponse = ctApiDAO.getAuthToken(licenseInfo.getDecryptedLicense()); + AuthTokenResponse authTokenResponse = ctApiDAO.getAuthToken(ingestJobState.getLicenseInfo().getDecryptedLicense()); // make sure we are in bounds for the remaining scans long remainingScans = remaining(authTokenResponse.getHashLookupLimit(), authTokenResponse.getHashLookupCount()); if (remainingScans <= 0) { - runState = RunState.DISABLED; + ingestJobState.disableDoFileLookups(); notifyWarning( Bundle.MalwareScanIngestModule_SharedProcessing_exhaustedHashLookups_title(), Bundle.MalwareScanIngestModule_SharedProcessing_exhaustedHashLookups_desc(), @@ -434,13 +493,14 @@ public class MalwareScanIngestModule implements FileIngestModule { // using auth token, get results return ctApiDAO.getReputationResults( - new AuthenticatedRequestData(licenseInfo.getDecryptedLicense(), authTokenResponse), + new AuthenticatedRequestData(ingestJobState.getLicenseInfo().getDecryptedLicense(), authTokenResponse), md5Hashes ); } /** * Normalizes an md5 string for the purposes of lookup in a map. + * * @param orig The original value. * @return The normalized value */ @@ -448,19 +508,6 @@ public class MalwareScanIngestModule implements FileIngestModule { return StringUtils.defaultString(orig).trim().toLowerCase(); } - /** - * Returns true if the cloud bean indicates that the file is not - * currently known by CT cloud. - * - * @param cloudBean The cloud bean. - * @return True if not known by CT cloud. - */ - private static boolean isUnknown(CTCloudBean cloudBean) { - return cloudBean != null - && cloudBean.getMalwareResult() != null - && cloudBean.getMalwareResult().getStatus() == MalwareResultBean.Status.NOT_FOUND; - } - /** * Whether or not an abstract file meets the requirements to be * uploaded. @@ -473,22 +520,22 @@ public class MalwareScanIngestModule implements FileIngestModule { return size >= MIN_UPLOAD_SIZE && size <= MAX_UPLOAD_SIZE; } - // TODO return to this - private boolean uploadFile(IngestJobState ingestJobState, CTCloudBean cloudBean, long objId) throws CTCloudException, TskCoreException { - if (!ingestJobState.uploadUnknownFiles()) { - return false; - } - - if (!isUnknown(cloudBean)) { + /** + * Uploads a file to CT Cloud if the file is valid for upload. + * + * @param ingestJobState The current state of the ingest job. + * @param objId The object id of the file to upload to CT cloud. + * @return True if successfully uploaded. + * @throws CTCloudException + * @throws TskCoreException + */ + private boolean uploadFile(IngestJobState ingestJobState, long objId) throws CTCloudException, TskCoreException { + if (!ingestJobState.isUploadUnknownFiles()) { return false; } AbstractFile af = ingestJobState.getTskCase().getAbstractFileById(objId); - if (af == null) { - return false; - } - - if (!isUploadable(af)) { + if (af == null || !isUploadable(af)) { return false; } @@ -498,7 +545,7 @@ public class MalwareScanIngestModule implements FileIngestModule { throw new CTCloudException(CTCloudException.ErrorCode.NETWORK_ERROR); } else if (remaining(authTokenResponse.getFileUploadLimit(), authTokenResponse.getFileUploadCount()) <= 0) { // don't proceed with upload if reached limit - ingestJobState.setUploadUnknownFiles(false); + ingestJobState.disableUploadUnknownFiles(); return false; } @@ -520,25 +567,58 @@ public class MalwareScanIngestModule implements FileIngestModule { return true; } - // TODO return to this - private boolean getUploadedFileResults(Map> md5objIdMapping) throws InterruptedException, CTCloudException, Blackboard.BlackboardException, TskCoreException { - Map> remaining = new HashMap<>(md5objIdMapping); + /** + * + * @param ingestJobState + * @param md5objIdMapping + * @return + * @throws InterruptedException + * @throws CTCloudException + * @throws org.sleuthkit.datamodel.Blackboard.BlackboardException + * @throws TskCoreException + */ + private void longPollForNotFound(IngestJobState ingestJobState) throws InterruptedException, CTCloudException, Blackboard.BlackboardException, TskCoreException { + if (!ingestJobState.isDoFileLookups() || !ingestJobState.isQueryForMissing() || MapUtils.isEmpty(ingestJobState.getUnidentifiedHashes())) { + return; + } + + // TODO notify as a part of status that we are long polling for any missing + Map> remaining = new HashMap<>(ingestJobState.getUnidentifiedHashes()); for (int retry = 0; retry < NUM_FILE_UPLOAD_RETRIES; retry++) { List> md5Batches = Lists.partition(new ArrayList<>(remaining.keySet()), BATCH_SIZE); for (List batch : md5Batches) { - List repResult = getHashLookupResults(batch); - createArtifacts(repResult, remaining); + // if we have exceeded limits, then we're done. + if (!ingestJobState.isDoFileLookups()) { + return; + } + + List repResult = getHashLookupResults(ingestJobState, batch); + + Map> statusGroupings = repResult.stream() + .filter(bean -> bean.getMalwareResult() != null) + .collect(Collectors.groupingBy(bean -> bean.getMalwareResult().getStatus())); + + // for all found items, create analysis results + List found = statusGroupings.get(Status.FOUND); + + createAnalysisResults(ingestJobState, found, remaining); + + // remove any found items from the list of items to long poll for + for (CTCloudBean foundItem : found) { + String normalizedMd5 = normalizedMd5(foundItem.getMd5HashValue()); + remaining.remove(normalizedMd5); + } } if (remaining.isEmpty()) { - return true; + return; } - Thread.sleep(FILE_UPLOAD_RETRY_SLEEP_MILLIS); + Thread.sleep(FILE_UPLOAD_RETRY_SLEEP_MILLIS * ((long) Math.pow(2, retry))); } - return false; + // TODO if we get here, notify that not all lookups performed } /** @@ -548,49 +628,52 @@ public class MalwareScanIngestModule implements FileIngestModule { * @param ingestJobState The ingest job state. * @param repResult The list of cloud beans. Only cloud beans with a * malware status - * @param md5ToObjId + * @param md5ToObjId The mapping of md5 * @throws org.sleuthkit.datamodel.Blackboard.BlackboardException * @throws TskCoreException */ private void createAnalysisResults(IngestJobState ingestJobState, List repResult, Map> md5ToObjId) throws Blackboard.BlackboardException, TskCoreException { - List createdArtifacts = new ArrayList<>(); - if (!CollectionUtils.isEmpty(repResult)) { - SleuthkitCase.CaseDbTransaction trans = null; - try { - trans = ingestJobState.getTskCase().beginTransaction(); - for (CTCloudBean result : repResult) { - String sanitizedMd5 = normalizedMd5(result.getMd5HashValue()); - List objIds = md5ToObjId.remove(sanitizedMd5); - if (objIds == null || objIds.isEmpty()) { - continue; - } + if (CollectionUtils.isEmpty(repResult)) { + return; + } - for (Long objId : objIds) { - AnalysisResult res = createAnalysisResult(ingestJobState, trans, result, objId); - if (res != null) { - createdArtifacts.add(res); - } - } + List createdArtifacts = new ArrayList<>(); + SleuthkitCase.CaseDbTransaction trans = null; + try { + trans = ingestJobState.getTskCase().beginTransaction(); + for (CTCloudBean result : repResult) { + String sanitizedMd5 = normalizedMd5(result.getMd5HashValue()); + List objIds = md5ToObjId.remove(sanitizedMd5); + if (CollectionUtils.isEmpty(objIds)) { + continue; } - trans.commit(); - trans = null; - } finally { - if (trans != null) { - trans.rollback(); - createdArtifacts.clear(); - trans = null; + for (Long objId : objIds) { + AnalysisResult res = createAnalysisResult(ingestJobState, trans, result, objId); + if (res != null) { + createdArtifacts.add(res); + } } } - if (!CollectionUtils.isEmpty(createdArtifacts)) { - ingestJobState.getTskCase().getBlackboard().postArtifacts( - createdArtifacts, - Bundle.MalwareScanIngestModuleFactory_displayName(), - ingestJobState.getIngestJobId() - ); + trans.commit(); + trans = null; + } finally { + if (trans != null) { + trans.rollback(); + createdArtifacts.clear(); + trans = null; } } + + if (!CollectionUtils.isEmpty(createdArtifacts)) { + ingestJobState.getTskCase().getBlackboard().postArtifacts( + createdArtifacts, + Bundle.MalwareScanIngestModuleFactory_displayName(), + ingestJobState.getIngestJobId() + ); + } + } /** @@ -652,15 +735,14 @@ public class MalwareScanIngestModule implements FileIngestModule { }) synchronized void shutDown() { // if already shut down, return - if (runState == RunState.SHUT_DOWN) { + if (ingestJobState == null) { return; } // flush any remaining items try { + longPollForNotFound(ingestJobState); batchProcessor.flushAndReset(); - - getUploadedFileResults(this.unidentifiedHashes); } catch (InterruptedException ex) { notifyWarning( Bundle.MalwareScanIngestModule_SharedProcessing_flushTimeout_title(), @@ -673,7 +755,7 @@ public class MalwareScanIngestModule implements FileIngestModule { ex); } finally { // set state to shut down and clear any remaining - runState = RunState.SHUT_DOWN; + ingestJobState = null; } } @@ -690,10 +772,6 @@ public class MalwareScanIngestModule implements FileIngestModule { logger.log(Level.WARNING, message, ex); } - private enum RunState { - STARTED_UP, DISABLED, SHUT_DOWN - } - class FileRecord { private final long objId; @@ -714,7 +792,28 @@ public class MalwareScanIngestModule implements FileIngestModule { } - class IngestJobState { + /** + * Represents the state of the current ingest job. + * + * NOTE: if doFileLookups is false, most variables will likely be null + * (TSK case, file type detector, etc.) and should not be used. The + * contract for this class should be that if doFileLookups is true or + * uploadUnknownFiles is true, the remaining variables should be non + * null, if doFileLookups is false and uploadUnknownFiles is false, no + * other access to this class can be made reliably. + */ + static class IngestJobState { + + static final IngestJobState DISABLED = new IngestJobState( + null, + null, + null, + null, + 0L, + 0L, + false, + false + ); private final SleuthkitCase tskCase; private final FileTypeDetector fileTypeDetector; @@ -722,19 +821,24 @@ public class MalwareScanIngestModule implements FileIngestModule { private final BlackboardArtifact.Type malwareType; private final long dsId; private final long ingestJobId; + private final boolean queryForMissing; private final Map> unidentifiedHashes = new HashMap<>(); // this can change mid run private boolean uploadUnknownFiles; + private boolean doFileLookups; - IngestJobState(SleuthkitCase tskCase, FileTypeDetector fileTypeDetector, LicenseInfo licenseInfo, BlackboardArtifact.Type malwareType, long dsId, long ingestJobId, boolean uploadUnknownFiles) { + IngestJobState(SleuthkitCase tskCase, FileTypeDetector fileTypeDetector, LicenseInfo licenseInfo, BlackboardArtifact.Type malwareType, long dsId, long ingestJobId, boolean uploadUnknownFiles, boolean doFileLookups) { this.tskCase = tskCase; this.fileTypeDetector = fileTypeDetector; this.licenseInfo = licenseInfo; this.malwareType = malwareType; this.dsId = dsId; this.ingestJobId = ingestJobId; + // for now, querying for any missing files will be tied to whether initially we should upload files and do lookups at all + this.queryForMissing = uploadUnknownFiles && doFileLookups; this.uploadUnknownFiles = uploadUnknownFiles; + this.doFileLookups = doFileLookups; } SleuthkitCase getTskCase() { @@ -765,12 +869,24 @@ public class MalwareScanIngestModule implements FileIngestModule { return unidentifiedHashes; } - boolean uploadUnknownFiles() { + boolean isQueryForMissing() { + return queryForMissing; + } + + boolean isUploadUnknownFiles() { return uploadUnknownFiles; } - void setUploadUnknownFiles(boolean uploadUnknownFiles) { - this.uploadUnknownFiles = uploadUnknownFiles; + void disableUploadUnknownFiles() { + this.uploadUnknownFiles = false; + } + + boolean isDoFileLookups() { + return doFileLookups; + } + + void disableDoFileLookups() { + this.doFileLookups = false; } } } From 346c03fb769f2e7b2d602807748730341af64602 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 27 Jul 2023 13:24:19 -0400 Subject: [PATCH 22/94] resolving TODOs --- .../malwarescan/MalwareScanIngestModule.java | 57 ++++++++++++++----- 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java index 8db2ba70e8..dc54656a15 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java @@ -229,12 +229,11 @@ public class MalwareScanIngestModule implements FileIngestModule { BlackboardArtifact.Category.ANALYSIS_RESULT); return new IngestJobState( + context, tskCase, new FileTypeDetector(), licenseInfoOpt.get(), malwareType, - context.getDataSource().getId(), - context.getJobId(), uploadFiles, true ); @@ -301,6 +300,7 @@ public class MalwareScanIngestModule implements FileIngestModule { try { if (ingestJobState != null && ingestJobState.isDoFileLookups() + && !ingestJobState.getIngestJobContext().fileIngestIsCancelled() && af.getKnown() != TskData.FileKnown.KNOWN && EXECUTABLE_MIME_TYPES.contains(StringUtils.defaultString(ingestJobState.getFileTypeDetector().getMIMEType(af)).trim().toLowerCase()) && CollectionUtils.isEmpty(af.getAnalysisResults(ingestJobState.getMalwareType()))) { @@ -345,7 +345,11 @@ public class MalwareScanIngestModule implements FileIngestModule { "MalwareScanIngestModule_SharedProcessing_generalProcessingError_title=Hash Lookup Error", "MalwareScanIngestModule_SharedProcessing_generalProcessingError_desc=An error occurred while processing hash lookup results",}) private void handleBatch(IngestJobState ingestJobState, List fileRecords) { - if (ingestJobState == null || !ingestJobState.isDoFileLookups() || fileRecords == null || fileRecords.isEmpty()) { + if (ingestJobState == null + || !ingestJobState.isDoFileLookups() + || ingestJobState.getIngestJobContext().fileIngestIsCancelled() + || fileRecords == null + || fileRecords.isEmpty()) { return; } @@ -477,6 +481,10 @@ public class MalwareScanIngestModule implements FileIngestModule { * @throws CTCloudException */ private List getHashLookupResults(IngestJobState ingestJobState, List md5Hashes) throws CTCloudException { + if (ingestJobState.getIngestJobContext().fileIngestIsCancelled()) { + return Collections.emptyList(); + } + // get an auth token with the license AuthTokenResponse authTokenResponse = ctApiDAO.getAuthToken(ingestJobState.getLicenseInfo().getDecryptedLicense()); @@ -489,6 +497,8 @@ public class MalwareScanIngestModule implements FileIngestModule { Bundle.MalwareScanIngestModule_SharedProcessing_exhaustedHashLookups_desc(), null); return Collections.emptyList(); + } else if (ingestJobState.getIngestJobContext().fileIngestIsCancelled()) { + return Collections.emptyList(); } // using auth token, get results @@ -530,7 +540,7 @@ public class MalwareScanIngestModule implements FileIngestModule { * @throws TskCoreException */ private boolean uploadFile(IngestJobState ingestJobState, long objId) throws CTCloudException, TskCoreException { - if (!ingestJobState.isUploadUnknownFiles()) { + if (!ingestJobState.isUploadUnknownFiles() || ingestJobState.getIngestJobContext().fileIngestIsCancelled()) { return false; } @@ -547,6 +557,8 @@ public class MalwareScanIngestModule implements FileIngestModule { // don't proceed with upload if reached limit ingestJobState.disableUploadUnknownFiles(); return false; + } else if (ingestJobState.getIngestJobContext().fileIngestIsCancelled()) { + return false; } // upload bytes @@ -577,19 +589,28 @@ public class MalwareScanIngestModule implements FileIngestModule { * @throws org.sleuthkit.datamodel.Blackboard.BlackboardException * @throws TskCoreException */ + @Messages({ + "MalwareScanIngestModule_longPollForNotFound_fileLookupPolling_title=Waiting for File Upload Results", + "MalwareScanIngestModule_longPollForNotFound_fileLookupPolling_desc=Currently waiting for all files uploaded to Cyber Triage to be processed before finalizing results.", + "MalwareScanIngestModule_longPollForNotFound_timeout_title=File Upload Results Timeout", + "MalwareScanIngestModule_longPollForNotFound_timeout_desc=There was a timeout while waiting for file uploads to be processed. Please try again later.",}) private void longPollForNotFound(IngestJobState ingestJobState) throws InterruptedException, CTCloudException, Blackboard.BlackboardException, TskCoreException { if (!ingestJobState.isDoFileLookups() || !ingestJobState.isQueryForMissing() || MapUtils.isEmpty(ingestJobState.getUnidentifiedHashes())) { return; } - // TODO notify as a part of status that we are long polling for any missing + MessageNotifyUtil.Notify.info( + Bundle.MalwareScanIngestModule_longPollForNotFound_fileLookupPolling_title(), + Bundle.MalwareScanIngestModule_longPollForNotFound_fileLookupPolling_desc() + ); + Map> remaining = new HashMap<>(ingestJobState.getUnidentifiedHashes()); for (int retry = 0; retry < NUM_FILE_UPLOAD_RETRIES; retry++) { List> md5Batches = Lists.partition(new ArrayList<>(remaining.keySet()), BATCH_SIZE); for (List batch : md5Batches) { - // if we have exceeded limits, then we're done. - if (!ingestJobState.isDoFileLookups()) { + // if we have exceeded limits or cancelled, then we're done. + if (!ingestJobState.isDoFileLookups() || ingestJobState.getIngestJobContext().fileIngestIsCancelled()) { return; } @@ -615,10 +636,15 @@ public class MalwareScanIngestModule implements FileIngestModule { return; } + // exponential backoff before trying again Thread.sleep(FILE_UPLOAD_RETRY_SLEEP_MILLIS * ((long) Math.pow(2, retry))); } - // TODO if we get here, notify that not all lookups performed + notifyWarning( + Bundle.MalwareScanIngestModule_longPollForNotFound_timeout_title(), + Bundle.MalwareScanIngestModule_longPollForNotFound_timeout_desc(), + null + ); } /** @@ -809,8 +835,7 @@ public class MalwareScanIngestModule implements FileIngestModule { null, null, null, - 0L, - 0L, + null, false, false ); @@ -827,14 +852,16 @@ public class MalwareScanIngestModule implements FileIngestModule { // this can change mid run private boolean uploadUnknownFiles; private boolean doFileLookups; + private final IngestJobContext ingestJobContext; - IngestJobState(SleuthkitCase tskCase, FileTypeDetector fileTypeDetector, LicenseInfo licenseInfo, BlackboardArtifact.Type malwareType, long dsId, long ingestJobId, boolean uploadUnknownFiles, boolean doFileLookups) { + IngestJobState(IngestJobContext ingestJobContext, SleuthkitCase tskCase, FileTypeDetector fileTypeDetector, LicenseInfo licenseInfo, BlackboardArtifact.Type malwareType, boolean uploadUnknownFiles, boolean doFileLookups) { this.tskCase = tskCase; this.fileTypeDetector = fileTypeDetector; this.licenseInfo = licenseInfo; this.malwareType = malwareType; - this.dsId = dsId; - this.ingestJobId = ingestJobId; + this.dsId = ingestJobContext == null ? 0L : ingestJobContext.getDataSource().getId(); + this.ingestJobId = ingestJobContext == null ? 0L : ingestJobContext.getJobId(); + this.ingestJobContext = ingestJobContext; // for now, querying for any missing files will be tied to whether initially we should upload files and do lookups at all this.queryForMissing = uploadUnknownFiles && doFileLookups; this.uploadUnknownFiles = uploadUnknownFiles; @@ -845,6 +872,10 @@ public class MalwareScanIngestModule implements FileIngestModule { return tskCase; } + IngestJobContext getIngestJobContext() { + return ingestJobContext; + } + FileTypeDetector getFileTypeDetector() { return fileTypeDetector; } From 9a702f5ccab1e64ce4726a29347e9fe1b0d96dbd Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 27 Jul 2023 13:47:49 -0400 Subject: [PATCH 23/94] fixes --- .../ctcloud/Bundle.properties-MERGED | 2 + .../ctcloud/CTMalwareScannerOptionsPanel.form | 94 +++++++++---------- .../ctcloud/CTMalwareScannerOptionsPanel.java | 64 ++++++------- .../malwarescan/Bundle.properties-MERGED | 19 +++- 4 files changed, 92 insertions(+), 87 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED index 58a1befb1f..376ddfa415 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED @@ -56,3 +56,5 @@ CTOPtionsPanel_loadMalwareScansInfo_loading=Loading... EULADialog.cancelButton.text=Cancel EULADialog.acceptButton.text=Accept EULADialog.title=Cyber Triage End User License Agreement +CTMalwareScannerOptionsPanel.fileUploadCheckbox.text=Upload executable if executable is unknown +CTMalwareScannerOptionsPanel.fileUploadPanel.border.title=File Upload diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form index 8f5020d9b9..8557f946d9 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form @@ -11,11 +11,54 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -195,54 +238,5 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java index 34db819373..5dd3a1db66 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java @@ -218,6 +218,8 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { private void initComponents() { java.awt.GridBagConstraints gridBagConstraints; + javax.swing.JPanel fileUploadPanel = new javax.swing.JPanel(); + fileUploadCheckbox = new javax.swing.JCheckBox(); javax.swing.JPanel licenseInfoPanel = new javax.swing.JPanel(); licenseInfoMessageLabel = new javax.swing.JLabel(); licenseInfoUserLabel = new javax.swing.JLabel(); @@ -231,11 +233,38 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { countersResetLabel = new javax.swing.JLabel(); hashLookupsRemainingLabel = new javax.swing.JLabel(); fileUploadsRemainingLabel = new javax.swing.JLabel(); - javax.swing.JPanel fileUploadPanel = new javax.swing.JPanel(); - fileUploadCheckbox = new javax.swing.JCheckBox(); setLayout(new java.awt.GridBagLayout()); + fileUploadPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.fileUploadPanel.border.title"))); // NOI18N + fileUploadPanel.setLayout(new java.awt.GridBagLayout()); + + fileUploadCheckbox.setSelected(true); + org.openide.awt.Mnemonics.setLocalizedText(fileUploadCheckbox, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.fileUploadCheckbox.text")); // NOI18N + fileUploadCheckbox.setMaximumSize(new java.awt.Dimension(32767, 20)); + fileUploadCheckbox.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + fileUploadCheckboxActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); + fileUploadPanel.add(fileUploadCheckbox, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + add(fileUploadPanel, gridBagConstraints); + licenseInfoPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.licenseInfoPanel.border.title"))); // NOI18N licenseInfoPanel.setLayout(new java.awt.GridBagLayout()); @@ -365,37 +394,6 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.weightx = 1.0; add(malwareScansPanel, gridBagConstraints); - - fileUploadPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.fileUploadPanel.border.title"))); // NOI18N - fileUploadPanel.setLayout(new java.awt.GridBagLayout()); - - fileUploadCheckbox.setSelected(true); - org.openide.awt.Mnemonics.setLocalizedText(fileUploadCheckbox, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.fileUploadCheckbox.text")); // NOI18N - fileUploadCheckbox.setMaximumSize(new java.awt.Dimension(32767, 32767)); - fileUploadCheckbox.setMinimumSize(new java.awt.Dimension(255, 50)); - fileUploadCheckbox.setPreferredSize(new java.awt.Dimension(255, 50)); - fileUploadCheckbox.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - fileUploadCheckboxActionPerformed(evt); - } - }); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); - fileUploadPanel.add(fileUploadCheckbox, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.weightx = 1.0; - add(fileUploadPanel, gridBagConstraints); }// //GEN-END:initComponents @Messages({ diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED index 0c97a98c2e..a03690feed 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED @@ -1,3 +1,7 @@ +MalwareScanIngestModule_longPollForNotFound_fileLookupPolling_desc=Currently waiting for all files uploaded to Cyber Triage to be processed before finalizing results. +MalwareScanIngestModule_longPollForNotFound_fileLookupPolling_title=Waiting for File Upload Results +MalwareScanIngestModule_longPollForNotFound_timeout_desc=There was a timeout while waiting for file uploads to be processed. Please try again later. +MalwareScanIngestModule_longPollForNotFound_timeout_title=File Upload Results Timeout MalwareScanIngestModule_malwareTypeDisplayName=Malware # {0} - errorResponse MalwareScanIngestModule_SharedProcessing_authTokenResponseError_desc=Received error: ''{0}'' when fetching the API authentication token for the license @@ -6,6 +10,8 @@ MalwareScanIngestModule_SharedProcessing_createAnalysisResult_No=NO MalwareScanIngestModule_SharedProcessing_createAnalysisResult_Yes=YES MalwareScanIngestModule_SharedProcessing_exhaustedHashLookups_desc=The remaining hash lookups for this license have been exhausted MalwareScanIngestModule_SharedProcessing_exhaustedHashLookups_title=Hash Lookups Exhausted +MalwareScanIngestModule_SharedProcessing_exhaustedResultsHashLookups_desc=Some lookup results were not processed due to exceeding limits. Please try again later. +MalwareScanIngestModule_SharedProcessing_exhaustedResultsHashLookups_title=Some Lookup Results Not Processed MalwareScanIngestModule_SharedProcessing_flushTimeout_desc=A timeout occurred while finishing processing MalwareScanIngestModule_SharedProcessing_flushTimeout_title=Processing Timeout MalwareScanIngestModule_SharedProcessing_generalProcessingError_desc=An error occurred while processing hash lookup results @@ -16,12 +22,17 @@ MalwareScanIngestModule_SharedProcessing_repServicenResponseError_title=Lookup A MalwareScanIngestModule_ShareProcessing_batchTimeout_desc=Batch processing timed out MalwareScanIngestModule_ShareProcessing_batchTimeout_title=Batch Processing Timeout # {0} - remainingLookups -MalwareScanIngestModule_ShareProcessing_lowLimitWarning_desc=This license only has {0} lookups remaining -MalwareScanIngestModule_ShareProcessing_lowLimitWarning_title=Hash Lookups Low +MalwareScanIngestModule_ShareProcessing_lowLookupsLimitWarning_desc=This license only has {0} lookups remaining. +MalwareScanIngestModule_ShareProcessing_lowLookupsLimitWarning_title=Hash Lookups Low +# {0} - remainingUploads +MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_desc=This license only has {0} file uploads remaining. +MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_title=File Uploads Limit Low MalwareScanIngestModule_ShareProcessing_noLicense_desc=No Cyber Triage license could be loaded. Cyber Triage processing will be disabled. MalwareScanIngestModule_ShareProcessing_noLicense_title=No Cyber Triage License -MalwareScanIngestModule_ShareProcessing_noRemaining_desc=There are no more remaining hash lookups for this license at this time. Cyber Triage processing will be disabled. -MalwareScanIngestModule_ShareProcessing_noRemaining_title=No remaining lookups +MalwareScanIngestModule_ShareProcessing_noLookupsRemaining_desc=There are no more remaining hash lookups for this license at this time. Cyber Triage processing will be disabled. +MalwareScanIngestModule_ShareProcessing_noLookupsRemaining_title=No remaining lookups +MalwareScanIngestModule_ShareProcessing_noUploadsRemaining_desc=There are no more remaining file uploads for this license at this time. File uploading will be disabled. +MalwareScanIngestModule_ShareProcessing_noUploadsRemaining_title=No remaining file uploads MalwareScanIngestModuleFactory_description=The malware scan ingest module queries the Cyber Triage cloud API for any possible malicious executables. MalwareScanIngestModuleFactory_displayName=Cyber Triage Malware Scanner MalwareScanIngestModuleFactory_version=1.0.0 From 8917867778cd45a0c6d48f82342a201f3b490e56 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 27 Jul 2023 15:33:29 -0400 Subject: [PATCH 24/94] some fixes --- .../df/cybertriage/autopsy/ctapi/CTApiDAO.java | 2 +- .../autopsy/ctapi/json/MetadataUploadRequest.java | 12 ++++++------ .../autopsy/malwarescan/MalwareScanIngestModule.java | 9 +++++---- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTApiDAO.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTApiDAO.java index b8883df4b2..c358feec61 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTApiDAO.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTApiDAO.java @@ -96,7 +96,7 @@ public class CTApiDAO { } public void uploadMeta(AuthenticatedRequestData authenticatedRequestData, MetadataUploadRequest metaRequest) throws CTCloudException { - httpClient.doPost(AUTH_TOKEN_REQUEST_PATH, getAuthParams(authenticatedRequestData), metaRequest, null); + httpClient.doPost(CTCLOUD_UPLOAD_FILE_METADATA_PATH, getAuthParams(authenticatedRequestData), metaRequest, null); } private static Map getAuthParams(AuthenticatedRequestData authenticatedRequestData) { diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/MetadataUploadRequest.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/MetadataUploadRequest.java index 57d59c3faa..7d7e1e7f64 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/MetadataUploadRequest.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/MetadataUploadRequest.java @@ -38,10 +38,10 @@ public class MetadataUploadRequest { private String filePath; @JsonProperty("fileSize") - private long fileSizeBytes; + private Long fileSizeBytes; @JsonProperty("createdDate") - private long createdDate; + private Long createdDate; public String getFileUploadUrl() { return fileUploadUrl; @@ -88,20 +88,20 @@ public class MetadataUploadRequest { return this; } - public long getFileSizeBytes() { + public Long getFileSizeBytes() { return fileSizeBytes; } - public MetadataUploadRequest setFileSizeBytes(long fileSizeBytes) { + public MetadataUploadRequest setFileSizeBytes(Long fileSizeBytes) { this.fileSizeBytes = fileSizeBytes; return this; } - public long getCreatedDate() { + public Long getCreatedDate() { return createdDate; } - public MetadataUploadRequest setCreatedDate(long createdDate) { + public MetadataUploadRequest setCreatedDate(Long createdDate) { this.createdDate = createdDate; return this; } diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java index dc54656a15..56bfde7356 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java @@ -462,7 +462,7 @@ public class MalwareScanIngestModule implements FileIngestModule { } if (performFileUpload) { - uploadFile(ingestJobState, correspondingObjIds.get(0)); + uploadFile(ingestJobState, sanitizedMd5, correspondingObjIds.get(0)); } ingestJobState.getUnidentifiedHashes().put(sanitizedMd5, correspondingObjIds); @@ -539,7 +539,7 @@ public class MalwareScanIngestModule implements FileIngestModule { * @throws CTCloudException * @throws TskCoreException */ - private boolean uploadFile(IngestJobState ingestJobState, long objId) throws CTCloudException, TskCoreException { + private boolean uploadFile(IngestJobState ingestJobState, String md5, long objId) throws CTCloudException, TskCoreException { if (!ingestJobState.isUploadUnknownFiles() || ingestJobState.getIngestJobContext().fileIngestIsCancelled()) { return false; } @@ -567,11 +567,12 @@ public class MalwareScanIngestModule implements FileIngestModule { // upload metadata MetadataUploadRequest metaRequest = new MetadataUploadRequest() - .setCreatedDate(af.getCrtime()) + .setCreatedDate(af.getCrtime() == 0 ? null : af.getCrtime()) .setFilePath(af.getUniquePath()) .setFileSizeBytes(af.getSize()) .setFileUploadUrl(authTokenResponse.getFileUploadUrl()) - .setMd5(af.getMd5Hash()) + .setMd5(md5) + // these may be missing, but that's fine .setSha1(af.getSha1Hash()) .setSha256(af.getSha256Hash()); From 3e2bbc64219bffa3237c982bb43de22183c22d55 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 27 Jul 2023 17:32:46 -0400 Subject: [PATCH 25/94] updates for sha1 hashing --- .../autopsy/ctapi/CTCloudHttpClient.java | 1 + .../malwarescan/MalwareScanIngestModule.java | 94 +++++++++++++++---- 2 files changed, 77 insertions(+), 18 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java index 91a180e9bc..06e5fb7fcd 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java @@ -200,6 +200,7 @@ public class CTCloudHttpClient { public void doFileUploadPost(String urlPath, String fileName, InputStream fileIs) throws CTCloudException { try (CloseableHttpClient httpclient = createConnection(getProxySettings(), sslContext)) { + LOGGER.log(Level.INFO, "initiating http post request to ctcloud server " + urlPath); HttpPost post = new HttpPost(urlPath); configureRequestTimeout(post); diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java index 56bfde7356..5cbbbed372 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java @@ -27,10 +27,14 @@ import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseInfo; import com.basistech.df.cybertriage.autopsy.ctapi.json.MalwareResultBean.Status; import com.basistech.df.cybertriage.autopsy.ctapi.json.MetadataUploadRequest; import com.basistech.df.cybertriage.autopsy.ctoptions.ctcloud.CTLicensePersistence; +import java.security.DigestInputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.HexFormat; import java.util.List; import java.util.Map; import java.util.Optional; @@ -133,6 +137,7 @@ public class MalwareScanIngestModule implements FileIngestModule { private final CTLicensePersistence ctSettingsPersistence = CTLicensePersistence.getInstance(); private final CTApiDAO ctApiDAO = CTApiDAO.getInstance(); + private final UsernameAnonymizer usernameAnonymizer = new UsernameAnonymizer(); private IngestJobState ingestJobState = null; @@ -258,31 +263,86 @@ public class MalwareScanIngestModule implements FileIngestModule { * @param af The abstract file. * @return The md5 hash (or null if could not be determined). */ - private static String getOrCalcHash(AbstractFile af) { - if (StringUtils.isNotBlank(af.getMd5Hash())) { - return af.getMd5Hash(); + private static String getOrCalcHash(AbstractFile af, HashType hashType) { + switch (hashType) { + case MD5: + if (StringUtils.isNotBlank(af.getMd5Hash())) { + return af.getMd5Hash(); + } + break; + case SHA256: + if (StringUtils.isNotBlank(af.getSha256Hash())) { + return af.getSha256Hash(); + } } try { - List hashResults = HashUtility.calculateHashes(af, Collections.singletonList(HashType.MD5)); + List hashResults = HashUtility.calculateHashes(af, Collections.singletonList(hashType)); if (CollectionUtils.isNotEmpty(hashResults)) { for (HashResult hashResult : hashResults) { - if (hashResult.getType() == HashType.MD5) { + if (hashResult.getType() == hashType) { return hashResult.getValue(); } } } } catch (TskCoreException ex) { logger.log(Level.WARNING, - MessageFormat.format("An error occurred while processing file name: {0} and obj id: {1}.", + MessageFormat.format("An error occurred while processing hash for file name: {0} and obj id: {1} and hash type {2}.", af.getName(), - af.getId()), + af.getId(), + hashType.name()), ex); } return null; } + /** + * Gets or calculates the md5 for a file. + * + * @param af The file. + * @return The hash. + */ + private static String getOrCalcMd5(AbstractFile af) { + return getOrCalcHash(af, HashType.MD5); + } + + /** + * Gets or calculates the sha256 for a file. + * + * @param af The file. + * @return The hash. + */ + private static String getOrCalcSha256(AbstractFile af) { + return getOrCalcHash(af, HashType.SHA256); + } + + /** + * Gets or calculates the sha1 for a file. + * + * @param af The file. + * @return The hash. + */ + private static String getOrCalcSha1(AbstractFile af) throws NoSuchAlgorithmException, ReadContentInputStream.ReadContentInputStreamException { + if (StringUtils.isNotBlank(af.getSha1Hash())) { + return af.getSha1Hash(); + } + // taken from https://stackoverflow.com/questions/6293713/java-how-to-create-sha-1-for-a-file + MessageDigest digest = MessageDigest.getInstance("SHA-1"); + ReadContentInputStream afStream = new ReadContentInputStream(af); + int n = 0; + byte[] buffer = new byte[8192]; + while (n != -1) { + n = afStream.read(buffer); + if (n > 0) { + digest.update(buffer, 0, n); + } + } + byte[] hashBytes = digest.digest(); + String hashString = HexFormat.of().formatHex(hashBytes); + return hashString; + } + /** * Processes a file. The file goes through the lookup process if the * file meets acceptable criteria: 1) not FileKnown.KNOWN 2) is @@ -305,7 +365,7 @@ public class MalwareScanIngestModule implements FileIngestModule { && EXECUTABLE_MIME_TYPES.contains(StringUtils.defaultString(ingestJobState.getFileTypeDetector().getMIMEType(af)).trim().toLowerCase()) && CollectionUtils.isEmpty(af.getAnalysisResults(ingestJobState.getMalwareType()))) { - String md5 = getOrCalcHash(af); + String md5 = getOrCalcMd5(af); if (StringUtils.isNotBlank(md5)) { batchProcessor.add(new FileRecord(af.getId(), md5)); } @@ -393,12 +453,11 @@ public class MalwareScanIngestModule implements FileIngestModule { * @param repResult The ct cloud results. * @throws org.sleuthkit.datamodel.Blackboard.BlackboardException * @throws TskCoreException - * @throws TskCoreException */ @Messages({ "MalwareScanIngestModule_SharedProcessing_exhaustedResultsHashLookups_title=Some Lookup Results Not Processed", "MalwareScanIngestModule_SharedProcessing_exhaustedResultsHashLookups_desc=Some lookup results were not processed due to exceeding limits. Please try again later.",}) - private void handleLookupResults(IngestJobState ingestJobState, Map> md5ToObjId, List repResult) throws Blackboard.BlackboardException, TskCoreException, TskCoreException, CTCloudException { + private void handleLookupResults(IngestJobState ingestJobState, Map> md5ToObjId, List repResult) throws Blackboard.BlackboardException, TskCoreException, TskCoreException, CTCloudException, NoSuchAlgorithmException, ReadContentInputStream.ReadContentInputStreamException { if (CollectionUtils.isEmpty(repResult)) { return; } @@ -445,7 +504,7 @@ public class MalwareScanIngestModule implements FileIngestModule { * @param performFileUpload True if the class of results warrants file * upload (i.e. NOT_FOUND) */ - private void handleNonFoundResults(IngestJobState ingestJobState, Map> md5ToObjId, List results, boolean performFileUpload) throws CTCloudException, TskCoreException { + private void handleNonFoundResults(IngestJobState ingestJobState, Map> md5ToObjId, List results, boolean performFileUpload) throws CTCloudException, TskCoreException, NoSuchAlgorithmException, ReadContentInputStream.ReadContentInputStreamException { if (CollectionUtils.isNotEmpty(results) && ingestJobState.isDoFileLookups() && ((performFileUpload && ingestJobState.isUploadUnknownFiles()) || (!performFileUpload && ingestJobState.isQueryForMissing()))) { @@ -539,7 +598,7 @@ public class MalwareScanIngestModule implements FileIngestModule { * @throws CTCloudException * @throws TskCoreException */ - private boolean uploadFile(IngestJobState ingestJobState, String md5, long objId) throws CTCloudException, TskCoreException { + private boolean uploadFile(IngestJobState ingestJobState, String md5, long objId) throws CTCloudException, TskCoreException, NoSuchAlgorithmException, ReadContentInputStream.ReadContentInputStreamException { if (!ingestJobState.isUploadUnknownFiles() || ingestJobState.getIngestJobContext().fileIngestIsCancelled()) { return false; } @@ -568,13 +627,12 @@ public class MalwareScanIngestModule implements FileIngestModule { // upload metadata MetadataUploadRequest metaRequest = new MetadataUploadRequest() .setCreatedDate(af.getCrtime() == 0 ? null : af.getCrtime()) - .setFilePath(af.getUniquePath()) + .setFilePath(usernameAnonymizer.anonymousUsername(af.getUniquePath())) .setFileSizeBytes(af.getSize()) .setFileUploadUrl(authTokenResponse.getFileUploadUrl()) .setMd5(md5) - // these may be missing, but that's fine - .setSha1(af.getSha1Hash()) - .setSha256(af.getSha256Hash()); + .setSha1(getOrCalcSha1(af)) + .setSha256(getOrCalcSha256(af)); ctApiDAO.uploadMeta(new AuthenticatedRequestData(ingestJobState.getLicenseInfo().getDecryptedLicense(), authTokenResponse), metaRequest); return true; @@ -627,7 +685,7 @@ public class MalwareScanIngestModule implements FileIngestModule { createAnalysisResults(ingestJobState, found, remaining); // remove any found items from the list of items to long poll for - for (CTCloudBean foundItem : found) { + for (CTCloudBean foundItem : CollectionUtils.emptyIfNull(found)) { String normalizedMd5 = normalizedMd5(foundItem.getMd5HashValue()); remaining.remove(normalizedMd5); } @@ -768,8 +826,8 @@ public class MalwareScanIngestModule implements FileIngestModule { // flush any remaining items try { - longPollForNotFound(ingestJobState); batchProcessor.flushAndReset(); + longPollForNotFound(ingestJobState); } catch (InterruptedException ex) { notifyWarning( Bundle.MalwareScanIngestModule_SharedProcessing_flushTimeout_title(), From 2dd82a21ea6bc45a1c003ceed1d2bb8a484d0809 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 27 Jul 2023 17:32:54 -0400 Subject: [PATCH 26/94] updates for sha1 hashing --- .../malwarescan/UsernameAnonymizer.java | 155 ++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/UsernameAnonymizer.java diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/UsernameAnonymizer.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/UsernameAnonymizer.java new file mode 100644 index 0000000000..2b00ece4ab --- /dev/null +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/UsernameAnonymizer.java @@ -0,0 +1,155 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2023 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.basistech.df.cybertriage.autopsy.malwarescan; + +import com.google.common.net.InetAddresses; +import java.net.InetAddress; +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; +import java.util.logging.Level; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.apache.commons.lang3.StringUtils; +import org.sleuthkit.autopsy.coreutils.Logger; + +/** + * Utility class to anonymize username in paths also anonymizes hostname / ip + * from UNC paths + */ +public class UsernameAnonymizer { + + private static final Logger LOGGER = Logger.getLogger(UsernameAnonymizer.class.getName()); + + private final String USER_PATH_FORWARD_SLASH_REGEX = "(?"); + } + String anonymousString = matcher.replaceAll(replacement); + + return anonymousString; + } + + // Most paths in CyberTriage are normalized with forward slashes + // but there can still be strings containing paths that are not normalized such paths contained in arguments or event log payloads + private String anonymizeUserFromPathsWithBackSlashes(String stringWithUsername) { + Pattern pattern = WINDOWS_VERSION < 6 ? Pattern.compile(USER_PATH_BACK_SLASH_REGEX_XP, Pattern.CASE_INSENSITIVE) : Pattern.compile(USER_PATH_BACK_SLASH_REGEX, Pattern.CASE_INSENSITIVE); + Matcher matcher = pattern.matcher(stringWithUsername.toLowerCase(Locale.ENGLISH)); + String replacement = ""; + while (matcher.find()) { + replacement = String.format("$1%s$4", ""); + } + String anonymousString = matcher.replaceAll(replacement); + + return anonymousString; + } + + private String anonymizeServerFromUNCPath(String inputString) { + + Set serverNames = new HashSet<>(); + String anonymousString = inputString.toLowerCase(Locale.ENGLISH); + + Matcher forwardSlashMatcher = UNC_PATH_FORWARD_SLASH_PATTERN.matcher(anonymousString); + while (forwardSlashMatcher.find()) { + String serverName = forwardSlashMatcher.group(2); + serverNames.add(serverName); + } + + Matcher backSlashMatcher = UNC_PATH_BACK_SLASH_PATTERN.matcher(anonymousString); + while (backSlashMatcher.find()) { + String serverName = backSlashMatcher.group(2); + serverNames.add(serverName); + } + + for (String serverName : serverNames) { + + if (StringUtils.isBlank(serverName)) { + continue; + } + + if (InetAddresses.isInetAddress(serverName)) { + if (isLocalIP(serverName)) { + anonymousString = StringUtils.replace(anonymousString, "\\" + serverName + "\\", "\\\\"); + anonymousString = StringUtils.replace(anonymousString, "/" + serverName + "/", "//"); + } + } else { + anonymousString = StringUtils.replace(anonymousString, "\\" + serverName + "\\", "\\\\"); + anonymousString = StringUtils.replace(anonymousString, "/" + serverName + "/", "//"); + } + + } + + return anonymousString; + } + + /** + * Returns true if IP Address is Any Local / Site Local / Link Local / Loop + * back local. Sample list "0.0.0.0", wildcard addres + * "10.1.1.1","10.10.10.10", site local address "127.0.0.0","127.2.2.2", + * loopback address "169.254.0.0","169.254.10.10", Link local address + * "172.16.0.0","172.31.245.245", site local address + * + * @param ipAddress + * @return + */ + public static boolean isLocalIP(String ipAddress) { + try { + InetAddress a = InetAddresses.forString(ipAddress); + return a.isAnyLocalAddress() || a.isSiteLocalAddress() + || a.isLoopbackAddress() || a.isLinkLocalAddress(); + } catch (IllegalArgumentException ex) { + LOGGER.log(Level.WARNING, "Invalid IP string", ex); + return false; + } + } + +} From e3353b29160eeea1ad7856d6e15c65529070ca14 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 27 Jul 2023 18:32:32 -0400 Subject: [PATCH 27/94] fixes for cancellation --- .../malwarescan/MalwareScanIngestModule.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java index 5cbbbed372..f528feb653 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java @@ -639,10 +639,8 @@ public class MalwareScanIngestModule implements FileIngestModule { } /** - * - * @param ingestJobState - * @param md5objIdMapping - * @return + * Does long polling for any pending results. + * @param ingestJobState The state of the ingest job. * @throws InterruptedException * @throws CTCloudException * @throws org.sleuthkit.datamodel.Blackboard.BlackboardException @@ -696,7 +694,13 @@ public class MalwareScanIngestModule implements FileIngestModule { } // exponential backoff before trying again - Thread.sleep(FILE_UPLOAD_RETRY_SLEEP_MILLIS * ((long) Math.pow(2, retry))); + long waitMultiplier = ((long) Math.pow(2, retry)); + for (int i = 0; i < waitMultiplier; i++) { + if (ingestJobState.getIngestJobContext().fileIngestIsCancelled()) { + return; + } + Thread.sleep(FILE_UPLOAD_RETRY_SLEEP_MILLIS); + } } notifyWarning( From dc9c212db521e8451785c022b44b0dc171686bbc Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 27 Jul 2023 19:41:29 -0400 Subject: [PATCH 28/94] fixes --- .../malwarescan/Bundle.properties-MERGED | 5 +++ .../malwarescan/MalwareScanIngestModule.java | 35 +++++++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED index a03690feed..9aecc568df 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED @@ -33,6 +33,11 @@ MalwareScanIngestModule_ShareProcessing_noLookupsRemaining_desc=There are no mor MalwareScanIngestModule_ShareProcessing_noLookupsRemaining_title=No remaining lookups MalwareScanIngestModule_ShareProcessing_noUploadsRemaining_desc=There are no more remaining file uploads for this license at this time. File uploading will be disabled. MalwareScanIngestModule_ShareProcessing_noUploadsRemaining_title=No remaining file uploads +MalwareScanIngestModule_uploadFile_noRemainingFileUploads_desc=There are no more file uploads on this license at this time. File uploads will be disabled for remaining uploads. +MalwareScanIngestModule_uploadFile_noRemainingFileUploads_title=No Remaining File Uploads +# {0} - objectId +MalwareScanIngestModule_uploadFile_notUploadable_desc=A file did not meet requirements for upload (object id: {0}). +MalwareScanIngestModule_uploadFile_notUploadable_title=Not Able to Upload MalwareScanIngestModuleFactory_description=The malware scan ingest module queries the Cyber Triage cloud API for any possible malicious executables. MalwareScanIngestModuleFactory_displayName=Cyber Triage Malware Scanner MalwareScanIngestModuleFactory_version=1.0.0 diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java index f528feb653..9b69226c58 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java @@ -27,7 +27,6 @@ import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseInfo; import com.basistech.df.cybertriage.autopsy.ctapi.json.MalwareResultBean.Status; import com.basistech.df.cybertriage.autopsy.ctapi.json.MetadataUploadRequest; import com.basistech.df.cybertriage.autopsy.ctoptions.ctcloud.CTLicensePersistence; -import java.security.DigestInputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.MessageFormat; @@ -559,6 +558,18 @@ public class MalwareScanIngestModule implements FileIngestModule { } else if (ingestJobState.getIngestJobContext().fileIngestIsCancelled()) { return Collections.emptyList(); } + + // while we have a valid auth token, also check file uploads. + if (ingestJobState.isUploadUnknownFiles()) { + long remainingUploads = remaining(authTokenResponse.getFileUploadLimit(), authTokenResponse.getHashLookupCount()); + if (remainingUploads <= 0) { + ingestJobState.disableUploadUnknownFiles(); + notifyWarning( + Bundle.MalwareScanIngestModule_uploadFile_noRemainingFileUploads_title(), + Bundle.MalwareScanIngestModule_uploadFile_noRemainingFileUploads_desc(), + null); + } + } // using auth token, get results return ctApiDAO.getReputationResults( @@ -598,13 +609,27 @@ public class MalwareScanIngestModule implements FileIngestModule { * @throws CTCloudException * @throws TskCoreException */ + @Messages({ + "MalwareScanIngestModule_uploadFile_notUploadable_title=Not Able to Upload", + "# {0} - objectId", + "MalwareScanIngestModule_uploadFile_notUploadable_desc=A file did not meet requirements for upload (object id: {0}).", + "MalwareScanIngestModule_uploadFile_noRemainingFileUploads_title=No Remaining File Uploads", + "MalwareScanIngestModule_uploadFile_noRemainingFileUploads_desc=There are no more file uploads on this license at this time. File uploads will be disabled for remaining uploads.",}) private boolean uploadFile(IngestJobState ingestJobState, String md5, long objId) throws CTCloudException, TskCoreException, NoSuchAlgorithmException, ReadContentInputStream.ReadContentInputStreamException { if (!ingestJobState.isUploadUnknownFiles() || ingestJobState.getIngestJobContext().fileIngestIsCancelled()) { return false; } AbstractFile af = ingestJobState.getTskCase().getAbstractFileById(objId); - if (af == null || !isUploadable(af)) { + if (af == null) { + return false; + } + + if (!isUploadable(af)) { + notifyWarning( + Bundle.MalwareScanIngestModule_uploadFile_notUploadable_title(), + Bundle.MalwareScanIngestModule_uploadFile_notUploadable_desc(objId), + null); return false; } @@ -615,6 +640,11 @@ public class MalwareScanIngestModule implements FileIngestModule { } else if (remaining(authTokenResponse.getFileUploadLimit(), authTokenResponse.getFileUploadCount()) <= 0) { // don't proceed with upload if reached limit ingestJobState.disableUploadUnknownFiles(); + notifyWarning( + Bundle.MalwareScanIngestModule_uploadFile_noRemainingFileUploads_title(), + Bundle.MalwareScanIngestModule_uploadFile_noRemainingFileUploads_desc(), + null); + return false; } else if (ingestJobState.getIngestJobContext().fileIngestIsCancelled()) { return false; @@ -640,6 +670,7 @@ public class MalwareScanIngestModule implements FileIngestModule { /** * Does long polling for any pending results. + * * @param ingestJobState The state of the ingest job. * @throws InterruptedException * @throws CTCloudException From ce1c57dc79f55157b474b9e73495c56688aec229 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 27 Jul 2023 20:22:22 -0400 Subject: [PATCH 29/94] some updates --- .../malwarescan/MalwareScanIngestModule.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java index 9b69226c58..bb7df071b2 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java @@ -558,16 +558,16 @@ public class MalwareScanIngestModule implements FileIngestModule { } else if (ingestJobState.getIngestJobContext().fileIngestIsCancelled()) { return Collections.emptyList(); } - + // while we have a valid auth token, also check file uploads. if (ingestJobState.isUploadUnknownFiles()) { - long remainingUploads = remaining(authTokenResponse.getFileUploadLimit(), authTokenResponse.getHashLookupCount()); + long remainingUploads = remaining(authTokenResponse.getFileUploadLimit(), authTokenResponse.getFileUploadCount()); if (remainingUploads <= 0) { ingestJobState.disableUploadUnknownFiles(); notifyWarning( - Bundle.MalwareScanIngestModule_uploadFile_noRemainingFileUploads_title(), - Bundle.MalwareScanIngestModule_uploadFile_noRemainingFileUploads_desc(), - null); + Bundle.MalwareScanIngestModule_uploadFile_noRemainingFileUploads_title(), + Bundle.MalwareScanIngestModule_uploadFile_noRemainingFileUploads_desc(), + null); } } @@ -683,7 +683,10 @@ public class MalwareScanIngestModule implements FileIngestModule { "MalwareScanIngestModule_longPollForNotFound_timeout_title=File Upload Results Timeout", "MalwareScanIngestModule_longPollForNotFound_timeout_desc=There was a timeout while waiting for file uploads to be processed. Please try again later.",}) private void longPollForNotFound(IngestJobState ingestJobState) throws InterruptedException, CTCloudException, Blackboard.BlackboardException, TskCoreException { - if (!ingestJobState.isDoFileLookups() || !ingestJobState.isQueryForMissing() || MapUtils.isEmpty(ingestJobState.getUnidentifiedHashes())) { + if (!ingestJobState.isDoFileLookups() + || !ingestJobState.isQueryForMissing() + || MapUtils.isEmpty(ingestJobState.getUnidentifiedHashes()) + || ingestJobState.getIngestJobContext().fileIngestIsCancelled()) { return; } From 16ec6a3ad6e63fb7cee6edda65353cbba63f953a Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Tue, 1 Aug 2023 07:50:12 -0400 Subject: [PATCH 30/94] Update NEWS.txtew --- NEWS.txt | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/NEWS.txt b/NEWS.txt index 5a2bd33b57..9a3e1ba6da 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -1,19 +1,22 @@ ---------------- VERSION 4.21.0 -------------- -General +Library Updates - Update Java to version 17 - -Recent Activity Updates: -- Check For Malicious Chrome Extensions +- Update aLeapp/iLeapp executables. +- Update JNA Version +- Update SQLite library version +- Updated 3rd party libraries that have known CVE's Ingest Module Updates: -- Inline Keyword Search -- Update aLeapp/iLeapp executables. +- Recent Activity checks for malicious Chrome extensions +- Keyword Search module now can search without needing to index text into Solr. +- New Cyber Triage Malware Scanner module that uses Reversing Labs (requires license) + +Add Data Source Updates: +- Timestamps for logical files can be added. +- List of logical files/folders can be edited before they are added. GUI Updates: -- Add "has attachments" flag for email's -- Add ability to delete a logical file/path from logical file - DSP panel before it is run. -- Add ability to add timestamps when adding localfiles as a data source +- Add "has attachments" flag for emails - Add Score to tree view Bugs: @@ -21,11 +24,8 @@ Bugs: - Fix exporting of CSV files Misc: -- Update JNA Version -- Update SQLite library version - Add export for Pasco -- Cyber Triage intergration -- Updated 3rd party libraries that have known CVE's +- Added File Repository concept ---------------- VERSION 4.20.0 -------------- Recent Activity Updates: From f2a32bf710a9f74e28dba587e82cf59e15e60f97 Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Tue, 1 Aug 2023 10:17:19 -0400 Subject: [PATCH 31/94] Update NEWS.txt fixes --- NEWS.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/NEWS.txt b/NEWS.txt index 9a3e1ba6da..3ba3ebf9af 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -1,4 +1,4 @@ ----------------- VERSION 4.21.0 -------------- +---------------- VERSION 4.21.0 --------------- Library Updates - Update Java to version 17 - Update aLeapp/iLeapp executables. @@ -7,25 +7,25 @@ Library Updates - Updated 3rd party libraries that have known CVE's Ingest Module Updates: -- Recent Activity checks for malicious Chrome extensions +- Recent Activity checks for malicious Chrome extensions from list provided by https://github.com/randomaccess3/detections - Keyword Search module now can search without needing to index text into Solr. - New Cyber Triage Malware Scanner module that uses Reversing Labs (requires license) Add Data Source Updates: -- Timestamps for logical files can be added. -- List of logical files/folders can be edited before they are added. +- Timestamps for logical files can be added. Issue https://github.com/sleuthkit/autopsy/issues/5852, https://github.com/sleuthkit/autopsy/issues/1788 +- List of logical files/folders can be edited before they are added. Issue https://github.com/sleuthkit/autopsy/issues/7347 GUI Updates: -- Add "has attachments" flag for emails +- Add "has attachments" flag for emails. Issue https://github.com/sleuthkit/autopsy/issues/7358 - Add Score to tree view Bugs: - Fix path for lnk files -- Fix exporting of CSV files +- Fix exporting of CSV files. Issue https://github.com/sleuthkit/autopsy/issues/6717 Misc: -- Add export for Pasco - Added File Repository concept +- Added Spanish language support, contributor https://github.com/AburtoArielPM ---------------- VERSION 4.20.0 -------------- Recent Activity Updates: From dde67efc0966fe9ebe27f446dc5bc8f74f025ca7 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 1 Aug 2023 11:45:08 -0400 Subject: [PATCH 32/94] centralize link and rename provider --- .../basistech/df/cybertriage/autopsy/Bundle.properties | 1 - .../cybertriage/autopsy/CTIntegrationMissingDialog.form | 8 ++------ .../cybertriage/autopsy/CTIntegrationMissingDialog.java | 5 +++-- Core/src/org/sleuthkit/autopsy/casemodule/Case.java | 2 +- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/Bundle.properties b/Core/src/com/basistech/df/cybertriage/autopsy/Bundle.properties index 4d7a376395..caab36116d 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/Bundle.properties +++ b/Core/src/com/basistech/df/cybertriage/autopsy/Bundle.properties @@ -5,6 +5,5 @@ CTIntegrationMissingDialog.title=Cyber Triage Importer Module Required CTIntegrationMissingDialog.descriptionLabel.text=

The Cyber Triage Importer Module is required to open this case.

To open this case:

  • Extract the module from the Integrations tab in the Cyber Triage options panel.
  • Select the 'Plugins' option from the 'Tools' menu, and go to the 'Downloaded' tab.
  • Click 'Add Plugins...' and select the path of the plugin.
  • Press 'Install' to finish the installation.
-CTIntegrationMissingDialog.link.text=http://docs.cybertriage.com CTIntegrationMissingDialog.docsLabel.text=For more information, refer to the Cyber Triage Users Guide CTIntegrationMissingDialog.okButton.text=OK diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/CTIntegrationMissingDialog.form b/Core/src/com/basistech/df/cybertriage/autopsy/CTIntegrationMissingDialog.form index 59955cb3dd..e61f2f6cbd 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/CTIntegrationMissingDialog.form +++ b/Core/src/com/basistech/df/cybertriage/autopsy/CTIntegrationMissingDialog.form @@ -68,8 +68,8 @@ - - + + @@ -78,10 +78,6 @@ - - - - diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/CTIntegrationMissingDialog.java b/Core/src/com/basistech/df/cybertriage/autopsy/CTIntegrationMissingDialog.java index 98690ced57..8fbec4abef 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/CTIntegrationMissingDialog.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/CTIntegrationMissingDialog.java @@ -56,7 +56,7 @@ public class CTIntegrationMissingDialog extends javax.swing.JDialog { javax.swing.JLabel descriptionLabel = new javax.swing.JLabel(); javax.swing.JLabel docsLabel = new javax.swing.JLabel(); - javax.swing.JLabel link = new javax.swing.JLabel(); + link = new javax.swing.JLabel(); javax.swing.JPanel paddingPanel = new javax.swing.JPanel(); javax.swing.JButton okButton = new javax.swing.JButton(); @@ -87,7 +87,7 @@ public class CTIntegrationMissingDialog extends javax.swing.JDialog { gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 0); getContentPane().add(docsLabel, gridBagConstraints); - org.openide.awt.Mnemonics.setLocalizedText(link, org.openide.util.NbBundle.getMessage(CTIntegrationMissingDialog.class, "CTIntegrationMissingDialog.link.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(link, "" + DOCS_PAGE_URL + ""); link.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR)); link.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { @@ -160,5 +160,6 @@ public class CTIntegrationMissingDialog extends javax.swing.JDialog { } // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel link; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 45a4d6dff6..b1d2f28c31 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -178,7 +178,7 @@ public class Case { private static final String CASE_ACTION_THREAD_NAME = "%s-case-action"; private static final String CASE_RESOURCES_THREAD_NAME = "%s-manage-case-resources"; private static final String NO_NODE_ERROR_MSG_FRAGMENT = "KeeperErrorCode = NoNode"; - private static final String CT_PROVIDER_PREFIX = "CTCustomContentProvider_"; + private static final String CT_PROVIDER_PREFIX = "CTStandardContentProvider_"; private static final Logger logger = Logger.getLogger(Case.class.getName()); private static final AutopsyEventPublisher eventPublisher = new AutopsyEventPublisher(); private static final Object caseActionSerializationLock = new Object(); From ffb1927a281c28a2b7bdaed6bdbf39ca33dff65f Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 1 Aug 2023 12:10:27 -0400 Subject: [PATCH 33/94] message updates --- .../autopsy/ctoptions/ctcloud/Bundle.properties | 2 +- .../autopsy/ctoptions/ctcloud/Bundle.properties-MERGED | 2 +- .../autopsy/malwarescan/Bundle.properties-MERGED | 8 ++++---- .../autopsy/malwarescan/MalwareScanIngestModule.java | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties index 979010bb23..d0395d6a1a 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties @@ -24,5 +24,5 @@ CTMalwareScannerOptionsPanel.licenseInfoUserLabel.text= EULADialog.cancelButton.text=Cancel EULADialog.acceptButton.text=Accept EULADialog.title=Cyber Triage End User License Agreement -CTMalwareScannerOptionsPanel.fileUploadCheckbox.text=Upload executable if executable is unknown +CTMalwareScannerOptionsPanel.fileUploadCheckbox.text=Upload file if hash lookup produces no results CTMalwareScannerOptionsPanel.fileUploadPanel.border.title=File Upload diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED index 376ddfa415..b05bb1cfe4 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED @@ -56,5 +56,5 @@ CTOPtionsPanel_loadMalwareScansInfo_loading=Loading... EULADialog.cancelButton.text=Cancel EULADialog.acceptButton.text=Accept EULADialog.title=Cyber Triage End User License Agreement -CTMalwareScannerOptionsPanel.fileUploadCheckbox.text=Upload executable if executable is unknown +CTMalwareScannerOptionsPanel.fileUploadCheckbox.text=Upload file if hash lookup produces no results CTMalwareScannerOptionsPanel.fileUploadPanel.border.title=File Upload diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED index 9aecc568df..4380a9607c 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED @@ -1,4 +1,4 @@ -MalwareScanIngestModule_longPollForNotFound_fileLookupPolling_desc=Currently waiting for all files uploaded to Cyber Triage to be processed before finalizing results. +MalwareScanIngestModule_longPollForNotFound_fileLookupPolling_desc=Waiting for all uploaded files to complete scanning. MalwareScanIngestModule_longPollForNotFound_fileLookupPolling_title=Waiting for File Upload Results MalwareScanIngestModule_longPollForNotFound_timeout_desc=There was a timeout while waiting for file uploads to be processed. Please try again later. MalwareScanIngestModule_longPollForNotFound_timeout_title=File Upload Results Timeout @@ -10,8 +10,8 @@ MalwareScanIngestModule_SharedProcessing_createAnalysisResult_No=NO MalwareScanIngestModule_SharedProcessing_createAnalysisResult_Yes=YES MalwareScanIngestModule_SharedProcessing_exhaustedHashLookups_desc=The remaining hash lookups for this license have been exhausted MalwareScanIngestModule_SharedProcessing_exhaustedHashLookups_title=Hash Lookups Exhausted -MalwareScanIngestModule_SharedProcessing_exhaustedResultsHashLookups_desc=Some lookup results were not processed due to exceeding limits. Please try again later. -MalwareScanIngestModule_SharedProcessing_exhaustedResultsHashLookups_title=Some Lookup Results Not Processed +MalwareScanIngestModule_SharedProcessing_exhaustedResultsHashLookups_desc=Not all files were processed because hash lookup limits were exceeded. Please try again when your limits reset. +MalwareScanIngestModule_SharedProcessing_exhaustedResultsHashLookups_title=Lookup Limits Exceeded MalwareScanIngestModule_SharedProcessing_flushTimeout_desc=A timeout occurred while finishing processing MalwareScanIngestModule_SharedProcessing_flushTimeout_title=Processing Timeout MalwareScanIngestModule_SharedProcessing_generalProcessingError_desc=An error occurred while processing hash lookup results @@ -29,7 +29,7 @@ MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_desc=This license MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_title=File Uploads Limit Low MalwareScanIngestModule_ShareProcessing_noLicense_desc=No Cyber Triage license could be loaded. Cyber Triage processing will be disabled. MalwareScanIngestModule_ShareProcessing_noLicense_title=No Cyber Triage License -MalwareScanIngestModule_ShareProcessing_noLookupsRemaining_desc=There are no more remaining hash lookups for this license at this time. Cyber Triage processing will be disabled. +MalwareScanIngestModule_ShareProcessing_noLookupsRemaining_desc=There are no more remaining hash lookups for this license at this time. Malware scanning will be disabled. MalwareScanIngestModule_ShareProcessing_noLookupsRemaining_title=No remaining lookups MalwareScanIngestModule_ShareProcessing_noUploadsRemaining_desc=There are no more remaining file uploads for this license at this time. File uploading will be disabled. MalwareScanIngestModule_ShareProcessing_noUploadsRemaining_title=No remaining file uploads diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java index bb7df071b2..f15236cd1d 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java @@ -145,7 +145,7 @@ public class MalwareScanIngestModule implements FileIngestModule { "MalwareScanIngestModule_ShareProcessing_noLicense_title=No Cyber Triage License", "MalwareScanIngestModule_ShareProcessing_noLicense_desc=No Cyber Triage license could be loaded. Cyber Triage processing will be disabled.", "MalwareScanIngestModule_ShareProcessing_noLookupsRemaining_title=No remaining lookups", - "MalwareScanIngestModule_ShareProcessing_noLookupsRemaining_desc=There are no more remaining hash lookups for this license at this time. Cyber Triage processing will be disabled.", + "MalwareScanIngestModule_ShareProcessing_noLookupsRemaining_desc=There are no more remaining hash lookups for this license at this time. Malware scanning will be disabled.", "MalwareScanIngestModule_ShareProcessing_lowLookupsLimitWarning_title=Hash Lookups Low", "# {0} - remainingLookups", "MalwareScanIngestModule_ShareProcessing_lowLookupsLimitWarning_desc=This license only has {0} lookups remaining.", @@ -454,8 +454,8 @@ public class MalwareScanIngestModule implements FileIngestModule { * @throws TskCoreException */ @Messages({ - "MalwareScanIngestModule_SharedProcessing_exhaustedResultsHashLookups_title=Some Lookup Results Not Processed", - "MalwareScanIngestModule_SharedProcessing_exhaustedResultsHashLookups_desc=Some lookup results were not processed due to exceeding limits. Please try again later.",}) + "MalwareScanIngestModule_SharedProcessing_exhaustedResultsHashLookups_title=Lookup Limits Exceeded", + "MalwareScanIngestModule_SharedProcessing_exhaustedResultsHashLookups_desc=Not all files were processed because hash lookup limits were exceeded. Please try again when your limits reset.",}) private void handleLookupResults(IngestJobState ingestJobState, Map> md5ToObjId, List repResult) throws Blackboard.BlackboardException, TskCoreException, TskCoreException, CTCloudException, NoSuchAlgorithmException, ReadContentInputStream.ReadContentInputStreamException { if (CollectionUtils.isEmpty(repResult)) { return; @@ -679,7 +679,7 @@ public class MalwareScanIngestModule implements FileIngestModule { */ @Messages({ "MalwareScanIngestModule_longPollForNotFound_fileLookupPolling_title=Waiting for File Upload Results", - "MalwareScanIngestModule_longPollForNotFound_fileLookupPolling_desc=Currently waiting for all files uploaded to Cyber Triage to be processed before finalizing results.", + "MalwareScanIngestModule_longPollForNotFound_fileLookupPolling_desc=Waiting for all uploaded files to complete scanning.", "MalwareScanIngestModule_longPollForNotFound_timeout_title=File Upload Results Timeout", "MalwareScanIngestModule_longPollForNotFound_timeout_desc=There was a timeout while waiting for file uploads to be processed. Please try again later.",}) private void longPollForNotFound(IngestJobState ingestJobState) throws InterruptedException, CTCloudException, Blackboard.BlackboardException, TskCoreException { From f27b432fe3885ab930d2615a01f8e490ac21d2cf Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 1 Aug 2023 13:58:25 -0400 Subject: [PATCH 34/94] fix for bundle --- .../basistech/df/cybertriage/autopsy/Bundle.properties-MERGED | 1 - 1 file changed, 1 deletion(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/Bundle.properties-MERGED b/Core/src/com/basistech/df/cybertriage/autopsy/Bundle.properties-MERGED index 4d7a376395..caab36116d 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/Bundle.properties-MERGED +++ b/Core/src/com/basistech/df/cybertriage/autopsy/Bundle.properties-MERGED @@ -5,6 +5,5 @@ CTIntegrationMissingDialog.title=Cyber Triage Importer Module Required CTIntegrationMissingDialog.descriptionLabel.text=

The Cyber Triage Importer Module is required to open this case.

To open this case:

  • Extract the module from the Integrations tab in the Cyber Triage options panel.
  • Select the 'Plugins' option from the 'Tools' menu, and go to the 'Downloaded' tab.
  • Click 'Add Plugins...' and select the path of the plugin.
  • Press 'Install' to finish the installation.
-CTIntegrationMissingDialog.link.text=http://docs.cybertriage.com CTIntegrationMissingDialog.docsLabel.text=For more information, refer to the Cyber Triage Users Guide CTIntegrationMissingDialog.okButton.text=OK From 5368f84853e92e99b3df1a569af6eff6d29714af Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 1 Aug 2023 21:04:30 -0400 Subject: [PATCH 35/94] change for package scope --- .../autopsy/ctapi/CTCloudHttpClient.java | 2 +- .../cybertriage/autopsy/ctapi/Constants.java | 2 +- .../autopsy/ctapi/ProxySettings.java | 2 +- .../ctoptions/ctcloud/CTLicenseDialog.java | 2 +- .../ctcloud/CTLicensePersistence.java | 1 - .../autopsy/ctoptions/ctcloud/EULADialog.java | 2 +- .../autopsy/malwarescan/BatchProcessor.java | 6 +- .../autopsy/malwarescan/FileUpload.java | 93 ------------------- .../malwarescan/MalwareScanIngestModule.java | 2 +- .../malwarescan/UsernameAnonymizer.java | 2 +- 10 files changed, 8 insertions(+), 106 deletions(-) delete mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/FileUpload.java diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java index 06e5fb7fcd..0374fd2b2b 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java @@ -67,7 +67,7 @@ import org.sleuthkit.autopsy.coreutils.Version; /** * Makes the http requests to CT cloud. */ -public class CTCloudHttpClient { +class CTCloudHttpClient { private static final CTCloudHttpClient instance = new CTCloudHttpClient(); private static final Logger LOGGER = Logger.getLogger(CTCloudHttpClient.class.getName()); diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/Constants.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/Constants.java index 9587b3cd44..8290d6621d 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/Constants.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/Constants.java @@ -23,7 +23,7 @@ import java.net.URI; /** * Constants regarding connections to cyber triage cloud. */ -final public class Constants { +final class Constants { public static final String CYBER_TRIAGE = "CyberTriage"; diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/ProxySettings.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/ProxySettings.java index f710a6ab1b..cbd538d01b 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/ProxySettings.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/ProxySettings.java @@ -32,7 +32,7 @@ import org.openide.util.lookup.ServiceProvider; * Taken from https://raw.githubusercontent.com/apache/netbeans/master/platform/o.n.core/src/org/netbeans/core/ProxySettings.java * @author Jiri Rechtacek */ -public class ProxySettings { +class ProxySettings { public static final String PROXY_HTTP_HOST = "proxyHttpHost"; // NOI18N public static final String PROXY_HTTP_PORT = "proxyHttpPort"; // NOI18N diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.java index 608ea63040..3bff998901 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.java @@ -27,7 +27,7 @@ import org.openide.util.NbBundle.Messages; /** * License dialog */ -public class CTLicenseDialog extends javax.swing.JDialog { +class CTLicenseDialog extends javax.swing.JDialog { private static final Pattern LICENSE_PATTERN = Pattern.compile("^\\s*[a-zA-Z0-9\\-]+?\\s*$"); private String licenseString = null; diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicensePersistence.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicensePersistence.java index e95d9e7279..717c4f4321 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicensePersistence.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicensePersistence.java @@ -26,7 +26,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.File; import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Paths; import java.util.Optional; import java.util.logging.Level; diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/EULADialog.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/EULADialog.java index 31056e1f2a..0279cafb9b 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/EULADialog.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/EULADialog.java @@ -36,7 +36,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; /** * Dialog for displaying the Cyber Triage EULA before the license is saved. */ -public class EULADialog extends javax.swing.JDialog { +class EULADialog extends javax.swing.JDialog { private static final Logger LOGGER = Logger.getLogger(EULADialog.class.getName()); private static final String EULA_RESOURCE = "EULA.htm"; diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/BatchProcessor.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/BatchProcessor.java index eab025a641..a65d319dc2 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/BatchProcessor.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/BatchProcessor.java @@ -21,14 +21,10 @@ package com.basistech.df.cybertriage.autopsy.malwarescan; import java.util.ArrayList; import java.util.List; import java.util.concurrent.BlockingQueue; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; import java.util.function.Consumer; /** @@ -36,7 +32,7 @@ import java.util.function.Consumer; * blocks (and subsequently add and flush operations) until previous batch * finishes. */ -public class BatchProcessor { +class BatchProcessor { private ExecutorService processingExecutorService = Executors.newSingleThreadExecutor(); diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/FileUpload.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/FileUpload.java deleted file mode 100644 index 4803793514..0000000000 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/FileUpload.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2023 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.basistech.df.cybertriage.autopsy.malwarescan; - -import com.basistech.df.cybertriage.autopsy.ctapi.CTApiDAO; -import com.basistech.df.cybertriage.autopsy.ctapi.CTCloudException; -import com.basistech.df.cybertriage.autopsy.ctapi.json.AuthTokenResponse; -import com.basistech.df.cybertriage.autopsy.ctapi.json.AuthenticatedRequestData; -import com.basistech.df.cybertriage.autopsy.ctapi.json.CTCloudBean; -import com.basistech.df.cybertriage.autopsy.ctapi.json.DecryptedLicenseResponse; -import com.basistech.df.cybertriage.autopsy.ctapi.json.MalwareResultBean.Status; -import com.basistech.df.cybertriage.autopsy.ctapi.json.MetadataUploadRequest; -import org.apache.commons.lang3.StringUtils; -import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.ReadContentInputStream; -import org.sleuthkit.datamodel.SleuthkitCase; -import org.sleuthkit.datamodel.TskCoreException; - -/** - * Handles uploading of files that are unknown. - */ -public class FileUpload { - private static final long MIN_UPLOAD_SIZE = 1; - private static final long MAX_UPLOAD_SIZE = 1_000_000_000; - - private final CTApiDAO ctApiDAO = CTApiDAO.getInstance(); - - private boolean isUnknown(CTCloudBean cloudBean) { - return cloudBean != null - && cloudBean.getMalwareResult() != null - && cloudBean.getMalwareResult().getStatus() == Status.NOT_FOUND; - } - - private boolean isUploadable(AbstractFile af) { - long size = af.getSize(); - return size >= MIN_UPLOAD_SIZE && size <= MAX_UPLOAD_SIZE; - } - - private boolean upload(SleuthkitCase skCase, DecryptedLicenseResponse decrypted, CTCloudBean cloudBean, long objId) throws CTCloudException, TskCoreException { - if (!isUnknown(cloudBean)) { - return false; - } - - AbstractFile af = skCase.getAbstractFileById(objId); - if (af == null) { - return false; - } - - if (!isUploadable(af)) { - return false; - } - - // get auth token / file upload url - AuthTokenResponse authTokenResponse = ctApiDAO.getAuthToken(decrypted, true); - if (StringUtils.isBlank(authTokenResponse.getFileUploadUrl())) { - throw new CTCloudException(CTCloudException.ErrorCode.NETWORK_ERROR); - } - - // upload bytes - ReadContentInputStream fileInputStream = new ReadContentInputStream(af); - ctApiDAO.uploadFile(authTokenResponse.getFileUploadUrl(), af.getName(), fileInputStream); - - // upload metadata - MetadataUploadRequest metaRequest = new MetadataUploadRequest() - .setCreatedDate(af.getCrtime()) - .setFilePath(af.getUniquePath()) - .setFileSizeBytes(af.getSize()) - .setFileUploadUrl(authTokenResponse.getFileUploadUrl()) - .setMd5(af.getMd5Hash()) - .setSha1(af.getSha1Hash()) - .setSha256(af.getSha256Hash()); - - ctApiDAO.uploadMeta(new AuthenticatedRequestData(decrypted, authTokenResponse), metaRequest); - return true; - } - -} diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java index f15236cd1d..2d73effa5c 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java @@ -69,7 +69,7 @@ import org.sleuthkit.datamodel.TskData; /** * Uses CT cloud API to determine if file is malware */ -public class MalwareScanIngestModule implements FileIngestModule { +class MalwareScanIngestModule implements FileIngestModule { private static final SharedProcessing sharedProcessing = new SharedProcessing(); diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/UsernameAnonymizer.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/UsernameAnonymizer.java index 2b00ece4ab..75261ae43f 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/UsernameAnonymizer.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/UsernameAnonymizer.java @@ -33,7 +33,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; * Utility class to anonymize username in paths also anonymizes hostname / ip * from UNC paths */ -public class UsernameAnonymizer { +class UsernameAnonymizer { private static final Logger LOGGER = Logger.getLogger(UsernameAnonymizer.class.getName()); From 7ec44a2fb290ff6315ef9611253dafc50b1716a8 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 3 Aug 2023 15:37:14 -0400 Subject: [PATCH 36/94] trust store changes --- .../autopsy/ctapi/CTCloudHttpClient.java | 98 ++++++++++++++++--- 1 file changed, 85 insertions(+), 13 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java index 0374fd2b2b..622595083e 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java @@ -28,6 +28,12 @@ import java.net.PasswordAuthentication; import java.net.URI; import java.net.URISyntaxException; import java.net.UnknownHostException; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.UnrecoverableKeyException; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; @@ -37,7 +43,12 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Objects; import java.util.logging.Level; +import javax.net.ssl.KeyManager; +import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpEntity; @@ -62,6 +73,7 @@ import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.client.SystemDefaultCredentialsProvider; import org.apache.http.impl.client.WinHttpClients; +import org.apache.http.ssl.SSLInitializationException; import org.sleuthkit.autopsy.coreutils.Version; /** @@ -69,7 +81,8 @@ import org.sleuthkit.autopsy.coreutils.Version; */ class CTCloudHttpClient { - private static final CTCloudHttpClient instance = new CTCloudHttpClient(); + private static final String KS_PASSWORD = "changeit"; // system default java password + private static final Logger LOGGER = Logger.getLogger(CTCloudHttpClient.class.getName()); private static final String HOST_URL = Version.getBuildType() == Version.Type.RELEASE ? Constants.CT_CLOUD_SERVER : Constants.CT_CLOUD_DEV_SERVER; @@ -84,6 +97,8 @@ class CTCloudHttpClient { private static final int CONNECTION_TIMEOUT_MS = 58 * 1000; // milli sec + private static final CTCloudHttpClient instance = new CTCloudHttpClient(); + public static CTCloudHttpClient getInstance() { return instance; } @@ -94,7 +109,7 @@ class CTCloudHttpClient { private CTCloudHttpClient() { // leave as null for now unless we want to customize this at a later date - this.sslContext = null; + this.sslContext = createSSLContext(); } private ProxySettingArgs getProxySettings() { @@ -125,7 +140,7 @@ class CTCloudHttpClient { null ); } - + public O doPost(String urlPath, Object jsonBody, Class classType) throws CTCloudException { return doPost(urlPath, Collections.emptyMap(), jsonBody, classType); } @@ -137,7 +152,7 @@ class CTCloudHttpClient { LOGGER.log(Level.INFO, "initiating http connection to ctcloud server"); try (CloseableHttpClient httpclient = createConnection(getProxySettings(), sslContext)) { URIBuilder builder = new URIBuilder(url); - + if (!MapUtils.isEmpty(urlReqParams)) { for (Entry e : urlReqParams.entrySet()) { String key = e.getKey(); @@ -151,7 +166,6 @@ class CTCloudHttpClient { URI postURI = builder.build(); HttpPost postRequest = new HttpPost(postURI); - configureRequestTimeout(postRequest); postRequest.setHeader("Content-type", "application/json"); @@ -189,6 +203,9 @@ class CTCloudHttpClient { } catch (IOException ex) { LOGGER.log(Level.WARNING, "IO Exception raised when connecting to CT Cloud using " + url, ex); throw new CTCloudException(CTCloudException.ErrorCode.NETWORK_ERROR, ex); + } catch (SSLInitializationException ex) { + LOGGER.log(Level.WARNING, "No such algorithm exception raised when creating SSL connection for CT Cloud using " + url, ex); + throw new CTCloudException(CTCloudException.ErrorCode.NETWORK_ERROR, ex); } catch (URISyntaxException ex) { LOGGER.log(Level.WARNING, "Wrong URL syntax for CT Cloud " + url, ex); throw new CTCloudException(CTCloudException.ErrorCode.UNKNOWN, ex); @@ -196,16 +213,16 @@ class CTCloudHttpClient { return null; } - + public void doFileUploadPost(String urlPath, String fileName, InputStream fileIs) throws CTCloudException { - + try (CloseableHttpClient httpclient = createConnection(getProxySettings(), sslContext)) { LOGGER.log(Level.INFO, "initiating http post request to ctcloud server " + urlPath); HttpPost post = new HttpPost(urlPath); configureRequestTimeout(post); - + post.addHeader("Connection", "keep-alive"); - + MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.addBinaryBody( "file", @@ -213,10 +230,10 @@ class CTCloudHttpClient { ContentType.APPLICATION_OCTET_STREAM, fileName ); - + HttpEntity multipart = builder.build(); post.setEntity(multipart); - + try (CloseableHttpResponse response = httpclient.execute(post)) { int statusCode = response.getStatusLine().getStatusCode(); if (statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_NO_CONTENT) { @@ -226,6 +243,9 @@ class CTCloudHttpClient { handleNonOKResponse(response, fileName); } } + } catch (SSLInitializationException ex) { + LOGGER.log(Level.WARNING, "SSL exception raised when connecting to Reversing Labs for file content upload ", ex); + throw new CTCloudException(CTCloudException.ErrorCode.NETWORK_ERROR, ex); } catch (IOException ex) { LOGGER.log(Level.WARNING, "IO Exception raised when connecting to Reversing Labs for file content upload ", ex); throw new CTCloudException(CTCloudException.ErrorCode.NETWORK_ERROR, ex); @@ -295,19 +315,71 @@ class CTCloudHttpClient { /** * Creates a connection to CT Cloud with the given arguments. + * * @param proxySettings The network proxy settings. * @param sslContext The ssl context or null. * @return The connection to CT Cloud. */ - private static CloseableHttpClient createConnection(ProxySettingArgs proxySettings, SSLContext sslContext) { + private static CloseableHttpClient createConnection(ProxySettingArgs proxySettings, SSLContext sslContext) throws SSLInitializationException { HttpClientBuilder builder = getHttpClientBuilder(proxySettings); - if (sslContext != null) { builder.setSSLContext(sslContext); } + return builder.build(); } + /** + * Create an SSLContext object using our in-memory keystore. + * + * @return + */ + private static SSLContext createSSLContext() { + LOGGER.log(Level.INFO, "Creating custom SSL context"); + try { + + // I'm not sure how much of this is really necessary to set up, but it works + SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); + KeyManager[] keyManagers = getKeyManagers(); + TrustManager[] trustManagers = getTrustManagers(); + sslContext.init(keyManagers, trustManagers, new SecureRandom()); + return sslContext; + } catch (NoSuchAlgorithmException | KeyManagementException ex) { + LOGGER.log(Level.SEVERE, "Error creating SSL context", ex); + return null; + } + } + + // based in part on this: https://stackoverflow.com/questions/1793979/registering-multiple-keystores-in-jvm/16229909 + private static KeyManager[] getKeyManagers() { + LOGGER.log(Level.INFO, "Using default algorithm to create trust store: " + KeyManagerFactory.getDefaultAlgorithm()); + try { + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(null, null); + return kmf.getKeyManagers(); + } catch (NoSuchAlgorithmException | KeyStoreException | UnrecoverableKeyException ex) { + LOGGER.log(Level.SEVERE, "Error getting KeyManagers", ex); + return new KeyManager[0]; + } + + } + + // based in part on this: https://stackoverflow.com/questions/1793979/registering-multiple-keystores-in-jvm/16229909 + private static TrustManager[] getTrustManagers() { + try { + LOGGER.log(Level.INFO, "Using default algorithm to create trust store: " + TrustManagerFactory.getDefaultAlgorithm()); + TrustManagerFactory tmf + = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init((KeyStore) null); + X509TrustManager tm = (X509TrustManager) tmf.getTrustManagers()[0]; + + return new TrustManager[]{tm}; + } catch (KeyStoreException | NoSuchAlgorithmException ex) { + LOGGER.log(Level.SEVERE, "Error getting TrustManager", ex); + return new TrustManager[0]; + } + } + private static HttpClientBuilder getHttpClientBuilder(ProxySettingArgs proxySettings) { if (proxySettings.isSystemOrManualProxy()) { From 8ed27b935d8be9d0285b394833dfae00291b5ebd Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Fri, 4 Aug 2023 14:35:30 -0400 Subject: [PATCH 37/94] updates for proxy configuration --- .../autopsy/ctapi/CTCloudHttpClient.java | 85 ++-- .../autopsy/ctapi/ProxySettings.java | 446 ------------------ .../ctcloud/CTMalwareScannerOptionsPanel.java | 5 +- 3 files changed, 59 insertions(+), 477 deletions(-) delete mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/ctapi/ProxySettings.java diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java index 622595083e..003a9e4347 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java @@ -74,6 +74,8 @@ import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.client.SystemDefaultCredentialsProvider; import org.apache.http.impl.client.WinHttpClients; import org.apache.http.ssl.SSLInitializationException; +import org.netbeans.core.ProxySettings; +import org.openide.util.NetworkSettings; import org.sleuthkit.autopsy.coreutils.Version; /** @@ -81,8 +83,6 @@ import org.sleuthkit.autopsy.coreutils.Version; */ class CTCloudHttpClient { - private static final String KS_PASSWORD = "changeit"; // system default java password - private static final Logger LOGGER = Logger.getLogger(CTCloudHttpClient.class.getName()); private static final String HOST_URL = Version.getBuildType() == Version.Type.RELEASE ? Constants.CT_CLOUD_SERVER : Constants.CT_CLOUD_DEV_SERVER; @@ -112,7 +112,7 @@ class CTCloudHttpClient { this.sslContext = createSSLContext(); } - private ProxySettingArgs getProxySettings() { + private ProxySettingArgs getProxySettings(URI uri) { if (StringUtils.isBlank(hostName)) { try { hostName = InetAddress.getLocalHost().getCanonicalHostName(); @@ -121,24 +121,49 @@ class CTCloudHttpClient { } } + String proxyPortStr = uri != null ? NetworkSettings.getProxyPort(uri) : ProxySettings.getHttpPort(); int proxyPort = 0; - if (StringUtils.isNotBlank(ProxySettings.getHttpPort())) { + if (StringUtils.isNotBlank(proxyPortStr)) { try { - proxyPort = Integer.parseInt(ProxySettings.getHttpsPort()); + proxyPort = Integer.parseInt(proxyPortStr); } catch (NumberFormatException ex) { LOGGER.log(Level.WARNING, "Unable to convert port to integer"); } } - return new ProxySettingArgs( + String proxyHost = uri != null ? NetworkSettings.getProxyHost(uri) : ProxySettings.getHttpHost(); + + ProxySettingArgs proxySettings = new ProxySettingArgs( ProxySettings.getProxyType() != ProxySettings.DIRECT_CONNECTION, hostName, - ProxySettings.getHttpsHost(), + proxyHost, proxyPort, ProxySettings.getAuthenticationUsername(), ProxySettings.getAuthenticationPassword(), null ); + + // TODO comment out later + LOGGER.log(Level.INFO, MessageFormat.format("Proxy settings to be used with {0} are {1}.", uri, proxySettings)); + + return proxySettings; + } + + private static URI getUri(String host, String path, Map urlReqParams) throws URISyntaxException { + String url = host + path; + URIBuilder builder = new URIBuilder(url); + + if (!MapUtils.isEmpty(urlReqParams)) { + for (Entry e : urlReqParams.entrySet()) { + String key = e.getKey(); + String value = e.getValue(); + if (StringUtils.isNotBlank(key) || StringUtils.isNotBlank(value)) { + builder.addParameter(key, value); + } + } + } + + return builder.build(); } public O doPost(String urlPath, Object jsonBody, Class classType) throws CTCloudException { @@ -146,24 +171,13 @@ class CTCloudHttpClient { } public O doPost(String urlPath, Map urlReqParams, Object jsonBody, Class classType) throws CTCloudException { - String url = HOST_URL + urlPath; + + URI postURI = null; try { - + postURI = getUri(HOST_URL, urlPath, urlReqParams); LOGGER.log(Level.INFO, "initiating http connection to ctcloud server"); - try (CloseableHttpClient httpclient = createConnection(getProxySettings(), sslContext)) { - URIBuilder builder = new URIBuilder(url); + try (CloseableHttpClient httpclient = createConnection(getProxySettings(postURI), sslContext)) { - if (!MapUtils.isEmpty(urlReqParams)) { - for (Entry e : urlReqParams.entrySet()) { - String key = e.getKey(); - String value = e.getValue(); - if (StringUtils.isNotBlank(key) || StringUtils.isNotBlank(value)) { - builder.addParameter(key, value); - } - } - } - - URI postURI = builder.build(); HttpPost postRequest = new HttpPost(postURI); configureRequestTimeout(postRequest); @@ -201,24 +215,31 @@ class CTCloudHttpClient { } } } catch (IOException ex) { - LOGGER.log(Level.WARNING, "IO Exception raised when connecting to CT Cloud using " + url, ex); + LOGGER.log(Level.WARNING, "IO Exception raised when connecting to CT Cloud using " + postURI, ex); throw new CTCloudException(CTCloudException.ErrorCode.NETWORK_ERROR, ex); } catch (SSLInitializationException ex) { - LOGGER.log(Level.WARNING, "No such algorithm exception raised when creating SSL connection for CT Cloud using " + url, ex); + LOGGER.log(Level.WARNING, "No such algorithm exception raised when creating SSL connection for CT Cloud using " + postURI, ex); throw new CTCloudException(CTCloudException.ErrorCode.NETWORK_ERROR, ex); } catch (URISyntaxException ex) { - LOGGER.log(Level.WARNING, "Wrong URL syntax for CT Cloud " + url, ex); + LOGGER.log(Level.WARNING, "Wrong URL syntax for CT Cloud " + postURI, ex); throw new CTCloudException(CTCloudException.ErrorCode.UNKNOWN, ex); } return null; } - public void doFileUploadPost(String urlPath, String fileName, InputStream fileIs) throws CTCloudException { + public void doFileUploadPost(String fullUrlPath, String fileName, InputStream fileIs) throws CTCloudException { + URI postUri; + try { + postUri = new URI(fullUrlPath); + } catch (URISyntaxException ex) { + LOGGER.log(Level.WARNING, "Wrong URL syntax for CT Cloud " + fullUrlPath, ex); + throw new CTCloudException(CTCloudException.ErrorCode.UNKNOWN, ex); + } - try (CloseableHttpClient httpclient = createConnection(getProxySettings(), sslContext)) { - LOGGER.log(Level.INFO, "initiating http post request to ctcloud server " + urlPath); - HttpPost post = new HttpPost(urlPath); + try (CloseableHttpClient httpclient = createConnection(getProxySettings(postUri), sslContext)) { + LOGGER.log(Level.INFO, "initiating http post request to ctcloud server " + fullUrlPath); + HttpPost post = new HttpPost(postUri); configureRequestTimeout(post); post.addHeader("Connection", "keep-alive"); @@ -508,5 +529,11 @@ class CTCloudHttpClient { public String getAuthScheme() { return authScheme; } + + @Override + public String toString() { + return "ProxySettingArgs{" + "systemOrManualProxy=" + systemOrManualProxy + ", hostName=" + hostName + ", proxyHostname=" + proxyHostname + ", proxyPort=" + proxyPort + ", proxyUserId=" + proxyUserId + ", proxyPassword set=" + (proxyPassword != null && proxyPassword.length > 0) + ", authScheme=" + authScheme + '}'; + } + } } diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/ProxySettings.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/ProxySettings.java deleted file mode 100644 index cbd538d01b..0000000000 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/ProxySettings.java +++ /dev/null @@ -1,446 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2023 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.basistech.df.cybertriage.autopsy.ctapi; - -import java.net.*; -import java.util.*; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.prefs.PreferenceChangeListener; -import java.util.prefs.Preferences; -import org.netbeans.api.keyring.Keyring; -import org.openide.util.*; -import org.openide.util.lookup.ServiceProvider; - -/** - * Taken from https://raw.githubusercontent.com/apache/netbeans/master/platform/o.n.core/src/org/netbeans/core/ProxySettings.java - * @author Jiri Rechtacek - */ -class ProxySettings { - - public static final String PROXY_HTTP_HOST = "proxyHttpHost"; // NOI18N - public static final String PROXY_HTTP_PORT = "proxyHttpPort"; // NOI18N - public static final String PROXY_HTTPS_HOST = "proxyHttpsHost"; // NOI18N - public static final String PROXY_HTTPS_PORT = "proxyHttpsPort"; // NOI18N - public static final String PROXY_SOCKS_HOST = "proxySocksHost"; // NOI18N - public static final String PROXY_SOCKS_PORT = "proxySocksPort"; // NOI18N - public static final String NOT_PROXY_HOSTS = "proxyNonProxyHosts"; // NOI18N - public static final String PROXY_TYPE = "proxyType"; // NOI18N - public static final String USE_PROXY_AUTHENTICATION = "useProxyAuthentication"; // NOI18N - public static final String PROXY_AUTHENTICATION_USERNAME = "proxyAuthenticationUsername"; // NOI18N - public static final String PROXY_AUTHENTICATION_PASSWORD = "proxyAuthenticationPassword"; // NOI18N - public static final String USE_PROXY_ALL_PROTOCOLS = "useProxyAllProtocols"; // NOI18N - public static final String DIRECT = "DIRECT"; // NOI18N - public static final String PAC = "PAC"; // NOI18N - - public static final String SYSTEM_PROXY_HTTP_HOST = "systemProxyHttpHost"; // NOI18N - public static final String SYSTEM_PROXY_HTTP_PORT = "systemProxyHttpPort"; // NOI18N - public static final String SYSTEM_PROXY_HTTPS_HOST = "systemProxyHttpsHost"; // NOI18N - public static final String SYSTEM_PROXY_HTTPS_PORT = "systemProxyHttpsPort"; // NOI18N - public static final String SYSTEM_PROXY_SOCKS_HOST = "systemProxySocksHost"; // NOI18N - public static final String SYSTEM_PROXY_SOCKS_PORT = "systemProxySocksPort"; // NOI18N - public static final String SYSTEM_NON_PROXY_HOSTS = "systemProxyNonProxyHosts"; // NOI18N - public static final String SYSTEM_PAC = "systemPAC"; // NOI18N - - // Only for testing purpose (Test connection in General options panel) - public static final String TEST_SYSTEM_PROXY_HTTP_HOST = "testSystemProxyHttpHost"; // NOI18N - public static final String TEST_SYSTEM_PROXY_HTTP_PORT = "testSystemProxyHttpPort"; // NOI18N - public static final String HTTP_CONNECTION_TEST_URL = "https://netbeans.apache.org";// NOI18N - - private static String presetNonProxyHosts; - - /** No proxy is used to connect. */ - public static final int DIRECT_CONNECTION = 0; - - /** Proxy setting is automatically detect in OS. */ - public static final int AUTO_DETECT_PROXY = 1; // as default - - /** Manually set proxy host and port. */ - public static final int MANUAL_SET_PROXY = 2; - - /** Proxy PAC file automatically detect in OS. */ - public static final int AUTO_DETECT_PAC = 3; - - /** Proxy PAC file manually set. */ - public static final int MANUAL_SET_PAC = 4; - - private static final Logger LOGGER = Logger.getLogger(ProxySettings.class.getName()); - - private static Preferences getPreferences() { - return NbPreferences.forModule (ProxySettings.class); - } - - - public static String getHttpHost () { - return normalizeProxyHost (getPreferences ().get (PROXY_HTTP_HOST, "")); - } - - public static String getHttpPort () { - return getPreferences ().get (PROXY_HTTP_PORT, ""); - } - - public static String getHttpsHost () { - if (useProxyAllProtocols ()) { - return getHttpHost (); - } else { - return getPreferences ().get (PROXY_HTTPS_HOST, ""); - } - } - - public static String getHttpsPort () { - if (useProxyAllProtocols ()) { - return getHttpPort (); - } else { - return getPreferences ().get (PROXY_HTTPS_PORT, ""); - } - } - - public static String getSocksHost () { - if (useProxyAllProtocols ()) { - return getHttpHost (); - } else { - return getPreferences ().get (PROXY_SOCKS_HOST, ""); - } - } - - public static String getSocksPort () { - if (useProxyAllProtocols ()) { - return getHttpPort (); - } else { - return getPreferences ().get (PROXY_SOCKS_PORT, ""); - } - } - - public static String getNonProxyHosts () { - String hosts = getPreferences ().get (NOT_PROXY_HOSTS, getDefaultUserNonProxyHosts ()); - return compactNonProxyHosts(hosts); - } - - public static int getProxyType () { - int type = getPreferences ().getInt (PROXY_TYPE, AUTO_DETECT_PROXY); - if (AUTO_DETECT_PROXY == type) { - type = ProxySettings.getSystemPac() != null ? AUTO_DETECT_PAC : AUTO_DETECT_PROXY; - } - return type; - } - - - public static String getSystemHttpHost() { - return getPreferences().get(SYSTEM_PROXY_HTTP_HOST, ""); - } - - public static String getSystemHttpPort() { - return getPreferences().get(SYSTEM_PROXY_HTTP_PORT, ""); - } - - public static String getSystemHttpsHost() { - return getPreferences().get(SYSTEM_PROXY_HTTPS_HOST, ""); - } - - public static String getSystemHttpsPort() { - return getPreferences().get(SYSTEM_PROXY_HTTPS_PORT, ""); - } - - public static String getSystemSocksHost() { - return getPreferences().get(SYSTEM_PROXY_SOCKS_HOST, ""); - } - - public static String getSystemSocksPort() { - return getPreferences().get(SYSTEM_PROXY_SOCKS_PORT, ""); - } - - public static String getSystemNonProxyHosts() { - return getPreferences().get(SYSTEM_NON_PROXY_HOSTS, getModifiedNonProxyHosts("")); - } - - public static String getSystemPac() { - return getPreferences().get(SYSTEM_PAC, null); - } - - - public static String getTestSystemHttpHost() { - return getPreferences().get(TEST_SYSTEM_PROXY_HTTP_HOST, ""); - } - - public static String getTestSystemHttpPort() { - return getPreferences().get(TEST_SYSTEM_PROXY_HTTP_PORT, ""); - } - - - public static boolean useAuthentication () { - return getPreferences ().getBoolean (USE_PROXY_AUTHENTICATION, false); - } - - public static boolean useProxyAllProtocols () { - return getPreferences ().getBoolean (USE_PROXY_ALL_PROTOCOLS, false); - } - - public static String getAuthenticationUsername () { - return getPreferences ().get (PROXY_AUTHENTICATION_USERNAME, ""); - } - - public static char[] getAuthenticationPassword () { - String old = getPreferences().get(PROXY_AUTHENTICATION_PASSWORD, null); - if (old != null) { - getPreferences().remove(PROXY_AUTHENTICATION_PASSWORD); - setAuthenticationPassword(old.toCharArray()); - } - char[] pwd = Keyring.read(PROXY_AUTHENTICATION_PASSWORD); - return pwd != null ? pwd : new char[0]; - } - - public static void setAuthenticationPassword(char[] password) { - Keyring.save(ProxySettings.PROXY_AUTHENTICATION_PASSWORD, password, - // XXX consider including getHttpHost and/or getHttpsHost - NbBundle.getMessage(ProxySettings.class, "ProxySettings.password.description")); // NOI18N - } - - public static void addPreferenceChangeListener (PreferenceChangeListener l) { - getPreferences ().addPreferenceChangeListener (l); - } - - public static void removePreferenceChangeListener (PreferenceChangeListener l) { - getPreferences ().removePreferenceChangeListener (l); - } - - private static String getPresetNonProxyHosts () { - if (presetNonProxyHosts == null) { - presetNonProxyHosts = System.getProperty ("http.nonProxyHosts", ""); // NOI18N - } - return presetNonProxyHosts; - } - - private static String getDefaultUserNonProxyHosts () { - return getModifiedNonProxyHosts (getSystemNonProxyHosts ()); - } - - - private static String concatProxies(String... proxies) { - StringBuilder sb = new StringBuilder(); - for (String n : proxies) { - if (n == null) { - continue; - } - n = n.trim(); - if (n.isEmpty()) { - continue; - } - if (sb.length() > 0 && sb.charAt(sb.length() - 1) != '|') { // NOI18N - if (!n.startsWith("|")) { // NOI18N - sb.append('|'); // NOI18N - } - } - sb.append(n); - } - return sb.toString(); - } - - private static String getModifiedNonProxyHosts (String systemPreset) { - String fromSystem = systemPreset.replace (";", "|").replace (",", "|"); //NOI18N - String fromUser = getPresetNonProxyHosts () == null ? "" : getPresetNonProxyHosts ().replace (";", "|").replace (",", "|"); //NOI18N - if (Utilities.isWindows ()) { - fromSystem = addReguralToNonProxyHosts (fromSystem); - } - final String staticNonProxyHosts = NbBundle.getMessage(ProxySettings.class, "StaticNonProxyHosts"); // NOI18N - String nonProxy = concatProxies(fromUser, fromSystem, staticNonProxyHosts); // NOI18N - String localhost; - try { - localhost = InetAddress.getLocalHost().getHostName(); - if (!"localhost".equals(localhost)) { // NOI18N - nonProxy = nonProxy + "|" + localhost; // NOI18N - } else { - // Avoid this error when hostname == localhost: - // Error in http.nonProxyHosts system property: sun.misc.REException: localhost is a duplicate - } - } - catch (UnknownHostException e) { - // OK. Sometimes a hostname is assigned by DNS, but a computer - // is later pulled off the network. It may then produce a bogus - // name for itself which can't actually be resolved. Normally - // "localhost" is aliased to 127.0.0.1 anyway. - } - /* per Milan's agreement it's removed. See issue #89868 - try { - String localhost2 = InetAddress.getLocalHost().getCanonicalHostName(); - if (!"localhost".equals(localhost2) && !localhost2.equals(localhost)) { // NOI18N - nonProxy = nonProxy + "|" + localhost2; // NOI18N - } else { - // Avoid this error when hostname == localhost: - // Error in http.nonProxyHosts system property: sun.misc.REException: localhost is a duplicate - } - } - catch (UnknownHostException e) { - // OK. Sometimes a hostname is assigned by DNS, but a computer - // is later pulled off the network. It may then produce a bogus - // name for itself which can't actually be resolved. Normally - // "localhost" is aliased to 127.0.0.1 anyway. - } - */ - return compactNonProxyHosts (nonProxy); - } - - - // avoid duplicate hosts - private static String compactNonProxyHosts (String hosts) { - StringTokenizer st = new StringTokenizer(hosts, ","); //NOI18N - StringBuilder nonProxyHosts = new StringBuilder(); - while (st.hasMoreTokens()) { - String h = st.nextToken().trim(); - if (h.length() == 0) { - continue; - } - if (nonProxyHosts.length() > 0) { - nonProxyHosts.append("|"); // NOI18N - } - nonProxyHosts.append(h); - } - st = new StringTokenizer (nonProxyHosts.toString(), "|"); //NOI18N - Set set = new HashSet (); - StringBuilder compactedProxyHosts = new StringBuilder(); - while (st.hasMoreTokens ()) { - String t = st.nextToken (); - if (set.add (t.toLowerCase (Locale.US))) { - if (compactedProxyHosts.length() > 0) { - compactedProxyHosts.append('|'); // NOI18N - } - compactedProxyHosts.append(t); - } - } - return compactedProxyHosts.toString(); - } - - private static String addReguralToNonProxyHosts (String nonProxyHost) { - StringTokenizer st = new StringTokenizer (nonProxyHost, "|"); // NOI18N - StringBuilder reguralProxyHosts = new StringBuilder(); - while (st.hasMoreTokens ()) { - String t = st.nextToken (); - if (t.indexOf ('*') == -1) { //NOI18N - t = t + '*'; //NOI18N - } - if (reguralProxyHosts.length() > 0) - reguralProxyHosts.append('|'); // NOI18N - reguralProxyHosts.append(t); - } - - return reguralProxyHosts.toString(); - } - - public static String normalizeProxyHost (String proxyHost) { - if (proxyHost.toLowerCase (Locale.US).startsWith ("http://")) { // NOI18N - return proxyHost.substring (7, proxyHost.length ()); - } else { - return proxyHost; - } - } - - private static InetSocketAddress analyzeProxy(URI uri) { - Parameters.notNull("uri", uri); // NOI18N - List proxies = ProxySelector.getDefault().select(uri); - assert proxies != null : "ProxySelector cannot return null for " + uri; // NOI18N - assert !proxies.isEmpty() : "ProxySelector cannot return empty list for " + uri; // NOI18N - String protocol = uri.getScheme(); - Proxy p = proxies.get(0); - if (Proxy.Type.DIRECT == p.type()) { - // return null for DIRECT proxy - return null; - } - if (protocol == null - || ((protocol.startsWith("http") || protocol.equals("ftp")) && Proxy.Type.HTTP == p.type()) // NOI18N - || !(protocol.startsWith("http") || protocol.equals("ftp"))) { // NOI18N - if (p.address() instanceof InetSocketAddress) { - // check is - //assert ! ((InetSocketAddress) p.address()).isUnresolved() : p.address() + " must be resolved address."; - return (InetSocketAddress) p.address(); - } else { - LOGGER.log(Level.INFO, p.address() + " is not instanceof InetSocketAddress but " + p.address().getClass()); // NOI18N - return null; - } - } else { - return null; - } - } - - public static void reload() { - Reloader reloader = Lookup.getDefault().lookup(Reloader.class); - reloader.reload(); - } - - @ServiceProvider(service = NetworkSettings.ProxyCredentialsProvider.class, position = 1000) - public static class NbProxyCredentialsProvider extends NetworkSettings.ProxyCredentialsProvider { - - @Override - public String getProxyHost(URI u) { - if (getPreferences() == null) { - return null; - } - InetSocketAddress sa = analyzeProxy(u); - return sa == null ? null : sa.getHostName(); - } - - @Override - public String getProxyPort(URI u) { - if (getPreferences() == null) { - return null; - } - InetSocketAddress sa = analyzeProxy(u); - return sa == null ? null : Integer.toString(sa.getPort()); - } - - @Override - protected String getProxyUserName(URI u) { - if (getPreferences() == null) { - return null; - } - return ProxySettings.getAuthenticationUsername(); - } - - @Override - protected char[] getProxyPassword(URI u) { - if (getPreferences() == null) { - return null; - } - return ProxySettings.getAuthenticationPassword(); - } - - @Override - protected boolean isProxyAuthentication(URI u) { - if (getPreferences() == null) { - return false; - } - return getPreferences().getBoolean(USE_PROXY_AUTHENTICATION, false); - } - - } - - /** A bridge between o.n.core and core.network. - * An implementation of this class brings a facility to reload Network Proxy Settings - * from underlying OS. - * The module core.network provides a implementation which may be accessible - * via Lookup.getDefault(). It's not guaranteed any implementation is found on all distribution. - * - * @since 3.40 - */ - public abstract static class Reloader { - - /** Reloads Network Proxy Settings from underlying system. - * - */ - public abstract void reload(); - } -} diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java index 5dd3a1db66..99d3ea2710 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java @@ -33,6 +33,7 @@ import java.io.IOException; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.Optional; +import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.logging.Level; import java.util.logging.Logger; @@ -552,7 +553,7 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { try { LicenseResponse licenseResponse = get(); SwingUtilities.invokeLater(() -> acceptEula(licenseResponse)); - } catch (InterruptedException ex) { + } catch (InterruptedException | CancellationException ex) { // ignore cancellation; just load current license setLicenseDisplay(licenseInfo, null); loadMalwareScansInfo(licenseInfo); @@ -608,7 +609,7 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { AuthTokenResponse authTokenResponse = null; try { authTokenResponse = get(); - } catch (InterruptedException ex) { + } catch (InterruptedException | CancellationException ex) { // ignore cancellation } catch (ExecutionException ex) { if (ex.getCause() != null && ex.getCause() instanceof CTCloudException cloudEx) { From 5f35af2247411aa27338a15cdd6c49bcd52a906d Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Fri, 4 Aug 2023 20:54:24 -0400 Subject: [PATCH 38/94] use Nb classes for auth and proxy selection --- .../autopsy/ctapi/CTCloudHttpClient.java | 281 ++++++------------ 1 file changed, 86 insertions(+), 195 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java index 003a9e4347..039d1d9e83 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java @@ -22,12 +22,11 @@ import com.basistech.df.cybertriage.autopsy.ctapi.util.ObjectMapperUtil; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.io.InputStream; -import java.net.Authenticator; -import java.net.InetAddress; -import java.net.PasswordAuthentication; +import java.net.Proxy; +import java.net.ProxySelector; +import java.net.SocketAddress; import java.net.URI; import java.net.URISyntaxException; -import java.net.UnknownHostException; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; @@ -35,14 +34,13 @@ import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.UnrecoverableKeyException; import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Objects; import java.util.logging.Level; +import java.util.stream.Stream; import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; @@ -50,14 +48,10 @@ import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpEntity; -import org.apache.http.HttpHost; import org.apache.http.HttpStatus; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.NTCredentials; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.client.config.AuthSchemes; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; @@ -71,29 +65,27 @@ import org.apache.http.entity.mime.MultipartEntityBuilder; import org.sleuthkit.autopsy.coreutils.Logger; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; -import org.apache.http.impl.client.SystemDefaultCredentialsProvider; import org.apache.http.impl.client.WinHttpClients; +import org.apache.http.impl.conn.SystemDefaultRoutePlanner; import org.apache.http.ssl.SSLInitializationException; import org.netbeans.core.ProxySettings; -import org.openide.util.NetworkSettings; +import org.openide.util.Lookup; import org.sleuthkit.autopsy.coreutils.Version; /** * Makes the http requests to CT cloud. + * + * NOTE: regarding proxy settings, the host and port are handled by the + * NbProxySelector. Any proxy authentication is handled by NbAuthenticator which + * is installed at startup (i.e. NbAuthenticator.install). See + * GeneralOptionsModel.testHttpConnection to see how the general options panel + * tests the connection. */ class CTCloudHttpClient { private static final Logger LOGGER = Logger.getLogger(CTCloudHttpClient.class.getName()); private static final String HOST_URL = Version.getBuildType() == Version.Type.RELEASE ? Constants.CT_CLOUD_SERVER : Constants.CT_CLOUD_DEV_SERVER; - - private static final List DEFAULT_SCHEME_PRIORITY - = new ArrayList<>(Arrays.asList( - AuthSchemes.SPNEGO, - AuthSchemes.KERBEROS, - AuthSchemes.NTLM, - AuthSchemes.CREDSSP, - AuthSchemes.DIGEST, - AuthSchemes.BASIC)); + private static final String NB_PROXY_SELECTOR_NAME = "org.netbeans.core.NbProxySelector"; private static final int CONNECTION_TIMEOUT_MS = 58 * 1000; // milli sec @@ -105,48 +97,12 @@ class CTCloudHttpClient { private final ObjectMapper mapper = ObjectMapperUtil.getInstance().getDefaultObjectMapper(); private final SSLContext sslContext; - private String hostName = null; + private final ProxySelector proxySelector; private CTCloudHttpClient() { // leave as null for now unless we want to customize this at a later date this.sslContext = createSSLContext(); - } - - private ProxySettingArgs getProxySettings(URI uri) { - if (StringUtils.isBlank(hostName)) { - try { - hostName = InetAddress.getLocalHost().getCanonicalHostName(); - } catch (UnknownHostException ex) { - LOGGER.log(Level.WARNING, "An error occurred while fetching the hostname", ex); - } - } - - String proxyPortStr = uri != null ? NetworkSettings.getProxyPort(uri) : ProxySettings.getHttpPort(); - int proxyPort = 0; - if (StringUtils.isNotBlank(proxyPortStr)) { - try { - proxyPort = Integer.parseInt(proxyPortStr); - } catch (NumberFormatException ex) { - LOGGER.log(Level.WARNING, "Unable to convert port to integer"); - } - } - - String proxyHost = uri != null ? NetworkSettings.getProxyHost(uri) : ProxySettings.getHttpHost(); - - ProxySettingArgs proxySettings = new ProxySettingArgs( - ProxySettings.getProxyType() != ProxySettings.DIRECT_CONNECTION, - hostName, - proxyHost, - proxyPort, - ProxySettings.getAuthenticationUsername(), - ProxySettings.getAuthenticationPassword(), - null - ); - - // TODO comment out later - LOGGER.log(Level.INFO, MessageFormat.format("Proxy settings to be used with {0} are {1}.", uri, proxySettings)); - - return proxySettings; + this.proxySelector = getProxySelector(); } private static URI getUri(String host, String path, Map urlReqParams) throws URISyntaxException { @@ -171,12 +127,12 @@ class CTCloudHttpClient { } public O doPost(String urlPath, Map urlReqParams, Object jsonBody, Class classType) throws CTCloudException { - + URI postURI = null; try { postURI = getUri(HOST_URL, urlPath, urlReqParams); LOGGER.log(Level.INFO, "initiating http connection to ctcloud server"); - try (CloseableHttpClient httpclient = createConnection(getProxySettings(postURI), sslContext)) { + try (CloseableHttpClient httpclient = createConnection(proxySelector, sslContext)) { HttpPost postRequest = new HttpPost(postURI); @@ -237,7 +193,7 @@ class CTCloudHttpClient { throw new CTCloudException(CTCloudException.ErrorCode.UNKNOWN, ex); } - try (CloseableHttpClient httpclient = createConnection(getProxySettings(postUri), sslContext)) { + try (CloseableHttpClient httpclient = createConnection(proxySelector, sslContext)) { LOGGER.log(Level.INFO, "initiating http post request to ctcloud server " + fullUrlPath); HttpPost post = new HttpPost(postUri); configureRequestTimeout(post); @@ -335,19 +291,30 @@ class CTCloudHttpClient { } /** - * Creates a connection to CT Cloud with the given arguments. + * Get ProxySelector present (favoring NbProxySelector if present). * - * @param proxySettings The network proxy settings. - * @param sslContext The ssl context or null. - * @return The connection to CT Cloud. + * @return The found ProxySelector or null. */ - private static CloseableHttpClient createConnection(ProxySettingArgs proxySettings, SSLContext sslContext) throws SSLInitializationException { - HttpClientBuilder builder = getHttpClientBuilder(proxySettings); - if (sslContext != null) { - builder.setSSLContext(sslContext); - } - - return builder.build(); + private static ProxySelector getProxySelector() { + Collection selectors = Lookup.getDefault().lookupAll(ProxySelector.class); + return (selectors != null ? selectors.stream() : Stream.empty()) + .filter(s -> s != null) + .map(s -> (ProxySelector) s) + .sorted((a, b) -> { + String aName = a.getClass().getCanonicalName(); + String bName = b.getClass().getCanonicalName(); + boolean aIsNb = aName.equalsIgnoreCase(NB_PROXY_SELECTOR_NAME); + boolean bIsNb = bName.equalsIgnoreCase(NB_PROXY_SELECTOR_NAME); + if (aIsNb == bIsNb) { + return StringUtils.compareIgnoreCase(aName, bName); + } else { + return aIsNb ? -1 : 1; + } + }) + .findFirst() + // TODO take this out to remove proxy selector logging + .map(s -> new LoggingProxySelector(s)) + .orElse(null); } /** @@ -371,6 +338,7 @@ class CTCloudHttpClient { } } + // jvm default key manager // based in part on this: https://stackoverflow.com/questions/1793979/registering-multiple-keystores-in-jvm/16229909 private static KeyManager[] getKeyManagers() { LOGGER.log(Level.INFO, "Using default algorithm to create trust store: " + KeyManagerFactory.getDefaultAlgorithm()); @@ -385,6 +353,7 @@ class CTCloudHttpClient { } + // jvm default trust store // based in part on this: https://stackoverflow.com/questions/1793979/registering-multiple-keystores-in-jvm/16229909 private static TrustManager[] getTrustManagers() { try { @@ -401,138 +370,60 @@ class CTCloudHttpClient { } } - private static HttpClientBuilder getHttpClientBuilder(ProxySettingArgs proxySettings) { - - if (proxySettings.isSystemOrManualProxy()) { - - Authenticator.setDefault(new Authenticator() { - @Override - protected PasswordAuthentication getPasswordAuthentication() { - LOGGER.info("Requesting Password Authentication..."); - return super.getPasswordAuthentication(); - } - }); - - HttpClientBuilder builder = null; - HttpHost proxyHost = null; - CredentialsProvider proxyCredsProvider = null; - RequestConfig config = null; - - if (Objects.nonNull(proxySettings.getProxyHostname()) && proxySettings.getProxyPort() > 0) { - proxyHost = new HttpHost(proxySettings.getProxyHostname(), proxySettings.getProxyPort()); - - proxyCredsProvider = getProxyCredentialsProvider(proxySettings); - if (StringUtils.isNotBlank(proxySettings.getAuthScheme())) { - if (!DEFAULT_SCHEME_PRIORITY.get(0).equalsIgnoreCase(proxySettings.getAuthScheme())) { - DEFAULT_SCHEME_PRIORITY.removeIf(s -> s.equalsIgnoreCase(proxySettings.getAuthScheme())); - DEFAULT_SCHEME_PRIORITY.add(0, proxySettings.getAuthScheme()); - } - } - config = RequestConfig.custom().setProxyPreferredAuthSchemes(DEFAULT_SCHEME_PRIORITY).build(); - } - - if (Objects.isNull(proxyCredsProvider) && WinHttpClients.isWinAuthAvailable()) { - builder = WinHttpClients.custom(); - builder.useSystemProperties(); - LOGGER.log(Level.WARNING, "Using Win HTTP Client"); - } else { - builder = HttpClients.custom(); - builder.setDefaultRequestConfig(config); - if (Objects.nonNull(proxyCredsProvider)) { // make sure non null proxycreds before setting it - builder.setDefaultCredentialsProvider(proxyCredsProvider); - } - LOGGER.log(Level.WARNING, "Using default http client"); - } - if (Objects.nonNull(proxyHost)) { - builder.setProxy(proxyHost); - LOGGER.log(Level.WARNING, MessageFormat.format("Using proxy {0}", proxyHost)); - } - - return builder; - } else { - return HttpClients.custom(); - } - } - /** - * Returns a CredentialsProvider for proxy, if one is configured. + * Creates a connection to CT Cloud with the given arguments. * - * @return CredentialsProvider, if a proxy is configured with credentials, - * null otherwise + * @param proxySelector The proxy selector. + * @param sslContext The ssl context or null. + * @return The connection to CT Cloud. */ - private static CredentialsProvider getProxyCredentialsProvider(ProxySettingArgs proxySettings) { - CredentialsProvider proxyCredsProvider = null; - if (proxySettings.isSystemOrManualProxy()) { - if (StringUtils.isNotBlank(proxySettings.getProxyUserId())) { - if (null != proxySettings.getProxyPassword() && proxySettings.getProxyPassword().length > 0) { // Password will be blank for KERBEROS / NEGOTIATE schemes. - proxyCredsProvider = new SystemDefaultCredentialsProvider(); - String userId = proxySettings.getProxyUserId(); - String domain = null; - if (userId.contains("\\")) { - domain = userId.split("\\\\")[0]; - userId = userId.split("\\\\")[1]; - } - String workStation = proxySettings.getHostName(); - proxyCredsProvider.setCredentials(new AuthScope(proxySettings.getProxyHostname(), proxySettings.getProxyPort()), - new NTCredentials(userId, new String(proxySettings.getProxyPassword()), workStation, domain)); - } - } + private static CloseableHttpClient createConnection(ProxySelector proxySelector, SSLContext sslContext) throws SSLInitializationException { + HttpClientBuilder builder; + + if (ProxySettings.getProxyType() != ProxySettings.DIRECT_CONNECTION + && StringUtils.isBlank(ProxySettings.getAuthenticationUsername()) + && ArrayUtils.isEmpty(ProxySettings.getAuthenticationPassword()) + && WinHttpClients.isWinAuthAvailable()) { + + builder = WinHttpClients.custom(); + builder.useSystemProperties(); + LOGGER.log(Level.WARNING, "Using Win HTTP Client"); + } else { + builder = HttpClients.custom(); + // builder.setDefaultRequestConfig(config); + LOGGER.log(Level.WARNING, "Using default http client"); } - return proxyCredsProvider; + if (sslContext != null) { + builder.setSSLContext(sslContext); + } + + if (proxySelector != null) { + builder.setRoutePlanner(new SystemDefaultRoutePlanner(proxySelector)); + } + + return builder.build(); } - private static class ProxySettingArgs { + private static class LoggingProxySelector extends ProxySelector { - private final boolean systemOrManualProxy; - private final String hostName; - private final String proxyHostname; - private final int proxyPort; - private final String proxyUserId; - private final char[] proxyPassword; - private final String authScheme; + private final ProxySelector delegate; - ProxySettingArgs(boolean systemOrManualProxy, String hostName, String proxyHostname, int proxyPort, String proxyUserId, char[] proxyPassword, String authScheme) { - this.systemOrManualProxy = systemOrManualProxy; - this.hostName = hostName; - this.proxyHostname = proxyHostname; - this.proxyPort = proxyPort; - this.proxyUserId = proxyUserId; - this.proxyPassword = proxyPassword; - this.authScheme = authScheme; - } - - boolean isSystemOrManualProxy() { - return systemOrManualProxy; - } - - String getHostName() { - return hostName; - } - - String getProxyHostname() { - return proxyHostname; - } - - int getProxyPort() { - return proxyPort; - } - - String getProxyUserId() { - return proxyUserId; - } - - char[] getProxyPassword() { - return proxyPassword; - } - - public String getAuthScheme() { - return authScheme; + public LoggingProxySelector(ProxySelector delegate) { + this.delegate = delegate; } @Override - public String toString() { - return "ProxySettingArgs{" + "systemOrManualProxy=" + systemOrManualProxy + ", hostName=" + hostName + ", proxyHostname=" + proxyHostname + ", proxyPort=" + proxyPort + ", proxyUserId=" + proxyUserId + ", proxyPassword set=" + (proxyPassword != null && proxyPassword.length > 0) + ", authScheme=" + authScheme + '}'; + public List select(URI uri) { + List selectedProxies = delegate.select(uri); + LOGGER.log(Level.FINE, MessageFormat.format("Proxy selected for {0} are {1}", uri, selectedProxies)); + return selectedProxies; + } + + @Override + public void connectFailed(URI uri, SocketAddress sa, IOException ioe) { + LOGGER.log(Level.WARNING, MessageFormat.format("Connection failed connecting to {0} socket address {1}", uri, sa), ioe); + delegate.connectFailed(uri, sa, ioe); } } From 35efa5a178ad8e5eccce8df54563f24d626ba349 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Sat, 5 Aug 2023 08:52:49 -0400 Subject: [PATCH 39/94] change log level --- .../df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java index 039d1d9e83..0a280c87e8 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java @@ -416,7 +416,7 @@ class CTCloudHttpClient { @Override public List select(URI uri) { List selectedProxies = delegate.select(uri); - LOGGER.log(Level.FINE, MessageFormat.format("Proxy selected for {0} are {1}", uri, selectedProxies)); + LOGGER.log(Level.INFO, MessageFormat.format("Proxy selected for {0} are {1}", uri, selectedProxies)); return selectedProxies; } From 5aded98cec022611558af88662b5450079380526 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 7 Aug 2023 10:45:33 -0400 Subject: [PATCH 40/94] dont check for file uploads if out of hash lookups --- .../autopsy/malwarescan/MalwareScanIngestModule.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java index 2d73effa5c..1d5871af3b 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java @@ -730,9 +730,10 @@ class MalwareScanIngestModule implements FileIngestModule { // exponential backoff before trying again long waitMultiplier = ((long) Math.pow(2, retry)); for (int i = 0; i < waitMultiplier; i++) { - if (ingestJobState.getIngestJobContext().fileIngestIsCancelled()) { + if (!ingestJobState.isDoFileLookups() || ingestJobState.getIngestJobContext().fileIngestIsCancelled()) { return; } + Thread.sleep(FILE_UPLOAD_RETRY_SLEEP_MILLIS); } } From c35357938d1c5cb1596b5f7f3e09147c206f663f Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 7 Aug 2023 16:29:08 -0400 Subject: [PATCH 41/94] update for limit type --- .../ctapi/json/DecryptedLicenseResponse.java | 6 +- .../ctcloud/Bundle.properties-MERGED | 10 ++- .../ctcloud/CTMalwareScannerOptionsPanel.java | 72 ++++++++++++++++--- 3 files changed, 72 insertions(+), 16 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/DecryptedLicenseResponse.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/DecryptedLicenseResponse.java index c6f91721ef..d939d6ed75 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/DecryptedLicenseResponse.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/DecryptedLicenseResponse.java @@ -38,7 +38,7 @@ public class DecryptedLicenseResponse { private final Long fileUploads; private final Instant activationTime; private final String product; - private final String limitType; + private final LicenseLimitType limitType; private final String timezone; private final String customerEmail; private final String customerName; @@ -54,7 +54,7 @@ public class DecryptedLicenseResponse { @JsonDeserialize(using = InstantEpochMillisDeserializer.class) @JsonProperty("activationTime") Instant activationTime, @JsonProperty("product") String product, - @JsonProperty("limitType") String limitType, + @JsonProperty("limitType") LicenseLimitType limitType, @JsonProperty("timezone") String timezone, @JsonProperty("customerEmail") String customerEmail, @JsonProperty("customerName") String customerName @@ -96,7 +96,7 @@ public class DecryptedLicenseResponse { return product; } - public String getLimitType() { + public LicenseLimitType getLimitType() { return limitType; } diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED index b05bb1cfe4..18e60839f3 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED @@ -22,6 +22,10 @@ CTMalwareScannerOptionsPanel.licenseInfoIdLabel.text= CTMalwareScannerOptionsPanel.licenseInfoExpiresLabel.text= CTMalwareScannerOptionsPanel.fileUploadsRemainingLabel.text= CTMalwareScannerOptionsPanel.licenseInfoUserLabel.text= +CTMalwareScannerOptionsPanel_getResetSuffix_daily=/day +CTMalwareScannerOptionsPanel_getResetSuffix_hourly=/hour +CTMalwareScannerOptionsPanel_getResetSuffix_monthly=/month +CTMalwareScannerOptionsPanel_getResetSuffix_weekly=/week CTMalwareScannerOptionsPanel_licenseAddDialog_desc=License Number: CTMalwareScannerOptionsPanel_licenseAddDialog_title=Add a License... CTMalwareScannerOptionsPanel_licenseAddDialogEnteredErr_desc=The license number has already been entered @@ -45,9 +49,11 @@ CTMalwareScannerOptionsPanel_malwareScans_fileUploadsRemaining=File uploads rema # {0} - hashLookupsRemaining CTMalwareScannerOptionsPanel_malwareScans_hashLookupsRemaining=Hash lookups remaining: {0} # {0} - maxDailyFileLookups -CTMalwareScannerOptionsPanel_malwareScans_maxDailyFileLookups=Max file uploads: {0}/day +# {1} - resetSuffix +CTMalwareScannerOptionsPanel_malwareScans_maxDailyFileLookups=Max file uploads: {0}{1} # {0} - maxDailyLookups -CTMalwareScannerOptionsPanel_malwareScans_maxDailyHashLookups=Max Hash lookups: {0}/day +# {1} - resetSuffix +CTMalwareScannerOptionsPanel_malwareScans_maxDailyHashLookups=Max Hash lookups: {0}{1} CTMalwareScannerOptionsPanel_MalwareScansFetcher_apiErr_title=Server Error CTMalwareScannerOptionsPanel_MalwareScansFetcher_localErr_desc=A general error occurred while fetching malware scans information. Please try again later. CTMalwareScannerOptionsPanel_MalwareScansFetcher_localErr_title=General Error diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java index 99d3ea2710..2a09c1ed55 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java @@ -24,6 +24,7 @@ import com.basistech.df.cybertriage.autopsy.ctapi.CTApiDAO; import com.basistech.df.cybertriage.autopsy.ctapi.json.AuthTokenResponse; import com.basistech.df.cybertriage.autopsy.ctapi.json.DecryptedLicenseResponse; import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseInfo; +import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseLimitType; import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseResponse; import com.basistech.df.cybertriage.autopsy.ctapi.util.LicenseDecryptorUtil; import com.basistech.df.cybertriage.autopsy.ctapi.util.LicenseDecryptorUtil.InvalidLicenseException; @@ -130,7 +131,7 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { if (licenseInfo != null) { loadMalwareScansInfo(licenseInfo); } - + MalwareIngestSettings ingestSettings = ctPersistence.loadMalwareIngestSettings(); setIngestSettings(ingestSettings); } @@ -138,12 +139,12 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { private synchronized LicenseResponse getLicenseInfo() { return this.licenseInfo == null ? null : this.licenseInfo.getLicenseResponse(); } - + private MalwareIngestSettings getIngestSettings() { return new MalwareIngestSettings() .setUploadFiles(this.fileUploadCheckbox.isSelected()); } - + private void setIngestSettings(MalwareIngestSettings ingestSettings) { if (ingestSettings == null) { ingestSettings = new MalwareIngestSettings(); @@ -439,9 +440,11 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { "# {0} - idNumber", "CTMalwareScannerOptionsPanel_licenseInfo_id=ID: {0}", "# {0} - maxDailyLookups", - "CTMalwareScannerOptionsPanel_malwareScans_maxDailyHashLookups=Max Hash lookups: {0}/day", + "# {1} - resetSuffix", + "CTMalwareScannerOptionsPanel_malwareScans_maxDailyHashLookups=Max Hash lookups: {0}{1}", "# {0} - maxDailyFileLookups", - "CTMalwareScannerOptionsPanel_malwareScans_maxDailyFileLookups=Max file uploads: {0}/day", + "# {1} - resetSuffix", + "CTMalwareScannerOptionsPanel_malwareScans_maxDailyFileLookups=Max file uploads: {0}{1}", "# {0} - countersResetDate", "CTMalwareScannerOptionsPanel_malwareScans_countersReset=Counters reset: {0}", "# {0} - hashLookupsRemaining", @@ -477,7 +480,7 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { this.malwareScansMessageLabel.setVisible(StringUtils.isNotBlank(this.authTokenMessage)); this.malwareScansMessageLabel.setText(this.authTokenMessage); - if (authTokenResponse == null) { + if (authTokenResponse == null || this.licenseInfo == null) { this.maxHashLookupsLabel.setVisible(false); this.maxFileUploadsLabel.setVisible(false); this.countersResetLabel.setVisible(false); @@ -485,15 +488,62 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { this.fileUploadsRemainingLabel.setVisible(false); } else { this.maxHashLookupsLabel.setVisible(true); - this.maxHashLookupsLabel.setText(Bundle.CTMalwareScannerOptionsPanel_malwareScans_maxDailyHashLookups(this.authTokenResponse.getHashLookupLimit())); + this.maxHashLookupsLabel.setText(Bundle.CTMalwareScannerOptionsPanel_malwareScans_maxDailyHashLookups( + this.authTokenResponse.getHashLookupLimit(), + getResetSuffix(this.licenseInfo.getDecryptedLicense().getLimitType()))); + this.maxFileUploadsLabel.setVisible(true); - this.maxFileUploadsLabel.setText(Bundle.CTMalwareScannerOptionsPanel_malwareScans_maxDailyFileLookups(this.authTokenResponse.getFileUploadLimit())); + this.maxFileUploadsLabel.setText(Bundle.CTMalwareScannerOptionsPanel_malwareScans_maxDailyFileLookups( + this.authTokenResponse.getFileUploadLimit(), + getResetSuffix(this.licenseInfo.getDecryptedLicense().getLimitType()))); + this.countersResetLabel.setVisible(true); - this.countersResetLabel.setText(Bundle.CTMalwareScannerOptionsPanel_malwareScans_countersReset(this.authTokenResponse.getResetDate() == null ? "" : MALWARE_SCANS_RESET_FORMAT.format(this.authTokenResponse.getResetDate()))); + this.countersResetLabel.setText(getCountersResetText(this.licenseInfo.getDecryptedLicense().getLimitType(), this.authTokenResponse)); + this.hashLookupsRemainingLabel.setVisible(true); - this.hashLookupsRemainingLabel.setText(Bundle.CTMalwareScannerOptionsPanel_malwareScans_hashLookupsRemaining(remaining(this.authTokenResponse.getHashLookupLimit(), this.authTokenResponse.getHashLookupCount()))); + this.hashLookupsRemainingLabel.setText( + Bundle.CTMalwareScannerOptionsPanel_malwareScans_hashLookupsRemaining( + remaining(this.authTokenResponse.getHashLookupLimit(), this.authTokenResponse.getHashLookupCount()))); + this.fileUploadsRemainingLabel.setVisible(true); - this.fileUploadsRemainingLabel.setText(Bundle.CTMalwareScannerOptionsPanel_malwareScans_fileUploadsRemaining(remaining(this.authTokenResponse.getFileUploadLimit(), this.authTokenResponse.getFileUploadCount()))); + this.fileUploadsRemainingLabel.setText( + Bundle.CTMalwareScannerOptionsPanel_malwareScans_fileUploadsRemaining( + remaining(this.authTokenResponse.getFileUploadLimit(), this.authTokenResponse.getFileUploadCount()))); + } + } + + private static String getCountersResetText(LicenseLimitType limitType, AuthTokenResponse authTokenResponse) { + if (limitType == null || limitType == LicenseLimitType.NO_RESET) { + return ""; + } else { + return Bundle.CTMalwareScannerOptionsPanel_malwareScans_countersReset( + MALWARE_SCANS_RESET_FORMAT.format(authTokenResponse.getResetDate())); + } + } + + @Messages({ + "CTMalwareScannerOptionsPanel_getResetSuffix_hourly=/hour", + "CTMalwareScannerOptionsPanel_getResetSuffix_daily=/day", + "CTMalwareScannerOptionsPanel_getResetSuffix_weekly=/week", + "CTMalwareScannerOptionsPanel_getResetSuffix_monthly=/month" + }) + private String getResetSuffix(LicenseLimitType limitType) { + if (limitType == null) { + return ""; + } + + switch (limitType) { + case HOURLY: + return Bundle.CTMalwareScannerOptionsPanel_getResetSuffix_hourly(); + case DAILY: + return Bundle.CTMalwareScannerOptionsPanel_getResetSuffix_daily(); + case WEEKLY: + return Bundle.CTMalwareScannerOptionsPanel_getResetSuffix_weekly(); + case MONTHLY: + return Bundle.CTMalwareScannerOptionsPanel_getResetSuffix_monthly(); + case NO_RESET: + default: + return ""; } } From 170a8583408090615c0beca0209193a064a3830a Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 7 Aug 2023 16:29:16 -0400 Subject: [PATCH 42/94] update for limit type --- .../autopsy/ctapi/json/LicenseLimitType.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/LicenseLimitType.java diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/LicenseLimitType.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/LicenseLimitType.java new file mode 100644 index 0000000000..7d185f86ae --- /dev/null +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/LicenseLimitType.java @@ -0,0 +1,30 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2023 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.basistech.df.cybertriage.autopsy.ctapi.json; + +/** + * The limit type (and reset) for the license. + */ +public enum LicenseLimitType { + HOURLY, + DAILY, + WEEKLY, + MONTHLY, + NO_RESET; +} From 89950593b4660cb86c5f44887b7f4fa254c49123 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 8 Aug 2023 20:03:49 -0400 Subject: [PATCH 43/94] doxygen update --- docs/doxygen-user/ct_malware_scanner.dox | 28 ++++++++++++++++++ .../images/ct_malware_license_agreement.png | Bin 0 -> 56663 bytes .../ct_malware_scanner_options_panel.png | Bin 0 -> 35019 bytes docs/doxygen-user/images/ct_upload_file.png | Bin 0 -> 52102 bytes docs/doxygen-user/main.dox | 1 + 5 files changed, 29 insertions(+) create mode 100644 docs/doxygen-user/ct_malware_scanner.dox create mode 100644 docs/doxygen-user/images/ct_malware_license_agreement.png create mode 100644 docs/doxygen-user/images/ct_malware_scanner_options_panel.png create mode 100644 docs/doxygen-user/images/ct_upload_file.png diff --git a/docs/doxygen-user/ct_malware_scanner.dox b/docs/doxygen-user/ct_malware_scanner.dox new file mode 100644 index 0000000000..4d49394156 --- /dev/null +++ b/docs/doxygen-user/ct_malware_scanner.dox @@ -0,0 +1,28 @@ +/*! \page ct_malware_scanner Cyber Triage Malware Scanner + +[TOC] + + +\section ct_malware_scanner_overview Overview + +The Malware Scanner Ingest Module uses Cyber Triage Cloud to identify if any executables in a data source are malware based on the executable's md5 hash. + +\section ct_malware_scanner_config Configuration + +Before using the Malware Scanner Ingest Module, you must register a Cyber Triage Cloud License. A license number can be added by selecting the 'Options' menu item from the 'Tools' menu, going to the 'Cyber Triage' tab, and then clicking 'Add License'. + +\image html ct_malware_scanner_options_panel.png + +The user will then be presented with a dialog to enter your license number. Enter your license number and then press 'OK'. If your license number is validated, you will be presented with the Cyber Triage End User License Agreement. The window may take a moment to load. + +\image html ct_malware_license_agreement.png + +Read through the license agreement, and press 'Accept'. At that point, your options panel should load with information pertaining to remaining lookups. + +\image html ct_upload_file.png + +\section ct_upload_executable Uploading Executable + +In the screenshot above, there is the option “Upload executable if executable is unknown.” In the event that an executable has not previously been seen by Cyber Triage Cloud, this option provides the ability to upload the executable for scanning. This option may cause increased processing time in order to upload the file and wait for scanning to complete. + +*/ diff --git a/docs/doxygen-user/images/ct_malware_license_agreement.png b/docs/doxygen-user/images/ct_malware_license_agreement.png new file mode 100644 index 0000000000000000000000000000000000000000..030a722e469c6ba1964a40fb9b5c3efcc99d11ce GIT binary patch literal 56663 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⋙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 Date: Wed, 9 Aug 2023 12:17:36 -0400 Subject: [PATCH 44/94] error message update --- .../df/cybertriage/autopsy/ctapi/CTCloudException.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudException.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudException.java index 52d586ee53..95605c4bce 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudException.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudException.java @@ -76,8 +76,7 @@ public class CTCloudException extends Exception{ public String getErrorDetails() { if(getErrorCode() == CTCloudException.ErrorCode.UNKNOWN && Objects.nonNull(getCause())){ - return String.format("Malware scan error %s occurred. Please try \"Re Scan\" from the dashboard to attempt Malware scaning again. " - + "\nPlease contact Basis support at %s for help if the problem presists.", + return String.format("An API error %s occurred. Please try again, and contact Basis support at %s for help if the problem persists.", StringUtils.isNotBlank(getCause().getLocalizedMessage()) ? "("+getCause().getLocalizedMessage()+")": "(Unknown)", Constants.SUPPORT_AT_CYBERTRIAGE_DOT_COM ); }else { From f1583a03534467d30b3292828cae0a0196996b10 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 9 Aug 2023 14:57:55 -0400 Subject: [PATCH 45/94] updated text in ct options panel disclaimer --- .../autopsy/ctoptions/Bundle.properties | 4 +- .../ctoptions/Bundle.properties-MERGED | 4 +- .../ctoptions/LicenseDisclaimerPanel.form | 157 +++++++++++++----- .../ctoptions/LicenseDisclaimerPanel.java | 129 ++++++++++---- 4 files changed, 210 insertions(+), 84 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/Bundle.properties b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/Bundle.properties index 46f62fdf7a..840725f5d7 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/Bundle.properties +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/Bundle.properties @@ -3,7 +3,7 @@ # Click nbfs://nbhost/SystemFileSystem/Templates/Other/properties.properties to edit this template OptionsCategory_Name_CyberTriage=Cyber Triage OptionsCategory_Keywords_CyberTriage=Cyber Triage,Cyber,Triage -LicenseDisclaimerPanel.disclaimer.text=The Cyber Triage Malware Scanner module uses 40+ malware scanning engines to identify if Windows executables are malicious. It requires a non-free license to use. +LicenseDisclaimerPanel.disclaimer.text=The Cyber Triage Malware Scanner module uses 40+ malware scanning engines to identify if Windows executables are malicious. It requires a paid subscription to use. LicenseDisclaimerPanel.purchaseFromLabel.text=You can purchase a license from -LicenseDisclaimerPanel.link.text=https://cybertriage.com/autopsy-checkout LicenseDisclaimerPanel.border.title=Disclaimer +LicenseDisclaimerPanel.trialLabel.text=You can try a free 7-day trial from diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/Bundle.properties-MERGED b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/Bundle.properties-MERGED index 46f62fdf7a..840725f5d7 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/Bundle.properties-MERGED +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/Bundle.properties-MERGED @@ -3,7 +3,7 @@ # Click nbfs://nbhost/SystemFileSystem/Templates/Other/properties.properties to edit this template OptionsCategory_Name_CyberTriage=Cyber Triage OptionsCategory_Keywords_CyberTriage=Cyber Triage,Cyber,Triage -LicenseDisclaimerPanel.disclaimer.text=The Cyber Triage Malware Scanner module uses 40+ malware scanning engines to identify if Windows executables are malicious. It requires a non-free license to use. +LicenseDisclaimerPanel.disclaimer.text=The Cyber Triage Malware Scanner module uses 40+ malware scanning engines to identify if Windows executables are malicious. It requires a paid subscription to use. LicenseDisclaimerPanel.purchaseFromLabel.text=You can purchase a license from -LicenseDisclaimerPanel.link.text=https://cybertriage.com/autopsy-checkout LicenseDisclaimerPanel.border.title=Disclaimer +LicenseDisclaimerPanel.trialLabel.text=You can try a free 7-day trial from diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/LicenseDisclaimerPanel.form b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/LicenseDisclaimerPanel.form index 83e3c8440a..a88404c592 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/LicenseDisclaimerPanel.form +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/LicenseDisclaimerPanel.form @@ -6,17 +6,18 @@ +
- + - + - +
@@ -29,7 +30,7 @@ - + @@ -47,45 +48,7 @@ - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -96,7 +59,7 @@ - + @@ -113,5 +76,111 @@
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/LicenseDisclaimerPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/LicenseDisclaimerPanel.java index 4299f02d62..328a252467 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/LicenseDisclaimerPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/LicenseDisclaimerPanel.java @@ -32,7 +32,12 @@ public class LicenseDisclaimerPanel extends javax.swing.JPanel { private static final Logger LOGGER = Logger.getLogger(LicenseDisclaimerPanel.class.getName()); - private static final String CHECKOUT_PAGE_URL = "https://cybertriage.com/autopsy-checkout"; + private static final String TRIAL_URL = "https://cybertriage.com/autopsy-trial"; + private static final String PURCHASE_URL = "https://cybertriage.com/autopsy-checkout"; + + private static String getHtmlLink(String url) { + return "" + url + ""; + } /** * Creates new form LicenseDisclaimerPanel @@ -52,14 +57,18 @@ public class LicenseDisclaimerPanel extends javax.swing.JPanel { java.awt.GridBagConstraints gridBagConstraints; javax.swing.JLabel disclaimer = new javax.swing.JLabel(); - javax.swing.JLabel purchaseFromLabel = new javax.swing.JLabel(); - javax.swing.JLabel link = new javax.swing.JLabel(); javax.swing.JPanel spacer = new javax.swing.JPanel(); + javax.swing.JPanel trialPanel = new javax.swing.JPanel(); + javax.swing.JLabel trialLabel = new javax.swing.JLabel(); + javax.swing.JLabel trialLink = new javax.swing.JLabel(); + javax.swing.JPanel purchasePanel = new javax.swing.JPanel(); + javax.swing.JLabel purchaseFromLabel = new javax.swing.JLabel(); + javax.swing.JLabel purchaseLink = new javax.swing.JLabel(); - setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(LicenseDisclaimerPanel.class, "LicenseDisclaimerPanel.border.title"))); // NOI18N - setMaximumSize(new java.awt.Dimension(2147483647, 90)); - setMinimumSize(new java.awt.Dimension(562, 90)); - setPreferredSize(new java.awt.Dimension(400, 90)); + setBorder(javax.swing.BorderFactory.createTitledBorder(null, org.openide.util.NbBundle.getMessage(LicenseDisclaimerPanel.class, "LicenseDisclaimerPanel.border.title"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Segoe UI", 0, 12), new java.awt.Color(255, 0, 0))); // NOI18N + setMaximumSize(new java.awt.Dimension(2147483647, 108)); + setMinimumSize(new java.awt.Dimension(562, 108)); + setPreferredSize(new java.awt.Dimension(400, 108)); setLayout(new java.awt.GridBagLayout()); org.openide.awt.Mnemonics.setLocalizedText(disclaimer, org.openide.util.NbBundle.getMessage(LicenseDisclaimerPanel.class, "LicenseDisclaimerPanel.disclaimer.text")); // NOI18N @@ -67,34 +76,12 @@ public class LicenseDisclaimerPanel extends javax.swing.JPanel { gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; - gridBagConstraints.gridwidth = 2; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); add(disclaimer, gridBagConstraints); - org.openide.awt.Mnemonics.setLocalizedText(purchaseFromLabel, org.openide.util.NbBundle.getMessage(LicenseDisclaimerPanel.class, "LicenseDisclaimerPanel.purchaseFromLabel.text")); // NOI18N - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridy = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 3); - add(purchaseFromLabel, gridBagConstraints); - - org.openide.awt.Mnemonics.setLocalizedText(link, org.openide.util.NbBundle.getMessage(LicenseDisclaimerPanel.class, "LicenseDisclaimerPanel.link.text")); // NOI18N - link.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR)); - link.addMouseListener(new java.awt.event.MouseAdapter() { - public void mouseClicked(java.awt.event.MouseEvent evt) { - linkMouseClicked(evt); - } - }); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridy = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 5); - add(link, gridBagConstraints); - javax.swing.GroupLayout spacerLayout = new javax.swing.GroupLayout(spacer); spacer.setLayout(spacerLayout); spacerLayout.setHorizontalGroup( @@ -108,24 +95,94 @@ public class LicenseDisclaimerPanel extends javax.swing.JPanel { gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 2; + gridBagConstraints.gridy = 3; gridBagConstraints.weighty = 1.0; add(spacer, gridBagConstraints); + + trialPanel.setLayout(new java.awt.GridBagLayout()); + + org.openide.awt.Mnemonics.setLocalizedText(trialLabel, org.openide.util.NbBundle.getMessage(LicenseDisclaimerPanel.class, "LicenseDisclaimerPanel.trialLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + trialPanel.add(trialLabel, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(trialLink, getHtmlLink(TRIAL_URL)); + trialLink.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR)); + trialLink.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent evt) { + trialLinkMouseClicked(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 0); + trialPanel.add(trialLink, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); + add(trialPanel, gridBagConstraints); + + purchasePanel.setLayout(new java.awt.GridBagLayout()); + + org.openide.awt.Mnemonics.setLocalizedText(purchaseFromLabel, org.openide.util.NbBundle.getMessage(LicenseDisclaimerPanel.class, "LicenseDisclaimerPanel.purchaseFromLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + purchasePanel.add(purchaseFromLabel, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(purchaseLink, getHtmlLink(PURCHASE_URL)); + purchaseLink.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR)); + purchaseLink.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent evt) { + purchaseLinkMouseClicked(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 0); + purchasePanel.add(purchaseLink, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); + add(purchasePanel, gridBagConstraints); }// //GEN-END:initComponents - private void linkMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_linkMouseClicked + private void purchaseLinkMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_purchaseLinkMouseClicked + gotoLink(PURCHASE_URL); + }//GEN-LAST:event_purchaseLinkMouseClicked + + private void trialLinkMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_trialLinkMouseClicked + gotoLink(TRIAL_URL); + }//GEN-LAST:event_trialLinkMouseClicked + + private void gotoLink(String url) { if (Desktop.isDesktopSupported()) { try { - Desktop.getDesktop().browse(new URI(CHECKOUT_PAGE_URL)); + Desktop.getDesktop().browse(new URI(url)); } catch (IOException | URISyntaxException e) { - LOGGER.log(Level.SEVERE, "Error opening link to: " + CHECKOUT_PAGE_URL, e); + LOGGER.log(Level.SEVERE, "Error opening link to: " + url, e); } } else { LOGGER.log(Level.WARNING, "Desktop API is not supported. Link cannot be opened."); } - }//GEN-LAST:event_linkMouseClicked - - + } // Variables declaration - do not modify//GEN-BEGIN:variables // End of variables declaration//GEN-END:variables } From 1b78b4964bc2e17d334af4555bb810d765f7905f Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 10 Aug 2023 14:03:17 -0400 Subject: [PATCH 46/94] updates for path normalizer --- .../malwarescan/MalwareScanIngestModule.java | 16 +- .../autopsy/malwarescan/PathNormalizer.java | 201 ++++++++++++++++++ .../malwarescan/UsernameAnonymizer.java | 155 -------------- 3 files changed, 213 insertions(+), 159 deletions(-) create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/PathNormalizer.java delete mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/UsernameAnonymizer.java diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java index 1d5871af3b..c52e72a350 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java @@ -136,7 +136,6 @@ class MalwareScanIngestModule implements FileIngestModule { private final CTLicensePersistence ctSettingsPersistence = CTLicensePersistence.getInstance(); private final CTApiDAO ctApiDAO = CTApiDAO.getInstance(); - private final UsernameAnonymizer usernameAnonymizer = new UsernameAnonymizer(); private IngestJobState ingestJobState = null; @@ -235,6 +234,7 @@ class MalwareScanIngestModule implements FileIngestModule { return new IngestJobState( context, tskCase, + new PathNormalizer(tskCase), new FileTypeDetector(), licenseInfoOpt.get(), malwareType, @@ -657,7 +657,7 @@ class MalwareScanIngestModule implements FileIngestModule { // upload metadata MetadataUploadRequest metaRequest = new MetadataUploadRequest() .setCreatedDate(af.getCrtime() == 0 ? null : af.getCrtime()) - .setFilePath(usernameAnonymizer.anonymousUsername(af.getUniquePath())) + .setFilePath(ingestJobState.getPathNormalizer().normalizePath(af.getUniquePath())) .setFileSizeBytes(af.getSize()) .setFileUploadUrl(authTokenResponse.getFileUploadUrl()) .setMd5(md5) @@ -733,7 +733,7 @@ class MalwareScanIngestModule implements FileIngestModule { if (!ingestJobState.isDoFileLookups() || ingestJobState.getIngestJobContext().fileIngestIsCancelled()) { return; } - + Thread.sleep(FILE_UPLOAD_RETRY_SLEEP_MILLIS); } } @@ -934,6 +934,7 @@ class MalwareScanIngestModule implements FileIngestModule { null, null, null, + null, false, false ); @@ -951,10 +952,12 @@ class MalwareScanIngestModule implements FileIngestModule { private boolean uploadUnknownFiles; private boolean doFileLookups; private final IngestJobContext ingestJobContext; + private final PathNormalizer pathNormalizer; - IngestJobState(IngestJobContext ingestJobContext, SleuthkitCase tskCase, FileTypeDetector fileTypeDetector, LicenseInfo licenseInfo, BlackboardArtifact.Type malwareType, boolean uploadUnknownFiles, boolean doFileLookups) { + IngestJobState(IngestJobContext ingestJobContext, SleuthkitCase tskCase, PathNormalizer pathNormalizer, FileTypeDetector fileTypeDetector, LicenseInfo licenseInfo, BlackboardArtifact.Type malwareType, boolean uploadUnknownFiles, boolean doFileLookups) { this.tskCase = tskCase; this.fileTypeDetector = fileTypeDetector; + this.pathNormalizer = pathNormalizer; this.licenseInfo = licenseInfo; this.malwareType = malwareType; this.dsId = ingestJobContext == null ? 0L : ingestJobContext.getDataSource().getId(); @@ -1017,6 +1020,11 @@ class MalwareScanIngestModule implements FileIngestModule { void disableDoFileLookups() { this.doFileLookups = false; } + + public PathNormalizer getPathNormalizer() { + return pathNormalizer; + } + } } } diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/PathNormalizer.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/PathNormalizer.java new file mode 100644 index 0000000000..f8a0a299a5 --- /dev/null +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/PathNormalizer.java @@ -0,0 +1,201 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2023 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.basistech.df.cybertriage.autopsy.malwarescan; + +import com.google.common.net.InetAddresses; +import java.net.InetAddress; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Set; +import java.util.logging.Level; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import org.apache.commons.lang3.StringUtils; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * Utility class to anonymize paths. + */ +class PathNormalizer { + + private static final Logger LOGGER = Logger.getLogger(PathNormalizer.class.getName()); + + private static final String ANONYMIZED_USERNAME = ""; + private static final String ANONYMIZED_IP = ""; + private static final String ANONYMIZED_HOSTNAME = ""; + private static final String FORWARD_SLASH = "/"; + private static final String BACK_SLASH = "\\"; + + private static final Pattern USER_PATH_FORWARD_SLASH_REGEX = Pattern.compile("(? getUsernames() { + try { + return this.skCase.getOsAccountManager().getOsAccounts().stream() + .filter(acct -> acct != null) + .map(acct -> acct.getLoginName().orElse(null)) + .filter(StringUtils::isNotBlank) + .collect(Collectors.toList()); + } catch (TskCoreException ex) { + LOGGER.log(Level.WARNING, "There was an error getting current os accounts", ex); + return Collections.emptyList(); + } + } + + public String normalizePath(String inputString) { + if (StringUtils.isBlank(inputString)) { + return ""; + } + + String anonymousString = anonymizeUserFromPathsWithForwardSlashes(inputString); + anonymousString = anonymizeUserFromPathsWithBackSlashes(anonymousString); + anonymousString = anonymizeServerFromUNCPath(anonymousString); + + return anonymousString; + } + + private String anonymizeUserFromPathsWithForwardSlashes(String stringWithUsername) { + String anonymousString = stringWithUsername; + anonymousString = regexReplace(anonymousString, USER_PATH_FORWARD_SLASH_REGEX_XP, USERNAME_REGEX_REPLACEMENT); + anonymousString = regexReplace(anonymousString, USER_PATH_FORWARD_SLASH_REGEX, USERNAME_REGEX_REPLACEMENT); + anonymousString = replaceFolder(anonymousString, getUsernames(), ANONYMIZED_USERNAME, FORWARD_SLASH); + return anonymousString; + } + + // Most paths in CyberTriage are normalized with forward slashes + // but there can still be strings containing paths that are not normalized such paths contained in arguments or event log payloads + private String anonymizeUserFromPathsWithBackSlashes(String stringWithUsername) { + String anonymousString = stringWithUsername; + anonymousString = regexReplace(anonymousString, USER_PATH_BACK_SLASH_REGEX_XP, USERNAME_REGEX_REPLACEMENT); + anonymousString = regexReplace(anonymousString, USER_PATH_BACK_SLASH_REGEX, USERNAME_REGEX_REPLACEMENT); + anonymousString = replaceFolder(anonymousString, getUsernames(), ANONYMIZED_USERNAME, BACK_SLASH); + + return anonymousString; + } + + private String anonymizeServerFromUNCPath(String inputString) { + + Set serverNames = new HashSet<>(); + String anonymousString = inputString.toLowerCase(Locale.ENGLISH); + + Matcher forwardSlashMatcher = UNC_PATH_FORWARD_SLASH_PATTERN.matcher(anonymousString); + while (forwardSlashMatcher.find()) { + String serverName = forwardSlashMatcher.group(2); + serverNames.add(serverName); + } + + Matcher backSlashMatcher = UNC_PATH_BACK_SLASH_PATTERN.matcher(anonymousString); + while (backSlashMatcher.find()) { + String serverName = backSlashMatcher.group(2); + serverNames.add(serverName); + } + + for (String serverName : serverNames) { + + if (StringUtils.isBlank(serverName)) { + continue; + } + + if (InetAddresses.isInetAddress(serverName) && isLocalIP(serverName)) { + anonymousString = replaceFolder(anonymousString, Collections.singletonList(serverName), ANONYMIZED_IP); + } else { + anonymousString = replaceFolder(anonymousString, Collections.singletonList(serverName), ANONYMIZED_HOSTNAME); + } + + } + + return anonymousString; + } + + private static String regexReplace(String orig, Pattern pattern, String regexReplacement) { + Matcher matcher = pattern.matcher(orig); + return matcher.replaceAll(regexReplacement); + } + + private static String replaceFolder(String orig, List valuesToReplace, String replacementValue) { + String anonymized = orig; + anonymized = replaceFolder(anonymized, valuesToReplace, replacementValue, FORWARD_SLASH); + anonymized = replaceFolder(anonymized, valuesToReplace, replacementValue, BACK_SLASH); + return anonymized; + } + + private static String replaceFolder(String orig, List valuesToReplace, String replacementValue, String folderDelimiter) { + if (orig == null || valuesToReplace == null) { + return orig; + } + + String anonymousString = orig; + + // ensure non-null + folderDelimiter = StringUtils.defaultString(folderDelimiter); + replacementValue = StringUtils.defaultString(replacementValue); + + // replace + for (String valueToReplace : valuesToReplace) { + if (StringUtils.isNotEmpty(valueToReplace)) { + anonymousString = StringUtils.replace(anonymousString, + folderDelimiter + valueToReplace + folderDelimiter, + folderDelimiter + replacementValue + folderDelimiter); + } + } + + return anonymousString; + } + + /** + * Returns true if IP Address is Any Local / Site Local / Link Local / Loop + * back local. Sample list "0.0.0.0", wildcard addres + * "10.1.1.1","10.10.10.10", site local address "127.0.0.0","127.2.2.2", + * loopback address "169.254.0.0","169.254.10.10", Link local address + * "172.16.0.0","172.31.245.245", site local address + * + * @param ipAddress + * @return + */ + public static boolean isLocalIP(String ipAddress) { + try { + InetAddress a = InetAddresses.forString(ipAddress); + return a.isAnyLocalAddress() || a.isSiteLocalAddress() + || a.isLoopbackAddress() || a.isLinkLocalAddress(); + } catch (IllegalArgumentException ex) { + LOGGER.log(Level.WARNING, "Invalid IP string", ex); + return false; + } + } + +} diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/UsernameAnonymizer.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/UsernameAnonymizer.java deleted file mode 100644 index 75261ae43f..0000000000 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/UsernameAnonymizer.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2023 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.basistech.df.cybertriage.autopsy.malwarescan; - -import com.google.common.net.InetAddresses; -import java.net.InetAddress; -import java.util.HashSet; -import java.util.Locale; -import java.util.Set; -import java.util.logging.Level; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import org.apache.commons.lang3.StringUtils; -import org.sleuthkit.autopsy.coreutils.Logger; - -/** - * Utility class to anonymize username in paths also anonymizes hostname / ip - * from UNC paths - */ -class UsernameAnonymizer { - - private static final Logger LOGGER = Logger.getLogger(UsernameAnonymizer.class.getName()); - - private final String USER_PATH_FORWARD_SLASH_REGEX = "(?"); - } - String anonymousString = matcher.replaceAll(replacement); - - return anonymousString; - } - - // Most paths in CyberTriage are normalized with forward slashes - // but there can still be strings containing paths that are not normalized such paths contained in arguments or event log payloads - private String anonymizeUserFromPathsWithBackSlashes(String stringWithUsername) { - Pattern pattern = WINDOWS_VERSION < 6 ? Pattern.compile(USER_PATH_BACK_SLASH_REGEX_XP, Pattern.CASE_INSENSITIVE) : Pattern.compile(USER_PATH_BACK_SLASH_REGEX, Pattern.CASE_INSENSITIVE); - Matcher matcher = pattern.matcher(stringWithUsername.toLowerCase(Locale.ENGLISH)); - String replacement = ""; - while (matcher.find()) { - replacement = String.format("$1%s$4", ""); - } - String anonymousString = matcher.replaceAll(replacement); - - return anonymousString; - } - - private String anonymizeServerFromUNCPath(String inputString) { - - Set serverNames = new HashSet<>(); - String anonymousString = inputString.toLowerCase(Locale.ENGLISH); - - Matcher forwardSlashMatcher = UNC_PATH_FORWARD_SLASH_PATTERN.matcher(anonymousString); - while (forwardSlashMatcher.find()) { - String serverName = forwardSlashMatcher.group(2); - serverNames.add(serverName); - } - - Matcher backSlashMatcher = UNC_PATH_BACK_SLASH_PATTERN.matcher(anonymousString); - while (backSlashMatcher.find()) { - String serverName = backSlashMatcher.group(2); - serverNames.add(serverName); - } - - for (String serverName : serverNames) { - - if (StringUtils.isBlank(serverName)) { - continue; - } - - if (InetAddresses.isInetAddress(serverName)) { - if (isLocalIP(serverName)) { - anonymousString = StringUtils.replace(anonymousString, "\\" + serverName + "\\", "\\\\"); - anonymousString = StringUtils.replace(anonymousString, "/" + serverName + "/", "//"); - } - } else { - anonymousString = StringUtils.replace(anonymousString, "\\" + serverName + "\\", "\\\\"); - anonymousString = StringUtils.replace(anonymousString, "/" + serverName + "/", "//"); - } - - } - - return anonymousString; - } - - /** - * Returns true if IP Address is Any Local / Site Local / Link Local / Loop - * back local. Sample list "0.0.0.0", wildcard addres - * "10.1.1.1","10.10.10.10", site local address "127.0.0.0","127.2.2.2", - * loopback address "169.254.0.0","169.254.10.10", Link local address - * "172.16.0.0","172.31.245.245", site local address - * - * @param ipAddress - * @return - */ - public static boolean isLocalIP(String ipAddress) { - try { - InetAddress a = InetAddresses.forString(ipAddress); - return a.isAnyLocalAddress() || a.isSiteLocalAddress() - || a.isLoopbackAddress() || a.isLinkLocalAddress(); - } catch (IllegalArgumentException ex) { - LOGGER.log(Level.WARNING, "Invalid IP string", ex); - return false; - } - } - -} From e4fb10458f1456fba13f62c95eff83cab04b8fb1 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Tue, 15 Aug 2023 14:02:44 -0400 Subject: [PATCH 47/94] added malware scanner doc template --- docs/doxygen-user/ct_malware_scanner.dox | 57 ++++++++++++++++++++++++ docs/doxygen-user/main.dox | 1 + 2 files changed, 58 insertions(+) create mode 100644 docs/doxygen-user/ct_malware_scanner.dox diff --git a/docs/doxygen-user/ct_malware_scanner.dox b/docs/doxygen-user/ct_malware_scanner.dox new file mode 100644 index 0000000000..196a4d5b00 --- /dev/null +++ b/docs/doxygen-user/ct_malware_scanner.dox @@ -0,0 +1,57 @@ +/*! \page ct_malware_scanner_page Cyber Triage Malware Scanner Module + +[TOC] + +What Does It Do +======== + +The Cyber Triage Malware Scanner module will use the malware scanning infrastructure from Cyber Triage to identify if any Windows executables are malware. It will query an online service using the file's hash value to see if the file was already analyzed and allows you to upload files for analysis if they are new. + +This module requires a commercial license from Cyber Triage. + +For more information on obtaining a license, refer to [CyberTriage.com](https://cybertriage.com/autopsy-malware-module). The remainder of this page is about the use of the module once it is licensed. + + +Configuration +======= + +Once you have a license, you must add it on the Options panel. Choose the 'Cyber Triage' tab and choose 'Add License'. + + +IMAGE + +After you enter the license number that you should have received from your email, you will then need to review and agree to the license terms. + + +The options panel should now display information about the lookup limits. You can always refer back to here about what your limits are and when they reset. + +IMAGE + + + +Using the Module +====== + +Ingest Settings +------ + +For each data source, you select if you want files to be uploaded if they have not already been analyzed. By default, they are uploaded. You can choose to not upload them though. + +IMAGE + + + +Out of Scans +------- + +If you go beyond your limits, you will get a dialog that not all files were analyzed. You can wait until your limits reset and then start ingest again with only the malware scanning module enabled. It will ignore the files that are already analyzed. + + +Seeing Results +------ + +Once ingest has completed, the files with malware will be listed in the Malware node in the tree. + +IMAGE + +*/ diff --git a/docs/doxygen-user/main.dox b/docs/doxygen-user/main.dox index a31367ff6c..193a5abcba 100644 --- a/docs/doxygen-user/main.dox +++ b/docs/doxygen-user/main.dox @@ -58,6 +58,7 @@ The following topics are available here: - \subpage ileapp_page - \subpage aleapp_page - \subpage yara_page + - \subpage ct_malware_scanner_page - Reviewing the Results - \subpage uilayout_page From 797e26569fa879d6dd82066f4061a5787c5904bf Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Tue, 15 Aug 2023 14:08:20 -0400 Subject: [PATCH 48/94] Update CTIntegrationMissingDialog.java --- .../df/cybertriage/autopsy/CTIntegrationMissingDialog.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/CTIntegrationMissingDialog.java b/Core/src/com/basistech/df/cybertriage/autopsy/CTIntegrationMissingDialog.java index 8fbec4abef..9e534c9833 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/CTIntegrationMissingDialog.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/CTIntegrationMissingDialog.java @@ -32,7 +32,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; */ public class CTIntegrationMissingDialog extends javax.swing.JDialog { - private static final String DOCS_PAGE_URL = "http://docs.cybertriage.com"; + private static final String DOCS_PAGE_URL = "https://docs.cybertriage.com/en/latest/chapters/integrations/autopsy.html"; private static final Logger LOGGER = Logger.getLogger(CTIntegrationMissingDialog.class.getName()); From 43d9352a1a748cf210678c33ac1e5f01adb5451f Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Tue, 15 Aug 2023 14:12:42 -0400 Subject: [PATCH 49/94] updated news --- NEWS.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.txt b/NEWS.txt index 3ba3ebf9af..b8db91ca62 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -24,7 +24,7 @@ Bugs: - Fix exporting of CSV files. Issue https://github.com/sleuthkit/autopsy/issues/6717 Misc: -- Added File Repository concept +- Added File Repository concept for data source files that are in a central location - Added Spanish language support, contributor https://github.com/AburtoArielPM ---------------- VERSION 4.20.0 -------------- From 4f9b1af344f54b2fa05211b11fb2a3e93ba535f1 Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Tue, 15 Aug 2023 14:20:06 -0400 Subject: [PATCH 50/94] Change option screens change option screens --- .../autopsy/ctapi/CTCloudHttpClient.java | 3 +- .../autopsy/ctoptions/CTOptionsPanel.java | 7 +- .../ctoptions/ctcloud/Bundle.properties | 7 +- .../ctcloud/Bundle.properties-MERGED | 7 +- .../ctcloud/CTMalwareScannerOptionsPanel.form | 356 +++++++++++------- .../ctcloud/CTMalwareScannerOptionsPanel.java | 145 +++++-- .../autopsy/incidentoptions/Bundle.properties | 14 + .../incidentoptions/Bundle.properties-MERGED | 14 + .../CTIncidentImportOptionsPanel.form | 168 +++++++++ .../CTIncidentImportOptionsPanel.java | 287 ++++++++++++++ .../autopsy/incidentoptions/CTSettings.java | 71 ++++ .../CTSettingsPersistence.java | 79 ++++ 12 files changed, 975 insertions(+), 183 deletions(-) create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties-MERGED create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.form create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.java create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettings.java create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettingsPersistence.java diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java index 0a280c87e8..44e94f82a1 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java @@ -84,7 +84,8 @@ import org.sleuthkit.autopsy.coreutils.Version; class CTCloudHttpClient { private static final Logger LOGGER = Logger.getLogger(CTCloudHttpClient.class.getName()); - private static final String HOST_URL = Version.getBuildType() == Version.Type.RELEASE ? Constants.CT_CLOUD_SERVER : Constants.CT_CLOUD_DEV_SERVER; +// private static final String HOST_URL = Version.getBuildType() == Version.Type.RELEASE ? Constants.CT_CLOUD_SERVER : Constants.CT_CLOUD_DEV_SERVER; + private static final String HOST_URL = Version.getBuildType() == Version.Type.RELEASE ? Constants.CT_CLOUD_DEV_SERVER : Constants.CT_CLOUD_SERVER; private static final String NB_PROXY_SELECTOR_NAME = "org.netbeans.core.NbProxySelector"; private static final int CONNECTION_TIMEOUT_MS = 58 * 1000; // milli sec diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/CTOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/CTOptionsPanel.java index 745aa1d03d..c0999e3b9e 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/CTOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/CTOptionsPanel.java @@ -64,12 +64,11 @@ public class CTOptionsPanel extends IngestModuleGlobalSettingsPanel { } }) .filter(item -> item != null) - .sorted(Comparator.comparing(p -> p.getClass().getSimpleName().toUpperCase())) .collect(Collectors.toList()); - addSubOptionsPanels(new LicenseDisclaimerPanel(), this.subPanels); + addSubOptionsPanels(this.subPanels); } - private void addSubOptionsPanels(JPanel disclaimerPanel, List subPanels) { + private void addSubOptionsPanels(List subPanels) { GridBagConstraints disclaimerConstraints = new GridBagConstraints(); disclaimerConstraints.gridx = 0; disclaimerConstraints.gridy = 0; @@ -79,7 +78,7 @@ public class CTOptionsPanel extends IngestModuleGlobalSettingsPanel { disclaimerConstraints.weighty = 0; disclaimerConstraints.weightx = 0; - contentPane.add(disclaimerPanel, disclaimerConstraints); +// contentPane.add(disclaimerPanel, disclaimerConstraints); for (int i = 0; i < subPanels.size(); i++) { CTOptionsSubPanel subPanel = subPanels.get(i); diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties index d0395d6a1a..3b48b0ea4e 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties @@ -9,13 +9,11 @@ CTLicenseDialog.cancelButton.text=Cancel CTLicenseDialog.okButton.text=Ok CTLicenseDialog.warningLabel.text= CTMalwareScannerOptionsPanel.hashLookupsRemainingLabel.text= -CTMalwareScannerOptionsPanel.licenseInfoMessageLabel.text= CTMalwareScannerOptionsPanel.countersResetLabel.text= -CTMalwareScannerOptionsPanel.licenseInfoPanel.border.title=License Info CTMalwareScannerOptionsPanel.maxFileUploadsLabel.text= CTMalwareScannerOptionsPanel.maxHashLookupsLabel.text= CTMalwareScannerOptionsPanel.malwareScansMessageLabel.text= -CTMalwareScannerOptionsPanel.malwareScansPanel.border.title=Malware Scans +CTMalwareScannerOptionsPanel.malwareScansPanel.border.title=Malware Scanner CTMalwareScannerOptionsPanel.licenseInfoAddButton.text=Add License CTMalwareScannerOptionsPanel.licenseInfoIdLabel.text= CTMalwareScannerOptionsPanel.licenseInfoExpiresLabel.text= @@ -26,3 +24,6 @@ EULADialog.acceptButton.text=Accept EULADialog.title=Cyber Triage End User License Agreement CTMalwareScannerOptionsPanel.fileUploadCheckbox.text=Upload file if hash lookup produces no results CTMalwareScannerOptionsPanel.fileUploadPanel.border.title=File Upload +CTMalwareScannerOptionsPanel.licenseInfoMessageLabel.text= +CTMalwareScannerOptionsPanel.disclaimer.text=The Cyber Triage Malware Scanner module uses 40+ malware scanning engines to identify if Windows executables are malicious. It requires a paid subscription to use. +CTMalwareScannerOptionsPanel.purchaseFromLabel.text=For licensing information, visit diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED index 18e60839f3..d3922b3c09 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED @@ -10,13 +10,11 @@ CTLicenseDialog.okButton.text=Ok CTLicenseDialog.warningLabel.text= CTLicenseDialog_verifyInput_licenseNumberError=Please verify license number format of 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' CTMalwareScannerOptionsPanel.hashLookupsRemainingLabel.text= -CTMalwareScannerOptionsPanel.licenseInfoMessageLabel.text= CTMalwareScannerOptionsPanel.countersResetLabel.text= -CTMalwareScannerOptionsPanel.licenseInfoPanel.border.title=License Info CTMalwareScannerOptionsPanel.maxFileUploadsLabel.text= CTMalwareScannerOptionsPanel.maxHashLookupsLabel.text= CTMalwareScannerOptionsPanel.malwareScansMessageLabel.text= -CTMalwareScannerOptionsPanel.malwareScansPanel.border.title=Malware Scans +CTMalwareScannerOptionsPanel.malwareScansPanel.border.title=Malware Scanner CTMalwareScannerOptionsPanel.licenseInfoAddButton.text=Add License CTMalwareScannerOptionsPanel.licenseInfoIdLabel.text= CTMalwareScannerOptionsPanel.licenseInfoExpiresLabel.text= @@ -64,3 +62,6 @@ EULADialog.acceptButton.text=Accept EULADialog.title=Cyber Triage End User License Agreement CTMalwareScannerOptionsPanel.fileUploadCheckbox.text=Upload file if hash lookup produces no results CTMalwareScannerOptionsPanel.fileUploadPanel.border.title=File Upload +CTMalwareScannerOptionsPanel.licenseInfoMessageLabel.text= +CTMalwareScannerOptionsPanel.disclaimer.text=The Cyber Triage Malware Scanner module uses 40+ malware scanning engines to identify if Windows executables are malicious. It requires a paid subscription to use. +CTMalwareScannerOptionsPanel.purchaseFromLabel.text=For licensing information, visit diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form index 8557f946d9..e9886eadf2 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form @@ -11,7 +11,7 @@ - + @@ -26,10 +26,6 @@
- - - - @@ -59,98 +55,11 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -164,78 +73,237 @@ - + - + + + + + + - + - - - - - - + + + + + - + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java index 2a09c1ed55..496e01d69f 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java @@ -28,9 +28,12 @@ import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseLimitType; import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseResponse; import com.basistech.df.cybertriage.autopsy.ctapi.util.LicenseDecryptorUtil; import com.basistech.df.cybertriage.autopsy.ctapi.util.LicenseDecryptorUtil.InvalidLicenseException; +import java.awt.Desktop; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.Optional; @@ -73,6 +76,8 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { private volatile String licenseInfoMessage = null; private volatile LicenseFetcher licenseFetcher = null; + private static final String PURCHASE_URL = "https://cybertriage.com/autopsy-checkout"; + private volatile AuthTokenResponse authTokenResponse = null; private volatile String authTokenMessage = null; private volatile AuthTokenFetcher authTokenFetcher = null; @@ -83,6 +88,8 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { public CTMalwareScannerOptionsPanel() { initComponents(); + this.fileUploadPanel.setVisible(false); + this.addComponentListener(new ComponentAdapter() { @Override public void componentHidden(ComponentEvent e) { @@ -136,6 +143,22 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { setIngestSettings(ingestSettings); } + private static String getHtmlLink(String url) { + return "" + url + ""; + } + + private void gotoLink(String url) { + if (Desktop.isDesktopSupported()) { + try { + Desktop.getDesktop().browse(new URI(url)); + } catch (IOException | URISyntaxException e) { + logger.log(Level.SEVERE, "Error opening link to: " + url, e); + } + } else { + logger.log(Level.WARNING, "Desktop API is not supported. Link cannot be opened."); + } + } + private synchronized LicenseResponse getLicenseInfo() { return this.licenseInfo == null ? null : this.licenseInfo.getLicenseResponse(); } @@ -220,21 +243,26 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { private void initComponents() { java.awt.GridBagConstraints gridBagConstraints; - javax.swing.JPanel fileUploadPanel = new javax.swing.JPanel(); + fileUploadPanel = new javax.swing.JPanel(); fileUploadCheckbox = new javax.swing.JCheckBox(); + malwareScansPanel = new javax.swing.JPanel(); + javax.swing.JLabel disclaimer = new javax.swing.JLabel(); javax.swing.JPanel licenseInfoPanel = new javax.swing.JPanel(); licenseInfoMessageLabel = new javax.swing.JLabel(); - licenseInfoUserLabel = new javax.swing.JLabel(); licenseInfoExpiresLabel = new javax.swing.JLabel(); licenseInfoIdLabel = new javax.swing.JLabel(); + licenseInfoUserLabel = new javax.swing.JLabel(); licenseInfoAddButton = new javax.swing.JButton(); - malwareScansPanel = new javax.swing.JPanel(); + malwareScannerStatsPanel = new javax.swing.JPanel(); malwareScansMessageLabel = new javax.swing.JLabel(); maxHashLookupsLabel = new javax.swing.JLabel(); maxFileUploadsLabel = new javax.swing.JLabel(); countersResetLabel = new javax.swing.JLabel(); hashLookupsRemainingLabel = new javax.swing.JLabel(); fileUploadsRemainingLabel = new javax.swing.JLabel(); + javax.swing.JPanel purchasePanel = new javax.swing.JPanel(); + javax.swing.JLabel purchaseFromLabel = new javax.swing.JLabel(); + javax.swing.JLabel purchaseLink = new javax.swing.JLabel(); setLayout(new java.awt.GridBagLayout()); @@ -267,7 +295,20 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { gridBagConstraints.weightx = 1.0; add(fileUploadPanel, gridBagConstraints); - licenseInfoPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.licenseInfoPanel.border.title"))); // NOI18N + malwareScansPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.malwareScansPanel.border.title"))); // NOI18N + malwareScansPanel.setLayout(new java.awt.GridBagLayout()); + + org.openide.awt.Mnemonics.setLocalizedText(disclaimer, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.disclaimer.text")); // NOI18N + disclaimer.setVerticalAlignment(javax.swing.SwingConstants.TOP); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); + malwareScansPanel.add(disclaimer, gridBagConstraints); + licenseInfoPanel.setLayout(new java.awt.GridBagLayout()); org.openide.awt.Mnemonics.setLocalizedText(licenseInfoMessageLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.licenseInfoMessageLabel.text")); // NOI18N @@ -281,18 +322,9 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); licenseInfoPanel.add(licenseInfoMessageLabel, gridBagConstraints); - org.openide.awt.Mnemonics.setLocalizedText(licenseInfoUserLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.licenseInfoUserLabel.text")); // NOI18N - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); - licenseInfoPanel.add(licenseInfoUserLabel, gridBagConstraints); - org.openide.awt.Mnemonics.setLocalizedText(licenseInfoExpiresLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.licenseInfoExpiresLabel.text")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; + gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 1; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.weightx = 1.0; @@ -301,12 +333,21 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { org.openide.awt.Mnemonics.setLocalizedText(licenseInfoIdLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.licenseInfoIdLabel.text")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); + licenseInfoPanel.add(licenseInfoIdLabel, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(licenseInfoUserLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.licenseInfoUserLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); - licenseInfoPanel.add(licenseInfoIdLabel, gridBagConstraints); + gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); + licenseInfoPanel.add(licenseInfoUserLabel, gridBagConstraints); org.openide.awt.Mnemonics.setLocalizedText(licenseInfoAddButton, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.licenseInfoAddButton.text")); // NOI18N licenseInfoAddButton.addActionListener(new java.awt.event.ActionListener() { @@ -328,10 +369,9 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.weightx = 1.0; - add(licenseInfoPanel, gridBagConstraints); + malwareScansPanel.add(licenseInfoPanel, gridBagConstraints); - malwareScansPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.malwareScansPanel.border.title"))); // NOI18N - malwareScansPanel.setLayout(new java.awt.GridBagLayout()); + malwareScannerStatsPanel.setLayout(new java.awt.GridBagLayout()); org.openide.awt.Mnemonics.setLocalizedText(malwareScansMessageLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.malwareScansMessageLabel.text")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); @@ -342,7 +382,7 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); - malwareScansPanel.add(malwareScansMessageLabel, gridBagConstraints); + malwareScannerStatsPanel.add(malwareScansMessageLabel, gridBagConstraints); org.openide.awt.Mnemonics.setLocalizedText(maxHashLookupsLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.maxHashLookupsLabel.text")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); @@ -351,16 +391,17 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); - malwareScansPanel.add(maxHashLookupsLabel, gridBagConstraints); + malwareScannerStatsPanel.add(maxHashLookupsLabel, gridBagConstraints); org.openide.awt.Mnemonics.setLocalizedText(maxFileUploadsLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.maxFileUploadsLabel.text")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 2; + gridBagConstraints.gridwidth = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); - malwareScansPanel.add(maxFileUploadsLabel, gridBagConstraints); + malwareScannerStatsPanel.add(maxFileUploadsLabel, gridBagConstraints); org.openide.awt.Mnemonics.setLocalizedText(countersResetLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.countersResetLabel.text")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); @@ -369,7 +410,7 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); - malwareScansPanel.add(countersResetLabel, gridBagConstraints); + malwareScannerStatsPanel.add(countersResetLabel, gridBagConstraints); org.openide.awt.Mnemonics.setLocalizedText(hashLookupsRemainingLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.hashLookupsRemainingLabel.text")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); @@ -378,7 +419,7 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); - malwareScansPanel.add(hashLookupsRemainingLabel, gridBagConstraints); + malwareScannerStatsPanel.add(hashLookupsRemainingLabel, gridBagConstraints); org.openide.awt.Mnemonics.setLocalizedText(fileUploadsRemainingLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.fileUploadsRemainingLabel.text")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); @@ -387,7 +428,46 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); - malwareScansPanel.add(fileUploadsRemainingLabel, gridBagConstraints); + malwareScannerStatsPanel.add(fileUploadsRemainingLabel, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + malwareScansPanel.add(malwareScannerStatsPanel, gridBagConstraints); + + purchasePanel.setLayout(new java.awt.GridBagLayout()); + + org.openide.awt.Mnemonics.setLocalizedText(purchaseFromLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.purchaseFromLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + purchasePanel.add(purchaseFromLabel, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(purchaseLink, getHtmlLink(PURCHASE_URL)); + purchaseLink.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR)); + purchaseLink.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent evt) { + purchaseLinkMouseClicked(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 0); + purchasePanel.add(purchaseLink, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 3; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); + malwareScansPanel.add(purchasePanel, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; @@ -431,6 +511,10 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { this.firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); }//GEN-LAST:event_fileUploadCheckboxActionPerformed + private void purchaseLinkMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_purchaseLinkMouseClicked + gotoLink(PURCHASE_URL); + }//GEN-LAST:event_purchaseLinkMouseClicked + @NbBundle.Messages({ "# {0} - userName", "# {1} - email", @@ -646,12 +730,15 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { } @Override - protected AuthTokenResponse doInBackground() throws Exception { + protected AuthTokenResponse doInBackground() throws Exception, CTCloudException { if (this.isCancelled()) { return null; } - - return ctApiDAO.getAuthToken(decryptedLicense); + try { + return ctApiDAO.getAuthToken(decryptedLicense); + } catch (CTCloudException ex) { + return null; + } } @Override @@ -692,6 +779,7 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel countersResetLabel; private javax.swing.JCheckBox fileUploadCheckbox; + private javax.swing.JPanel fileUploadPanel; private javax.swing.JLabel fileUploadsRemainingLabel; private javax.swing.JLabel hashLookupsRemainingLabel; private javax.swing.JButton licenseInfoAddButton; @@ -699,6 +787,7 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { private javax.swing.JLabel licenseInfoIdLabel; private javax.swing.JLabel licenseInfoMessageLabel; private javax.swing.JLabel licenseInfoUserLabel; + private javax.swing.JPanel malwareScannerStatsPanel; private javax.swing.JLabel malwareScansMessageLabel; private javax.swing.JPanel malwareScansPanel; private javax.swing.JLabel maxFileUploadsLabel; diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties new file mode 100644 index 0000000000..ebde860d0b --- /dev/null +++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties @@ -0,0 +1,14 @@ + +# Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license +# Click nbfs://nbhost/SystemFileSystem/Templates/Other/properties.properties to edit this template + +CTIncidentImportOptionsPanel.border.title=Local Settings +CTIncidentImportOptionsPanel.fileRepoPathLabel.text=Update the Cyber Triage Data Folder if you are not using the default location: +CTIncidentImportOptionsPanel.fileRepoPathField.text= +CTIncidentImportOptionsPanel.fileRepoBrowseButton.text=Browse +CTIncidentImportOptionsPanel.caseOpenWarningLabel.text=Some settings cannot be modified while a case is open. +CTIncidentImportOptionsPanel.fileRepoFileChooser.title=Cyber Triage Data Folder +CTIncidentImportOptionsPanel.border.title_1=Incident Importer +CTIncidentImportOptionsPanel.incidentTextLabel.text=The Cyber Triage Incident Import module allows you to open data collected by Cyber Triage in Autopsy. To use this feature you must install the Cyber Triage Import Module. +CTincidentImportOptionsPanel.instructionsTextLabel.text= +CTIncidentImportOptionsPanel.instructionsTextLabel.text=For instructions on obtaining the module refer to: diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties-MERGED b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties-MERGED new file mode 100644 index 0000000000..ebde860d0b --- /dev/null +++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties-MERGED @@ -0,0 +1,14 @@ + +# Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license +# Click nbfs://nbhost/SystemFileSystem/Templates/Other/properties.properties to edit this template + +CTIncidentImportOptionsPanel.border.title=Local Settings +CTIncidentImportOptionsPanel.fileRepoPathLabel.text=Update the Cyber Triage Data Folder if you are not using the default location: +CTIncidentImportOptionsPanel.fileRepoPathField.text= +CTIncidentImportOptionsPanel.fileRepoBrowseButton.text=Browse +CTIncidentImportOptionsPanel.caseOpenWarningLabel.text=Some settings cannot be modified while a case is open. +CTIncidentImportOptionsPanel.fileRepoFileChooser.title=Cyber Triage Data Folder +CTIncidentImportOptionsPanel.border.title_1=Incident Importer +CTIncidentImportOptionsPanel.incidentTextLabel.text=The Cyber Triage Incident Import module allows you to open data collected by Cyber Triage in Autopsy. To use this feature you must install the Cyber Triage Import Module. +CTincidentImportOptionsPanel.instructionsTextLabel.text= +CTIncidentImportOptionsPanel.instructionsTextLabel.text=For instructions on obtaining the module refer to: diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.form b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.form new file mode 100644 index 0000000000..d887a3765e --- /dev/null +++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.form @@ -0,0 +1,168 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.java new file mode 100644 index 0000000000..8a399c0f0f --- /dev/null +++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.java @@ -0,0 +1,287 @@ +/** ************************************************************************* + ** This data and information is proprietary to, and a valuable trade secret + ** of, Sleuth Kit Labs. It is given in confidence by Sleuth Kit Labs + ** and may only be used as permitted under the license agreement under which + ** it has been distributed, and in no other way. + ** + ** Copyright (c) 2023 Sleuth Kit Labs, LLC. All rights reserved + ** + ** The technical data and information provided herein are provided with + ** `limited rights', and the computer software provided herein is provided + ** with `restricted rights' as those terms are defined in DAR and ASPR + ** 7-104.9(a). + ************************************************************************** */ +package com.basistech.df.cybertriage.autopsy.incidentoptions; + +import com.basistech.df.cybertriage.autopsy.ctoptions.subpanel.CTOptionsSubPanel; +import java.awt.Desktop; +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Collections; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.JFileChooser; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import org.apache.commons.lang3.StringUtils; +import org.netbeans.spi.options.OptionsPanelController; +import org.openide.util.lookup.ServiceProvider; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.guiutils.JFileChooserFactory; + +/** + * Options panel for CyberTriage options for importing a CyberTriage incident + */ +@ServiceProvider(service = CTOptionsSubPanel.class) +public class CTIncidentImportOptionsPanel extends CTOptionsSubPanel { + + private static final Logger logger = Logger.getLogger(CTIncidentImportOptionsPanel.class.getName()); + + private static final String CT_IMPORTER_DOC_LINK = "https://docs.cybertriage.com/en/latest/chapters/integrations/autopsy.html"; + + private final JFileChooserFactory fileRepoChooserFactory = new JFileChooserFactory(); + private final CTSettingsPersistence ctPersistence = CTSettingsPersistence.getInstance(); + + private static String getHtmlLink(String url) { + return "" + url + ""; + } + + /** + * Creates new form CTIncidentImportOptionsPanel + */ + public CTIncidentImportOptionsPanel() { + initComponents(); + this.fileRepoPathField.getDocument().addDocumentListener(new DocumentListener() { + @Override + public void changedUpdate(DocumentEvent e) { + fireSettingsChanged(); + } + + @Override + public void insertUpdate(DocumentEvent e) { + fireSettingsChanged(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + fireSettingsChanged(); + } + }); + + Case.addEventTypeSubscriber(Collections.singleton(Case.Events.CURRENT_CASE), (evt) -> { + CTIncidentImportOptionsPanel.this.setEnabledItems(evt.getNewValue() != null); + }); + } + + private void setCTSettingsDisplay(CTSettings ctSettings) { + this.fileRepoPathField.setText(ctSettings.getFileRepoPath()); + } + + @Override + public synchronized void saveSettings() { + ctPersistence.saveCTSettings(getSettings()); + } + + @Override + public synchronized void loadSettings() { + CTSettings ctSettings = ctPersistence.loadCTSettings(); + setCTSettingsDisplay(ctSettings); + setEnabledItems(Case.isCaseOpen()); + } + + private void setEnabledItems(boolean caseOpen) { + this.caseOpenWarningLabel.setVisible(caseOpen); + this.fileRepoBrowseButton.setEnabled(!caseOpen); + this.fileRepoPathField.setEnabled(!caseOpen); + } + + private void fireSettingsChanged() { + this.firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); + } + + private CTSettings getSettings() { + return new CTSettings().setFileRepoPath(this.fileRepoPathField.getText()); + } + + @Override + public boolean valid() { + return new File(this.fileRepoPathField.getText()).isDirectory(); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + java.awt.GridBagConstraints gridBagConstraints; + + incidentTextPanel = new javax.swing.JPanel(); + incidentTextLabel = new javax.swing.JLabel(); + instructionsPanel = new javax.swing.JPanel(); + instructionsTextLabel = new javax.swing.JLabel(); + instructionsLinkLabel = new javax.swing.JLabel(); + repoPanel = new javax.swing.JPanel(); + javax.swing.JLabel fileRepoPathLabel = new javax.swing.JLabel(); + fileRepoPathField = new javax.swing.JTextField(); + fileRepoBrowseButton = new javax.swing.JButton(); + caseOpenWarningLabel = new javax.swing.JLabel(); + + setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(CTIncidentImportOptionsPanel.class, "CTIncidentImportOptionsPanel.border.title_1"))); // NOI18N + setLayout(new java.awt.GridBagLayout()); + + incidentTextPanel.setLayout(new java.awt.GridBagLayout()); + + org.openide.awt.Mnemonics.setLocalizedText(incidentTextLabel, org.openide.util.NbBundle.getMessage(CTIncidentImportOptionsPanel.class, "CTIncidentImportOptionsPanel.incidentTextLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); + incidentTextPanel.add(incidentTextLabel, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + add(incidentTextPanel, gridBagConstraints); + + instructionsPanel.setLayout(new java.awt.GridBagLayout()); + + org.openide.awt.Mnemonics.setLocalizedText(instructionsTextLabel, org.openide.util.NbBundle.getMessage(CTIncidentImportOptionsPanel.class, "CTIncidentImportOptionsPanel.instructionsTextLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 0); + instructionsPanel.add(instructionsTextLabel, gridBagConstraints); + instructionsTextLabel.getAccessibleContext().setAccessibleName("For instructions on obtaining the module refer to:"); + + org.openide.awt.Mnemonics.setLocalizedText(instructionsLinkLabel, getHtmlLink(CT_IMPORTER_DOC_LINK)); + instructionsLinkLabel.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent evt) { + instructionsLinkLabelMouseClicked(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); + instructionsPanel.add(instructionsLinkLabel, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + add(instructionsPanel, gridBagConstraints); + + repoPanel.setLayout(new java.awt.GridBagLayout()); + + org.openide.awt.Mnemonics.setLocalizedText(fileRepoPathLabel, org.openide.util.NbBundle.getMessage(CTIncidentImportOptionsPanel.class, "CTIncidentImportOptionsPanel.fileRepoPathLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); + repoPanel.add(fileRepoPathLabel, gridBagConstraints); + + fileRepoPathField.setText(org.openide.util.NbBundle.getMessage(CTIncidentImportOptionsPanel.class, "CTIncidentImportOptionsPanel.fileRepoPathField.text")); // NOI18N + fileRepoPathField.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + fileRepoPathFieldActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); + repoPanel.add(fileRepoPathField, gridBagConstraints); + fileRepoPathField.getAccessibleContext().setAccessibleName(""); + + org.openide.awt.Mnemonics.setLocalizedText(fileRepoBrowseButton, org.openide.util.NbBundle.getMessage(CTIncidentImportOptionsPanel.class, "CTIncidentImportOptionsPanel.fileRepoBrowseButton.text")); // NOI18N + fileRepoBrowseButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + fileRepoBrowseButtonActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); + repoPanel.add(fileRepoBrowseButton, gridBagConstraints); + + caseOpenWarningLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/modules/hashdatabase/warning16.png"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(caseOpenWarningLabel, org.openide.util.NbBundle.getMessage(CTIncidentImportOptionsPanel.class, "CTIncidentImportOptionsPanel.caseOpenWarningLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 2; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); + repoPanel.add(caseOpenWarningLabel, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + add(repoPanel, gridBagConstraints); + }// //GEN-END:initComponents + private void fileRepoBrowseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fileRepoBrowseButtonActionPerformed + JFileChooser fileChooser = fileRepoChooserFactory.getChooser(); + fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + fileChooser.setMultiSelectionEnabled(false); + + File curSelectedDir = StringUtils.isBlank(this.fileRepoPathField.getText()) ? null : new File(this.fileRepoPathField.getText()); + if (curSelectedDir == null || !curSelectedDir.isDirectory()) { + curSelectedDir = new File(CTSettings.getDefaultFileRepoPath()); + } + + fileChooser.setCurrentDirectory(curSelectedDir); + fileChooser.setDialogTitle(org.openide.util.NbBundle.getMessage(CTIncidentImportOptionsPanel.class, "CTIncidentImportOptionsPanel.fileRepoFileChooser.title")); + int retVal = fileChooser.showOpenDialog(this); + if (retVal == JFileChooser.APPROVE_OPTION) { + this.fileRepoPathField.setText(fileChooser.getSelectedFile().getAbsolutePath()); + } + }//GEN-LAST:event_fileRepoBrowseButtonActionPerformed + + private void fileRepoPathFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fileRepoPathFieldActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_fileRepoPathFieldActionPerformed + + private void instructionsLinkLabelMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_instructionsLinkLabelMouseClicked + gotoLink(CT_IMPORTER_DOC_LINK); + }//GEN-LAST:event_instructionsLinkLabelMouseClicked + + private void gotoLink(String url) { + if (Desktop.isDesktopSupported()) { + try { + Desktop.getDesktop().browse(new URI(url)); + } catch (IOException | URISyntaxException e) { + logger.log(Level.SEVERE, "Error opening link to: " + url, e); + } + } else { + logger.log(Level.WARNING, "Desktop API is not supported. Link cannot be opened."); + } + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel caseOpenWarningLabel; + private javax.swing.JButton fileRepoBrowseButton; + private javax.swing.JTextField fileRepoPathField; + private javax.swing.JLabel incidentTextLabel; + private javax.swing.JPanel incidentTextPanel; + private javax.swing.JLabel instructionsLinkLabel; + private javax.swing.JPanel instructionsPanel; + private javax.swing.JLabel instructionsTextLabel; + private javax.swing.JPanel repoPanel; + // End of variables declaration//GEN-END:variables +} diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettings.java b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettings.java new file mode 100644 index 0000000000..4e9d4b4697 --- /dev/null +++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettings.java @@ -0,0 +1,71 @@ +/** ************************************************************************* + ** This data and information is proprietary to, and a valuable trade secret + ** of, Sleuth Kit Labs. It is given in confidence by Sleuth Kit Labs + ** and may only be used as permitted under the license agreement under which + ** it has been distributed, and in no other way. + ** + ** Copyright (c) 2023 Sleuth Kit Labs, LLC. All rights reserved + ** + ** The technical data and information provided herein are provided with + ** `limited rights', and the computer software provided herein is provided + ** with `restricted rights' as those terms are defined in DAR and ASPR + ** 7-104.9(a). + ************************************************************************** */ +package com.basistech.df.cybertriage.autopsy.incidentoptions; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Objects; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.openide.modules.Places; + +/** + * CT settings that don't include license information. + */ +public class CTSettings { + + private static final String DEFAULT_FILE_REPO_PATH = getAppDataLocalDirectory(); + + // taken from com.basistech.df.cybertriage.utils.SystemProperties + private static String getAppDataLocalDirectory() { + + Logger LOGGER = java.util.logging.Logger.getLogger(CTSettings.class.getCanonicalName()); + if (Objects.nonNull(Places.getUserDirectory()) && Places.getUserDirectory().getAbsolutePath().endsWith("testuserdir")) { // APP is in testing .. this should return the test path + LOGGER.log(Level.INFO, "Application Data (test mode) Path: " + Places.getUserDirectory().getAbsolutePath()); + return Places.getUserDirectory().getAbsolutePath(); + } else { + Path localAppPath = Paths.get(System.getenv("LOCALAPPDATA"), "cybertriage"); + try { + Files.createDirectories(localAppPath); + LOGGER.log(Level.INFO, "Application Data Path: " + localAppPath.toString()); + return localAppPath.toString(); + } catch (IOException ex) { + LOGGER.log(Level.SEVERE, "IO Error, defaulting to user dir", ex); + return Places.getUserDirectory().getAbsolutePath(); // In case of an IO Error + } + } + } + + public static String getDefaultFileRepoPath() { + return DEFAULT_FILE_REPO_PATH; + } + + static CTSettings getDefaultSettings() { + return new CTSettings() + .setFileRepoPath(DEFAULT_FILE_REPO_PATH); + } + + private String fileRepoPath = DEFAULT_FILE_REPO_PATH; + + public String getFileRepoPath() { + return fileRepoPath; + } + + public CTSettings setFileRepoPath(String fileRepoPath) { + this.fileRepoPath = fileRepoPath; + return this; + } +} diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettingsPersistence.java b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettingsPersistence.java new file mode 100644 index 0000000000..d9addd1960 --- /dev/null +++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettingsPersistence.java @@ -0,0 +1,79 @@ +/** ************************************************************************* + ** This data and information is proprietary to, and a valuable trade secret + ** of, Sleuth Kit Labs. It is given in confidence by Sleuth Kit Labs + ** and may only be used as permitted under the license agreement under which + ** it has been distributed, and in no other way. + ** + ** Copyright (c) 2023 Sleuth Kit Labs, LLC. All rights reserved + ** + ** The technical data and information provided herein are provided with + ** `limited rights', and the computer software provided herein is provided + ** with `restricted rights' as those terms are defined in DAR and ASPR + ** 7-104.9(a). + ************************************************************************** */ +package com.basistech.df.cybertriage.autopsy.incidentoptions; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.File; +import java.io.IOException; +import java.nio.file.Paths; +import java.util.logging.Level; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.PlatformUtil; + +/** + * Handles persisting CT Settings. + */ +public class CTSettingsPersistence { + + private static final String CT_SETTINGS_DIR = "CyberTriage"; + private static final String CT_SETTINGS_FILENAME = "CyberTriageSettings.json"; + + private static final Logger logger = Logger.getLogger(CTSettingsPersistence.class.getName()); + + private static final CTSettingsPersistence instance = new CTSettingsPersistence(); + + private final ObjectMapper objectMapper = new ObjectMapper(); + + public static CTSettingsPersistence getInstance() { + return instance; + } + + public synchronized boolean saveCTSettings(CTSettings ctSettings) { + if (ctSettings != null) { + + File settingsFile = getCTSettingsFile(); + settingsFile.getParentFile().mkdirs(); + try { + objectMapper.writeValue(settingsFile, ctSettings); + return true; + } catch (IOException ex) { + logger.log(Level.WARNING, "There was an error writing CyberTriage settings to file: " + settingsFile.getAbsolutePath(), ex); + } + } + + return false; + } + + public synchronized CTSettings loadCTSettings() { + + CTSettings settings = null; + File settingsFile = getCTSettingsFile(); + if (settingsFile.isFile()) { + try { + settings = objectMapper.readValue(settingsFile, CTSettings.class); + } catch (IOException ex) { + logger.log(Level.WARNING, "There was an error reading CyberTriage settings to file: " + settingsFile.getAbsolutePath(), ex); + } + } + + return settings == null + ? CTSettings.getDefaultSettings() + : settings; + + } + + private File getCTSettingsFile() { + return Paths.get(PlatformUtil.getModuleConfigDirectory(), CT_SETTINGS_DIR, CT_SETTINGS_FILENAME).toFile(); + } +} From 4517a30887fd211b7fd0412487b7bb0d03a0e6b2 Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Tue, 15 Aug 2023 20:55:02 -0400 Subject: [PATCH 51/94] remove licenseDisclaimerPanel and point to prod server Remove licenseDisclaimerPanel Point to prod server instead of develop --- .../autopsy/ctapi/CTCloudHttpClient.java | 3 +- .../autopsy/ctoptions/CTOptionsPanel.java | 3 - .../ctoptions/LicenseDisclaimerPanel.form | 186 ----------------- .../ctoptions/LicenseDisclaimerPanel.java | 188 ------------------ 4 files changed, 1 insertion(+), 379 deletions(-) delete mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/LicenseDisclaimerPanel.form delete mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/LicenseDisclaimerPanel.java diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java index 44e94f82a1..0a280c87e8 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java @@ -84,8 +84,7 @@ import org.sleuthkit.autopsy.coreutils.Version; class CTCloudHttpClient { private static final Logger LOGGER = Logger.getLogger(CTCloudHttpClient.class.getName()); -// private static final String HOST_URL = Version.getBuildType() == Version.Type.RELEASE ? Constants.CT_CLOUD_SERVER : Constants.CT_CLOUD_DEV_SERVER; - private static final String HOST_URL = Version.getBuildType() == Version.Type.RELEASE ? Constants.CT_CLOUD_DEV_SERVER : Constants.CT_CLOUD_SERVER; + private static final String HOST_URL = Version.getBuildType() == Version.Type.RELEASE ? Constants.CT_CLOUD_SERVER : Constants.CT_CLOUD_DEV_SERVER; private static final String NB_PROXY_SELECTOR_NAME = "org.netbeans.core.NbProxySelector"; private static final int CONNECTION_TIMEOUT_MS = 58 * 1000; // milli sec diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/CTOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/CTOptionsPanel.java index c0999e3b9e..29f8bec3a4 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/CTOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/CTOptionsPanel.java @@ -24,7 +24,6 @@ import java.awt.GridBagConstraints; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.Collection; -import java.util.Comparator; import java.util.List; import java.util.logging.Logger; import java.util.stream.Collectors; @@ -78,8 +77,6 @@ public class CTOptionsPanel extends IngestModuleGlobalSettingsPanel { disclaimerConstraints.weighty = 0; disclaimerConstraints.weightx = 0; -// contentPane.add(disclaimerPanel, disclaimerConstraints); - for (int i = 0; i < subPanels.size(); i++) { CTOptionsSubPanel subPanel = subPanels.get(i); diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/LicenseDisclaimerPanel.form b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/LicenseDisclaimerPanel.form deleted file mode 100644 index a88404c592..0000000000 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/LicenseDisclaimerPanel.form +++ /dev/null @@ -1,186 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/LicenseDisclaimerPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/LicenseDisclaimerPanel.java deleted file mode 100644 index 328a252467..0000000000 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/LicenseDisclaimerPanel.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2023 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.basistech.df.cybertriage.autopsy.ctoptions; - -import java.awt.Desktop; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.logging.Level; -import org.sleuthkit.autopsy.coreutils.Logger; - -/** - * Disclaimer for license and place to purchase CT license. - */ -public class LicenseDisclaimerPanel extends javax.swing.JPanel { - - private static final Logger LOGGER = Logger.getLogger(LicenseDisclaimerPanel.class.getName()); - - private static final String TRIAL_URL = "https://cybertriage.com/autopsy-trial"; - private static final String PURCHASE_URL = "https://cybertriage.com/autopsy-checkout"; - - private static String getHtmlLink(String url) { - return "" + url + ""; - } - - /** - * Creates new form LicenseDisclaimerPanel - */ - public LicenseDisclaimerPanel() { - initComponents(); - } - - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - @SuppressWarnings("unchecked") - // //GEN-BEGIN:initComponents - private void initComponents() { - java.awt.GridBagConstraints gridBagConstraints; - - javax.swing.JLabel disclaimer = new javax.swing.JLabel(); - javax.swing.JPanel spacer = new javax.swing.JPanel(); - javax.swing.JPanel trialPanel = new javax.swing.JPanel(); - javax.swing.JLabel trialLabel = new javax.swing.JLabel(); - javax.swing.JLabel trialLink = new javax.swing.JLabel(); - javax.swing.JPanel purchasePanel = new javax.swing.JPanel(); - javax.swing.JLabel purchaseFromLabel = new javax.swing.JLabel(); - javax.swing.JLabel purchaseLink = new javax.swing.JLabel(); - - setBorder(javax.swing.BorderFactory.createTitledBorder(null, org.openide.util.NbBundle.getMessage(LicenseDisclaimerPanel.class, "LicenseDisclaimerPanel.border.title"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Segoe UI", 0, 12), new java.awt.Color(255, 0, 0))); // NOI18N - setMaximumSize(new java.awt.Dimension(2147483647, 108)); - setMinimumSize(new java.awt.Dimension(562, 108)); - setPreferredSize(new java.awt.Dimension(400, 108)); - setLayout(new java.awt.GridBagLayout()); - - org.openide.awt.Mnemonics.setLocalizedText(disclaimer, org.openide.util.NbBundle.getMessage(LicenseDisclaimerPanel.class, "LicenseDisclaimerPanel.disclaimer.text")); // NOI18N - disclaimer.setVerticalAlignment(javax.swing.SwingConstants.TOP); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); - add(disclaimer, gridBagConstraints); - - javax.swing.GroupLayout spacerLayout = new javax.swing.GroupLayout(spacer); - spacer.setLayout(spacerLayout); - spacerLayout.setHorizontalGroup( - spacerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 0, Short.MAX_VALUE) - ); - spacerLayout.setVerticalGroup( - spacerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 0, Short.MAX_VALUE) - ); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 3; - gridBagConstraints.weighty = 1.0; - add(spacer, gridBagConstraints); - - trialPanel.setLayout(new java.awt.GridBagLayout()); - - org.openide.awt.Mnemonics.setLocalizedText(trialLabel, org.openide.util.NbBundle.getMessage(LicenseDisclaimerPanel.class, "LicenseDisclaimerPanel.trialLabel.text")); // NOI18N - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - trialPanel.add(trialLabel, gridBagConstraints); - - org.openide.awt.Mnemonics.setLocalizedText(trialLink, getHtmlLink(TRIAL_URL)); - trialLink.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR)); - trialLink.addMouseListener(new java.awt.event.MouseAdapter() { - public void mouseClicked(java.awt.event.MouseEvent evt) { - trialLinkMouseClicked(evt); - } - }); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 0; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 0); - trialPanel.add(trialLink, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); - add(trialPanel, gridBagConstraints); - - purchasePanel.setLayout(new java.awt.GridBagLayout()); - - org.openide.awt.Mnemonics.setLocalizedText(purchaseFromLabel, org.openide.util.NbBundle.getMessage(LicenseDisclaimerPanel.class, "LicenseDisclaimerPanel.purchaseFromLabel.text")); // NOI18N - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - purchasePanel.add(purchaseFromLabel, gridBagConstraints); - - org.openide.awt.Mnemonics.setLocalizedText(purchaseLink, getHtmlLink(PURCHASE_URL)); - purchaseLink.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR)); - purchaseLink.addMouseListener(new java.awt.event.MouseAdapter() { - public void mouseClicked(java.awt.event.MouseEvent evt) { - purchaseLinkMouseClicked(evt); - } - }); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 0; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 0); - purchasePanel.add(purchaseLink, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 2; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); - add(purchasePanel, gridBagConstraints); - }// //GEN-END:initComponents - - private void purchaseLinkMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_purchaseLinkMouseClicked - gotoLink(PURCHASE_URL); - }//GEN-LAST:event_purchaseLinkMouseClicked - - private void trialLinkMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_trialLinkMouseClicked - gotoLink(TRIAL_URL); - }//GEN-LAST:event_trialLinkMouseClicked - - private void gotoLink(String url) { - if (Desktop.isDesktopSupported()) { - try { - Desktop.getDesktop().browse(new URI(url)); - } catch (IOException | URISyntaxException e) { - LOGGER.log(Level.SEVERE, "Error opening link to: " + url, e); - } - } else { - LOGGER.log(Level.WARNING, "Desktop API is not supported. Link cannot be opened."); - } - } - // Variables declaration - do not modify//GEN-BEGIN:variables - // End of variables declaration//GEN-END:variables -} From 8a7fb19decdc58c7fa90707b38844cb57b98326c Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Tue, 15 Aug 2023 21:02:16 -0400 Subject: [PATCH 52/94] Update URL for malware scanner Update URL for malware scanner --- .../autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java index 496e01d69f..cfc9057aa6 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java @@ -76,7 +76,7 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { private volatile String licenseInfoMessage = null; private volatile LicenseFetcher licenseFetcher = null; - private static final String PURCHASE_URL = "https://cybertriage.com/autopsy-checkout"; + private static final String PURCHASE_URL = "https://cybertriage.com/autopsy-malware-module"; private volatile AuthTokenResponse authTokenResponse = null; private volatile String authTokenMessage = null; From b8b608930aa89d7d0cb18ff48fa36c602ab60a42 Mon Sep 17 00:00:00 2001 From: "eugene.livis" Date: Thu, 17 Aug 2023 13:53:24 -0400 Subject: [PATCH 53/94] First cut --- .../autopsy/datamodel/Artifacts.java | 17 +- .../autopsy/datamodel/AutopsyItemVisitor.java | 7 + .../datamodel/DisplayableItemNodeVisitor.java | 7 + .../autopsy/datamodel/MalwareHits.java | 331 ++++++++++++++++++ 4 files changed, 361 insertions(+), 1 deletion(-) create mode 100755 Core/src/org/sleuthkit/autopsy/datamodel/MalwareHits.java diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java b/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java index 3dee283999..373c5b5fed 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java @@ -72,6 +72,9 @@ public class Artifacts { private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED); + + private static BlackboardArtifact.Type MALWARE_ARTIFACT_TYPE = null; + private static final String MALWARE_HITS = "TSK_MALWARE"; /** * Base class for a parent node of artifacts. @@ -242,6 +245,16 @@ public class Artifacts { */ @SuppressWarnings("deprecation") private static TypeNodeKey getTypeKey(BlackboardArtifact.Type type, SleuthkitCase skCase, long dsObjId) { + + // ELTODO + if (MALWARE_ARTIFACT_TYPE == null) { + try { + MALWARE_ARTIFACT_TYPE = skCase.getArtifactType(MALWARE_HITS); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Unable to get TSK_MALWARE artifact type from database : ", ex); //NON-NLS + } + } + int typeId = type.getTypeID(); if (TSK_EMAIL_MSG.getTypeID() == typeId) { EmailExtracted.RootNode emailNode = new EmailExtracted(skCase, dsObjId).new RootNode(); @@ -267,7 +280,9 @@ public class Artifacts { } else if (TSK_HASHSET_HIT.getTypeID() == typeId) { HashsetHits.RootNode hashsetHits = new HashsetHits(skCase, dsObjId).new RootNode(); return new TypeNodeKey(hashsetHits, TSK_HASHSET_HIT); - + } else if (MALWARE_ARTIFACT_TYPE != null && MALWARE_ARTIFACT_TYPE.getTypeID() == typeId) { + MalwareHits.RootNode malwareHits = new MalwareHits(skCase, dsObjId).new RootNode(); + return new TypeNodeKey(malwareHits, MALWARE_ARTIFACT_TYPE); } else { return new TypeNodeKey(type, dsObjId); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyItemVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyItemVisitor.java index d433d0d6df..5ebd7c4216 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyItemVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyItemVisitor.java @@ -60,6 +60,8 @@ public interface AutopsyItemVisitor { T visit(KeywordHits kh); T visit(HashsetHits hh); + + T visit(MalwareHits mh); T visit(EmailExtracted ee); @@ -169,6 +171,11 @@ public interface AutopsyItemVisitor { return defaultVisit(hh); } + @Override + public T visit(MalwareHits mh) { + return defaultVisit(mh); + } + @Override public T visit(InterestingHits ih) { return defaultVisit(ih); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java index 85e715382e..b80fa67d94 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java @@ -111,6 +111,8 @@ public interface DisplayableItemNodeVisitor { T visit(HashsetHits.RootNode hhrn); T visit(HashsetHits.HashsetNameNode hhsn); + + T visit(MalwareHits.RootNode mhrn); T visit(EmailExtracted.RootNode eern); @@ -431,6 +433,11 @@ public interface DisplayableItemNodeVisitor { return defaultVisit(hhsn); } + @Override + public T visit(MalwareHits.RootNode mhrn) { + return defaultVisit(mhrn); + } + @Override public T visit(InterestingHits.RootNode ihrn) { return defaultVisit(ihrn); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/MalwareHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/MalwareHits.java new file mode 100755 index 0000000000..6c3a9f74d6 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datamodel/MalwareHits.java @@ -0,0 +1,331 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2023 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.datamodel; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Observable; +import java.util.Observer; +import java.util.Set; +import java.util.logging.Level; +import org.openide.nodes.ChildFactory; +import org.openide.nodes.Children; +import org.openide.nodes.Node; +import org.openide.nodes.Sheet; +import org.openide.util.NbBundle; +import org.openide.util.WeakListeners; +import org.openide.util.lookup.Lookups; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.ingest.IngestManager; +import org.sleuthkit.autopsy.ingest.ModuleDataEvent; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery; +import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.autopsy.datamodel.Artifacts.UpdatableCountTypeNode; +import org.sleuthkit.datamodel.AnalysisResult; +import org.sleuthkit.datamodel.Score; + +/** + * Malware hits node support. Inner classes have all of the nodes in the tree. + */ +@NbBundle.Messages({ + "MalwareHits_malwareTypeDisplayName=Malware",}) +public class MalwareHits implements AutopsyVisitableItem { + + private static final String MALWARE_HITS = "TSK_MALWARE"; + private static BlackboardArtifact.Type MALWARE_ARTIFACT_TYPE = null; + private static final String DISPLAY_NAME = Bundle.MalwareHits_malwareTypeDisplayName(); // ELTODO get from database + private static final Logger logger = Logger.getLogger(MalwareHits.class.getName()); + private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED); + private static final Set INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestModuleEvent.DATA_ADDED); + private SleuthkitCase skCase; + private final MalwareResults malwareResults; + private final long filteringDSObjId; // 0 if not filtering/grouping by data source + + /** + * Constructor + * + * @param skCase Case DB + * + */ + public MalwareHits(SleuthkitCase skCase) { + this(skCase, 0); + } + + /** + * Constructor + * + * @param skCase Case DB + * @param objId Object id of the data source + * + */ + public MalwareHits(SleuthkitCase skCase, long objId) { + this.skCase = skCase; + this.filteringDSObjId = objId; + malwareResults = new MalwareResults(); + } + + @Override + public T accept(AutopsyItemVisitor visitor) { + return visitor.visit(this); + } + + /** + * Stores all of the malware results in a single class that is observable + * for the child nodes + */ + private class MalwareResults extends Observable { + + // list of artifacts + // NOTE: the list can be accessed by multiple worker threads and needs to be synchronized + private final Set malwareHits = new HashSet<>(); + + MalwareResults() { + update(); + } + + Set getArtifactIds() { + synchronized (malwareHits) { + return Collections.unmodifiableSet(malwareHits); + } + } + + @SuppressWarnings("deprecation") + final void update() { + synchronized (malwareHits) { + malwareHits.clear(); + } + + if (skCase == null) { + return; + } + + if (MALWARE_ARTIFACT_TYPE == null) { + try { + MALWARE_ARTIFACT_TYPE = skCase.getArtifactType(MALWARE_HITS); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Unable to get TSK_MALWARE artifact type from database : ", ex); //NON-NLS + return; + } + } + + String query = "SELECT blackboard_artifacts.artifact_obj_id " //NON-NLS + + "FROM blackboard_artifacts,tsk_analysis_results WHERE " //NON-NLS + + "blackboard_artifacts.artifact_type_id=" + MALWARE_ARTIFACT_TYPE.getTypeID() + + " AND tsk_analysis_results.artifact_obj_id=blackboard_artifacts.artifact_obj_id" //NON-NLS + + " AND (tsk_analysis_results.significance=" + Score.Significance.NOTABLE.getId() + + " OR tsk_analysis_results.significance=" + Score.Significance.LIKELY_NONE.getId() + " )"; // ELTODO LIKELY_NOTABLE + if (filteringDSObjId > 0) { + query += " AND blackboard_artifacts.data_source_obj_id = " + filteringDSObjId; + } + + try (CaseDbQuery dbQuery = skCase.executeQuery(query)) { + ResultSet resultSet = dbQuery.getResultSet(); + synchronized (malwareHits) { + while (resultSet.next()) { + long artifactObjId = resultSet.getLong("artifact_obj_id"); //NON-NLS + malwareHits.add(artifactObjId); + } + } + } catch (TskCoreException | SQLException ex) { + logger.log(Level.WARNING, "SQL Exception occurred: ", ex); //NON-NLS + } + + setChanged(); + notifyObservers(); + } + } + + /** + * Top-level node for all malware hits + */ + public class RootNode extends UpdatableCountTypeNode { + + public RootNode() { + super(Children.create(new HitFactory(DISPLAY_NAME), true), + Lookups.singleton(DISPLAY_NAME), + DISPLAY_NAME, + filteringDSObjId, + MALWARE_ARTIFACT_TYPE); + + super.setName(MALWARE_HITS); + //this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/hashset_hits.png"); // ELTODO + } + + @Override + public boolean isLeafTypeNode() { + return true; + } + + @Override + public T accept(DisplayableItemNodeVisitor visitor) { + return visitor.visit(this); + } + + @Override + protected Sheet createSheet() { + Sheet sheet = super.createSheet(); + Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES); + if (sheetSet == null) { + sheetSet = Sheet.createPropertiesSet(); + sheet.put(sheetSet); + } + + sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "MalwareHits.createSheet.name.name"), + NbBundle.getMessage(this.getClass(), "MalwareHits.createSheet.name.displayName"), + NbBundle.getMessage(this.getClass(), "MalwareHits.createSheet.name.desc"), + getName())); + + return sheet; + } + + @Override + public String getItemType() { + return getClass().getName(); + } + } + + /** + * Node for a hash set name + + public class HashsetNameNode extends DisplayableItemNode implements Observer { + + private final String hashSetName; + + public HashsetNameNode(String hashSetName) { + super(Children.create(new HitFactory(hashSetName), true), Lookups.singleton(hashSetName)); + super.setName(hashSetName); + this.hashSetName = hashSetName; + updateDisplayName(); + this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/hashset_hits.png"); // ELTODO + malwareResults.addObserver(this); + } + + // Update the count in the display name + private void updateDisplayName() { + super.setDisplayName(hashSetName + " (" + malwareResults.getArtifactIds(hashSetName).size() + ")"); + } + + @Override + public boolean isLeafTypeNode() { + return true; + } + + @Override + protected Sheet createSheet() { + Sheet sheet = super.createSheet(); + Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES); + if (sheetSet == null) { + sheetSet = Sheet.createPropertiesSet(); + sheet.put(sheetSet); + } + + sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "MalwareHits.createSheet.name.name"), + NbBundle.getMessage(this.getClass(), "MalwareHits.createSheet.name.displayName"), + NbBundle.getMessage(this.getClass(), "MalwareHits.createSheet.name.desc"), + getName())); + + return sheet; + } + + @Override + public T accept(DisplayableItemNodeVisitor visitor) { + return visitor.visit(this); + } + + @Override + public void update(Observable o, Object arg) { + updateDisplayName(); + } + + @Override + public String getItemType() { + // For custom settings for each hash set, return + *getClass().getName() + hashSetName instead. + return getClass().getName(); + } + }*/ + + /** + * Creates the nodes for the malware hits. + */ + private class HitFactory extends BaseChildFactory implements Observer { + + private final Map artifactHits = new HashMap<>(); + + private HitFactory(String nodeName) { + super(nodeName); + } + + @Override + protected void onAdd() { + malwareResults.addObserver(this); + } + + @Override + protected void onRemove() { + malwareResults.deleteObserver(this); + } + + @Override + protected Node createNodeForKey(AnalysisResult key) { + return new BlackboardArtifactNode(key); + } + + @Override + public void update(Observable o, Object arg) { + refresh(true); + } + + @Override + protected List makeKeys() { + if (skCase != null) { + + malwareResults.getArtifactIds().forEach((id) -> { + try { + if (!artifactHits.containsKey(id)) { + AnalysisResult art = skCase.getBlackboard().getAnalysisResultById(id); + //Cache attributes while we are off the EDT. + //See JIRA-5969 + art.getAttributes(); + artifactHits.put(id, art); + } + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "TSK Exception occurred", ex); //NON-NLS + } + }); + return new ArrayList<>(artifactHits.values()); + } + return Collections.emptyList(); + } + } +} From 739cbbdcddfa140a60b33951ecb04b0a0f67fe2d Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Thu, 17 Aug 2023 13:53:54 -0400 Subject: [PATCH 54/94] add ingest screen Remove global ingest option for uploads and add to ingest options panel. --- .../ctoptions/ctcloud/Bundle.properties | 2 - .../ctcloud/Bundle.properties-MERGED | 2 - .../ctcloud/CTMalwareScannerOptionsPanel.form | 43 ----- .../ctcloud/CTMalwareScannerOptionsPanel.java | 40 +---- .../autopsy/malwarescan/Bundle.properties | 7 + .../malwarescan/Bundle.properties-MERGED | 9 +- .../autopsy/malwarescan/Bundle_ar.properties | 1 + .../autopsy/malwarescan/Bundle_ja.properties | 1 + .../malwarescan/MalwareScanIngestModule.java | 20 ++- .../MalwareScanIngestModuleFactory.java | 25 ++- .../MalwareScanIngestSettings.java | 96 +++++++++++ .../MalwareScanIngestSettingsPanel.form | 123 +++++++++++++++ .../MalwareScanIngestSettingsPanel.java | 149 ++++++++++++++++++ 13 files changed, 422 insertions(+), 96 deletions(-) create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle_ar.properties create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle_ja.properties create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettings.java create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.form create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.java diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties index d0395d6a1a..bd06716288 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties @@ -24,5 +24,3 @@ CTMalwareScannerOptionsPanel.licenseInfoUserLabel.text= EULADialog.cancelButton.text=Cancel EULADialog.acceptButton.text=Accept EULADialog.title=Cyber Triage End User License Agreement -CTMalwareScannerOptionsPanel.fileUploadCheckbox.text=Upload file if hash lookup produces no results -CTMalwareScannerOptionsPanel.fileUploadPanel.border.title=File Upload diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED index 18e60839f3..ccd4780aae 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED @@ -62,5 +62,3 @@ CTOPtionsPanel_loadMalwareScansInfo_loading=Loading... EULADialog.cancelButton.text=Cancel EULADialog.acceptButton.text=Accept EULADialog.title=Cyber Triage End User License Agreement -CTMalwareScannerOptionsPanel.fileUploadCheckbox.text=Upload file if hash lookup produces no results -CTMalwareScannerOptionsPanel.fileUploadPanel.border.title=File Upload diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form index 8557f946d9..407f55844a 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form @@ -16,49 +16,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java index 2a09c1ed55..1abd64b2d9 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java @@ -141,15 +141,13 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { } private MalwareIngestSettings getIngestSettings() { - return new MalwareIngestSettings() - .setUploadFiles(this.fileUploadCheckbox.isSelected()); + return new MalwareIngestSettings(); } private void setIngestSettings(MalwareIngestSettings ingestSettings) { if (ingestSettings == null) { ingestSettings = new MalwareIngestSettings(); } - this.fileUploadCheckbox.setSelected(ingestSettings.isUploadFiles()); } private synchronized void setLicenseDisplay(LicenseInfo licenseInfo, String licenseMessage) { @@ -220,8 +218,6 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { private void initComponents() { java.awt.GridBagConstraints gridBagConstraints; - javax.swing.JPanel fileUploadPanel = new javax.swing.JPanel(); - fileUploadCheckbox = new javax.swing.JCheckBox(); javax.swing.JPanel licenseInfoPanel = new javax.swing.JPanel(); licenseInfoMessageLabel = new javax.swing.JLabel(); licenseInfoUserLabel = new javax.swing.JLabel(); @@ -238,35 +234,6 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { setLayout(new java.awt.GridBagLayout()); - fileUploadPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.fileUploadPanel.border.title"))); // NOI18N - fileUploadPanel.setLayout(new java.awt.GridBagLayout()); - - fileUploadCheckbox.setSelected(true); - org.openide.awt.Mnemonics.setLocalizedText(fileUploadCheckbox, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.fileUploadCheckbox.text")); // NOI18N - fileUploadCheckbox.setMaximumSize(new java.awt.Dimension(32767, 20)); - fileUploadCheckbox.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - fileUploadCheckboxActionPerformed(evt); - } - }); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); - fileUploadPanel.add(fileUploadCheckbox, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.weightx = 1.0; - add(fileUploadPanel, gridBagConstraints); - licenseInfoPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.licenseInfoPanel.border.title"))); // NOI18N licenseInfoPanel.setLayout(new java.awt.GridBagLayout()); @@ -427,10 +394,6 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { } }//GEN-LAST:event_licenseInfoAddButtonActionPerformed - private void fileUploadCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fileUploadCheckboxActionPerformed - this.firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - }//GEN-LAST:event_fileUploadCheckboxActionPerformed - @NbBundle.Messages({ "# {0} - userName", "# {1} - email", @@ -691,7 +654,6 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel countersResetLabel; - private javax.swing.JCheckBox fileUploadCheckbox; private javax.swing.JLabel fileUploadsRemainingLabel; private javax.swing.JLabel hashLookupsRemainingLabel; private javax.swing.JButton licenseInfoAddButton; diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties new file mode 100644 index 0000000000..e9fdcb1cb5 --- /dev/null +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties @@ -0,0 +1,7 @@ +MalwareScanIngestSettingsPanel.uploadFilesCheckbox.AccessibleContext.accessibleName=Upload file content for files that do not have results +MalwareScanIngestSettingsPanel.uploadFilesCheckbox.label=Upload file content for files that do not have results +MalwareScanIngestSettingsPanel.uploadFilesCheckbox.text=Upload file content for files that do not have results +DataSourceIntegrityIngestSettingsPanel.queryFilesTextArea.text=Query file existing results using file\u2019s hash +MalwareScanIngestSettingsPanel.ingestSettingsLabel.text=Ingest Settings +MalwareScanIngestSettingsPanel.paidLicenseTextArea.text=This module requires a paid license. \nSee the Global Options panel for details +MalwareScanIngestSettingsPanel.queryFilesCheckbox.text=Query for existing results using file\u2019s hash diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED index 4380a9607c..3b886d02cb 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED @@ -38,6 +38,13 @@ MalwareScanIngestModule_uploadFile_noRemainingFileUploads_title=No Remaining Fil # {0} - objectId MalwareScanIngestModule_uploadFile_notUploadable_desc=A file did not meet requirements for upload (object id: {0}). MalwareScanIngestModule_uploadFile_notUploadable_title=Not Able to Upload -MalwareScanIngestModuleFactory_description=The malware scan ingest module queries the Cyber Triage cloud API for any possible malicious executables. +MalwareScanIngestModuleFactory_description=Identifies executable files with malware. MalwareScanIngestModuleFactory_displayName=Cyber Triage Malware Scanner MalwareScanIngestModuleFactory_version=1.0.0 +MalwareScanIngestSettingsPanel.uploadFilesCheckbox.AccessibleContext.accessibleName=Upload file content for files that do not have results +MalwareScanIngestSettingsPanel.uploadFilesCheckbox.label=Upload file content for files that do not have results +MalwareScanIngestSettingsPanel.uploadFilesCheckbox.text=Upload file content for files that do not have results +DataSourceIntegrityIngestSettingsPanel.queryFilesTextArea.text=Query file existing results using file\u2019s hash +MalwareScanIngestSettingsPanel.ingestSettingsLabel.text=Ingest Settings +MalwareScanIngestSettingsPanel.paidLicenseTextArea.text=This module requires a paid license. \nSee the Global Options panel for details +MalwareScanIngestSettingsPanel.queryFilesCheckbox.text=Query for existing results using file\u2019s hash diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle_ar.properties b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle_ar.properties new file mode 100644 index 0000000000..7a6ad43a3e --- /dev/null +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle_ar.properties @@ -0,0 +1 @@ +MalwareScanIngestSettingsPanel.ingestSettingsLabel.text=Configuracion de Ingesta diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle_ja.properties b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle_ja.properties new file mode 100644 index 0000000000..cff7aa2e8d --- /dev/null +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle_ja.properties @@ -0,0 +1 @@ +MalwareScanIngestSettingsPanel.ingestSettingsLabel.text=\u53d6\u8fbc\u307f\u8a2d\u5b9a diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java index c52e72a350..190b1412ce 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java @@ -72,10 +72,17 @@ import org.sleuthkit.datamodel.TskData; class MalwareScanIngestModule implements FileIngestModule { private static final SharedProcessing sharedProcessing = new SharedProcessing(); - + private boolean uploadFiles; + private boolean queryFiles; + + MalwareScanIngestModule(MalwareScanIngestSettings settings) { + uploadFiles = settings.shouldUploadFiles(); + queryFiles = settings.shouldQueryFiles(); + } + @Override public void startUp(IngestJobContext context) throws IngestModuleException { - sharedProcessing.startUp(context); + sharedProcessing.startUp(context, uploadFiles); } @Override @@ -123,7 +130,7 @@ class MalwareScanIngestModule implements FileIngestModule { "application/msdos-windows",//NON-NLS "application/x-msdos-program"//NON-NLS ).collect(Collectors.toSet()); - + private static final String MALWARE_TYPE_NAME = "TSK_MALWARE"; private static final String MALWARE_CONFIG = "Cyber Triage Cloud"; @@ -153,14 +160,14 @@ class MalwareScanIngestModule implements FileIngestModule { "MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_title=File Uploads Limit Low", "# {0} - remainingUploads", "MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_desc=This license only has {0} file uploads remaining.",}) - synchronized void startUp(IngestJobContext context) throws IngestModuleException { + synchronized void startUp(IngestJobContext context, boolean uploadFiles) throws IngestModuleException { // only run this code once per startup if (ingestJobState != null) { return; } try { - ingestJobState = getNewJobState(context); + ingestJobState = getNewJobState(context, uploadFiles); } catch (Exception ex) { ingestJobState = IngestJobState.DISABLED; throw new IngestModuleException("An exception occurred on MalwareScanIngestModule startup", ex); @@ -175,7 +182,7 @@ class MalwareScanIngestModule implements FileIngestModule { * parameters required for the job. * @throws Exception */ - private IngestJobState getNewJobState(IngestJobContext context) throws Exception { + private IngestJobState getNewJobState(IngestJobContext context, boolean uploadFiles) throws Exception { // get saved license Optional licenseInfoOpt = ctSettingsPersistence.loadLicenseInfo(); if (licenseInfoOpt.isEmpty() || licenseInfoOpt.get().getDecryptedLicense() == null) { @@ -207,7 +214,6 @@ class MalwareScanIngestModule implements FileIngestModule { } // determine lookups remaining - boolean uploadFiles = ctSettingsPersistence.loadMalwareIngestSettings().isUploadFiles(); if (uploadFiles) { long uploadsRemaining = remaining(authTokenResponse.getFileUploadLimit(), authTokenResponse.getFileUploadCount()); if (uploadsRemaining <= 0) { diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModuleFactory.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModuleFactory.java index e138116036..83cb93f689 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModuleFactory.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModuleFactory.java @@ -25,6 +25,8 @@ import org.sleuthkit.autopsy.ingest.FileIngestModule; import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter; import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel; import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; +import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel; +import org.sleuthkit.autopsy.ingest.NoIngestModuleIngestJobSettings; /** * Factory for malware scan ingest modules. @@ -32,7 +34,7 @@ import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; @ServiceProvider(service = org.sleuthkit.autopsy.ingest.IngestModuleFactory.class) @Messages({ "MalwareScanIngestModuleFactory_displayName=Cyber Triage Malware Scanner", - "MalwareScanIngestModuleFactory_description=The malware scan ingest module queries the Cyber Triage cloud API for any possible malicious executables.", + "MalwareScanIngestModuleFactory_description=Identifies executable files with malware.", "MalwareScanIngestModuleFactory_version=1.0.0" }) public class MalwareScanIngestModuleFactory extends IngestModuleFactoryAdapter { @@ -66,7 +68,7 @@ public class MalwareScanIngestModuleFactory extends IngestModuleFactoryAdapter { @Override public FileIngestModule createFileIngestModule(IngestModuleIngestJobSettings ingestOptions) { - return new MalwareScanIngestModule(); + return new MalwareScanIngestModule((MalwareScanIngestSettings) ingestOptions); } @Override @@ -81,4 +83,23 @@ public class MalwareScanIngestModuleFactory extends IngestModuleFactoryAdapter { return optionsPanel; } + @Override + public boolean hasIngestJobSettingsPanel() { + return true; + } + + @Override + public IngestModuleIngestJobSettingsPanel getIngestJobSettingsPanel(IngestModuleIngestJobSettings settings) { + if (settings instanceof MalwareScanIngestSettings) { + return new MalwareScanIngestSettingsPanel((MalwareScanIngestSettings) settings); + } + /* + * Compatibility check for older versions. + */ + if (settings instanceof NoIngestModuleIngestJobSettings) { + return new MalwareScanIngestSettingsPanel(new MalwareScanIngestSettings()); + } + + throw new IllegalArgumentException("Expected settings argument to be an instance of IngestSettings"); + } } diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettings.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettings.java new file mode 100644 index 0000000000..158e967745 --- /dev/null +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettings.java @@ -0,0 +1,96 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2023 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.basistech.df.cybertriage.autopsy.malwarescan; + +import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; + +/** + * Ingest job settings for the Malware scanner module. + */ +final class MalwareScanIngestSettings implements IngestModuleIngestJobSettings { + + private static final long serialVersionUID = 1L; + + private static final boolean DEFAULT_QUERY_FILES = true; + private static final boolean DEFAULT_UPLOAD_FILES = true; + + public boolean queryFiles; + public boolean uploadFiles; + + /** + * Instantiate the ingest job settings with default values. + */ + MalwareScanIngestSettings() { + this.queryFiles = DEFAULT_QUERY_FILES; + this.uploadFiles = DEFAULT_UPLOAD_FILES; + } + + /** + * Instantiate the ingest job settings. + * + * @param computeHashes Compute hashes if none are present + * @param verifyHashes Verify hashes if any are present + */ + MalwareScanIngestSettings(boolean queryFiles, boolean uploadFiles) { + this.queryFiles = queryFiles; + this.uploadFiles = uploadFiles; + } + + @Override + public long getVersionNumber() { + return serialVersionUID; + } + + /** + * Should files be queried? + * + * @return true if files should be queried, false otherwise + */ + public boolean shouldQueryFiles() { + return queryFiles; + } + + /** + * Set whether files should be queried. + * + * @param queryFiles true if files should be queried + */ + void setqueryFiles(boolean queryFiles) { + this.queryFiles = queryFiles; + } + + + /** + * Should files be uploaded? + * + * @return true if files should be uploaded, false otherwise + */ + public boolean shouldUploadFiles() { + return uploadFiles; + } + + /** + * Set whether files should be uploaded. + * + * @param uploadFiles true if files should be uploaded + */ + void setUploadFiles(boolean uploadFiles) { + this.uploadFiles = uploadFiles; + } +} diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.form b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.form new file mode 100644 index 0000000000..46a928c98e --- /dev/null +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.form @@ -0,0 +1,123 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.java new file mode 100644 index 0000000000..a418de0f83 --- /dev/null +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.java @@ -0,0 +1,149 @@ +/* + * Autopsy Browser + * + * Copyright 2023 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.basistech.df.cybertriage.autopsy.malwarescan; + +import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseInfo; +import com.basistech.df.cybertriage.autopsy.ctoptions.ctcloud.CTLicensePersistence; +import java.util.Optional; +import org.sleuthkit.autopsy.modules.dataSourceIntegrity.*; +import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; +import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel; + +/** + * Ingest job settings panel for the Malware scanner ingest. + */ +@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives +final class MalwareScanIngestSettingsPanel extends IngestModuleIngestJobSettingsPanel { + + private final CTLicensePersistence ctPersistence = CTLicensePersistence.getInstance(); + + MalwareScanIngestSettingsPanel(MalwareScanIngestSettings settings) { + initComponents(); + customizeComponents(settings); + } + + /** + * Update components with values from the ingest job settings. + * + * @param settings The ingest job settings. + */ + private void customizeComponents(MalwareScanIngestSettings settings) { + Optional licenseInfoOpt = ctPersistence.loadLicenseInfo(); + LicenseInfo licenseInfo = licenseInfoOpt.orElse(null); + if (licenseInfo != null) { + this.paidLicenseTextArea.setVisible(false); + this.queryFilesCheckbox.setVisible(true); + this.queryFilesCheckbox.setEnabled(false); + this.uploadFilesCheckbox.setVisible(true); + this.queryFilesCheckbox.setSelected(true); + this.uploadFilesCheckbox.setSelected(settings.shouldUploadFiles()); + } else { + this.paidLicenseTextArea.setVisible(true); + this.queryFilesCheckbox.setVisible(false); + this.uploadFilesCheckbox.setVisible(false); + } + } + + @Override + public IngestModuleIngestJobSettings getSettings() { + return new MalwareScanIngestSettings(queryFilesCheckbox.isSelected(), uploadFilesCheckbox.isSelected()); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + queryFilesCheckbox = new javax.swing.JCheckBox(); + uploadFilesCheckbox = new javax.swing.JCheckBox(); + ingestSettingsLabel = new javax.swing.JLabel(); + paidLicenseTextArea = new javax.swing.JTextArea(); + + setPreferredSize(new java.awt.Dimension(300, 155)); + + queryFilesCheckbox.setSelected(true); + org.openide.awt.Mnemonics.setLocalizedText(queryFilesCheckbox, org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.queryFilesCheckbox.text")); // NOI18N + queryFilesCheckbox.setEnabled(false); + + org.openide.awt.Mnemonics.setLocalizedText(uploadFilesCheckbox, org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.uploadFilesCheckbox.text")); // NOI18N + uploadFilesCheckbox.setFocusable(false); + uploadFilesCheckbox.setLabel(org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.uploadFilesCheckbox.label")); // NOI18N + + ingestSettingsLabel.setFont(ingestSettingsLabel.getFont().deriveFont(ingestSettingsLabel.getFont().getStyle() | java.awt.Font.BOLD)); + org.openide.awt.Mnemonics.setLocalizedText(ingestSettingsLabel, org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.ingestSettingsLabel.text")); // NOI18N + + paidLicenseTextArea.setColumns(20); + paidLicenseTextArea.setFont(new java.awt.Font("Segoe UI", 1, 12)); // NOI18N + paidLicenseTextArea.setRows(5); + paidLicenseTextArea.setText(org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.paidLicenseTextArea.text")); // NOI18N + paidLicenseTextArea.setWrapStyleWord(true); + paidLicenseTextArea.setBorder(null); + paidLicenseTextArea.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR)); + paidLicenseTextArea.setFocusable(false); + paidLicenseTextArea.setOpaque(false); + paidLicenseTextArea.setRequestFocusEnabled(false); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(6, 6, 6) + .addComponent(ingestSettingsLabel)) + .addGroup(layout.createSequentialGroup() + .addGap(6, 6, 6) + .addComponent(uploadFilesCheckbox)) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(queryFilesCheckbox)) + .addGroup(layout.createSequentialGroup() + .addGap(5, 5, 5) + .addComponent(paidLicenseTextArea, javax.swing.GroupLayout.PREFERRED_SIZE, 243, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addGap(185, 185, 185)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(ingestSettingsLabel) + .addGap(18, 18, 18) + .addComponent(queryFilesCheckbox) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(uploadFilesCheckbox) + .addGap(18, 18, 18) + .addComponent(paidLicenseTextArea, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)) + ); + + uploadFilesCheckbox.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.uploadFilesCheckbox.AccessibleContext.accessibleName")); // NOI18N + }// //GEN-END:initComponents + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel ingestSettingsLabel; + private javax.swing.JTextArea paidLicenseTextArea; + private javax.swing.JCheckBox queryFilesCheckbox; + private javax.swing.JCheckBox uploadFilesCheckbox; + // End of variables declaration//GEN-END:variables + +} From 0dfa1fb93aafad98792f0a5149885a037c9e04bd Mon Sep 17 00:00:00 2001 From: "eugene.livis" Date: Thu, 17 Aug 2023 15:12:30 -0400 Subject: [PATCH 55/94] Mostly works --- .../autopsy/datamodel/Artifacts.java | 2 +- .../autopsy/datamodel/MalwareHits.java | 163 ++++++++++-------- 2 files changed, 95 insertions(+), 70 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java b/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java index 373c5b5fed..57db059411 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java @@ -246,7 +246,7 @@ public class Artifacts { @SuppressWarnings("deprecation") private static TypeNodeKey getTypeKey(BlackboardArtifact.Type type, SleuthkitCase skCase, long dsObjId) { - // ELTODO + // Get the custom TSK_MALWARE artifact type from case database if (MALWARE_ARTIFACT_TYPE == null) { try { MALWARE_ARTIFACT_TYPE = skCase.getArtifactType(MALWARE_HITS); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/MalwareHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/MalwareHits.java index 6c3a9f74d6..784da11ba5 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/MalwareHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/MalwareHits.java @@ -27,14 +27,12 @@ import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Observable; import java.util.Observer; import java.util.Set; import java.util.logging.Level; -import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.nodes.Sheet; @@ -57,13 +55,11 @@ import org.sleuthkit.datamodel.Score; /** * Malware hits node support. Inner classes have all of the nodes in the tree. */ -@NbBundle.Messages({ - "MalwareHits_malwareTypeDisplayName=Malware",}) public class MalwareHits implements AutopsyVisitableItem { private static final String MALWARE_HITS = "TSK_MALWARE"; private static BlackboardArtifact.Type MALWARE_ARTIFACT_TYPE = null; - private static final String DISPLAY_NAME = Bundle.MalwareHits_malwareTypeDisplayName(); // ELTODO get from database + private static String DISPLAY_NAME; private static final Logger logger = Logger.getLogger(MalwareHits.class.getName()); private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED); private static final Set INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestModuleEvent.DATA_ADDED); @@ -103,13 +99,14 @@ public class MalwareHits implements AutopsyVisitableItem { * Stores all of the malware results in a single class that is observable * for the child nodes */ - private class MalwareResults extends Observable { + private class MalwareResults extends Observable implements Observer { // list of artifacts // NOTE: the list can be accessed by multiple worker threads and needs to be synchronized private final Set malwareHits = new HashSet<>(); MalwareResults() { + addNotify(); update(); } @@ -128,16 +125,18 @@ public class MalwareHits implements AutopsyVisitableItem { if (skCase == null) { return; } - + + // Get the custom TSK_MALWARE artifact type from case database if (MALWARE_ARTIFACT_TYPE == null) { try { MALWARE_ARTIFACT_TYPE = skCase.getArtifactType(MALWARE_HITS); + DISPLAY_NAME = MALWARE_ARTIFACT_TYPE.getDisplayName(); } catch (TskCoreException ex) { logger.log(Level.WARNING, "Unable to get TSK_MALWARE artifact type from database : ", ex); //NON-NLS return; } } - + String query = "SELECT blackboard_artifacts.artifact_obj_id " //NON-NLS + "FROM blackboard_artifacts,tsk_analysis_results WHERE " //NON-NLS + "blackboard_artifacts.artifact_type_id=" + MALWARE_ARTIFACT_TYPE.getTypeID() @@ -163,6 +162,84 @@ public class MalwareHits implements AutopsyVisitableItem { setChanged(); notifyObservers(); } + + private final PropertyChangeListener pcl = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + String eventType = evt.getPropertyName(); + if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) { + /** + * Checking for a current case is a stop gap measure until a + * different way of handling the closing of cases is worked + * out. Currently, remote events may be received for a case + * that is already closed. + */ + try { + Case.getCurrentCaseThrows(); + /** + * Due to some unresolved issues with how cases are + * closed, it is possible for the event to have a null + * oldValue if the event is a remote event. + */ + ModuleDataEvent eventData = (ModuleDataEvent) evt.getOldValue(); + if (null != eventData && eventData.getBlackboardArtifactType().getTypeID() == MALWARE_ARTIFACT_TYPE.getTypeID()) { + malwareResults.update(); + } + } catch (NoCurrentCaseException notUsed) { + /** + * Case is closed, do nothing. + */ + } + } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) + || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { + /** + * Checking for a current case is a stop gap measure until a + * different way of handling the closing of cases is worked + * out. Currently, remote events may be received for a case + * that is already closed. + */ + try { + Case.getCurrentCaseThrows(); + malwareResults.update(); + } catch (NoCurrentCaseException notUsed) { + /** + * Case is closed, do nothing. + */ + } + } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) { + // case was closed. Remove listeners so that we don't get called with a stale case handle + if (evt.getNewValue() == null) { + removeNotify(); + skCase = null; + } + } + } + }; + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); + + protected void addNotify() { + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl); + Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); + } + + protected void removeNotify() { + IngestManager.getInstance().removeIngestJobEventListener(weakPcl); + IngestManager.getInstance().removeIngestModuleEventListener(weakPcl); + Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + removeNotify(); + } + + @Override + public void update(Observable o, Object arg) { + update(); + } } /** @@ -212,69 +289,17 @@ public class MalwareHits implements AutopsyVisitableItem { public String getItemType() { return getClass().getName(); } + + /** + * When this method is called, the count to be displayed will be + * updated. + */ + @Override + void updateDisplayName() { + super.setDisplayName(DISPLAY_NAME + " (" + malwareResults.getArtifactIds().size() + ")"); + } } - /** - * Node for a hash set name - - public class HashsetNameNode extends DisplayableItemNode implements Observer { - - private final String hashSetName; - - public HashsetNameNode(String hashSetName) { - super(Children.create(new HitFactory(hashSetName), true), Lookups.singleton(hashSetName)); - super.setName(hashSetName); - this.hashSetName = hashSetName; - updateDisplayName(); - this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/hashset_hits.png"); // ELTODO - malwareResults.addObserver(this); - } - - // Update the count in the display name - private void updateDisplayName() { - super.setDisplayName(hashSetName + " (" + malwareResults.getArtifactIds(hashSetName).size() + ")"); - } - - @Override - public boolean isLeafTypeNode() { - return true; - } - - @Override - protected Sheet createSheet() { - Sheet sheet = super.createSheet(); - Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES); - if (sheetSet == null) { - sheetSet = Sheet.createPropertiesSet(); - sheet.put(sheetSet); - } - - sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "MalwareHits.createSheet.name.name"), - NbBundle.getMessage(this.getClass(), "MalwareHits.createSheet.name.displayName"), - NbBundle.getMessage(this.getClass(), "MalwareHits.createSheet.name.desc"), - getName())); - - return sheet; - } - - @Override - public T accept(DisplayableItemNodeVisitor visitor) { - return visitor.visit(this); - } - - @Override - public void update(Observable o, Object arg) { - updateDisplayName(); - } - - @Override - public String getItemType() { - // For custom settings for each hash set, return - *getClass().getName() + hashSetName instead. - return getClass().getName(); - } - }*/ - /** * Creates the nodes for the malware hits. */ From 47ce334b4c1bf2437814eb5c0f0c185914e7ea72 Mon Sep 17 00:00:00 2001 From: "eugene.livis" Date: Thu, 17 Aug 2023 15:22:27 -0400 Subject: [PATCH 56/94] Polishing --- .../src/org/sleuthkit/autopsy/datamodel/Artifacts.java | 1 + .../org/sleuthkit/autopsy/datamodel/MalwareHits.java | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java b/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java index 57db059411..ded4c9cbed 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java @@ -73,6 +73,7 @@ public class Artifacts { private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED); + // this is currently a custom TSK artifact type, created in MalwareScanIngestModule private static BlackboardArtifact.Type MALWARE_ARTIFACT_TYPE = null; private static final String MALWARE_HITS = "TSK_MALWARE"; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/MalwareHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/MalwareHits.java index 784da11ba5..b0f48495c3 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/MalwareHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/MalwareHits.java @@ -57,7 +57,7 @@ import org.sleuthkit.datamodel.Score; */ public class MalwareHits implements AutopsyVisitableItem { - private static final String MALWARE_HITS = "TSK_MALWARE"; + private static final String MALWARE_HITS = "TSK_MALWARE"; // this is currently a custom TSK artifact type, created in MalwareScanIngestModule private static BlackboardArtifact.Type MALWARE_ARTIFACT_TYPE = null; private static String DISPLAY_NAME; private static final Logger logger = Logger.getLogger(MalwareHits.class.getName()); @@ -139,12 +139,12 @@ public class MalwareHits implements AutopsyVisitableItem { String query = "SELECT blackboard_artifacts.artifact_obj_id " //NON-NLS + "FROM blackboard_artifacts,tsk_analysis_results WHERE " //NON-NLS - + "blackboard_artifacts.artifact_type_id=" + MALWARE_ARTIFACT_TYPE.getTypeID() + + "blackboard_artifacts.artifact_type_id=" + MALWARE_ARTIFACT_TYPE.getTypeID() //NON-NLS + " AND tsk_analysis_results.artifact_obj_id=blackboard_artifacts.artifact_obj_id" //NON-NLS - + " AND (tsk_analysis_results.significance=" + Score.Significance.NOTABLE.getId() - + " OR tsk_analysis_results.significance=" + Score.Significance.LIKELY_NONE.getId() + " )"; // ELTODO LIKELY_NOTABLE + + " AND (tsk_analysis_results.significance=" + Score.Significance.NOTABLE.getId() //NON-NLS + + " OR tsk_analysis_results.significance=" + Score.Significance.LIKELY_NOTABLE.getId() + " )"; //NON-NLS if (filteringDSObjId > 0) { - query += " AND blackboard_artifacts.data_source_obj_id = " + filteringDSObjId; + query += " AND blackboard_artifacts.data_source_obj_id = " + filteringDSObjId; //NON-NLS } try (CaseDbQuery dbQuery = skCase.executeQuery(query)) { From 8ba3f2740b18d002d5370960682a310716a36fd9 Mon Sep 17 00:00:00 2001 From: "eugene.livis" Date: Thu, 17 Aug 2023 16:52:05 -0400 Subject: [PATCH 57/94] Bug fixes during ingest --- .../autopsy/malwarescan/MalwareScanIngestModule.java | 8 ++++++-- Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java | 2 +- Core/src/org/sleuthkit/autopsy/datamodel/MalwareHits.java | 3 ++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java index c52e72a350..4698392478 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java @@ -775,7 +775,11 @@ class MalwareScanIngestModule implements FileIngestModule { for (Long objId : objIds) { AnalysisResult res = createAnalysisResult(ingestJobState, trans, result, objId); if (res != null) { - createdArtifacts.add(res); + // only post results that have score NOTABLE or LIKELY_NOTABLE + Score score = res.getScore(); + if (score.getSignificance() == Score.Significance.NOTABLE || score.getSignificance() == Score.Significance.LIKELY_NOTABLE) { + createdArtifacts.add(res); + } } } } @@ -837,7 +841,7 @@ class MalwareScanIngestModule implements FileIngestModule { : Bundle.MalwareScanIngestModule_SharedProcessing_createAnalysisResult_No(); String justification = cloudBean.getMalwareResult().getStatusDescription(); - + return ingestJobState.getTskCase().getBlackboard().newAnalysisResult( ingestJobState.getMalwareType(), objId, diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java b/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java index ded4c9cbed..a38383c183 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2021 Basis Technology Corp. + * Copyright 2011-2023 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/MalwareHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/MalwareHits.java index b0f48495c3..c1761a7ad5 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/MalwareHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/MalwareHits.java @@ -255,7 +255,8 @@ public class MalwareHits implements AutopsyVisitableItem { MALWARE_ARTIFACT_TYPE); super.setName(MALWARE_HITS); - //this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/hashset_hits.png"); // ELTODO + // TODO make an icon + this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/artifact-icon.png"); } @Override From eb6f7a4f78353d6d5de78c11f32d455b9ab1e07a Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Fri, 18 Aug 2023 13:27:07 -0400 Subject: [PATCH 58/94] logging for long polling --- .../autopsy/malwarescan/MalwareScanIngestModule.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java index 4698392478..37a66c0380 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java @@ -694,6 +694,7 @@ class MalwareScanIngestModule implements FileIngestModule { Bundle.MalwareScanIngestModule_longPollForNotFound_fileLookupPolling_title(), Bundle.MalwareScanIngestModule_longPollForNotFound_fileLookupPolling_desc() ); + logger.log(Level.INFO, "Begin polling for malware status of file uploads."); Map> remaining = new HashMap<>(ingestJobState.getUnidentifiedHashes()); @@ -729,6 +730,9 @@ class MalwareScanIngestModule implements FileIngestModule { // exponential backoff before trying again long waitMultiplier = ((long) Math.pow(2, retry)); + + logger.log(Level.INFO, MessageFormat.format("Waiting {0} milliseconds before polling again for malware status of file uploads.", (waitMultiplier * FILE_UPLOAD_RETRY_SLEEP_MILLIS))); + for (int i = 0; i < waitMultiplier; i++) { if (!ingestJobState.isDoFileLookups() || ingestJobState.getIngestJobContext().fileIngestIsCancelled()) { return; From 2045b2357ccfe0eb0e5a17ff0a9ba5b2637eb26d Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Fri, 18 Aug 2023 14:55:11 -0400 Subject: [PATCH 59/94] Remove upload panel remove upload panel --- .../ctoptions/ctcloud/Bundle.properties | 2 - .../ctcloud/CTMalwareScannerOptionsPanel.form | 39 ------------------- .../ctcloud/CTMalwareScannerOptionsPanel.java | 37 ------------------ 3 files changed, 78 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties index 3b48b0ea4e..3c86b5446d 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties @@ -22,8 +22,6 @@ CTMalwareScannerOptionsPanel.licenseInfoUserLabel.text= EULADialog.cancelButton.text=Cancel EULADialog.acceptButton.text=Accept EULADialog.title=Cyber Triage End User License Agreement -CTMalwareScannerOptionsPanel.fileUploadCheckbox.text=Upload file if hash lookup produces no results -CTMalwareScannerOptionsPanel.fileUploadPanel.border.title=File Upload CTMalwareScannerOptionsPanel.licenseInfoMessageLabel.text= CTMalwareScannerOptionsPanel.disclaimer.text=The Cyber Triage Malware Scanner module uses 40+ malware scanning engines to identify if Windows executables are malicious. It requires a paid subscription to use. CTMalwareScannerOptionsPanel.purchaseFromLabel.text=For licensing information, visit diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form index e9886eadf2..841490d657 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form @@ -16,45 +16,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java index cfc9057aa6..056b96915b 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java @@ -243,8 +243,6 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { private void initComponents() { java.awt.GridBagConstraints gridBagConstraints; - fileUploadPanel = new javax.swing.JPanel(); - fileUploadCheckbox = new javax.swing.JCheckBox(); malwareScansPanel = new javax.swing.JPanel(); javax.swing.JLabel disclaimer = new javax.swing.JLabel(); javax.swing.JPanel licenseInfoPanel = new javax.swing.JPanel(); @@ -266,35 +264,6 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { setLayout(new java.awt.GridBagLayout()); - fileUploadPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.fileUploadPanel.border.title"))); // NOI18N - fileUploadPanel.setLayout(new java.awt.GridBagLayout()); - - fileUploadCheckbox.setSelected(true); - org.openide.awt.Mnemonics.setLocalizedText(fileUploadCheckbox, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.fileUploadCheckbox.text")); // NOI18N - fileUploadCheckbox.setMaximumSize(new java.awt.Dimension(32767, 20)); - fileUploadCheckbox.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - fileUploadCheckboxActionPerformed(evt); - } - }); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); - fileUploadPanel.add(fileUploadCheckbox, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.weightx = 1.0; - add(fileUploadPanel, gridBagConstraints); - malwareScansPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.malwareScansPanel.border.title"))); // NOI18N malwareScansPanel.setLayout(new java.awt.GridBagLayout()); @@ -507,10 +476,6 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { } }//GEN-LAST:event_licenseInfoAddButtonActionPerformed - private void fileUploadCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fileUploadCheckboxActionPerformed - this.firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - }//GEN-LAST:event_fileUploadCheckboxActionPerformed - private void purchaseLinkMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_purchaseLinkMouseClicked gotoLink(PURCHASE_URL); }//GEN-LAST:event_purchaseLinkMouseClicked @@ -778,8 +743,6 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel countersResetLabel; - private javax.swing.JCheckBox fileUploadCheckbox; - private javax.swing.JPanel fileUploadPanel; private javax.swing.JLabel fileUploadsRemainingLabel; private javax.swing.JLabel hashLookupsRemainingLabel; private javax.swing.JButton licenseInfoAddButton; From 5fc14328bf76e18d618a22bd70edfbfdc2b0fa7d Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Fri, 18 Aug 2023 15:34:41 -0400 Subject: [PATCH 60/94] Revert "Merge branch '2457-change-from-global-to-ingest-panel' into 2452-change-ct-option-panel" This reverts commit c103c490a0123a4ba498301f24b31e8d2125ef17, reversing changes made to 2045b2357ccfe0eb0e5a17ff0a9ba5b2637eb26d. --- .../ctcloud/Bundle.properties-MERGED | 1 - .../ctcloud/CTMalwareScannerOptionsPanel.form | 87 ---------- .../ctcloud/CTMalwareScannerOptionsPanel.java | 8 +- .../autopsy/malwarescan/Bundle.properties | 7 - .../malwarescan/Bundle.properties-MERGED | 9 +- .../autopsy/malwarescan/Bundle_ar.properties | 1 - .../autopsy/malwarescan/Bundle_ja.properties | 1 - .../malwarescan/MalwareScanIngestModule.java | 20 +-- .../MalwareScanIngestModuleFactory.java | 25 +-- .../MalwareScanIngestSettings.java | 96 ----------- .../MalwareScanIngestSettingsPanel.form | 123 --------------- .../MalwareScanIngestSettingsPanel.java | 149 ------------------ 12 files changed, 14 insertions(+), 513 deletions(-) delete mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties delete mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle_ar.properties delete mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle_ja.properties delete mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettings.java delete mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.form delete mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.java diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED index 2bd5bc5eab..d3922b3c09 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED @@ -65,4 +65,3 @@ CTMalwareScannerOptionsPanel.fileUploadPanel.border.title=File Upload CTMalwareScannerOptionsPanel.licenseInfoMessageLabel.text= CTMalwareScannerOptionsPanel.disclaimer.text=The Cyber Triage Malware Scanner module uses 40+ malware scanning engines to identify if Windows executables are malicious. It requires a paid subscription to use. CTMalwareScannerOptionsPanel.purchaseFromLabel.text=For licensing information, visit - diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form index abd9449e67..841490d657 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form @@ -16,93 +16,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java index 6215440e92..056b96915b 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java @@ -164,13 +164,15 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { } private MalwareIngestSettings getIngestSettings() { - return new MalwareIngestSettings(); + return new MalwareIngestSettings() + .setUploadFiles(this.fileUploadCheckbox.isSelected()); } private void setIngestSettings(MalwareIngestSettings ingestSettings) { if (ingestSettings == null) { ingestSettings = new MalwareIngestSettings(); } + this.fileUploadCheckbox.setSelected(ingestSettings.isUploadFiles()); } private synchronized void setLicenseDisplay(LicenseInfo licenseInfo, String licenseMessage) { @@ -240,6 +242,7 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { // //GEN-BEGIN:initComponents private void initComponents() { java.awt.GridBagConstraints gridBagConstraints; + malwareScansPanel = new javax.swing.JPanel(); javax.swing.JLabel disclaimer = new javax.swing.JLabel(); javax.swing.JPanel licenseInfoPanel = new javax.swing.JPanel(); @@ -275,8 +278,6 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); malwareScansPanel.add(disclaimer, gridBagConstraints); - - licenseInfoPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.licenseInfoPanel.border.title"))); // NOI18N licenseInfoPanel.setLayout(new java.awt.GridBagLayout()); org.openide.awt.Mnemonics.setLocalizedText(licenseInfoMessageLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.licenseInfoMessageLabel.text")); // NOI18N @@ -479,7 +480,6 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { gotoLink(PURCHASE_URL); }//GEN-LAST:event_purchaseLinkMouseClicked - @NbBundle.Messages({ "# {0} - userName", "# {1} - email", diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties deleted file mode 100644 index e9fdcb1cb5..0000000000 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties +++ /dev/null @@ -1,7 +0,0 @@ -MalwareScanIngestSettingsPanel.uploadFilesCheckbox.AccessibleContext.accessibleName=Upload file content for files that do not have results -MalwareScanIngestSettingsPanel.uploadFilesCheckbox.label=Upload file content for files that do not have results -MalwareScanIngestSettingsPanel.uploadFilesCheckbox.text=Upload file content for files that do not have results -DataSourceIntegrityIngestSettingsPanel.queryFilesTextArea.text=Query file existing results using file\u2019s hash -MalwareScanIngestSettingsPanel.ingestSettingsLabel.text=Ingest Settings -MalwareScanIngestSettingsPanel.paidLicenseTextArea.text=This module requires a paid license. \nSee the Global Options panel for details -MalwareScanIngestSettingsPanel.queryFilesCheckbox.text=Query for existing results using file\u2019s hash diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED index 3b886d02cb..4380a9607c 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED @@ -38,13 +38,6 @@ MalwareScanIngestModule_uploadFile_noRemainingFileUploads_title=No Remaining Fil # {0} - objectId MalwareScanIngestModule_uploadFile_notUploadable_desc=A file did not meet requirements for upload (object id: {0}). MalwareScanIngestModule_uploadFile_notUploadable_title=Not Able to Upload -MalwareScanIngestModuleFactory_description=Identifies executable files with malware. +MalwareScanIngestModuleFactory_description=The malware scan ingest module queries the Cyber Triage cloud API for any possible malicious executables. MalwareScanIngestModuleFactory_displayName=Cyber Triage Malware Scanner MalwareScanIngestModuleFactory_version=1.0.0 -MalwareScanIngestSettingsPanel.uploadFilesCheckbox.AccessibleContext.accessibleName=Upload file content for files that do not have results -MalwareScanIngestSettingsPanel.uploadFilesCheckbox.label=Upload file content for files that do not have results -MalwareScanIngestSettingsPanel.uploadFilesCheckbox.text=Upload file content for files that do not have results -DataSourceIntegrityIngestSettingsPanel.queryFilesTextArea.text=Query file existing results using file\u2019s hash -MalwareScanIngestSettingsPanel.ingestSettingsLabel.text=Ingest Settings -MalwareScanIngestSettingsPanel.paidLicenseTextArea.text=This module requires a paid license. \nSee the Global Options panel for details -MalwareScanIngestSettingsPanel.queryFilesCheckbox.text=Query for existing results using file\u2019s hash diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle_ar.properties b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle_ar.properties deleted file mode 100644 index 7a6ad43a3e..0000000000 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle_ar.properties +++ /dev/null @@ -1 +0,0 @@ -MalwareScanIngestSettingsPanel.ingestSettingsLabel.text=Configuracion de Ingesta diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle_ja.properties b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle_ja.properties deleted file mode 100644 index cff7aa2e8d..0000000000 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle_ja.properties +++ /dev/null @@ -1 +0,0 @@ -MalwareScanIngestSettingsPanel.ingestSettingsLabel.text=\u53d6\u8fbc\u307f\u8a2d\u5b9a diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java index a9c814e767..4698392478 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java @@ -72,17 +72,10 @@ import org.sleuthkit.datamodel.TskData; class MalwareScanIngestModule implements FileIngestModule { private static final SharedProcessing sharedProcessing = new SharedProcessing(); - private boolean uploadFiles; - private boolean queryFiles; - - MalwareScanIngestModule(MalwareScanIngestSettings settings) { - uploadFiles = settings.shouldUploadFiles(); - queryFiles = settings.shouldQueryFiles(); - } - + @Override public void startUp(IngestJobContext context) throws IngestModuleException { - sharedProcessing.startUp(context, uploadFiles); + sharedProcessing.startUp(context); } @Override @@ -130,7 +123,7 @@ class MalwareScanIngestModule implements FileIngestModule { "application/msdos-windows",//NON-NLS "application/x-msdos-program"//NON-NLS ).collect(Collectors.toSet()); - + private static final String MALWARE_TYPE_NAME = "TSK_MALWARE"; private static final String MALWARE_CONFIG = "Cyber Triage Cloud"; @@ -160,14 +153,14 @@ class MalwareScanIngestModule implements FileIngestModule { "MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_title=File Uploads Limit Low", "# {0} - remainingUploads", "MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_desc=This license only has {0} file uploads remaining.",}) - synchronized void startUp(IngestJobContext context, boolean uploadFiles) throws IngestModuleException { + synchronized void startUp(IngestJobContext context) throws IngestModuleException { // only run this code once per startup if (ingestJobState != null) { return; } try { - ingestJobState = getNewJobState(context, uploadFiles); + ingestJobState = getNewJobState(context); } catch (Exception ex) { ingestJobState = IngestJobState.DISABLED; throw new IngestModuleException("An exception occurred on MalwareScanIngestModule startup", ex); @@ -182,7 +175,7 @@ class MalwareScanIngestModule implements FileIngestModule { * parameters required for the job. * @throws Exception */ - private IngestJobState getNewJobState(IngestJobContext context, boolean uploadFiles) throws Exception { + private IngestJobState getNewJobState(IngestJobContext context) throws Exception { // get saved license Optional licenseInfoOpt = ctSettingsPersistence.loadLicenseInfo(); if (licenseInfoOpt.isEmpty() || licenseInfoOpt.get().getDecryptedLicense() == null) { @@ -214,6 +207,7 @@ class MalwareScanIngestModule implements FileIngestModule { } // determine lookups remaining + boolean uploadFiles = ctSettingsPersistence.loadMalwareIngestSettings().isUploadFiles(); if (uploadFiles) { long uploadsRemaining = remaining(authTokenResponse.getFileUploadLimit(), authTokenResponse.getFileUploadCount()); if (uploadsRemaining <= 0) { diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModuleFactory.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModuleFactory.java index 83cb93f689..e138116036 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModuleFactory.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModuleFactory.java @@ -25,8 +25,6 @@ import org.sleuthkit.autopsy.ingest.FileIngestModule; import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter; import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel; import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; -import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel; -import org.sleuthkit.autopsy.ingest.NoIngestModuleIngestJobSettings; /** * Factory for malware scan ingest modules. @@ -34,7 +32,7 @@ import org.sleuthkit.autopsy.ingest.NoIngestModuleIngestJobSettings; @ServiceProvider(service = org.sleuthkit.autopsy.ingest.IngestModuleFactory.class) @Messages({ "MalwareScanIngestModuleFactory_displayName=Cyber Triage Malware Scanner", - "MalwareScanIngestModuleFactory_description=Identifies executable files with malware.", + "MalwareScanIngestModuleFactory_description=The malware scan ingest module queries the Cyber Triage cloud API for any possible malicious executables.", "MalwareScanIngestModuleFactory_version=1.0.0" }) public class MalwareScanIngestModuleFactory extends IngestModuleFactoryAdapter { @@ -68,7 +66,7 @@ public class MalwareScanIngestModuleFactory extends IngestModuleFactoryAdapter { @Override public FileIngestModule createFileIngestModule(IngestModuleIngestJobSettings ingestOptions) { - return new MalwareScanIngestModule((MalwareScanIngestSettings) ingestOptions); + return new MalwareScanIngestModule(); } @Override @@ -83,23 +81,4 @@ public class MalwareScanIngestModuleFactory extends IngestModuleFactoryAdapter { return optionsPanel; } - @Override - public boolean hasIngestJobSettingsPanel() { - return true; - } - - @Override - public IngestModuleIngestJobSettingsPanel getIngestJobSettingsPanel(IngestModuleIngestJobSettings settings) { - if (settings instanceof MalwareScanIngestSettings) { - return new MalwareScanIngestSettingsPanel((MalwareScanIngestSettings) settings); - } - /* - * Compatibility check for older versions. - */ - if (settings instanceof NoIngestModuleIngestJobSettings) { - return new MalwareScanIngestSettingsPanel(new MalwareScanIngestSettings()); - } - - throw new IllegalArgumentException("Expected settings argument to be an instance of IngestSettings"); - } } diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettings.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettings.java deleted file mode 100644 index 158e967745..0000000000 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettings.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2023 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.basistech.df.cybertriage.autopsy.malwarescan; - -import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; - -/** - * Ingest job settings for the Malware scanner module. - */ -final class MalwareScanIngestSettings implements IngestModuleIngestJobSettings { - - private static final long serialVersionUID = 1L; - - private static final boolean DEFAULT_QUERY_FILES = true; - private static final boolean DEFAULT_UPLOAD_FILES = true; - - public boolean queryFiles; - public boolean uploadFiles; - - /** - * Instantiate the ingest job settings with default values. - */ - MalwareScanIngestSettings() { - this.queryFiles = DEFAULT_QUERY_FILES; - this.uploadFiles = DEFAULT_UPLOAD_FILES; - } - - /** - * Instantiate the ingest job settings. - * - * @param computeHashes Compute hashes if none are present - * @param verifyHashes Verify hashes if any are present - */ - MalwareScanIngestSettings(boolean queryFiles, boolean uploadFiles) { - this.queryFiles = queryFiles; - this.uploadFiles = uploadFiles; - } - - @Override - public long getVersionNumber() { - return serialVersionUID; - } - - /** - * Should files be queried? - * - * @return true if files should be queried, false otherwise - */ - public boolean shouldQueryFiles() { - return queryFiles; - } - - /** - * Set whether files should be queried. - * - * @param queryFiles true if files should be queried - */ - void setqueryFiles(boolean queryFiles) { - this.queryFiles = queryFiles; - } - - - /** - * Should files be uploaded? - * - * @return true if files should be uploaded, false otherwise - */ - public boolean shouldUploadFiles() { - return uploadFiles; - } - - /** - * Set whether files should be uploaded. - * - * @param uploadFiles true if files should be uploaded - */ - void setUploadFiles(boolean uploadFiles) { - this.uploadFiles = uploadFiles; - } -} diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.form b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.form deleted file mode 100644 index 46a928c98e..0000000000 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.form +++ /dev/null @@ -1,123 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.java deleted file mode 100644 index a418de0f83..0000000000 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Autopsy Browser - * - * Copyright 2023 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.basistech.df.cybertriage.autopsy.malwarescan; - -import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseInfo; -import com.basistech.df.cybertriage.autopsy.ctoptions.ctcloud.CTLicensePersistence; -import java.util.Optional; -import org.sleuthkit.autopsy.modules.dataSourceIntegrity.*; -import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; -import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel; - -/** - * Ingest job settings panel for the Malware scanner ingest. - */ -@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives -final class MalwareScanIngestSettingsPanel extends IngestModuleIngestJobSettingsPanel { - - private final CTLicensePersistence ctPersistence = CTLicensePersistence.getInstance(); - - MalwareScanIngestSettingsPanel(MalwareScanIngestSettings settings) { - initComponents(); - customizeComponents(settings); - } - - /** - * Update components with values from the ingest job settings. - * - * @param settings The ingest job settings. - */ - private void customizeComponents(MalwareScanIngestSettings settings) { - Optional licenseInfoOpt = ctPersistence.loadLicenseInfo(); - LicenseInfo licenseInfo = licenseInfoOpt.orElse(null); - if (licenseInfo != null) { - this.paidLicenseTextArea.setVisible(false); - this.queryFilesCheckbox.setVisible(true); - this.queryFilesCheckbox.setEnabled(false); - this.uploadFilesCheckbox.setVisible(true); - this.queryFilesCheckbox.setSelected(true); - this.uploadFilesCheckbox.setSelected(settings.shouldUploadFiles()); - } else { - this.paidLicenseTextArea.setVisible(true); - this.queryFilesCheckbox.setVisible(false); - this.uploadFilesCheckbox.setVisible(false); - } - } - - @Override - public IngestModuleIngestJobSettings getSettings() { - return new MalwareScanIngestSettings(queryFilesCheckbox.isSelected(), uploadFilesCheckbox.isSelected()); - } - - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - @SuppressWarnings("unchecked") - // //GEN-BEGIN:initComponents - private void initComponents() { - - queryFilesCheckbox = new javax.swing.JCheckBox(); - uploadFilesCheckbox = new javax.swing.JCheckBox(); - ingestSettingsLabel = new javax.swing.JLabel(); - paidLicenseTextArea = new javax.swing.JTextArea(); - - setPreferredSize(new java.awt.Dimension(300, 155)); - - queryFilesCheckbox.setSelected(true); - org.openide.awt.Mnemonics.setLocalizedText(queryFilesCheckbox, org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.queryFilesCheckbox.text")); // NOI18N - queryFilesCheckbox.setEnabled(false); - - org.openide.awt.Mnemonics.setLocalizedText(uploadFilesCheckbox, org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.uploadFilesCheckbox.text")); // NOI18N - uploadFilesCheckbox.setFocusable(false); - uploadFilesCheckbox.setLabel(org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.uploadFilesCheckbox.label")); // NOI18N - - ingestSettingsLabel.setFont(ingestSettingsLabel.getFont().deriveFont(ingestSettingsLabel.getFont().getStyle() | java.awt.Font.BOLD)); - org.openide.awt.Mnemonics.setLocalizedText(ingestSettingsLabel, org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.ingestSettingsLabel.text")); // NOI18N - - paidLicenseTextArea.setColumns(20); - paidLicenseTextArea.setFont(new java.awt.Font("Segoe UI", 1, 12)); // NOI18N - paidLicenseTextArea.setRows(5); - paidLicenseTextArea.setText(org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.paidLicenseTextArea.text")); // NOI18N - paidLicenseTextArea.setWrapStyleWord(true); - paidLicenseTextArea.setBorder(null); - paidLicenseTextArea.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR)); - paidLicenseTextArea.setFocusable(false); - paidLicenseTextArea.setOpaque(false); - paidLicenseTextArea.setRequestFocusEnabled(false); - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGap(6, 6, 6) - .addComponent(ingestSettingsLabel)) - .addGroup(layout.createSequentialGroup() - .addGap(6, 6, 6) - .addComponent(uploadFilesCheckbox)) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addComponent(queryFilesCheckbox)) - .addGroup(layout.createSequentialGroup() - .addGap(5, 5, 5) - .addComponent(paidLicenseTextArea, javax.swing.GroupLayout.PREFERRED_SIZE, 243, javax.swing.GroupLayout.PREFERRED_SIZE))) - .addGap(185, 185, 185)) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addComponent(ingestSettingsLabel) - .addGap(18, 18, 18) - .addComponent(queryFilesCheckbox) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(uploadFilesCheckbox) - .addGap(18, 18, 18) - .addComponent(paidLicenseTextArea, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)) - ); - - uploadFilesCheckbox.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.uploadFilesCheckbox.AccessibleContext.accessibleName")); // NOI18N - }// //GEN-END:initComponents - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JLabel ingestSettingsLabel; - private javax.swing.JTextArea paidLicenseTextArea; - private javax.swing.JCheckBox queryFilesCheckbox; - private javax.swing.JCheckBox uploadFilesCheckbox; - // End of variables declaration//GEN-END:variables - -} From a95195062a5c1252a4152d7daaf50027e0e22fcd Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Fri, 18 Aug 2023 15:36:07 -0400 Subject: [PATCH 61/94] Revert "Remove upload panel" This reverts commit 2045b2357ccfe0eb0e5a17ff0a9ba5b2637eb26d. --- .../ctoptions/ctcloud/Bundle.properties | 2 + .../ctcloud/CTMalwareScannerOptionsPanel.form | 39 +++++++++++++++++++ .../ctcloud/CTMalwareScannerOptionsPanel.java | 37 ++++++++++++++++++ 3 files changed, 78 insertions(+) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties index 3c86b5446d..3b48b0ea4e 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties @@ -22,6 +22,8 @@ CTMalwareScannerOptionsPanel.licenseInfoUserLabel.text= EULADialog.cancelButton.text=Cancel EULADialog.acceptButton.text=Accept EULADialog.title=Cyber Triage End User License Agreement +CTMalwareScannerOptionsPanel.fileUploadCheckbox.text=Upload file if hash lookup produces no results +CTMalwareScannerOptionsPanel.fileUploadPanel.border.title=File Upload CTMalwareScannerOptionsPanel.licenseInfoMessageLabel.text= CTMalwareScannerOptionsPanel.disclaimer.text=The Cyber Triage Malware Scanner module uses 40+ malware scanning engines to identify if Windows executables are malicious. It requires a paid subscription to use. CTMalwareScannerOptionsPanel.purchaseFromLabel.text=For licensing information, visit diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form index 841490d657..e9886eadf2 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form @@ -16,6 +16,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java index 056b96915b..cfc9057aa6 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java @@ -243,6 +243,8 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { private void initComponents() { java.awt.GridBagConstraints gridBagConstraints; + fileUploadPanel = new javax.swing.JPanel(); + fileUploadCheckbox = new javax.swing.JCheckBox(); malwareScansPanel = new javax.swing.JPanel(); javax.swing.JLabel disclaimer = new javax.swing.JLabel(); javax.swing.JPanel licenseInfoPanel = new javax.swing.JPanel(); @@ -264,6 +266,35 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { setLayout(new java.awt.GridBagLayout()); + fileUploadPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.fileUploadPanel.border.title"))); // NOI18N + fileUploadPanel.setLayout(new java.awt.GridBagLayout()); + + fileUploadCheckbox.setSelected(true); + org.openide.awt.Mnemonics.setLocalizedText(fileUploadCheckbox, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.fileUploadCheckbox.text")); // NOI18N + fileUploadCheckbox.setMaximumSize(new java.awt.Dimension(32767, 20)); + fileUploadCheckbox.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + fileUploadCheckboxActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); + fileUploadPanel.add(fileUploadCheckbox, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + add(fileUploadPanel, gridBagConstraints); + malwareScansPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.malwareScansPanel.border.title"))); // NOI18N malwareScansPanel.setLayout(new java.awt.GridBagLayout()); @@ -476,6 +507,10 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { } }//GEN-LAST:event_licenseInfoAddButtonActionPerformed + private void fileUploadCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fileUploadCheckboxActionPerformed + this.firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); + }//GEN-LAST:event_fileUploadCheckboxActionPerformed + private void purchaseLinkMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_purchaseLinkMouseClicked gotoLink(PURCHASE_URL); }//GEN-LAST:event_purchaseLinkMouseClicked @@ -743,6 +778,8 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel countersResetLabel; + private javax.swing.JCheckBox fileUploadCheckbox; + private javax.swing.JPanel fileUploadPanel; private javax.swing.JLabel fileUploadsRemainingLabel; private javax.swing.JLabel hashLookupsRemainingLabel; private javax.swing.JButton licenseInfoAddButton; From 5899d2dfdf38bcd1c3acd287b1f632e90a18841f Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Sun, 20 Aug 2023 09:10:12 -0400 Subject: [PATCH 62/94] remove upload from options panel remove upload from options panel --- .../ctcloud/Bundle.properties-MERGED | 2 - .../ctcloud/CTLicensePersistence.java | 33 ----------------- .../ctcloud/CTMalwareScannerOptionsPanel.java | 27 ++------------ .../ctcloud/MalwareIngestSettings.java | 37 ------------------- .../malwarescan/MalwareScanIngestModule.java | 2 +- 5 files changed, 4 insertions(+), 97 deletions(-) delete mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/MalwareIngestSettings.java diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED index d3922b3c09..0e888c7fac 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED @@ -60,8 +60,6 @@ CTOPtionsPanel_loadMalwareScansInfo_loading=Loading... EULADialog.cancelButton.text=Cancel EULADialog.acceptButton.text=Accept EULADialog.title=Cyber Triage End User License Agreement -CTMalwareScannerOptionsPanel.fileUploadCheckbox.text=Upload file if hash lookup produces no results -CTMalwareScannerOptionsPanel.fileUploadPanel.border.title=File Upload CTMalwareScannerOptionsPanel.licenseInfoMessageLabel.text= CTMalwareScannerOptionsPanel.disclaimer.text=The Cyber Triage Malware Scanner module uses 40+ malware scanning engines to identify if Windows executables are malicious. It requires a paid subscription to use. CTMalwareScannerOptionsPanel.purchaseFromLabel.text=For licensing information, visit diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicensePersistence.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicensePersistence.java index 717c4f4321..43e34a8d2a 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicensePersistence.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicensePersistence.java @@ -91,39 +91,6 @@ public class CTLicensePersistence { }); } - public synchronized boolean saveMalwareSettings(MalwareIngestSettings malwareIngestSettings) { - if (malwareIngestSettings != null) { - File settingsFile = getMalwareIngestFile(); - try { - settingsFile.getParentFile().mkdirs(); - objectMapper.writeValue(settingsFile, malwareIngestSettings); - return true; - } catch (IOException ex) { - logger.log(Level.WARNING, "There was an error writing malware ingest settings to file: " + settingsFile.getAbsolutePath(), ex); - } - } - - return false; - } - - public synchronized MalwareIngestSettings loadMalwareIngestSettings() { - MalwareIngestSettings settings = null; - File settingsFile = getMalwareIngestFile(); - if (settingsFile.exists() && settingsFile.isFile()) { - try { - settings = objectMapper.readValue(settingsFile, MalwareIngestSettings.class); - } catch (IOException ex) { - logger.log(Level.WARNING, "There was an error reading malware ingest settings from file: " + settingsFile.getAbsolutePath(), ex); - } - } - - if (settings == null) { - settings = new MalwareIngestSettings(); - } - - return settings; - } - private File getCTLicenseFile() { return Paths.get(PlatformUtil.getModuleConfigDirectory(), CT_SETTINGS_DIR, CT_LICENSE_FILENAME).toFile(); } diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java index 056b96915b..f0e1a4e88f 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java @@ -88,8 +88,6 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { public CTMalwareScannerOptionsPanel() { initComponents(); - this.fileUploadPanel.setVisible(false); - this.addComponentListener(new ComponentAdapter() { @Override public void componentHidden(ComponentEvent e) { @@ -121,7 +119,6 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { @Override public synchronized void saveSettings() { ctPersistence.saveLicenseResponse(getLicenseInfo()); - ctPersistence.saveMalwareSettings(getIngestSettings()); } @Override @@ -138,9 +135,6 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { if (licenseInfo != null) { loadMalwareScansInfo(licenseInfo); } - - MalwareIngestSettings ingestSettings = ctPersistence.loadMalwareIngestSettings(); - setIngestSettings(ingestSettings); } private static String getHtmlLink(String url) { @@ -163,18 +157,6 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { return this.licenseInfo == null ? null : this.licenseInfo.getLicenseResponse(); } - private MalwareIngestSettings getIngestSettings() { - return new MalwareIngestSettings() - .setUploadFiles(this.fileUploadCheckbox.isSelected()); - } - - private void setIngestSettings(MalwareIngestSettings ingestSettings) { - if (ingestSettings == null) { - ingestSettings = new MalwareIngestSettings(); - } - this.fileUploadCheckbox.setSelected(ingestSettings.isUploadFiles()); - } - private synchronized void setLicenseDisplay(LicenseInfo licenseInfo, String licenseMessage) { this.licenseInfo = licenseInfo; this.licenseInfoMessage = licenseMessage; @@ -695,15 +677,12 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { } @Override - protected AuthTokenResponse doInBackground() throws Exception, CTCloudException { + protected AuthTokenResponse doInBackground() throws Exception { if (this.isCancelled()) { return null; } - try { - return ctApiDAO.getAuthToken(decryptedLicense); - } catch (CTCloudException ex) { - return null; - } + + return ctApiDAO.getAuthToken(decryptedLicense); } @Override diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/MalwareIngestSettings.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/MalwareIngestSettings.java deleted file mode 100644 index 11e671d561..0000000000 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/MalwareIngestSettings.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2023 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.basistech.df.cybertriage.autopsy.ctoptions.ctcloud; - -/** - * Settings for the malware ingest module. - */ -public class MalwareIngestSettings { - - private boolean uploadFiles = true; - - public boolean isUploadFiles() { - return uploadFiles; - } - - public MalwareIngestSettings setUploadFiles(boolean uploadFiles) { - this.uploadFiles = uploadFiles; - return this; - } - -} diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java index 4698392478..d8119baab0 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java @@ -207,7 +207,7 @@ class MalwareScanIngestModule implements FileIngestModule { } // determine lookups remaining - boolean uploadFiles = ctSettingsPersistence.loadMalwareIngestSettings().isUploadFiles(); + boolean uploadFiles = true; if (uploadFiles) { long uploadsRemaining = remaining(authTokenResponse.getFileUploadLimit(), authTokenResponse.getFileUploadCount()); if (uploadsRemaining <= 0) { From 92ccddb9bf22128b0febca0f0b583256673c997b Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Sun, 20 Aug 2023 09:29:08 -0400 Subject: [PATCH 63/94] Fix merge conflict Fix merge conflict --- .../ctoptions/ctcloud/Bundle.properties-MERGED | 1 + .../ctcloud/CTMalwareScannerOptionsPanel.form | 14 +++++++------- .../ctcloud/CTMalwareScannerOptionsPanel.java | 11 +---------- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED index 0e888c7fac..c04ee1b62d 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED @@ -63,3 +63,4 @@ EULADialog.title=Cyber Triage End User License Agreement CTMalwareScannerOptionsPanel.licenseInfoMessageLabel.text= CTMalwareScannerOptionsPanel.disclaimer.text=The Cyber Triage Malware Scanner module uses 40+ malware scanning engines to identify if Windows executables are malicious. It requires a paid subscription to use. CTMalwareScannerOptionsPanel.purchaseFromLabel.text=For licensing information, visit + diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form index abd9449e67..5305e3cb2e 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form @@ -20,7 +20,7 @@ - + @@ -138,7 +138,7 @@
- + @@ -151,7 +151,7 @@ - + @@ -163,7 +163,7 @@ - + @@ -175,7 +175,7 @@ - + @@ -187,7 +187,7 @@ - + @@ -199,7 +199,7 @@ - + diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java index 481dc31955..a73a6c1656 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java @@ -155,16 +155,7 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { private synchronized LicenseResponse getLicenseInfo() { return this.licenseInfo == null ? null : this.licenseInfo.getLicenseResponse(); - - private MalwareIngestSettings getIngestSettings() { - return new MalwareIngestSettings(); - } - - private void setIngestSettings(MalwareIngestSettings ingestSettings) { - if (ingestSettings == null) { - ingestSettings = new MalwareIngestSettings(); - } - } + } private synchronized void setLicenseDisplay(LicenseInfo licenseInfo, String licenseMessage) { this.licenseInfo = licenseInfo; From f5d65a4d39b706acc47897b047f370be22226dea Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Sun, 20 Aug 2023 10:44:33 -0400 Subject: [PATCH 64/94] FIx Merge Issues Fix Merge Issues --- .../autopsy/malwarescan/Bundle.properties | 7 + .../malwarescan/Bundle.properties-MERGED | 9 +- .../malwarescan/MalwareScanIngestModule.java | 28 ++-- .../MalwareScanIngestModuleFactory.java | 25 ++- .../MalwareScanIngestSettings.java | 96 +++++++++++ .../MalwareScanIngestSettingsPanel.form | 123 +++++++++++++++ .../MalwareScanIngestSettingsPanel.java | 149 ++++++++++++++++++ 7 files changed, 421 insertions(+), 16 deletions(-) create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettings.java create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.form create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.java diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties new file mode 100644 index 0000000000..fbf6db930c --- /dev/null +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties @@ -0,0 +1,7 @@ +MalwareScanIngestSettingsPanel.uploadFilesCheckbox.AccessibleContext.accessibleName=Upload file content for files that do not have results +MalwareScanIngestSettingsPanel.uploadFilesCheckbox.label=Upload file content for files that do not have results +MalwareScanIngestSettingsPanel.uploadFilesCheckbox.text=Upload file content for files that do not have results +DataSourceIntegrityIngestSettingsPanel.queryFilesTextArea.text=Query for existing results using file\u2019s hash +MalwareScanIngestSettingsPanel.ingestSettingsLabel.text=Ingest Settings +MalwareScanIngestSettingsPanel.paidLicenseTextArea.text=This module requires a paid license. \nSee the Global Options panel for details +MalwareScanIngestSettingsPanel.queryFilesCheckbox.text=Query for existing results using file\u2019s hash diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED index 4380a9607c..decbae37cf 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED @@ -38,6 +38,13 @@ MalwareScanIngestModule_uploadFile_noRemainingFileUploads_title=No Remaining Fil # {0} - objectId MalwareScanIngestModule_uploadFile_notUploadable_desc=A file did not meet requirements for upload (object id: {0}). MalwareScanIngestModule_uploadFile_notUploadable_title=Not Able to Upload -MalwareScanIngestModuleFactory_description=The malware scan ingest module queries the Cyber Triage cloud API for any possible malicious executables. +MalwareScanIngestModuleFactory_description=Identifies executable files with malware. MalwareScanIngestModuleFactory_displayName=Cyber Triage Malware Scanner MalwareScanIngestModuleFactory_version=1.0.0 +MalwareScanIngestSettingsPanel.uploadFilesCheckbox.AccessibleContext.accessibleName=Upload file content for files that do not have results +MalwareScanIngestSettingsPanel.uploadFilesCheckbox.label=Upload file content for files that do not have results +MalwareScanIngestSettingsPanel.uploadFilesCheckbox.text=Upload file content for files that do not have results +DataSourceIntegrityIngestSettingsPanel.queryFilesTextArea.text=Query for existing results using file\u2019s hash +MalwareScanIngestSettingsPanel.ingestSettingsLabel.text=Ingest Settings +MalwareScanIngestSettingsPanel.paidLicenseTextArea.text=This module requires a paid license. \nSee the Global Options panel for details +MalwareScanIngestSettingsPanel.queryFilesCheckbox.text=Query for existing results using file\u2019s hash diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java index 4698392478..190b1412ce 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java @@ -72,10 +72,17 @@ import org.sleuthkit.datamodel.TskData; class MalwareScanIngestModule implements FileIngestModule { private static final SharedProcessing sharedProcessing = new SharedProcessing(); - + private boolean uploadFiles; + private boolean queryFiles; + + MalwareScanIngestModule(MalwareScanIngestSettings settings) { + uploadFiles = settings.shouldUploadFiles(); + queryFiles = settings.shouldQueryFiles(); + } + @Override public void startUp(IngestJobContext context) throws IngestModuleException { - sharedProcessing.startUp(context); + sharedProcessing.startUp(context, uploadFiles); } @Override @@ -123,7 +130,7 @@ class MalwareScanIngestModule implements FileIngestModule { "application/msdos-windows",//NON-NLS "application/x-msdos-program"//NON-NLS ).collect(Collectors.toSet()); - + private static final String MALWARE_TYPE_NAME = "TSK_MALWARE"; private static final String MALWARE_CONFIG = "Cyber Triage Cloud"; @@ -153,14 +160,14 @@ class MalwareScanIngestModule implements FileIngestModule { "MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_title=File Uploads Limit Low", "# {0} - remainingUploads", "MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_desc=This license only has {0} file uploads remaining.",}) - synchronized void startUp(IngestJobContext context) throws IngestModuleException { + synchronized void startUp(IngestJobContext context, boolean uploadFiles) throws IngestModuleException { // only run this code once per startup if (ingestJobState != null) { return; } try { - ingestJobState = getNewJobState(context); + ingestJobState = getNewJobState(context, uploadFiles); } catch (Exception ex) { ingestJobState = IngestJobState.DISABLED; throw new IngestModuleException("An exception occurred on MalwareScanIngestModule startup", ex); @@ -175,7 +182,7 @@ class MalwareScanIngestModule implements FileIngestModule { * parameters required for the job. * @throws Exception */ - private IngestJobState getNewJobState(IngestJobContext context) throws Exception { + private IngestJobState getNewJobState(IngestJobContext context, boolean uploadFiles) throws Exception { // get saved license Optional licenseInfoOpt = ctSettingsPersistence.loadLicenseInfo(); if (licenseInfoOpt.isEmpty() || licenseInfoOpt.get().getDecryptedLicense() == null) { @@ -207,7 +214,6 @@ class MalwareScanIngestModule implements FileIngestModule { } // determine lookups remaining - boolean uploadFiles = ctSettingsPersistence.loadMalwareIngestSettings().isUploadFiles(); if (uploadFiles) { long uploadsRemaining = remaining(authTokenResponse.getFileUploadLimit(), authTokenResponse.getFileUploadCount()); if (uploadsRemaining <= 0) { @@ -775,11 +781,7 @@ class MalwareScanIngestModule implements FileIngestModule { for (Long objId : objIds) { AnalysisResult res = createAnalysisResult(ingestJobState, trans, result, objId); if (res != null) { - // only post results that have score NOTABLE or LIKELY_NOTABLE - Score score = res.getScore(); - if (score.getSignificance() == Score.Significance.NOTABLE || score.getSignificance() == Score.Significance.LIKELY_NOTABLE) { - createdArtifacts.add(res); - } + createdArtifacts.add(res); } } } @@ -841,7 +843,7 @@ class MalwareScanIngestModule implements FileIngestModule { : Bundle.MalwareScanIngestModule_SharedProcessing_createAnalysisResult_No(); String justification = cloudBean.getMalwareResult().getStatusDescription(); - + return ingestJobState.getTskCase().getBlackboard().newAnalysisResult( ingestJobState.getMalwareType(), objId, diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModuleFactory.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModuleFactory.java index e138116036..83cb93f689 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModuleFactory.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModuleFactory.java @@ -25,6 +25,8 @@ import org.sleuthkit.autopsy.ingest.FileIngestModule; import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter; import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel; import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; +import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel; +import org.sleuthkit.autopsy.ingest.NoIngestModuleIngestJobSettings; /** * Factory for malware scan ingest modules. @@ -32,7 +34,7 @@ import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; @ServiceProvider(service = org.sleuthkit.autopsy.ingest.IngestModuleFactory.class) @Messages({ "MalwareScanIngestModuleFactory_displayName=Cyber Triage Malware Scanner", - "MalwareScanIngestModuleFactory_description=The malware scan ingest module queries the Cyber Triage cloud API for any possible malicious executables.", + "MalwareScanIngestModuleFactory_description=Identifies executable files with malware.", "MalwareScanIngestModuleFactory_version=1.0.0" }) public class MalwareScanIngestModuleFactory extends IngestModuleFactoryAdapter { @@ -66,7 +68,7 @@ public class MalwareScanIngestModuleFactory extends IngestModuleFactoryAdapter { @Override public FileIngestModule createFileIngestModule(IngestModuleIngestJobSettings ingestOptions) { - return new MalwareScanIngestModule(); + return new MalwareScanIngestModule((MalwareScanIngestSettings) ingestOptions); } @Override @@ -81,4 +83,23 @@ public class MalwareScanIngestModuleFactory extends IngestModuleFactoryAdapter { return optionsPanel; } + @Override + public boolean hasIngestJobSettingsPanel() { + return true; + } + + @Override + public IngestModuleIngestJobSettingsPanel getIngestJobSettingsPanel(IngestModuleIngestJobSettings settings) { + if (settings instanceof MalwareScanIngestSettings) { + return new MalwareScanIngestSettingsPanel((MalwareScanIngestSettings) settings); + } + /* + * Compatibility check for older versions. + */ + if (settings instanceof NoIngestModuleIngestJobSettings) { + return new MalwareScanIngestSettingsPanel(new MalwareScanIngestSettings()); + } + + throw new IllegalArgumentException("Expected settings argument to be an instance of IngestSettings"); + } } diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettings.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettings.java new file mode 100644 index 0000000000..158e967745 --- /dev/null +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettings.java @@ -0,0 +1,96 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2023 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.basistech.df.cybertriage.autopsy.malwarescan; + +import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; + +/** + * Ingest job settings for the Malware scanner module. + */ +final class MalwareScanIngestSettings implements IngestModuleIngestJobSettings { + + private static final long serialVersionUID = 1L; + + private static final boolean DEFAULT_QUERY_FILES = true; + private static final boolean DEFAULT_UPLOAD_FILES = true; + + public boolean queryFiles; + public boolean uploadFiles; + + /** + * Instantiate the ingest job settings with default values. + */ + MalwareScanIngestSettings() { + this.queryFiles = DEFAULT_QUERY_FILES; + this.uploadFiles = DEFAULT_UPLOAD_FILES; + } + + /** + * Instantiate the ingest job settings. + * + * @param computeHashes Compute hashes if none are present + * @param verifyHashes Verify hashes if any are present + */ + MalwareScanIngestSettings(boolean queryFiles, boolean uploadFiles) { + this.queryFiles = queryFiles; + this.uploadFiles = uploadFiles; + } + + @Override + public long getVersionNumber() { + return serialVersionUID; + } + + /** + * Should files be queried? + * + * @return true if files should be queried, false otherwise + */ + public boolean shouldQueryFiles() { + return queryFiles; + } + + /** + * Set whether files should be queried. + * + * @param queryFiles true if files should be queried + */ + void setqueryFiles(boolean queryFiles) { + this.queryFiles = queryFiles; + } + + + /** + * Should files be uploaded? + * + * @return true if files should be uploaded, false otherwise + */ + public boolean shouldUploadFiles() { + return uploadFiles; + } + + /** + * Set whether files should be uploaded. + * + * @param uploadFiles true if files should be uploaded + */ + void setUploadFiles(boolean uploadFiles) { + this.uploadFiles = uploadFiles; + } +} diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.form b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.form new file mode 100644 index 0000000000..46a928c98e --- /dev/null +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.form @@ -0,0 +1,123 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.java new file mode 100644 index 0000000000..a418de0f83 --- /dev/null +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.java @@ -0,0 +1,149 @@ +/* + * Autopsy Browser + * + * Copyright 2023 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.basistech.df.cybertriage.autopsy.malwarescan; + +import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseInfo; +import com.basistech.df.cybertriage.autopsy.ctoptions.ctcloud.CTLicensePersistence; +import java.util.Optional; +import org.sleuthkit.autopsy.modules.dataSourceIntegrity.*; +import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; +import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel; + +/** + * Ingest job settings panel for the Malware scanner ingest. + */ +@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives +final class MalwareScanIngestSettingsPanel extends IngestModuleIngestJobSettingsPanel { + + private final CTLicensePersistence ctPersistence = CTLicensePersistence.getInstance(); + + MalwareScanIngestSettingsPanel(MalwareScanIngestSettings settings) { + initComponents(); + customizeComponents(settings); + } + + /** + * Update components with values from the ingest job settings. + * + * @param settings The ingest job settings. + */ + private void customizeComponents(MalwareScanIngestSettings settings) { + Optional licenseInfoOpt = ctPersistence.loadLicenseInfo(); + LicenseInfo licenseInfo = licenseInfoOpt.orElse(null); + if (licenseInfo != null) { + this.paidLicenseTextArea.setVisible(false); + this.queryFilesCheckbox.setVisible(true); + this.queryFilesCheckbox.setEnabled(false); + this.uploadFilesCheckbox.setVisible(true); + this.queryFilesCheckbox.setSelected(true); + this.uploadFilesCheckbox.setSelected(settings.shouldUploadFiles()); + } else { + this.paidLicenseTextArea.setVisible(true); + this.queryFilesCheckbox.setVisible(false); + this.uploadFilesCheckbox.setVisible(false); + } + } + + @Override + public IngestModuleIngestJobSettings getSettings() { + return new MalwareScanIngestSettings(queryFilesCheckbox.isSelected(), uploadFilesCheckbox.isSelected()); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + queryFilesCheckbox = new javax.swing.JCheckBox(); + uploadFilesCheckbox = new javax.swing.JCheckBox(); + ingestSettingsLabel = new javax.swing.JLabel(); + paidLicenseTextArea = new javax.swing.JTextArea(); + + setPreferredSize(new java.awt.Dimension(300, 155)); + + queryFilesCheckbox.setSelected(true); + org.openide.awt.Mnemonics.setLocalizedText(queryFilesCheckbox, org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.queryFilesCheckbox.text")); // NOI18N + queryFilesCheckbox.setEnabled(false); + + org.openide.awt.Mnemonics.setLocalizedText(uploadFilesCheckbox, org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.uploadFilesCheckbox.text")); // NOI18N + uploadFilesCheckbox.setFocusable(false); + uploadFilesCheckbox.setLabel(org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.uploadFilesCheckbox.label")); // NOI18N + + ingestSettingsLabel.setFont(ingestSettingsLabel.getFont().deriveFont(ingestSettingsLabel.getFont().getStyle() | java.awt.Font.BOLD)); + org.openide.awt.Mnemonics.setLocalizedText(ingestSettingsLabel, org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.ingestSettingsLabel.text")); // NOI18N + + paidLicenseTextArea.setColumns(20); + paidLicenseTextArea.setFont(new java.awt.Font("Segoe UI", 1, 12)); // NOI18N + paidLicenseTextArea.setRows(5); + paidLicenseTextArea.setText(org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.paidLicenseTextArea.text")); // NOI18N + paidLicenseTextArea.setWrapStyleWord(true); + paidLicenseTextArea.setBorder(null); + paidLicenseTextArea.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR)); + paidLicenseTextArea.setFocusable(false); + paidLicenseTextArea.setOpaque(false); + paidLicenseTextArea.setRequestFocusEnabled(false); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(6, 6, 6) + .addComponent(ingestSettingsLabel)) + .addGroup(layout.createSequentialGroup() + .addGap(6, 6, 6) + .addComponent(uploadFilesCheckbox)) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(queryFilesCheckbox)) + .addGroup(layout.createSequentialGroup() + .addGap(5, 5, 5) + .addComponent(paidLicenseTextArea, javax.swing.GroupLayout.PREFERRED_SIZE, 243, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addGap(185, 185, 185)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(ingestSettingsLabel) + .addGap(18, 18, 18) + .addComponent(queryFilesCheckbox) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(uploadFilesCheckbox) + .addGap(18, 18, 18) + .addComponent(paidLicenseTextArea, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)) + ); + + uploadFilesCheckbox.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.uploadFilesCheckbox.AccessibleContext.accessibleName")); // NOI18N + }// //GEN-END:initComponents + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel ingestSettingsLabel; + private javax.swing.JTextArea paidLicenseTextArea; + private javax.swing.JCheckBox queryFilesCheckbox; + private javax.swing.JCheckBox uploadFilesCheckbox; + // End of variables declaration//GEN-END:variables + +} From bad497cb881e1e25f987ca395372c93ea8597b2d Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Sun, 20 Aug 2023 21:26:47 -0400 Subject: [PATCH 65/94] fix panel fix panel --- .../ctcloud/CTMalwareScannerOptionsPanel.form | 51 +++---------------- .../ctcloud/CTMalwareScannerOptionsPanel.java | 3 -- 2 files changed, 6 insertions(+), 48 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form index 012ff3486c..841490d657 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form @@ -16,45 +16,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -90,7 +51,7 @@
- + @@ -103,7 +64,7 @@ - + @@ -115,7 +76,7 @@ - + @@ -127,7 +88,7 @@ - + @@ -139,7 +100,7 @@ - + @@ -151,7 +112,7 @@ - + diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java index 96732b1d31..b7c7c7b31d 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java @@ -260,7 +260,6 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); malwareScansPanel.add(disclaimer, gridBagConstraints); - licenseInfoPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.licenseInfoPanel.border.title"))); // NOI18N licenseInfoPanel.setLayout(new java.awt.GridBagLayout()); org.openide.awt.Mnemonics.setLocalizedText(licenseInfoMessageLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.licenseInfoMessageLabel.text")); // NOI18N @@ -723,8 +722,6 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel countersResetLabel; - private javax.swing.JCheckBox fileUploadCheckbox; - private javax.swing.JPanel fileUploadPanel; private javax.swing.JLabel fileUploadsRemainingLabel; private javax.swing.JLabel hashLookupsRemainingLabel; private javax.swing.JButton licenseInfoAddButton; From c3cbb7c826a6c0cee4a9336be37d73f205be58c3 Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Mon, 21 Aug 2023 09:26:04 -0400 Subject: [PATCH 66/94] Update CTMalwareScannerOptionsPanel.java fix disappearing screen --- .../autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java index b7c7c7b31d..4d4f156fe9 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java @@ -506,8 +506,6 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { StringUtils.defaultString(this.licenseInfo.getDecryptedLicense().getCustomerEmail()))); } - this.malwareScansPanel.setVisible(StringUtils.isNotBlank(this.authTokenMessage) || authTokenResponse != null); - this.malwareScansMessageLabel.setVisible(StringUtils.isNotBlank(this.authTokenMessage)); this.malwareScansMessageLabel.setText(this.authTokenMessage); From 65ba14f8a35dd7992f999cc7b4d8929e5e76ed91 Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Mon, 21 Aug 2023 11:32:11 -0400 Subject: [PATCH 67/94] Update Malware Scanner doc Update Malware scanner doc --- docs/doxygen-user/ct_malware_scanner.dox | 9 +++++---- ...scanner-global-options-panel-no-license.png | Bin 0 -> 56344 bytes .../images/ct_malware_license_agreement.png | Bin 56663 -> 0 bytes .../ct_malware_scanner_options_panel.png | Bin 35019 -> 0 bytes docs/doxygen-user/images/ct_upload_file.png | Bin 52102 -> 0 bytes .../images/malware-artifact-tree.png | Bin 0 -> 108340 bytes .../malware-scanner-global-options-panel.png | Bin 0 -> 66206 bytes .../images/malware-scanner-ingest-panel.png | Bin 0 -> 69373 bytes 8 files changed, 5 insertions(+), 4 deletions(-) create mode 100644 docs/doxygen-user/images/Malware-scanner-global-options-panel-no-license.png delete mode 100644 docs/doxygen-user/images/ct_malware_license_agreement.png delete mode 100644 docs/doxygen-user/images/ct_malware_scanner_options_panel.png delete mode 100644 docs/doxygen-user/images/ct_upload_file.png create mode 100644 docs/doxygen-user/images/malware-artifact-tree.png create mode 100644 docs/doxygen-user/images/malware-scanner-global-options-panel.png create mode 100644 docs/doxygen-user/images/malware-scanner-ingest-panel.png diff --git a/docs/doxygen-user/ct_malware_scanner.dox b/docs/doxygen-user/ct_malware_scanner.dox index 196a4d5b00..fa1dd6fb6b 100644 --- a/docs/doxygen-user/ct_malware_scanner.dox +++ b/docs/doxygen-user/ct_malware_scanner.dox @@ -18,14 +18,14 @@ Configuration Once you have a license, you must add it on the Options panel. Choose the 'Cyber Triage' tab and choose 'Add License'. -IMAGE +\image html Malware-scanner-global-options-panel-no-license.png After you enter the license number that you should have received from your email, you will then need to review and agree to the license terms. The options panel should now display information about the lookup limits. You can always refer back to here about what your limits are and when they reset. -IMAGE +\image html malware-scanner-global-options-panel.png @@ -37,7 +37,7 @@ Ingest Settings For each data source, you select if you want files to be uploaded if they have not already been analyzed. By default, they are uploaded. You can choose to not upload them though. -IMAGE +\image html malware-scanner-ingest-panel.png @@ -52,6 +52,7 @@ Seeing Results Once ingest has completed, the files with malware will be listed in the Malware node in the tree. -IMAGE + +\image html malware-artifact-tree.png */ diff --git a/docs/doxygen-user/images/Malware-scanner-global-options-panel-no-license.png b/docs/doxygen-user/images/Malware-scanner-global-options-panel-no-license.png new file mode 100644 index 0000000000000000000000000000000000000000..09bb7d8344de194cc29290d49f29d48eb60f446d GIT binary patch literal 56344 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 tcibBKuCn`>0A5L5}oViog zr{v-5;?TBNK0z{O=|S{|MDmzomF9M_TG!XSixUS7ubNt2%Bd*;uedF>O;YJN;pxfd zunamafviW>Uz=z?kqk^(L`})2t@pZ0^3OLbMo%$AmhJ?5vlULGS?bT8*qNrEBNDvI zvX*W0m!&3RSR$I)kY2Ir+1nHn!?{X2<7xJS3fBeo(ZjDx0#Eo-?MF58xc)hEldJ8p zU-sf+$K4@1w=!O(|I0weu-wUf9I?i8c63!`~OVLhT z<845-2sfb=b6)nult$VVayG-d36m^JP+sX(&Bp%9!W=5kbD@3GFx2n0AE4cqOG{T= z(_S~V=;4U=mPT!s5$dzCX?F+72r+TRS2?10*B@J?#i(d82T9hRJn2U7#HShJ)a=xo zrs=$}a0%++B7@QulUHpFhYaHD_#jDqRN4E(P05qwYU_oDSNTDKD;hV(A=NQo8siN{Pzq9q7f!&5Yt4vg_;j>PUC*kU&wDCjW@hN6xK^dcbz^5ybQ=lzkPh zm}K2DJ1z|i21{5WV|ORwp6TGUL$PPd+a{NCi66Sk_y-LgDAZYFDp>Y)5_wbixP5Tz z$mZT$*XP|e)U1l+q$iKsTiblqUVae_7T_y21x_UB=QNcOCXV<9cn#S(+~{%!hwyX! zhx~@4l8((?@tf)rg#dCoA54 z`{pPj$2SgIUHicwQF&yBRdUHUFY6#DA|kJ6YCkSg*PmTa_0{R=aT5rz1F2yE{D=s*GI=F?WhURzP$BE;shi;AVnS4xg;;A^hRRt6-bmzei*aid`To7U zSA8$wXo3)XgxY^5*dJ&nral^NSpyd8$UNYmsaqS0)L6Y!abceTva)}0P@z-2OfLLm zN4ok8f-(&%A?VIgPCDW`Bq6Re^>6sY?h}U{h%*NTiy=0D4lex<^ml2KRjkkb1@tT0Sr>V56BH*NZi8Z8WGyL(@1Tod-gK=?;3u#P1eNJ8t3CmFyVAvM=myDY`Sfy>sD5@*hB; zlsnvFMH?tY)eWp^2|eDu*#s^~T$hykXdN>8>e%Fue2vXC{8~=fne-jFicGTSPRh1? zM=ZZ*l}7tEHqQ8+tSr7dKC%cFZm^|K2k98rvjKS&_1la>S9NaFhDb8#8wP+oZIhK-zx6tO?i?b9kdek4oC_@3t+xo$k%$_`EjoA5;p5xFL z=TAcoIWi*bvnI69F`_gNN>Jz0EhKY#5D(IpOPa_N4_JFMJ3ubla=(mq3P>81W4`{; z7|rY!OS3Ic_?^s2vqvLFjjtR}HuF69D-JGydJDjqPP@~JlE~Uzx0hE;XK(Y;BxsTB z74~m`0n1*B(7QHsd7{_$n-inHJX82X7z==Qn?k2kQzI-hOp zYC4L);0RrhOXx9JfHzJgnhDm(_;?&2HNe%4d@?Xbd`?d&R{?vDGd09)9Dg@UimiV| zn%^(CN?t4gaS;hGTZwdSQ49CtWeSOylqpL&TO4RpWAMk(HJi7p3oaBVx(+o}Beim@(B%u5mCz4B zilipptIR0gAiqMtDluaSOuUilW5bSdx}E~JI2BeVg}f-9A7qMbcA&eJ1WOvCl{{0p18|{tci(+m zh<2^WT8pR{xbNR^lCirnTGG3|S{SLI-lWf5gTc$?f~Kg7w<1-0PR zwdH5TkX(rW?BGK?Et&ujzu77GK?x5~fKF{iLCEFR;MRl}K(@5k_1I9uV9+D%kc?N= zP#4j-uC}_=#MSs|`C?ET02m8`G>?O6z;0ocmAkF%$+9~2-jmZvhl!{5$dHL3rCsm6(5<5ZWKPTM8_%Q0y; zKZjX~uiqk?QR4n#S+_sb{>r?s#d|fB)C}yrc+zI@@BVbZ&2kWQq=e8*@^*T+TdLoY zT|P}rGFCvow literal 0 HcmV?d00001 diff --git a/docs/doxygen-user/images/ct_malware_license_agreement.png b/docs/doxygen-user/images/ct_malware_license_agreement.png deleted file mode 100644 index 030a722e469c6ba1964a40fb9b5c3efcc99d11ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 56663 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⋙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

ddu&d$z&P7jH9A-^e{LYV;n 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 z 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 literal 0 HcmV?d00001 diff --git a/docs/doxygen-user/images/malware-scanner-global-options-panel.png b/docs/doxygen-user/images/malware-scanner-global-options-panel.png new file mode 100644 index 0000000000000000000000000000000000000000..fd0b131832bfdf79e29ffae389b94f3f86f6b7a9 GIT binary patch literal 66206 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%0DW((Nx%Y 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

W%FjF6}| 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 Date: Mon, 21 Aug 2023 11:59:47 -0400 Subject: [PATCH 68/94] file upload api changes --- .../cybertriage/autopsy/ctapi/CTApiDAO.java | 9 ++--- .../autopsy/ctapi/CTCloudHttpClient.java | 33 +++++++++++-------- .../autopsy/ctapi/json/AuthTokenRequest.java | 13 ++++++++ .../malwarescan/MalwareScanIngestModule.java | 6 ++-- 4 files changed, 41 insertions(+), 20 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTApiDAO.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTApiDAO.java index c358feec61..e17e771b2a 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTApiDAO.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTApiDAO.java @@ -78,13 +78,14 @@ public class CTApiDAO { } public AuthTokenResponse getAuthToken(DecryptedLicenseResponse decrypted) throws CTCloudException { - return getAuthToken(decrypted, false); + return getAuthToken(decrypted, null); } - public AuthTokenResponse getAuthToken(DecryptedLicenseResponse decrypted, boolean fileUpload) throws CTCloudException { + public AuthTokenResponse getAuthToken(DecryptedLicenseResponse decrypted, Long fileUploadSize) throws CTCloudException { AuthTokenRequest authTokenRequest = new AuthTokenRequest() .setAutopsyVersion(getAppVersion()) - .setRequestFileUpload(fileUpload) + .setRequestFileUpload(fileUploadSize != null && fileUploadSize > 0) + .setFileUploadSize(fileUploadSize != null && fileUploadSize > 0 ? fileUploadSize : null) .setBoostLicenseId(decrypted.getBoostLicenseId()) .setHostId(decrypted.getLicenseHostId()); @@ -92,7 +93,7 @@ public class CTApiDAO { } public void uploadFile(String url, String fileName, InputStream fileIs) throws CTCloudException { - httpClient.doFileUploadPost(url, fileName, fileIs); + httpClient.doFileUploadPut(url, fileName, fileIs); } public void uploadMeta(AuthenticatedRequestData authenticatedRequestData, MetadataUploadRequest metaRequest) throws CTCloudException { diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java index 0a280c87e8..a5a1e0b554 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java @@ -55,11 +55,13 @@ import org.apache.http.HttpStatus; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.util.EntityUtils; import org.apache.http.client.utils.URIBuilder; import org.apache.http.entity.ContentType; +import org.apache.http.entity.InputStreamEntity; import org.apache.http.entity.StringEntity; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.sleuthkit.autopsy.coreutils.Logger; @@ -184,7 +186,7 @@ class CTCloudHttpClient { return null; } - public void doFileUploadPost(String fullUrlPath, String fileName, InputStream fileIs) throws CTCloudException { + public void doFileUploadPut(String fullUrlPath, String fileName, InputStream fileIs) throws CTCloudException { URI postUri; try { postUri = new URI(fullUrlPath); @@ -195,23 +197,26 @@ class CTCloudHttpClient { try (CloseableHttpClient httpclient = createConnection(proxySelector, sslContext)) { LOGGER.log(Level.INFO, "initiating http post request to ctcloud server " + fullUrlPath); - HttpPost post = new HttpPost(postUri); - configureRequestTimeout(post); + HttpPut put = new HttpPut(postUri); + configureRequestTimeout(put); - post.addHeader("Connection", "keep-alive"); + put.addHeader("Connection", "keep-alive"); + put.addHeader("Content-Type", "application/octet-stream"); - MultipartEntityBuilder builder = MultipartEntityBuilder.create(); - builder.addBinaryBody( - "file", - fileIs, - ContentType.APPLICATION_OCTET_STREAM, - fileName - ); +// MultipartEntityBuilder builder = MultipartEntityBuilder.create(); +// builder.addBinaryBody( +// "file", +// fileBytes, +// ContentType.APPLICATION_OCTET_STREAM, +// file.getFileName() +// ); +// +// HttpEntity multipart = builder.build(); +// post.setEntity(multipart); - HttpEntity multipart = builder.build(); - post.setEntity(multipart); + put.setEntity(new InputStreamEntity(fileIs)); - try (CloseableHttpResponse response = httpclient.execute(post)) { + try (CloseableHttpResponse response = httpclient.execute(put)) { int statusCode = response.getStatusLine().getStatusCode(); if (statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_NO_CONTENT) { LOGGER.log(Level.INFO, "Response Received. - Status OK"); diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/AuthTokenRequest.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/AuthTokenRequest.java index 6a093fee8e..f137818346 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/AuthTokenRequest.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/AuthTokenRequest.java @@ -34,6 +34,9 @@ public class AuthTokenRequest { @JsonProperty("requestFileUpload") private boolean requestFileUpload; + @JsonProperty("fileUploadSize") + private Long fileUploadSize; + @JsonProperty("host_id") private String hostId; @@ -64,6 +67,16 @@ public class AuthTokenRequest { return this; } + public Long getFileUploadSize() { + return fileUploadSize; + } + + public AuthTokenRequest setFileUploadSize(Long fileUploadSize) { + this.fileUploadSize = fileUploadSize; + return this; + } + + public String getHostId() { return hostId; } diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java index 4698392478..cbe76ba235 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java @@ -105,8 +105,10 @@ class MalwareScanIngestModule implements FileIngestModule { //minimum file uploads left before issuing warning private static final long LOW_UPLOADS_REMAINING = 25; + // min and max upload size in bytes private static final long MIN_UPLOAD_SIZE = 1; - private static final long MAX_UPLOAD_SIZE = 1_000_000_000; + private static final long MAX_UPLOAD_SIZE = 100_000_000; // 100MB + private static final int NUM_FILE_UPLOAD_RETRIES = 7; private static final long FILE_UPLOAD_RETRY_SLEEP_MILLIS = 60 * 1000; @@ -634,7 +636,7 @@ class MalwareScanIngestModule implements FileIngestModule { } // get auth token / file upload url - AuthTokenResponse authTokenResponse = ctApiDAO.getAuthToken(ingestJobState.getLicenseInfo().getDecryptedLicense(), true); + AuthTokenResponse authTokenResponse = ctApiDAO.getAuthToken(ingestJobState.getLicenseInfo().getDecryptedLicense(), af.getSize()); if (StringUtils.isBlank(authTokenResponse.getFileUploadUrl())) { throw new CTCloudException(CTCloudException.ErrorCode.NETWORK_ERROR); } else if (remaining(authTokenResponse.getFileUploadLimit(), authTokenResponse.getFileUploadCount()) <= 0) { From 0176f83d84d416c7b519c8c1f2cb57395248503c Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Mon, 21 Aug 2023 14:57:13 -0400 Subject: [PATCH 69/94] fixes Fixes --- .../autopsy/ctoptions/CTOptionsPanel.java | 2 ++ .../ctcloud/CTMalwareScannerOptionsPanel.form | 9 ++------- .../ctcloud/CTMalwareScannerOptionsPanel.java | 13 +++++++++++-- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/CTOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/CTOptionsPanel.java index 29f8bec3a4..83a4a9a51a 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/CTOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/CTOptionsPanel.java @@ -24,6 +24,7 @@ import java.awt.GridBagConstraints; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.Collection; +import java.util.Comparator; import java.util.List; import java.util.logging.Logger; import java.util.stream.Collectors; @@ -63,6 +64,7 @@ public class CTOptionsPanel extends IngestModuleGlobalSettingsPanel { } }) .filter(item -> item != null) + .sorted(Comparator.comparing(p -> p.getClass().getSimpleName().toUpperCase()).reversed()) .collect(Collectors.toList()); addSubOptionsPanels(this.subPanels); } diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form index 841490d657..52595d16a3 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form @@ -132,7 +132,7 @@ - + @@ -231,10 +231,6 @@ - - - - @@ -254,8 +250,7 @@ - - + diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java index 4d4f156fe9..fd39cd5fad 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java @@ -134,6 +134,11 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { setMalwareScansDisplay(null, null); if (licenseInfo != null) { loadMalwareScansInfo(licenseInfo); + this.purchaseFromLabel.setVisible(false); + this.purchaseLink.setVisible(false); + } else { + this.purchaseFromLabel.setVisible(false); + this.purchaseLink.setVisible(false); } } @@ -241,8 +246,8 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { hashLookupsRemainingLabel = new javax.swing.JLabel(); fileUploadsRemainingLabel = new javax.swing.JLabel(); javax.swing.JPanel purchasePanel = new javax.swing.JPanel(); - javax.swing.JLabel purchaseFromLabel = new javax.swing.JLabel(); - javax.swing.JLabel purchaseLink = new javax.swing.JLabel(); + purchaseFromLabel = new javax.swing.JLabel(); + purchaseLink = new javax.swing.JLabel(); setLayout(new java.awt.GridBagLayout()); @@ -384,7 +389,9 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; malwareScansPanel.add(malwareScannerStatsPanel, gridBagConstraints); purchasePanel.setLayout(new java.awt.GridBagLayout()); @@ -732,5 +739,7 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { private javax.swing.JPanel malwareScansPanel; private javax.swing.JLabel maxFileUploadsLabel; private javax.swing.JLabel maxHashLookupsLabel; + private javax.swing.JLabel purchaseFromLabel; + private javax.swing.JLabel purchaseLink; // End of variables declaration//GEN-END:variables } From 780293331eea05c7b7d5deb18c393f52984e6a96 Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Mon, 21 Aug 2023 16:11:40 -0400 Subject: [PATCH 70/94] fix alignment fix alignment --- .../ctcloud/CTMalwareScannerOptionsPanel.form | 10 +++++----- .../ctcloud/CTMalwareScannerOptionsPanel.java | 10 +++++++--- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form index 52595d16a3..0553a46df1 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form @@ -84,7 +84,7 @@ - + @@ -96,7 +96,7 @@ - + @@ -108,7 +108,7 @@ - + @@ -123,7 +123,7 @@ - + @@ -194,7 +194,7 @@ - + diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java index fd39cd5fad..dfdea83ea9 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java @@ -282,6 +282,7 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 1; + gridBagConstraints.gridwidth = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); @@ -289,8 +290,9 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { org.openide.awt.Mnemonics.setLocalizedText(licenseInfoIdLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.licenseInfoIdLabel.text")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; + gridBagConstraints.gridx = 2; gridBagConstraints.gridy = 1; + gridBagConstraints.gridwidth = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); @@ -300,6 +302,7 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 2; + gridBagConstraints.gridwidth = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); @@ -312,7 +315,7 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { } }); gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; + gridBagConstraints.gridx = 3; gridBagConstraints.gridy = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST; gridBagConstraints.weightx = 1.0; @@ -370,8 +373,9 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { org.openide.awt.Mnemonics.setLocalizedText(hashLookupsRemainingLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.hashLookupsRemainingLabel.text")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; + gridBagConstraints.gridx = 2; gridBagConstraints.gridy = 1; + gridBagConstraints.gridwidth = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); From ca16f87f5d8d9fcc3675948440591de8ee11aa28 Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Mon, 21 Aug 2023 16:20:58 -0400 Subject: [PATCH 71/94] Align panel text align panel text --- .../ctcloud/CTMalwareScannerOptionsPanel.form | 75 ++++------ .../ctcloud/CTMalwareScannerOptionsPanel.java | 138 ++++++++---------- 2 files changed, 95 insertions(+), 118 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form index 0553a46df1..c84d92fecc 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form @@ -96,7 +96,7 @@ - + @@ -123,42 +123,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -170,19 +135,19 @@ - + - + - + - + @@ -194,7 +159,31 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -206,7 +195,7 @@ - + diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java index dfdea83ea9..c5cbed663f 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java @@ -238,12 +238,11 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { licenseInfoIdLabel = new javax.swing.JLabel(); licenseInfoUserLabel = new javax.swing.JLabel(); licenseInfoAddButton = new javax.swing.JButton(); - malwareScannerStatsPanel = new javax.swing.JPanel(); - malwareScansMessageLabel = new javax.swing.JLabel(); - maxHashLookupsLabel = new javax.swing.JLabel(); maxFileUploadsLabel = new javax.swing.JLabel(); - countersResetLabel = new javax.swing.JLabel(); + maxHashLookupsLabel = new javax.swing.JLabel(); hashLookupsRemainingLabel = new javax.swing.JLabel(); + malwareScansMessageLabel = new javax.swing.JLabel(); + countersResetLabel = new javax.swing.JLabel(); fileUploadsRemainingLabel = new javax.swing.JLabel(); javax.swing.JPanel purchasePanel = new javax.swing.JPanel(); purchaseFromLabel = new javax.swing.JLabel(); @@ -290,7 +289,7 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { org.openide.awt.Mnemonics.setLocalizedText(licenseInfoIdLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.licenseInfoIdLabel.text")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 2; + gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 1; gridBagConstraints.gridwidth = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; @@ -315,13 +314,71 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { } }); gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 3; + gridBagConstraints.gridx = 2; gridBagConstraints.gridy = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); licenseInfoPanel.add(licenseInfoAddButton, gridBagConstraints); + org.openide.awt.Mnemonics.setLocalizedText(maxFileUploadsLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.maxFileUploadsLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 4; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); + licenseInfoPanel.add(maxFileUploadsLabel, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(maxHashLookupsLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.maxHashLookupsLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 3; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); + licenseInfoPanel.add(maxHashLookupsLabel, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(hashLookupsRemainingLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.hashLookupsRemainingLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 3; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); + licenseInfoPanel.add(hashLookupsRemainingLabel, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(malwareScansMessageLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.malwareScansMessageLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 3; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); + licenseInfoPanel.add(malwareScansMessageLabel, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(countersResetLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.countersResetLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 5; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); + licenseInfoPanel.add(countersResetLabel, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(fileUploadsRemainingLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.fileUploadsRemainingLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 4; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); + licenseInfoPanel.add(fileUploadsRemainingLabel, gridBagConstraints); + gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 1; @@ -330,74 +387,6 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { gridBagConstraints.weightx = 1.0; malwareScansPanel.add(licenseInfoPanel, gridBagConstraints); - malwareScannerStatsPanel.setLayout(new java.awt.GridBagLayout()); - - org.openide.awt.Mnemonics.setLocalizedText(malwareScansMessageLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.malwareScansMessageLabel.text")); // NOI18N - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - gridBagConstraints.gridwidth = 2; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); - malwareScannerStatsPanel.add(malwareScansMessageLabel, gridBagConstraints); - - org.openide.awt.Mnemonics.setLocalizedText(maxHashLookupsLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.maxHashLookupsLabel.text")); // NOI18N - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 1; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); - malwareScannerStatsPanel.add(maxHashLookupsLabel, gridBagConstraints); - - org.openide.awt.Mnemonics.setLocalizedText(maxFileUploadsLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.maxFileUploadsLabel.text")); // NOI18N - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 2; - gridBagConstraints.gridwidth = 2; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); - malwareScannerStatsPanel.add(maxFileUploadsLabel, gridBagConstraints); - - org.openide.awt.Mnemonics.setLocalizedText(countersResetLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.countersResetLabel.text")); // NOI18N - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 3; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); - malwareScannerStatsPanel.add(countersResetLabel, gridBagConstraints); - - org.openide.awt.Mnemonics.setLocalizedText(hashLookupsRemainingLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.hashLookupsRemainingLabel.text")); // NOI18N - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 2; - gridBagConstraints.gridy = 1; - gridBagConstraints.gridwidth = 2; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); - malwareScannerStatsPanel.add(hashLookupsRemainingLabel, gridBagConstraints); - - org.openide.awt.Mnemonics.setLocalizedText(fileUploadsRemainingLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.fileUploadsRemainingLabel.text")); // NOI18N - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); - malwareScannerStatsPanel.add(fileUploadsRemainingLabel, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 2; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.weightx = 1.0; - malwareScansPanel.add(malwareScannerStatsPanel, gridBagConstraints); - purchasePanel.setLayout(new java.awt.GridBagLayout()); org.openide.awt.Mnemonics.setLocalizedText(purchaseFromLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.purchaseFromLabel.text")); // NOI18N @@ -738,7 +727,6 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { private javax.swing.JLabel licenseInfoIdLabel; private javax.swing.JLabel licenseInfoMessageLabel; private javax.swing.JLabel licenseInfoUserLabel; - private javax.swing.JPanel malwareScannerStatsPanel; private javax.swing.JLabel malwareScansMessageLabel; private javax.swing.JPanel malwareScansPanel; private javax.swing.JLabel maxFileUploadsLabel; From 14d8a09288eeadb7d20afd6afa7672e52bdebe24 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 21 Aug 2023 16:35:24 -0400 Subject: [PATCH 72/94] file upload changes --- .../cybertriage/autopsy/ctapi/CTApiDAO.java | 5 +- .../autopsy/ctapi/CTCloudHttpClient.java | 41 +++++------ .../autopsy/ctapi/json/FileUploadRequest.java | 69 +++++++++++++++++++ .../malwarescan/MalwareScanIngestModule.java | 13 +++- 4 files changed, 103 insertions(+), 25 deletions(-) create mode 100644 Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/FileUploadRequest.java diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTApiDAO.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTApiDAO.java index e17e771b2a..f21873f565 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTApiDAO.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTApiDAO.java @@ -25,6 +25,7 @@ import com.basistech.df.cybertriage.autopsy.ctapi.json.CTCloudBean; import com.basistech.df.cybertriage.autopsy.ctapi.json.CTCloudBeanResponse; import com.basistech.df.cybertriage.autopsy.ctapi.json.DecryptedLicenseResponse; import com.basistech.df.cybertriage.autopsy.ctapi.json.FileReputationRequest; +import com.basistech.df.cybertriage.autopsy.ctapi.json.FileUploadRequest; import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseRequest; import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseResponse; import com.basistech.df.cybertriage.autopsy.ctapi.json.MetadataUploadRequest; @@ -92,8 +93,8 @@ public class CTApiDAO { return httpClient.doPost(AUTH_TOKEN_REQUEST_PATH, authTokenRequest, AuthTokenResponse.class); } - public void uploadFile(String url, String fileName, InputStream fileIs) throws CTCloudException { - httpClient.doFileUploadPut(url, fileName, fileIs); + public void uploadFile(FileUploadRequest fileUploadRequest) throws CTCloudException { + httpClient.doFileUploadPut(fileUploadRequest); } public void uploadMeta(AuthenticatedRequestData authenticatedRequestData, MetadataUploadRequest metaRequest) throws CTCloudException { diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java index a5a1e0b554..0a7c69cdee 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java @@ -18,6 +18,8 @@ */ package com.basistech.df.cybertriage.autopsy.ctapi; +import com.basistech.df.cybertriage.autopsy.ctapi.CTCloudException.ErrorCode; +import com.basistech.df.cybertriage.autopsy.ctapi.json.FileUploadRequest; import com.basistech.df.cybertriage.autopsy.ctapi.util.ObjectMapperUtil; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; @@ -63,7 +65,6 @@ import org.apache.http.client.utils.URIBuilder; import org.apache.http.entity.ContentType; import org.apache.http.entity.InputStreamEntity; import org.apache.http.entity.StringEntity; -import org.apache.http.entity.mime.MultipartEntityBuilder; import org.sleuthkit.autopsy.coreutils.Logger; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; @@ -186,10 +187,23 @@ class CTCloudHttpClient { return null; } - public void doFileUploadPut(String fullUrlPath, String fileName, InputStream fileIs) throws CTCloudException { - URI postUri; + public void doFileUploadPut(FileUploadRequest fileUploadRequest) throws CTCloudException { + if (fileUploadRequest == null) { + throw new CTCloudException(ErrorCode.BAD_REQUEST, new IllegalArgumentException("fileUploadRequest cannot be null")); + } + + String fullUrlPath = fileUploadRequest.getFullUrlPath(); + String fileName = fileUploadRequest.getFileName(); + InputStream fileInputStream = fileUploadRequest.getFileInputStream(); + Long contentLength = fileUploadRequest.getContentLength(); + + if (StringUtils.isBlank(fullUrlPath) || fileInputStream == null || contentLength == null || contentLength <= 0) { + throw new CTCloudException(ErrorCode.BAD_REQUEST, new IllegalArgumentException("fullUrlPath, fileInputStream, contentLength must not be empty, null or less than 0")); + } + + URI putUri; try { - postUri = new URI(fullUrlPath); + putUri = new URI(fullUrlPath); } catch (URISyntaxException ex) { LOGGER.log(Level.WARNING, "Wrong URL syntax for CT Cloud " + fullUrlPath, ex); throw new CTCloudException(CTCloudException.ErrorCode.UNKNOWN, ex); @@ -197,24 +211,11 @@ class CTCloudHttpClient { try (CloseableHttpClient httpclient = createConnection(proxySelector, sslContext)) { LOGGER.log(Level.INFO, "initiating http post request to ctcloud server " + fullUrlPath); - HttpPut put = new HttpPut(postUri); + HttpPut put = new HttpPut(putUri); configureRequestTimeout(put); put.addHeader("Connection", "keep-alive"); - put.addHeader("Content-Type", "application/octet-stream"); - -// MultipartEntityBuilder builder = MultipartEntityBuilder.create(); -// builder.addBinaryBody( -// "file", -// fileBytes, -// ContentType.APPLICATION_OCTET_STREAM, -// file.getFileName() -// ); -// -// HttpEntity multipart = builder.build(); -// post.setEntity(multipart); - - put.setEntity(new InputStreamEntity(fileIs)); + put.setEntity(new InputStreamEntity(fileInputStream, contentLength, ContentType.APPLICATION_OCTET_STREAM)); try (CloseableHttpResponse response = httpclient.execute(put)) { int statusCode = response.getStatusLine().getStatusCode(); @@ -386,7 +387,7 @@ class CTCloudHttpClient { HttpClientBuilder builder; if (ProxySettings.getProxyType() != ProxySettings.DIRECT_CONNECTION - && StringUtils.isBlank(ProxySettings.getAuthenticationUsername()) + && StringUtils.isBlank(ProxySettings.getAuthenticationUsername()) && ArrayUtils.isEmpty(ProxySettings.getAuthenticationPassword()) && WinHttpClients.isWinAuthAvailable()) { diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/FileUploadRequest.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/FileUploadRequest.java new file mode 100644 index 0000000000..48d8dc77b4 --- /dev/null +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/FileUploadRequest.java @@ -0,0 +1,69 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2023 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.basistech.df.cybertriage.autopsy.ctapi.json; + +import java.io.InputStream; + +/** + * Data for a file upload request. + */ +public class FileUploadRequest { + + private String fullUrlPath; + private String fileName; + private InputStream fileInputStream; + private Long contentLength; + + public String getFullUrlPath() { + return fullUrlPath; + } + + public FileUploadRequest setFullUrlPath(String fullUrlPath) { + this.fullUrlPath = fullUrlPath; + return this; + } + + public String getFileName() { + return fileName; + } + + public FileUploadRequest setFileName(String fileName) { + this.fileName = fileName; + return this; + } + + public InputStream getFileInputStream() { + return fileInputStream; + } + + public FileUploadRequest setFileInputStream(InputStream fileInputStream) { + this.fileInputStream = fileInputStream; + return this; + } + + public Long getContentLength() { + return contentLength; + } + + public FileUploadRequest setContentLength(Long contentLength) { + this.contentLength = contentLength; + return this; + } + +} diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java index cbe76ba235..c66b88cce9 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java @@ -23,6 +23,7 @@ import com.basistech.df.cybertriage.autopsy.ctapi.CTCloudException; import com.basistech.df.cybertriage.autopsy.ctapi.json.AuthTokenResponse; import com.basistech.df.cybertriage.autopsy.ctapi.json.AuthenticatedRequestData; import com.basistech.df.cybertriage.autopsy.ctapi.json.CTCloudBean; +import com.basistech.df.cybertriage.autopsy.ctapi.json.FileUploadRequest; import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseInfo; import com.basistech.df.cybertriage.autopsy.ctapi.json.MalwareResultBean.Status; import com.basistech.df.cybertriage.autopsy.ctapi.json.MetadataUploadRequest; @@ -108,7 +109,7 @@ class MalwareScanIngestModule implements FileIngestModule { // min and max upload size in bytes private static final long MIN_UPLOAD_SIZE = 1; private static final long MAX_UPLOAD_SIZE = 100_000_000; // 100MB - + private static final int NUM_FILE_UPLOAD_RETRIES = 7; private static final long FILE_UPLOAD_RETRY_SLEEP_MILLIS = 60 * 1000; @@ -654,7 +655,13 @@ class MalwareScanIngestModule implements FileIngestModule { // upload bytes ReadContentInputStream fileInputStream = new ReadContentInputStream(af); - ctApiDAO.uploadFile(authTokenResponse.getFileUploadUrl(), af.getName(), fileInputStream); + + ctApiDAO.uploadFile(new FileUploadRequest() + .setContentLength(af.getSize()) + .setFileInputStream(fileInputStream) + .setFileName(af.getName()) + .setFullUrlPath(authTokenResponse.getFileUploadUrl()) + ); // upload metadata MetadataUploadRequest metaRequest = new MetadataUploadRequest() @@ -843,7 +850,7 @@ class MalwareScanIngestModule implements FileIngestModule { : Bundle.MalwareScanIngestModule_SharedProcessing_createAnalysisResult_No(); String justification = cloudBean.getMalwareResult().getStatusDescription(); - + return ingestJobState.getTskCase().getBlackboard().newAnalysisResult( ingestJobState.getMalwareType(), objId, From c0b8145f5b037f5258fc4abef02ed055a000cb6d Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Mon, 21 Aug 2023 22:51:35 -0400 Subject: [PATCH 73/94] Minor Fixes from code review MInor fixes from code review --- .../ctcloud/CTMalwareScannerOptionsPanel.form | 14 ++++++------- .../ctcloud/CTMalwareScannerOptionsPanel.java | 20 +++++++++++-------- .../CTIncidentImportOptionsPanel.form | 3 +++ .../CTIncidentImportOptionsPanel.java | 1 + .../malwarescan/MalwareScanIngestModule.java | 6 +++++- 5 files changed, 28 insertions(+), 16 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form index c84d92fecc..dcdfb0a767 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form @@ -72,7 +72,7 @@ - + @@ -84,7 +84,7 @@ - + @@ -96,7 +96,7 @@ - + @@ -108,7 +108,7 @@ - + @@ -135,7 +135,7 @@ - + @@ -159,7 +159,7 @@ - + @@ -171,7 +171,7 @@ - + diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java index c5cbed663f..8b9b169d67 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java @@ -270,7 +270,6 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; - gridBagConstraints.gridwidth = 2; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.weightx = 1.0; @@ -281,7 +280,6 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 1; - gridBagConstraints.gridwidth = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); @@ -291,7 +289,6 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 1; - gridBagConstraints.gridwidth = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); @@ -301,7 +298,6 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 2; - gridBagConstraints.gridwidth = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); @@ -325,7 +321,6 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 4; - gridBagConstraints.gridwidth = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); @@ -344,7 +339,6 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 3; - gridBagConstraints.gridwidth = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); @@ -354,7 +348,6 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 3; - gridBagConstraints.gridwidth = 2; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.weightx = 1.0; @@ -631,7 +624,18 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { protected void done() { try { LicenseResponse licenseResponse = get(); - SwingUtilities.invokeLater(() -> acceptEula(licenseResponse)); + if (licenseResponse != null && licenseResponse.isSuccess()) { + SwingUtilities.invokeLater(() -> acceptEula(licenseResponse)); + } else { + logger.log(Level.WARNING, "An API error occurred while fetching license information. License fetch was not successful"); + JOptionPane.showMessageDialog( + CTMalwareScannerOptionsPanel.this, + CTCloudException.ErrorCode.UN_AUTHORIZED.getDescription(), + Bundle.CTMalwareScannerOptionsPanel_LicenseFetcher_apiErr_title(), + JOptionPane.ERROR_MESSAGE); + setLicenseDisplay(licenseInfo, null); + loadMalwareScansInfo(licenseInfo); + } } catch (InterruptedException | CancellationException ex) { // ignore cancellation; just load current license setLicenseDisplay(licenseInfo, null); diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.form b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.form index d887a3765e..7382a2de2c 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.form +++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.form @@ -77,6 +77,9 @@ + + + diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.java index 8a399c0f0f..bf018701ca 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.java @@ -161,6 +161,7 @@ public class CTIncidentImportOptionsPanel extends CTOptionsSubPanel { instructionsTextLabel.getAccessibleContext().setAccessibleName("For instructions on obtaining the module refer to:"); org.openide.awt.Mnemonics.setLocalizedText(instructionsLinkLabel, getHtmlLink(CT_IMPORTER_DOC_LINK)); + instructionsLinkLabel.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR)); instructionsLinkLabel.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { instructionsLinkLabelMouseClicked(evt); diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java index 190b1412ce..bf395eb4b5 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java @@ -781,7 +781,11 @@ class MalwareScanIngestModule implements FileIngestModule { for (Long objId : objIds) { AnalysisResult res = createAnalysisResult(ingestJobState, trans, result, objId); if (res != null) { - createdArtifacts.add(res); + // only post results that have score NOTABLE or LIKELY_NOTABLE + Score score = res.getScore(); + if (score.getSignificance() == Score.Significance.NOTABLE || score.getSignificance() == Score.Significance.LIKELY_NOTABLE) { + createdArtifacts.add(res); + } } } } From 53c848e5ada8ea642d3a180bbd9e414c1efca6bc Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Tue, 22 Aug 2023 08:19:50 -0400 Subject: [PATCH 74/94] fixes fixes --- .../ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java | 9 +++++++-- .../cybertriage/autopsy/incidentoptions/CTSettings.java | 3 ++- .../autopsy/incidentoptions/CTSettingsPersistence.java | 3 ++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java index 8b9b169d67..375943188c 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java @@ -137,8 +137,8 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { this.purchaseFromLabel.setVisible(false); this.purchaseLink.setVisible(false); } else { - this.purchaseFromLabel.setVisible(false); - this.purchaseLink.setVisible(false); + this.purchaseFromLabel.setVisible(true); + this.purchaseLink.setVisible(true); } } @@ -485,7 +485,12 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { this.licenseInfoExpiresLabel.setVisible(false); this.licenseInfoIdLabel.setVisible(false); this.licenseInfoUserLabel.setVisible(false); + this.purchaseFromLabel.setVisible(true); + this.purchaseLink.setVisible(true); } else { + this.purchaseFromLabel.setVisible(false); + this.purchaseLink.setVisible(false); + this.licenseInfoExpiresLabel.setVisible(true); this.licenseInfoExpiresLabel.setText(Bundle.CTMalwareScannerOptionsPanel_licenseInfo_expires( this.licenseInfo.getDecryptedLicense().getExpirationDate() == null diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettings.java b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettings.java index 4e9d4b4697..35e2d108ea 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettings.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettings.java @@ -23,7 +23,8 @@ import java.util.logging.Logger; import org.openide.modules.Places; /** - * CT settings that don't include license information. + * CT settings that don't include license information. This code must be kept in-sync with code in + * CT Autopsy Importer NBM. */ public class CTSettings { diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettingsPersistence.java b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettingsPersistence.java index d9addd1960..be60813edd 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettingsPersistence.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettingsPersistence.java @@ -22,7 +22,8 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.PlatformUtil; /** - * Handles persisting CT Settings. + * Handles persisting CT Settings. This code must be kept in-sync with code in + * CT Autopsy Importer NBM. */ public class CTSettingsPersistence { From 2de8646ba7cb968e1ac52f7546a64723352f7d42 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 22 Aug 2023 11:45:11 -0400 Subject: [PATCH 75/94] updates for ignoring placeholder paths --- Core/src/org/sleuthkit/autopsy/casemodule/Case.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index b1d2f28c31..57739bda76 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -194,6 +194,8 @@ public class Case { private final SleuthkitEventListener sleuthkitEventListener; private CollaborationMonitor collaborationMonitor; private Services caseServices; + // matches something like '\\.\PHYSICALDRIVE0' + private static final String PLACEHOLDER_DS_PATH_REGEX = "^\\s*\\\\\\\\\\.\\\\(PHYSICALDRIVE)\\d*\\s*$"; private volatile boolean hasDataSource = false; private volatile boolean hasData = false; @@ -1305,6 +1307,13 @@ public class Case { String path = entry.getValue(); boolean fileExists = (new File(path).isFile() || DriveUtils.driveExists(path)); if (!fileExists) { + // CT-7336: ignore relocating datasources if file provider is present and placeholder path is used. + if (newCurrentCase.getMetadata() != null + && !StringUtils.isBlank(newCurrentCase.getMetadata().getContentProviderName()) + && (path == null || path.matches(PLACEHOLDER_DS_PATH_REGEX))) { + continue; + } + try { // Using invokeAndWait means that the dialog will // open on the EDT but this thread will wait for an From 1c963d6480944acf4857d5b84c100bf393aca316 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 22 Aug 2023 12:39:47 -0400 Subject: [PATCH 76/94] fixes from testing --- Core/src/org/sleuthkit/autopsy/casemodule/Case.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 57739bda76..f39b286f1c 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -195,7 +195,7 @@ public class Case { private CollaborationMonitor collaborationMonitor; private Services caseServices; // matches something like '\\.\PHYSICALDRIVE0' - private static final String PLACEHOLDER_DS_PATH_REGEX = "^\\s*\\\\\\\\\\.\\\\(PHYSICALDRIVE)\\d*\\s*$"; + private static final String PLACEHOLDER_DS_PATH_REGEX = "^\\s*\\\\\\\\\\.\\\\(PHYSICALDRIVE\\d*)\\s*$"; private volatile boolean hasDataSource = false; private volatile boolean hasData = false; @@ -1305,7 +1305,7 @@ public class Case { for (Map.Entry entry : imgPaths.entrySet()) { long obj_id = entry.getKey(); String path = entry.getValue(); - boolean fileExists = (new File(path).isFile() || DriveUtils.driveExists(path)); + boolean fileExists = (new File(path).exists()|| DriveUtils.driveExists(path)); if (!fileExists) { // CT-7336: ignore relocating datasources if file provider is present and placeholder path is used. if (newCurrentCase.getMetadata() != null From 6bc95d1253cf8436970c0dcb8fe47fc98cace7cb Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 22 Aug 2023 14:26:42 -0400 Subject: [PATCH 77/94] updates for message --- .../org/sleuthkit/autopsy/casemodule/Bundle.properties | 4 ++-- .../sleuthkit/autopsy/casemodule/Bundle.properties-MERGED | 4 ++-- Core/src/org/sleuthkit/autopsy/casemodule/Case.java | 8 +++++--- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index cae89e41ce..92b64b840b 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -66,8 +66,8 @@ Case.open.msgDlg.updated.msg=Updated case database schema.\nA backup copy of the Case.open.msgDlg.updated.title=Case Database Schema Update Case.checkImgExist.confDlg.doesntExist.msg=One of the images associated with \n\ this case are missing. Would you like to search for them now?\n\ -Previously, the image was located at:\n\ -{0}\n\ +Previously, the image with host, {0}, was located at:\n\ +{1}\n\ Please note that you will still be able to browse directories and generate reports\n\ if you choose No, but you will not be able to view file content or run the ingest process. Case.checkImgExist.confDlg.doesntExist.title=Missing Image diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED index dc96292d9a..ce1fb9aa70 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED @@ -253,8 +253,8 @@ Case.open.msgDlg.updated.msg=Updated case database schema.\nA backup copy of the Case.open.msgDlg.updated.title=Case Database Schema Update Case.checkImgExist.confDlg.doesntExist.msg=One of the images associated with \n\ this case are missing. Would you like to search for them now?\n\ -Previously, the image was located at:\n\ -{0}\n\ +Previously, the image with host, {0}, was located at:\n\ +{1}\n\ Please note that you will still be able to browse directories and generate reports\n\ if you choose No, but you will not be able to view file content or run the ingest process. Case.checkImgExist.confDlg.doesntExist.title=Missing Image diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index f39b286f1c..eb279febe7 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -195,7 +195,7 @@ public class Case { private CollaborationMonitor collaborationMonitor; private Services caseServices; // matches something like '\\.\PHYSICALDRIVE0' - private static final String PLACEHOLDER_DS_PATH_REGEX = "^\\s*\\\\\\\\\\.\\\\(PHYSICALDRIVE\\d*)\\s*$"; + private static final String PLACEHOLDER_DS_PATH_REGEX = "^\\s*\\\\\\\\\\.\\\\PHYSICALDRIVE\\d*\\s*$"; private volatile boolean hasDataSource = false; private volatile boolean hasData = false; @@ -1315,6 +1315,8 @@ public class Case { } try { + DataSource ds = newCurrentCase.getSleuthkitCase().getDataSource(obj_id); + String hostName = StringUtils.defaultString(ds.getHost() == null ? "" : ds.getHost().getName()); // Using invokeAndWait means that the dialog will // open on the EDT but this thread will wait for an // answer. Using invokeLater would cause this loop to @@ -1324,7 +1326,7 @@ public class Case { public void run() { int response = JOptionPane.showConfirmDialog( mainFrame, - NbBundle.getMessage(Case.class, "Case.checkImgExist.confDlg.doesntExist.msg", path), + NbBundle.getMessage(Case.class, "Case.checkImgExist.confDlg.doesntExist.msg", hostName, path), NbBundle.getMessage(Case.class, "Case.checkImgExist.confDlg.doesntExist.title"), JOptionPane.YES_NO_OPTION); if (response == JOptionPane.YES_OPTION) { @@ -1336,7 +1338,7 @@ public class Case { } }); - } catch (InterruptedException | InvocationTargetException ex) { + } catch (InterruptedException | InvocationTargetException | TskCoreException | TskDataException ex) { logger.log(Level.SEVERE, "Failed to show missing image confirmation dialog", ex); //NON-NLS } } From 2ec56b2dbab82863b563ae12a48fa3ae2ec385b0 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Wed, 23 Aug 2023 08:16:58 -0400 Subject: [PATCH 78/94] Update NEWS --- NEWS.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NEWS.txt b/NEWS.txt index b8db91ca62..f6658a92ed 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -9,7 +9,7 @@ Library Updates Ingest Module Updates: - Recent Activity checks for malicious Chrome extensions from list provided by https://github.com/randomaccess3/detections - Keyword Search module now can search without needing to index text into Solr. -- New Cyber Triage Malware Scanner module that uses Reversing Labs (requires license) +- New Cyber Triage Malware Scanner module that uses Reversing Labs (requires license). https://www.cybertriage.com/autopsy-malware-module/ Add Data Source Updates: - Timestamps for logical files can be added. Issue https://github.com/sleuthkit/autopsy/issues/5852, https://github.com/sleuthkit/autopsy/issues/1788 @@ -24,7 +24,7 @@ Bugs: - Fix exporting of CSV files. Issue https://github.com/sleuthkit/autopsy/issues/6717 Misc: -- Added File Repository concept for data source files that are in a central location +- Added File Repository concept for data source files that are in a central location. Required for Cyber Triage import feature. - Added Spanish language support, contributor https://github.com/AburtoArielPM ---------------- VERSION 4.20.0 -------------- From 6e5e2ff2f53fd3bbda4776003496628d0955cf1e Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 23 Aug 2023 12:59:58 -0400 Subject: [PATCH 79/94] fix for local app data on non-windows systems --- .../df/cybertriage/autopsy/incidentoptions/CTSettings.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettings.java b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettings.java index 35e2d108ea..67abb34f7b 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettings.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettings.java @@ -20,6 +20,7 @@ import java.nio.file.Paths; import java.util.Objects; import java.util.logging.Level; import java.util.logging.Logger; +import org.apache.commons.lang3.StringUtils; import org.openide.modules.Places; /** @@ -38,7 +39,11 @@ public class CTSettings { LOGGER.log(Level.INFO, "Application Data (test mode) Path: " + Places.getUserDirectory().getAbsolutePath()); return Places.getUserDirectory().getAbsolutePath(); } else { - Path localAppPath = Paths.get(System.getenv("LOCALAPPDATA"), "cybertriage"); + + Path localAppPath = StringUtils.isBlank(System.getenv("LOCALAPPDATA")) + ? Places.getUserDirectory().toPath().toAbsolutePath() + : Paths.get(System.getenv("LOCALAPPDATA"), "cybertriage"); + try { Files.createDirectories(localAppPath); LOGGER.log(Level.INFO, "Application Data Path: " + localAppPath.toString()); From 0bec001773e64a70c15c99790fd346be180c1656 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 24 Aug 2023 14:10:59 -0400 Subject: [PATCH 80/94] fixes --- .../autopsy/ctoptions/CTOptionsPanel.java | 2 +- .../ctcloud/CTMalwareScannerOptionsPanel.java | 2 +- .../CTIncidentImportOptionsPanel.java | 33 ++++---- .../autopsy/incidentoptions/CTSettings.java | 79 ++++++++++++------- .../CTSettingsPersistence.java | 31 +++++--- 5 files changed, 91 insertions(+), 56 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/CTOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/CTOptionsPanel.java index 83a4a9a51a..2b6cffe789 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/CTOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/CTOptionsPanel.java @@ -26,12 +26,12 @@ import java.beans.PropertyChangeListener; import java.util.Collection; import java.util.Comparator; import java.util.List; -import java.util.logging.Logger; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.swing.JPanel; import org.netbeans.spi.options.OptionsPanelController; import org.openide.util.Lookup; +import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel; /** diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java index 375943188c..3c71bd3cba 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java @@ -40,7 +40,6 @@ import java.util.Optional; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.logging.Level; -import java.util.logging.Logger; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; @@ -51,6 +50,7 @@ import org.openide.util.NbBundle.Messages; import org.openide.util.lookup.ServiceProvider; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.core.UserPreferences; +import org.sleuthkit.autopsy.coreutils.Logger; /** * Options panel to be displayed in the CTOptionsPanel for settings regarding diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.java index bf018701ca..ef7aa5a67e 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.java @@ -1,16 +1,21 @@ -/** ************************************************************************* - ** This data and information is proprietary to, and a valuable trade secret - ** of, Sleuth Kit Labs. It is given in confidence by Sleuth Kit Labs - ** and may only be used as permitted under the license agreement under which - ** it has been distributed, and in no other way. - ** - ** Copyright (c) 2023 Sleuth Kit Labs, LLC. All rights reserved - ** - ** The technical data and information provided herein are provided with - ** `limited rights', and the computer software provided herein is provided - ** with `restricted rights' as those terms are defined in DAR and ASPR - ** 7-104.9(a). - ************************************************************************** */ +/* + * Autopsy Forensic Browser + * + * Copyright 2023 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.basistech.df.cybertriage.autopsy.incidentoptions; import com.basistech.df.cybertriage.autopsy.ctoptions.subpanel.CTOptionsSubPanel; @@ -21,7 +26,7 @@ import java.net.URI; import java.net.URISyntaxException; import java.util.Collections; import java.util.logging.Level; -import java.util.logging.Logger; +import org.sleuthkit.autopsy.coreutils.Logger; import javax.swing.JFileChooser; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettings.java b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettings.java index 67abb34f7b..d6427a641c 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettings.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettings.java @@ -1,16 +1,21 @@ -/** ************************************************************************* - ** This data and information is proprietary to, and a valuable trade secret - ** of, Sleuth Kit Labs. It is given in confidence by Sleuth Kit Labs - ** and may only be used as permitted under the license agreement under which - ** it has been distributed, and in no other way. - ** - ** Copyright (c) 2023 Sleuth Kit Labs, LLC. All rights reserved - ** - ** The technical data and information provided herein are provided with - ** `limited rights', and the computer software provided herein is provided - ** with `restricted rights' as those terms are defined in DAR and ASPR - ** 7-104.9(a). - ************************************************************************** */ +/* + * Autopsy Forensic Browser + * + * Copyright 2023 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.basistech.df.cybertriage.autopsy.incidentoptions; import java.io.IOException; @@ -19,40 +24,60 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Objects; import java.util.logging.Level; -import java.util.logging.Logger; +import org.sleuthkit.autopsy.coreutils.Logger; import org.apache.commons.lang3.StringUtils; import org.openide.modules.Places; +import org.sleuthkit.autopsy.coreutils.PlatformUtil; /** - * CT settings that don't include license information. This code must be kept in-sync with code in - * CT Autopsy Importer NBM. + * CT settings that don't include license information. This code must be kept + * in-sync with code in CT Autopsy Importer NBM. */ public class CTSettings { + private static final Logger LOGGER = Logger.getLogger(CTSettings.class.getCanonicalName()); private static final String DEFAULT_FILE_REPO_PATH = getAppDataLocalDirectory(); - // taken from com.basistech.df.cybertriage.utils.SystemProperties - private static String getAppDataLocalDirectory() { + private static final String CYBERTRIAGE_FOLDER = "cybertriage"; + private static final String CYBERTRIAGE_DOT_FOLDER = "." + CYBERTRIAGE_FOLDER; - Logger LOGGER = java.util.logging.Logger.getLogger(CTSettings.class.getCanonicalName()); + // based on com.basistech.df.cybertriage.utils.SystemProperties + private static String getAppDataLocalDirectory() { if (Objects.nonNull(Places.getUserDirectory()) && Places.getUserDirectory().getAbsolutePath().endsWith("testuserdir")) { // APP is in testing .. this should return the test path LOGGER.log(Level.INFO, "Application Data (test mode) Path: " + Places.getUserDirectory().getAbsolutePath()); return Places.getUserDirectory().getAbsolutePath(); - } else { - - Path localAppPath = StringUtils.isBlank(System.getenv("LOCALAPPDATA")) - ? Places.getUserDirectory().toPath().toAbsolutePath() - : Paths.get(System.getenv("LOCALAPPDATA"), "cybertriage"); - + } + + // try to use LOCALAPPDATA on windows + String localDataStr = System.getenv("LOCALAPPDATA"); + if (StringUtils.isNotBlank(localDataStr)) { + Path localAppPath = Paths.get(localDataStr, CYBERTRIAGE_FOLDER); try { Files.createDirectories(localAppPath); LOGGER.log(Level.INFO, "Application Data Path: " + localAppPath.toString()); return localAppPath.toString(); } catch (IOException ex) { - LOGGER.log(Level.SEVERE, "IO Error, defaulting to user dir", ex); - return Places.getUserDirectory().getAbsolutePath(); // In case of an IO Error + LOGGER.log(Level.SEVERE, "IO Error using " + localAppPath.toString(), ex); } } + + // try to use ~/.cybertriage anywhere else + if (!PlatformUtil.isWindowsOS()) { + String homePathStr = System.getenv("HOME"); + if (StringUtils.isNotBlank(homePathStr)) { + Path localAppPath = Paths.get(homePathStr, CYBERTRIAGE_DOT_FOLDER); + try { + Files.createDirectories(localAppPath); + LOGGER.log(Level.INFO, "Non-windows Application Data Path: " + localAppPath.toString()); + return localAppPath.toString(); + } catch (IOException ex) { + LOGGER.log(Level.SEVERE, "IO Error using " + localAppPath.toString(), ex); + } + } + } + + // defer to user directory otherwise + return Places.getUserDirectory().getAbsolutePath(); // In case of an IO Error } public static String getDefaultFileRepoPath() { diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettingsPersistence.java b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettingsPersistence.java index be60813edd..e5e5b6838f 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettingsPersistence.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettingsPersistence.java @@ -1,16 +1,21 @@ -/** ************************************************************************* - ** This data and information is proprietary to, and a valuable trade secret - ** of, Sleuth Kit Labs. It is given in confidence by Sleuth Kit Labs - ** and may only be used as permitted under the license agreement under which - ** it has been distributed, and in no other way. - ** - ** Copyright (c) 2023 Sleuth Kit Labs, LLC. All rights reserved - ** - ** The technical data and information provided herein are provided with - ** `limited rights', and the computer software provided herein is provided - ** with `restricted rights' as those terms are defined in DAR and ASPR - ** 7-104.9(a). - ************************************************************************** */ +/* + * Autopsy Forensic Browser + * + * Copyright 2023 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.basistech.df.cybertriage.autopsy.incidentoptions; import com.fasterxml.jackson.databind.ObjectMapper; From ed444f466141c70f552ae0591b1ad99fbdeb7a58 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 24 Aug 2023 15:22:40 -0400 Subject: [PATCH 81/94] better feedback on unsuccessful license --- .../autopsy/ctapi/json/LicenseResponse.java | 9 +++++- .../ctapi/util/LicenseDecryptorUtil.java | 19 ++++++++--- .../ctcloud/Bundle.properties-MERGED | 2 ++ .../ctcloud/CTMalwareScannerOptionsPanel.java | 32 ++++++++++++++++--- 4 files changed, 53 insertions(+), 9 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/LicenseResponse.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/LicenseResponse.java index a3a8247884..5a85778b60 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/LicenseResponse.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/LicenseResponse.java @@ -32,18 +32,21 @@ public class LicenseResponse { private final Boolean hostChanged; private final Long hostChangesRemaining; private final BoostLicenseResponse boostLicense; + private final String errorMsg; @JsonCreator public LicenseResponse( @JsonProperty("success") Boolean success, @JsonProperty("hostChanged") Boolean hostChanged, @JsonProperty("hostChangesRemaining") Long hostChangesRemaining, - @JsonProperty("boostLicense") BoostLicenseResponse boostLicense + @JsonProperty("boostLicense") BoostLicenseResponse boostLicense, + @JsonProperty("errorMsg") String errorMsg ) { this.success = success; this.hostChanged = hostChanged; this.hostChangesRemaining = hostChangesRemaining; this.boostLicense = boostLicense; + this.errorMsg = errorMsg; } public Boolean isSuccess() { @@ -61,4 +64,8 @@ public class LicenseResponse { public BoostLicenseResponse getBoostLicense() { return boostLicense; } + + public String getErrorMsg() { + return errorMsg; + } } diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/util/LicenseDecryptorUtil.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/util/LicenseDecryptorUtil.java index f62b57d795..26ebe793a4 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/util/LicenseDecryptorUtil.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/util/LicenseDecryptorUtil.java @@ -34,6 +34,7 @@ import java.security.PublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import java.security.spec.X509EncodedKeySpec; +import java.text.MessageFormat; import java.util.Base64; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; @@ -42,6 +43,7 @@ import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; +import org.apache.commons.lang3.ObjectUtils; /** * Decrypts the payload of boost license. @@ -58,12 +60,12 @@ public class LicenseDecryptorUtil { private LicenseDecryptorUtil() { } - + public LicenseInfo createLicenseInfo(LicenseResponse licenseResponse) throws JsonProcessingException, InvalidLicenseException { - if (licenseResponse == null || licenseResponse.getBoostLicense() == null) { - throw new InvalidLicenseException("License or boost license are null"); + if (licenseResponse == null) { + throw new InvalidLicenseException("License is null"); } - + DecryptedLicenseResponse decrypted = parseLicenseJSON(licenseResponse.getBoostLicense()); return new LicenseInfo(licenseResponse, decrypted); } @@ -78,6 +80,9 @@ public class LicenseDecryptorUtil { * com.basistech.df.cybertriage.autopsy.ctapi.util.LicenseDecryptorUtil.InvalidLicenseException */ public DecryptedLicenseResponse parseLicenseJSON(BoostLicenseResponse licenseResponse) throws JsonProcessingException, InvalidLicenseException { + if (licenseResponse == null) { + throw new InvalidLicenseException("Boost license is null"); + } String decryptedJsonResponse; try { @@ -101,6 +106,12 @@ public class LicenseDecryptorUtil { } private String decryptLicenseString(String encryptedJson, String ivBase64, String encryptedKey, String version) throws IOException, GeneralSecurityException, InvalidLicenseException { + if (ObjectUtils.anyNull(encryptedJson, ivBase64, encryptedKey, version)) { + throw new InvalidLicenseException(MessageFormat.format( + "encryptedJson: {0}, iv: {1}, encryptedKey: {2}, version: {3} must all be non-null", + encryptedJson, ivBase64, encryptedKey, version)); + } + if (!"1.0".equals(version)) { throw new InvalidLicenseException("Unexpected file version: " + version); } diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED index 0e888c7fac..8dd673e2d7 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED @@ -31,6 +31,8 @@ CTMalwareScannerOptionsPanel_licenseAddDialogEnteredErr_title=License Number Alr CTMalwareScannerOptionsPanel_licenseAddDialogPatternErr_desc=Please verify that license number is of format 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' CTMalwareScannerOptionsPanel_licenseAddDialogPatternErr_title=Invalid License Number CTMalwareScannerOptionsPanel_LicenseFetcher_apiErr_title=Server Error +# {0} - licenseCode +CTMalwareScannerOptionsPanel_LicenseFetcher_defaultErrMsg_desc=Error activating boost license {0} CTMalwareScannerOptionsPanel_LicenseFetcher_localErr_desc=A general error occurred while fetching license information. Please try again later. CTMalwareScannerOptionsPanel_LicenseFetcher_localErr_title=General Error # {0} - expiresDate diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java index 375943188c..735be72afc 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java @@ -608,6 +608,8 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { @NbBundle.Messages({ "CTMalwareScannerOptionsPanel_LicenseFetcher_apiErr_title=Server Error", "CTMalwareScannerOptionsPanel_LicenseFetcher_localErr_title=General Error", + "# {0} - licenseCode", + "CTMalwareScannerOptionsPanel_LicenseFetcher_defaultErrMsg_desc=Error activating boost license {0}", "CTMalwareScannerOptionsPanel_LicenseFetcher_localErr_desc=A general error occurred while fetching license information. Please try again later.",}) private class LicenseFetcher extends SwingWorker { @@ -629,10 +631,9 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { protected void done() { try { LicenseResponse licenseResponse = get(); - if (licenseResponse != null && licenseResponse.isSuccess()) { - SwingUtilities.invokeLater(() -> acceptEula(licenseResponse)); - } else { - logger.log(Level.WARNING, "An API error occurred while fetching license information. License fetch was not successful"); + // if no result, show unauthorized + if (licenseResponse == null) { + logger.log(Level.WARNING, "An API error occurred while fetching license information. License fetch returned no result."); JOptionPane.showMessageDialog( CTMalwareScannerOptionsPanel.this, CTCloudException.ErrorCode.UN_AUTHORIZED.getDescription(), @@ -640,7 +641,30 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel { JOptionPane.ERROR_MESSAGE); setLicenseDisplay(licenseInfo, null); loadMalwareScansInfo(licenseInfo); + return; } + + // if not successful response + if (!Boolean.TRUE.equals(licenseResponse.isSuccess())) { + logger.log(Level.WARNING, "An API error occurred while fetching license information. License fetch was not successful"); + // use default message unless error message specified + String message = Bundle.CTMalwareScannerOptionsPanel_LicenseFetcher_defaultErrMsg_desc(licenseText); + if (!StringUtils.isBlank(licenseResponse.getErrorMsg())) { + message = licenseResponse.getErrorMsg(); + } + JOptionPane.showMessageDialog( + CTMalwareScannerOptionsPanel.this, + message, + Bundle.CTMalwareScannerOptionsPanel_LicenseFetcher_apiErr_title(), + JOptionPane.ERROR_MESSAGE); + setLicenseDisplay(licenseInfo, null); + loadMalwareScansInfo(licenseInfo); + return; + } + + // otherwise, load + SwingUtilities.invokeLater(() -> acceptEula(licenseResponse)); + } catch (InterruptedException | CancellationException ex) { // ignore cancellation; just load current license setLicenseDisplay(licenseInfo, null); From cfb619aaad83725fa8775fe9f166598e90027534 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 24 Aug 2023 17:15:30 -0400 Subject: [PATCH 82/94] add hint text --- .../ctoptions/ctcloud/Bundle.properties | 3 ++- .../ctoptions/ctcloud/Bundle.properties-MERGED | 5 +++-- .../ctoptions/ctcloud/CTLicenseDialog.form | 3 +++ .../ctoptions/ctcloud/CTLicenseDialog.java | 18 ++++++++++++++++-- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties index 3c86b5446d..44e71a4513 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties @@ -4,7 +4,7 @@ CTLicenseDialog.title=Add a License... CTLicenseDialog.licenseNumberLabel.text=License Number: -CTLicenseDialog.licenseNumberTextField.text=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX +CTLicenseDialog.licenseNumberTextField.text= CTLicenseDialog.cancelButton.text=Cancel CTLicenseDialog.okButton.text=Ok CTLicenseDialog.warningLabel.text= @@ -25,3 +25,4 @@ EULADialog.title=Cyber Triage End User License Agreement CTMalwareScannerOptionsPanel.licenseInfoMessageLabel.text= CTMalwareScannerOptionsPanel.disclaimer.text=The Cyber Triage Malware Scanner module uses 40+ malware scanning engines to identify if Windows executables are malicious. It requires a paid subscription to use. CTMalwareScannerOptionsPanel.purchaseFromLabel.text=For licensing information, visit +CTLicenseDialog.licenseNumberTextField.toolTipText=AUT-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED index 8dd673e2d7..d9876a8ed7 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED @@ -4,11 +4,11 @@ CTLicenseDialog.title=Add a License... CTLicenseDialog.licenseNumberLabel.text=License Number: -CTLicenseDialog.licenseNumberTextField.text=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX +CTLicenseDialog.licenseNumberTextField.text= CTLicenseDialog.cancelButton.text=Cancel CTLicenseDialog.okButton.text=Ok CTLicenseDialog.warningLabel.text= -CTLicenseDialog_verifyInput_licenseNumberError=Please verify license number format of 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' +CTLicenseDialog_verifyInput_licenseNumberError=Please enter a license number CTMalwareScannerOptionsPanel.hashLookupsRemainingLabel.text= CTMalwareScannerOptionsPanel.countersResetLabel.text= CTMalwareScannerOptionsPanel.maxFileUploadsLabel.text= @@ -65,3 +65,4 @@ EULADialog.title=Cyber Triage End User License Agreement CTMalwareScannerOptionsPanel.licenseInfoMessageLabel.text= CTMalwareScannerOptionsPanel.disclaimer.text=The Cyber Triage Malware Scanner module uses 40+ malware scanning engines to identify if Windows executables are malicious. It requires a paid subscription to use. CTMalwareScannerOptionsPanel.purchaseFromLabel.text=For licensing information, visit +CTLicenseDialog.licenseNumberTextField.toolTipText=AUT-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.form b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.form index e7cd2743a0..2ea57d43a8 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.form +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.form @@ -127,6 +127,9 @@ + + + diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.java index 3bff998901..495ee9d032 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.java @@ -18,11 +18,13 @@ */ package com.basistech.df.cybertriage.autopsy.ctoptions.ctcloud; +import java.awt.Color; import java.util.regex.Pattern; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import org.apache.commons.lang3.StringUtils; import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.corecomponents.TextPrompt; /** * License dialog @@ -38,6 +40,7 @@ class CTLicenseDialog extends javax.swing.JDialog { public CTLicenseDialog(java.awt.Frame parent, boolean modal) { super(parent, modal); initComponents(); + configureHintText(); this.licenseNumberTextField.getDocument().putProperty("filterNewlines", Boolean.TRUE); this.licenseNumberTextField.getDocument().addDocumentListener(new DocumentListener() { @Override @@ -56,13 +59,23 @@ class CTLicenseDialog extends javax.swing.JDialog { } }); } - + + private void configureHintText() { + TextPrompt textPrompt = new TextPrompt( + StringUtils.defaultString(this.licenseNumberTextField.getToolTipText()), + this.licenseNumberTextField); + + textPrompt.setForeground(Color.LIGHT_GRAY); + float alpha = 0.9f; // Mostly opaque + textPrompt.changeAlpha(alpha); + } + String getValue() { return licenseString; } @Messages({ - "CTLicenseDialog_verifyInput_licenseNumberError=Please verify license number format of 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'" + "CTLicenseDialog_verifyInput_licenseNumberError=Please enter a license number" }) private void verifyInput() { String licenseInput = StringUtils.defaultString(this.licenseNumberTextField.getText()); @@ -165,6 +178,7 @@ class CTLicenseDialog extends javax.swing.JDialog { getContentPane().add(cancelButton, gridBagConstraints); licenseNumberTextField.setText(org.openide.util.NbBundle.getMessage(CTLicenseDialog.class, "CTLicenseDialog.licenseNumberTextField.text")); // NOI18N + licenseNumberTextField.setToolTipText(org.openide.util.NbBundle.getMessage(CTLicenseDialog.class, "CTLicenseDialog.licenseNumberTextField.toolTipText")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 1; From e5666ac18306546a74d12208f7ec2010a7040950 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Fri, 25 Aug 2023 07:49:37 -0400 Subject: [PATCH 83/94] Update TSK Version --- Core/nbproject/project.properties | 4 ++-- Core/nbproject/project.xml | 8 ++++---- TSKVersion.xml | 2 +- release_scripts/update_sleuthkit_version.pl | 2 +- unix_setup.sh | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Core/nbproject/project.properties b/Core/nbproject/project.properties index 9adb1c7649..71acddc08a 100644 --- a/Core/nbproject/project.properties +++ b/Core/nbproject/project.properties @@ -85,8 +85,8 @@ file.reference.Rejistry-1.1-SNAPSHOT.jar=release/modules/ext/Rejistry-1.1-SNAPSH file.reference.serializer-2.7.2.jar=release/modules/ext/serializer-2.7.2.jar file.reference.sevenzipjbinding-AllPlatforms.jar=release/modules/ext/sevenzipjbinding-AllPlatforms.jar file.reference.sevenzipjbinding.jar=release/modules/ext/sevenzipjbinding.jar -file.reference.sleuthkit-4.12.0.jar=release/modules/ext/sleuthkit-4.12.0.jar -file.reference.sleuthkit-caseuco-4.12.0.jar=release/modules/ext/sleuthkit-caseuco-4.12.0.jar +file.reference.sleuthkit-4.12.1.jar=release/modules/ext/sleuthkit-4.12.1.jar +file.reference.sleuthkit-caseuco-4.12.1.jar=release/modules/ext/sleuthkit-caseuco-4.12.1.jar file.reference.slf4j-api-1.7.36.jar=release/modules/ext/slf4j-api-1.7.36.jar file.reference.snakeyaml-2.0.jar=release/modules/ext/snakeyaml-2.0.jar file.reference.SparseBitSet-1.1.jar=release/modules/ext/SparseBitSet-1.1.jar diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml index 9b960955aa..754da003d9 100644 --- a/Core/nbproject/project.xml +++ b/Core/nbproject/project.xml @@ -718,12 +718,12 @@ release/modules/ext/sevenzipjbinding.jar - ext/sleuthkit-4.12.0.jar - release/modules/ext/sleuthkit-4.12.0.jar + ext/sleuthkit-4.12.1.jar + release/modules/ext/sleuthkit-4.12.1.jar - ext/sleuthkit-caseuco-4.12.0.jar - release/modules/ext/sleuthkit-caseuco-4.12.0.jar + ext/sleuthkit-caseuco-4.12.1.jar + release/modules/ext/sleuthkit-caseuco-4.12.1.jar ext/slf4j-api-1.7.36.jar diff --git a/TSKVersion.xml b/TSKVersion.xml index 087dac0912..7f6a1a8848 100644 --- a/TSKVersion.xml +++ b/TSKVersion.xml @@ -1,3 +1,3 @@ - + diff --git a/release_scripts/update_sleuthkit_version.pl b/release_scripts/update_sleuthkit_version.pl index 1d6bdc7e72..f197477c82 100755 --- a/release_scripts/update_sleuthkit_version.pl +++ b/release_scripts/update_sleuthkit_version.pl @@ -33,7 +33,7 @@ sub main { update_core_project_xml(); update_unix_setup(); - print "Files updated. You need to commit and push them\n"; + print "Files updated and added to git. You need to commit (no -a) and push.\n"; } diff --git a/unix_setup.sh b/unix_setup.sh index d2572c9de2..ab2d1094f6 100644 --- a/unix_setup.sh +++ b/unix_setup.sh @@ -5,7 +5,7 @@ # NOTE: update_sleuthkit_version.pl updates this value and relies # on it keeping the same name and whitespace. Don't change it. -TSK_VERSION=4.12.0 +TSK_VERSION=4.12.1 usage() { From 227d32d1c01b81ea34cc01c3f09de51f94c4de40 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Fri, 25 Aug 2023 07:56:29 -0400 Subject: [PATCH 84/94] better error message --- .../autopsy/ctapi/CTCloudHttpClient.java | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java index 0a7c69cdee..cf93d58307 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java @@ -158,16 +158,23 @@ class CTCloudHttpClient { // Parse Response if (classType != null) { HttpEntity entity = response.getEntity(); - String entityStr = EntityUtils.toString(entity); - O respObj = mapper.readValue(entityStr, classType); - return respObj; - } else { - return null; + if (entity != null) { + String entityStr = EntityUtils.toString(entity); + if (StringUtils.isNotBlank(entityStr)) { + O respObj = mapper.readValue(entityStr, classType); + return respObj; + } + } } + + return null; } else { LOGGER.log(Level.WARNING, "Response Received. - Status Error {}", response.getStatusLine()); handleNonOKResponse(response, ""); } + // transform all non-CTCloudException's into a CTCloudException + } catch (CTCloudException ex) { + throw ex; } catch (Exception ex) { LOGGER.log(Level.WARNING, "Error when parsing response from CyberTriage Cloud", ex); throw new CTCloudException(CTCloudException.parseUnknownException(ex), ex); @@ -191,7 +198,7 @@ class CTCloudHttpClient { if (fileUploadRequest == null) { throw new CTCloudException(ErrorCode.BAD_REQUEST, new IllegalArgumentException("fileUploadRequest cannot be null")); } - + String fullUrlPath = fileUploadRequest.getFullUrlPath(); String fileName = fileUploadRequest.getFileName(); InputStream fileInputStream = fileUploadRequest.getFileInputStream(); @@ -200,7 +207,7 @@ class CTCloudHttpClient { if (StringUtils.isBlank(fullUrlPath) || fileInputStream == null || contentLength == null || contentLength <= 0) { throw new CTCloudException(ErrorCode.BAD_REQUEST, new IllegalArgumentException("fullUrlPath, fileInputStream, contentLength must not be empty, null or less than 0")); } - + URI putUri; try { putUri = new URI(fullUrlPath); From dd761c9a9fb8dce9137ee60c58ad7e75d40bce17 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Fri, 25 Aug 2023 08:03:23 -0400 Subject: [PATCH 85/94] update malware doc images --- docs/doxygen-user/ct_malware_scanner.dox | 7 +++++-- ...canner-global-options-panel-no-license.png | Bin 56344 -> 0 bytes .../images/malware-artifact-tree.png | Bin 108340 -> 80016 bytes ...canner-global-options-panel-no-license.png | Bin 0 -> 49782 bytes .../malware-scanner-global-options-panel.png | Bin 66206 -> 60189 bytes 5 files changed, 5 insertions(+), 2 deletions(-) delete mode 100644 docs/doxygen-user/images/Malware-scanner-global-options-panel-no-license.png create mode 100644 docs/doxygen-user/images/malware-scanner-global-options-panel-no-license.png diff --git a/docs/doxygen-user/ct_malware_scanner.dox b/docs/doxygen-user/ct_malware_scanner.dox index fa1dd6fb6b..3b0aff0b88 100644 --- a/docs/doxygen-user/ct_malware_scanner.dox +++ b/docs/doxygen-user/ct_malware_scanner.dox @@ -18,9 +18,12 @@ Configuration Once you have a license, you must add it on the Options panel. Choose the 'Cyber Triage' tab and choose 'Add License'. -\image html Malware-scanner-global-options-panel-no-license.png +\image html malware-scanner-global-options-panel-no-license.png -After you enter the license number that you should have received from your email, you will then need to review and agree to the license terms. +After you enter the license number that you should have received from your email, you will then need to review and agree to the license terms. Example license formats include: + +* X +* Y The options panel should now display information about the lookup limits. You can always refer back to here about what your limits are and when they reset. diff --git a/docs/doxygen-user/images/Malware-scanner-global-options-panel-no-license.png b/docs/doxygen-user/images/Malware-scanner-global-options-panel-no-license.png deleted file mode 100644 index 09bb7d8344de194cc29290d49f29d48eb60f446d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 56344 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 tcibBKuCn`>0A5L5}oViog zr{v-5;?TBNK0z{O=|S{|MDmzomF9M_TG!XSixUS7ubNt2%Bd*;uedF>O;YJN;pxfd zunamafviW>Uz=z?kqk^(L`})2t@pZ0^3OLbMo%$AmhJ?5vlULGS?bT8*qNrEBNDvI zvX*W0m!&3RSR$I)kY2Ir+1nHn!?{X2<7xJS3fBeo(ZjDx0#Eo-?MF58xc)hEldJ8p zU-sf+$K4@1w=!O(|I0weu-wUf9I?i8c63!`~OVLhT z<845-2sfb=b6)nult$VVayG-d36m^JP+sX(&Bp%9!W=5kbD@3GFx2n0AE4cqOG{T= z(_S~V=;4U=mPT!s5$dzCX?F+72r+TRS2?10*B@J?#i(d82T9hRJn2U7#HShJ)a=xo zrs=$}a0%++B7@QulUHpFhYaHD_#jDqRN4E(P05qwYU_oDSNTDKD;hV(A=NQo8siN{Pzq9q7f!&5Yt4vg_;j>PUC*kU&wDCjW@hN6xK^dcbz^5ybQ=lzkPh zm}K2DJ1z|i21{5WV|ORwp6TGUL$PPd+a{NCi66Sk_y-LgDAZYFDp>Y)5_wbixP5Tz z$mZT$*XP|e)U1l+q$iKsTiblqUVae_7T_y21x_UB=QNcOCXV<9cn#S(+~{%!hwyX! zhx~@4l8((?@tf)rg#dCoA54 z`{pPj$2SgIUHicwQF&yBRdUHUFY6#DA|kJ6YCkSg*PmTa_0{R=aT5rz1F2yE{D=s*GI=F?WhURzP$BE;shi;AVnS4xg;;A^hRRt6-bmzei*aid`To7U zSA8$wXo3)XgxY^5*dJ&nral^NSpyd8$UNYmsaqS0)L6Y!abceTva)}0P@z-2OfLLm zN4ok8f-(&%A?VIgPCDW`Bq6Re^>6sY?h}U{h%*NTiy=0D4lex<^ml2KRjkkb1@tT0Sr>V56BH*NZi8Z8WGyL(@1Tod-gK=?;3u#P1eNJ8t3CmFyVAvM=myDY`Sfy>sD5@*hB; zlsnvFMH?tY)eWp^2|eDu*#s^~T$hykXdN>8>e%Fue2vXC{8~=fne-jFicGTSPRh1? zM=ZZ*l}7tEHqQ8+tSr7dKC%cFZm^|K2k98rvjKS&_1la>S9NaFhDb8#8wP+oZIhK-zx6tO?i?b9kdek4oC_@3t+xo$k%$_`EjoA5;p5xFL z=TAcoIWi*bvnI69F`_gNN>Jz0EhKY#5D(IpOPa_N4_JFMJ3ubla=(mq3P>81W4`{; z7|rY!OS3Ic_?^s2vqvLFjjtR}HuF69D-JGydJDjqPP@~JlE~Uzx0hE;XK(Y;BxsTB z74~m`0n1*B(7QHsd7{_$n-inHJX82X7z==Qn?k2kQzI-hOp zYC4L);0RrhOXx9JfHzJgnhDm(_;?&2HNe%4d@?Xbd`?d&R{?vDGd09)9Dg@UimiV| zn%^(CN?t4gaS;hGTZwdSQ49CtWeSOylqpL&TO4RpWAMk(HJi7p3oaBVx(+o}Beim@(B%u5mCz4B zilipptIR0gAiqMtDluaSOuUilW5bSdx}E~JI2BeVg}f-9A7qMbcA&eJ1WOvCl{{0p18|{tci(+m zh<2^WT8pR{xbNR^lCirnTGG3|S{SLI-lWf5gTc$?f~Kg7w<1-0PR zwdH5TkX(rW?BGK?Et&ujzu77GK?x5~fKF{iLCEFR;MRl}K(@5k_1I9uV9+D%kc?N= zP#4j-uC}_=#MSs|`C?ET02m8`G>?O6z;0ocmAkF%$+9~2-jmZvhl!{5$dHL3rCsm6(5<5ZWKPTM8_%Q0y; zKZjX~uiqk?QR4n#S+_sb{>r?s#d|fB)C}yrc+zI@@BVbZ&2kWQq=e8*@^*T+TdLoY zT|P}rGFCvow diff --git a/docs/doxygen-user/images/malware-artifact-tree.png b/docs/doxygen-user/images/malware-artifact-tree.png index 53b229751ca4e7f8e89e214f175bf1176e6729e4..b47afb86c17ba60916bbfb267b4391c3e54194bd 100644 GIT binary patch literal 80016 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

IV&{a5c)qE{#~@3kl-)wsJ>st-66v=8lL- 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 S6syk#d=3~NHhOC49QI!|x(As6 literal 108340 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

ddu&d$z&P7jH9A-^e{LYV;n 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 z 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 diff --git a/docs/doxygen-user/images/malware-scanner-global-options-panel-no-license.png b/docs/doxygen-user/images/malware-scanner-global-options-panel-no-license.png new file mode 100644 index 0000000000000000000000000000000000000000..de6484387299b664179ceb99bcde248b6b3dc95d GIT binary patch literal 49782 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 literal 0 HcmV?d00001 diff --git a/docs/doxygen-user/images/malware-scanner-global-options-panel.png b/docs/doxygen-user/images/malware-scanner-global-options-panel.png index fd0b131832bfdf79e29ffae389b94f3f86f6b7a9..b5a0ad4f3d0665265e0847271bf4f82214cedf8d 100644 GIT binary patch literal 60189 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 literal 66206 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%0DW((Nx%Y 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


-

Copyright © 2012-2022 Basis Technology. Generated on $date
+

Copyright © 2012-2023 BasisTech. Generated on $date
This work is licensed under a
Creative Commons Attribution-Share Alike 3.0 United States License.

From 9a9bedfd3bdbb919e1ca31e96d0cd4df2a3d98cf Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Tue, 29 Aug 2023 09:08:18 -0400 Subject: [PATCH 93/94] Fix bullets --- docs/doxygen-user/ct_malware_scanner.dox | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/doxygen-user/ct_malware_scanner.dox b/docs/doxygen-user/ct_malware_scanner.dox index ea73f1dcba..ad875a270d 100644 --- a/docs/doxygen-user/ct_malware_scanner.dox +++ b/docs/doxygen-user/ct_malware_scanner.dox @@ -17,8 +17,8 @@ Configuration You will need to first get a paid or eval license from the above URL. The code will come in via email. Example license formats include: -* AUT-8ed86eb5-17fc-4b3a-9b75-ce638c11b070 -* b826a555-951f-42ca-86ce-439a81106688 +- AUT-8ed86eb5-17fc-4b3a-9b75-ce638c11b070 +- b826a555-951f-42ca-86ce-439a81106688 Once you have a license, you must add it on the Autopsy Options panel. Choose the 'Cyber Triage' tab and choose 'Add License'. From db2a4979cec69b480da5bd75d2b1c80f1fe956ac Mon Sep 17 00:00:00 2001 From: "eugene.livis" Date: Tue, 29 Aug 2023 11:57:47 -0400 Subject: [PATCH 94/94] Using TSK_MALWARE standard Autopsy artifact --- .../malwarescan/MalwareScanIngestModule.java | 10 ++---- .../autopsy/datamodel/Artifacts.java | 18 ++--------- .../autopsy/datamodel/MalwareHits.java | 32 ++++++------------- 3 files changed, 14 insertions(+), 46 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java index ba8bd556b1..fee67fdff2 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java @@ -134,8 +134,7 @@ class MalwareScanIngestModule implements FileIngestModule { "application/x-msdos-program"//NON-NLS ).collect(Collectors.toSet()); - private static final String MALWARE_TYPE_NAME = "TSK_MALWARE"; - private static final String MALWARE_CONFIG = "Cyber Triage Cloud"; + private static final String MALWARE_CONFIG = ""; // NOTE: Adding a configuration complicates NTL branch UI private static final Logger logger = Logger.getLogger(MalwareScanIngestModule.class.getName()); @@ -235,18 +234,13 @@ class MalwareScanIngestModule implements FileIngestModule { // setup necessary variables for processing SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase(); - BlackboardArtifact.Type malwareType = tskCase.getBlackboard().getOrAddArtifactType( - MALWARE_TYPE_NAME, - Bundle.MalwareScanIngestModule_malwareTypeDisplayName(), - BlackboardArtifact.Category.ANALYSIS_RESULT); - return new IngestJobState( context, tskCase, new PathNormalizer(tskCase), new FileTypeDetector(), licenseInfoOpt.get(), - malwareType, + BlackboardArtifact.Type.TSK_MALWARE, uploadFiles, true ); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java b/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java index a38383c183..4475b682c5 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java @@ -64,6 +64,7 @@ import static org.sleuthkit.datamodel.BlackboardArtifact.Type.TSK_INTERESTING_IT import static org.sleuthkit.datamodel.BlackboardArtifact.Type.TSK_TL_EVENT; import static org.sleuthkit.datamodel.BlackboardArtifact.Type.TSK_ASSOCIATED_OBJECT; import static org.sleuthkit.datamodel.BlackboardArtifact.Type.TSK_KEYWORD_HIT; +import static org.sleuthkit.datamodel.BlackboardArtifact.Type.TSK_MALWARE; /** * Classes for creating nodes for BlackboardArtifacts. @@ -73,10 +74,6 @@ public class Artifacts { private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED); - // this is currently a custom TSK artifact type, created in MalwareScanIngestModule - private static BlackboardArtifact.Type MALWARE_ARTIFACT_TYPE = null; - private static final String MALWARE_HITS = "TSK_MALWARE"; - /** * Base class for a parent node of artifacts. */ @@ -247,15 +244,6 @@ public class Artifacts { @SuppressWarnings("deprecation") private static TypeNodeKey getTypeKey(BlackboardArtifact.Type type, SleuthkitCase skCase, long dsObjId) { - // Get the custom TSK_MALWARE artifact type from case database - if (MALWARE_ARTIFACT_TYPE == null) { - try { - MALWARE_ARTIFACT_TYPE = skCase.getArtifactType(MALWARE_HITS); - } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Unable to get TSK_MALWARE artifact type from database : ", ex); //NON-NLS - } - } - int typeId = type.getTypeID(); if (TSK_EMAIL_MSG.getTypeID() == typeId) { EmailExtracted.RootNode emailNode = new EmailExtracted(skCase, dsObjId).new RootNode(); @@ -281,9 +269,9 @@ public class Artifacts { } else if (TSK_HASHSET_HIT.getTypeID() == typeId) { HashsetHits.RootNode hashsetHits = new HashsetHits(skCase, dsObjId).new RootNode(); return new TypeNodeKey(hashsetHits, TSK_HASHSET_HIT); - } else if (MALWARE_ARTIFACT_TYPE != null && MALWARE_ARTIFACT_TYPE.getTypeID() == typeId) { + } else if (TSK_MALWARE.getTypeID() == typeId) { MalwareHits.RootNode malwareHits = new MalwareHits(skCase, dsObjId).new RootNode(); - return new TypeNodeKey(malwareHits, MALWARE_ARTIFACT_TYPE); + return new TypeNodeKey(malwareHits, TSK_MALWARE); } else { return new TypeNodeKey(type, dsObjId); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/MalwareHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/MalwareHits.java index c1761a7ad5..2524650178 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/MalwareHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/MalwareHits.java @@ -44,12 +44,12 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.ModuleDataEvent; -import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.datamodel.Artifacts.UpdatableCountTypeNode; import org.sleuthkit.datamodel.AnalysisResult; +import static org.sleuthkit.datamodel.BlackboardArtifact.Type.TSK_MALWARE; import org.sleuthkit.datamodel.Score; /** @@ -57,9 +57,6 @@ import org.sleuthkit.datamodel.Score; */ public class MalwareHits implements AutopsyVisitableItem { - private static final String MALWARE_HITS = "TSK_MALWARE"; // this is currently a custom TSK artifact type, created in MalwareScanIngestModule - private static BlackboardArtifact.Type MALWARE_ARTIFACT_TYPE = null; - private static String DISPLAY_NAME; private static final Logger logger = Logger.getLogger(MalwareHits.class.getName()); private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED); private static final Set INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestModuleEvent.DATA_ADDED); @@ -126,20 +123,9 @@ public class MalwareHits implements AutopsyVisitableItem { return; } - // Get the custom TSK_MALWARE artifact type from case database - if (MALWARE_ARTIFACT_TYPE == null) { - try { - MALWARE_ARTIFACT_TYPE = skCase.getArtifactType(MALWARE_HITS); - DISPLAY_NAME = MALWARE_ARTIFACT_TYPE.getDisplayName(); - } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Unable to get TSK_MALWARE artifact type from database : ", ex); //NON-NLS - return; - } - } - String query = "SELECT blackboard_artifacts.artifact_obj_id " //NON-NLS + "FROM blackboard_artifacts,tsk_analysis_results WHERE " //NON-NLS - + "blackboard_artifacts.artifact_type_id=" + MALWARE_ARTIFACT_TYPE.getTypeID() //NON-NLS + + "blackboard_artifacts.artifact_type_id=" + TSK_MALWARE.getTypeID() //NON-NLS + " AND tsk_analysis_results.artifact_obj_id=blackboard_artifacts.artifact_obj_id" //NON-NLS + " AND (tsk_analysis_results.significance=" + Score.Significance.NOTABLE.getId() //NON-NLS + " OR tsk_analysis_results.significance=" + Score.Significance.LIKELY_NOTABLE.getId() + " )"; //NON-NLS @@ -182,7 +168,7 @@ public class MalwareHits implements AutopsyVisitableItem { * oldValue if the event is a remote event. */ ModuleDataEvent eventData = (ModuleDataEvent) evt.getOldValue(); - if (null != eventData && eventData.getBlackboardArtifactType().getTypeID() == MALWARE_ARTIFACT_TYPE.getTypeID()) { + if (null != eventData && eventData.getBlackboardArtifactType().getTypeID() == TSK_MALWARE.getTypeID()) { malwareResults.update(); } } catch (NoCurrentCaseException notUsed) { @@ -248,13 +234,13 @@ public class MalwareHits implements AutopsyVisitableItem { public class RootNode extends UpdatableCountTypeNode { public RootNode() { - super(Children.create(new HitFactory(DISPLAY_NAME), true), - Lookups.singleton(DISPLAY_NAME), - DISPLAY_NAME, + super(Children.create(new HitFactory(TSK_MALWARE.getDisplayName()), true), + Lookups.singleton(TSK_MALWARE.getDisplayName()), + TSK_MALWARE.getDisplayName(), filteringDSObjId, - MALWARE_ARTIFACT_TYPE); + TSK_MALWARE); - super.setName(MALWARE_HITS); + super.setName(TSK_MALWARE.getTypeName()); // TODO make an icon this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/artifact-icon.png"); } @@ -297,7 +283,7 @@ public class MalwareHits implements AutopsyVisitableItem { */ @Override void updateDisplayName() { - super.setDisplayName(DISPLAY_NAME + " (" + malwareResults.getArtifactIds().size() + ")"); + super.setDisplayName(TSK_MALWARE.getDisplayName() + " (" + malwareResults.getArtifactIds().size() + ")"); } }

xhbR(;BWv9z5-j6QrVrt1m4w1PV{ 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 Iwfj&17iemGumAu6 From bffecc82c4421cc93aab26e1ff22ae97aff48881 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Fri, 25 Aug 2023 08:07:32 -0400 Subject: [PATCH 86/94] added sample codes --- docs/doxygen-user/ct_malware_scanner.dox | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/doxygen-user/ct_malware_scanner.dox b/docs/doxygen-user/ct_malware_scanner.dox index 3b0aff0b88..f8d44a1c84 100644 --- a/docs/doxygen-user/ct_malware_scanner.dox +++ b/docs/doxygen-user/ct_malware_scanner.dox @@ -15,15 +15,15 @@ For more information on obtaining a license, refer to [CyberTriage.com](https:// Configuration ======= -Once you have a license, you must add it on the Options panel. Choose the 'Cyber Triage' tab and choose 'Add License'. +You will need to first get a paid or eval license from the above URL. The code will come in via email. Example license formats include: +* AUT-8ed86eb5-17fc-4b3a-9b75-ce638c11b070 +* b826a555-951f-42ca-86ce-439a81106688 +Once you have a license, you must add it on the Options panel. Choose the 'Cyber Triage' tab and choose 'Add License'. \image html malware-scanner-global-options-panel-no-license.png -After you enter the license number that you should have received from your email, you will then need to review and agree to the license terms. Example license formats include: - -* X -* Y +After you enter the license number that you should have received from your email, you will then need to review and agree to the license terms. The options panel should now display information about the lookup limits. You can always refer back to here about what your limits are and when they reset. From 8db2ef652189f2bf4092c67caf47a35bd1b7aa77 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Fri, 25 Aug 2023 08:09:29 -0400 Subject: [PATCH 87/94] update malware page --- docs/doxygen-user/ct_malware_scanner.dox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/doxygen-user/ct_malware_scanner.dox b/docs/doxygen-user/ct_malware_scanner.dox index f8d44a1c84..21d857e6f7 100644 --- a/docs/doxygen-user/ct_malware_scanner.dox +++ b/docs/doxygen-user/ct_malware_scanner.dox @@ -9,7 +9,7 @@ The Cyber Triage Malware Scanner module will use the malware scanning infrastruc This module requires a commercial license from Cyber Triage. -For more information on obtaining a license, refer to [CyberTriage.com](https://cybertriage.com/autopsy-malware-module). The remainder of this page is about the use of the module once it is licensed. +For more information on what the module does or obtaining a license, refer to [CyberTriage.com](https://cybertriage.com/autopsy-malware-module). The remainder of this page is about the use of the module once it is licensed. Configuration From 12fe1e961472488dc4c9c92c5c77d5ee2e6b57f2 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Fri, 25 Aug 2023 11:01:35 -0400 Subject: [PATCH 88/94] license code validation and trim --- .../autopsy/ctoptions/ctcloud/CTLicenseDialog.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.java index 495ee9d032..99fc749dd7 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.java @@ -31,7 +31,7 @@ import org.sleuthkit.autopsy.corecomponents.TextPrompt; */ class CTLicenseDialog extends javax.swing.JDialog { - private static final Pattern LICENSE_PATTERN = Pattern.compile("^\\s*[a-zA-Z0-9\\-]+?\\s*$"); + private static final Pattern LICENSE_PATTERN = Pattern.compile("^\\s*[a-zA-Z0-9-_]+?\\s*$"); private String licenseString = null; /** @@ -191,7 +191,8 @@ class CTLicenseDialog extends javax.swing.JDialog { }// //GEN-END:initComponents private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed - this.licenseString = this.licenseNumberTextField.getText(); + String inputText = this.licenseNumberTextField.getText(); + this.licenseString = inputText == null ? null : inputText.trim(); this.dispose(); }//GEN-LAST:event_okButtonActionPerformed From 518643d988ff05b683d669239eeaac777f25adb4 Mon Sep 17 00:00:00 2001 From: "eugene.livis" Date: Fri, 25 Aug 2023 15:59:27 -0400 Subject: [PATCH 89/94] Updated NBM and Autopsy version numbers --- Core/manifest.mf | 2 +- Core/nbproject/project.properties | 2 +- CoreLibs/manifest.mf | 2 +- Experimental/nbproject/project.xml | 4 ++-- ImageGallery/nbproject/project.xml | 2 +- KeywordSearch/manifest.mf | 2 +- KeywordSearch/nbproject/project.properties | 2 +- KeywordSearch/nbproject/project.xml | 2 +- RecentActivity/manifest.mf | 2 +- Testing/nbproject/project.xml | 4 ++-- nbproject/project.properties | 2 +- thunderbirdparser/nbproject/project.xml | 2 +- 12 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Core/manifest.mf b/Core/manifest.mf index 59baf3f8c2..683690ef1b 100644 --- a/Core/manifest.mf +++ b/Core/manifest.mf @@ -2,7 +2,7 @@ Manifest-Version: 1.0 OpenIDE-Module: org.sleuthkit.autopsy.core/10 OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/core/Bundle.properties OpenIDE-Module-Layer: org/sleuthkit/autopsy/core/layer.xml -OpenIDE-Module-Implementation-Version: 37 +OpenIDE-Module-Implementation-Version: 38 OpenIDE-Module-Requires: org.openide.windows.WindowManager AutoUpdate-Show-In-Client: true AutoUpdate-Essential-Module: true diff --git a/Core/nbproject/project.properties b/Core/nbproject/project.properties index 71acddc08a..893ff6510e 100644 --- a/Core/nbproject/project.properties +++ b/Core/nbproject/project.properties @@ -107,4 +107,4 @@ license.file=../LICENSE-2.0.txt nbm.homepage=http://www.sleuthkit.org/ nbm.module.author=Brian Carrier nbm.needs.restart=true -spec.version.base=10.24 +spec.version.base=10.25 diff --git a/CoreLibs/manifest.mf b/CoreLibs/manifest.mf index 1d3168bf2c..9f684569fe 100644 --- a/CoreLibs/manifest.mf +++ b/CoreLibs/manifest.mf @@ -1,6 +1,6 @@ Manifest-Version: 1.0 OpenIDE-Module: org.sleuthkit.autopsy.corelibs/3 -OpenIDE-Module-Implementation-Version: 7 +OpenIDE-Module-Implementation-Version: 8 OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/corelibs/Bundle.properties OpenIDE-Module-Specification-Version: 1.4 AutoUpdate-Show-In-Client: true diff --git a/Experimental/nbproject/project.xml b/Experimental/nbproject/project.xml index 7760187c5e..79af40a112 100644 --- a/Experimental/nbproject/project.xml +++ b/Experimental/nbproject/project.xml @@ -144,7 +144,7 @@ 10 - 10.24 + 10.25 @@ -162,7 +162,7 @@ 6 - 6.6 + 6.7 diff --git a/ImageGallery/nbproject/project.xml b/ImageGallery/nbproject/project.xml index 7a505d2ea6..d42fd1a08a 100644 --- a/ImageGallery/nbproject/project.xml +++ b/ImageGallery/nbproject/project.xml @@ -127,7 +127,7 @@ 10 - 10.24 + 10.25 diff --git a/KeywordSearch/manifest.mf b/KeywordSearch/manifest.mf index 0e947e073b..f4abb2b2b9 100644 --- a/KeywordSearch/manifest.mf +++ b/KeywordSearch/manifest.mf @@ -1,7 +1,7 @@ Manifest-Version: 1.0 AutoUpdate-Show-In-Client: true OpenIDE-Module: org.sleuthkit.autopsy.keywordsearch/6 -OpenIDE-Module-Implementation-Version: 23 +OpenIDE-Module-Implementation-Version: 24 OpenIDE-Module-Install: org/sleuthkit/autopsy/keywordsearch/Installer.class OpenIDE-Module-Layer: org/sleuthkit/autopsy/keywordsearch/layer.xml OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/keywordsearch/Bundle.properties diff --git a/KeywordSearch/nbproject/project.properties b/KeywordSearch/nbproject/project.properties index baa7a10c98..16289e9e73 100644 --- a/KeywordSearch/nbproject/project.properties +++ b/KeywordSearch/nbproject/project.properties @@ -48,4 +48,4 @@ javac.compilerargs=-Xlint -Xlint:-serial license.file=../LICENSE-2.0.txt nbm.homepage=http://www.sleuthkit.org/autopsy/ nbm.needs.restart=true -spec.version.base=6.6 +spec.version.base=6.7 diff --git a/KeywordSearch/nbproject/project.xml b/KeywordSearch/nbproject/project.xml index c1048f48ee..98a84faeb5 100644 --- a/KeywordSearch/nbproject/project.xml +++ b/KeywordSearch/nbproject/project.xml @@ -128,7 +128,7 @@ 10 - 10.24 + 10.25 diff --git a/RecentActivity/manifest.mf b/RecentActivity/manifest.mf index 03c6ce986b..6ab9cc4ccc 100644 --- a/RecentActivity/manifest.mf +++ b/RecentActivity/manifest.mf @@ -1,6 +1,6 @@ Manifest-Version: 1.0 OpenIDE-Module: org.sleuthkit.autopsy.recentactivity/6 -OpenIDE-Module-Implementation-Version: 19 +OpenIDE-Module-Implementation-Version: 20 OpenIDE-Module-Layer: org/sleuthkit/autopsy/recentactivity/layer.xml OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/recentactivity/Bundle.properties OpenIDE-Module-Requires: diff --git a/Testing/nbproject/project.xml b/Testing/nbproject/project.xml index c27ee220ec..cee5e3ed5b 100644 --- a/Testing/nbproject/project.xml +++ b/Testing/nbproject/project.xml @@ -47,7 +47,7 @@ 10 - 10.24 + 10.25 @@ -73,7 +73,7 @@ 6 - 6.6 + 6.7 diff --git a/nbproject/project.properties b/nbproject/project.properties index e8d17eb3c8..d613ea09d4 100644 --- a/nbproject/project.properties +++ b/nbproject/project.properties @@ -4,7 +4,7 @@ app.title=Autopsy ### lowercase version of above app.name=${branding.token} ### if left unset, version will default to today's date -app.version=4.20.0 +app.version=4.21.0 ### build.type must be one of: DEVELOPMENT, RELEASE #build.type=RELEASE build.type=DEVELOPMENT diff --git a/thunderbirdparser/nbproject/project.xml b/thunderbirdparser/nbproject/project.xml index 5c4fa0e042..abcccdc19c 100644 --- a/thunderbirdparser/nbproject/project.xml +++ b/thunderbirdparser/nbproject/project.xml @@ -54,7 +54,7 @@ 10 - 10.24 + 10.25 From fd74be8a11f14a55f41bafc8db52e0ff0391d1c8 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Fri, 25 Aug 2023 20:42:46 -0400 Subject: [PATCH 90/94] detect ct module --- .../autopsy/incidentoptions/Bundle.properties | 2 + .../incidentoptions/Bundle.properties-MERGED | 4 ++ .../CTIncidentImportOptionsPanel.form | 34 ++++++++++++-- .../CTIncidentImportOptionsPanel.java | 47 ++++++++++++++++++- 4 files changed, 82 insertions(+), 5 deletions(-) diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties index ebde860d0b..48a2628742 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties +++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties @@ -12,3 +12,5 @@ CTIncidentImportOptionsPanel.border.title_1=Incident Importer CTIncidentImportOptionsPanel.incidentTextLabel.text=The Cyber Triage Incident Import module allows you to open data collected by Cyber Triage in Autopsy. To use this feature you must install the Cyber Triage Import Module. CTincidentImportOptionsPanel.instructionsTextLabel.text= CTIncidentImportOptionsPanel.instructionsTextLabel.text=For instructions on obtaining the module refer to: +CTIncidentImportOptionsPanel.importModule.text=Cyber Triage Import Module: +CTIncidentImportOptionsPanel.importModuleDetected.text= diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties-MERGED b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties-MERGED index ebde860d0b..dd406e6725 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties-MERGED +++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties-MERGED @@ -12,3 +12,7 @@ CTIncidentImportOptionsPanel.border.title_1=Incident Importer CTIncidentImportOptionsPanel.incidentTextLabel.text=The Cyber Triage Incident Import module allows you to open data collected by Cyber Triage in Autopsy. To use this feature you must install the Cyber Triage Import Module. CTincidentImportOptionsPanel.instructionsTextLabel.text= CTIncidentImportOptionsPanel.instructionsTextLabel.text=For instructions on obtaining the module refer to: +CTIncidentImportOptionsPanel.importModule.text=Cyber Triage Import Module: +CTIncidentImportOptionsPanel.importModuleDetected.text= +CTIncidentImportOptionsPanel_setModuleDetected_detected=Detected +CTIncidentImportOptionsPanel_setModuleDetected_notDetected=Not Detected diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.form b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.form index 7382a2de2c..fd11f53ee8 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.form +++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.form @@ -42,7 +42,35 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -68,7 +96,7 @@ - + @@ -86,7 +114,7 @@ - + diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.java index ef7aa5a67e..40a2c0fe3f 100644 --- a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.java +++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.java @@ -24,15 +24,20 @@ import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; +import java.util.Collection; import java.util.Collections; import java.util.logging.Level; +import java.util.stream.Stream; import org.sleuthkit.autopsy.coreutils.Logger; import javax.swing.JFileChooser; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import org.apache.commons.lang3.StringUtils; import org.netbeans.spi.options.OptionsPanelController; +import org.openide.util.Lookup; +import org.openide.util.NbBundle.Messages; import org.openide.util.lookup.ServiceProvider; +import org.sleuthkit.autopsy.casemodule.AutopsyContentProvider; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.guiutils.JFileChooserFactory; @@ -46,6 +51,8 @@ public class CTIncidentImportOptionsPanel extends CTOptionsSubPanel { private static final String CT_IMPORTER_DOC_LINK = "https://docs.cybertriage.com/en/latest/chapters/integrations/autopsy.html"; + private static final String CT_STANDARD_CONTENT_PROVIDER_NAME = "CTStandardContentProvider"; + private final JFileChooserFactory fileRepoChooserFactory = new JFileChooserFactory(); private final CTSettingsPersistence ctPersistence = CTSettingsPersistence.getInstance(); @@ -93,8 +100,23 @@ public class CTIncidentImportOptionsPanel extends CTOptionsSubPanel { public synchronized void loadSettings() { CTSettings ctSettings = ctPersistence.loadCTSettings(); setCTSettingsDisplay(ctSettings); + setModuleDetected(); setEnabledItems(Case.isCaseOpen()); } + + @Messages({ + "CTIncidentImportOptionsPanel_setModuleDetected_detected=Detected", + "CTIncidentImportOptionsPanel_setModuleDetected_notDetected=Not Detected" + }) + private void setModuleDetected() { + Collection contentProviders = Lookup.getDefault().lookupAll(AutopsyContentProvider.class); + boolean detected = ((Collection) (contentProviders != null ? contentProviders : Collections.emptyList())).stream() + .anyMatch(p -> p != null && StringUtils.defaultString(p.getName()).toUpperCase().startsWith(CT_STANDARD_CONTENT_PROVIDER_NAME.toUpperCase())); + + this.importModuleDetected.setText(detected + ? Bundle.CTIncidentImportOptionsPanel_setModuleDetected_detected() + : Bundle.CTIncidentImportOptionsPanel_setModuleDetected_notDetected()); + } private void setEnabledItems(boolean caseOpen) { this.caseOpenWarningLabel.setVisible(caseOpen); @@ -127,6 +149,8 @@ public class CTIncidentImportOptionsPanel extends CTOptionsSubPanel { incidentTextPanel = new javax.swing.JPanel(); incidentTextLabel = new javax.swing.JLabel(); + javax.swing.JLabel importModule = new javax.swing.JLabel(); + importModuleDetected = new javax.swing.JLabel(); instructionsPanel = new javax.swing.JPanel(); instructionsTextLabel = new javax.swing.JLabel(); instructionsLinkLabel = new javax.swing.JLabel(); @@ -145,10 +169,28 @@ public class CTIncidentImportOptionsPanel extends CTOptionsSubPanel { gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; + gridBagConstraints.gridwidth = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); incidentTextPanel.add(incidentTextLabel, gridBagConstraints); + org.openide.awt.Mnemonics.setLocalizedText(importModule, org.openide.util.NbBundle.getMessage(CTIncidentImportOptionsPanel.class, "CTIncidentImportOptionsPanel.importModule.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 3); + incidentTextPanel.add(importModule, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(importModuleDetected, org.openide.util.NbBundle.getMessage(CTIncidentImportOptionsPanel.class, "CTIncidentImportOptionsPanel.importModuleDetected.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(5, 0, 5, 5); + incidentTextPanel.add(importModuleDetected, gridBagConstraints); + gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; @@ -161,7 +203,7 @@ public class CTIncidentImportOptionsPanel extends CTOptionsSubPanel { gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 0); + gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 0); instructionsPanel.add(instructionsTextLabel, gridBagConstraints); instructionsTextLabel.getAccessibleContext().setAccessibleName("For instructions on obtaining the module refer to:"); @@ -176,7 +218,7 @@ public class CTIncidentImportOptionsPanel extends CTOptionsSubPanel { gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 0; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); + gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5); instructionsPanel.add(instructionsLinkLabel, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); @@ -283,6 +325,7 @@ public class CTIncidentImportOptionsPanel extends CTOptionsSubPanel { private javax.swing.JLabel caseOpenWarningLabel; private javax.swing.JButton fileRepoBrowseButton; private javax.swing.JTextField fileRepoPathField; + private javax.swing.JLabel importModuleDetected; private javax.swing.JLabel incidentTextLabel; private javax.swing.JPanel incidentTextPanel; private javax.swing.JLabel instructionsLinkLabel; From c70eec9ced5f1461c0436a89293356f7faa1855b Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 28 Aug 2023 13:23:53 -0400 Subject: [PATCH 91/94] update sqlite to 3.42.0.1 --- Core/build.xml | 4 ++-- Core/nbproject/project.properties | 2 +- Core/nbproject/project.xml | 4 ++-- ImageGallery/nbproject/project.properties | 2 +- ImageGallery/nbproject/project.xml | 4 ++-- RecentActivity/nbproject/project.properties | 2 +- RecentActivity/nbproject/project.xml | 4 ++-- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Core/build.xml b/Core/build.xml index 5b8a4aec61..0c83b8158f 100644 --- a/Core/build.xml +++ b/Core/build.xml @@ -134,8 +134,8 @@ - + release/modules/ext/spotbugs-annotations-4.6.0.jar - ext/sqlite-jdbc-3.42.0.0.jar - release/modules/ext/sqlite-jdbc-3.42.0.0.jar + ext/sqlite-jdbc-3.42.0.1.jar + release/modules/ext/sqlite-jdbc-3.42.0.1.jar ext/txw2-2.3.3.jar diff --git a/ImageGallery/nbproject/project.properties b/ImageGallery/nbproject/project.properties index d9bd5f605c..d69f7d273a 100644 --- a/ImageGallery/nbproject/project.properties +++ b/ImageGallery/nbproject/project.properties @@ -1,4 +1,4 @@ -file.reference.sqlite-jdbc-3.42.0.0.jar=release/modules/ext/sqlite-jdbc-3.42.0.0.jar +file.reference.sqlite-jdbc-3.42.0.1.jar=release/modules/ext/sqlite-jdbc-3.42.0.1.jar javac.source=17 javac.compilerargs=-Xlint -Xlint:-serial license.file=LICENSE-2.0.txt diff --git a/ImageGallery/nbproject/project.xml b/ImageGallery/nbproject/project.xml index d42fd1a08a..49221290cd 100644 --- a/ImageGallery/nbproject/project.xml +++ b/ImageGallery/nbproject/project.xml @@ -142,8 +142,8 @@ - ext/sqlite-jdbc-3.42.0.0.jar - release/modules/ext/sqlite-jdbc-3.42.0.0.jar + ext/sqlite-jdbc-3.42.0.1.jar + release/modules/ext/sqlite-jdbc-3.42.0.1.jar diff --git a/RecentActivity/nbproject/project.properties b/RecentActivity/nbproject/project.properties index 1727284eb3..430436bea9 100644 --- a/RecentActivity/nbproject/project.properties +++ b/RecentActivity/nbproject/project.properties @@ -1,6 +1,6 @@ javac.source=17 file.reference.Rejistry-1.1-SNAPSHOT.jar=release/modules/ext/Rejistry-1.1-SNAPSHOT.jar -file.reference.sqlite-jdbc-3.42.0.0.jar=release/modules/ext/sqlite-jdbc-3.42.0.0.jar +file.reference.sqlite-jdbc-3.42.0.1.jar=release/modules/ext/sqlite-jdbc-3.42.0.1.jar javac.compilerargs=-Xlint -Xlint:-serial license.file=../LICENSE-2.0.txt nbm.homepage=http://www.sleuthkit.org/autopsy/ diff --git a/RecentActivity/nbproject/project.xml b/RecentActivity/nbproject/project.xml index bf1d1df30b..05745bb79a 100644 --- a/RecentActivity/nbproject/project.xml +++ b/RecentActivity/nbproject/project.xml @@ -88,8 +88,8 @@ release/modules/ext/Rejistry-1.1-SNAPSHOT.jar - ext/sqlite-jdbc-3.42.0.0.jar - release/modules/ext/sqlite-jdbc-3.42.0.0.jar + ext/sqlite-jdbc-3.42.0.1.jar + release/modules/ext/sqlite-jdbc-3.42.0.1.jar From cbabf3a3fe50dd43ddb71753b4bc023918dab250 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Mon, 28 Aug 2023 21:21:19 -0400 Subject: [PATCH 92/94] update malware docs --- docs/doxygen-user/ct_malware_scanner.dox | 10 ++++++---- docs/doxygen-user/footer.html | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/doxygen-user/ct_malware_scanner.dox b/docs/doxygen-user/ct_malware_scanner.dox index 21d857e6f7..ea73f1dcba 100644 --- a/docs/doxygen-user/ct_malware_scanner.dox +++ b/docs/doxygen-user/ct_malware_scanner.dox @@ -13,17 +13,19 @@ For more information on what the module does or obtaining a license, refer to [C Configuration -======= +============== You will need to first get a paid or eval license from the above URL. The code will come in via email. Example license formats include: + * AUT-8ed86eb5-17fc-4b3a-9b75-ce638c11b070 * b826a555-951f-42ca-86ce-439a81106688 -Once you have a license, you must add it on the Options panel. Choose the 'Cyber Triage' tab and choose 'Add License'. +Once you have a license, you must add it on the Autopsy Options panel. +Choose the 'Cyber Triage' tab and choose 'Add License'. \image html malware-scanner-global-options-panel-no-license.png -After you enter the license number that you should have received from your email, you will then need to review and agree to the license terms. +After you enter the license number from your email, you will then need to review and agree to the license terms. The options panel should now display information about the lookup limits. You can always refer back to here about what your limits are and when they reset. @@ -38,7 +40,7 @@ Using the Module Ingest Settings ------ -For each data source, you select if you want files to be uploaded if they have not already been analyzed. By default, they are uploaded. You can choose to not upload them though. +For each data source, you select if you want files to be uploaded if they have not already been analyzed. By default, they are uploaded. You can choose to not upload them though. Refer to the main [website](https://cybertriage.com/autopsy-malware-module) for details on what happens when files are uploaded. \image html malware-scanner-ingest-panel.png diff --git a/docs/doxygen-user/footer.html b/docs/doxygen-user/footer.html index d648961fdc..cfedffe82c 100644 --- a/docs/doxygen-user/footer.html +++ b/docs/doxygen-user/footer.html @@ -1,5 +1,5 @@

xhbR(;BWv9z5-j6QrVrt1m4w1PV{ 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 Iwfj&17iemGumAu6 literal 0 HcmV?d00001 diff --git a/docs/doxygen-user/images/malware-scanner-ingest-panel.png b/docs/doxygen-user/images/malware-scanner-ingest-panel.png new file mode 100644 index 0000000000000000000000000000000000000000..719768baaf9acc36c9f6ecda010d0ed877e45d31 GIT binary patch literal 69373 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