zoukankan      html  css  js  c++  java
  • ClamAV学习【4】——cli_magic_scandesc函数浏览

    今晚继续浏览ClamAV代码,挖掘到了cli_magic_scandesc函数,发现前面包装了很多次扫描函数,这里就是最后一层的感觉。一些扫描限制判断加上文件类型判断,采用不同扫描函数处理。

    (PS:发现这些函数个头都很大,虽然按着功能分段好理解,但是书本不是说一个函数一个功能模块么?难道是不实际,还是理解错误?)

    代码分析如下:

    //magic,说明这很神奇
    int cli_magic_scandesc(int desc, cli_ctx *ctx)
    {
    	int ret = CL_CLEAN;
    	cli_file_t type, dettype = 0;
    	struct stat sb;
    	uint8_t typercg = 1;
    
    	//获取文件属性stat结构
        if(fstat(desc, &sb) == -1) {
    	cli_errmsg("magic_scandesc: Can't fstat descriptor %d
    ", desc);
    	return CL_EIO;
        }
    
    	//文件太小无需扫描
        if(sb.st_size <= 5) {
    	cli_dbgmsg("Small data (%u bytes)
    ", (unsigned int) sb.st_size);
    	return CL_CLEAN;
        }
    
    	//引擎已经构建
        if(!ctx->engine) {
    	cli_errmsg("CRITICAL: engine == NULL
    ");
    	return CL_EMALFDB;
        }
    
    	//默认模式扫描
        if(!ctx->options) { /* raw mode (stdin, etc.) */
    	cli_dbgmsg("Raw mode: No support for special files
    ");
    	if((ret = cli_scandesc(desc, ctx, 0, 0, NULL, AC_SCAN_VIR)) == CL_VIRUS)
    	    cli_dbgmsg("%s found in descriptor %d
    ", *ctx->virname, desc);
    	return ret;
        }
    
    	//是否超过设置的扫描限制
        if(cli_updatelimits(ctx, sb.st_size)!=CL_CLEAN)
            return CL_CLEAN;
    
    	//邮件或者压缩文件扫描
        if((SCAN_MAIL || SCAN_ARCHIVE) && ctx->limits && ctx->limits->maxreclevel && ctx->recursion > ctx->limits->maxreclevel) {
            cli_dbgmsg("Archive recursion limit exceeded (level = %u).
    ", ctx->recursion);
    	return CL_CLEAN;
        }
    
    	//定位文件,找到文件类型
        lseek(desc, 0, SEEK_SET);
        type = cli_filetype2(desc, ctx->engine);
        if(type == CL_TYPE_ERROR) {
    	cli_dbgmsg("cli_magic_scandesc: cli_filetype2 returned CL_TYPE_ERROR
    ");
    	return CL_EIO;
        }
        lseek(desc, 0, SEEK_SET);
    
    	//非忽略类型还有个什么。需要研究
        if(type != CL_TYPE_IGNORED && ctx->engine->sdb) {
    	if((ret = cli_scanraw(desc, ctx, type, 0, &dettype)) == CL_VIRUS)
    	    return CL_VIRUS;
    	lseek(desc, 0, SEEK_SET);
        }
    
        ctx->recursion++;
    
    	//根据不同的类型,让文件见鬼去吧
        switch(type) {
    	case CL_TYPE_IGNORED:
    	    break;
    
    	case CL_TYPE_RAR:
    #ifdef ENABLE_UNRAR
    	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_RAR))
    		ret = cli_scanrar(desc, ctx, 0, NULL);
    #else
    	    cli_warnmsg("RAR code not compiled-in
    ");
    #endif
    	    break;
    
    	case CL_TYPE_ZIP:
    	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ZIP))
    		ret = cli_unzip(desc, ctx);
    	    break;
    
    	case CL_TYPE_GZ:
    	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_GZ))
    		ret = cli_scangzip(desc, ctx);
    	    break;
    
    	case CL_TYPE_BZ:
    #ifdef HAVE_BZLIB_H
    	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_BZ))
    		ret = cli_scanbzip(desc, ctx);
    #endif
    	    break;
    	case CL_TYPE_ARJ:
    	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ARJ))
    		ret = cli_scanarj(desc, ctx, 0, NULL);
    	    break;
    
            case CL_TYPE_NULSFT:
    	  if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_NSIS))
    		ret = cli_scannulsft(desc, ctx, 0);
    	    break;
    
            case CL_TYPE_AUTOIT:
    	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_AUTOIT))
    		ret = cli_scanautoit(desc, ctx, 23);
    	    break;
    
    	case CL_TYPE_MSSZDD:
    	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_SZDD))
    		ret = cli_scanszdd(desc, ctx);
    	    break;
    
    	case CL_TYPE_MSCAB:
    	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CAB))
    		ret = cli_scanmscab(desc, ctx, 0);
    	    break;
    
    	case CL_TYPE_HTML:
    	    if(SCAN_HTML && (DCONF_DOC & DOC_CONF_HTML))
    		ret = cli_scanhtml(desc, ctx);
    	    break;
    
    	case CL_TYPE_HTML_UTF16:
    	    if(SCAN_HTML && (DCONF_DOC & DOC_CONF_HTML))
    		ret = cli_scanhtml_utf16(desc, ctx);
    	    break;
    
    	case CL_TYPE_SCRIPT:
    	    if((DCONF_DOC & DOC_CONF_SCRIPT) && dettype != CL_TYPE_HTML)
    	        ret = cli_scanscript(desc, ctx);
    	    break;
    
    	case CL_TYPE_RTF:
    	    if(SCAN_ARCHIVE && (DCONF_DOC & DOC_CONF_RTF))
    		ret = cli_scanrtf(desc, ctx);
    	    break;
    
    	case CL_TYPE_MAIL:
    	    if(SCAN_MAIL && (DCONF_MAIL & MAIL_CONF_MBOX))
    		ret = cli_scanmail(desc, ctx);
    	    break;
    
    	case CL_TYPE_TNEF:
    	    if(SCAN_MAIL && (DCONF_MAIL & MAIL_CONF_TNEF))
    		ret = cli_scantnef(desc, ctx);
    	    break;
    
    	case CL_TYPE_UUENCODED:
    	    if(DCONF_OTHER & OTHER_CONF_UUENC)
    		ret = cli_scanuuencoded(desc, ctx);
    	    break;
    
    	case CL_TYPE_MSCHM:
    	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CHM))
    		ret = cli_scanmschm(desc, ctx);
    	    break;
    
    	case CL_TYPE_MSOLE2:
    	    if(SCAN_OLE2 && (DCONF_ARCH & ARCH_CONF_OLE2))
    		ret = cli_scanole2(desc, ctx);
    	    break;
    
    	case CL_TYPE_POSIX_TAR:
    	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_TAR))
    		ret = cli_scantar(desc, ctx, 1);
    	    break;
    
    	case CL_TYPE_OLD_TAR:
    	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_TAR))
    		ret = cli_scantar(desc, ctx, 0);
    	    break;
    
    	case CL_TYPE_BINHEX:
    	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_BINHEX))
    		ret = cli_scanbinhex(desc, ctx);
    	    break;
    
    	case CL_TYPE_SCRENC:
    	    if(DCONF_OTHER & OTHER_CONF_SCRENC)
    		ret = cli_scanscrenc(desc, ctx);
    	    break;
    
    	case CL_TYPE_RIFF:
    	    if(SCAN_ALGO && (DCONF_OTHER & OTHER_CONF_RIFF))
    		ret = cli_scanriff(desc, ctx->virname);
    	    break;
    
    	case CL_TYPE_GRAPHICS:
    	    if(SCAN_ALGO && (DCONF_OTHER & OTHER_CONF_JPEG))
    		ret = cli_scanjpeg(desc, ctx->virname);
    	    break;
    
            case CL_TYPE_PDF: /* FIXMELIMITS: pdf should be an archive! */
    	    if(SCAN_PDF && (DCONF_DOC & DOC_CONF_PDF))
    		ret = cli_scanpdf(desc, ctx, 0);
    	    break;
    
    	case CL_TYPE_CRYPTFF:
    	    if(DCONF_OTHER & OTHER_CONF_CRYPTFF)
    		ret = cli_scancryptff(desc, ctx);
    	    break;
    
    	case CL_TYPE_ELF:
    	    if(SCAN_ELF && ctx->dconf->elf)
    		ret = cli_scanelf(desc, ctx);
    	    break;
    
    	case CL_TYPE_SIS:
    	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_SIS))
    		ret = cli_scansis(desc, ctx);
    	    break;
    
    	case CL_TYPE_BINARY_DATA:
    	    ret = cli_check_mydoom_log(desc, ctx->virname);
    	    break;
    
    	default:
    	    break;
        }
    
        ctx->recursion--;
    
    	//没有检查植入性pe文件
        if(type == CL_TYPE_ZIP && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ZIP)) {
    	if(sb.st_size > 1048576) {
    	    cli_dbgmsg("cli_magic_scandesc: Not checking for embedded PEs (zip file > 1 MB)
    ");
    	    typercg = 0;
    	}
        }
    
        /* CL_TYPE_HTML: raw HTML files are not scanned, unless safety measure activated via DCONF */
        if(type != CL_TYPE_IGNORED && (type != CL_TYPE_HTML || !(DCONF_DOC & DOC_CONF_HTML_SKIPRAW)) && ret != CL_VIRUS && !ctx->engine->sdb) {
    	if(cli_scanraw(desc, ctx, type, typercg, &dettype) == CL_VIRUS)
    	    return CL_VIRUS;
        }
    
        ctx->recursion++;
        lseek(desc, 0, SEEK_SET);
        switch(type) {
    	case CL_TYPE_TEXT_ASCII:
    	    if((DCONF_DOC & DOC_CONF_SCRIPT) && dettype != CL_TYPE_HTML)
    	        ret = cli_scanscript(desc, ctx);
    	    break;
    	/* Due to performance reasons all executables were first scanned
    	 * in raw mode. Now we will try to unpack them
    	 */
    	case CL_TYPE_MSEXE:
    	    if(SCAN_PE && ctx->dconf->pe)
    		ret = cli_scanpe(desc, ctx);
    	    break;
    
    	default:
    	    break;
        }
        ctx->recursion--;
    
        switch(ret) {
    	case CL_EFORMAT:
    	case CL_EMAXREC:
    	case CL_EMAXSIZE:
    	case CL_EMAXFILES:
    	    cli_dbgmsg("Descriptor[%d]: %s
    ", desc, cl_strerror(ret));
    	    return CL_CLEAN;
    	default:
    	    return ret;
        }
    }
    

    原文:http://blog.csdn.net/betabin/article/details/7424762 

  • 相关阅读:
    如何强制360浏览器以极速模式打开页面
    如何解决Android SDK无法下载Package的问题(.net)
    Xamarin 安装步骤
    使用require.js和backbone实现简单单页应用实践
    HBuilder之初体验
    ClassLoader&双亲委派&类初始化过程
    List remove ConcurrentModificationException源码分析
    二十九、简谈设计模式
    二十八、Java基础--------正则表达式
    二十七、JDK1.5新特性---Annotation
  • 原文地址:https://www.cnblogs.com/sunylat/p/6393420.html
Copyright © 2011-2022 走看看