FreeBSD 3.0 Character Drivers(part 1)
Cain

Uhg, so I tried to write this thing a couple times. What did I learn,
well, I learn best by example, and I belive I can explain it best that way
as well. I would recommend you check out www.freebsd.org for further
knowledge on character drivers, but in all honesty their page is so far
out of date the LKM structs have changed three times. Anyways, look at the
code I have provided and follow along.

Part 1
We will create /dev/cain. It's a character device under FreeBSD 3.0. We
will write a driver to do minimal functions to talk to it. But this will
give us some idea as to how the kernel werx, and we can do more fun stuff
later. If you start having questions about how stuff werx, refer to the
include files. Again, the FreeBSD device tutorial is out of date, the
include files are the easiest way to learn I've found. Remember, this is
not some elite hack, this is just learning something.

Section 1: explanation of the internals
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The switch table:
The kernel keeps an internal array of (struct cdevsw *). Refer to
/usr/include/sys/conf.h for the complete structure. The structure
cain_dev will be stuck into the kernel array so the kernel knows what
functions to execute for our device. The function names return types are
pretty self explanitory.

		 ___ name of our particular structure
		|
struct cdevsw cain_dev = {
        (d_open_t *)    cain_open,
	    |		   |
	    |		   |___ function to call
	return type

MOD_DEV:
This creates the cain structure, it's really a #define from
/usr/include/sys/lkm.h. "cain" will be the name of the module. LM_DT_CHAR
tells the kernel that this will be a character driver. LKM_ANON tells the
kernel to choose a random(as in the next in sequence) major number for
this driver. "&cain_dev" tell the kernel to stick the cain_dev struct into
the character device array.

   MOD_DEV( cain, LM_DT_CHAR, LKM_ANON, &cain_dev);
	     |	     |		|	     |
    module name	     |	      major number   |
		  device type		   chardevice structure 
					   to use
	
int cain_mod():
This is just the function run when you do a modload. DISPATCH sticks all
of the necessary info into the kernel. "cain" is whatever was specified in
the MOD_DEV call. "lkmtp" is the lkm table. I tried to mess with the
values but it didnt seem to work(/usr/include/sys/lkm.h again). "cmd" is
the command being passed(either LKM_E_LOAD, LKM_E_UNLOAD, LKM_E_STAT).
"ver" is the version, it should always be 1. the last three cain_load's
point to what function to call for each command(the LKM_E_<blah>). I chose
to call the same function each time, and check the command value in the
function. NOTE: this function must have the same name as the KMOD=
variable in the Makefile.
				    __ load function
   				   |		
  DISPATCH(cain, lkmtp, cmd, ver, cain_load, cain_load, cain_load);
	    |	   |	 |    |			   |	   |
     device name   |  the     |__ the LKM version  |	Stat function
		   |  command			   |
		LKM table			Unload
		to use				function


int cain_load():
This function basiclly just sets up stuff upon loading, unloading, or a
status check.

in funcs.h:

look in /usr/include/sys/conf.h for the parameters an stuff

cain_open() and cain_close() have the same parameters:
int cain_open(the device, major #, minor #, calling process inf0z)

/usr/include/sys/uio.h for more info...
cain_write() and cain_read() (if there were one) have these parameters
int cain_write(the device, input/output structure, ioflags)

Section 2: how ta load it
~~~~~~~~~~~~~~~~~~~~~~~~~
Well, heres what you do. "modload cain_mod.o". Then it will load into the
kernel. type "modstat" to get the inf0z...:

   cain# modload cain_mod.o 
   Cain module has been loaded...
   Module loaded as ID 2
   cain# modstat
   Type     Id Off Loadaddr Size Info     Rev Module Name
   EXEC      0   0 f5a31000 0020 f5a38010   1 linux_mod
   SYSCALL   1 126 f5ac2000 0008 f5ac3010   1 n_setreuid (part 2)
   DEV       2 128 f5bc6000 0008 f5bc704c   1 cain_mod
   cain# 

Notice that the offset is 128. This is also the major number. Now we
create the device that the driver will communicate with:

   cain# mknod /dev/cain c 128 0

/dev/cain is the name, "c" for character, 128 is the major, an 0 is the
minor. Now you can use a simple test program to do things to the device:

   #include <stdio.h>
   #include <fcntl.h>

   int main()
   {
      int fd;

      fd = open("/dev/cain", O_WRONLY);
      write(fd, "c", 1);
      close(fd);
   }

Will give the output:

   Cain driver opened
   maj: 2 min: 8192 id: 0
   You said 'c' to cain
   Cain is going away now

Section 3: Stuff ta do
~~~~~~~~~~~~~~~~~~~~~~
Getting inta part two, not yet decided what to write about, trojan system
calls, or messing with /dev/lkm. /dev/lkm is where modstat gets the
current LKM stuff from, so you can see potential there. Well, let's see,
expect part 2 ta be about /dev/lkm stuff, seeing as /dev/lkm is a
character device, we can use our new found knowledge of character drivers
to trojan /dev/lkm! It is a quick way to hide stuff you don't want
found... but untill then play around, its the only way to learn... try new
things, do what people say you can't, then make them look stupid.

greetz:  rc, alec, smiler, JP(i guess it was destiny that you would merge
with happyhacker, heh heh heh), gH(thanx for givin the fedz somebody else
to look for)
