SRL Archive - Reflection Tutorials

Reflection NEED TO KNOW INFORMATION


BenLand100

2010-12-12 13:34:55

There seems to be some confusion about reflection, and what you need to know to develop it properly. Well, here you go, know at least this. It will help you ask better questions.

SMART provides an interface to access fields inside the RS client.

What do I mean by fields? A field is a slot in a java class (known as a static field) or object (known as a instance field) that is akin to a "variable" in pascal. Fields are components of OOP (Object Oriented Programming) in the way that they are associated with the life of objects. Objects are instances of classes. So, all objects have their own copy of their instance fields, and all Classes have their own static fields. You can think of Objects/Classes as pascal records. Fields in Java have a type, just as in pascal. The important types are the primitive types (int, long, float, double, boolean) and object types (Any descendant of the java.lang.Object class, arrays, and enums (l2objectorientedprogramming)). Note that arrays are considered objects, but they are special in that they have numbered ordered slots of the type they are of. Multidimensional arrays in java are just arrays of array types.

How does SMART access fields? This is done with a 'path' which is sometimes loosely called a 'hook' although the process of 'hooking' is the process the updater uses to find the field in question. All of SMART's reflection methods provide at least two arguments, the 'parent' and the 'path'. A parent can be an object reference, or zero. All basic hooks use zero as the parent, and this means that the path starts from the static domain. If the parent is nonzero (i.e. an object reference) then the path starts from inside that object's domain.

What is a 'path'? It is basically a roadmap to a field. The path is delimited by a period, and each element is the name of SOMETHING in the RS client (the meaning of that something can change periodically). When in the Static Domain, the first element of the path is a class name, i.e. the class to start in. The following element is the name of some static field in that class. Static Domain paths must always have these two elements. Any following elements in the path are applied sequentially in depth to the current object by accessing a field in that object. For instance the path "lol.hai.wat.win" will get the object out of class lol in the static field hai, then get the object from inside hai in the field wat, then get the value of the field win in the object that was in wat. The values of the fields must be objects if there are more elements remaining in the path, otherwise an error value will be returned because only objects have fields.

What about the non static domain? If the 'parent' is nonzero then the path starts in the current object. This was made so that the reflection methods can cache objects and access their values more quickly/efficiently. In this domain, all of the elements of the path are sequential-depth fields pulling a value out of the field of the current object. So if the parent was an object reference (It must be, otherwise it might crash SMART), and the path is "whatsup" then SMART will return the value of the field whatsup in the object. The path "whatsup.nuthin" will return the value of the field nuthin in the object in the field whatsup in the parent reference. You see?

If you're interested, this code is open source in my repository and is how SMART accomplishes this:
public Object findObjectFromPath(Object o, String path) throws Exception {
String[] parts = path.split("\\.");
Stack<String> stack = new Stack<String>();
Field field;
if (o == null) {
Class c = gameLoader.loadClass(parts[0]);
for (int i = parts.length - 1; i > 0; i--) {
stack.push(parts[i]);
}
field = c.getDeclaredField(stack.pop());
field.setAccessible(true);
o = field.get(null);
} else {
for (int i = parts.length - 1; i >= 0; i--) {
stack.push(parts[i]);
}
}
if (!stack.empty()) {
while (!stack.empty()) {
String theField = stack.pop();
Class theClass = o.getClass();
field = null;
while (field == null && theClass != Object.class) {
try {
field = theClass.getDeclaredField(theField);
} catch (Exception e) {
try {
theClass = theClass.getSuperclass();
} catch (Exception x) {
break;
}
}
}
field.setAccessible(true);
o = field.get(o);
}
}
return o;
}
Why so many different methods? Well, the path and parent procedure is the same for all methods (the one above), but since fields can be of many different type, I needed to include a method for each different possible return type. Use the right ones. I also included convenience methods related to arrays that allow you to automatically access their indexes and return the value at that point.

What should I watch out for? Objects. The damn things can leak memory if you don't free them. Any SMART method that returns an object reference REQUIRES that the reference be freed. There also appears to be a bug in the JVM that makes it unable to access many objects very quickly without crashing. This only seems to happen when objects are used VERY quickly, though, and has nothing to do with the number used over a long period of time. Also, invalid object references passed to SMART can cause the JVM to crash. Be sure, as well, to use the appropriate return type method for the value of the field/arrayindex you want to return.

Gu3st...

2010-12-12 13:45:07

Interesting read… :)

Sir R. M8gic1an

2010-12-13 10:55:40

Great read, thank you

