/* exec.c 1.0.4 by Pat Szuta * * exec.c is a kernel module which allows administrators to log all the * commands executed by users. Although many have done this sort of * thing, I haven't seen any public releases, so here it is. * The basic output looks like this: Nov 15 00:42:27 perly kernel: EXECVE(0)[4837]: /bin/ps uax * The EXECVE()[] format is: EXECVE(UID)[PID]. * I suggest redirecting kern.info to your own file, because that's where * exec.c will log its stuff. You can do this by adding this line to * your /etc/sysconf.log, and restarting it: kern.info /path/to/myfile * Applaud gersh for catching a nasty little syslog thingy that caused * the output to be printed twice. * Do whatever you want with this code, just leave my name on it. If you * have any comments/questions/mods, send them to perly@xnet.com * Oh, and if you do use this module, drop me an email, so that if I * update it, you'll be the first one to know. Good luck :) * To compile and execute: gcc exec.c -c insmod exec.o * Changelog: dec 6, 99 I have just recieved an email from Pavel Urban () with code to fix a major bug!! Thanks Pavel!!!!!! He says that the accual person who found the bug is Belgarat (svatopluk.dedic@netbeans.cz). Thanks a lot to him too! nov 18, 99 Recieving not too many complaints, I have decided to make this into a stable version. I have noticed that if a user does 'ls *' in a big directory, the shell will expand the * to all the files in the directory and pass them as arguments. Thus I have limited the number of arguments logged to 10. This should be enough for everyone, and enough to keep syslog from bugging you about long prints :) (You can change the define if you want to). nov 18, 99 After a bug report, I have improved the pointer error checking routine. Before it would not log any arguments, now it should. Note that this is the beta version. nov 15, 99 Gersh caught a rather nasty bug. If a user wrote a program which did execl("some", "stuff"); without a NULL at the end, the kernel would oops. So, I added a little pointer checking. */ #define MODULE #define __KERNEL__ #include #include #include #include #include #include #include #include #include #define ARGS_LOGGED 10 /* Max number of arguments logged */ int (*orig_execve)(struct pt_regs); void execve_log(char *, char **); extern void *sys_call_table[]; int hacked_execve(struct pt_regs regs) { int error; char * filename; lock_kernel(); filename = getname((char *) regs.ebx); error = PTR_ERR(filename); if (IS_ERR(filename)) goto out; execve_log(filename, (char **) regs.ecx); error = do_execve(filename, (char **) regs.ecx, (char **) regs.edx, ®s); if (error == 0) current->flags &= ~PF_DTRACE; putname(filename); out: unlock_kernel(); return error; } void execve_log(char *file, char **argv) { int args_logged = ARGS_LOGGED; char *tmp; /* pavel/belgarat's fix */ printk(KERN_INFO "EXECVE(%d)[%d]: %s ", current->uid, current->pid, file); *argv++; while(*argv && args_logged--) { if(IS_ERR(tmp = getname(*argv))) /* Pointer checking, changed dec 6, 99 */ break; printk("%s ", tmp); putname(tmp); /* (frees up what getname allocated) */ } printk("\n"); } int init_module(void) { orig_execve = sys_call_table[SYS_execve]; sys_call_table[SYS_execve] = hacked_execve; printk(KERN_INFO "execve() backdoor version 1.0.4 by Perly loaded.\n"); return(0); } void cleanup_module(void) { sys_call_table[SYS_execve] = orig_execve; printk(KERN_INFO "execve() backdoor version 1.0.4 by Perly unloaded.\n"); }