com.dank.analysis.impl.definition.object.ObjectDefinition.java Source code

Java tutorial

Introduction

Here is the source code for com.dank.analysis.impl.definition.object.ObjectDefinition.java

Source

package com.dank.analysis.impl.definition.object;

import org.objectweb.asm.commons.cfg.BasicBlock;
import org.objectweb.asm.commons.cfg.query.MemberQuery;
import org.objectweb.asm.commons.cfg.tree.NodeVisitor;
import org.objectweb.asm.commons.cfg.tree.node.FieldMemberNode;
import org.objectweb.asm.commons.cfg.tree.node.JumpNode;
import org.objectweb.asm.commons.cfg.tree.node.MethodMemberNode;
import org.objectweb.asm.commons.cfg.tree.node.StoreNode;
import org.objectweb.asm.commons.cfg.tree.node.VariableNode;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.MethodNode;

import com.dank.DankEngine;
import com.dank.analysis.Analyser;
import com.dank.analysis.impl.definition.object.visitor.IdVisitor;
import com.dank.analysis.impl.definition.object.visitor.TempTransformVisitor;
import com.dank.analysis.impl.definition.object.visitor.TransformVisitor;
import com.dank.analysis.visitor.TreeVisitor;
import com.dank.hook.Hook;
import com.dank.hook.RSField;
import com.dank.hook.RSMethod;

/**
 * Project: DankWise
 * Date: 28-02-2015
 * Time: 15:35
 * Created by Dogerina.
 * Copyright under GPL license by Dogerina.
 */
public class ObjectDefinition extends Analyser {

    @Override
    public ClassSpec specify(ClassNode cn) {
        return cn.superName(Hook.DUAL_NODE.getInternalName()) && cn.fieldCount(boolean.class) > 3
                && cn.fieldCount(int.class) > 22 ? new ClassSpec(Hook.OBJECT_DEFINITION, cn) : null;
    }

    @Override
    public void evaluate(ClassNode cn) {
        for (final FieldNode fn : cn.fields) {
            if (!fn.isStatic()) {
                if (fn.desc.equals("Ljava/lang/String;")) {
                    Hook.OBJECT_DEFINITION.put(new RSField(fn, "name"));
                } else if (fn.desc.equals("[Ljava/lang/String;")) {
                    Hook.OBJECT_DEFINITION.put(new RSField(fn, "actions"));
                }
            }
        }
        for (final MethodNode mn : cn.methods) {
            if (!mn.isStatic()) {
                if (mn.desc.endsWith(";")) {
                    for (final BasicBlock block : mn.graph()) {
                        block.tree().accept(new ColorVisitor());
                    }
                }
                if (mn.desc.endsWith(String.format("L%s;", cn.name))) {
                    for (final BasicBlock block : mn.graph()) {
                        block.tree().accept(new TempTransformVisitor(block));
                    }
                }
                mn.graph().forEach(block -> {
                    block.tree().accept(new IdVisitor(block));
                    block.tree().accept(new ClipType());
                });
            }
        }
        for (final MethodNode mn : cn.methods) {
            if (!mn.isStatic() && mn.desc.endsWith(String.format("L%s;", cn.name))) {
                for (final BasicBlock block : mn.graph()) {
                    block.tree().accept(new TransformVisitor(block)); //requires the other transform to be done first..
                }
                Hook.OBJECT_DEFINITION.put(new RSMethod(mn, "transform"));
            }
        }
        for (final ClassNode c : super.getClassPath()) {
            for (final MethodNode mn : c.methods) {
                mn.graph().forEach(b -> {
                    b.tree().accept(new SizeVisitor(b));
                    b.tree().accept(new MapFunction());
                    b.tree().accept(new Clip());
                });
            }
        }
    }

    private final class SizeVisitor extends TreeVisitor {

        public SizeVisitor(BasicBlock block) {
            super(block);
        }

        @Override
        public boolean validateBlock(BasicBlock block) {
            return block.count(new MemberQuery(GETFIELD, Hook.OBJECT_DEFINITION.getInternalName(), "I")) > 0;
        }

