SRL Archive - Reflection Tutorials

An Introduction to Client Hacking for the Java Impaired


Echo_

2011-03-08 11:00:14

Have you ever wondered how reflection actually works? Have you ever wanted to know how software like RSBot and SMART is created? Maybe your just bored and need something to read? If any of the above statements are true, then keep reading :)

History


Client hacking in Runescape has taken an interesting path over the years. People have become famous in the RS cheating communities for their work with the client. Jagex has tried to make their client harder to mess with but the client hackers are always one step ahead. Take Aryan for example. Aryan was a hacked client used for botting a few years ago. What had to be done to create this bot? Well, all the bot developers had to do was decompile the client, find the fields they needed to auto, write a bot to work off of those fields, and recompile the client :p Jagex eventually got wise and started obfusicating their code. Obfusification is moving and renaming code so that it is hard to read and understand what the client is doing. I won't go much more into history, BenLand100 has a great topic on it here. So this brings us to the current age of client hacking, with the use of hooks, updaters, and injectors.

The Client


For this section, you will need:
A Java decompiler - link
A copy of the client - link
WinRar (optional) - link

The first step of hacking the client is getting the client. After you have downloaded a copy, it's time to take a peek at the code. Create a new folder to house all of the files from the client, then use WinRaR to extract the files from the jar to that folder. You can also just change the file extension from .jar to .zip then extract the files from there. You will now have a folder full of cryptically named class files and a few folders from the client. Now is the time to use the decompiler. Open up JD-GUI, find the location of the extracted files, and open one up. It will load all of the classes in the folder to the left panel and the class that you are viewing into the right panel. I will open up wq.class. Keep in mind the classes will change after every update, so I will include the client I used in the tut in a download link at the end of the tutorial.


Ugly, isn't it? The static modifier just means that the field isn't associated with an individual object, it is associated with the entire class of objects. The private modifier means that the field cannot be accessed by other classes. Just try to think about it from a Pascal perspective, I know most of the people in this community more comfortable with that than Java.


That's a little better. Anyways, this is Jagex's client obfusication. Now, you may be wondering, "How am I supposed to do anything with this?". The logic is simple. You want to be able to use the fields to return data to your bot. Fields are like variables in Pascal, they hold values. The only way to figure out which is which is by finding patterns and functions that the fields are used in. Fortunately, all of the hard work has been done by earlier bot developers, and you can just find what you are looking for by studying their hook updates. Here's an example:

We want to find the SoftReference class in the client so that we can return its value to our bot. By looking at patterns within the client, earlier developers have found that the SoftReference class is the only class in the entire client to reference java.lang.ref.SoftReference. So we have to loop through every class to find a field of the java.lang.ref.SoftReference type or even search for a UTF8 constant related to java.lang.ref.SoftReference in order to find the SoftReference class. After hooking SoftReference, you can easily hook Reference, NodeSub, and Node because they are all part of a class hierarchy ending with SoftReference.

Those are the kind of patterns you are looking for, something to make the field distinguishable from every other field in the client. Now it's time to start coding. You will now have to write a hook updater that can find the fields you want dynamically, or else you will have to search through the client's 820 different class files by hand. I don't know about you, but I would go insane doing something like that. This is where BCEL becomes your best friend. BCEL stands for Bytecode Engineering Library, and contains many useful functions for editing Java bytecode. If you don't already know, Java bytecode is the code Java is converted to after compilation, and is executed by the Java Virtual Machine at runtime. All editing of the client has to be done via bytecode. Decompiling the client, editing it, then recompiling it hasn't worked since Aryan, remember?

Using BCEL


For this section, you will need:
An IDE, I will be using Eclipse- Link
If you want to test these out but can't get them to work on your own, I will include the source code from my examples at the end of the tutorial.

Here's where we make our first simple field finder! Let's say that I have found field "kf.m" to represent the field "pixelX". So I go to the class "kf" and look for field "m".


