some updates

This commit is contained in:
Greg DiCristofaro 2023-07-20 21:45:39 -04:00
parent 38ad881023
commit 541825472a
14 changed files with 106 additions and 43 deletions

View File

@ -22,14 +22,23 @@ import java.net.PasswordAuthentication;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.logging.Level; import java.util.logging.Level;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity; import org.apache.http.HttpEntity;
import org.apache.http.HttpHost; import org.apache.http.HttpHost;
@ -80,14 +89,8 @@ public class CTCloudHttpClient {
private String hostName = null; private String hostName = null;
private CTCloudHttpClient() { private CTCloudHttpClient() {
SSLContext tmpSslContext; // leave as null for now unless we want to customize this at a later date
try { this.sslContext = null;
tmpSslContext = SSLContext.getInstance("TLSv1.2");
} catch (NoSuchAlgorithmException ex) {
LOGGER.log(Level.WARNING, "Unable to setup ssl context instance", ex);
tmpSslContext = null;
}
this.sslContext = tmpSslContext;
} }
private ProxySettingArgs getProxySettings() { private ProxySettingArgs getProxySettings() {
@ -100,10 +103,12 @@ public class CTCloudHttpClient {
} }
int proxyPort = 0; int proxyPort = 0;
if (StringUtils.isNotBlank(ProxySettings.getHttpPort())) {
try { try {
proxyPort = Integer.parseInt(ProxySettings.getHttpsPort()); proxyPort = Integer.parseInt(ProxySettings.getHttpsPort());
} catch (NumberFormatException ex) { } catch (NumberFormatException ex) {
LOGGER.log(Level.WARNING, "An exception occurred while converting port number to integer", ex); LOGGER.log(Level.WARNING, "Unable to convert port to integer");
}
} }
return new ProxySettingArgs( return new ProxySettingArgs(

View File

@ -13,12 +13,7 @@
************************************************************************** */ ************************************************************************** */
package com.basistech.df.cybertriage.autopsy.ctapi; package com.basistech.df.cybertriage.autopsy.ctapi;
import com.google.common.collect.ImmutableList;
import java.net.URI; import java.net.URI;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
// TODO take out anything sensitive or not used // TODO take out anything sensitive or not used
final public class Constants { final public class Constants {
@ -31,10 +26,13 @@ final public class Constants {
public static final String SSLTEST_URL = "https://www2.cybertriage.com/ssl_test.html"; public static final String SSLTEST_URL = "https://www2.cybertriage.com/ssl_test.html";
public static final String CT_CLOUD_SERVER = "https://rep1.cybertriage.com";
public static final String CT_CLOUD_DEV_SERVER = "https://cyber-triage-dev.appspot.com"; public static final String CT_CLOUD_DEV_SERVER = "https://cyber-triage-dev.appspot.com";
// TODO put back
public static final String CT_CLOUD_SERVER = CT_CLOUD_DEV_SERVER; //"https://rep1.cybertriage.com";
/** /**
* Link to watch demo video * Link to watch demo video
* @since 3.1.0 * @since 3.1.0

View File

@ -36,6 +36,7 @@ public class CTApiDAO {
private static final String LICENSE_REQUEST_PATH = "/_ah/api/license/v1/activate"; 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 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_SERVER_HASH_PATH = "/_ah/api/reputation/v1/query/file/hash/md5?query_types=CORRELATION,MALWARE";
private static final String AUTOPSY_PRODUCT = "AUTOPSY";
private static final CTApiDAO instance = new CTApiDAO(); private static final CTApiDAO instance = new CTApiDAO();
@ -48,7 +49,7 @@ public class CTApiDAO {
} }
private static String getAppVersion() { private static String getAppVersion() {
return Version.getName() + " " + Version.getVersion(); return Version.getVersion();
} }
private final CTCloudHttpClient httpClient = CTCloudHttpClient.getInstance(); private final CTCloudHttpClient httpClient = CTCloudHttpClient.getInstance();
@ -58,7 +59,7 @@ public class CTApiDAO {
LicenseRequest licenseRequest = new LicenseRequest() LicenseRequest licenseRequest = new LicenseRequest()
.setBoostLicenseCode(licenseString) .setBoostLicenseCode(licenseString)
.setHostId(CTHostIDGenerationUtil.generateLicenseHostID()) .setHostId(CTHostIDGenerationUtil.generateLicenseHostID())
.setProduct(getAppVersion()); .setProduct(AUTOPSY_PRODUCT);
return httpClient.doPost(LICENSE_REQUEST_PATH, licenseRequest, LicenseResponse.class); return httpClient.doPost(LICENSE_REQUEST_PATH, licenseRequest, LicenseResponse.class);
@ -89,8 +90,4 @@ public class CTApiDAO {
? Collections.emptyList() ? Collections.emptyList()
: resp.getItems(); : resp.getItems();
} }
public enum ResultType {
OK, SERVER_ERROR, NOT_AUTHORIZED
}
} }

View File

@ -13,8 +13,12 @@
************************************************************************** */ ************************************************************************** */
package com.basistech.df.cybertriage.autopsy.ctapi.json; package com.basistech.df.cybertriage.autopsy.ctapi.json;
import com.basistech.df.cybertriage.autopsy.ctapi.util.ObjectMapperUtil.InstantEpochMillisDeserializer;
import com.basistech.df.cybertriage.autopsy.ctapi.util.ObjectMapperUtil.MDYDateDeserializer;
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import java.time.Instant;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
/** /**
@ -27,7 +31,7 @@ public class DecryptedLicenseResponse {
private final ZonedDateTime expirationDate; private final ZonedDateTime expirationDate;
private final Long hashLookups; private final Long hashLookups;
private final Long fileUploads; private final Long fileUploads;
private final ZonedDateTime activationTime; private final Instant activationTime;
private final String product; private final String product;
private final String limitType; private final String limitType;
@ -35,12 +39,17 @@ public class DecryptedLicenseResponse {
public DecryptedLicenseResponse( public DecryptedLicenseResponse(
@JsonProperty("boostLicenseId") String boostLicenseId, @JsonProperty("boostLicenseId") String boostLicenseId,
@JsonProperty("licenseHostId") String licenseHostId, @JsonProperty("licenseHostId") String licenseHostId,
@JsonDeserialize(using=MDYDateDeserializer.class)
@JsonProperty("expirationDate") ZonedDateTime expirationDate, @JsonProperty("expirationDate") ZonedDateTime expirationDate,
@JsonProperty("hashLookups") Long hashLookups, @JsonProperty("hashLookups") Long hashLookups,
@JsonProperty("fileUploads") Long fileUploads, @JsonProperty("fileUploads") Long fileUploads,
@JsonProperty("activationTime") ZonedDateTime activationTime, @JsonDeserialize(using=InstantEpochMillisDeserializer.class)
@JsonProperty("activationTime") Instant activationTime,
@JsonProperty("product") String product, @JsonProperty("product") String product,
@JsonProperty("limitType") String limitType @JsonProperty("limitType") String limitType,
@JsonProperty("l4jLicenseId") String l4jlicenseId,
@JsonProperty("ctLicenseId") String ctLicenseId
) { ) {
this.boostLicenseId = boostLicenseId; this.boostLicenseId = boostLicenseId;
this.licenseHostId = licenseHostId; this.licenseHostId = licenseHostId;
@ -68,7 +77,7 @@ public class DecryptedLicenseResponse {
return fileUploads; return fileUploads;
} }
public ZonedDateTime getActivationTime() { public Instant getActivationTime() {
return activationTime; return activationTime;
} }

View File

@ -87,9 +87,9 @@ public class LicenseDecryptorUtil {
} }
DecryptedLicenseResponse decryptedLicense = objectMapper.readValue(decryptedJsonResponse, DecryptedLicenseResponse.class); DecryptedLicenseResponse decryptedLicense = objectMapper.readValue(decryptedJsonResponse, DecryptedLicenseResponse.class);
if (!"CYBERTRIAGE".equalsIgnoreCase(decryptedLicense.getProduct())) { if (!"AUTOPSY".equalsIgnoreCase(decryptedLicense.getProduct())) {
// license file is expected to contain product of "CYBERTRIAGE" // license file is expected to contain product of "CYBERTRIAGE"
throw new InvalidLicenseException("Not a valid Cyber Triage license"); throw new InvalidLicenseException("Not a valid Autopsy license");
} }
return decryptedLicense; return decryptedLicense;

View File

@ -13,8 +13,19 @@
************************************************************************** */ ************************************************************************** */
package com.basistech.df.cybertriage.autopsy.ctapi.util; package com.basistech.df.cybertriage.autopsy.ctapi.util;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.io.IOException;
import java.time.DateTimeException;
import java.time.Instant;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
/** /**
* Creates default ObjectMapper * Creates default ObjectMapper
@ -33,9 +44,41 @@ public class ObjectMapperUtil {
public ObjectMapper getDefaultObjectMapper() { public ObjectMapper getDefaultObjectMapper() {
ObjectMapper defaultMapper = new ObjectMapper(); ObjectMapper defaultMapper = new ObjectMapper();
defaultMapper.configure(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // defaultMapper.configure(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
defaultMapper.registerModule(new JavaTimeModule()); defaultMapper.registerModule(new JavaTimeModule());
return defaultMapper; return defaultMapper;
} }
public static class MDYDateDeserializer extends JsonDeserializer<ZonedDateTime> {
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("MMM dd, yyyy");
@Override
public ZonedDateTime deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JacksonException {
JsonNode node = jp.getCodec().readTree(jp);
String nodeText = node.asText();
try {
return ZonedDateTime.parse(nodeText, FORMATTER);
} catch (DateTimeParseException ex) {
return null;
}
}
}
public static class InstantEpochMillisDeserializer extends JsonDeserializer<Instant> {
@Override
public Instant deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JacksonException {
JsonNode node = jp.getCodec().readTree(jp);
if (!node.isNumber()) {
return null;
} else {
try {
long millis = node.asLong();
return Instant.ofEpochMilli(millis);
} catch (DateTimeException ex) {
return null;
}
}
}
}
} }

View File

@ -2,7 +2,7 @@
# Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license # 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 # Click nbfs://nbhost/SystemFileSystem/Templates/Other/properties.properties to edit this template
CTLicenseDialog.title=Add a License...
CTLicenseDialog.licenseNumberLabel.text=License Number: CTLicenseDialog.licenseNumberLabel.text=License Number:
CTLicenseDialog.licenseNumberTextField.text=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX CTLicenseDialog.licenseNumberTextField.text=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
CTLicenseDialog.cancelButton.text=Cancel CTLicenseDialog.cancelButton.text=Cancel
@ -21,3 +21,4 @@ CTMalwareScannerOptionsPanel.licenseInfoIdLabel.text=
CTMalwareScannerOptionsPanel.licenseInfoExpiresLabel.text= CTMalwareScannerOptionsPanel.licenseInfoExpiresLabel.text=
CTMalwareScannerOptionsPanel.fileUploadsRemainingLabel.text= CTMalwareScannerOptionsPanel.fileUploadsRemainingLabel.text=
CTMalwareScannerOptionsPanel.licenseInfoUserLabel.text= CTMalwareScannerOptionsPanel.licenseInfoUserLabel.text=

View File

@ -2,7 +2,7 @@
# Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license # 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 # Click nbfs://nbhost/SystemFileSystem/Templates/Other/properties.properties to edit this template
CTLicenseDialog.title=Add a License...
CTLicenseDialog.licenseNumberLabel.text=License Number: CTLicenseDialog.licenseNumberLabel.text=License Number:
CTLicenseDialog.licenseNumberTextField.text=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX CTLicenseDialog.licenseNumberTextField.text=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
CTLicenseDialog.cancelButton.text=Cancel CTLicenseDialog.cancelButton.text=Cancel
@ -22,6 +22,7 @@ CTMalwareScannerOptionsPanel.licenseInfoIdLabel.text=
CTMalwareScannerOptionsPanel.licenseInfoExpiresLabel.text= CTMalwareScannerOptionsPanel.licenseInfoExpiresLabel.text=
CTMalwareScannerOptionsPanel.fileUploadsRemainingLabel.text= CTMalwareScannerOptionsPanel.fileUploadsRemainingLabel.text=
CTMalwareScannerOptionsPanel.licenseInfoUserLabel.text= CTMalwareScannerOptionsPanel.licenseInfoUserLabel.text=
CTMalwareScannerOptionsPanel_licenseAddDialog_desc=License Number: CTMalwareScannerOptionsPanel_licenseAddDialog_desc=License Number:
CTMalwareScannerOptionsPanel_licenseAddDialog_title=Add a License... CTMalwareScannerOptionsPanel_licenseAddDialog_title=Add a License...
CTMalwareScannerOptionsPanel_licenseAddDialogEnteredErr_desc=The license number has already been entered CTMalwareScannerOptionsPanel_licenseAddDialogEnteredErr_desc=The license number has already been entered

View File

@ -24,8 +24,9 @@ import org.openide.util.NbBundle.Messages;
*/ */
public class CTLicenseDialog extends javax.swing.JDialog { public class CTLicenseDialog extends javax.swing.JDialog {
private static final Pattern LICENSE_PATTERN = Pattern.compile("^\\s*[0-9a-zA-Z]{8}\\-[0-9a-zA-Z]{4}\\-[0-9a-zA-Z]{4}\\-[0-9a-zA-Z]{4}\\-[0-9a-zA-Z]{12}\\s*$"); //private static final Pattern LICENSE_PATTERN = Pattern.compile("^\\s*[0-9a-zA-Z]{8}\\-[0-9a-zA-Z]{4}\\-[0-9a-zA-Z]{4}\\-[0-9a-zA-Z]{4}\\-[0-9a-zA-Z]{12}\\s*$");
private static final Pattern LICENSE_PATTERN = Pattern.compile("\\s*[a-zA-Z0-9\\-]+?\\s*");
private String licenseString = null; private String licenseString = null;
/** /**

View File

@ -49,6 +49,7 @@ public class CTLicensePersistence {
if (licenseResponse != null) { if (licenseResponse != null) {
File licenseFile = getCTLicenseFile(); File licenseFile = getCTLicenseFile();
try { try {
licenseFile.getParentFile().mkdirs();
objectMapper.writeValue(licenseFile, licenseResponse); objectMapper.writeValue(licenseFile, licenseResponse);
return true; return true;
} catch (IOException ex) { } catch (IOException ex) {
@ -62,7 +63,7 @@ public class CTLicensePersistence {
public synchronized Optional<LicenseResponse> loadLicenseResponse() { public synchronized Optional<LicenseResponse> loadLicenseResponse() {
Optional<LicenseResponse> toRet = Optional.empty(); Optional<LicenseResponse> toRet = Optional.empty();
File licenseFile = getCTLicenseFile(); File licenseFile = getCTLicenseFile();
if (licenseFile.isFile()) { if (licenseFile.exists() && licenseFile.isFile()) {
try { try {
toRet = Optional.ofNullable(objectMapper.readValue(licenseFile, LicenseResponse.class)); toRet = Optional.ofNullable(objectMapper.readValue(licenseFile, LicenseResponse.class));
} catch (IOException ex) { } catch (IOException ex) {

View File

@ -162,12 +162,15 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel {
this.authTokenFetcher.cancel(true); this.authTokenFetcher.cancel(true);
} }
setMalwareScansDisplay(null, Bundle.CTOPtionsPanel_loadMalwareScansInfo_loading());
if (licenseInfo == null || licenseInfo.getDecryptedLicense() == null) { if (licenseInfo == null || licenseInfo.getDecryptedLicense() == null) {
setMalwareScansDisplay(null, null);
return; return;
} }
setMalwareScansDisplay(null, Bundle.CTOPtionsPanel_loadMalwareScansInfo_loading());
this.authTokenFetcher = new AuthTokenFetcher(licenseInfo.getDecryptedLicense().getBoostLicenseId()); this.authTokenFetcher = new AuthTokenFetcher(licenseInfo.getDecryptedLicense().getBoostLicenseId());
this.authTokenFetcher.execute(); this.authTokenFetcher.execute();
} }
@ -388,7 +391,7 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel {
this.licenseInfoUserLabel.setVisible(false); this.licenseInfoUserLabel.setVisible(false);
} else { } else {
this.licenseInfoExpiresLabel.setVisible(true); this.licenseInfoExpiresLabel.setVisible(true);
this.licenseInfoExpiresLabel.setText(Bundle.CTMalwareScannerOptionsPanel_licenseInfo_expires(LICENSE_EXPIRES_FORMAT.format(this.licenseInfo.getDecryptedLicense().getExpirationDate()))); this.licenseInfoExpiresLabel.setText(Bundle.CTMalwareScannerOptionsPanel_licenseInfo_expires(this.licenseInfo.getDecryptedLicense().getExpirationDate() == null ? "" : LICENSE_EXPIRES_FORMAT.format(this.licenseInfo.getDecryptedLicense().getExpirationDate())));
this.licenseInfoIdLabel.setVisible(true); this.licenseInfoIdLabel.setVisible(true);
this.licenseInfoIdLabel.setText(Bundle.CTMalwareScannerOptionsPanel_licenseInfo_id(this.licenseInfo.getDecryptedLicense().getBoostLicenseId())); this.licenseInfoIdLabel.setText(Bundle.CTMalwareScannerOptionsPanel_licenseInfo_id(this.licenseInfo.getDecryptedLicense().getBoostLicenseId()));
this.licenseInfoUserLabel.setVisible(true); this.licenseInfoUserLabel.setVisible(true);
@ -412,7 +415,7 @@ public class CTMalwareScannerOptionsPanel extends CTOptionsSubPanel {
this.maxFileUploadsLabel.setVisible(true); this.maxFileUploadsLabel.setVisible(true);
this.maxFileUploadsLabel.setText(Bundle.CTMalwareScannerOptionsPanel_malwareScans_maxDailyFileLookups(this.authTokenResponse.getFileUploadLimit())); this.maxFileUploadsLabel.setText(Bundle.CTMalwareScannerOptionsPanel_malwareScans_maxDailyFileLookups(this.authTokenResponse.getFileUploadLimit()));
this.countersResetLabel.setVisible(true); this.countersResetLabel.setVisible(true);
this.countersResetLabel.setText(Bundle.CTMalwareScannerOptionsPanel_malwareScans_countersReset(MALWARE_SCANS_RESET_FORMAT.format(this.authTokenResponse.getExpiration()))); this.countersResetLabel.setText(Bundle.CTMalwareScannerOptionsPanel_malwareScans_countersReset(this.authTokenResponse.getExpiration() == null ? "" : MALWARE_SCANS_RESET_FORMAT.format(this.authTokenResponse.getExpiration())));
this.hashLookupsRemainingLabel.setVisible(true); 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.setVisible(true);

View File

@ -64,6 +64,10 @@
<package>com.fasterxml.jackson.databind.util</package> <package>com.fasterxml.jackson.databind.util</package>
<package>com.fasterxml.jackson.dataformat.csv</package> <package>com.fasterxml.jackson.dataformat.csv</package>
<package>com.fasterxml.jackson.datatype.jsr310</package> <package>com.fasterxml.jackson.datatype.jsr310</package>
<package>com.fasterxml.jackson.datatype.jsr310.deser</package>
<package>com.fasterxml.jackson.datatype.jsr310.deser.key</package>
<package>com.fasterxml.jackson.datatype.jsr310.ser</package>
<package>com.fasterxml.jackson.datatype.jsr310.ser.key</package>
<package>com.fasterxml.jackson.datatype.jsr310.util</package> <package>com.fasterxml.jackson.datatype.jsr310.util</package>
<package>com.github.lgooddatepicker.components</package> <package>com.github.lgooddatepicker.components</package>
<package>com.github.lgooddatepicker.optionalusertools</package> <package>com.github.lgooddatepicker.optionalusertools</package>

View File

@ -1,5 +1,5 @@
#Updated by build script #Updated by build script
#Thu, 20 Jul 2023 14:02:30 -0400 #Thu, 20 Jul 2023 19:55:04 -0400
LBL_splash_window_title=Starting Autopsy LBL_splash_window_title=Starting Autopsy
SPLASH_HEIGHT=314 SPLASH_HEIGHT=314
SPLASH_WIDTH=538 SPLASH_WIDTH=538

View File

@ -1,4 +1,4 @@
#Updated by build script #Updated by build script
#Thu, 20 Jul 2023 14:02:30 -0400 #Thu, 20 Jul 2023 19:55:04 -0400
CTL_MainWindow_Title=Autopsy 4.20.0 CTL_MainWindow_Title=Autopsy 4.20.0
CTL_MainWindow_Title_No_Project=Autopsy 4.20.0 CTL_MainWindow_Title_No_Project=Autopsy 4.20.0