01-11-2016, 09:14 AM
(This post was last modified: 01-11-2016, 09:41 AM by Dank Vader.)
I've fixed the bug where bytecode "contradicted" the decompiled source. It was an issue where the UTF8 strings were not being updated.
Anyways moving on. I'm working on my mapping generation. It's working well except that it renames methods that it shouldn't.
Example: It renames void start(Stage stage) which overrides a method in the Application class (Part of the JavaFX library). Currently since I do not include the JavaFX classes in the jar file (They come with the latest JRE) I have to resort to reflection to get the methods in parent classes.
Code I have:
Is there a way I could use ASM (The main library I'm working with) to achieve what I'm doing with reflection? I don't want to have to use reflection since does not statically analyze the class. If something in the static block is malicious it will be initialized when using reflection. I really don't want that... Plus reflection is extremely slow compared to pure static analysis of ASM.
Edit: Well I guess this is resolved. Was informed that ClassReader can take a string parameter and do exactly what I wanted.
Anyways moving on. I'm working on my mapping generation. It's working well except that it renames methods that it shouldn't.
Example: It renames void start(Stage stage) which overrides a method in the Application class (Part of the JavaFX library). Currently since I do not include the JavaFX classes in the jar file (They come with the latest JRE) I have to resort to reflection to get the methods in parent classes.
Code I have:
PHP Code:
private static void addMethods(MappedClass classMap) {
Set<String> syntheticMethods = new HashSet<String>();
for (MethodNode methodNode : classMap.getNode().methods) {
if (AccessHelper.isSynthetic(methodNode.access)) {
syntheticMethods.add(methodNode.name);
}
}
for (MethodNode methodNode : classMap.getNode().methods) {
MappedMethod mappedMethod = null;
// If the method is the main one, make sure it's output name is the
// same as the intial name. Mark it as the main method as well.
if (isMain(methodNode)) {
mappedMethod = new MappedMethod(methodNode.name, methodNode.name);
setMain(classMap.getRenamed());
} else if (methodNode.name.contains("<")) {
// If the name is <init> or <clinit>
mappedMethod = new MappedMethod(methodNode.name, methodNode.name);
} else if (syntheticMethods.contains(methodNode.name)) {
// The method shares a synthetic method's name. It most likely
// should not be renamed.
mappedMethod = new MappedMethod(methodNode.name, methodNode.name);
} else {
// If the method is not the main method and not <init>/<clinit>,
// attempt to find it in a parent class.
mappedMethod = getParentMethod(classMap, methodNode);
}
// If the method belongs to an enum and is an inbuilt method
// belonging to the Enum class.
if (mappedMethod == null && AccessHelper.isEnum(classMap.getNode().access)) {
if (methodNode.name.equals("values") || methodNode.name.equals("getName") || methodNode.name.equals("ordinal")) {
mappedMethod = new MappedMethod(methodNode.name, methodNode.name);
}
}
// If the method is still null, attempt to find it in
// the interfaces.
if (mappedMethod == null) {
mappedMethod = getInterfaceMethod(classMap, methodNode);
}
// Use reflection to see if a parent class has the method
if (mappedMethod == null) {
mappedMethod = getReflectionParent(classMap, methodNode);
}
// If the method is STILL null this means it must be totally
// new. Obfuscate it.
if (mappedMethod == null) {
mappedMethod = new MappedMethod(methodNode.name, getMethodName(methodNode, mode));
}
// Add the method to the mapped class.
classMap.getMethods().put(methodNode.name, mappedMethod);
methodIndex++;
}
}
PHP Code:
/**
* Attempt to find the given method in a parent class, given the inital
* class the method belongs do.
*
* @param classMap
* Initial class
* @param methodNode
* Initial method
* @return
*/
private static MappedMethod getParentMethod(final MappedClass classMap, final MethodNode methodNode) {
MappedClass parentMap = classMap.getParent();
while (parentMap != null) {
if (parentMap.getMethods().containsKey(methodNode.name)) {
return parentMap.getMethods().get(methodNode.name);
}
parentMap = parentMap.getParent();
}
return null;
}
PHP Code:
/**
* Attempt to find the given method in an interface, given the inital class
* the method belongs do.
*
* @param classMap
* Inital class
* @param methodNode
* Initial method
* @return
*/
private static MappedMethod getInterfaceMethod(final MappedClass classMap, final MethodNode methodNode) {
MappedClass parentMap = classMap;
while (parentMap != null) {
ClassNode node = parentMap.getNode();
for (String interfaze : node.interfaces) {
if (rename.containsKey(interfaze)) {
MappedClass mappedInterface = rename.get(interfaze);
if (mappedInterface.getMethods().containsKey(methodNode.name)) {
return mappedInterface.getMethods().get(methodNode.name);
}
}
}
parentMap = parentMap.getParent();
}
return null;
}
PHP Code:
/**
* Attempt to find the given method in a parent class, given the inital
* class the method belongs to. Uses reflection to load classes not provided
* by the jar file.
*
* @param classMap
* Initial class
* @param methodNode
* Initial method
* @return
*/
private static MappedMethod getReflectionParent(final MappedClass classMap, final MethodNode methodNode) {
try {
Class clazz = Class.forName(methodNode.owner.name.replace("/", "."));
if (clazz != null) {
clazz = clazz.getSuperclass();
}
while (clazz != null) {
String asmName = clazz.getName().replace(".", "/");
for (Method method : clazz.getMethods()) {
if (method.getName().equals(methodNode.name)) {
if (rename.containsKey(asmName)) {
MappedClass mc = rename.get(asmName);
if (mc.getMethods().containsKey(methodNode.name)) {
return mc.getMethods().get(methodNode.name);
}
} else {
return new MappedMethod(methodNode.name, methodNode.name);
}
}
}
if (clazz.getName().contains("java.lang.Object")) {
clazz = null;
break;
} else {
clazz = clazz.getSuperclass();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
Is there a way I could use ASM (The main library I'm working with) to achieve what I'm doing with reflection? I don't want to have to use reflection since does not statically analyze the class. If something in the static block is malicious it will be initialized when using reflection. I really don't want that... Plus reflection is extremely slow compared to pure static analysis of ASM.
Edit: Well I guess this is resolved. Was informed that ClassReader can take a string parameter and do exactly what I wanted.