2015-11-11 04:16:45 +00:00
|
|
|
package the.bytecode.club.bytecodeviewer.api;
|
|
|
|
|
|
|
|
import java.security.AllPermission;
|
|
|
|
import java.security.CodeSource;
|
|
|
|
import java.security.Permissions;
|
|
|
|
import java.security.ProtectionDomain;
|
|
|
|
import java.security.cert.Certificate;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Collection;
|
|
|
|
import java.util.HashMap;
|
2021-08-27 08:49:31 +00:00
|
|
|
import java.util.List;
|
2021-08-26 21:59:07 +00:00
|
|
|
import java.util.Map;
|
2018-01-31 15:03:53 +00:00
|
|
|
import org.objectweb.asm.ClassWriter;
|
|
|
|
import org.objectweb.asm.tree.ClassNode;
|
|
|
|
|
2015-11-11 04:16:45 +00:00
|
|
|
/***************************************************************************
|
|
|
|
* 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/>. *
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @author Demmonic
|
|
|
|
*/
|
|
|
|
|
2021-07-06 22:11:55 +00:00
|
|
|
public final class ClassNodeLoader extends ClassLoader
|
|
|
|
{
|
2021-08-26 21:59:07 +00:00
|
|
|
private final Map<String, ClassNode> classes = new HashMap<>();
|
2018-01-31 15:41:24 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds the provided class node to the class loader
|
|
|
|
*
|
|
|
|
* @param cn The class
|
|
|
|
*/
|
|
|
|
public void addClass(ClassNode cn) {
|
|
|
|
classes.put(cn.name.replace("/", "."), cn);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param name The name of the class
|
|
|
|
* @return If this class loader contains the provided class node
|
|
|
|
*/
|
|
|
|
public boolean contains(String name) {
|
|
|
|
return (classes.get(name) != null);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return All class nodes in this loader
|
|
|
|
*/
|
|
|
|
public Collection<ClassNode> getAll() {
|
|
|
|
return classes.values();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Clears out all class nodes
|
|
|
|
*/
|
|
|
|
public void clear() {
|
|
|
|
classes.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return All classes in this loader
|
|
|
|
*/
|
|
|
|
public Collection<Class<?>> getAllClasses() {
|
2021-08-27 08:49:31 +00:00
|
|
|
List<Class<?>> classes = new ArrayList<>();
|
2018-01-31 15:41:24 +00:00
|
|
|
for (String s : this.classes.keySet()) {
|
|
|
|
try {
|
|
|
|
classes.add(loadClass(s));
|
|
|
|
} catch (ClassNotFoundException e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return classes;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param name The name of the class
|
|
|
|
* @return The class node with the provided name
|
|
|
|
*/
|
|
|
|
public ClassNode get(String name) {
|
|
|
|
return classes.get(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Class<?> loadClass(String className) throws ClassNotFoundException {
|
|
|
|
return findClass(className);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Class<?> findClass(String name) throws ClassNotFoundException {
|
|
|
|
if (classes.containsKey(name)) {
|
|
|
|
return nodeToClass(classes.get(name));
|
|
|
|
} else {
|
|
|
|
return super.loadClass(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Converts a class node to a class
|
|
|
|
*
|
|
|
|
* @param node The node to convert
|
|
|
|
* @return The converted class
|
|
|
|
*/
|
2021-07-06 22:11:55 +00:00
|
|
|
public Class<?> nodeToClass(ClassNode node)
|
|
|
|
{
|
2018-01-31 15:41:24 +00:00
|
|
|
if (super.findLoadedClass(node.name.replace("/", ".")) != null)
|
|
|
|
return findLoadedClass(node.name.replace("/", "."));
|
2021-07-06 22:11:55 +00:00
|
|
|
|
2018-01-31 15:41:24 +00:00
|
|
|
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
|
|
|
|
try {
|
|
|
|
node.accept(cw);
|
|
|
|
} catch (Exception e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
2021-07-06 22:11:55 +00:00
|
|
|
|
2018-01-31 15:41:24 +00:00
|
|
|
byte[] b = cw.toByteArray();
|
|
|
|
return defineClass(node.name.replaceAll("/", "."), b, 0, b.length,
|
|
|
|
getDomain());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return This class loader's protection domain
|
|
|
|
*/
|
|
|
|
private ProtectionDomain getDomain() {
|
|
|
|
CodeSource code = new CodeSource(null, (Certificate[]) null);
|
|
|
|
return new ProtectionDomain(code, getPermissions());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return This class loader's permissions
|
|
|
|
*/
|
|
|
|
private Permissions getPermissions() {
|
|
|
|
Permissions permissions = new Permissions();
|
|
|
|
permissions.add(new AllPermission());
|
|
|
|
return permissions;
|
|
|
|
}
|
2015-11-11 04:16:45 +00:00
|
|
|
}
|