mirror of
https://github.com/MaintainTeam/Hypatia.git
synced 2025-03-01 05:48:23 +03:00
Lots of refractoring
This commit is contained in:
parent
b8c68528f6
commit
4dfca28d22
6 changed files with 185 additions and 193 deletions
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
|
@ -24,7 +24,7 @@
|
|||
</value>
|
||||
</option>
|
||||
</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" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
android:configChanges="orientation|keyboardHidden">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
|
|
@ -2,6 +2,7 @@ package us.spotco.malwarescanner;
|
|||
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
|
@ -36,8 +37,12 @@ public class Database {
|
|||
//signatureDatabases.add(new SignatureDatabase("http://cdn.malware.expert/malware.expert.hdb", "malware.expert.hdb"));
|
||||
}
|
||||
|
||||
public static boolean doesDatabaseExist() {
|
||||
return databasePath.listFiles().length > 0;
|
||||
public static boolean isDatabaseLoaded() {
|
||||
return signaturesMD5.size() > 0 && signaturesSHA1.size() > 0 && signaturesSHA256.size() > 0;
|
||||
}
|
||||
|
||||
public static int getSignatureCount() {
|
||||
return signaturesMD5.size() + signaturesSHA1.size() + signaturesSHA256.size();
|
||||
}
|
||||
|
||||
public static void updateDatabase(ArrayList<SignatureDatabase> signatureDatabases) {
|
||||
|
@ -46,7 +51,9 @@ public class Database {
|
|||
}
|
||||
}
|
||||
|
||||
public static void loadDatabase(ArrayList<SignatureDatabase> signatureDatabases) {
|
||||
public static void loadDatabase(boolean ignoreifLoaded, ArrayList<SignatureDatabase> signatureDatabases) {
|
||||
if (!isDatabaseLoaded() || !ignoreifLoaded && isDatabaseLoaded()) {
|
||||
Log.d("Theia", "Loading database");
|
||||
signaturesMD5.clear();
|
||||
signaturesSHA1.clear();
|
||||
signaturesSHA256.clear();
|
||||
|
@ -87,6 +94,7 @@ public class Database {
|
|||
}
|
||||
System.gc();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Downloader extends AsyncTask<String, String, String> {
|
||||
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package us.spotco.malwarescanner;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
|
@ -16,6 +18,10 @@ import android.view.View;
|
|||
import android.view.WindowManager;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
private boolean scanSystem = false;
|
||||
|
@ -42,16 +48,31 @@ public class MainActivity extends AppCompatActivity {
|
|||
logView.append("\nDisclaimer: This is an extremely basic signature scanner\n\n");
|
||||
|
||||
final Database database = new Database(this, logView);
|
||||
final MalwareScanner scanner = new MalwareScanner(this, logView);
|
||||
final MalwareScanner malwareScanner = new MalwareScanner(this, this, true);
|
||||
|
||||
FloatingActionButton fab = findViewById(R.id.fab);
|
||||
fab.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (!scanner.isScannerRunning()) {
|
||||
MalwareScanner.startScanner(scanSystem, scanApps, scanInternal, scanExternal);
|
||||
if (!malwareScanner.getStatus().equals(AsyncTask.Status.RUNNING)) {
|
||||
Set<File> filesToScan = new HashSet<>();
|
||||
if (scanSystem) {
|
||||
filesToScan.addAll(Utils.getFilesRecursive(Environment.getRootDirectory()));
|
||||
}
|
||||
if (scanApps) {
|
||||
for (ApplicationInfo packageInfo : getPackageManager().getInstalledApplications(PackageManager.GET_META_DATA)) {
|
||||
filesToScan.add(new File(packageInfo.sourceDir));
|
||||
}
|
||||
}
|
||||
if (scanInternal) {
|
||||
filesToScan.addAll(Utils.getFilesRecursive(Environment.getExternalStorageDirectory()));
|
||||
}
|
||||
if (scanExternal) {
|
||||
filesToScan.addAll(Utils.getFilesRecursive(new File("/storage")));
|
||||
}
|
||||
malwareScanner.execute(filesToScan);
|
||||
} else {
|
||||
scanner.stopScanner();
|
||||
malwareScanner.cancel(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -67,7 +88,7 @@ public class MainActivity extends AppCompatActivity {
|
|||
|
||||
private void requestPermissions() {
|
||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||
ActivityCompat.requestPermissions(this, new String[]{ Manifest.permission.READ_EXTERNAL_STORAGE }, REQUEST_PERMISSION_EXTERNAL_STORAGE);
|
||||
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_PERMISSION_EXTERNAL_STORAGE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,6 +97,9 @@ public class MainActivity extends AppCompatActivity {
|
|||
switch (item.getItemId()) {
|
||||
case R.id.mnuUpdateDatabase:
|
||||
Database.updateDatabase(Database.signatureDatabases);
|
||||
if (Database.isDatabaseLoaded()) {
|
||||
Database.loadDatabase(false, Database.signatureDatabases);
|
||||
}
|
||||
break;
|
||||
case R.id.mnuScanSystem:
|
||||
scanSystem = !item.isChecked();
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package us.spotco.malwarescanner;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Environment;
|
||||
import android.os.SystemClock;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -14,173 +14,102 @@ import java.io.InputStream;
|
|||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class MalwareScanner {
|
||||
public class MalwareScanner extends AsyncTask<Set<File>, Object, String> {
|
||||
|
||||
private static Context context = null;
|
||||
private static TextView log = null;
|
||||
private static AsyncTask<Boolean, String, String> malwareScannerTask = null;
|
||||
private Context context = null;
|
||||
private TextView logOutput = null;
|
||||
private boolean userFacing = false;
|
||||
private NotificationManager notificationManager = null;
|
||||
private long scanTime = 0;
|
||||
private HashMap<String, File> fileHashesMD5 = new HashMap<>();
|
||||
private HashMap<String, File> fileHashesSHA1 = new HashMap<>();
|
||||
private HashMap<String, File> fileHashesSHA256 = new HashMap<>();
|
||||
|
||||
private static final int MAX_FILE_SIZE = (1000 * 1000) * 50; //50MB
|
||||
private static long scanTime = 0;
|
||||
|
||||
private static HashMap<String, File> fileHashesMD5 = new HashMap<>();
|
||||
private static HashMap<String, File> fileHashesSHA1 = new HashMap<>();
|
||||
private static HashMap<String, File> fileHashesSHA256 = new HashMap<>();
|
||||
|
||||
public MalwareScanner(Context context, TextView log) {
|
||||
MalwareScanner.context = context;
|
||||
MalwareScanner.log = log;
|
||||
}
|
||||
|
||||
public static void startScanner(boolean scanSystem, boolean scanApps, boolean scanInternal, boolean scanExternal) {
|
||||
if (Database.doesDatabaseExist()) {
|
||||
malwareScannerTask = new MalwareScannerTask().execute(scanSystem, scanApps, scanInternal, scanExternal);
|
||||
public MalwareScanner(Activity activity, Context context, boolean userFacing) {
|
||||
this.context = context;
|
||||
this.userFacing = userFacing;
|
||||
if (activity != null) {
|
||||
logOutput = activity.findViewById(R.id.txtLogOutput);
|
||||
} else {
|
||||
log.append("No database found... download one first!\n");
|
||||
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
}
|
||||
}
|
||||
|
||||
public void stopScanner() {
|
||||
malwareScannerTask.cancel(true);
|
||||
private void logResult(String result, boolean userFacingOnly) {
|
||||
if (userFacing) {
|
||||
logOutput.append(result + "\n");
|
||||
} else if (!userFacingOnly) {
|
||||
NotificationCompat.Builder mBuilder =
|
||||
new NotificationCompat.Builder(context)
|
||||
.setSmallIcon(R.drawable.ic_launcher_foreground)
|
||||
.setContentTitle("Malware Detected!")
|
||||
.setContentText(result);
|
||||
notificationManager.notify(1, mBuilder.build());
|
||||
}
|
||||
|
||||
public boolean isScannerRunning() {
|
||||
return malwareScannerTask != null && (malwareScannerTask.getStatus().equals(AsyncTask.Status.PENDING) || malwareScannerTask.getStatus().equals(AsyncTask.Status.RUNNING));
|
||||
}
|
||||
|
||||
public static class MalwareScannerTask extends AsyncTask<Boolean, String, String> {
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
scanTime = SystemClock.elapsedRealtime();
|
||||
log.append("Initiating scan...\n");
|
||||
logResult("Starting scan...", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doInBackground(Set<File>[] filesToScan) {
|
||||
//Pre
|
||||
fileHashesMD5.clear();
|
||||
fileHashesSHA1.clear();
|
||||
fileHashesSHA256.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCancelled() {
|
||||
log.append("Scan cancelled\n");
|
||||
}
|
||||
publishProgress(filesToScan[0].size() + " files pending scan\n", true);
|
||||
|
||||
@Override
|
||||
protected String doInBackground(Boolean... booleans) {
|
||||
boolean scanSystem = booleans[0];
|
||||
boolean scanApps = booleans[1];
|
||||
boolean scanInternal = booleans[2];
|
||||
boolean scanExternal = booleans[3];
|
||||
Database.loadDatabase(true, Database.signatureDatabases);
|
||||
publishProgress("Loaded database with " + Database.getSignatureCount() + " signatures\n", true);
|
||||
|
||||
Set<File> filesToScan = new HashSet<>();
|
||||
|
||||
if (scanSystem) {
|
||||
filesToScan.addAll(getFilesRecursive(Environment.getRootDirectory()));
|
||||
}
|
||||
if (scanApps) {
|
||||
for (ApplicationInfo packageInfo : context.getPackageManager().getInstalledApplications(PackageManager.GET_META_DATA)) {
|
||||
filesToScan.add(new File(packageInfo.sourceDir));
|
||||
}
|
||||
}
|
||||
if (scanInternal) {
|
||||
filesToScan.addAll(getFilesRecursive(Environment.getExternalStorageDirectory()));
|
||||
}
|
||||
if (scanExternal) {
|
||||
filesToScan.addAll(getFilesRecursive(new File("/storage")));
|
||||
}
|
||||
publishProgress(filesToScan.size() + " files pending scan\n");
|
||||
|
||||
Database.loadDatabase(Database.signatureDatabases);
|
||||
publishProgress("Loaded " + Database.signaturesMD5.size() + " MD5 signatures");
|
||||
publishProgress("Loaded " + Database.signaturesSHA1.size() + " SHA-1 signatures");
|
||||
publishProgress("Loaded " + Database.signaturesSHA256.size() + " SHA-256 signatures\n");
|
||||
|
||||
publishProgress("Hashing files...");
|
||||
for (File file : filesToScan) {
|
||||
//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");
|
||||
publishProgress("Calculated MD5/SHA-1/SHA-256 hashes for all files\n", true);
|
||||
|
||||
if (Database.signaturesMD5.size() > 0) {
|
||||
|
||||
for (Map.Entry<String, File> file : fileHashesMD5.entrySet()) {
|
||||
if (Database.signaturesMD5.containsKey(file.getKey())) {
|
||||
String result = Database.signaturesMD5.get(file.getKey());
|
||||
publishProgress(file.getValue() + " detected as " + result);
|
||||
}
|
||||
}
|
||||
publishProgress("Checked all MD5 hashes against signature databases\n");
|
||||
} else {
|
||||
publishProgress("No MD5 signatures available\n");
|
||||
}
|
||||
|
||||
if (Database.signaturesSHA1.size() > 0) {
|
||||
for (Map.Entry<String, File> file : fileHashesSHA1.entrySet()) {
|
||||
if (Database.signaturesSHA1.containsKey(file.getKey())) {
|
||||
String result = Database.signaturesSHA1.get(file.getKey());
|
||||
publishProgress(file.getValue() + " detected as " + result);
|
||||
}
|
||||
}
|
||||
publishProgress("Checked all SHA-1 hashes against signature databases\n");
|
||||
} else {
|
||||
publishProgress("No SHA-1 signatures available\n");
|
||||
}
|
||||
|
||||
if (Database.signaturesSHA256.size() > 0) {
|
||||
for (Map.Entry<String, File> file : fileHashesSHA256.entrySet()) {
|
||||
if (Database.signaturesSHA256.containsKey(file.getKey())) {
|
||||
String result = Database.signaturesSHA256.get(file.getKey());
|
||||
publishProgress(file.getValue() + " detected as " + result);
|
||||
}
|
||||
}
|
||||
publishProgress("Checked all SHA-256 hashes against signature databases\n");
|
||||
} else {
|
||||
publishProgress("No SHA-256 signatures available\n");
|
||||
}
|
||||
//Check the hashes
|
||||
checkSignature("MD5", fileHashesMD5, Database.signaturesMD5);
|
||||
checkSignature("SHA-1", fileHashesSHA1, Database.signaturesSHA1);
|
||||
checkSignature("SHA-256", fileHashesSHA256, Database.signaturesSHA256);
|
||||
|
||||
//Post
|
||||
fileHashesMD5.clear();
|
||||
fileHashesSHA1.clear();
|
||||
fileHashesSHA256.clear();
|
||||
System.gc();
|
||||
|
||||
publishProgress("Scan completed in " + ((SystemClock.elapsedRealtime() - scanTime) / 1000) + " seconds!\n\n\n\n", true);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onProgressUpdate(String... progress) {
|
||||
log.append(progress[0] + "\n");
|
||||
protected void onProgressUpdate(Object... objects) {
|
||||
logResult((String) objects[0], (boolean) objects[1]);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(String result) {
|
||||
log.append("Scan completed in " + ((SystemClock.elapsedRealtime() - scanTime) / 1000) + " seconds!\n\n\n\n\n");
|
||||
private void checkSignature(String hashType, HashMap<String, File> signaturesToCheck, HashMap<String, String> signatureDatabase) {
|
||||
if (signatureDatabase.size() > 0) {
|
||||
for (Map.Entry<String, File> file : signaturesToCheck.entrySet()) {
|
||||
if (signatureDatabase.containsKey(file.getKey())) {
|
||||
String result = signatureDatabase.get(file.getKey());
|
||||
publishProgress(result + " in " + file.getValue(), false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static Set<File> getFilesRecursive(File root) {
|
||||
Set<File> filesAll = new HashSet<>();
|
||||
|
||||
File[] files = root.listFiles();
|
||||
if (files != null && files.length > 0) {
|
||||
for (File f : files) {
|
||||
if (f.isDirectory()) {
|
||||
Set<File> filesTmp = getFilesRecursive(f);
|
||||
if (filesTmp != null) {
|
||||
filesAll.addAll(filesTmp);
|
||||
}
|
||||
publishProgress("Checked all " + hashType + " hashes against signature databases\n", true);
|
||||
} else {
|
||||
if(f.length() <= MAX_FILE_SIZE) {//Exclude files larger than 50MB for performance
|
||||
filesAll.add(f);
|
||||
}
|
||||
}
|
||||
publishProgress("No " + hashType + " signatures available\n", true);
|
||||
}
|
||||
}
|
||||
|
||||
return filesAll;
|
||||
}
|
||||
|
||||
private static void getFileHashes(File file) {
|
||||
private void getFileHashes(File file) {
|
||||
try {
|
||||
InputStream fis = new FileInputStream(file);
|
||||
|
||||
|
|
32
app/src/main/java/us/spotco/malwarescanner/Utils.java
Normal file
32
app/src/main/java/us/spotco/malwarescanner/Utils.java
Normal file
|
@ -0,0 +1,32 @@
|
|||
package us.spotco.malwarescanner;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class Utils {
|
||||
|
||||
private static final int MAX_FILE_SIZE = (1000 * 1000) * 50; //50MB
|
||||
|
||||
public static Set<File> getFilesRecursive(File root) {
|
||||
Set<File> filesAll = new HashSet<>();
|
||||
|
||||
File[] files = root.listFiles();
|
||||
if (files != null && files.length > 0) {
|
||||
for (File f : files) {
|
||||
if (f.isDirectory()) {
|
||||
Set<File> filesTmp = getFilesRecursive(f);
|
||||
if (filesTmp != null) {
|
||||
filesAll.addAll(filesTmp);
|
||||
}
|
||||
} else {
|
||||
if (f.length() <= MAX_FILE_SIZE) {//Exclude files larger than 50MB for performance
|
||||
filesAll.add(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return filesAll;
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue