我是靠谱客的博主 斯文草丛,最近开发中收集的这篇文章主要介绍CLAMD检测到病毒的处理,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

可通过clamd配置文件/usr/local/etc/clamd.conf中的配置项VirusEvent进行定义,默认情况下未指定VirusEvent,变量v会替换为发现的病毒名称。

# Execute a command when virus is found. In the command string %v will
# be replaced with the virus name.
# Default: no
#VirusEvent /usr/local/bin/send_sms 123456789 "VIRUS ALERT: %v"

关于VirusEvent的处理位于clamd/clamd_others.c文件中,如下函数virusaction,首先判断配置项VirusEvent是否使能,否则,退出处理。

#define VE_FILENAME "CLAM_VIRUSEVENT_FILENAME"
#define VE_VIRUSNAME "CLAM_VIRUSEVENT_VIRUSNAME"

void virusaction(const char *filename, const char *virname, const struct optstruct *opts)
{
    const struct optstruct *opt;
    char *buffer_file, *buffer_vir, *buffer_cmd, *path;
    const char *pt;
    char *env[4];

    if (!(opt = optget(opts, "VirusEvent"))->enabled)
        return;

接下来,将在环境变量中添加两个值,分别表示检查的文件名称,和病毒名称。键值由以上的宏VE_FILENAME和VE_VIRUSNAME指定。

    path   = getenv("PATH");
    env[0] = path ? strdup(path) : NULL;
    j      = env[0] ? 1 : 0;
    /* Allocate env vars.. to be portable env vars should not be freed */
    buffer_file =
        (char *)malloc(strlen(VE_FILENAME) + strlen(filename) + 2);
    if (buffer_file) {
        sprintf(buffer_file, "%s=%s", VE_FILENAME, filename);
        env[j++] = buffer_file;
    }

    buffer_vir =
        (char *)malloc(strlen(VE_VIRUSNAME) + strlen(virname) + 2);
    if (buffer_vir) {
        sprintf(buffer_vir, "%s=%s", VE_VIRUSNAME, virname);
        env[j++] = buffer_vir;
    }
    env[j++] = NULL;

以下,使用病毒名称替换掉VirusEvent配置中指定的%v变量。

    pt = opt->strarg;
    while ((pt = strstr(pt, "%v"))) {
        pt += 2;
        v++;
    }
    len = strlen(opt->strarg);
    buffer_cmd = (char *)calloc(len + v * strlen(virname) + 1, sizeof(char));
    if (!buffer_cmd) {
        if (path)
            xfree(env[0]);
        xfree(buffer_file);
        xfree(buffer_vir);
        return;
    }
    for (i = 0, j = 0; i < len; i++) {
        if (i + 1 < len && opt->strarg[i] == '%' && opt->strarg[i + 1] == 'v') {
            strcat(buffer_cmd, virname);
            j += strlen(virname);
            i++;
        } else {
            buffer_cmd[j++] = opt->strarg[i];
        }
    }

最后,启动一个新进程执行VirusEvent中指定的命令。

    pthread_mutex_lock(&virusaction_lock);
    /* We can only call async-signal-safe functions after fork(). */
    pid = vfork();
    if (pid == 0) { /* child */
        _exit(execle("/bin/sh", "sh", "-c", buffer_cmd, NULL, env));
    } else if (pid > 0) { /* parent */
        pthread_mutex_unlock(&virusaction_lock);
        while (waitpid(pid, NULL, 0) == -1 && errno == EINTR) continue;
    } else {
        pthread_mutex_unlock(&virusaction_lock);
        logg("!VirusEvent: fork failed.n");
    }
    if (path)
        xfree(env[0]);

    xfree(buffer_cmd);
    xfree(buffer_file);
    xfree(buffer_vir);
}

对于流检测方式,filename固定为字符串"stream"。

int scanstream( int odesc, unsigned long int *scanned,
    const struct cl_engine *engine, struct cl_scan_options *options,
    const struct optstruct *opts, char term)
{
    ...
    if (ret == CL_VIRUS) {
        if (context.virsize && optget(opts, "ExtendedDetectionInfo")->enabled) {
            logg("stream(%s@%u): %s(%s:%llu) FOUNDn", peer_addr, port, virname, context.virhash, context.virsize);
        } else {
            logg("stream(%s@%u): %s FOUNDn", peer_addr, port, virname);
        }
        virusaction("stream", virname, opts);

对于文件描述符检测方式(scanfd函数),通过读取/proc/self/fd/目录下,描述符对应的连接文件,获取到文件名称。

cl_error_t cli_get_filepath_from_filedesc(int desc, char **filepath)
{
    cl_error_t status        = CL_EARG;
    char *evaluated_filepath = NULL;

#ifdef __linux__
    char fname[PATH_MAX];
    char link[32];

    memset(&fname, 0, PATH_MAX);
    snprintf(link, sizeof(link), "/proc/self/fd/%u", desc);
    link[sizeof(link) - 1] = '';

    if (-1 == (linksz = readlink(link, fname, PATH_MAX - 1))) {
        cli_dbgmsg("cli_get_filepath_from_filedesc: Failed to resolve filename for descriptor %d (%s)n", desc, link);
        status = CL_EOPEN;
        goto done;
    }
    /* Success. Add null terminator */
    fname[linksz] = '';
    evaluated_filepath = CLI_STRNDUP(fname, CLI_STRNLEN(fname, PATH_MAX));

对于文件名检测方式,filename即是传递的真正的文件名称。如下可见,如果指定了扩展检测信息项ExtendedDetectionInfo,clamd将打印文件的哈希值和大小。

cl_error_t scan_callback(STATBUF *sb, char *filename, const char *msg, enum cli_ftw_reason reason, struct cli_ftw_cbdata *data)
{
    ...
    if (ret == CL_VIRUS) {
        ...
            if (context.virsize && optget(scandata->opts, "ExtendedDetectionInfo")->enabled)
                logg("~%s: %s(%s:%llu) FOUNDn", filename, virname, context.virhash, context.virsize);
            else
                logg("~%s: %s FOUNDn", filename, virname);
            virusaction(filename, virname, scandata->opts);

clamav版本:0.103.1

最后

以上就是斯文草丛为你收集整理的CLAMD检测到病毒的处理的全部内容,希望文章能够帮你解决CLAMD检测到病毒的处理所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(48)

评论列表共有 0 条评论

立即
投稿
返回
顶部