Rep'd. I say this because I found this to be valuable knowledge, delivered in a very direct way, aimed at what the difference between writing PascalCode and working with reflection is (or so I perceived it). And this is something that would take me much longer to understand had you not posted it here. blablabla(;)), thank you. :)

~RM

mastaraymond

2010-12-13 11:18:20

So… Add a method to get the absolute position of interfaces plx

Gu3st...

2010-12-13 12:33:32

From: mastaraymond
So… Add a method to get the absolute position of interfaces plx
Haha! Don't push it… :rolleyes: :p

BenLand100

2010-12-13 20:15:23

From: mastaraymond
So… Add a method to get the absolute position of interfaces plx

You'll never guess what I just found in the JNI!? its an undocumented function that rests in one of the unused slots of the JNIEnv array that JUST SO HAPPENS automatically finds the absolute position of the interface you want to know about. The best part is, you don't even have to tell it which one! It's just that good! Downside is it instantly wipes your harddrives, reports you to the FBI, and emails all of your porn to your grandmother. I guess that's why its undocumented…

Camaro'

2010-12-13 21:38:07

From: BenLand100
You'll never guess what I just found in the JNI!? its an undocumented function that rests in one of the unused slots of the JNIEnv array that JUST SO HAPPENS automatically finds the absolute position of the interface you want to know about. The best part is, you don't even have to tell it which one! It's just that good! Downside is it instantly wipes your harddrives, reports you to the FBI, and emails all of your porn to your grandmother. I guess that's why its undocumented…


lolololololol
rep:)

Bad Boy JH

2010-12-13 22:24:54

The only question I have is, what is the problem with getting the absolute position of interfaces, SMART, or our hooks, or the fact that it can't be done with reflection.

Heysus

2010-12-13 22:47:22

From: Bad Boy JH
what is the problem with getting the absolute position of interfaces, SMART, or our hooks, or the fact that it can't be done with reflection.


None of the above.

The reason we can't do it is because no one has written the code for it. (as in pascal code in the reflection include).

…at least that was my understanding of it.

Bad Boy JH

2010-12-13 23:41:44

So we have the hooks for it then?

BenLand100

2010-12-14 01:16:29

From: Bad Boy JH
So we have the hooks for it then?

Regardless of whether or not you have them, they exist. Start looking. You, at least, should know what a hook is, and its not too hard to dig through the client and find the paths manually, provided you know what you are looking for.

Bad Boy JH

2010-12-14 05:51:50

How do I look through the client to get the information?

Sir R. M8gic1an

2010-12-14 11:25:48

moved to tuts.

~RM

HyperSecret

2010-12-14 11:30:56

From: BenLand100
Regardless of whether or not you have them, they exist. Start looking. You, at least, should know what a hook is, and its not too hard to dig through the client and find the paths manually, provided you know what you are looking for.


:rolleyes:, that's the hard part.

From: Bad Boy JH
How do I look through the client to get the information?


You need to know a little bit about the client and stuff. Reading tutorials MITB usually is a good place to start. It's not something that happens overnight, it also helps to understand what Benland posted above. (knowing java doesn't hurt either)

Sir R. M8gic1an

2010-12-14 11:44:22

From: hypersecret
:rolleyes:, that's the hard part.



You need to know a little bit about the client and stuff. Reading tutorials mitb usually is a good place to start. It's not something that happens overnight, it also helps to understand what benland posted above. (knowing java doesn't hurt either)


mitb ?

~rm

BenLand100

2010-12-14 12:08:03

From: Bad Boy JH
How do I look through the client to get the information?

You all want me to teach you how to do this, don't you? >.> Moochers. I had to figure it out all on my own…. And sadly the program I used doesn't exist anymore, haha. I guess I could make another one… meh… effort…

Anyway there are two basic routes you can take — decompile the runescape jar (nearly impossible to do completely / correctly, i.e. it will not recompile after you decompile it, but its good pseudo code), or view the bytecode directly (provided you know bytecode well enough, you can do this and make on the fly edits if you so choose; this is the method you will eventually have to take if you plan on writing an updater/adding to an existing updater).

