Scanning and refractoring to support multiple databases

This commit is contained in:
Tad 2017-12-14 14:18:49 -05:00
parent 9512e736ba
commit cbc8c1e64a
6 changed files with 112 additions and 28 deletions

2
.idea/misc.xml generated
View file

@ -24,7 +24,7 @@
</value> </value>
</option> </option>
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="JDK" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" project-jdk-name="JDK" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" /> <output url="file://$PROJECT_DIR$/build/classes" />
</component> </component>
<component name="ProjectType"> <component name="ProjectType">

View file

@ -6,43 +6,82 @@ import android.view.MenuItem;
import android.widget.TextView; import android.widget.TextView;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;
public class Database { public class Database {
private static Context context = null; private static Context context = null;
private static TextView log = null; private static TextView log = null;
private static MenuItem databaseUpdateCheckOption = null;
private static File databasePath = null; private static File databasePath = null;
private static String databaseName = "clamav-main.hsb";
private static final String databaseUpdateURL = "https://spotco.us/clamav-main.hsb";
public Database(Context context, TextView log, MenuItem databaseUpdateCheckOption) { private static HashMap<String, String> signaturesMD5 = new HashMap<String, String>();
private static HashMap<String, String> signaturesSHA256 = new HashMap<String, String>();
public Database(Context context, TextView log) {
this.context = context; this.context = context;
this.log = log; this.log = log;
this.databaseUpdateCheckOption = databaseUpdateCheckOption; this.databasePath = new File(context.getFilesDir() + "signatures/");
databasePath = new File(context.getFilesDir() + databaseName);
} }
public static boolean doesDatabaseExist() { public static boolean doesDatabaseExist() {
return databasePath.exists(); return databasePath.listFiles().length > 0;
} }
public static boolean shouldUpdateDatabase() { public static void updateDatabase(ArrayList<SignatureDatabase> signatureDatabases) {
return databaseUpdateCheckOption.isChecked(); for(SignatureDatabase signatureDatabase : signatureDatabases) {
new Downloader().execute(signatureDatabase.getUrl(), context.getFilesDir() + signatureDatabase.getName());
}
} }
public static void updateDatabase() { public static void loadDatabase(ArrayList<SignatureDatabase> signatureDatabases) {
new Downloader().execute(databaseUpdateURL, databasePath.toString()); for(SignatureDatabase database : signatureDatabases) {
} File databaseLocation = new File(databasePath + database.getName());
if(!databaseLocation.exists()) {
public static void loadDatabase() { log.append("Database " + database.getName() + " doesn't exist!\n");
//Database format: md5, size, name, unknown } else {
if (database.getName().contains(".hdb")) {//.hdb format: md5, size, name
try {
Scanner scanner = new Scanner(databaseLocation);
while(scanner.hasNextLine()) {
String[] line = scanner.nextLine().split(":");
signaturesMD5.put(line[0], line[2]);
}
scanner.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
} else if (database.getName().contains(".hsb")) {//.hsb format: sha256, size, name
try {
Scanner scanner = new Scanner(databaseLocation);
while(scanner.hasNextLine()) {
String[] line = scanner.nextLine().split(":");
signaturesSHA256.put(line[0], line[2]);
}
scanner.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
}
} }
public static String checkInDatabase(String hash) { public static String checkInDatabase(String hash) {
if(hash.length() == 32) {
if (signaturesMD5.containsKey(hash)) {
return signaturesMD5.get(hash);
}
} else if(hash.length() == 64) {
if (signaturesSHA256.containsKey(hash)) {
return signaturesSHA256.get(hash);
}
}
return null; return null;
} }

View file

@ -32,9 +32,7 @@ public class MainActivity extends AppCompatActivity {
logView.append("Powered by ClamAV signatures, License: GPLv3\n"); logView.append("Powered by ClamAV signatures, License: GPLv3\n");
logView.append("\nDisclaimer: This is an extremely basic signature scanner\n\n"); logView.append("\nDisclaimer: This is an extremely basic signature scanner\n\n");
MenuItem databaseUpdateCheckOption = findViewById(R.id.mnuUpdateDatabase); final Database database = new Database(this, logView);
final Database database = new Database(this, logView, databaseUpdateCheckOption);
final MalwareScanner scanner = new MalwareScanner(this, logView); final MalwareScanner scanner = new MalwareScanner(this, logView);
FloatingActionButton fab = findViewById(R.id.fab); FloatingActionButton fab = findViewById(R.id.fab);

View file

@ -12,7 +12,9 @@ import com.google.common.io.Files;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
import java.util.Set; import java.util.Set;
public class MalwareScanner { public class MalwareScanner {
@ -30,8 +32,7 @@ public class MalwareScanner {
if(Database.doesDatabaseExist()) { if(Database.doesDatabaseExist()) {
malwareScannerTask = new MalwareScannerTask().execute(scanSystem, scanApps, scanInternal, scanExternal); malwareScannerTask = new MalwareScannerTask().execute(scanSystem, scanApps, scanInternal, scanExternal);
} else { } else {
log.append("No database found... downloading!\n"); log.append("No database found... download one first!\n");
Database.updateDatabase();
} }
} }
@ -83,8 +84,29 @@ public class MalwareScanner {
} }
publishProgress(filesToScan.size() + " files pending scan"); publishProgress(filesToScan.size() + " files pending scan");
//TODO: Hash the files HashMap<String, File> fileHashesMD5 = new HashMap<String, File>();
//TODO: Check the status of the files HashMap<String, File> fileHashesSHA256 = new HashMap<String, File>();
for(File file : filesToScan) {
fileHashesMD5.put(getFileMD5Sum(file), file);
fileHashesSHA256.put(getFileSHA256Sum(file), file);
}
publishProgress("Calculated MD5 and SHA256 hashes for all files");
for(Map.Entry<String, File> file : fileHashesMD5.entrySet()) {
String result = Database.checkInDatabase(file.getKey());
if(result != null) {
publishProgress(file.getValue() + " detected as " + result);
}
}
publishProgress("Checked all MD5 hashes against signature databases");
for(Map.Entry<String, File> file : fileHashesSHA256.entrySet()) {
String result = Database.checkInDatabase(file.getKey());
if(result != null) {
publishProgress(file.getValue() + " detected as " + result);
}
}
publishProgress("Checked all SHA256 hashes against signature databases");
return null; return null;
} }
@ -129,4 +151,13 @@ public class MalwareScanner {
return null; return null;
} }
private String getFileSHA256Sum(File file) {
try {
return Files.asByteSource(file).hash(Hashing.sha256()).toString();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
} }

View file

@ -0,0 +1,21 @@
package us.spotco.malwarescanner;
public class SignatureDatabase {
private String url = null;
private String name = null;
public SignatureDatabase(String url, String name) {
this.url = url;
this.name = name;
}
public String getUrl() {
return url;
}
public String getName() {
return name;
}
}

View file

@ -3,11 +3,6 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context="us.spotco.malwarescanner.MainActivity"> tools:context="us.spotco.malwarescanner.MainActivity">
<item
android:id="@+id/mnuUpdateDatabase"
android:title="@string/lblUpdateDatabase"
android:checkable="true"
android:checked="true" />
<item <item
android:id="@+id/mnuScanSystem" android:id="@+id/mnuScanSystem"
android:title="@string/lblScanSystem" android:title="@string/lblScanSystem"