Extended The Malicious Code Scanner

The new system is designed to make creating a new scan module painless
This commit is contained in:
Konloch 2021-06-27 22:54:09 -07:00
parent b7deff48da
commit 10d4bcf1f5
16 changed files with 650 additions and 129 deletions

View File

@ -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());

View File

@ -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);

View File

@ -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 <http://www.gnu.org/licenses/>. *
***************************************************************************/
/**
* 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<MaliciousCodeOptions> 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;
}
}
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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<ClassNode> classNodeList;
public final StringBuilder sb;
public final HashSet<String> scanOptions;
public MalwareScan(ArrayList<ClassNode> classNodeList, StringBuilder sb, HashSet<String> scanOptions)
{
this.classNodeList = classNodeList;
this.sb = sb;
this.scanOptions = scanOptions;
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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) { }
}

View File

@ -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();
}
}

View File

@ -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<MaliciousCodeScannerOptionsV2.MaliciousCodeOptions> 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<MaliciousCodeScannerOptionsV2.MaliciousCodeOptions> options)
{
this.options = options;
}
@Override
public void execute(ArrayList<ClassNode> classNodeList) {
public void execute(ArrayList<ClassNode> 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;
//TODO automate this when the GUI has been changed
HashSet<String> scanOptions = new HashSet<>();
for (Object o : classNode.methods.toArray()) {
MethodNode m = (MethodNode) o;
for(MaliciousCodeScannerOptionsV2.MaliciousCodeOptions option : options)
if(option.getCheckBox().isSelected())
scanOptions.add(option.getModule().name());
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);
}
}
}
//create a new code scan object with all of the scan options
MalwareScan scan = new MalwareScan(classNodeList, sb, scanOptions);
// 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;
}
}
}
}
//scan the modules one by one
MalwareScanModule.performScan(scan);
frame.appendText(sb.toString());
frame.setVisible(true);