Browse code

fix 0.99.3 false negative of virus Pdf.Exploit.CVE_2016_1046-1.

Steven Morgan authored on 2017/05/24 04:56:41
Showing 4 changed files
... ...
@@ -166,7 +166,7 @@ static inline int matcher_run(const struct cli_matcher *root,
166 166
     PERF_LOG_TRIES(acmode, 0, length);
167 167
     ret = cli_ac_scanbuff(buffer, length, virname, NULL, acres, root, mdata, offset, ftype, ftoffset, acmode, ctx);
168 168
     if (ret != CL_CLEAN) {
169
-	    if (ret == CL_VIRUS) {
169
+        if (ret == CL_VIRUS) {
170 170
             if (SCAN_ALL)
171 171
                 viruses_found = 1;
172 172
             else {
... ...
@@ -178,7 +178,7 @@ static inline int matcher_run(const struct cli_matcher *root,
178 178
             saved_ret = ret;
179 179
         else
180 180
             return ret;
181
-	}
181
+    }
182 182
 
183 183
     /* due to logical triggered, pcres cannot be evaluated until after full subsig matching */
184 184
     /* cannot save pcre execution state without possible evasion; must scan entire buffer */
... ...
@@ -721,7 +721,7 @@ static int intermediates_eval(cli_ctx *ctx, struct cli_ac_lsig *ac_lsig)
721 721
     for (i = icnt; i > 0; i--) {
722 722
         if (ac_lsig->tdb.intermediates[i] == CL_TYPE_ANY)
723 723
             continue;
724
-        if (ac_lsig->tdb.intermediates[i] != cli_get_container_type(ctx, j--))
724
+        if (ac_lsig->tdb.intermediates[i] != cli_get_container_intermediate(ctx, j--))
725 725
             return 0;
726 726
     }
727 727
     return 1;
... ...
@@ -741,7 +741,7 @@ static int lsig_eval(cli_ctx *ctx, struct cli_matcher *root, struct cli_ac_data
741 741
     if (rc != CL_SUCCESS)
742 742
         return rc;
743 743
     if (cli_ac_chklsig(exp, exp_end, acdata->lsigcnt[lsid], &evalcnt, &evalids, 0) == 1) {
744
-        if(ac_lsig->tdb.container && ac_lsig->tdb.container[0] != cli_get_container_type(ctx, -1))
744
+        if(ac_lsig->tdb.container && ac_lsig->tdb.container[0] != cli_get_container(ctx, -1))
745 745
             return CL_CLEAN;
746 746
         if(ac_lsig->tdb.intermediates && !intermediates_eval(ctx, ac_lsig))
747 747
             return CL_CLEAN;
... ...
@@ -1239,11 +1239,11 @@ int cli_matchmeta(cli_ctx *ctx, const char *fname, size_t fsizec, size_t fsizer,
1239 1239
         int ret = CL_CLEAN;
1240 1240
 
1241 1241
     cli_dbgmsg("CDBNAME:%s:%llu:%s:%llu:%llu:%d:%u:%u:%p\n",
1242
-	       cli_ftname(cli_get_container_type(ctx, -1)), (long long unsigned)fsizec, fname, (long long unsigned)fsizec, (long long unsigned)fsizer,
1242
+	       cli_ftname(cli_get_container(ctx, -1)), (long long unsigned)fsizec, fname, (long long unsigned)fsizec, (long long unsigned)fsizer,
1243 1243
 	       encrypted, filepos, res1, res2);
1244 1244
 
1245 1245
     if (ctx->engine && ctx->engine->cb_meta)
1246
-	if (ctx->engine->cb_meta(cli_ftname(cli_get_container_type(ctx, -1)), fsizec, fname, fsizer, encrypted, filepos, ctx->cb_ctx) == CL_VIRUS) {
1246
+	if (ctx->engine->cb_meta(cli_ftname(cli_get_container(ctx, -1)), fsizec, fname, fsizer, encrypted, filepos, ctx->cb_ctx) == CL_VIRUS) {
1247 1247
 	    cli_dbgmsg("inner file blacklisted by callback: %s\n", fname);
1248 1248
 
1249 1249
 	    ret = cli_append_virus(ctx, "Detected.By.Callback");
... ...
@@ -1256,7 +1256,7 @@ int cli_matchmeta(cli_ctx *ctx, const char *fname, size_t fsizec, size_t fsizer,
1256 1256
 	return CL_CLEAN;
1257 1257
 
1258 1258
     do {
1259
-	if(cdb->ctype != CL_TYPE_ANY && cdb->ctype != cli_get_container_type(ctx, -1))
1259
+	if(cdb->ctype != CL_TYPE_ANY && cdb->ctype != cli_get_container(ctx, -1))
1260 1260
 	    continue;
1261 1261
 
1262 1262
 	if(cdb->encrypted != 2 && cdb->encrypted != encrypted)
... ...
@@ -1163,12 +1163,28 @@ void cli_set_container(cli_ctx *ctx, cli_file_t type, size_t size)
1163 1163
 {
1164 1164
     ctx->containers[ctx->recursion].type = type;
1165 1165
     ctx->containers[ctx->recursion].size = size;
1166
+    if (type >=  CL_TYPE_MSEXE && type != CL_TYPE_OTHER && type != CL_TYPE_IGNORED)
1167
+        ctx->containers[ctx->recursion].flag = CONTAINER_FLAG_VALID;
1168
+    else
1169
+        ctx->containers[ctx->recursion].flag = 0;
1166 1170
 }
1167 1171
 
1168
-cli_file_t cli_get_container_type(cli_ctx *ctx, int index)
1172
+cli_file_t cli_get_container(cli_ctx *ctx, int index)
1169 1173
 {
1170 1174
     if (index < 0)
1171 1175
 	index = ctx->recursion + index + 1;
1176
+    while (index >= 0 && index <= ctx->recursion) {
1177
+        if (ctx->containers[index].flag & CONTAINER_FLAG_VALID)
1178
+            return ctx->containers[index].type;
1179
+        index--;
1180
+    }
1181
+    return CL_TYPE_ANY;
1182
+}
1183
+
1184
+cli_file_t cli_get_container_intermediate(cli_ctx *ctx, int index)
1185
+{
1186
+   if (index < 0)
1187
+	index = ctx->recursion + index + 1;
1172 1188
     if (index >= 0 && index <= ctx->recursion)
1173 1189
 	return ctx->containers[index].type;
1174 1190
     return CL_TYPE_ANY;
... ...
@@ -1178,8 +1194,11 @@ size_t cli_get_container_size(cli_ctx *ctx, int index)
1178 1178
 {
1179 1179
     if (index < 0)
1180 1180
 	index = ctx->recursion + index + 1;
1181
-    if (index >= 0 && index <= ctx->recursion)
1182
-	return ctx->containers[index].size;
1181
+    while (index >= 0 && index <= ctx->recursion) {
1182
+        if (ctx->containers[index].flag & CONTAINER_FLAG_VALID)
1183
+            return ctx->containers[index].size;
1184
+        index--;
1185
+    }
1183 1186
     return 0;
1184 1187
 }
1185 1188
 
... ...
@@ -129,7 +129,9 @@ typedef struct bitset_tag
129 129
 typedef struct cli_ctx_container_tag {
130 130
     cli_file_t type;
131 131
     size_t size;
132
+    unsigned char flag;
132 133
 } cli_ctx_container;
134
+#define CONTAINER_FLAG_VALID 0x01
133 135
 
134 136
 /* internal clamav context */
135 137
 typedef struct cli_ctx_tag {
... ...
@@ -607,8 +609,9 @@ const char *cli_get_last_virus_str(const cli_ctx *ctx);
607 607
 void cli_virus_found_cb(cli_ctx *ctx);
608 608
 
609 609
 void cli_set_container(cli_ctx *ctx, cli_file_t type, size_t size);
610
-cli_file_t cli_get_container_type(cli_ctx *ctx, int index);
610
+cli_file_t cli_get_container(cli_ctx *ctx, int index);
611 611
 size_t cli_get_container_size(cli_ctx *ctx, int index);
612
+cli_file_t cli_get_container_intermediate(cli_ctx *ctx, int index);
612 613
 
613 614
 /* used by: spin, yc (C) aCaB */
614 615
 #define __SHIFTBITS(a) (sizeof(a)<<3)
... ...
@@ -2366,7 +2366,7 @@ static int cli_scanraw(cli_ctx *ctx, cli_file_t type, uint8_t typercg, cli_file_
2366 2366
 	if(nret != CL_VIRUS) switch(ret) {
2367 2367
 	    case CL_TYPE_HTML:
2368 2368
 		/* bb#11196 - autoit script file misclassified as HTML */
2369
-		if (cli_get_container_type(ctx, -2) == CL_TYPE_AUTOIT) {
2369
+		if (cli_get_container_intermediate(ctx, -2) == CL_TYPE_AUTOIT) {
2370 2370
 		    ret = CL_TYPE_TEXT_ASCII;
2371 2371
 		} else if (SCAN_HTML && (type == CL_TYPE_TEXT_ASCII || type == CL_TYPE_GRAPHICS) &&
2372 2372
                     (DCONF_DOC & DOC_CONF_HTML)) {
... ...
@@ -3146,7 +3146,7 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type)
3146 3146
 	    perf_nested_start(ctx, PERFT_SCRIPT, PERFT_SCAN);
3147 3147
 	    if((DCONF_DOC & DOC_CONF_SCRIPT) && dettype != CL_TYPE_HTML && (ret != CL_VIRUS || SCAN_ALL) && SCAN_HTML)
3148 3148
 	        ret = cli_scanscript(ctx);
3149
-	    if(SCAN_MAIL && (DCONF_MAIL & MAIL_CONF_MBOX) && ret != CL_VIRUS && (cli_get_container_type(ctx, -1) == CL_TYPE_MAIL || dettype == CL_TYPE_MAIL)) {
3149
+	    if(SCAN_MAIL && (DCONF_MAIL & MAIL_CONF_MBOX) && ret != CL_VIRUS && (cli_get_container(ctx, -1) == CL_TYPE_MAIL || dettype == CL_TYPE_MAIL)) {
3150 3150
 		ret = cli_fmap_scandesc(ctx, CL_TYPE_MAIL, 0, NULL, AC_SCAN_VIR, NULL, NULL);
3151 3151
 	    }
3152 3152
 	    perf_nested_stop(ctx, PERFT_SCRIPT, PERFT_SCAN);