Introduction To ByteCode Patterns

Discussion in 'Programming General' started by iJava, Nov 15, 2012.

Introduction To ByteCode Patterns
  1. Unread #1 - Nov 15, 2012 at 5:54 PM
  2. iJava
    Joined:
    Nov 21, 2011
    Posts:
    1,197
    Referrals:
    11
    Sythe Gold:
    485
    Discord Unique ID:
    220055593568829441

    iJava .Previously known as RSGoldRush
    $200 USD Donor New

    Introduction To ByteCode Patterns

    HUGE THANKS/CREDITS TO Static HE HELPED/TAUGHT ME ABOUT A LOT OF THIS.

    Thought I'd make this so people can understand how 'hooks' are found, I've done parts of this using the ASM 4.0 Lib. Basically when you compile your .java file it is compiled into bytecode which is then read by the JVM. More info can be found http://en.wikipedia....i/Java_bytecode


    For example this code :

    Code:
    public class test {
    
    public static String name = "Name";
    
    public String getName() {
    return name;
    }
    }
    Would look like this in Bytecode :

    Code:
    public class test {
    
    public static String name = "Name";
    
    public String getName() {
    aload_0 0
    getstatic String test.name
    areturn
    }
    }

    To view the bytecode I use a program called reJ, it can be found http://sourceforge.n...rojects/rejava/, now lets use this gamepack http://up.ht/QgU83Q. Open reJ and open the gamepack I provided you. Next we'll work in the client class so open up the client class and look in the editor tab, if we scroll to the bottom you will see a a few getters. We'll focus on getCurrentAction().

    As you can see it references the field client.pi so go to the top of the file and ctrl +f then type "pi". Now to iterate through the search you press f3, once you press it you should come to code like this :

    [​IMG]

    Now we see two instructions which reference "pi",
    putstatic String client.pi
    getstatic String client.pi

    the putstatic instruction is assigning a value to the field "pi" and the getstatic is getting the value of the field "pi". Just from looking at this we know the field is static due to the instruction getstatic/putstatic, if it wasn't static then in place of getstatic/putstatic would be getfield/putfield.

    Now to create a pattern for this we first need to find the attributes of the method which this code is in, so scroll up until you see the method name etc....

    [​IMG]

    Now from this information we take out that it is public, static, final and a void. We shouldn't use the parameters as we don't want to base it around structure in that way. Basically you'd use this as when you're iterating through each MethodNode(ASM) in the class you can check if it is public, static, final and void before searching if the pattern exists insdie it, you can use the Modifier class to do so :

    Code:
    if(!methodnode.desc.endsWith("Z") || !Modifier.isStatic(methodnode.access) || !Modifier.isFinal(methodnode.access) || !Modifier.isPublic(methodnode.access)) {
    continue;
    }
    We should also make sure that we don't search inside the "<clinit>" method as you shouldn't really create patterns inside their as it is too unreliable/not stable, to do so we simply do :

    Code:
    methodnode.name.contains("<clinit>")
    Now that we know how to only search the methods we want to, we can get back to the pattern(hit f3 again and you'll be back there)

    ldc_w Integer constant (int) -1262470041
    invokestatic String yr.ms(eu, int)
    putstatic String client.pi
    aconst_null
    getstatic String client.pi
    if_acmpne label_1670
    ldc_w String Constant "Null"
    putstatic String client.pi


    Lets work with these instructions, your pattern shouldn't really be too long ( > 5) so lets start at the putstatic instruction. Depending on your updater base, you might have a regex searcher or you might not so I'll just give you the basic idea... What we do is search through the instructions in our methodnode(which we learnt how to filter before) until we find a series of instructions that is our pattern, so basically our pattern would be...

    Code:
    putstatic aconst_null getstatic if_acmpne ldc
    This is for ASM, you may have noticed the ldc_w but I only included ldc, take a look at the fields http://asm.ow2.org/a...sm/Opcodes.html there for what you would use, e.g Opcodes.LDC

    Now from this we can use either the first([0]) or the third([2]) instruction to get the field name from as they both reference the same field. This may return more than one field so we can filter even more, we can use the FieldNode class(ASM) and check if it's "description"(String, int, boolean etc) is a String as we know our field is... to do this we can simply do :

    Code:
    if (!fieldnode.desc.equals("Ljava/lang/String;")) {
    continue;
    }
    This will skip the field if it's not a String basically, here's an example of how the code could look...
    [​IMG]

    Now here, I've filtered through the fields, methods and then searched for the pattern, you're "updater" may not use regex to search for patterns but all you do then is get an array of the instructions in a method and search for the pattern of instructions in a series basically.

    You can apply this knowledge to any game which has a client that is made in java. JaGeX made it harder for RS when they introduced different gamepacks as you have to deal with multiple levels of obfuscation(thanks pyroryan for that quote) in which the instruction patterns can be quite different.

    I'd recommend reading this http://en.wikipedia.org/wiki/Java_bytecode_instruction_listings as it educates you about each instruction, you don't have to know them but it helps.

    Need an updater Famework? Check out the VFramework at https://veloxbot.org
     
  3. Unread #2 - Nov 22, 2012 at 10:48 AM
  4. RuneScapeJJ
    Joined:
    Aug 14, 2011
    Posts:
    1,522
    Referrals:
    1
    Sythe Gold:
    0
    Potamus

    RuneScapeJJ Guru
    $25 USD Donor New

    Introduction To ByteCode Patterns

    Nice introduction, thanks :)
    I'm currently playing around a bit with non-script related RuneScape stuff. I have made a loader now and once I get my jar working I might look into some bytecode related stuff.
     
  5. Unread #3 - Nov 22, 2012 at 12:39 PM
  6. iJava
    Joined:
    Nov 21, 2011
    Posts:
    1,197
    Referrals:
    11
    Sythe Gold:
    485
    Discord Unique ID:
    220055593568829441

    iJava .Previously known as RSGoldRush
    $200 USD Donor New

    Introduction To ByteCode Patterns

    You'll need to decrypt the inner pack. Take a look at VFramework.
     
  7. Unread #4 - Nov 22, 2012 at 1:47 PM
  8. RuneScapeJJ
    Joined:
    Aug 14, 2011
    Posts:
    1,522
    Referrals:
    1
    Sythe Gold:
    0
    Potamus

    RuneScapeJJ Guru
    $25 USD Donor New

    Introduction To ByteCode Patterns

    Penta post from you, must be bad internet? Guess you posted with your phone and a mobile network or something, happened to me once. I actually posted that using the WiFi network in the train which isn't the best so it's always a guess if it's going to work.

    Anyways, I'll do that for sure :) Going to see if I can make my loader more efficient and look into more advanced RegEx.

    Oh and I just noticed two minor typo's:
    Currently looking into "hacking" the RS Canvas or better said replacing it with my own so I can get the BufferedImage. Once that is done I need to figure out a way to actually run scripts in the applet, not sure how to do that. But more on topic about ByteCode, I'll definately look into it very soon.
     
  9. Unread #5 - Nov 22, 2012 at 2:20 PM
  10. iJava
    Joined:
    Nov 21, 2011
    Posts:
    1,197
    Referrals:
    11
    Sythe Gold:
    485
    Discord Unique ID:
    220055593568829441

    iJava .Previously known as RSGoldRush
    $200 USD Donor New

    Introduction To ByteCode Patterns

    Sythe just didn't load so I resent the post data a couple of times.... The Framework actually shows you how to load the client with the decrypting etc all included. So use that for reference, it also shows you how to hack the canvas however you could just xboot with your own canvas as it's less detectable.
     
  11. Unread #6 - Nov 22, 2012 at 2:52 PM
  12. RuneScapeJJ
    Joined:
    Aug 14, 2011
    Posts:
    1,522
    Referrals:
    1
    Sythe Gold:
    0
    Potamus

    RuneScapeJJ Guru
    $25 USD Donor New

    Introduction To ByteCode Patterns

    Yeah I just got the VFramework and looked through some stuff, interesting. I'm planning to xboot it with my own canvas. One of the main things I'm worried about atm is the organizing of my project. Must keep all the code clean and well organized otherwise you will never be able to recognize what you did :p

    Making a bot is a nice way to learn and I have java classes at college aswell so that's nice. Learning the proper way to use it and what it actually does, which is hard to learn from tutorials or by experimenting. We just covered the usage this & static which I understand a lot better now. I wasn't sure what "this" did and why I needed to use static sometimes, even though my code did work :p

    What I have so far (I need to set up a proper package etc as I mentioned before)
    Code:
    package hooking;
    
    import java.applet.Applet;
    import java.applet.AppletContext;
    import java.applet.AppletStub;
    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.net.URLClassLoader;
    import java.util.HashMap;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    
    public class Loader extends JFrame implements AppletStub {
    	private static HashMap<String, String> parameters = new HashMap<String, String>();
    	private final URL theBaseURL = getBaseURL(),
    				      theGameURL = getGameURL(theBaseURL),
    				      theJarURL = getJarURL(theGameURL); 
    
    	public Loader(){
    		try{
    			setTitle("JJ's RS2 Client");
    			setSize(763, 563);
    	
    			JPanel game = new JPanel(new BorderLayout());
    			game.setPreferredSize(new Dimension(763, 553));
    			
    			parseParameters();
    			ClassLoader clientClassLoader = new URLClassLoader(new URL[] { theJarURL });
    			Applet loader = clientClassLoader.loadClass("Rs2Applet").asSubclass(Applet.class).newInstance();
    			
    			loader.setStub(this);
    			loader.init();
    			loader.start();
    			
    			game.add(loader);
    			getContentPane().add(game, BorderLayout.CENTER);
    			setDefaultCloseOperation(EXIT_ON_CLOSE);
    			setVisible(true);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    
    	public URL getBaseURL(){
    		URL  u = null;
    		
    		try{
    			u = new URL("http://www.runescape.com/game.ws?j=1");
    		} catch (MalformedURLException e) {
    			e.printStackTrace();
    		}
    		
    		System.out.println("Base URL: " + u);
    		return u;
    	}
    	
    	public URL getGameURL(URL baseURL){
    		URL u = null;
    		
    		try{
    			BufferedReader in = new BufferedReader(new InputStreamReader(baseURL.openStream()));
    			String raw;
    	
    			while((raw = in.readLine()) != null){
    				System.out.println(raw);
    				if(raw.contains("src")){
    					try{
    						int start = raw.indexOf("src") + 5,
    							    end = raw.indexOf("frameborder") - 3;
    						String s =  raw.substring(start, end);
    						u = new URL(s);
    						break;
    					} catch (MalformedURLException e) {
    						e.printStackTrace();
    					}
    				}
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		
    		System.out.println("Game URL: " + u);
    		return u;
    	}
    	
    	public URL getJarURL(URL gameURL){
    		URL u = null;
    		
    		try{
    			BufferedReader in = new BufferedReader(new InputStreamReader(gameURL.openStream()));
    			String raw;
    			
    			while((raw = in.readLine()) != null){
    				if(raw.contains("archive")){
    					try{
    						int start = raw.indexOf("archive") + 8,
    						    end = raw.indexOf("jar") + 3;
    						
    						String jar = raw.substring(start, end),
    							   rs = gameURL.toString(),
    							   rs2 = rs.substring(0, rs.indexOf(","));
    						
    						u = new URL(rs2 + jar);
    					} catch (MalformedURLException e) {
    						e.printStackTrace();
    					}
    				}
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		
    		System.out.println("Jar URL: " + u);
    		return u;
    	}
    	
    	public void parseParameters(){
    		try{
    			URL baseURL = getBaseURL(),
    				gameURL = getGameURL(baseURL);
    	
    			BufferedReader in = new BufferedReader(new InputStreamReader(gameURL.openStream()));
    			String raw;
    			
    			while((raw = in.readLine()) != null){
    				if(!raw.contains("param name") || !raw.contains("value") || raw.contains("haveie6")){
    					continue;
    				}
    				
    				raw = raw.substring(raw.indexOf('<')+1, raw.indexOf('>'));
    				raw = raw.replaceAll("\"", "");
    				raw = raw.replaceAll(" ", "");
    				
    				String param = raw.substring(raw.indexOf("param name") + 11, raw.indexOf("value")),
    					   value = raw.substring(raw.indexOf("value") + 6, raw.length());
    
    				parameters.put(param, value);
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    	
    	@Override
    	public void appletResize(int width, int height) {
    		setSize(width, height);
    	}
    
    	@Override
    	public AppletContext getAppletContext() {
    		throw new UnsupportedOperationException();
    	}
    
    	@Override
    	public URL getCodeBase() {
    		return theGameURL;
    	}
    	
    	@Override
    	public URL getDocumentBase() {
    		return getCodeBase();
    	}
    
    	@Override
    	public String getParameter(String name) {
    		return parameters.get(name);
    	}
    
    	public static void main(String[] args) {
    		new Loader();
    	}
    }
    It works but it can be improved on some points. I could just copy the regex from your loader or from Wyn's loader but I played around a bit and this works aswell.

    Anyways I need to get off my computer and head off to the gym so I can do a proper workout before it closes.. I just get stuck at the computer something if I get interested.

    Do you know anything about HTML5 and HTML5 hooking/injection or whatever is possible? Behind the Scenes: http://services.runescape.com/m=news/behind-the-scenes-special-edition

    I searched around and found some information at Powerbot's forum and at Villavu I believe and a question on stackoverflow: http://stackoverflow.com/questions/...ml5-be-reverse-engineered-to-be-used-in-a-cli But it's still not really clear what you can do with HTML 5. Any idea?
     
  13. Unread #7 - Nov 22, 2012 at 3:46 PM
  14. iJava
    Joined:
    Nov 21, 2011
    Posts:
    1,197
    Referrals:
    11
    Sythe Gold:
    485
    Discord Unique ID:
    220055593568829441

    iJava .Previously known as RSGoldRush
    $200 USD Donor New

    Introduction To ByteCode Patterns


    You shouldn't call methods outside of a constructor or method, set the baseURL etc in the constructor.


    Obviously a lot more could be touched up.

    As for HTML5 I doubt they're going to remove the java client and I've heard of WebGL but We'll have to wait and see.
     
< Help Needed(IRC Dicing Channel) | Need some ideas|VB 2010|AHK >

Users viewing this thread
1 guest


 
 
Adblock breaks this site