• We see that you're not registered. Please read this thread and if you want, sign up on the forum.

Tutorial [Ultimate Guide] How to Write a Runescape Injection Bot

abdul

New member
Joined
Apr 27, 2020
Posts
20
Points
3
Reaction score
6
Quality Posts
I'm glad you found it helpful!

As for your question, that's actually really hard to answer. I might get around to making a tutorial on that in the future, but I'm working on some other projects right now so I simply don't have the time.

Applying this knowledge and creating a fully functioning bot will require intricate knowledge on how the client works, which means you will have to spend quite some time deobfuscating and analyzing the code. Luckily, people have already done this so you can just check out the source code for other bot frameworks on Github. Parabot has a pretty decent framework that is also easy to understand. Unfortunately, there is a good chance you'll have to find which variable is which in the code of your target client, which will take some time unless you're very experienced already.

Could you point me in the right direction and tell me how I'd go about and try implement something very small, e.g. where are the npc id's normally stored, how do I get that id, and once I have that id, do I use a different java library that interacts with the game somehow or send a packet to the rsps server that I clicked this npc?
 

Shenandoah

Access Write Violation
Admin
Legend
Joined
Nov 1, 2019
Posts
93
Points
18
Reaction score
52
Quality Posts
1
Could you point me in the right direction and tell me how I'd go about and try implement something very small, e.g. where are the npc id's normally stored, how do I get that id, and once I have that id, do I use a different java library that interacts with the game somehow or send a packet to the rsps server that I clicked this npc?
I don't know where the NPC IDs are usually stored, but I'm sure there are plenty of resources online that have valuable information on that in particular. I assume you want to create a bot for educational purposes, and if that's the case, I think it would be wise to explore this yourself. Reverse engineering is a whole different field, and it can be very time-consuming to do.

When you have the IDs, you have several options for how to proceed. Sending packets is definitely an option, but you can also control the client by sending events directly to the client as shown in the tutorial. If you find some NPC object, I'm sure it stores some coordinates that you can convert into screen coordinates, and then send mouse click events at that particular coordinate.

I suggest you try out a few approaches, and see where it leads.
 

abdul

New member
Joined
Apr 27, 2020
Posts
20
Points
3
Reaction score
6
Quality Posts
I don't know where the NPC IDs are usually stored, but I'm sure there are plenty of resources online that have valuable information on that in particular. I assume you want to create a bot for educational purposes, and if that's the case, I think it would be wise to explore this yourself. Reverse engineering is a whole different field, and it can be very time-consuming to do.

When you have the IDs, you have several options for how to proceed. Sending packets is definitely an option, but you can also control the client by sending events directly to the client as shown in the tutorial. If you find some NPC object, I'm sure it stores some coordinates that you can convert into screen coordinates, and then send mouse click events at that particular coordinate.

I suggest you try out a few approaches, and see where it leads.

I will definitely look at other resources and spend some time reverse engineering and digging deep into the code, would you recommend me anything to improve my knowledge around this area.

Also from your opinion what do you think is a better approach, sending packets or controlling the client by sending events directly?
 

abdul

New member
Joined
Apr 27, 2020
Posts
20
Points
3
Reaction score
6
Quality Posts
The variable thread isn't being used, is this needed?

Java:
public Graphics getGraphics() {
        Graphics g = super.getGraphics();
        if (!threadStarted) {
            Thread thread = new Thread(new Runnable() {

                @Override
                public void run() {
                    g.setColor(Color.RED);
                    g.drawString("Some string here!", 100, 100);
                }
            });
            
            threadStarted = true;
        }
        
        // We eventually have to return the Graphics object, since that's what the RSApplet class wanted in the first place
        return g;
    }
 

abdul

