From c40ff53cb0de8ff930171c5008958afc2db6e4bd Mon Sep 17 00:00:00 2001 From: Tad Date: Sun, 21 Oct 2018 23:00:39 -0400 Subject: [PATCH] Add the malware scanner task --- .../malwarescanner/DatabaseManager.java | 8 +- .../spotco/malwarescanner/MalwareScanner.java | 127 +++++++++++++++++- .../java/us/spotco/malwarescanner/Utils.java | 1 + 3 files changed, 130 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/us/spotco/malwarescanner/DatabaseManager.java b/app/src/main/java/us/spotco/malwarescanner/DatabaseManager.java index 76c7267..d9eadbe 100644 --- a/app/src/main/java/us/spotco/malwarescanner/DatabaseManager.java +++ b/app/src/main/java/us/spotco/malwarescanner/DatabaseManager.java @@ -54,7 +54,7 @@ public class DatabaseManager { new File(databasePath + "/" + name).delete(); } - public void loadRemoteDatabases() { + public static void loadRemoteDatabases() { try { signatureDatabases.clear(); String api = Utils.prefs.getString("database_repo", "https://spotco.us/MalwareScannerSignatures/api.php"); @@ -78,7 +78,7 @@ public class DatabaseManager { } } - public void updateDatabases() { + public static void updateDatabases() { loadRemoteDatabases(); for (Signatures.SignatureDatabase db : signatureDatabases) { if (db.isAvailable()) { @@ -88,7 +88,7 @@ public class DatabaseManager { loadAllAvailableDatabases(true); } - public void loadAllAvailableDatabases(boolean forceReload) { + public static void loadAllAvailableDatabases(boolean forceReload) { if (!Signatures.available() || forceReload) { Signatures.clear(); for (Signatures.SignatureDatabase db : signatureDatabases) { @@ -102,7 +102,7 @@ public class DatabaseManager { } } - private void loadDatabase(File database) { + private static void loadDatabase(File database) { try { if (database.exists()) { BufferedReader reader; diff --git a/app/src/main/java/us/spotco/malwarescanner/MalwareScanner.java b/app/src/main/java/us/spotco/malwarescanner/MalwareScanner.java index 346ecbc..2537a42 100644 --- a/app/src/main/java/us/spotco/malwarescanner/MalwareScanner.java +++ b/app/src/main/java/us/spotco/malwarescanner/MalwareScanner.java @@ -17,5 +17,128 @@ along with this program. If not, see . */ package us.spotco.malwarescanner; -public class MalwareScanner { -} +import android.os.AsyncTask; +import android.os.Environment; +import android.os.SystemClock; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +class MalwareScanner extends AsyncTask, Object, String> { + + private boolean userFacing = false; + private long scanTime = 0; + private int hashMaxLength = 0; + private final HashMap fileHashesMD5 = new HashMap<>(); + private final HashMap fileHashesSHA1 = new HashMap<>(); + private final HashMap fileHashesSHA256 = new HashMap<>(); + + public MalwareScanner(boolean userFacing) { + this.userFacing = userFacing; + hashMaxLength = Utils.prefs.getInt("database_hash_length", 12); + } + + private void returnResult(String result, boolean userFacingOnly) { + //TODO HANDLE STATUS UPDATES + } + + @Override + protected final void onPreExecute() { + scanTime = SystemClock.elapsedRealtime(); + returnResult("Starting scan...", true); + } + + @Override + protected final String doInBackground(Set[] filesToScan) { + //Pre + fileHashesMD5.clear(); + fileHashesSHA1.clear(); + fileHashesSHA256.clear(); + + publishProgress(filesToScan[0].size() + " files pending scan\n", true); + + DatabaseManager.loadAllAvailableDatabases(false); + if (Signatures.getSignatureCount() >= 0) { + publishProgress("Loaded database with " + Signatures.getSignatureCount() + " signatures\n", true); + + //Get file hashes + publishProgress("Hashing files...", true); + for (File file : filesToScan[0]) { + getFileHashes(file); + } + publishProgress("Calculated MD5/SHA-1/SHA-256 hashes for all files\n", true); + + //Check the hashes + checkSignature("MD5", fileHashesMD5, Signatures.MD5); + checkSignature("SHA-1", fileHashesSHA1, Signatures.SHA1); + checkSignature("SHA-256", fileHashesSHA256, Signatures.SHA256); + + //Post + fileHashesMD5.clear(); + fileHashesSHA1.clear(); + fileHashesSHA256.clear(); + System.gc(); + Utils.amtFilesScanned += filesToScan[0].size(); + publishProgress("Scan completed in " + ((SystemClock.elapsedRealtime() - scanTime) / 1000) + " seconds!\n\n\n\n", true); + } else { + publishProgress("No database available, not scanning...", true); + } + return null; + } + + @Override + protected final void onProgressUpdate(Object... objects) { + returnResult((String) objects[0], (boolean) objects[1]); + } + + private void checkSignature(String hashType, HashMap signaturesToCheck, HashMap signatureDatabase) { + if (signatureDatabase.size() > 0) { + for (Map.Entry file : signaturesToCheck.entrySet()) { + if (signatureDatabase.containsKey(file.getKey())) { + String result = signatureDatabase.get(file.getKey()); + publishProgress(result + " in " + file.getValue().toString().replaceAll(Environment.getExternalStorageDirectory().toString(), "~"), false); + } + } + publishProgress("Checked all " + hashType + " hashes against signature databases\n", true); + } else { + publishProgress("No " + hashType + " signatures available\n", true); + } + } + + private void getFileHashes(File file) { + try { + InputStream fis = new FileInputStream(file); + + byte[] buffer = new byte[4096]; + int numRead; + + MessageDigest digestMD5 = MessageDigest.getInstance("MD5"); + MessageDigest digestSHA1 = MessageDigest.getInstance("SHA-1"); + MessageDigest digestSHA256 = MessageDigest.getInstance("SHA-256"); + + do { + numRead = fis.read(buffer); + if (numRead > 0) { + digestMD5.update(buffer, 0, numRead); + digestSHA1.update(buffer, 0, numRead); + digestSHA256.update(buffer, 0, numRead); + } + } while (numRead != -1); + + fis.close(); + + fileHashesMD5.put(String.format("%032x", new BigInteger(1, digestMD5.digest())).substring(0, hashMaxLength), file); + fileHashesSHA1.put(String.format("%032x", new BigInteger(1, digestSHA1.digest())).substring(0, hashMaxLength), file); + fileHashesSHA256.put(String.format("%064x", new BigInteger(1, digestSHA256.digest())).substring(0, hashMaxLength), file); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/us/spotco/malwarescanner/Utils.java b/app/src/main/java/us/spotco/malwarescanner/Utils.java index a168adb..608d63c 100644 --- a/app/src/main/java/us/spotco/malwarescanner/Utils.java +++ b/app/src/main/java/us/spotco/malwarescanner/Utils.java @@ -36,6 +36,7 @@ import java.util.concurrent.ThreadPoolExecutor; public class Utils { + public static int amtFilesScanned = 0; public static SharedPreferences prefs = null; public Utils(Context context) {