Well, that makes sense! Of course the class containing a field about pixel arrangement would also need to import java.awt.canvas! A canvas is pretty much a java frame that can react to user input, so the part of the Runescape client we see and click while playing is called the canvas. So now that we have found the field, we want to be able to find it without any human intervention. Here is what you would use to find it. Don't worry, I will explain everything used in this snippet.

import org.apache.*;
import org.apache.bcel.*;
import org.apache.bcel.classfile.*;
import org.apache.bcel.generic.*;
import org.apache.bcel.util.*;
import org.apache.bcel.verifier.*;
import org.apache.bcel.verifier.exc.*;
import org.apache.bcel.verifier.statics.*;
import org.apache.bcel.verifier.structurals.*;

import java.io.IOException;

/**
*
* simple pixelX field searcher
* @author: Echo_
*
*/
public class FieldSearcher {
private ClassGen cGen;

public FieldSearcher() {
loadClass();
search();
dumpClass();
}

private void loadClass() {
try {
cGen = new ClassGen(new ClassParser("kf.class").parse());
} catch (ClassFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

private void search() {
for(Field f : cGen.getFields()) {
if(f.getName().equals("m")) {
System.out.println("Found pixelX!");
break;
}
}
}

public void dumpClass() {
try {
cGen.getJavaClass().dump("kf.class");
}
catch(IOException ex) {
ex.printStackTrace();
}
}

public static void main(String[] args) {
new FieldSearcher();
}
}

Alright, we will go through this step-by-step. First is this:

                        cGen = new ClassGen(new ClassParser("kf.class").parse());

This loads the class into a ClassGen, you have to do this for any class that you try to search through or edit.

                for(Field f : cGen.getFields()) {
if(f.getName().equals("m")) {
System.out.println("Found pixelX!");
break;

This is the really cool bit of code. It takes the class loaded into ClassGen, iterates through every field in the file, and prints out a message if it finds the field.

                        cGen.getJavaClass().dump("kf.class");

This piece simply dumps the class after it has been messed with. It's just like bitmaps and DTMs in your scripts, they always have to be freed after use to prevent memory leaks :)

If you set this up and run it on the kf class, you should get this in the prompt after execution.

Found pixelX!

Hooray, you made your first BCEL class! Keep in mind though, this searching method would never be used in an updater for obvious reasons. It relies on a field name to find the field, and the names change after every update. Eventually your BCEL classes will look a little something like this, although this is also a simple class. Yours would likely loop through every class in the client instead of loading just one class at a time, but it's still a good example.

import org.apache.*;
import org.apache.bcel.*;
import org.apache.bcel.classfile.*;
import org.apache.bcel.generic.*;
import org.apache.bcel.util.*;
import org.apache.bcel.verifier.*;
import org.apache.bcel.verifier.exc.*;
import org.apache.bcel.verifier.statics.*;
import org.apache.bcel.verifier.structurals.*;

import java.io.IOException;

/**
*
* more advanced pixelX field searcher
* @author: Echo_
*
*/
public class FieldSearcher {
private ClassGen cGen;

public FieldSearcher() {
loadClass();
findField();
dumpClass();
}

private void loadClass() {
try {
cGen = new ClassGen(new ClassParser("kf.class").parse());
} catch (ClassFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

private void findField() {
for(Field f : cGen.getFields()) {
if(f.getType().equals(Type.INT)) {
System.out.println("possible baseX field = '" + f + "'");
}
}
}

public void dumpClass() {
try {
cGen.getJavaClass().dump("kf.class");
}
catch(IOException ex) {
ex.printStackTrace();
}
}

public static void main(String[] args) {
new FieldSearcher();
}
}

If you run this successfully, you should get this in the prompt box.

possible baseX field = 'int h'
possible baseX field = 'static int i'
possible baseX field = 'int j'
possible baseX field = 'static int l'
possible baseX field = 'int m'
possible baseX field = 'static int n'
possible baseX field = 'int o'
possible baseX field = 'int q'
possible baseX field = 'int r'
possible baseX field = 'static int t'
possible baseX field = 'static int z'

Cool huh? It found every integer field in the class :) The point I was trying to teach in this snippet was this piece:

        		if(f.getType().equals(Type.INT)) {

These type of statements are the key to finding fields dynamically. You narrow down the searches until only one field matches the criteria: the field you want for your bot. More functions for you to use in your BCEL classes can be found in the BCEL Documentation.

Injection


Now that you understand how BCEL works, you can properly understand the different kinds of bots. The two types of bots that rely upon client hacking are reflection bots and injection bots. We will discuss injection first. Most of you guys know about RSBot right? Well RSBot is an injection bot. You may be wondering, "What the hell does injection mean?". Injection is a technique used by bot developers to return the values of fields to their hooks during runtime. This allows for scripts to make decisions depending on the state of a field at any given time. Let's take a look at how it works.

import org.apache.*;
import org.apache.bcel.*;
import org.apache.bcel.classfile.*;
import org.apache.bcel.generic.*;
import org.apache.bcel.util.*;
import org.apache.bcel.verifier.*;
import org.apache.bcel.verifier.exc.*;
import org.apache.bcel.verifier.statics.*;
import org.apache.bcel.verifier.structurals.*;

import java.io.IOException;

/**
*
* pixelX accessor method injector
* @author: Echo_
*
*/
public class Injector {
private ClassGen cGen;

public Injector() {
loadClass();
injectMethod();
dumpClass();
}

private void loadClass() {
try {
cGen = new ClassGen(new ClassParser("kf.class").parse());
} catch (ClassFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

private void injectMethod() {

cGen.addInterface("Animable");

for(Field f : cGen.getFields()) {
if(f.getName().equals("m")) {
System.out.println("Found pixelX!");
break;
}
}

InstructionList methodIList = new InstructionList();
ConstantPoolGen theCPool = cGen.getConstantPool();
MethodGen pixelXMethod = new MethodGen(Constants.ACC_PUBLIC,Type.INT,Type.NO_ARGS,new String[]{},"pixelX",cGen.getClassName(),methodIList,theCPool);

InstructionFactory iFactory = new InstructionFactory(cGen,theCPool);
Instruction pushThis = new ALOAD(0);
Instruction pixelXField = iFactory.createFieldAccess(cGen.getClassName(),"m",Type.INT,Constants.GETSTATIC);
Instruction returnPixelX = InstructionFactory.createReturn(Type.INT);

methodIList.append(pushThis);
methodIList.append(pixelXField);
methodIList.append(returnPixelX);

pixelXMethod.setMaxStack();
pixelXMethod.setMaxLocals();

cGen.addMethod(pixelXMethod.getMethod());

System.out.println("Accessor method injected into " + cGen.getClassName() + ".");
}


public void dumpClass() {
try {
cGen.getJavaClass().dump("kf.class");
}
catch(IOException ex) {
ex.printStackTrace();
}
}

public static void main(String[] args) {
new Injector();
}
}

If you run this, you should get this in the prompt:

Found pixelX!
Accessor method injected into kf.

So, what the hell just happened? Well, let's take a peek at the kf class now, and I will explain further.


And you should see this towards the bottom:


What our injector did was implement an interface called Animable (this will be our hook) and added an accessor method for the field m. Notice the method is returning the value of m? It's just like a function in Pascal, it is returning the value of that variable whenever the function is called. So now that we know it is returning a value, we need to make something for the value to return to. This is what we refer to as hooks. It's easier than it sounds.

public interface Animable {

public int pixelX();
}

This interface will "hold" the value of the field in a class that is outside of the client. So how does this help us? Let's say you want your script to do something when pixelX is in a certain state. Your script would look kind of like this:

if (pixelX = state) then
begin
Action1;
end else
if not (pixelX = state) then
begin
Action2;
end;

Now that you understand the point of accessor methods, I think it's time to explain my injection snippet. It looks similar to my field searcher, but with a few modifications for method creation.

    		InstructionList methodIList = new InstructionList();
ConstantPoolGen theCPool = cGen.getConstantPool();
MethodGen pixelXMethod = new MethodGen(Constants.ACC_PUBLIC,Type.INT,Type.NO_ARGS,new String[]{},"pixelX",cGen.getClassName(),methodIList,theCPool);

As you can see, these are just constructors we have to call before we can create the accessor method. In Java, you can't just use an object out of the blue, you have to construct it first. An instruction is a feature of Java bytecode, it pretty much invokes the procedure. We don't see it in Java itself, just in the bytecode. The constant pool is just the list of fields in the class. The method gen is a BCEL feature that creates a custom method for you to add to the bytecode. You customize it through the parameters, the possibilities for different methods are endless.

    		InstructionFactory iFactory = new InstructionFactory(cGen,theCPool);
Instruction pushThis = new ALOAD(0);
Instruction pixelXField = iFactory.createFieldAccess(cGen.getClassName(),"m",Type.INT,Constants.GETSTATIC);
Instruction returnPixelX = InstructionFactory.createReturn(Type.INT);


The next few lines are also constructors, I will explain their meanings as well. Since you have created a methodIList earlier, it's time to put instructions in the list. pushThis is a reference to the bytecode stack theory, which I will explain in a moment. Instruction pixelXField is giving the new method access to our pixelX field, or m in the obfusicated class. Instruction returnPixelX allows for the new method to return the value of the method m.

    		methodIList.append(pushThis);
methodIList.append(pixelXField);
methodIList.append(returnPixelX);

These few lines are just adding our constructors to the method, so this is where the method really starts to be created.

    		pixelXMethod.setMaxStack();
pixelXMethod.setMaxLocals();

These are just clean up procedures, you have to run them every time you create a new method.

    		cGen.addMethod(pixelXMethod.getMethod());

And finally, our method is added to the class. Now I will explain the bytecode stack theory I mentioned earlier. Imagine a deck of cards. If you have a card and put it on top of the stack, which card will be the first to be drawn? The card on the top. So basically, this means the last piece of code added will be the first one to get invoked by the JVM. Here's a pic for you visual learners out there.


When you add something to the stack it is referred to as a "push". When you take something off of the stack, it is referred to as a "pop". I hope this helps you understand the "pushThis" method we saw earlier.

If you want to go further with injection, I would suggest using the ASM bytecode engineering library, its kept more up to date and will soon surpass BCEL in functionality. So that's about it for injection, on to reflection!

Reflection


So let's start out with the basics, "What is reflection?". Reflection is a feature exclusive to Java that allows programs to examine and give off information about their own behavior. Reflection is capable of inspecting this behavior at runtime. The reflection functions can be accessed in a program by importing java.lang.reflect. The cool thing about reflection is you can learn about a classes fields, methods, its superclass, and its name without even knowing the class name at the beginning! This allows for hackers to better understand the client without having to deal too much with the clusterf**k of Jagex's client obfusication. You can then use these "reflected" pieces of a class to return values of fields just like I explained in the Injection section. Here's a new snippet for reflection to run on the kf class. Keep in mind you will get errors if you don't run this on the entire client, so all of the classes should be in the same directory as this file.

import java.lang.reflect.*;

/**
*
* pixelX field reflector
* @author: Echo_
*
*/
public class FieldReflector {
public static void main(String[] args) {
try {
Class cls = Class.forName("kf");

Field fieldlist[] = cls.getDeclaredFields();
for (int i = 0; i < fieldlist.length; i++) {
Field fld = fieldlist[i];
System.out.println("name = " + fld.getName());
System.out.println("class = " + fld.getDeclaringClass());
System.out.println("type = " + fld.getType());
int mod = fld.getModifiers();
System.out.println("modifiers = " + Modifier.toString(mod));
System.out.println("-----");
}
}
catch (Throwable e) {
System.err.println(e);
}
}
}

If you run this successfully, you should get this in the prompt box:

name      = h
class = class kf
type = int
modifiers =
-----
name = i
class = class kf
type = int
modifiers = static
-----
name = j
class = class kf
type = int
modifiers =
-----
name = k
class = class kf
type = boolean
modifiers =
-----
name = l
class = class kf
type = int
modifiers = static
-----
name = m
class = class kf
type = int
modifiers =
-----
name = n
class = class kf
type = int
modifiers = static
-----
name = o
class = class kf
type = int
modifiers =
-----
name = p
class = class kf
type = byte
modifiers =
-----
name = q
class = class kf
type = int
modifiers =
-----
name = r
class = class kf
type = int
modifiers =
-----
name = s
class = class kf
type = boolean
modifiers =
-----
name = t
class = class kf
type = int
modifiers = static
-----
name = u
class = class kf
type = class kf
modifiers =
-----
name = v
class = class kf
type = class hda
modifiers = static
-----
name = w
class = class kf
type = byte
modifiers =
-----
name = x
class = class kf
type = class ht
modifiers = static
-----
name = y
class = class kf
type = class dia
modifiers = static
-----
name = z
class = class kf
type = int
modifiers = static
-----

Pretty cool, right? It returned the data about every single field in the class! This can be used in the exact same ways as we discussed earlier, finding fields and returning their values. That's pretty much it for reflection, you can learn more about it functions at the Java Reflection Documentation page.

Conclusion


Now that you know all of this information, you are now capable of becoming a client hacker! It's tough work at times, but I enjoy the challenge. If you find any mistakes or bugs or have any further questions, feel free to post them on this thread. I will answer them as quickly as i can. I will also put up all the source code for this tutorial so that you can study it. The Moparisthebest forums also have a plethora of information on client hacking, so be sure to take a look over there if you want to learn more.

Client Hacking tutorials on MITB - Link
Source code from my examples - Link

HyperSecret

2011-03-08 11:41:58

NICE! I have to give this stuff a try again. I have learned a lot more about programming/memory/etc.. since the last time I tried and I think it will be much easier.

Great contribution!

Nava2

2011-03-08 11:57:44

Definitely one of the most informative tutorials on the subject on Villavu. Well done! :)

Echo_

2011-03-08 13:39:21

Thanks guys :)

lordsaturn

2011-03-08 14:32:19

Very much needed! Thanks for your help ! :)

Floor66

2011-03-08 14:36:34

Awesome tut! Tut cup anybody? :P

Iamadam

2011-03-08 18:44:50

Well done for publishing.
I didn't read much… got up to
Ugly, isn't it? Static just means that it is a class constant, while private means that the field cannot be accessed by other classes. Just try to think about it from a Pascal perspective, I know most of the people in this community more comfortable with that than Java.
and had to reply :P

The static modifier is not the same as a class constant at all. Static just means the variable is not associated with an object. If something isn't static, you need to access it through its parent object - if it is, you can just access it like you would any class variable in pascal :)

Echo_

2011-03-09 08:22:53

From: Iamadam
Well done for publishing.
I didn't read much… got up to and had to reply :P

The static modifier is not the same as a class constant at all. Static just means the variable is not associated with an object. If something isn't static, you need to access it through its parent object - if it is, you can just access it like you would any class variable in pascal :)


Alright, I'll fix that. Thanks :)

weequ

2011-03-09 08:33:28

Looks great. I don't have time to read it now but I will for sure after march 23th :)

footballjds

2011-03-15 08:15:22

Wonderful Tutorial, i actually read the whole thing.
reads well, easy to understand, and straight forward.
grats,

Wanted

2011-03-15 18:25:04

Amazing.