diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/MainViewerGUI.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/MainViewerGUI.java
index d6e59e4e..78fd6ead 100644
--- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/MainViewerGUI.java
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/MainViewerGUI.java
@@ -13,6 +13,7 @@ import the.bytecode.club.bytecodeviewer.*;
import the.bytecode.club.bytecodeviewer.api.ExceptionUI;
import the.bytecode.club.bytecodeviewer.gui.components.*;
import the.bytecode.club.bytecodeviewer.gui.plugins.MaliciousCodeScannerOptions;
+import the.bytecode.club.bytecodeviewer.gui.plugins.MaliciousCodeScannerOptionsV2;
import the.bytecode.club.bytecodeviewer.gui.plugins.ReplaceStringsOptions;
import the.bytecode.club.bytecodeviewer.gui.resourcelist.ResourceListPane;
import the.bytecode.club.bytecodeviewer.gui.resourcesearch.SearchBoxPane;
@@ -566,7 +567,7 @@ public class MainViewerGUI extends JFrame
openExternalPlugin.addActionListener(arg0 -> openExternalPlugin());
codeSequenceDiagram.addActionListener(arg0 -> CodeSequenceDiagram.open());
- maliciousCodeScanner.addActionListener(e -> MaliciousCodeScannerOptions.open());
+ maliciousCodeScanner.addActionListener(e -> MaliciousCodeScannerOptionsV2.open());
showMainMethods.addActionListener(e -> PluginManager.runPlugin(new ShowMainMethods()));
showAllStrings.addActionListener(e -> PluginManager.runPlugin(new ShowAllStrings()));
replaceStrings.addActionListener(arg0 -> ReplaceStringsOptions.open());
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/plugins/MaliciousCodeScannerOptions.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/plugins/MaliciousCodeScannerOptions.java
index 84689871..071f4bf8 100644
--- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/plugins/MaliciousCodeScannerOptions.java
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/plugins/MaliciousCodeScannerOptions.java
@@ -104,7 +104,7 @@ public class MaliciousCodeScannerOptions extends JFrame
getContentPane().add(chckbxJavaawtrobot);
JButton btnNewButton = new JButton("Start Scanning");
- btnNewButton.addActionListener(arg0 -> {
+ /*btnNewButton.addActionListener(arg0 -> {
PluginManager.runPlugin(new MaliciousCodeScanner(
chckbxJavalangreflection.isSelected(),
chckbxJavalangruntime.isSelected(),
@@ -117,7 +117,7 @@ public class MaliciousCodeScannerOptions extends JFrame
chckbxNullSecMan.isSelected(),
chckbxJavaawtrobot.isSelected()));
dispose();
- });
+ });*/
btnNewButton.setBounds(6, 264, 232, 23);
getContentPane().add(btnNewButton);
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/plugins/MaliciousCodeScannerOptionsV2.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/plugins/MaliciousCodeScannerOptionsV2.java
new file mode 100644
index 00000000..ab3b4a6e
--- /dev/null
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/plugins/MaliciousCodeScannerOptionsV2.java
@@ -0,0 +1,106 @@
+package the.bytecode.club.bytecodeviewer.gui.plugins;
+
+import the.bytecode.club.bytecodeviewer.BytecodeViewer;
+import the.bytecode.club.bytecodeviewer.Resources;
+import the.bytecode.club.bytecodeviewer.malwarescanner.MalwareScanModule;
+import the.bytecode.club.bytecodeviewer.plugin.PluginManager;
+import the.bytecode.club.bytecodeviewer.plugin.preinstalled.MaliciousCodeScanner;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.ArrayList;
+
+/***************************************************************************
+ * Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
+ * Copyright (C) 2014 Kalen 'Konloch' Kinloch - http://bytecodeviewer.com *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program. If not, see . *
+ ***************************************************************************/
+
+/**
+ * This GUI automatically populates the scan options from the MalwareScanModule enum.
+ *
+ * @author Konloch
+ */
+
+public class MaliciousCodeScannerOptionsV2 extends JFrame
+{
+ private static final int SPACER_HEIGHT_BETWEEN_OPTIONS = 26;
+
+ public static void open()
+ {
+ if (BytecodeViewer.getLoadedClasses().isEmpty())
+ {
+ BytecodeViewer.showMessage("First open a class, jar, zip, apk or dex file.");
+ return;
+ }
+
+ new MaliciousCodeScannerOptionsV2().setVisible(true);
+ }
+
+ public MaliciousCodeScannerOptionsV2()
+ {
+ this.setIconImages(Resources.iconList);
+ setSize(new Dimension(250, 7+(MalwareScanModule.values().length * SPACER_HEIGHT_BETWEEN_OPTIONS)+90));
+ setResizable(false);
+ setTitle("Malicious Code Scanner Options");
+ getContentPane().setLayout(null);
+ ArrayList checkBoxes = new ArrayList<>();
+
+ int y = 7;
+ for(MalwareScanModule module : MalwareScanModule.values())
+ {
+ final JCheckBox checkBox = new JCheckBox(module.getReadableName());
+ checkBox.setSelected(module.isToggledByDefault()); //TODO
+ checkBox.setBounds(6, y, 232, 23);
+ getContentPane().add(checkBox);
+ checkBoxes.add(new MaliciousCodeOptions(module, checkBox));
+
+ y += SPACER_HEIGHT_BETWEEN_OPTIONS;
+ }
+
+ JButton btnNewButton = new JButton("Start Scanning");
+ btnNewButton.addActionListener(arg0 -> {
+ PluginManager.runPlugin(new MaliciousCodeScanner(checkBoxes));
+ dispose();
+ });
+
+ btnNewButton.setBounds(6, y, 232, 23);
+ getContentPane().add(btnNewButton);
+ this.setLocationRelativeTo(null);
+ }
+
+ private static final long serialVersionUID = -2662514582647810868L;
+
+ public static class MaliciousCodeOptions
+ {
+ private final MalwareScanModule module;
+ private final JCheckBox checkBox;
+
+ public MaliciousCodeOptions(MalwareScanModule module, JCheckBox checkBox) {
+ this.module = module;
+ this.checkBox = checkBox;
+ }
+
+ public JCheckBox getCheckBox()
+ {
+ return checkBox;
+ }
+
+ public MalwareScanModule getModule()
+ {
+ return module;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/CodeScanner.java b/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/CodeScanner.java
new file mode 100644
index 00000000..5a3b2654
--- /dev/null
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/CodeScanner.java
@@ -0,0 +1,19 @@
+package the.bytecode.club.bytecodeviewer.malwarescanner;
+
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.FieldNode;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * @author Konloch
+ * @since 6/27/2021
+ */
+
+public interface CodeScanner
+{
+ void scanningClass(MalwareScan scan, ClassNode cn);
+
+ void scanFields(MalwareScan scan, ClassNode cn, FieldNode[] fields);
+
+ void scanMethods(MalwareScan scan, ClassNode cn, MethodNode[] methods);
+}
\ No newline at end of file
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/MalwareCodeScanner.java b/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/MalwareCodeScanner.java
new file mode 100644
index 00000000..39fb1b50
--- /dev/null
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/MalwareCodeScanner.java
@@ -0,0 +1,93 @@
+package the.bytecode.club.bytecodeviewer.malwarescanner;
+
+import org.objectweb.asm.tree.*;
+import the.bytecode.club.bytecodeviewer.malwarescanner.util.SearchableString;
+
+/**
+ * The base class for the malware code scanners
+ *
+ * @author Konloch
+ * @since 6/27/2021
+ */
+public abstract class MalwareCodeScanner implements CodeScanner
+{
+ public abstract void scanFieldString(MalwareScan scan, ClassNode cn, FieldNode field, SearchableString string);
+
+ public abstract void scanMethodString(MalwareScan scan, ClassNode cn, MethodNode method, SearchableString string);
+
+ public abstract void scanMethodInstruction(MalwareScan scan, ClassNode cn, MethodNode method, AbstractInsnNode instruction);
+
+ @Override
+ public void scanningClass(MalwareScan scan, ClassNode cn)
+ {
+ scanFields(scan, cn, cn.fields.toArray(new FieldNode[0]));
+ scanMethods(scan, cn, cn.methods.toArray(new MethodNode[0]));
+ }
+
+ @Override
+ public void scanFields(MalwareScan scan, ClassNode cn, FieldNode[] fields)
+ {
+ for (FieldNode field : fields)
+ {
+ Object fieldValue = field.value;
+
+ //scan strings
+ if (fieldValue instanceof String)
+ scanFieldString(scan, cn, field, new SearchableString((String) fieldValue));
+
+ //scan string array
+ else if (fieldValue instanceof String[])
+ for(String s : (String[]) fieldValue)
+ scanFieldString(scan, cn, field, new SearchableString(s));
+ }
+ }
+
+ @Override
+ public void scanMethods(MalwareScan scan, ClassNode cn, MethodNode[] methods)
+ {
+ for (MethodNode method : methods)
+ {
+ InsnList instructionList = method.instructions;
+
+ //scan each instruction
+ for (AbstractInsnNode instruction : instructionList.toArray())
+ {
+ scanMethodInstruction(scan, cn, method, instruction);
+
+ if (instruction instanceof LdcInsnNode)
+ {
+ if (((LdcInsnNode) instruction).cst instanceof String)
+ {
+ final String string = (String) ((LdcInsnNode) instruction).cst;
+ scanMethodString(scan, cn, method, new SearchableString(string));
+ }
+ }
+ }
+ }
+ }
+
+ public String fieldToString(ClassNode cn, FieldNode field)
+ {
+ return cn.name + "." + field.name + "(" + field.desc + ")";
+ }
+
+ public String methodToString(ClassNode cn, MethodNode method)
+ {
+ return cn.name + "." + method.name + "(" + method.desc + ")";
+ }
+
+ public void foundLDC(MalwareScan scan, String ldc, String foundAt)
+ {
+ scan.sb.append("Found LDC \"").append(ldc).append("\" ").append(foundAt);
+ }
+
+ public void foundMethod(MalwareScan scan, String foundAt)
+ {
+ scan.sb.append("Found Method call to ").append(foundAt);
+ }
+
+ public void found(MalwareScan scan, String found)
+ {
+ scan.sb.append("Found ").append(found);
+ }
+}
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/MalwareScan.java b/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/MalwareScan.java
new file mode 100644
index 00000000..4e18980e
--- /dev/null
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/MalwareScan.java
@@ -0,0 +1,29 @@
+package the.bytecode.club.bytecodeviewer.malwarescanner;
+
+import org.objectweb.asm.tree.ClassNode;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+
+/**
+ * A new malware scan object is created any time the MalicousCodeScanner plugin is ran
+ *
+ * This contains all of the details for the scan, including what should be scanned,
+ * and what was detected during the scan.
+ *
+ * @author Konloch
+ * @since 6/27/2021
+ */
+public class MalwareScan
+{
+ public final ArrayList classNodeList;
+ public final StringBuilder sb;
+ public final HashSet scanOptions;
+
+ public MalwareScan(ArrayList classNodeList, StringBuilder sb, HashSet scanOptions)
+ {
+ this.classNodeList = classNodeList;
+ this.sb = sb;
+ this.scanOptions = scanOptions;
+ }
+}
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/MalwareScanModule.java b/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/MalwareScanModule.java
new file mode 100644
index 00000000..8c417271
--- /dev/null
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/MalwareScanModule.java
@@ -0,0 +1,57 @@
+package the.bytecode.club.bytecodeviewer.malwarescanner;
+
+import org.objectweb.asm.tree.ClassNode;
+import the.bytecode.club.bytecodeviewer.malwarescanner.impl.*;
+
+/**
+ * All of the installed malware scan modules
+ *
+ * @author Konloch
+ * @since 6/27/2021
+ */
+public enum MalwareScanModule
+{
+ URL_SCANNER("Scan String URLs", new URLScanner(), true),
+ REFLECTION_SCANNER("Scan Java Reflection", new ReflectionScanner(), true),
+ JAVA_RUNTIME_SCANNER("Scan Java Runtime", new JavaRuntimeScanner(), true),
+ JAVA_NET_SCANNER("Scan Java Net", new JavaNetScanner(), true),
+ JAVA_IO_SCANNER("Scan Java IO", new JavaIOScanner(), false),
+ AWT_ROBOT_SCANNER("Scan AWT Robot", new AWTRobotScanner(), true),
+ NULL_SECURITY_MANAGER("Scan Null SecurityManager", new NullSecurityManagerScanner(), true),
+ ;
+
+ private final String readableName;
+ private final CodeScanner codeScanner;
+ private final boolean toggledByDefault;
+
+ MalwareScanModule(String readableName, CodeScanner codeScanner, boolean toggledByDefault) {
+ this.readableName = readableName;
+ this.codeScanner = codeScanner;
+ this.toggledByDefault = toggledByDefault;
+ }
+
+ public String getReadableName()
+ {
+ return readableName;
+ }
+
+ public CodeScanner getCodeScanner()
+ {
+ return codeScanner;
+ }
+
+ public boolean isToggledByDefault()
+ {
+ return toggledByDefault;
+ }
+
+ public static void performScan(MalwareScan scan)
+ {
+ for (ClassNode cn : scan.classNodeList)
+ {
+ for (MalwareScanModule module : values())
+ if(scan.scanOptions.contains(module.name()))
+ module.codeScanner.scanningClass(scan, cn);
+ }
+ }
+}
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/impl/AWTRobotScanner.java b/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/impl/AWTRobotScanner.java
new file mode 100644
index 00000000..74c70f52
--- /dev/null
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/impl/AWTRobotScanner.java
@@ -0,0 +1,44 @@
+package the.bytecode.club.bytecodeviewer.malwarescanner.impl;
+
+import org.objectweb.asm.tree.*;
+import the.bytecode.club.bytecodeviewer.malwarescanner.MalwareCodeScanner;
+import the.bytecode.club.bytecodeviewer.malwarescanner.MalwareScan;
+import the.bytecode.club.bytecodeviewer.malwarescanner.util.SearchableString;
+
+import static the.bytecode.club.bytecodeviewer.Constants.nl;
+
+/**
+ * Scans for any trace of java/awt/Robot inside of method instructions and strings
+ *
+ * @author Konloch
+ * @since 6/27/2021
+ */
+public class AWTRobotScanner extends MalwareCodeScanner
+{
+ @Override
+ public void scanFieldString(MalwareScan scan, ClassNode cn, FieldNode field, SearchableString string)
+ {
+ if(string.searchable.contains("java/awt/Robot")
+ || string.searchable.contains("java.awt.Robot"))
+ foundLDC(scan, string.original, "at field " + fieldToString(cn, field) + nl);
+ }
+
+ @Override
+ public void scanMethodString(MalwareScan scan, ClassNode cn, MethodNode method, SearchableString string)
+ {
+ if(string.searchable.contains("java/awt/Robot")
+ || string.searchable.contains("java.awt.Robot"))
+ foundLDC(scan, string.original, "at method " + methodToString(cn, method) + nl);
+ }
+
+ @Override
+ public void scanMethodInstruction(MalwareScan scan, ClassNode cn, MethodNode method, AbstractInsnNode instruction)
+ {
+ if (instruction instanceof MethodInsnNode)
+ {
+ final MethodInsnNode min = (MethodInsnNode) instruction;
+ if (min.owner.startsWith("java/awt/Robot"))
+ foundMethod(scan, methodToString(cn, method) + nl);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/impl/JavaIOScanner.java b/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/impl/JavaIOScanner.java
new file mode 100644
index 00000000..f40dbeae
--- /dev/null
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/impl/JavaIOScanner.java
@@ -0,0 +1,32 @@
+package the.bytecode.club.bytecodeviewer.malwarescanner.impl;
+
+import org.objectweb.asm.tree.*;
+import the.bytecode.club.bytecodeviewer.malwarescanner.MalwareScan;
+import the.bytecode.club.bytecodeviewer.malwarescanner.MalwareCodeScanner;
+import the.bytecode.club.bytecodeviewer.malwarescanner.util.SearchableString;
+
+import static the.bytecode.club.bytecodeviewer.Constants.nl;
+
+/**
+ * @author Konloch
+ * @since 6/27/2021
+ */
+public class JavaIOScanner extends MalwareCodeScanner
+{
+ @Override
+ public void scanFieldString(MalwareScan scan, ClassNode cn, FieldNode field, SearchableString string) { }
+
+ @Override
+ public void scanMethodString(MalwareScan scan, ClassNode cn, MethodNode method, SearchableString string) { }
+
+ @Override
+ public void scanMethodInstruction(MalwareScan scan, ClassNode cn, MethodNode method, AbstractInsnNode instruction)
+ {
+ if (instruction instanceof MethodInsnNode)
+ {
+ final MethodInsnNode min = (MethodInsnNode) instruction;
+ if (min.owner.startsWith("java/io"))
+ foundMethod(scan, methodToString(cn, method) + nl);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/impl/JavaNetScanner.java b/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/impl/JavaNetScanner.java
new file mode 100644
index 00000000..5f786386
--- /dev/null
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/impl/JavaNetScanner.java
@@ -0,0 +1,33 @@
+package the.bytecode.club.bytecodeviewer.malwarescanner.impl;
+
+import org.objectweb.asm.tree.*;
+import the.bytecode.club.bytecodeviewer.malwarescanner.MalwareScan;
+import the.bytecode.club.bytecodeviewer.malwarescanner.MalwareCodeScanner;
+import the.bytecode.club.bytecodeviewer.malwarescanner.util.SearchableString;
+
+import static the.bytecode.club.bytecodeviewer.Constants.nl;
+
+/**
+ * @author Konloch
+ * @author WaterWolf
+ * @since 6/27/2021
+ */
+public class JavaNetScanner extends MalwareCodeScanner
+{
+ @Override
+ public void scanFieldString(MalwareScan scan, ClassNode cn, FieldNode field, SearchableString string) { }
+
+ @Override
+ public void scanMethodString(MalwareScan scan, ClassNode cn, MethodNode method, SearchableString string) { }
+
+ @Override
+ public void scanMethodInstruction(MalwareScan scan, ClassNode cn, MethodNode method, AbstractInsnNode instruction)
+ {
+ if (instruction instanceof MethodInsnNode)
+ {
+ final MethodInsnNode min = (MethodInsnNode) instruction;
+ if (min.owner.startsWith("java/net"))
+ foundMethod(scan, methodToString(cn, method) + nl);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/impl/JavaRuntimeScanner.java b/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/impl/JavaRuntimeScanner.java
new file mode 100644
index 00000000..948b87f5
--- /dev/null
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/impl/JavaRuntimeScanner.java
@@ -0,0 +1,44 @@
+package the.bytecode.club.bytecodeviewer.malwarescanner.impl;
+
+import org.objectweb.asm.tree.*;
+import the.bytecode.club.bytecodeviewer.malwarescanner.MalwareScan;
+import the.bytecode.club.bytecodeviewer.malwarescanner.MalwareCodeScanner;
+import the.bytecode.club.bytecodeviewer.malwarescanner.util.SearchableString;
+
+import static the.bytecode.club.bytecodeviewer.Constants.nl;
+
+/**
+ * Scans for any trace of java/lang/Runtime inside of method instructions and strings
+ *
+ * @author Konloch
+ * @since 6/27/2021
+ */
+public class JavaRuntimeScanner extends MalwareCodeScanner
+{
+ @Override
+ public void scanFieldString(MalwareScan scan, ClassNode cn, FieldNode field, SearchableString string)
+ {
+ if(string.searchable.contains("java/lang/Runtime")
+ || string.searchable.contains("java.lang.Runtime"))
+ foundLDC(scan, string.original, "at field " + fieldToString(cn, field) + nl);
+ }
+
+ @Override
+ public void scanMethodString(MalwareScan scan, ClassNode cn, MethodNode method, SearchableString string)
+ {
+ if(string.searchable.contains("java/lang/Runtime")
+ || string.searchable.contains("java.lang.Runtime"))
+ foundLDC(scan, string.original, "at method " + methodToString(cn, method) + nl);
+ }
+
+ @Override
+ public void scanMethodInstruction(MalwareScan scan, ClassNode cn, MethodNode method, AbstractInsnNode instruction)
+ {
+ if (instruction instanceof MethodInsnNode)
+ {
+ final MethodInsnNode min = (MethodInsnNode) instruction;
+ if (min.owner.startsWith("java/lang/Runtime"))
+ foundMethod(scan, methodToString(cn, method) + nl);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/impl/NullSecurityManagerScanner.java b/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/impl/NullSecurityManagerScanner.java
new file mode 100644
index 00000000..3e1eae26
--- /dev/null
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/impl/NullSecurityManagerScanner.java
@@ -0,0 +1,55 @@
+package the.bytecode.club.bytecodeviewer.malwarescanner.impl;
+
+import com.strobel.assembler.ir.OpCode;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.*;
+import the.bytecode.club.bytecodeviewer.malwarescanner.MalwareCodeScanner;
+import the.bytecode.club.bytecodeviewer.malwarescanner.MalwareScan;
+import the.bytecode.club.bytecodeviewer.malwarescanner.util.SearchableString;
+
+import static the.bytecode.club.bytecodeviewer.Constants.nl;
+
+/**
+ * Checks for the security manager getting set to null
+ *
+ * @author Konloch
+ * @author Adrianherrera
+ * @since 6/27/2021
+ */
+public class NullSecurityManagerScanner extends MalwareCodeScanner
+{
+ private int lastInstruction;
+
+ @Override
+ public void scanFieldString(MalwareScan scan, ClassNode cn, FieldNode field, SearchableString string) { }
+
+ @Override
+ public void scanMethodString(MalwareScan scan, ClassNode cn, MethodNode method, SearchableString string) { }
+
+ @Override
+ public void scanMethodInstruction(MalwareScan scan, ClassNode cn, MethodNode method, AbstractInsnNode instruction)
+ {
+ if (instruction instanceof MethodInsnNode && instruction.getOpcode() == Opcodes.INVOKESTATIC)
+ {
+ final MethodInsnNode min = (MethodInsnNode) instruction;
+ final String owner = min.owner;
+ final String name = min.name;
+
+ if(lastInstruction == OpCode.ACONST_NULL.getCode()
+ && owner.equals("java/lang/System")
+ && name.equals("setSecurityManager"))
+ {
+ found(scan, "Security Manager set to null at method " + methodToString(cn, method) + nl);
+ }
+ }
+
+ lastInstruction = instruction.getOpcode();
+ }
+
+ @Override
+ public void scanningClass(MalwareScan scan, ClassNode cn)
+ {
+ lastInstruction = 0;
+ super.scanningClass(scan, cn);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/impl/ReflectionScanner.java b/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/impl/ReflectionScanner.java
new file mode 100644
index 00000000..dae795dd
--- /dev/null
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/impl/ReflectionScanner.java
@@ -0,0 +1,35 @@
+package the.bytecode.club.bytecodeviewer.malwarescanner.impl;
+
+import org.objectweb.asm.tree.*;
+import the.bytecode.club.bytecodeviewer.malwarescanner.MalwareScan;
+import the.bytecode.club.bytecodeviewer.malwarescanner.MalwareCodeScanner;
+import the.bytecode.club.bytecodeviewer.malwarescanner.util.SearchableString;
+
+import static the.bytecode.club.bytecodeviewer.Constants.nl;
+
+/**
+ * Scans for method instructions containing java/lang/reflect
+ *
+ * @author Konloch
+ * @author WaterWolf
+ * @since 6/27/2021
+ */
+public class ReflectionScanner extends MalwareCodeScanner
+{
+ @Override
+ public void scanFieldString(MalwareScan scan, ClassNode cn, FieldNode field, SearchableString string) { }
+
+ @Override
+ public void scanMethodString(MalwareScan scan, ClassNode cn, MethodNode method, SearchableString string) { }
+
+ @Override
+ public void scanMethodInstruction(MalwareScan scan, ClassNode cn, MethodNode method, AbstractInsnNode instruction)
+ {
+ if (instruction instanceof MethodInsnNode)
+ {
+ final MethodInsnNode min = (MethodInsnNode) instruction;
+ if (min.owner.startsWith("java/lang/reflect"))
+ foundMethod(scan, methodToString(cn, method) + nl);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/impl/URLScanner.java b/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/impl/URLScanner.java
new file mode 100644
index 00000000..9c4ed170
--- /dev/null
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/impl/URLScanner.java
@@ -0,0 +1,49 @@
+package the.bytecode.club.bytecodeviewer.malwarescanner.impl;
+
+import org.objectweb.asm.tree.*;
+import the.bytecode.club.bytecodeviewer.malwarescanner.MalwareScan;
+import the.bytecode.club.bytecodeviewer.malwarescanner.MalwareCodeScanner;
+import the.bytecode.club.bytecodeviewer.malwarescanner.util.SearchableString;
+
+import java.util.regex.Pattern;
+
+import static the.bytecode.club.bytecodeviewer.Constants.nl;
+
+/**
+ * Scans strings for common URL patterns:
+ * Any string containing www
+ * Any string containing http://
+ * Any string containing https://
+ * Any string matching an IP pattern
+ *
+ * @author Konloch
+ * @author WaterWolf
+ * @since 6/27/2021
+ */
+public class URLScanner extends MalwareCodeScanner
+{
+ private static final Pattern ipPattern = Pattern.compile("\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b");
+
+ @Override
+ public void scanFieldString(MalwareScan scan, ClassNode cn, FieldNode field, SearchableString string)
+ {
+ if (string.searchable.contains("www.")
+ || string.searchable.contains("http://")
+ || string.searchable.contains("https://")
+ || ipPattern.matcher(string.searchable).matches())
+ foundLDC(scan, string.original, "at field " + fieldToString(cn, field) + nl);
+ }
+
+ @Override
+ public void scanMethodString(MalwareScan scan, ClassNode cn, MethodNode method, SearchableString string)
+ {
+ if (string.searchable.contains("www.")
+ || string.searchable.contains("http://")
+ || string.searchable.contains("https://")
+ || ipPattern.matcher(string.searchable).matches())
+ foundLDC(scan, string.original, "at method " + methodToString(cn, method) + nl);
+ }
+
+ @Override
+ public void scanMethodInstruction(MalwareScan scan, ClassNode cn, MethodNode method, AbstractInsnNode instruction) { }
+}
\ No newline at end of file
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/util/SearchableString.java b/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/util/SearchableString.java
new file mode 100644
index 00000000..ef09a7db
--- /dev/null
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/malwarescanner/util/SearchableString.java
@@ -0,0 +1,17 @@
+package the.bytecode.club.bytecodeviewer.malwarescanner.util;
+
+/**
+ * @author Konloch
+ * @since 6/27/2021
+ */
+public class SearchableString
+{
+ public final String original;
+ public final String searchable;
+
+ public SearchableString(String original)
+ {
+ this.original = original;
+ this.searchable = original.toLowerCase();
+ }
+}
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/plugin/preinstalled/MaliciousCodeScanner.java b/src/main/java/the/bytecode/club/bytecodeviewer/plugin/preinstalled/MaliciousCodeScanner.java
index 25d690a9..e5af7e7c 100644
--- a/src/main/java/the/bytecode/club/bytecodeviewer/plugin/preinstalled/MaliciousCodeScanner.java
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/plugin/preinstalled/MaliciousCodeScanner.java
@@ -1,20 +1,18 @@
package the.bytecode.club.bytecodeviewer.plugin.preinstalled;
import java.util.ArrayList;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.tree.AbstractInsnNode;
+import java.util.HashSet;
+import java.util.List;
+
import org.objectweb.asm.tree.ClassNode;
-import org.objectweb.asm.tree.FieldNode;
-import org.objectweb.asm.tree.InsnList;
-import org.objectweb.asm.tree.InsnNode;
-import org.objectweb.asm.tree.LdcInsnNode;
-import org.objectweb.asm.tree.MethodInsnNode;
-import org.objectweb.asm.tree.MethodNode;
-import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.api.Plugin;
import the.bytecode.club.bytecodeviewer.api.PluginConsole;
+import the.bytecode.club.bytecodeviewer.gui.plugins.MaliciousCodeScannerOptions;
+import the.bytecode.club.bytecodeviewer.gui.plugins.MaliciousCodeScannerOptionsV2;
+import the.bytecode.club.bytecodeviewer.malwarescanner.MalwareScan;
+import the.bytecode.club.bytecodeviewer.malwarescanner.MalwareScanModule;
-import static the.bytecode.club.bytecodeviewer.Constants.*;
+import javax.swing.*;
/***************************************************************************
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
@@ -35,134 +33,43 @@ import static the.bytecode.club.bytecodeviewer.Constants.*;
***************************************************************************/
/**
- * The idea/core was based off of J-RET's Malicious Code Searcher I improved it,
- * and added more stuff to search for.
+ * The Malicious Code Scanner plugin. All of the core components have been moved to the malwarescanner package.
+ *
+ * This tool is used to help aid reverse engineers in identifying malicious code.
*
* @author Konloch
* @author Adrianherrera
* @author WaterWolf
+ * @since 10/02/2011
*/
-public class MaliciousCodeScanner extends Plugin {
+public class MaliciousCodeScanner extends Plugin
+{
+ public final List options;
- public boolean ORE, ONE, ORU, OIO, LWW, LHT, LHS, LIP, NSM, ROB;
-
- public MaliciousCodeScanner(boolean reflect, boolean runtime, boolean net,
- boolean io, boolean www, boolean http, boolean https, boolean ip,
- boolean nullSecMan, boolean robot) {
- ORE = reflect;
- ONE = net;
- ORU = runtime;
- OIO = io;
- LWW = www;
- LHT = http;
- LHS = https;
- LIP = ip;
- NSM = nullSecMan;
- ROB = robot;
+ public MaliciousCodeScanner(List options)
+ {
+ this.options = options;
}
@Override
- public void execute(ArrayList classNodeList) {
+ public void execute(ArrayList classNodeList)
+ {
PluginConsole frame = new PluginConsole("Malicious Code Scanner");
StringBuilder sb = new StringBuilder();
- for (ClassNode classNode : classNodeList) {
- for (Object o : classNode.fields.toArray()) {
- FieldNode f = (FieldNode) o;
- Object v = f.value;
- if (v instanceof String) {
- String s = (String) v;
- if ((LWW && s.contains("www."))
- || (LHT && s.contains("http://"))
- || (LHS && s.contains("https://"))
- || (ORE && s.contains("java/lang/Runtime"))
- || (ORE && s.contains("java.lang.Runtime"))
- || (ROB && s.contains("java.awt.Robot"))
- || (ROB && s.contains("java/awt/Robot"))
- || (LIP && s
- .matches("\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b")))
- sb.append("Found LDC \"").append(s).append("\" at field ").append(classNode.name).append(".")
- .append(f.name).append("(").append(f.desc).append(")").append(nl);
- }
- if (v instanceof String[]) {
- for (int i = 0; i < ((String[]) v).length; i++) {
- String s = ((String[]) v)[i];
- if ((LWW && s.contains("www."))
- || (LHT && s.contains("http://"))
- || (LHS && s.contains("https://"))
- || (ORE && s.contains("java/lang/Runtime"))
- || (ORE && s.contains("java.lang.Runtime"))
- || (ROB && s.contains("java.awt.Robot"))
- || (ROB && s.contains("java/awt/Robot"))
- || (LIP && s
- .matches("\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b")))
- sb.append("Found LDC \"").append(s).append("\" at field ").append(classNode.name)
- .append(".").append(f.name).append("(").append(f.desc).append(")")
- .append(nl);
- }
- }
- }
-
- boolean prevInsn_aconst_null = false;
-
- for (Object o : classNode.methods.toArray()) {
- MethodNode m = (MethodNode) o;
-
- InsnList iList = m.instructions;
- for (AbstractInsnNode a : iList.toArray()) {
- if (a instanceof MethodInsnNode) {
- final MethodInsnNode min = (MethodInsnNode) a;
- if ((ORE && min.owner.startsWith("java/lang/reflect"))
- || (ONE && min.owner.startsWith("java/net"))
- || (ORU && min.owner.equals("java/lang/Runtime"))
- || (ROB && min.owner.equals("java/awt/Robot"))
- || (OIO && min.owner.startsWith("java/io"))) {
- sb.append("Found Method call to ").append(min.owner).append(".").append(min.name)
- .append("(").append(min.desc).append(") at ").append(classNode.name).append(".")
- .append(m.name).append("(").append(m.desc).append(")").append(nl);
- }
- }
- if (a instanceof LdcInsnNode) {
- if (((LdcInsnNode) a).cst instanceof String) {
- final String s = (String) ((LdcInsnNode) a).cst;
- if ((LWW && s.contains("www."))
- || (LHT && s.contains("http://"))
- || (LHS && s.contains("https://"))
- || (ORE && s.contains("java/lang/Runtime"))
- || (ORE && s.contains("java.lang.Runtime"))
- || (ROB && s.contains("java.awt.Robot"))
- || (ROB && s.contains("java/awt/Robot"))
- || (LIP && s
- .matches("\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b"))) {
- sb.append("Found LDC \"").append(s).append("\" at method ").append(classNode.name)
- .append(".").append(m.name).append("(").append(m.desc).append(")")
- .append(nl);
- }
- }
- }
-
- // Check if the security manager is getting set to null
- if ((a instanceof InsnNode)
- && (a.getOpcode() == Opcodes.ACONST_NULL)) {
- prevInsn_aconst_null = true;
- } else if ((a instanceof MethodInsnNode)
- && (a.getOpcode() == Opcodes.INVOKESTATIC)) {
- final String owner = ((MethodInsnNode) a).owner;
- final String name = ((MethodInsnNode) a).name;
- if ((NSM && prevInsn_aconst_null
- && owner.equals("java/lang/System") && name
- .equals("setSecurityManager"))) {
- sb.append("Found Security Manager set to null at method ").append(classNode.name)
- .append(".").append(m.name).append("(").append(m.desc).append(")")
- .append(nl);
- prevInsn_aconst_null = false;
- }
- } else {
- prevInsn_aconst_null = false;
- }
- }
- }
- }
+
+ //TODO automate this when the GUI has been changed
+ HashSet scanOptions = new HashSet<>();
+
+ for(MaliciousCodeScannerOptionsV2.MaliciousCodeOptions option : options)
+ if(option.getCheckBox().isSelected())
+ scanOptions.add(option.getModule().name());
+
+ //create a new code scan object with all of the scan options
+ MalwareScan scan = new MalwareScan(classNodeList, sb, scanOptions);
+
+ //scan the modules one by one
+ MalwareScanModule.performScan(scan);
frame.appendText(sb.toString());
frame.setVisible(true);