Skip to content
This repository has been archived by the owner on Jun 13, 2018. It is now read-only.

Architecture

supergillis edited this page Sep 4, 2012 · 1 revision

Architecture

The hook is written with Qt. With Qt you can make cross-platform applications and it has great support for multithreaded applications.

Core

When the hook gets injected, a new thread is created. Qt runs in this thread. So we actually have two threads then: the Tibia thread, and the injected Qt thread.

The hook has three important elements. The DetourManager class, the Hook class and the Handler interface.

Hook

The Hook class runs in the Qt thread. It delegates client and server messages to an instance of the Handler class. The handler decides if it blocks a packet or not. If it decides that a packet shouldn't be blocked, then the hook puts the packet on DetourManager's queue.

Currently only client packets can be blocked.

DetourManager

The DetourManager class installs the detours, or function hooks. So when Tibia calls the function to send its buffer to the server, we can actually intercept it and send something different, or we can send nothing at all.

It contains only static functions and static variables. You might ask why I didn't use the singleton pattern here. Well, this is because we cannot detour a Tibia function to a member function.

The hooked functions get called in Tibia's thread, but the Hook and the Handler run in the Qt thread. How do we make this thread-safe? I solved this by looking for a loop in the Tibia client. When we then find a function that gets called every time in this loop, and we hook it, then we can do stuff in this function, and thus in Tibia's thread. So when we want to send a packet from the Qt thread, we put this packet on DetourManager's queue and then when the function in the loop gets called, we can send this queued packet in Tibia's thread.

I'll explain the above with an example. Tibia has a function send. We hook this function with a new function, onSend. So from now on, when Tibia calls send it will actually call onSend. In the onSend function we read out the buffer that Tibia is trying to send and we put a DataEvent, that contains the buffer, on the Qt thread. Then we exit the onSend function, without actually sending something. The Hook, running in the Qt thread then does all kinds of nasty things with this buffer. If it wants this buffer to be sent to the client for real, then it puts it on DetourManager's queue. Now remember the loop function. It runs in the Tibia thread. When this function runs, we check if there is something on the queue. If this is the case, we replace Tibia's buffer with the buffer on the queue and call the real send function. That's how it's done. I hope it was clear...

Plugins

Clone this wiki locally