Created
July 30, 2015 17:58
-
-
Save t81lal/8e776c1f63ba8e25837c to your computer and use it in GitHub Desktop.
QueueAnalyser.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.nullbool.impl.analysers.collections; | |
import java.lang.reflect.Modifier; | |
import java.util.ArrayList; | |
import java.util.List; | |
import org.nullbool.api.Builder; | |
import org.nullbool.api.analysis.ClassAnalyser; | |
import org.nullbool.api.analysis.IFieldAnalyser; | |
import org.nullbool.api.analysis.IMethodAnalyser; | |
import org.nullbool.api.analysis.IMultiAnalyser; | |
import org.nullbool.api.analysis.SupportedHooks; | |
import org.nullbool.api.util.StaticDescFilter; | |
import org.nullbool.pi.core.hook.api.FieldHook; | |
import org.nullbool.pi.core.hook.api.MethodHook; | |
import org.objectweb.asm.tree.AbstractInsnNode; | |
import org.objectweb.asm.tree.ClassNode; | |
import org.objectweb.asm.tree.FieldInsnNode; | |
import org.objectweb.asm.tree.FieldNode; | |
import org.objectweb.asm.tree.InsnNode; | |
import org.objectweb.asm.tree.MethodInsnNode; | |
import org.objectweb.asm.tree.MethodNode; | |
import org.objectweb.asm.tree.TypeInsnNode; | |
import org.objectweb.asm.tree.VarInsnNode; | |
import org.topdank.banalysis.asm.insn.InstructionPattern; | |
import org.topdank.banalysis.asm.insn.InstructionSearcher; | |
/** | |
* @author Bibl (don't ban me pls) | |
* @created 21 Jul 2015 02:55:01 | |
*/ | |
@SupportedHooks(fields = { "head&DualNode" }, | |
methods = { "get&()DualNode", "remove&()DualNode", | |
"insertHead&(DualNode)V", "insertTail&(DualNode)V" }) | |
public class QueueAnalyser extends ClassAnalyser { | |
private ClassNode dual; | |
public QueueAnalyser() { | |
super("Queue"); | |
} | |
private ClassNode dual() { | |
if(dual == null) { | |
dual = getClassNodeByRefactoredName("DualNode"); | |
} | |
return dual; | |
} | |
/* (non-Javadoc) | |
* @see org.nullbool.api.analysis.ClassAnalyser#matches(org.objectweb.asm.tree.ClassNode) | |
*/ | |
@Override | |
protected boolean matches(ClassNode cn) { | |
if(!cn.superName.equals("java/lang/Object")) | |
return false; | |
if(cn.interfaces.size() != 0) | |
return false; | |
String desc = "L" + dual().name + ";"; | |
int dns = getFieldCount(cn, new StaticDescFilter(desc)); | |
if(dns != 1) | |
return false; | |
int ns = 0; | |
for(FieldNode f : cn.fields) { | |
if(!Modifier.isStatic(f.access)) { | |
ns++; | |
} | |
} | |
if(ns != 1) | |
return false; | |
for(MethodNode m : cn.methods) { | |
if(m.name.equals("<init>")) { | |
// aload0 // reference to self | |
// new gk | |
// dup | |
// invokespecial gk <init>(()V); | |
// putfield gp.p:gk | |
InstructionPattern pattern = new InstructionPattern(new AbstractInsnNode[]{ | |
new VarInsnNode(ALOAD, 0), | |
new TypeInsnNode(NEW, dual().name), | |
new InsnNode(DUP), | |
new MethodInsnNode(INVOKESPECIAL, dual().name, "<init>", "()V", false), | |
new FieldInsnNode(PUTFIELD, cn.name, null, desc) | |
}); | |
InstructionSearcher searcher = new InstructionSearcher(m.instructions, pattern); | |
if(searcher.search()) { | |
return true; | |
} | |
} | |
} | |
return false; | |
} | |
public class HeadFieldAnalyser implements IFieldAnalyser { | |
/* (non-Javadoc) | |
* @see org.nullbool.api.analysis.IFieldAnalyser#find(org.objectweb.asm.tree.ClassNode) | |
*/ | |
@Override | |
public List<FieldHook> findFields(ClassNode cn) { | |
List<FieldHook> list = new ArrayList<FieldHook>(); | |
String desc = "L" + dual().name + ";"; | |
for(FieldNode f : cn.fields) { | |
if(!Modifier.isStatic(f.access)) { | |
if(f.desc.equals(desc)) { | |
list.add(asFieldHook(f, "head")); | |
// let it run on, shouldn't dup hook unless there is some | |
// huge gaping wide bug in asm/something else. | |
} | |
} | |
} | |
return list; | |
} | |
} | |
public class GetRemoveMethodAnalysers implements IMethodAnalyser { | |
/* (non-Javadoc) | |
* @see org.nullbool.api.analysis.IMethodAnalyser#find(org.objectweb.asm.tree.ClassNode) | |
*/ | |
@Override | |
public List<MethodHook> findMethods(ClassNode cn) { | |
List<MethodHook> list = new ArrayList<MethodHook>(); | |
String desc = "()L" + dual() + ";"; | |
for(MethodNode m : cn.methods) { | |
if(m.desc.equals(desc)) { | |
if(findMethod(cn, m, new String[]{"aconst_null", "areturn"}) && findMethod(cn, m, new String[]{"aload", "areturn"})) { | |
if(findOpcodePattern(m, new int[]{INVOKEVIRTUAL}) != null) { | |
list.add(asMethodHook(m, "remove")); | |
} else { | |
list.add(asMethodHook(m, "get")); | |
} | |
} | |
} | |
} | |
return list; | |
} | |
} | |
public class InsertMethodsAnalyser implements IMethodAnalyser { | |
/* (non-Javadoc) | |
* @see org.nullbool.api.analysis.IMethodAnalyser#find(org.objectweb.asm.tree.ClassNode) | |
*/ | |
@Override | |
public List<MethodHook> findMethods(ClassNode cn) { | |
List<MethodHook> list = new ArrayList<MethodHook>(); | |
String fdesc = "L" + dual().name + ";"; | |
FieldHook prev = getAnalyser("DualNode").getFoundHook().fbyRefactoredName("previousDualNode"); | |
FieldHook next = getAnalyser("DualNode").getFoundHook().fbyRefactoredName("nextDualNode"); | |
//System.out.println(fdesc); | |
// cant get this getfield to work | |
// aload1 | |
// aload0 // reference to self | |
// getfield gp.p:gk | |
// getfield gk.ca:gk | |
// putfield gk.ca:gk | |
// aload1 | |
// aload0 // reference to self | |
// getfield gp.p:gk | |
// putfield gk.cl:gk | |
// the difference between the two methods is that two lines | |
// look like they are switched | |
// so we gotta match them in the right order | |
// fuck that, different fields used. | |
String[] pat1 = new String[]{"aload 1", "aload 0", "getfield " + cn.name + ".*" + fdesc, "getfield .*" + fdesc, "putfield .*" + fdesc}; | |
String[] pat2 = new String[]{"aload 1", "aload 0", "getfield " + cn.name + ".*" + fdesc, "putfield .*" + fdesc}; | |
String desc = "(L" + dual().name + ";)V"; | |
for(MethodNode m : cn.methods) { | |
if(m.desc.equals(desc)) { | |
AbstractInsnNode ain1 = pointOf(m, pat1).instruction(); | |
AbstractInsnNode ain2 = pointOf(m, pat2).instruction(); | |
if(ain1 != null && ain2 != null) { | |
FieldInsnNode fin = (FieldInsnNode) ain1.getNext().getNext().getNext(); | |
if(fin.name.equals(next.obfuscated())) { | |
list.add(asMethodHook(m, "insertHead")); | |
} else if(fin.name.equals(prev.obfuscated())) { | |
list.add(asMethodHook(m, "insertTail")); | |
} else { | |
throw new RuntimeException(); | |
} | |
} | |
} | |
} | |
return list; | |
} | |
} | |
/* (non-Javadoc) | |
* @see org.nullbool.api.analysis.ClassAnalyser#registerFieldAnalysers() | |
*/ | |
@Override | |
protected Builder<IFieldAnalyser> registerFieldAnalysers() { | |
System.out.println("queue is: " + getFoundClass().name); | |
return new Builder<IFieldAnalyser>().addAll(new HeadFieldAnalyser()); | |
} | |
/* (non-Javadoc) | |
* @see org.nullbool.api.analysis.ClassAnalyser#registerMethodAnalysers() | |
*/ | |
@Override | |
protected Builder<IMethodAnalyser> registerMethodAnalysers() { | |
return new Builder<IMethodAnalyser>().addAll(new GetRemoveMethodAnalysers(), new InsertMethodsAnalyser()); | |
} | |
/* (non-Javadoc) | |
* @see org.nullbool.api.analysis.ClassAnalyser#registerMultiAnalysers() | |
*/ | |
@Override | |
public Builder<IMultiAnalyser> registerMultiAnalysers() { | |
// TODO Auto-generated method stub | |
return null; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment