38
39
#define BM_BLOCK_SIZE 3
39
40
#define HASH(a,b,c) (211 * a + 37 * b + c)
41
int cli_bm_addpatt(struct cli_matcher *root, struct cli_bm_patt *pattern)
42
int cli_bm_addpatt(struct cli_matcher *root, struct cli_bm_patt *pattern, const char *offset)
44
45
const unsigned char *pt = pattern->pattern;
45
46
struct cli_bm_patt *prev, *next = NULL;
48
50
if(pattern->length < BM_MIN_LENGTH) {
55
if((ret = cli_caloff(offset, NULL, NULL, root->type, pattern->offdata, &pattern->offset_min, &pattern->offset_max))) {
56
cli_errmsg("cli_bm_addpatt: Can't calculate offset for signature %s\n", pattern->virname);
59
if(pattern->offdata[0] != CLI_OFF_ANY) {
60
if(pattern->offdata[0] == CLI_OFF_ABSOLUTE)
61
root->bm_absoff_num++;
63
root->bm_reloff_num++;
67
/* the bm_suffix load balancing below can shorten the sig,
68
* we want to see the entire signature! */
69
if (filter_add_static(root->filter, pattern->pattern, pattern->length, pattern->virname) == -1) {
70
cli_warnmsg("cli_bm_addpatt: cannot use filter for trie\n");
71
mpool_free(root->mempool, root->filter);
74
/* TODO: should this affect maxpatlen? */
53
77
#if BM_MIN_LENGTH == BM_BLOCK_SIZE
54
78
/* try to load balance bm_suffix (at the cost of bm_shift) */
55
79
for(i = 0; i < pattern->length - BM_BLOCK_SIZE + 1; i++) {
92
116
pattern->pattern0 = pattern->pattern[0];
93
117
root->bm_suffix[idx]->cnt++;
119
if(root->bm_offmode) {
120
root->bm_pattab = (struct cli_bm_patt **) mpool_realloc2(root->mempool, root->bm_pattab, (root->bm_patterns + 1) * sizeof(struct cli_bm_patt *));
121
if(!root->bm_pattab) {
122
cli_errmsg("cli_bm_addpatt: Can't allocate memory for root->bm_pattab\n");
125
root->bm_pattab[root->bm_patterns] = pattern;
126
if(pattern->offdata[0] != CLI_OFF_ABSOLUTE)
127
pattern->offset_min = root->bm_patterns;
95
130
root->bm_patterns++;
96
131
return CL_SUCCESS;
116
152
return CL_SUCCESS;
155
int cli_bm_initoff(const struct cli_matcher *root, struct cli_bm_off *data, fmap_t *map)
159
struct cli_bm_patt *patt;
160
struct cli_target_info info;
163
if(!root->bm_patterns) {
164
data->offtab = data->offset = NULL;
165
data->cnt = data->pos = 0;
168
memset(&info, 0, sizeof(info));
169
info.fsize = map->len;
171
data->cnt = data->pos = 0;
172
data->offtab = (uint32_t *) cli_malloc(root->bm_patterns * sizeof(uint32_t));
174
cli_errmsg("cli_bm_initoff: Can't allocate memory for data->offtab\n");
177
data->offset = (uint32_t *) cli_malloc(root->bm_patterns * sizeof(uint32_t));
179
cli_errmsg("cli_bm_initoff: Can't allocate memory for data->offset\n");
183
for(i = 0; i < root->bm_patterns; i++) {
184
patt = root->bm_pattab[i];
185
if(patt->offdata[0] == CLI_OFF_ABSOLUTE) {
186
data->offtab[data->cnt] = patt->offset_min + patt->prefix_length;
187
if(data->offtab[data->cnt] >= map->len)
190
} else if((ret = cli_caloff(NULL, &info, map, root->type, patt->offdata, &data->offset[patt->offset_min], NULL))) {
191
cli_errmsg("cli_bm_initoff: Can't calculate relative offset in signature for %s\n", patt->virname);
192
if(info.exeinfo.section)
193
free(info.exeinfo.section);
197
} else if((data->offset[patt->offset_min] != CLI_OFF_NONE) && (data->offset[patt->offset_min] + patt->length <= info.fsize)) {
198
if(!data->cnt || (data->offset[patt->offset_min] + patt->prefix_length != data->offtab[data->cnt - 1])) {
199
data->offtab[data->cnt] = data->offset[patt->offset_min] + patt->prefix_length;
200
if(data->offtab[data->cnt] >= map->len)
206
if(info.exeinfo.section)
207
free(info.exeinfo.section);
209
cli_qsort(data->offtab, data->cnt, sizeof(uint32_t), NULL);
213
void cli_bm_freeoff(struct cli_bm_off *data)
119
221
void cli_bm_free(struct cli_matcher *root)
121
223
struct cli_bm_patt *patt, *prev;
125
227
if(root->bm_shift)
126
228
mpool_free(root->mempool, root->bm_shift);
231
mpool_free(root->mempool, root->bm_pattab);
128
233
if(root->bm_suffix) {
129
234
for(i = 0; i < size; i++) {
130
235
patt = root->bm_suffix[i];
137
242
mpool_free(root->mempool, prev->pattern);
138
243
if(prev->virname)
139
244
mpool_free(root->mempool, prev->virname);
141
mpool_free(root->mempool, prev->offset);
142
245
mpool_free(root->mempool, prev);
149
int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_bm_patt **patt, const struct cli_matcher *root, uint32_t offset, cli_file_t ftype, int fd)
252
int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_bm_patt **patt, const struct cli_matcher *root, uint32_t offset, fmap_t *map, struct cli_bm_off *offdata)
254
uint32_t i, j, off, off_min, off_max;
152
255
uint8_t found, pchain, shift;
153
256
uint16_t idx, idxchk;
154
257
struct cli_bm_patt *p;
155
258
const unsigned char *bp, *pt;
156
259
unsigned char prefix;
157
struct cli_target_info info;
260
struct cli_target_info info;
160
263
if(!root || !root->bm_shift)
166
269
memset(&info, 0, sizeof(info));
168
for(i = BM_MIN_LENGTH - BM_BLOCK_SIZE; i < length - BM_BLOCK_SIZE + 1; ) {
270
i = BM_MIN_LENGTH - BM_BLOCK_SIZE;
274
for(; offdata->pos && offdata->offtab[offdata->pos] > offset; offdata->pos--);
275
if(offdata->offtab[offdata->pos] < offset)
277
if(offdata->pos >= offdata->cnt)
279
i += offdata->offtab[offdata->pos] - offset;
281
for(; i < length - BM_BLOCK_SIZE + 1; ) {
169
282
idx = HASH(buffer[i], buffer[i + 1], buffer[i + 2]);
170
283
shift = root->bm_shift[idx];
173
286
prefix = buffer[i - BM_MIN_LENGTH + BM_BLOCK_SIZE];
174
287
p = root->bm_suffix[idx];
288
if(p && p->cnt == 1 && p->pattern0 != prefix) {
290
off = offset + i - BM_MIN_LENGTH + BM_BLOCK_SIZE;
291
for(; offdata->pos < offdata->cnt && off >= offdata->offtab[offdata->pos]; offdata->pos++);
292
if(offdata->pos == offdata->cnt || off >= offdata->offtab[offdata->pos])
294
i += offdata->offtab[offdata->pos] - off;
177
302
if(p->pattern0 != prefix) {
318
if(p->offdata[0] == CLI_OFF_ABSOLUTE) {
319
if(p->offset_min != offset + off - p->prefix_length) {
323
} else if((offdata->offset[p->offset_min] == CLI_OFF_NONE) || (offdata->offset[p->offset_min] != offset + off - p->prefix_length)) {
192
329
idxchk = MIN(p->length, length - off) - 1;
194
331
if((bp[idxchk] != p->pattern[idxchk]) || (bp[idxchk / 2] != p->pattern[idxchk / 2])) {
353
if(found && (p->boundary & BM_BOUNDARY_EOL)) {
216
360
if(found && p->length + p->prefix_length == j) {
361
if(!offdata && (p->offset_min != CLI_OFF_ANY)) {
362
if(p->offdata[0] != CLI_OFF_ABSOLUTE) {
363
ret = cli_caloff(NULL, &info, map, root->type, p->offdata, &off_min, &off_max);
364
if(ret != CL_SUCCESS) {
365
cli_errmsg("cli_bm_scanbuff: Can't calculate relative offset in signature for %s\n", p->virname);
366
if(info.exeinfo.section)
367
free(info.exeinfo.section);
371
off_min = p->offset_min;
372
off_max = p->offset_max;
219
374
off = offset + i - p->prefix_length - BM_MIN_LENGTH + BM_BLOCK_SIZE;
220
if(!cli_validatesig(ftype, p->offset, off, &info, fd, p->virname)) {
375
if(off_min == CLI_OFF_NONE || off_max < off || off_min > off) {
227
381
*virname = p->virname;
230
384
if(info.exeinfo.section)
231
385
free(info.exeinfo.section);
394
off = offset + i - BM_MIN_LENGTH + BM_BLOCK_SIZE;
395
for(; offdata->pos < offdata->cnt && off >= offdata->offtab[offdata->pos]; offdata->pos++);
396
if(offdata->pos == offdata->cnt || off >= offdata->offtab[offdata->pos])
398
i += offdata->offtab[offdata->pos] - off;
245
405
if(info.exeinfo.section)
246
406
free(info.exeinfo.section);