New member
Joined
Apr 27, 2020
Posts
20
Points
3
Reaction score
6
Quality Posts
I'm getting this weird error in the following file RSAppletClassTransformer.java
Java:
public class RSAppletClassTransformer extends ClassTransformer {
    @Override
    public void transform(ClassNode node) {
        Objects.requireNonNull(node, "Node must not be null!");

        node.interfaces.add("RSAppletInterface");
        MethodNode methodNode = new MethodNode(Opcodes.ACC_PUBLIC, "getGraphicsObject", "()Ljava/awt/Graphics;", null, null);
        methodNode.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
        methodNode.instructions.add(new FieldInsnNode(Opcodes.GETFIELD, "RSApplet", "graphics", "Ljava/awt/Graphics;"));
        methodNode.instructions.add(new InsnNode(Opcodes.ARETURN));
        int size = methodNode.instructions.size();
        methodNode.visitMaxs(size, size);
        methodNode.visitEnd();
        node.methods.add(methodNode);
}

This is what my RSAppletInterface file looks like
Java:
public interface RSAppletInterface {
    public Graphics getGraphicsObject();
}

This is the error I'm getting
Java:
Exception in thread "main" java.lang.NoClassDefFoundError: RSAppletInterface
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)

There's a bunch more error but I think from that the important thing you can see is NoClassDefFoundError

If I comment out node.interfaces.add("RSAppletInterface"); it works fine, and the RSApplet has a method called getGraphicsObject

Also same problem with node.superName = "BotApplet"; returns the same error
Exception in thread "main" java.lang.NoClassDefFoundError: BotApplet
 

Shenandoah

Access Write Violation
Admin
Legend
Joined
Nov 1, 2019
Posts
93
Points
18
Reaction score
52
Quality Posts
1
I will definitely look at other resources and spend some time reverse engineering and digging deep into the code, would you recommend me anything to improve my knowledge around this area.

Also from your opinion what do you think is a better approach, sending packets or controlling the client by sending events directly?
For improving at reverse engineering, going by trial-and-error will probably help you gain experience the most. You can look up generic tutorials on how to reverse engineer programs in Java, those tutorials might have some useful information. But you should definitely just try out different things for yourself.

I'd say they're both good approaches, but the latter is more convenient in your case since you've already learned how to send keyboard and mouse events to the client.


The variable thread isn't being used, is this needed?

Java:
public Graphics getGraphics() {
        Graphics g = super.getGraphics();
        if (!threadStarted) {
            Thread thread = new Thread(new Runnable() {

                @Override
                public void run() {
                    g.setColor(Color.RED);
                    g.drawString("Some string here!", 100, 100);
                }
            });
           
            threadStarted = true;
        }
       
        // We eventually have to return the Graphics object, since that's what the RSApplet class wanted in the first place
        return g;
    }
Yes, for some reason, it's missing a start method call on the thread. So, you need to call the start method on the thread instance to see the text.

I'm getting this weird error in the following file RSAppletClassTransformer.java
Java:
public class RSAppletClassTransformer extends ClassTransformer {
    @Override
    public void transform(ClassNode node) {
        Objects.requireNonNull(node, "Node must not be null!");

        node.interfaces.add("RSAppletInterface");
        MethodNode methodNode = new MethodNode(Opcodes.ACC_PUBLIC, "getGraphicsObject", "()Ljava/awt/Graphics;", null, null);
        methodNode.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
        methodNode.instructions.add(new FieldInsnNode(Opcodes.GETFIELD, "RSApplet", "graphics", "Ljava/awt/Graphics;"));
        methodNode.instructions.add(new InsnNode(Opcodes.ARETURN));
        int size = methodNode.instructions.size();
        methodNode.visitMaxs(size, size);
        methodNode.visitEnd();
        node.methods.add(methodNode);
}

This is what my RSAppletInterface file looks like
Java:
public interface RSAppletInterface {
    public Graphics getGraphicsObject();
}

This is the error I'm getting
Java:
Exception in thread "main" java.lang.NoClassDefFoundError: RSAppletInterface
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)

There's a bunch more error but I think from that the important thing you can see is NoClassDefFoundError

If I comment out node.interfaces.add("RSAppletInterface"); it works fine, and the RSApplet has a method called getGraphicsObject

Also same problem with node.superName = "BotApplet"; returns the same error
Exception in thread "main" java.lang.NoClassDefFoundError: BotApplet
It's incredibly difficult to debug a program remotely, but I'll try anyways.

Have you made sure you've copied everything I've done in the tutorial to a T? It's very easy to gloss over some important details sometimes.