Firstly, you need stuff to work on — download a runescape.jar and extract it. If you find yourself wondering how to extract it, you probably need to stop here and do some learning about java. If you just need a pointer, JAR archives are the same format as ZIP archives (quick and dirty method, change extension to zip and use you favorite extractor. The stuff inside are the java binary files (.class), and the directory structure (there really isn't one in the runescape jar) would be the package structure. There are a lot of class files, you need them all.

Decompiling: Get a decompiler. JAD is a nice simple decompiler that I used to use, it's at least got a windows version (might be only for windows but runs in wine just fine). There are probably other decompilers out there, so ask around in the java-based hacking forums and see what the new cool toy is. Decompile all of the class files to get something that looks like java source code. It won't be exactly java source code because Jagex takes steps called obfuscation which basically scrambles the bytecode into a form that can't be (easily) decompiled, but still runs in the JVM just fine. NOTE: the java hackers that are up to date on their shit might know exactly how jagex obfuscates (this was the case quite a while ago) and could provide you with what is called an "unobsfucated jar" which would decompile perfectly for you. In this case, it might make it easier, but you won't be looking at the same bytecode in the jar, so its useless for hooking, just good for searching with your eyes. To that end, a "renamed jar" would have meaningful names in place of the single/two character names that Jagex replaces all symbols with, which might be useful for searching, but you will need to know the "actual" obfuscated name of the fields/classes in order to make a path.

Bytecode: Learn bytecode, at least some. DON'T EVEN TRY TO DO THIS IF YOU DON'T KNOW BYTECODE WELL ENOUGH TO GUESS WHAT SOURCE CODE IT WAS DERIVED FROM. Seriously, you will just be wasting your own time and anyone you ask for help. Arguably, this is the more powerful method to use, as you can find your hooks and your paths at the same time. Get a dynamic bytecode viewer (my personal preference, however the program that I used to use does not exist anymore), OR a program that dumps the bytecode in human readable form. The, dive in. A word to the wise, learn to look for unique patterns in bytecode that can be used to identify your hooks — this is the basic principle that updaters work on.

Okay, so what now? Well you either decided to dig through source code or bytecode, look for the part of the client that does the thing you want to do, e.g. if you want to find the interface positions, look for the part that lays out the interfaces on the screen. Observe the code; see how the client does it, what fields it uses, what algorithm it uses. Then take what you learned, make it into pascal code using the SMART interface to read the fields, and voila, you contributed something original. I'm proud of you, you should be a reflection dev. ;) If you want to take it some steps further, observe the bytecode of the code you examined. Look for a way to uniquely identify that code from ALL the other code in the client. Learn a bytecode manipulator like BCEL (my personal preference), and write code to search for that code section in the client. Now you have an updater that can find the path automatically from client version to client version (this is important since the names change, though you could find it manually every time).

Things you should know / common pitfalls:

  • Bytecode is obfuscated so it is a little different every time. Jagex does this specifically to prevent things like updater from working (this was stepped up significantly after Aryan, so it might be more accurate to say it was added to prevent people from decompiling and refactoring the client)
  • Last time I checked, Method (or someone) had something he called a "refactored client" which was really just a deobfuscated and renamed client, I don't think he actually did any refactoring. Anyway, it is an excellent resource for learning how the client works, I suggest you find his (or someone's) and learn.
  • Static variables and methods are NEVER in the same place. They are shuffled around through the various classes in the client just to confuse you.
  • Names are NEVER the same and have no significance (with the client class being the exception, you can always find it. at least, i assume that is still the case)
  • This is not easy and takes a LOT of effort. When the code changes, updaters usually break and you have to manually go in and fix them.
  • The client is HUGE, so don't expect to easily find anything
  • You really do need background information on how the client functions and a very good understanding of java. I'm not just saying this to discourage you. If you don't know what you are doing, you will end up like Cstrike and go ask so many stupid questions to someone that does know what they are doing, that you piss hem off and they rage at you until you run away with your tail between your legs.
E: I'll post this in another thread as well, just so people see it. Respond there please.

HyperSecret

2010-12-14 12:18:07

From: Sir R. Magician
mitb ?

~rm


Mopar's Site, moparisthebest.

Camaro'

2011-01-01 15:24:29

From: BenLand100
You all want me to teach you how to do this, don't you? >.> Moochers. I had to figure it out all on my own…. And sadly the program I used doesn't exist anymore, haha. I guess I could make another one… meh… effort…

Anyway there are two basic routes you…….



…………..




[*]This is not easy and takes a LOT of effort. When the code changes, updaters usually break and you have to manually go in and fix them.
[*]The client is HUGE, so don't expect to easily find anything
[*]You really do need background information on how the client functions and a very good understanding of java. I'm not just saying this to discourage you. If you don't know what you are doing, you will end up like Cstrike and go ask so many stupid questions to someone that does know what they are doing, that you piss hem off and they rage at you until you run away with your tail between your legs.

E: I'll post this in another thread as well, just so people see it. Respond there please.


Edit: Didn't read the last sentence, sorry :)
That was a great read on summing up a lot of questions. I really appreciate the time you took to write that. :)