Minimalistic hook engine for x86_64/Linux
Imagine we'd like to hook read
function from libc:
ssize_t read(int fd, void *buf, size_t count);
Whenever read
is called, we want to transfer control to
__wrap__read
(our custom function), as if read
was
defined as follows:
ssize_t read(int fd, void *buf, size_t count) {
return __wrap__read(fd, buf, count);
}
Hook-engine
literally patches read
code in memory. Since read
was altered, we need
another function that performs identically to unmodified
read
. This is called a trampoline, and hook-engine
can create one.
Let's start with a trampoline definition:
ssize_t __real__read(int fd, void *buf, size_t count);
HOOK_DEFINE_TRAMPOLINE(__real__read);
HOOK_DEFINE_TRAMPOLINE
reserves space in the
program's code
segment. Hook-engine
renders tramoline's code there at runtime.
Now we can implement fake descriptor #42
, yielding
a quote from Douglas Adams:
ssize_t __wrap__read(int fd, void *buf, size_t count) {
if (fd == 42) {
static const char msg[] = "answer to life the universe and everything";
if (count >= sizeof msg) count = (sizeof msg) - 1;
memcpy(buf, msg, count);
return count;
}
return __real__read(fd, buf, count);
}
Finally install the hook and render the trampoline:
if (hook_install(read, __wrap__read, __real__read) != 0) {
fprintf(stderr, "%s\n", hook_last_error());
exit(EXIT_FAILURE);
}