Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[ASM] Getting methods of a parent class without reflection [Fixed]
#1
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:
PHP Code:
private static void addMethods(MappedClass classMap) {
        
Set<StringsyntheticMethods = 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.namemethodNode.name);
                
setMain(classMap.getRenamed());
            } else if (
methodNode.name.contains("<")) {
                
// If the name is <init> or <clinit>
                
mappedMethod = new MappedMethod(methodNode.namemethodNode.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.namemethodNode.name);
            } else {
                
// If the method is not the main method and not <init>/<clinit>,
                // attempt to find it in a parent class.
                
mappedMethod getParentMethod(classMapmethodNode);
            }
            
// 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.namemethodNode.name);
                }
            }
            
// If the method is still null, attempt to find it in
            // the interfaces.
            
if (mappedMethod == null) {
                
mappedMethod getInterfaceMethod(classMapmethodNode);
            }
            
// Use reflection to see if a parent class has the method
            
if (mappedMethod == null) {
                
mappedMethod getReflectionParent(classMapmethodNode);
            }
            
// If the method is STILL null this means it must be totally
            // new. Obfuscate it.
            
if (mappedMethod == null) {
                
mappedMethod = new MappedMethod(methodNode.namegetMethodName(methodNodemode));
            }
            
// Add the method to the mapped class.
            
classMap.getMethods().put(methodNode.namemappedMethod);
            
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.namemethodNode.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.
Reply
 


Forum Jump:


Users browsing this thread: 3 Guest(s)

About The Bytecode Club

We're a community forum focused on Reverse Engineering, we try to target Java/Android but we also include other langauges/platforms. We pride ourselves in supporting and free and open sourced applications.

Website