Skip to content

Hook Guide

Introduction

Hook is a technique for modifying the behavior of functions at runtime. It is commonly used to alter the behavior of functions without modifying the original source code.

Explanation of Hook on Wikipedia: Hooking

In LeviLamina, we provide well-packaged Hook APIs, allowing you to quickly and conveniently modify the behavior of game functions in Minecraft Bedrock Dedicated Servers (referred to as BDS).

Defines of Hooks

In ll/api/memory/Hook.h, we defined the following Hook macros:

C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#define LL_TYPE_STATIC_HOOK(DEF_TYPE, PRIORITY, TYPE, IDENTIFIER, RET_TYPE, ...)

#define LL_STATIC_HOOK(DEF_TYPE, PRIORITY, IDENTIFIER, RET_TYPE, ...)

#define LL_TYPE_INSTANCE_HOOK(DEF_TYPE, PRIORITY, TYPE, IDENTIFIER, RET_TYPE, ...)

#define LL_INSTANCE_HOOK(DEF_TYPE, PRIORITY, IDENTIFIER, RET_TYPE, ...)

#define LL_AUTO_TYPE_STATIC_HOOK(DEF_TYPE, PRIORITY, TYPE, IDENTIFIER, RET_TYPE, ...)

#define LL_AUTO_STATIC_HOOK(DEF_TYPE, PRIORITY, IDENTIFIER, RET_TYPE, ...)

#define LL_AUTO_TYPE_INSTANCE_HOOK(DEF_TYPE, PRIORITY, TYPE, IDENTIFIER, RET_TYPE, ...)

#define LL_AUTO_INSTANCE_HOOK(DEF_TYPE, PRIORITY, IDENTIFIER, RET_TYPE, ...)

The AUTO-marked Hooks automatically register, i.e., call the hook() function to register at runtime. The TYPED-marked Hooks inherit your DEF_TYPE to the specified type.

STATIC_HOOK

For hooking static functions.

INSTANCE_HOOK

For hooking member functions.

Explanation of Hook Parameters

DEF_TYPE: The type name you give to your Hook.

PRIORITY: Hook priority, e.g., ll::memory::HookPriority::Normal

Note

Generally, unless there's a special need, we do not recommend a very high priority; Normal is sufficient.

TYPE: The type to which your defined DEF_TYPE is inherited.

IDENTIFIER: The identifier used for the Hook lookup function, which can be: function's decorated name, function bytecode, function definition.

RET_TYPE: The return type of the Hook function.

...: The parameter list of the Hook function.

Using Hooks

You can refer to static program analysis tools, such as IDA Pro, to obtain the symbols or signatures of the functions you want to Hook.

Or refer to the Fake Header provided by LeviLamina to obtain the symbols or definitions of the functions you want to Hook.

A Simple Hook Example

C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#include "ll/api/Logger.h"
#include "mc/server/common/DedicatedServer.h"

ll::Logger dedicatedServerLogger("DedicatedServer");

LL_AUTO_TYPE_INSTANCE_HOOK(
    DedicatedServerHook,
    ll::memory::HookPriority::Normal,
    DedicatedServer,
    "??0DedicatedServer@@QEAA@XZ",
    void
) {
    origin();
    dedicatedServerLogger.info("DedicatedServer::DedicatedServer");
}

This code hooks the constructor of DedicatedServer and prints a log message when the constructor is called.

Analysis:

Referring to the DedicatedServer.h provided by LeviLamina, we know that the symbol for DedicatedServer's constructor is ??0DedicatedServer@@QEAA@XZ.

Since the constructor is a member function of the class, we used the INSTANCE_HOOK type of Hook, which means we don't need to fill in the first this pointer parameter generated by the compiler.

We used the AUTO-marked Hook because we want it to automatically register when the plugin is loaded.

Finally, for convenience, we used the TYPE-marked Hook, so we can directly call functions under the DedicatedServer type in the function body. Although we did not use it in this code, it is a good habit.

Registering and Unloading Hooks

Registration

For non-automatically registered Hooks, you need

to call the hook() function to register at the moment your plugin needs to register the Hook.

Unloading

All Hooks will automatically unload when BDS unloads. You can also call the unhook() function to unload when your plugin needs to unload the Hook.

In Conclusion

Hook is a very powerful technique but also a double-edged sword. If used improperly, it can cause crashes of the BDS core or plugins, and in severe cases, affect the game saves.

Therefore, please be cautious when using Hooks, check your code carefully to avoid unnecessary errors.