ClamAV学习【9】——cvd文件解析及cli_untgz函数浏览
这个cli_untgz函数,是用来解压CVD文件的。
那么,就刚先搞清楚CVD文件的功能作用。下了源码,我们会发现,没有前面提到的*.mdb或者*.hbd等病毒签名文件。原因就是,那些文件都是由CVD文件解压生成的,是的,CVD是个病毒签名压缩文件。(下面是daily.cvd解压后的)
CVD文件,前512个bytes是一个特殊的头文件,在前面也提到过了(http://blog.csdn.net/betabin/article/details/7448447)。记录引擎病毒库的简单信息。然后后面的内容,曾经多次用UE打开,发现是乱码。所以,是个压缩文件。压缩类型,根据cli_untgz函数里面使用的gzread读取函数,可以猜到是使用zlib压缩库压缩的。然后根据函数内容,接着可以判断出,原信息是一个接着一个病毒库文件存储的。既是每个新的病毒库开始的前512bytes中,存储着名字及病毒签名数量。接着就是病毒签名信息。通过签名的病毒签名数量,可以判断正在读取的病毒签名是否读取完。
还是贴代码注释比较好理解:
//解压CVD文件到临时目录中
int cli_untgz(int fd, const char *destdir)
{
char *path, osize[13], name[101], type;
char block[TAR_BLOCKSIZE];
int nbytes, nread, nwritten, in_block = 0, fdd;
unsigned int size, pathlen = strlen(destdir) + 100 + 5;
FILE *outfile = NULL;
struct stat foo;
gzFile *infile; //提示
cli_dbgmsg("in cli_untgz()\n"); //dup复制文件描述符
if((fdd = dup(fd)) == -1) {
cli_errmsg("cli_untgz: Can't duplicate descriptor %d\n", fd);
return -1;
} //打开文件
if((infile = gzdopen(fdd, "rb")) == NULL) {
cli_errmsg("cli_untgz: Can't gzdopen() descriptor %d, errno = %d\n", fdd, errno);
if(fstat(fdd, &foo) == 0)
close(fdd);
return -1;
} //路径变量分配内存
path = (char *) cli_calloc(sizeof(char), pathlen);
if(!path) {
cli_errmsg("cli_untgz: Can't allocate memory for path\n");
gzclose(infile);
return -1;
} //开始循环读取cvd文件内容
while(1) { //每次读取512个bytes部分
nread = gzread(infile, block, TAR_BLOCKSIZE); //上一种病毒库已经读完
//且读不到下一种病毒库头信息时
//结束
if(!in_block && !nread)
break; if(nread != TAR_BLOCKSIZE) {
cli_errmsg("cli_untgz: Incomplete block read\n");
free(path);
gzclose(infile);
return -1;
} //上一种病毒库已经读完
//进行下一种病毒库文件头信息处理
//既是文件名、大小等
if(!in_block) {
//解压完病毒库
if (block[0] == '\0') /* We're done */
break; //前99bytes中是文件名属性
strncpy(name, block, 100);
name[100] = '\0'; //该斜号分割不允许
//在錡indows下应该也需要更改,不过不影响
//name只能是文件名
if(strchr(name, '/')) {
cli_errmsg("cli_untgz: Slash separators are not allowed in CVD\n");
free(path);
gzclose(infile);
return -1;
} //给路径变量赋值
//设置为$tempdir$/newvirusfilename
snprintf(path, pathlen, "%s/%s", destdir, name);
cli_dbgmsg("cli_untgz: Unpacking %s\n", path); //156位置文件标志
type = block[156]; //判断类型
switch(type) {
case '0':
case '\0':
break;
case '5':
cli_errmsg("cli_untgz: Directories are not supported in CVD\n");
free(path);
gzclose(infile);
return -1;
default:
cli_errmsg("cli_untgz: Unknown type flag '%c'\n", type);
free(path);
gzclose(infile);
return -1;
}
//设置in_block参数
//表示接下来开始写内容
in_block = 1; //关闭上一个病毒库文件指针
if(outfile) {
if(fclose(outfile)) {
cli_errmsg("cli_untgz: Cannot close file %s\n", path);
free(path);
gzclose(infile);
return -1;
}
outfile = NULL;
} //输出文件指针指向当前病毒库文件
if(!(outfile = fopen(path, "wb"))) {
cli_errmsg("cli_untgz: Cannot create file %s\n", path);
free(path);
gzclose(infile);
return -1;
} //124后的为病毒签名数量
strncpy(osize, block + 124, 12);
osize[12] = '\0'; //读取数量,用于写是否结束判断标志
if((sscanf(osize, "%o", &size)) == 0) {
cli_errmsg("cli_untgz: Invalid size in header\n");
free(path);
gzclose(infile);
fclose(outfile);
return -1;
} } else { /* write or continue writing file contents */
//写入path病毒文件
nbytes = size > TAR_BLOCKSIZE ? TAR_BLOCKSIZE : size;
nwritten = fwrite(block, 1, nbytes, outfile); if(nwritten != nbytes) {
cli_errmsg("cli_untgz: Wrote %d instead of %d (%s)\n", nwritten, nbytes, path);
free(path);
gzclose(infile);
return -1;
} //减去已经写了的病毒签名数
//判断是否结束
size -= nbytes;
if(size == 0)
in_block = 0;
}
} if(outfile)
fclose(outfile); gzclose(infile);
free(path);
return 0;
}
原文:http://blog.csdn.net/betabin/article/details/7456873
ClamAV学习【9】——cvd文件解析及cli_untgz函数浏览的更多相关文章
- Android学习----AndroidManifest.xml文件解析
一个Android应用程序的结构: 一.关于AndroidManifest.xml AndroidManifest.xml 是每个android程序中必须的文件.它位于整个项目的根目录,描述了pack ...
- mybatis 学习三 关键文件解析
1: mybatis-config.xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYP ...
- 简单学习一下ibd数据文件解析
来源:原创投稿 作者:花家舍 简介:数据库技术爱好者. GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 简单学习一下数据文件解析 这是尝试使用Golang语言简单解析My ...
- 八、Android学习第七天——XML文件解析方法(转)
(转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 八.Android学习第七天——XML文件解析方法 XML文件:exten ...
- CocosBuilder 学习笔记(3) AnimationManager 与 ccbi 文件解析
[CocosBuilder]学习笔记目录 1. 相关的类 先介绍和AnimationManager相关的几个类: CCBSequence 时间线.有成员duration(时间线时间,默认10秒).na ...
- 学习 WebService 第二步:知识准备——WSDL文件解析
原文地址:https://www.cnblogs.com/yzw23333/p/7245104.html Web service中一个 WSDL 对应一个 web service地址. 可以想象成一个 ...
- android基础知识13:AndroidManifest.xml文件解析
注:本文转载于:http://blog.csdn.net/xianming01/article/details/7526987 AndroidManifest.xml文件解析. 1.重要性 Andro ...
- Android之AndroidManifest.xml文件解析
转自:Android学习笔记之AndroidManifest.xml文件解析 一.关于AndroidManifest.xml AndroidManifest.xml 是每个android程序中必须的文 ...
- [置顶] Android学习系列-Android中解析xml(7)
Android学习系列-Android中解析xml(7) 一,概述 1,一个是DOM,它是生成一个树,有了树以后你搜索.查找都可以做. 2,另一种是基于流的,就是解析器从头到尾解析一遍xml文件. ...
随机推荐
- Selenium Webdriver——Xpath轴定位(preceding)
1.preceding-sibling 选取当前节点之前的所有同级节点 text=出发之前的同级节点: 2.preceding 选取当前节点开始标签之前的所有节点 text=出发节点标签之前的所有i ...
- c# 二维码支持中文
/// <summary> /// 生成二维码,保存成图片 /// </summary> static void Generate1(string text) { Barcod ...
- String(byte[] bytes, Charset charset) 和 getBytes() 使用
转自:https://techbirds.iteye.com/blog/1855960 @Test public void testBytes(){ //字节数 //中文:ISO:1 GBK:2 UT ...
- nginx错误页面重定向
一.Nginx错误页面优雅显示的原因? 当我们访问网站时,由于特殊的原因,经常会出现诸如403,404,503等错误,这极大的影响用户的访问体验,所以我们很有必要做一下错误页面的优雅显示,以提升用 ...
- 关于使用testng的retry问题
总体是利用TestNG里面的IRetryAnalyzer.TestListenerAdapter接口来实现相关问题 1.定义一个自己的retryanalyzer import org.testng.I ...
- jquery.validate ajax方式验证
在做网站的时候有一块需要用到jquery.validate插件 ajax方式的方式来验证原始密码是否正确,研究了研究加上博客园朋友的帮助,终于实现了.贴出代码 <script type=&quo ...
- 拒绝用户登录:/bin/false和/usr/sbin/nologin
要拒绝系统用户登录,可以将其shell设置为/usr/sbin/nologin或者/bin/false 1 # usermod -s | --shell /usr/sbin/nologin usern ...
- 3-java_string学习笔记:
java中String的常用方法
- 清官谈mysql中utf8和utf8mb4区别
清官谈mysql中utf8和utf8mb4区别 发布时间:2015 年 10 月 4 日 发布者: OurMySQL 来源:JavaRanger - 专注JAVA高性能程序开发.JVM.Mysql优化 ...
- Laravel/Homestead storage:link -> symlink(): Protocol error
I'm trying to run the following artisan command: php artisan storage:link I get this error: [ErrorEx ...