Can I see all of the errors, and also the code of the main class that is instantiating the RSAppletClassTransformer instance please?
 

abdul

New member
Joined
Apr 27, 2020
Posts
20
Points
3
Reaction score
6
Quality Posts
It's incredibly difficult to debug a program remotely, but I'll try anyways.

Have you made sure you've copied everything I've done in the tutorial to a T? It's very easy to gloss over some important details sometimes.

Can I see all of the errors, and also the code of the main class that is instantiating the RSAppletClassTransformer instance please?

Yeah I have copied everything to a T (I think 😅)

This is the main.java that calls RSAppletClassTransformer
Java:
public static void main(String[] args) throws IOException {
        JarHelper helper = new JarHelper(new JarFile("client.jar"));

        ClassNode rsApplet = helper.getClasses().get("RSApplet.class");
        RSAppletClassTransformer ract = new RSAppletClassTransformer();
        ract.transform(rsApplet);

        helper.saveJar();

        reflection(); // <---- this is what launches the client
    }

Pastebin of RSAppletClassTransformer.java ->
https://pastebin.com/0TAMjszZ
Pastebin with errors from RSAppletInterface -> https://pastebin.com/YnG4rMnc
Pastebin with the errors from BotApplet -> https://pastebin.com/rZkuxXXw
Pastebin of BotApplet.java -> https://pastebin.com/qxQZ6WNP
The client loads successfully when I call reflection(); * when the instance of RSAppletClassTranser is commented out *
 

abdul

New member
Joined
Apr 27, 2020
Posts
20
Points
3
Reaction score
6
Quality Posts
If it helps, you could give me your discord @ and you can connect to my screen via TeamViewer?
 

Shenandoah

Access Write Violation
Admin
Legend
Joined
Nov 1, 2019
Posts
93
Points
18
Reaction score
52
Quality Posts
1
Yeah I have copied everything to a T (I think 😅)

This is the main.java that calls RSAppletClassTransformer
Java:
public static void main(String[] args) throws IOException {
        JarHelper helper = new JarHelper(new JarFile("client.jar"));

        ClassNode rsApplet = helper.getClasses().get("RSApplet.class");
        RSAppletClassTransformer ract = new RSAppletClassTransformer();
        ract.transform(rsApplet);

        helper.saveJar();

        reflection(); // <---- this is what launches the client
    }

Pastebin of RSAppletClassTransformer.java ->
https://pastebin.com/0TAMjszZ
Pastebin with errors from RSAppletInterface -> https://pastebin.com/YnG4rMnc
Pastebin with the errors from BotApplet -> https://pastebin.com/rZkuxXXw
Pastebin of BotApplet.java -> https://pastebin.com/qxQZ6WNP
The client loads successfully when I call reflection(); * when the instance of RSAppletClassTranser is commented out *
Okay, I have some questions.

Are you using Eclipse? If so, try restarting Eclipse just to see if it could be a bug there. Do the same if you're using another IDE.

Do you keep all your classes in the same package? Is the RSAppletInterface in the same package as the RSAppletClassTransformer class? If not, try to provide the complete path in this fashion: node.interfaces.add("path/to/RSAppletInterface"); and see if that works. Also, if they are all in the same package, try replacing the add interface statement with this: node.interfaces.add("com/abdul/RSAppletInterface");
 

abdul

New member
Joined
Apr 27, 2020
Posts
20
Points
3
Reaction score
6
Quality Posts
You sir... is a genius node.interfaces.add("com/abdul/RSAppletInterface"); worked!! I decompiled the new jar and it was implemented. Just a question, where would I print the graphics from the interface public Graphics getGraphicsObject();

Also if you look at my Pastebin of RSAppletClassTransformer.java I sent from the previous post, is the node.superName = "com/abdul/BotApplet"; and the rest of code beneath it meant to be in this file along with the RSAppletInterface because I'm receiving a new error. https://pastebin.com/wgiuN4kP
 

Shenandoah

