Chinaunix首页 | 论坛 | 博客
  • 博客访问: 151186
  • 博文数量: 32
  • 博客积分: 2053
  • 博客等级: 大尉
  • 技术积分: 382
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-09 12:45
文章分类

全部博文(32)

文章存档

2011年(12)

2010年(20)

分类: LINUX

2010-06-09 21:34:03

    这周看到有人写clamAV杀毒软件的代码分析(http://blog.csdn.net/littlehedgehog),以前一直想找个杀毒软件想看看,所以就看了一眼。在这个过程中发现其实clamAV并非杀毒了,而是查毒。它使用了一种手段叫做file on access。就是用户在openexec一个文件的时候,它在内核态截获到用户的这种操作,获取用户要访问的文件信息,并对这个文件进行查毒操作。如果发现文件有毒,则open失败,否则正常返回。因为是在内核态进行操作,对用户来说是透明的。自己这种手段比较感兴趣,看了作者的分析知道是通过dazuko库实现的,自己就从网上找了很多资料,并下载了1.0.0的代码,因为感觉最新的代码不注重程序的流程性,而花很多代码在处理错误和移植性上。1.0.0的代码简单明了,而且万变不离其宗。

一:dazuko的结构分析

dazuko实际上实现了一个字符型设备驱动程序,它在加载进内核时,布置hook函数,截获用户操作。下面是一次运行流程图。

上面显示了一个查毒软件,下面对查毒软件编程模式进行分析。


int    RUNNING = 1;    /* flag for main loop */

int main(void)
{
    char        buffer[10];
    int        dev_major;
    int        dazuko_device;
    struct access_t    acc;
    struct option_t    opt;

    /* make sure we are root */
    if (getuid() != 0)//必须是root用来才能运行,防止普通权限的人通过此功能干扰其他人的文件操作

    {
        printf("only root can run this program\n");
        return -1;
    }

    /* open dazuko device */
      dazuko_device = open("/dev/dazuko", 0);//打开dazuko字符设备

    if (dazuko_device < 0)
    {
        printf("error: failed to open dazuko device\n");
        return -1;
    }

    printf("/dev/dazuko opened successfully\n");

    /* read major device number */
    if (read(dazuko_device, buffer, sizeof(buffer)) < 1)//从该设备中读取到设备编号。。

    {
            printf("error: failed to read from /dev/dazuko\n");
        close(dazuko_device);
        return -1;
    }

    dev_major = atoi(buffer);

    printf("major device number read successfully : %d\n", dev_major);

    /* detect TERM signals */
    signal(15, sigterm);

    /* set access mask */
    bzero(&opt, sizeof(struct option_t));
    opt.command = SET_ACCESS_MASK;
    opt.buffer[0] = ON_OPEN | ON_CLOSE | ON_EXEC;//查毒软件所关心的事件,如文件打开、文件执行

    opt.buffer_length = 1;
    if (ioctl(dazuko_device, _IOW(dev_major, IOCTL_SET_OPTION, void *), &opt) != 0)//通过ioctl告知内核中dazuko驱动

    {
        printf("error: failed to set option\n");
        close(dazuko_device);
        return -1;
    }

    printf("set access mask successfully\n");

    /* set scan path */
    bzero(&opt, sizeof(struct option_t));
    opt.command = ADD_INCLUDE_PATH;//设置想监听哪个文件夹下文件的操作

    strcpy(opt.buffer, "/home/");
    opt.buffer_length = strlen(opt.buffer) + 1;
    if (ioctl(dazuko_device, _IOW(dev_major, IOCTL_SET_OPTION, void *), &opt) != 0)
    {
        printf("error: failed to set option\n");
        close(dazuko_device);
        return -1;
    }

    printf("set scan path successfully\n");

    while (RUNNING)
    {
        if (ioctl(dazuko_device, _IOR(dev_major, IOCTL_GET_AN_ACCESS, struct access_t *), &acc) == 0)
        {//监听特定事件的发生,直到一个特定的事件发生才返回。并在acc中保存了文件的信息,如用户想要打开的文件名。

            
            /* always allow access */
            /*
            这里是查毒软件的主要部分,要对这个文件进行分析,是否被感染。
            最后在acc中设置标记位,告知设备驱动是否允许用户的打开或者执行文件操作
            */

            acc.deny = 0;//这里默认忽略了上述部分,直接标记允许。


            /* return access (IMPORTANT, the kernel is waiting for us!) */
            if (ioctl(dazuko_device, _IOW(dev_major, IOCTL_RETURN_ACCESS, struct access_t *), &acc) != 0)
            {//告知设备驱动查毒软件的分析结果。

                printf("error: failed to return access\n");
                RUNNING = 0;
            }
        }
        else
        {
            printf("warning: failed to get an access\n");
        }
    }

    /* close dazuko device */
      close(dazuko_device);

    return 0;
}


阅读(1776) | 评论(0) | 转发(1) |
0

上一篇:经典文章集

下一篇:dazuko1.0.0代码分析(2)

给主人留下些什么吧!~~