diff --git a/app/build.gradle b/app/build.gradle index e76de54..6fc3171 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,8 +6,8 @@ android { applicationId "us.spotco.malwarescanner" minSdkVersion 19 targetSdkVersion 32 - versionCode 113 - versionName "2.36" + versionCode 116 + versionName "2.37" resConfigs 'en', 'af', 'de', 'el', 'es', 'fi', 'fr', 'it', 'pl', 'pt', 'ru', 'tr', 'zh-rCN' } buildTypes { diff --git a/app/src/main/java/us/spotco/malwarescanner/Database.java b/app/src/main/java/us/spotco/malwarescanner/Database.java index 7c6ebec..629bc86 100644 --- a/app/src/main/java/us/spotco/malwarescanner/Database.java +++ b/app/src/main/java/us/spotco/malwarescanner/Database.java @@ -166,10 +166,10 @@ class Database { boolean onionRouting = (boolean) objects[0]; String url = (String) objects[1]; File out = new File((String) objects[2]); - File outNew = new File((String) objects[2] + ".new"); + File outNew = new File(objects[2] + ".new"); String baseURL = (String) objects[3]; try { - if(outNew.exists()) { + if (outNew.exists()) { outNew.delete(); } HttpURLConnection connection; @@ -218,7 +218,7 @@ class Database { connection.disconnect(); } catch (Exception e) { e.printStackTrace(); - if(outNew.exists()) { + if (outNew.exists()) { outNew.delete(); } publishProgress(url.replaceAll(baseURL, "") @@ -232,4 +232,13 @@ class Database { log.append(progress[0] + "\n"); } } + + public static boolean selfTest() { + if (signaturesMD5 != null && signaturesSHA1 != null && signaturesSHA256 != null) { + return signaturesMD5.mightContain("903616d0dbe074aa363d2d49c03f7362") + && signaturesSHA1.mightContain("fc4a3e802894cc2229be77ec6f082d1aab744e54") + && signaturesSHA256.mightContain("df44844a0e99ddd935e8419257440a2ca7ef3243435a67416fcbb6cd3ae560c3"); + } + return false; + } } diff --git a/app/src/main/java/us/spotco/malwarescanner/MainActivity.java b/app/src/main/java/us/spotco/malwarescanner/MainActivity.java index a3b46e4..20fd6cc 100644 --- a/app/src/main/java/us/spotco/malwarescanner/MainActivity.java +++ b/app/src/main/java/us/spotco/malwarescanner/MainActivity.java @@ -279,28 +279,29 @@ public class MainActivity extends Activity { private void updateDatabase() { new Database(findViewById(R.id.txtLogOutput)); - if(!Database.isDatabaseLoading()) { + if (!Database.isDatabaseLoading()) { Database.updateDatabase(this, Database.signatureDatabases); } else { - Log.w("Hypatia", "Database is loading, not downloading!"); + logView.append(getString(R.string.lblDatabaseLoading) + "\n"); } - if (Database.isDatabaseLoaded()) { - Utils.getThreadPoolExecutor().execute(() -> { - try { + Utils.getThreadPoolExecutor().execute(() -> { + try { + Thread.sleep(500); + Log.w("Hypatia", "Invoking database reload!"); + while (Database.hasDownloadsRunning()) { Thread.sleep(500); - Log.w("Hypatia", "Invoking database reload!"); - while (Database.hasDownloadsRunning()) { - Thread.sleep(500); - Log.w("Hypatia", "Download in progress, waiting!"); + Log.w("Hypatia", "Download in progress, waiting!"); - } - } catch (InterruptedException e) { - throw new RuntimeException(e); } + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + logView.append(getString(R.string.lblDatabasesUpdated) + "\n"); + if (Database.isDatabaseLoaded()) { Log.w("Hypatia", "Really reloading database!"); Database.loadDatabase(getApplicationContext(), true, Database.signatureDatabases); - }); - } + } + }); } private void updateScanButton(boolean running) { diff --git a/app/src/main/java/us/spotco/malwarescanner/MalwareScanner.java b/app/src/main/java/us/spotco/malwarescanner/MalwareScanner.java index eee0e6a..432c15a 100644 --- a/app/src/main/java/us/spotco/malwarescanner/MalwareScanner.java +++ b/app/src/main/java/us/spotco/malwarescanner/MalwareScanner.java @@ -137,6 +137,13 @@ class MalwareScanner extends AsyncTask, Object, String> { if (Database.isDatabaseLoaded()) { publishProgress("\t" + context.getString(R.string.main_database_loaded, "?") + "\n", true); + //Perform a self-test + if (Database.selfTest()) { + publishProgress("\t" + context.getString(R.string.self_test_result_success), true); + } else { + publishProgress("\t" + context.getString(R.string.self_test_result_failure), true); + } + //Get file hashes publishProgress("\t" + context.getString(R.string.main_hashing_files), true); publishProgress("\t", true); @@ -203,7 +210,7 @@ class MalwareScanner extends AsyncTask, Object, String> { } private void checkSignature(String hashType, HashMap signaturesToCheck, BloomFilter signatureDatabase) { - if (Database.isDatabaseLoaded()) { + if (Database.isDatabaseLoaded() && signatureDatabase != null) { for (Map.Entry file : signaturesToCheck.entrySet()) { if (signatureDatabase.mightContain(file.getValue())) { publishProgress("Potential match in " + file.getKey().toString().replaceAll(Environment.getExternalStorageDirectory().toString(), "~"), false); @@ -239,9 +246,9 @@ class MalwareScanner extends AsyncTask, Object, String> { fis.close(); - fileHashesMD5.put(file, String.format("%032x", new BigInteger(1, digestMD5.digest()))); - fileHashesSHA1.put(file, String.format("%032x", new BigInteger(1, digestSHA1.digest()))); - fileHashesSHA256.put(file, String.format("%064x", new BigInteger(1, digestSHA256.digest()))); + fileHashesMD5.put(file, String.format("%032x", new BigInteger(1, digestMD5.digest())).toLowerCase()); + fileHashesSHA1.put(file, String.format("%032x", new BigInteger(1, digestSHA1.digest())).toLowerCase()); + fileHashesSHA256.put(file, String.format("%064x", new BigInteger(1, digestSHA256.digest())).toLowerCase()); } catch (Exception e) { e.printStackTrace(); } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7c25794..634f33f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -63,4 +63,8 @@ Skipping action, a scan is running! Database signing key No network connected! + Self test successful. + Self test failed! + Database is loading, not updating! + All databases updated! diff --git a/scripts/Main.java b/scripts/Main.java index 0c7064b..07336fd 100644 --- a/scripts/Main.java +++ b/scripts/Main.java @@ -55,7 +55,7 @@ public class Main { if (databaseLocation.getName().contains(".hdb")) {//.hdb format: md5, size, name while ((line = reader.readLine()) != null) { if (line.length() > 0) { - String[] lineS = line.trim().split(":"); + String[] lineS = line.trim().toLowerCase().split(":"); if (lineS[0].length() > 0) { if (signaturesMD5.put(lineS[0])) { amtSignaturesMD5++; @@ -67,7 +67,7 @@ public class Main { } else if (databaseLocation.getName().contains(".hsb")) {//.hsb format: sha256, size, name while ((line = reader.readLine()) != null) { if (line.length() > 0) { - String[] lineS = line.trim().split(":"); + String[] lineS = line.trim().toLowerCase().split(":"); if (lineS[0].length() == 32) { if (signaturesSHA1.put(lineS[0])) { amtSignaturesSHA1++; @@ -84,7 +84,7 @@ public class Main { } else if (databaseLocation.getName().contains(".md5")) {//one signature per line while ((line = reader.readLine()) != null) { if (line.length() > 0) { - if (signaturesMD5.put(line.trim())) { + if (signaturesMD5.put(line.trim().toLowerCase())) { amtSignaturesMD5++; } amtSignaturesRead++; @@ -93,7 +93,7 @@ public class Main { } else if (databaseLocation.getName().contains(".sha1")) {//one signature per line while ((line = reader.readLine()) != null) { if (line.length() > 0) { - if (signaturesSHA1.put(line.trim())) { + if (signaturesSHA1.put(line.trim().toLowerCase())) { amtSignaturesSHA1++; } amtSignaturesRead++; @@ -102,7 +102,7 @@ public class Main { } else if (databaseLocation.getName().contains(".sha256")) {//one signature per line while ((line = reader.readLine()) != null) { if (line.length() > 0) { - if (signaturesSHA256.put(line.trim())) { + if (signaturesSHA256.put(line.trim().toLowerCase())) { amtSignaturesSHA256++; } amtSignaturesRead++; @@ -118,6 +118,10 @@ public class Main { signaturesMD5.put("44d88612fea8a8f36de82e1278abb02f"); //Eicar test file signaturesSHA256.put("6a0b4866f143c32e651662cebf7f380d27b0db809db3b6a34cf34c7436ab6bbf"); //Hypatia test file + signaturesMD5.put("903616d0dbe074aa363d2d49c03f7362"); //Hypatia self-test canaries (echo -n "HypatiaHypatiaHypatia" | sum) + signaturesSHA1.put("fc4a3e802894cc2229be77ec6f082d1aab744e54"); + signaturesSHA256.put("df44844a0e99ddd935e8419257440a2ca7ef3243435a67416fcbb6cd3ae560c3"); + System.out.println("Total: " + amtSignaturesRead); System.out.println("Mismatch: " + (amtSignaturesRead-amtSignaturesMD5-amtSignaturesSHA1-amtSignaturesSHA256)); System.out.println("Loaded all databases - md5: " + amtSignaturesMD5 + ", sha1: " + amtSignaturesSHA1 + ", sha256: " + amtSignaturesSHA256);