Access Write Violation
Admin
Legend
Joined
Nov 1, 2019
Posts
93
Points
18
Reaction score
52
Quality Posts
1
You sir... is a genius node.interfaces.add("com/abdul/RSAppletInterface"); worked!! I decompiled the new jar and it was implemented. Just a question, where would I print the graphics from the interface public Graphics getGraphicsObject();

Also if you look at my Pastebin of RSAppletClassTransformer.java I sent from the previous post, is the node.superName = "com/abdul/BotApplet"; and the rest of code beneath it meant to be in this file along with the RSAppletInterface because I'm receiving a new error. https://pastebin.com/wgiuN4kP
I apologize if the tutorial is a bit confusing. Looking back on it, I'm unsure why I structured it this way. Oh well, you live and learn I guess. :p

The part of the tutorial that shows you how to add an interface was just an example to illustrate how injecting accessor methods into a jar works. You can remove the code in the RSAppletClassTransformer that has to do with adding the interface if you want because it won't be needed later in the tutorial, as it was just an example showing how to add interfaces, and we needed a use case, so I just used the example of getting the graphics object as a way to show how to do this.

And yes, that code is supposed to be there. I understand if it was a little confusing; I confused myself just now reading through the code again, haha. :)

Can I see the code of the BotApplet class? And also the code of the reflection method?
 

abdul

New member
Joined
Apr 27, 2020
Posts
20
Points
3
Reaction score
6
Quality Posts
I apologize if the tutorial is a bit confusing. Looking back on it, I'm unsure why I structured it this way. Oh well, you live and learn I guess. :p

The part of the tutorial that shows you how to add an interface was just an example to illustrate how injecting accessor methods into a jar works. You can remove the code in the RSAppletClassTransformer that has to do with adding the interface if you want because it won't be needed later in the tutorial, as it was just an example showing how to add interfaces, and we needed a use case, so I just used the example of getting the graphics object as a way to show how to do this.

And yes, that code is supposed to be there. I understand if it was a little confusing; I confused myself just now reading through the code again, haha. :)

Can I see the code of the BotApplet class? And also the code of the reflection method?
Surprisingly it wasn't confusing at all, especially considering how hard this is and there's no other tutorial out here like this!

And I managed to fix the problem by also changing this min.owner = "BotApplet"; to this min.owner = "com/abdul/BotApplet";

Heres the BotApplet code incase your curious to see -> https://pastebin.com/Tg20208e
And here's the reflection method code -> https://pastebin.com/PnzentYe

Sweet it now works! *not an issue but I'm setting the colour to be BLUE in the BotApplet file but it's white*
1588011913298.png
 

Shenandoah

Access Write Violation
Admin
Legend
Joined
Nov 1, 2019
Posts
93
Points
18
Reaction score
52
Quality Posts
1
Surprisingly it wasn't confusing at all, especially considering how hard this is and there's no other tutorial out here like this!

And I managed to fix the problem by also changing this min.owner = "BotApplet"; to this min.owner = "com/abdul/BotApplet";

Heres the BotApplet code incase your curious to see -> https://pastebin.com/Tg20208e
And here's the reflection method code -> https://pastebin.com/PnzentYe

Sweet it now works! *not an issue but I'm setting the colour to be BLUE in the BotApplet file but it's white*
View attachment 61
Oh right, I didn't think of that actually! Haha. I'm glad it works, mate! The world is your oyster now!
 

abdul

New member
Joined
Apr 27, 2020
Posts
20
Points
3
Reaction score
6
Quality Posts
Oh right, I didn't think of that actually! Haha. I'm glad it works, mate! The world is your oyster now!
Just want to say thank you sm man! the tutorial was on point and everything was explained well to a newbie like me :p and the fast replies were superrrr helpful! Definitely keep tutorials like these coming if you can, I'll definitely be on the look out. Also whats your discord @
 

Shenandoah

Access Write Violation
Admin
Legend
Joined
Nov 1, 2019
Posts
93
Points
18
Reaction score
52
Quality Posts
1
Just want to say thank you sm man! the tutorial was on point and everything was explained well to a newbie like me :p and the fast replies were superrrr helpful! Definitely keep tutorials like these coming if you can, I'll definitely be on the look out. Also whats your discord @
Thank you for the kind words, that means a lot to me! I'll keep making tutorials. If your friends are curious to see how RS bots work on a core level, I hope you'll refer them to this tutorial. :p

