git-svn: trunk@2047
Tomasz Kojm authored on 2006/06/27 03:26:32... | ... |
@@ -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 |
} |