Hooking System Call

システムコールを自作できるので,当然上書きも出来る.

ここでは,sysent[]にある既存のシステムコールを上書きすることでhookを行う.

Syscall hook

早速実装する.

mkdirをフックし,デバッグメッセージを出力するようなKLD

#include <sys/types.h>
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/module.h>
#include <sys/sysent.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/syscall.h>
#include <sys/sysproto.h>

static int
mkdir_hook(struct thread *td, void *syscall_args)
{
    struct mkdir_args *uap; // in <sys/sysproto.h>
    uap = (struct mkdir_args*)syscall_args;

    char path[255];
    size_t done;
    int error;

    error = copyinstr(uap->path, path, 255, &done);

    if (error != 0)
        return (error);

    uprintf("The directory \"%s\" will be created with the following permissions: %o\n", path, uap->mode);

    return (sys_mkdir(td, syscall_args));
}

static int
load(struct module *module, int cmd, void *arg)
{
    int error = 0;

    switch (cmd) {
    case MOD_LOAD:
        sysent[SYS_mkdir].sy_call = (sy_call_t *)mkdir_hook;
        break;
    case MOD_UNLOAD:
        sysent[SYS_mkdir].sy_call = (sy_call_t *)sys_mkdir;
        break;
    default:
        error = EOPNOTSUPP;
        break;
    }

    return (error);
}

static moduledata_t mkdir_hook_mod = {
    "mkdir_hook",
    load,
    NULL
};

DECLARE_MODULE(mkdir_hook, mkdir_hook_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);

フックの追加,削除はsysentを書き換えるだけでいい.

hookされるシステムコールは,<sys/sysproto.h>にあるsys_

各システムコールのsysentでのオフセットは<sys/syscall.h>

ビルド,ロードしてmkdirしてみると,

$ make
machine -> /usr/src/11/sys/amd64/include
x86 -> /usr/src/11/sys/x86/include
Warning: Object directory not changed from original /home/vagrant/src/hook
cc -O2 -pipe  -fno-strict-aliasing -Werror -D_KERNEL -DKLD_MODULE -nostdinc   -I. -I/usr/src/11/sys -fno-common  -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer   -MD  -MF.depend.mkdir_hook.o -MTmkdir_hook.o -mcmodel=kernel -mno-red-zone -mno-mmx -mno-sse -msoft-float  -fno-asynchronous-unwind-tables -ffreestanding -fwrapv -fstack-protector -Wall -Wredundant-decls -Wnested-externs -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith -Winline -Wcast-qual -Wundef -Wno-pointer-sign -D__printf__=__freebsd_kprintf__ -Wmissing-include-dirs -fdiagnostics-show-option -Wno-unknown-pragmas -Wno-error-tautological-compare -Wno-error-empty-body -Wno-error-parentheses-equality -Wno-error-unused-function -Wno-error-pointer-sign -Wno-error-shift-negative-value -Wno-address-of-packed-member  -mno-aes -mno-avx  -std=iso9899:1999 -c mkdir_hook.c -o mkdir_hook.o
ld -m elf_x86_64_fbsd -d -warn-common -r -d -o mkdir_hook.ko mkdir_hook.o
:> export_syms
awk -f /usr/src/11/sys/conf/kmod_syms.awk mkdir_hook.ko  export_syms | xargs -J% objcopy % mkdir_hook.ko
objcopy --strip-debug mkdir_hook.ko
$ sudo kldload ./mkdir_hook.ko
$ mkdir tmp
The directory "tmp" will be created with the following permissions: 777
$ l
total 20
-rw-r--r--  1 vagrant  vagrant    88 Oct 30 02:58 Makefile
-rw-r--r--  1 vagrant  vagrant     0 Oct 30 03:14 export_syms
lrwxr-xr-x  1 vagrant  vagrant    29 Oct 30 03:14 machine -> /usr/src/11/sys/amd64/include
-rw-r--r--  1 vagrant  vagrant  1212 Oct 30 03:11 mkdir_hook.c
-rw-r--r--  1 vagrant  wheel    3584 Oct 30 03:14 mkdir_hook.ko
-rw-r--r--  1 vagrant  vagrant  3312 Oct 30 03:14 mkdir_hook.o
drwxr-xr-x  2 vagrant  vagrant   512 Oct 30 03:14 tmp
lrwxr-xr-x  1 vagrant  vagrant    27 Oct 30 03:14 x86 -> /usr/src/11/sys/x86/include

はいできた.

参考文献

Designing BSD Rootkits