Browse code

allow wildcarded prefix when signature contains static pattern of length AC_DEFAULT_DEPTH

git-svn: trunk@2047

Tomasz Kojm authored on 2006/06/27 03:26:32
Showing 4 changed files
... ...
@@ -1,3 +1,8 @@
1
+Mon Jun 26 20:23:22 CEST 2006 (tk)
2
+----------------------------------
3
+  * libclamav: allow wildcarded prefix when signature contains static
4
+	       pattern of length AC_DEFAULT_DEPTH
5
+
1 6
 Sun Jun 25 14:29:22 CEST 2006 (tk)
2 7
 ----------------------------------
3 8
   * libclamav/matcher-ac.c: fix possible false matches of alternatives
... ...
@@ -110,11 +110,11 @@ struct cli_bm_patt {
110 110
 };
111 111
 
112 112
 struct cli_ac_patt {
113
-    short int *pattern;
114
-    unsigned int length, mindist, maxdist;
113
+    short int *pattern, *prefix;
114
+    unsigned int length, mindist, maxdist, prefix_length;
115 115
     char *virname, *offset;
116 116
     const char *viralias;
117
-    unsigned short int sigid, parts, partno, alt, *altn;
117
+    unsigned short int sigid, parts, partno, alt, *altn, alt_pattern;
118 118
     unsigned short type, target;
119 119
     char **altc;
120 120
     struct cli_ac_patt *next;
... ...
@@ -190,7 +190,10 @@ static void cli_freepatt(struct cli_ac_patt *list)
190 190
     handler = list;
191 191
 
192 192
     while(handler) {
193
-	free(handler->pattern);
193
+	if(handler->prefix)
194
+	    free(handler->prefix);
195
+	else
196
+	    free(handler->pattern);
194 197
 	free(handler->virname);
195 198
 	if(handler->offset && (!handler->sigid || handler->partno == 1))
196 199
 	    free(handler->offset);
... ...
@@ -227,8 +230,12 @@ inline static int cli_findpos(const char *buffer, unsigned int depth, unsigned i
227 227
 {
228 228
 	unsigned int bufferpos = offset + depth;
229 229
 	unsigned int postfixend = offset + length;
230
-	unsigned int i, j, alt = 0, found;
230
+	unsigned int i, j, alt = pattern->alt_pattern, found;
231
+
231 232
 
233
+    if(pattern->prefix)
234
+	if(pattern->prefix_length > offset)
235
+	    return 0;
232 236
 
233 237
     if(bufferpos >= length)
234 238
 	bufferpos %= length;
... ...
@@ -258,6 +265,30 @@ inline static int cli_findpos(const char *buffer, unsigned int depth, unsigned i
258 258
 	    bufferpos = 0;
259 259
     }
260 260
 
261
+    if(pattern->prefix) {
262
+	alt = 0;
263
+	bufferpos = offset - pattern->prefix_length;
264
+
265
+	for(i = 0; i < pattern->prefix_length; i++) {
266
+
267
+	    if(pattern->prefix[i] == CLI_ALT) {
268
+		found = 0;
269
+		for(j = 0; j < pattern->altn[alt]; j++) {
270
+		    if(pattern->altc[alt][j] == buffer[bufferpos])
271
+			found = 1;
272
+		}
273
+
274
+		if(!found)
275
+		    return 0;
276
+		alt++;
277
+
278
+	    } else if(pattern->prefix[i] != CLI_IGN && (char) pattern->prefix[i] != buffer[bufferpos])
279
+		return 0;
280
+
281
+	    bufferpos++;
282
+	}
283
+    }
284
+
261 285
     return 1;
262 286
 }
263 287
 
... ...
@@ -295,7 +326,7 @@ int cli_ac_scanbuff(const char *buffer, unsigned int length, const char **virnam
295 295
 			else
296 296
 			    t = ftype;
297 297
 
298
-			if((fd == -1 && !t) || !cli_validatesig(t, pt->offset, offset + position, fd, pt->virname)) {
298
+			if((fd == -1 && !t) || !cli_validatesig(t, pt->offset, offset + position - pt->prefix_length, fd, pt->virname)) {
299 299
 			    pt = pt->next;
300 300
 			    continue;
301 301
 			}
... ...
@@ -305,11 +336,11 @@ int cli_ac_scanbuff(const char *buffer, unsigned int length, const char **virnam
305 305
 			if(partcnt[pt->sigid] + 1 == pt->partno) {
306 306
 			    dist = 1;
307 307
 			    if(pt->maxdist)
308
-				if(offset + i - partoff[pt->sigid] > pt->maxdist)
308
+				if((offset + i - pt->prefix_length) - partoff[pt->sigid] > pt->maxdist)
309 309
 				    dist = 0;
310 310
 
311 311
 			    if(dist && pt->mindist)
312
-				if(offset + i - partoff[pt->sigid] < pt->mindist)
312
+				if((offset + i - pt->prefix_length) - partoff[pt->sigid] < pt->mindist)
313 313
 				    dist = 0;
314 314
 
315 315
 			    if(dist) {
... ...
@@ -319,7 +350,7 @@ int cli_ac_scanbuff(const char *buffer, unsigned int length, const char **virnam
319 319
 				    if(pt->type) {
320 320
 					if(otfrec) {
321 321
 					    if(pt->type > type || pt->type >= CL_TYPE_SFX) {
322
-						cli_dbgmsg("Matched signature for file type %s at %d\n", pt->virname, offset + position);
322
+						cli_dbgmsg("Matched signature for file type %s at %d\n", pt->virname, offset + position - pt->prefix_length);
323 323
 						type = pt->type;
324 324
 						if(ftoffset && (!*ftoffset || (*ftoffset)->cnt < SFX_MAX_TESTS) && ftype == CL_TYPE_MSEXE && type >= CL_TYPE_SFX) {
325 325
 						    if(!(tnode = cli_calloc(1, sizeof(struct cli_matched_type)))) {
... ...
@@ -328,7 +359,7 @@ int cli_ac_scanbuff(const char *buffer, unsigned int length, const char **virnam
328 328
 						    }
329 329
 
330 330
 						    tnode->type = type;
331
-						    tnode->offset = offset + position;
331
+						    tnode->offset = offset + position - pt->prefix_length;
332 332
 
333 333
 						    if(*ftoffset)
334 334
 							tnode->cnt = (*ftoffset)->cnt + 1;
... ...
@@ -355,7 +386,7 @@ int cli_ac_scanbuff(const char *buffer, unsigned int length, const char **virnam
355 355
 			if(pt->type) {
356 356
 			    if(otfrec) {
357 357
 				if(pt->type > type || pt->type >= CL_TYPE_SFX) {
358
-				    cli_dbgmsg("Matched signature for file type %s at %d\n", pt->virname, offset + position);
358
+				    cli_dbgmsg("Matched signature for file type %s at %d\n", pt->virname, offset + position - pt->prefix_length);
359 359
 				    type = pt->type;
360 360
 				    if(ftoffset && (!*ftoffset ||(*ftoffset)->cnt < SFX_MAX_TESTS) && ftype == CL_TYPE_MSEXE && type >= CL_TYPE_SFX) {
361 361
 					if(!(tnode = cli_calloc(1, sizeof(struct cli_matched_type)))) {
... ...
@@ -363,7 +394,7 @@ int cli_ac_scanbuff(const char *buffer, unsigned int length, const char **virnam
363 363
 					    return CL_EMEM;
364 364
 					}
365 365
 					tnode->type = type;
366
-					tnode->offset = offset + position;
366
+					tnode->offset = offset + position - pt->prefix_length;
367 367
 
368 368
 					if(*ftoffset)
369 369
 					    tnode->cnt = (*ftoffset)->cnt + 1;
... ...
@@ -76,8 +76,16 @@ static int cli_ac_addsig(struct cli_matcher *root, const char *virname, const ch
76 76
 	struct cli_ac_patt *new;
77 77
 	char *pt, *hex;
78 78
 	int virlen, ret, error = 0;
79
-	unsigned int i;
80
-
79
+	unsigned int i, j, wprefix = 0;
80
+
81
+#define FREE_ALT			\
82
+    if(new->alt) {			\
83
+	free(new->altn);		\
84
+	for(i = 0; i < new->alt; i++)	\
85
+	    free(new->altc[i]);		\
86
+	free(new->altc);		\
87
+	free(hex);			\
88
+    }
81 89
 
82 90
     if((new = (struct cli_ac_patt *) cli_calloc(1, sizeof(struct cli_ac_patt))) == NULL)
83 91
 	return CL_EMEM;
... ...
@@ -172,14 +180,7 @@ static int cli_ac_addsig(struct cli_matcher *root, const char *virname, const ch
172 172
 	free(hexcpy);
173 173
 
174 174
 	if(error) {
175
-	    free(hexnew);
176
-	    if(new->alt) {
177
-		free(new->altn);
178
-		for(i = 0; i < new->alt; i++)
179
-		    if(new->altc[i])
180
-			free(new->altc[i]);
181
-		free(new->altc);
182
-	    }
175
+	    FREE_ALT;
183 176
 	    free(new);
184 177
 	    return CL_EMALFDB;
185 178
 	}
... ...
@@ -187,51 +188,75 @@ static int cli_ac_addsig(struct cli_matcher *root, const char *virname, const ch
187 187
     } else
188 188
 	hex = (char *) hexsig;
189 189
 
190
+    if((new->pattern = cli_hex2si(hex)) == NULL) {
191
+	FREE_ALT;
192
+	free(new);
193
+	return CL_EMALFDB;
194
+    }
190 195
 
191 196
     new->length = strlen(hex) / 2;
192 197
 
193
-    if(new->length > root->maxpatlen)
194
-	root->maxpatlen = new->length;
198
+    for(i = 0; i < AC_DEFAULT_DEPTH; i++) {
199
+	if(new->pattern[i] == CLI_IGN || new->pattern[i] == CLI_ALT) {
200
+	    wprefix = 1;
201
+	    break;
202
+	}
203
+    }
195 204
 
196
-    if((new->pattern = cli_hex2si(hex)) == NULL) {
197
-	if(new->alt) {
198
-	    free(new->altn);
199
-	    for(i = 0; i < new->alt; i++)
200
-		free(new->altc[i]);
201
-	    free(new->altc);
202
-	    free(hex);
205
+    if(wprefix) {
206
+	for(; i < new->length - AC_DEFAULT_DEPTH + 1; i++) {
207
+	    wprefix = 0;
208
+	    for(j = i; j < i + AC_DEFAULT_DEPTH; j++) {
209
+		if(new->pattern[j] == CLI_IGN || new->pattern[j] == CLI_ALT) {
210
+		    wprefix = 1;
211
+		    break;
212
+		}
213
+	    }
214
+	    if(!wprefix)
215
+		break;
203 216
 	}
204
-	free(new);
205
-	return CL_EMALFDB;
217
+
218
+	if(wprefix) {
219
+	    FREE_ALT;
220
+	    free(new->pattern);
221
+	    free(new);
222
+	    return CL_EMALFDB;
223
+	}
224
+
225
+	new->prefix = new->pattern;
226
+	new->prefix_length = i;
227
+	new->pattern = &new->prefix[i];
228
+	new->length -= i;
229
+
230
+	for(i = 0; i < new->prefix_length; i++)
231
+	    if(new->prefix[i] == CLI_ALT)
232
+		new->alt_pattern++;
206 233
     }
207 234
 
235
+    if(new->length > root->maxpatlen)
236
+	root->maxpatlen = new->length;
237
+
208 238
     if((pt = strstr(virname, "(Clam)")))
209 239
 	virlen = strlen(virname) - strlen(pt) - 1;
210 240
     else
211 241
 	virlen = strlen(virname);
212 242
 
213 243
     if(virlen <= 0) {
214
-	free(new->pattern);
215
-	if(new->alt) {
216
-	    free(new->altn);
217
-	    for(i = 0; i < new->alt; i++)
218
-		free(new->altc[i]);
219
-	    free(new->altc);
220
-	    free(hex);
221
-	}
244
+	if(new->prefix)
245
+	    free(new->prefix);
246
+	else
247
+	    free(new->pattern);
248
+	FREE_ALT;
222 249
 	free(new);
223 250
 	return CL_EMALFDB;
224 251
     }
225 252
 
226 253
     if((new->virname = cli_calloc(virlen + 1, sizeof(char))) == NULL) {
227
-	free(new->pattern);
228
-	if(new->alt) {
229
-	    free(new->altn);
230
-	    for(i = 0; i < new->alt; i++)
231
-		free(new->altc[i]);
232
-	    free(new->altc);
233
-	    free(hex);
234
-	}
254
+	if(new->prefix)
255
+	    free(new->prefix);
256
+	else
257
+	    free(new->pattern);
258
+	FREE_ALT;
235 259
 	free(new);
236 260
 	return CL_EMEM;
237 261
     }
... ...
@@ -239,15 +264,12 @@ static int cli_ac_addsig(struct cli_matcher *root, const char *virname, const ch
239 239
     strncpy(new->virname, virname, virlen);
240 240
 
241 241
     if((ret = cli_ac_addpatt(root, new))) {
242
-	free(new->pattern);
242
+	if(new->prefix)
243
+	    free(new->prefix);
244
+	else
245
+	    free(new->pattern);
243 246
 	free(new->virname);
244
-	if(new->alt) {
245
-	    free(new->altn);
246
-	    for(i = 0; i < new->alt; i++)
247
-		free(new->altc[i]);
248
-	    free(new->altc);
249
-	    free(hex);
250
-	}
247
+	FREE_ALT;
251 248
 	free(new);
252 249
 	return ret;
253 250
     }