asm rsps client hacking pt 2

Upload: evan-zaruba

Post on 02-Jun-2018

212 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/10/2019 Asm Rsps Client Hacking Pt 2

    1/6

    Welcome!

    If you haven't already done this, please visit Part 1 before continuing on withPart 2:> Part 1

    Special credits to Divine whom's information has helped completed my adapters!

    Setup

    From this part onward, we will be using ASM. If you have yet to learn ASM, it'shighly recommended that you learn bytecode and the JVM specifications.

    Here's the website (get the external JARs and add them to your project):

    http://forge.ow2.org/projects/asm/

    You could also find a guide on how to use ASM in that link, so read it if you haven't already. This will take you a while, so it's recommended that you completely read both of the APIs, or atleast the Core API.

    If you're done, let's get started!

    2.1 - Abstract Class Transform

    In order to get started with injection, we must build the basic components of it. First off, we need to create an abstract class that would "hold" our methods for the transformations that we need to make.

    Create an abstract class called "AbstractClassTransform". After that, we need tocreate a method that reads a given class file from a given jar. Recall from theprevious part that we needed to inject "accessor methods" in order to get the values from the program we want. Create a "setup" method that does this (for learning purposes). It should look similar to this:

    public abstract class AbstractClassTransform {private static String clazz;

    private static String theJar;public void setup(final String theJar, final String clazz){this.theJar = theJar;this.clazz = clazz;}}

    We can't just directly manipulate the class' bytecode within this class. That will just create a mess. We need to create adapters that do this for us, and all we need to do is to use them with given parameters. Leave this class aside, as wewill come back to it.

    2.2: Adapters Explained

    What are adapters?

    Adapters act as our "filter" for the ClassVisitor passed as our argument. Remember that a simple ClassVisitor "goes over" nearly everything contained within theclass given by a ClassReader in the following order:

    visit visitSource? visitOuterClass? ( visitAnnotation | visitAttribute )*( visitInnerClass | visitField | visitMethod )*

  • 8/10/2019 Asm Rsps Client Hacking Pt 2

    2/6

    visitEndNote: "|" means 'or'.

    Adapters are used to mark the transformations of a class using the Core API. TheTree API, however, calls their adapters transformers.They can be used just like adapters, but in a different way.

    Note that the adapters DO NOT DIRECTLY MANIPULATE BYTECODE! This is where most people go wrong while creating transformation classes. So please note this!

    2.3: Creating the GetterAdapter

    The "accessor methods" that we use to return fields are called "getters" (nothing new here). So create a new class, preferably under an adapter package, and call it "GetterAdapter". It needs to be subclass of ClassVisitor. Remember that alladapters are based on the ClassVisitor class. Implement the Opcodes provided byASM.

    There is a default constructor needed, which is a ClassVisitor. We're using ASM-4 (because that's the latest version) so we need to put that constant in as well. It should look like this:

    import org.objectweb.asm.ClassVisitor;import org.objectweb.asm.Opcodes;

    public class AddGetterAdapter extends ClassVisitor implements Opcodes {

    public AddGetterAdapter(final ClassVisitor cv){ //Need this for all adapters that use the Core API!super(ASM4, cv); //Need this for all adapters that use the Core API!}

    }The superclass's constructor is the basis of all Core API adapters.

    Now we need the following information in order to let the ClassVisitor class know what to look for and what to change. Remember that a "getter" should return th

    e variable that we want.

    So the logic we need to follow while creating this adapter:

    -> Find the variable (a field):Get the name of the field. If it matches what's given, then remember that it exists (as the methods in ClassVisitor are recursive, excluding visitEnd).Check to see if the type descriptors of the field match what's given (descriptors are the type of the method in COMPILED FORM)Type Descriptors:

    boolean -> Zchar -> C

    byte -> Bshort -> Sint -> Ifloat -> Flong -> Jdouble -> DObject -> Ljava/lang/Object;int[] -> [IObject[][] -> [[Ljava/lang/Object;

  • 8/10/2019 Asm Rsps Client Hacking Pt 2

    3/6

    -> Check to see if the method's name already exists from the list of methods ofthe class (done recursively) (you don't want to create a method with the same name).If it doesn't exist, create the method.So lets gather the information in our class (self-explanitory):

    import org.objectweb.asm.ClassVisitor;import org.objectweb.asm.Opcodes;

    public class AddGetterAdapter extends ClassVisitor implements Opcodes {

    private String fieldName = null;private String getterName = null;private String fieldDescriptor = null;private String signature = null; // i.e. genericsprivate String targetClazz = null;private boolean isFieldPresent = false, isInterface = false, isMethodPresent = false;private int varInsn, retInsn; //will need this for later!

    public AddGetterAdapter(final ClassVisitor cv, final String fieldName, final String fieldDescriptor, final String getterName, final String targetClazz, final int varInsn, final int retInsn) {

    super(ASM4, cv);this.fieldName = fieldName;this.getterName = getterName;this.targetClazz = targetClazz;this.varInsn = varInsn;this.retInsn = retInsn;this.fieldDescriptor = fieldDescriptor;}}So first, you need to check if the field is present. We will also need to get its generics if it has any (which in most clients, it shouldn't).This can be done in the visitField method:

    @Overridepublic FieldVisitor visitField(int access, java.lang.String name, java.lang.String desc, java.lang.String signature, java.lang.Object value){

    if(name.equals(fieldName) && desc.equals(fieldDescriptor)){isFieldPresent = true;this.signature = signature;

    }return null;

    }(Recall the order of the methods called if you need to)

    We also don't want to write a method that exists in the class (i.e. writing thesame method twice) with the same parameters.@Override

    public MethodVisitor visitMethod(int access, String name,String

    desc, String signature, String[] exceptions) {if (name.equals(getterName) && desc.equals(fieldDescriptor)) {

    isMethodPresent = true;}return null;

    }When everything is parsed, then you need to go to the visitEnd method, and makethe changes to the ClassVisitor passed in our constructor's parameters (i.e. a C

  • 8/10/2019 Asm Rsps Client Hacking Pt 2

    4/6

    lassReader or another adapter). Remember that the visitEnd method is called onlyONCE!

    So first, we need to create a MethodVisitor object using the ClassVisitor passedfrom the constructor's parameters using the information we have. We do this ONLY if the field exists, AND if the method doesn't.

    We need to visit its code so that way, it is recorded by the ClassVisitor.We then need to insert our bytecode instructions.

    When explained in words:Create a variable 0 space on the operand stack of the xType (remember the special cases; e.g. byte -> integer when it's placed on the stack)Get the field that we want to get and place it on the stack.Return the the result on the stack.We then need to "close" the record by calling the MethodVisitor's visitEnd method, then "close" the record of the ClassVisitor by doing the same.

    The result:@Overridepublic void visitEnd(){

    if(isFieldPresent && !isMethodPresent){MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, getterName, "()"+

    fieldDescriptor, signature, null);

    mv.visitCode();mv.visitVarInsn(varInsn, 0);mv.visitFieldInsn(GETFIELD, targetClazz, fieldName, fieldDescri

    ptor);mv.visitInsn(retInsn);mv.visitEnd();if(mv != null){

    mv.visitEnd();}

    } else {cv.visitEnd();

    }cv.visitEnd();

    }Now your class should look like this:import org.objectweb.asm.*;/*** Adds a method of a given accessor that returns the given field.* @author trDna*/public class AddGetterAdapter extends ClassVisitor implements Opcodes {

    private String fieldName = null;private String getterName = null;private String fieldDescriptor = null;private String signature = null;

    private String targetClazz = null;private boolean isFieldPresent = false, isInterface = false, isMethodPresent = false;private int varInsn, retInsn;

    public AddGetterAdapter(final ClassVisitor cv, final String fieldName, final String fieldDescriptor, final String getterName, final String targetClazz, final int varInsn, final int retInsn) {

    super(ASM4, cv);this.fieldName = fieldName;

  • 8/10/2019 Asm Rsps Client Hacking Pt 2

    5/6

    this.getterName = getterName;this.targetClazz = targetClazz;this.varInsn = varInsn;this.retInsn = retInsn;this.fieldDescriptor = fieldDescriptor;

    }

    @Overridepublic FieldVisitor visitField(int access, java.lang.String name, java.lang.String desc, java.lang.String signature, java.lang.Object value){

    if(name.equals(fieldName) && desc.equals(fieldDescriptor)){isFieldPresent = true;this.signature = signature;

    }return null;

    }@Overridepublic MethodVisitor visitMethod(int access, String name,

    Stringdesc, String signature, String[] exceptions) {

    if (name.equals(getterName) && desc.equals(fieldDescriptor)) {isMethodPresent = true;

    }return null;

    }@Overridepublic void visitEnd(){

    if(isFieldPresent && !isMethodPresent){MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, getterName, "()"+

    fieldDescriptor, signature, null);mv.visitCode();mv.visitVarInsn(varInsn, 0);mv.visitFieldInsn(GETFIELD, targetClazz, fieldName, fieldDescri

    ptor);mv.visitInsn(retInsn);mv.visitEnd();if(mv != null){

    mv.visitEnd();}} else {

    cv.visitEnd();}cv.visitEnd();

    }}Congratulations! You have built your first adapter. It modifies the ClassVisitorobject (usually ClassWriter or another adapter, containing a ClassReader's parsed bytecode of a given class) by finding the variable, and returning it using amethod that we give it.

    We will need another adapter to add in the interface as well (which will be covered on the next part).

    We will go deeper, and come back to our AbstractClassTransform. There, I will show you where the injection happens

    I'll type up the next tutorial soon.

    My Repo Link (for people who want to look ahead): https://github.com/t.../master/com/dna

  • 8/10/2019 Asm Rsps Client Hacking Pt 2

    6/6

    Part 3 Link: Here

    Hope you found the tutorial informative so far