        @Override
        public void visitStore(StoreNode sn) {
            if (sn.isOpcode(ISTORE)) {
                final FieldMemberNode layer = (FieldMemberNode) sn.layer(IDIV, ISUB, IMUL, GETFIELD);
                if (layer != null) {
                    final VariableNode aload = layer.firstVariable();
                    if ((aload != null && aload.var() < 11) || sn.var() < 13) {
                        if (Hook.OBJECT_DEFINITION.get("sizeX") == null) {
                            Hook.OBJECT_DEFINITION.put(new RSField(layer, "sizeX"));
                        } else if (Hook.OBJECT_DEFINITION.get("sizeY") == null) {
                            Hook.OBJECT_DEFINITION.put(new RSField(layer, "sizeY"));
                        }
                    }
                }
            }
        }
    }

    private final class ColorVisitor extends NodeVisitor {

        @Override
        public void visitMethod(MethodMemberNode mmn) {
            if (mmn.opcode() == INVOKEVIRTUAL) {
                final MethodNode mn = DankEngine.lookupMethod(mmn.owner(), mmn.name(), mmn.desc());
                /**
                 * if it does have ifnonnull then the method contains textures and modifiedTextures
                 * but we dont need textures so itsk
                 */
                if (mn != null && !contains(mn.instructions, IFNONNULL)) {
                    mmn.tree().accept(new NodeVisitor() {
                        @Override
                        public void visitField(FieldMemberNode fmn) {
                            if (fmn.desc().equals("[S")) {
                                if (Hook.OBJECT_DEFINITION.get("colors") == null) {
                                    Hook.OBJECT_DEFINITION.put(new RSField(fmn, "colors"));
                                } else if (Hook.OBJECT_DEFINITION.get("modifiedColors") == null) {
                                    Hook.OBJECT_DEFINITION.put(new RSField(fmn, "modifiedColors"));
                                }
                            }
                        }
                    });
                }
            }
        }

        private boolean contains(InsnList iList, int op) {
            for (final AbstractInsnNode ain : iList) {
                if (ain.opcode() == op) {
                    return true;
                }
            }
            return false;
        }
    }

    private class ClipType extends NodeVisitor {

        public void visitJump(JumpNode jn) {
            if (Hook.OBJECT_DEFINITION.get("clipType") == null && jn.opcode() == IFLT) {
                FieldMemberNode fmn = (FieldMemberNode) jn.layer(IMUL, GETFIELD);
                if (fmn != null && fmn.owner().equals(Hook.OBJECT_DEFINITION.getInternalName())
                        && fmn.desc().equals("I"))
                    Hook.OBJECT_DEFINITION.put(new RSField(fmn, "clipType"));
            }
        }
    }

    private class MapFunction extends NodeVisitor {

        @Override
        public void visitField(FieldMemberNode fmn) {
            if (Hook.OBJECT_DEFINITION.get("mapFunction") == null && fmn.opcode() == GETFIELD
                    && fmn.owner().equals(Hook.OBJECT_DEFINITION.getInternalName()) && fmn.desc().equals("I")) {
                MethodMemberNode method = fmn.firstMethod();
                if (method != null && method.desc().endsWith(Hook.OBJECT_DEFINITION.getInternalDesc())) {
                    VariableNode vn = method.firstVariable();
                    if (vn != null) {
                        Hook.OBJECT_DEFINITION.put(new RSField(fmn, "mapFunction"));
                    }
                }
            }
        }
    }

    private int clipPTR = 0;

    private class Clip extends NodeVisitor {

        private String[] hooks = { "clipped", "modelClipped" };

        public void visitField(FieldMemberNode fmn) {
            if (clipPTR < 2 && fmn.hasParent() && fmn.parent().opcode() == IFEQ && fmn.opcode() == GETFIELD
                    && fmn.owner().equals(Hook.OBJECT_DEFINITION.getInternalName()) && fmn.desc().equals("Z")) {
                VariableNode vn = fmn.firstVariable();
                if (vn != null && vn.var() == 9) {
                    Hook.OBJECT_DEFINITION.put(new RSField(fmn, hooks[clipPTR++]));
                }
            }
        }
    }
}