How to hook a server

How to hook a server

There's a few topics to talk about;

  • Requirements
  • Difference between loader and client
  • How Parabot loads its hooks
  • What kind of hooks there are
  • The XML file
  • How to start hooking
  • Requirements to test locally

The requirements

Even though we explain a lot of basic stuff in here, the hooking process itself requires you to have a lot of knowledge around this topic. You can gather this knowledge by inspecting clients, doing things yourself and simply try, try, try.

Loader vs client

There's a real difference between a loader and a client.
Long story short, it's the client you'll need, not the loader!

The loader is basically a simple application that starts up the client, which could include various arguments, auto-updating etc.
Because we rely on the client and not the launcher, you'll need to grab the jar.

In most launchers it's easy to grab the actual client, as they have some string with ".jar" in it, to load the client.
Simply download this jar and check if it contains enough classes to be the client.

Parabot and its hooks

Parabot loads its hooks using an XML parser. This system reads an XML file and gets all contents from it using the XML structure.

Once loaded, it goes through all types of hooks and edits the client to receive those hooks easily.

The backend isn't quite simple, but isn't required to understand when start hooking a server.
If you're interested (for some reason), you probably have enough knowledge to understand, so you'll figure your way out with this link.

Type of hooks

We've a few different type of hooks;

  • Interfaces
  • Getters
  • Setters
  • Callbacks
  • Invokers
Interfaces

Interfaces is basically a reference to the actual class, it looks like this:

<add>
    <classname>client</classname>
    <interface>Client</interface>
</add>

As you can see, we reference the name Client to the class client.
In that way we can easily say Client.fieldname to retrieve a fieldname, without typing out the whole class each time.
This is especially useful for clients which have strange names (like oAjEaif) for their classes.

Getters

A getter looks like this:

<add>
    <accessor>Client</accessor>
    <field>backDialogID</field>
    <methodname>getBackDialogId</methodname>
    <descfield>I</descfield>
</add>
  • In here we first reference to the accessor (the interface) and then set all required fields.
  • The field is the field name within the current client, this could be something totally random (like aF), but in this case it's a more logic name.
  • Then we let the system know which method relates to which field, which is in this case getBackDialogId (this field is not for the client, but for the system itself, Parabot).
  • At last we also provide the desc of the field, which is in this case an integer, which has a desc of I
Setters

A setter could be useful to change a field value; it looks like the following:

<add>
    <accessor>Client</accessor>
    <field>openInterfaceID</field>
    <methodname>setInterface</methodname>
    <descfield>I</descfield>
</add>
  • Again we start with the accessor, referencing to the actual class file.
  • Then we say which field needs to be changed when calling the method
  • This is again the method from the system, Parabot
  • The descfield is again letting the system know which type of field it is, which is an integer in this case
Callbacks

A callback is a way of intercepting methods called in the client, called by the client itself.
Let's say the client sends a message to an user, we can intercept that method to see what message is sent.

A callback looks like the following:

<add>
    <accessor>Client</accessor>
    <methodname>doAction</methodname>
    <desc>(I)V</desc>
    <callclass>org/rev317/min/callback/MenuAction</callclass>
    <callmethod>intercept</callmethod>
    <calldesc>(I)V</calldesc>
    <callargs>0</callargs>
</add>
  • First we assign the accessor again, which is the client, once again
  • Then we say which method has to be intercepted
  • Then we say what kind of desc the method has. This is quite different from a field, as also have to define what parameters there are (within the ()) and what kind of type it returns (it's a void in this case)
  • Then we say which system class has to be called, which is MenuAction in this case
  • After that, we say which method has to be called in the system once the interception happens
  • We also provide the desc of the method (intercept), which is most likely the same as the desc of the client method
  • We also provide the order of the args, using the index of the arguments. In this case the first (and only) parameter is assigned to the first parameter of the system method (intercept())
Invokers

An invoker is a way to call a method. This is different from the intercepter, as we now call the method instead of receive the output of the method.

An invoker looks like the following:

<add>
    <accessor>Client</accessor>
    <methodname>doAction</methodname>
    <invokemethod>doAction</invokemethod>
    <desc>V</desc>
    <argsdesc>(I)</argsdesc>
</add>
  • As usual, we first say to which reference the system must check, which is Client once again
  • Then we tell what the method is in the client itself
  • After that we tell the system what the method is in its own system, in this case this is the same
  • The desc stands for the description of the method
  • The argsdesc stands for the arguments description of the method

The hook file

We've created a basic hook file, where you can copy the fields from, you can find this here.

You can also find a lot of other hooks (and old hooks) for reference here.

How to start hooking

Well the hooking process isn't an easy thing to teach, it's better to practice a lot and understand (317) clients.

It's basically comparing a non-obfuscated client to the actual client.
Most easy to use would probably JD-GUI and simply insert the client and the non-obfuscated client (you can find that one here).

An example of looking for hooks would be like as in the following screenshot:

ExampleExample2

In this case we've found the field backDialogID by simply comparing actions in the non-obfuscated client against the actual client.
So for this client the getter field would look like this:

<add>
    <accessor>Client</accessor>
    <field>YJ</field>
    <methodname>getBackDialogId</methodname>
    <descfield>I</descfield>
</add>

How to test locally

We've created an smart system to detect local development/hooking of a server, you can do this by creating a new (json) file within your Parabot/Servers directory.
For example create a file called server.json and insert the following:

{
        "name": "New server",
        "author": "My name",
        "version": 1.0,
        "client-class": "client",
        "locations":{
            "provider": "http://bdn.parabot.org/api/v2/bot/download/317-api-minified",
            "server": "/path/to/the/server_jar.jar",
            "hooks": "/path/to/the/hook_file.xml"
    }
}

This will load the provider, get the client class (make sure this is correctly set) and insert the server and hooks file.
It's also possible to set web urls, you can for example set the value of server to http://www.site.com/client.jar, it'll then simply download the client!

Questions

If you've any questions, please use slack to ask those.
On slack we've an really active community where you can ask questions to everyone and everyone will get notified of your questions.
If you have specific questions, you can also simply private message someone, including moderators, developers and administrators!