My discord handle is: Shenandoah#2403. Although I must tell you, my responses on Discord might be quite slow, so if things are urgent, DM'ing me on the forums would be your best bet. ^^
 

abdul

New member
Joined
Apr 27, 2020
Posts
20
Points
3
Reaction score
6
Quality Posts
Thank you for the kind words, that means a lot to me! I'll keep making tutorials. If your friends are curious to see how RS bots work on a core level, I hope you'll refer them to this tutorial. :p

My discord handle is: Shenandoah#2403. Although I must tell you, my responses on Discord might be quite slow, so if things are urgent, DM'ing me on the forums would be your best bet. ^^

Most definitely will recommend them to this! Only tutorial out there like this. Absolutely amazing man! (won't spam you, just for future reference incase this forum goes down and whatnot)

I have a weird problem, so I was coding this on my Mac laptop, and with the exact same code, I tried to run it on my windows pc (since mac can only run the client and not the source) but it doesn't show the string Some string here! when the client is loaded. I think it appears a for a quick mili second and then disappears. I have a print statement to check if it entered the Graphics thread and it did. Is there a reason why it does this?
 

abdul

New member
Joined
Apr 27, 2020
Posts
20
Points
3
Reaction score
6
Quality Posts
I even tried to a load an image, it successfully loaded an image but it only lasted for a few seconds then when the client started it went, felt like the client is overlaying it maybe?
 

Shenandoah

Access Write Violation
Admin
Legend
Joined
Nov 1, 2019
Posts
93
Points
18
Reaction score
52
Quality Posts
1
Most definitely will recommend them to this! Only tutorial out there like this. Absolutely amazing man! (won't spam you, just for future reference incase this forum goes down and whatnot)

I have a weird problem, so I was coding this on my Mac laptop, and with the exact same code, I tried to run it on my windows pc (since mac can only run the client and not the source) but it doesn't show the string Some string here! when the client is loaded. I think it appears a for a quick mili second and then disappears. I have a print statement to check if it entered the Graphics thread and it did. Is there a reason why it does this?
It should work on Windows too; I wrote the tutorial on a Windows computer. It should show the string, although some flickering will happen. Not sure how to fix the flickering exactly, but I'd look into how double buffering to get some ideas on how to fix that.

That's really strange if it's not showing at all. Remember that the client is drawing on the screen many times per second, so when you want to draw, ideally you'd want to be the last drawing call in the game loop. If the screen keeps getting reset too quickly, you might not be able to see the text otherwise.

I'm not sure what the problem could be, but I'd assume it's a problem with the threading somehow. I noticed just now that the code for rendering the string is really bad. It creates a new thread every time you want to draw the string. I'm sure there's a much better way to do it. Maybe Windows handles threading differently or something, but that's just me grasping at straws. It should work on Windows too. Make sure everything is as in the tutorial.
 

abdul

New member
Joined
Apr 27, 2020
Posts
20
Points
3
Reaction score
6
Quality Posts
It should work on Windows too; I wrote the tutorial on a Windows computer. It should show the string, although some flickering will happen. Not sure how to fix the flickering exactly, but I'd look into how double buffering to get some ideas on how to fix that.

That's really strange if it's not showing at all. Remember that the client is drawing on the screen many times per second, so when you want to draw, ideally you'd want to be the last drawing call in the game loop. If the screen keeps getting reset too quickly, you might not be able to see the text otherwise.

I'm not sure what the problem could be, but I'd assume it's a problem with the threading somehow. I noticed just now that the code for rendering the string is really bad. It creates a new thread every time you want to draw the string. I'm sure there's a much better way to do it. Maybe Windows handles threading differently or something, but that's just me grasping at straws. It should work on Windows too. Make sure everything is as in the tutorial.

Have a look at this gyazo -> https://gyazo.com/e6fd345c9ef9857c33cc5a90c8f5f6d0

If you pause the video, you can see the the image and text being loaded before the client does, so i'm assuming it loads the graphics first then runs the client which makes it disappear. Any idea?

 
Top