Coverage Report

Created: 2023-09-25 07:12

/src/yara/libyara/scanner.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
Copyright (c) 2018. The YARA Authors. All Rights Reserved.
3
4
Redistribution and use in source and binary forms, with or without modification,
5
are permitted provided that the following conditions are met:
6
7
1. Redistributions of source code must retain the above copyright notice, this
8
list of conditions and the following disclaimer.
9
10
2. Redistributions in binary form must reproduce the above copyright notice,
11
this list of conditions and the following disclaimer in the documentation and/or
12
other materials provided with the distribution.
13
14
3. Neither the name of the copyright holder nor the names of its contributors
15
may be used to endorse or promote products derived from this software without
16
specific prior written permission.
17
18
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
22
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
*/
29
30
#include <stdlib.h>
31
#include <yara/ahocorasick.h>
32
#include <yara/error.h>
33
#include <yara/exec.h>
34
#include <yara/exefiles.h>
35
#include <yara/libyara.h>
36
#include <yara/mem.h>
37
#include <yara/object.h>
38
#include <yara/proc.h>
39
#include <yara/scanner.h>
40
#include <yara/strutils.h>
41
#include <yara/types.h>
42
43
#include "exception.h"
44
45
static int _yr_scanner_scan_mem_block(
46
    YR_SCANNER* scanner,
47
    const uint8_t* block_data,
48
    YR_MEMORY_BLOCK* block)
49
6.97k
{
50
6.97k
  YR_DEBUG_FPRINTF(
51
6.97k
      2,
52
6.97k
      stderr,
53
6.97k
      "+ %s(block_data=%p block->base=0x%" PRIx64 " block->size=%zu) {\n",
54
6.97k
      __FUNCTION__,
55
6.97k
      block_data,
56
6.97k
      block->base,
57
6.97k
      block->size);
58
59
6.97k
  int result = ERROR_SUCCESS;
60
61
6.97k
  YR_RULES* rules = scanner->rules;
62
6.97k
  YR_AC_TRANSITION* transition_table = rules->ac_transition_table;
63
6.97k
  uint32_t* match_table = rules->ac_match_table;
64
65
6.97k
  YR_AC_MATCH* match;
66
6.97k
  YR_AC_TRANSITION transition;
67
68
6.97k
  size_t i = 0;
69
6.97k
  uint32_t state = YR_AC_ROOT_STATE;
70
6.97k
  uint16_t index;
71
6.97k
  YR_STRING* report_string = NULL;
72
6.97k
  YR_RULE* rule = NULL;
73
74
50.3M
  while (i < block->size)
75
50.2M
  {
76
50.2M
    if (i % 4096 == 0 && scanner->timeout > 0)
77
0
    {
78
0
      if (yr_stopwatch_elapsed_ns(&scanner->stopwatch) > scanner->timeout)
79
0
      {
80
0
        result = ERROR_SCAN_TIMEOUT;
81
0
        goto _exit;
82
0
      }
83
0
    }
84
85
#if 2 == YR_DEBUG_VERBOSITY
86
    if (0 != state)
87
      YR_DEBUG_FPRINTF(
88
          2,
89
          stderr,
90
          "- match_table[state=%u]=%'u i=%'ld "
91
          "block_data=%p block->base=0x%" PRIx64 " // %s()\n",
92
          state,
93
          match_table[state],
94
          i,
95
          block_data,
96
          block->base,
97
          __FUNCTION__);
98
#endif
99
100
50.2M
    if (match_table[state] != 0)
101
0
    {
102
      // If the entry corresponding to state N in the match table is zero, it
103
      // means that there's no match associated to the state. If it's non-zero,
104
      // its value is the 1-based index within ac_match_pool where the first
105
      // match resides.
106
107
0
      match = &rules->ac_match_pool[match_table[state] - 1];
108
109
0
      if (scanner->matches->count >= YR_SLOW_STRING_MATCHES)
110
0
      {
111
0
        report_string = match->string;
112
0
        rule = report_string
113
0
                   ? &scanner->rules->rules_table[report_string->rule_idx]
114
0
                   : NULL;
115
0
      }
116
117
0
      while (match != NULL)
118
0
      {
119
0
        if (match->backtrack <= i)
120
0
        {
121
0
          GOTO_EXIT_ON_ERROR(yr_scan_verify_match(
122
0
              scanner,
123
0
              match,
124
0
              block_data,
125
0
              block->size,
126
0
              block->base,
127
0
              i - match->backtrack));
128
0
        }
129
130
0
        match = match->next;
131
0
      }
132
0
    }
133
134
50.2M
    index = block_data[i++] + 1;
135
50.2M
    transition = transition_table[state + index];
136
137
50.2M
    while (YR_AC_INVALID_TRANSITION(transition, index))
138
50.2M
    {
139
50.2M
      if (state != YR_AC_ROOT_STATE)
140
0
      {
141
0
        state = YR_AC_NEXT_STATE(transition_table[state]);
142
0
        transition = transition_table[state + index];
143
0
      }
144
50.2M
      else
145
50.2M
      {
146
50.2M
        transition = 0;
147
50.2M
        break;
148
50.2M
      }
149
50.2M
    }
150
151
50.2M
    state = YR_AC_NEXT_STATE(transition);
152
50.2M
  }
153
154
6.97k
  if (match_table[state] != 0)
155
0
  {
156
0
    match = &rules->ac_match_pool[match_table[state] - 1];
157
158
0
    while (match != NULL)
159
0
    {
160
0
      if (match->backtrack <= i)
161
0
      {
162
0
        GOTO_EXIT_ON_ERROR(yr_scan_verify_match(
163
0
            scanner,
164
0
            match,
165
0
            block_data,
166
0
            block->size,
167
0
            block->base,
168
0
            i - match->backtrack));
169
0
      }
170
171
0
      match = match->next;
172
0
    }
173
0
  }
174
175
6.97k
  if (rule != NULL &&
176
6.97k
      scanner->matches->count >= YR_SLOW_STRING_MATCHES &&
177
6.97k
      scanner->matches->count < YR_MAX_STRING_MATCHES)
178
0
  {
179
0
    if (rule != NULL && report_string != NULL)
180
0
    {
181
0
      result = scanner->callback(
182
0
        scanner,
183
0
        CALLBACK_MSG_TOO_SLOW_SCANNING,
184
0
        (void*) report_string,
185
0
        scanner->user_data);
186
0
      if (result != CALLBACK_CONTINUE)
187
0
      {
188
0
        result = ERROR_TOO_SLOW_SCANNING;
189
0
        goto _exit;
190
0
      }
191
0
    }
192
0
  }
193
194
6.97k
_exit:
195
196
6.97k
  YR_DEBUG_FPRINTF(
197
6.97k
      2,
198
6.97k
      stderr,
199
6.97k
      "} = %d AKA %s // %s()\n",
200
6.97k
      result,
201
6.97k
      yr_debug_error_as_string(result),
202
6.97k
      __FUNCTION__);
203
204
6.97k
  return result;
205
6.97k
}
206
207
static void _yr_scanner_clean_matches(YR_SCANNER* scanner)
208
6.97k
{
209
6.97k
  YR_DEBUG_FPRINTF(2, stderr, "- %s() {} \n", __FUNCTION__);
210
211
6.97k
  memset(
212
6.97k
      scanner->rule_matches_flags,
213
6.97k
      0,
214
6.97k
      sizeof(YR_BITMASK) * YR_BITMASK_SIZE(scanner->rules->num_rules));
215
216
6.97k
  memset(
217
6.97k
      scanner->rule_evaluate_condition_flags,
218
6.97k
      0,
219
6.97k
      sizeof(YR_BITMASK) * YR_BITMASK_SIZE(scanner->rules->num_rules));
220
221
6.97k
  memset(
222
6.97k
      scanner->ns_unsatisfied_flags,
223
6.97k
      0,
224
6.97k
      sizeof(YR_BITMASK) * YR_BITMASK_SIZE(scanner->rules->num_namespaces));
225
226
6.97k
  memset(
227
6.97k
      scanner->strings_temp_disabled,
228
6.97k
      0,
229
6.97k
      sizeof(YR_BITMASK) * YR_BITMASK_SIZE(scanner->rules->num_strings));
230
231
6.97k
  memset(scanner->matches, 0, sizeof(YR_MATCHES) * scanner->rules->num_strings);
232
233
6.97k
  memset(
234
6.97k
      scanner->unconfirmed_matches,
235
6.97k
      0,
236
6.97k
      sizeof(YR_MATCHES) * scanner->rules->num_strings);
237
6.97k
}
238
239
YR_API int yr_scanner_create(YR_RULES* rules, YR_SCANNER** scanner)
240
6.97k
{
241
6.97k
  YR_DEBUG_FPRINTF(2, stderr, "- %s() {} \n", __FUNCTION__);
242
243
6.97k
  YR_EXTERNAL_VARIABLE* external;
244
6.97k
  YR_SCANNER* new_scanner;
245
246
6.97k
  new_scanner = (YR_SCANNER*) yr_calloc(1, sizeof(YR_SCANNER));
247
248
6.97k
  if (new_scanner == NULL)
249
0
    return ERROR_INSUFFICIENT_MEMORY;
250
251
6.97k
  FAIL_ON_ERROR_WITH_CLEANUP(
252
6.97k
      yr_hash_table_create(64, &new_scanner->objects_table),
253
6.97k
      yr_free(new_scanner));
254
255
6.97k
  new_scanner->rules = rules;
256
6.97k
  new_scanner->entry_point = YR_UNDEFINED;
257
6.97k
  new_scanner->file_size = YR_UNDEFINED;
258
6.97k
  new_scanner->canary = rand();
259
260
  // By default report both matching and non-matching rules.
261
6.97k
  new_scanner->flags = SCAN_FLAGS_REPORT_RULES_MATCHING |
262
6.97k
                       SCAN_FLAGS_REPORT_RULES_NOT_MATCHING;
263
264
6.97k
  new_scanner->rule_matches_flags = (YR_BITMASK*) yr_calloc(
265
6.97k
      sizeof(YR_BITMASK), YR_BITMASK_SIZE(rules->num_rules));
266
267
6.97k
  new_scanner->rule_evaluate_condition_flags = (YR_BITMASK*) yr_calloc(
268
6.97k
      sizeof(YR_BITMASK), YR_BITMASK_SIZE(rules->num_rules));
269
270
6.97k
  new_scanner->ns_unsatisfied_flags = (YR_BITMASK*) yr_calloc(
271
6.97k
      sizeof(YR_BITMASK), YR_BITMASK_SIZE(rules->num_namespaces));
272
273
6.97k
  new_scanner->strings_temp_disabled = (YR_BITMASK*) yr_calloc(
274
6.97k
      sizeof(YR_BITMASK), YR_BITMASK_SIZE(rules->num_strings));
275
276
6.97k
  new_scanner->matches = (YR_MATCHES*) yr_calloc(
277
6.97k
      rules->num_strings, sizeof(YR_MATCHES));
278
279
6.97k
  new_scanner->unconfirmed_matches = (YR_MATCHES*) yr_calloc(
280
6.97k
      rules->num_strings, sizeof(YR_MATCHES));
281
282
6.97k
  if (new_scanner->rule_matches_flags == NULL ||
283
6.97k
      new_scanner->rule_evaluate_condition_flags == NULL ||
284
6.97k
      new_scanner->ns_unsatisfied_flags == NULL ||
285
6.97k
      new_scanner->strings_temp_disabled == NULL ||
286
6.97k
      new_scanner->matches == NULL ||  //
287
6.97k
      new_scanner->unconfirmed_matches == NULL)
288
0
  {
289
0
    yr_scanner_destroy(new_scanner);
290
0
    return ERROR_INSUFFICIENT_MEMORY;
291
0
  }
292
293
#ifdef YR_PROFILING_ENABLED
294
  new_scanner->profiling_info = yr_calloc(
295
      rules->num_rules, sizeof(YR_PROFILING_INFO));
296
297
  if (new_scanner->profiling_info == NULL)
298
  {
299
    yr_scanner_destroy(new_scanner);
300
    return ERROR_INSUFFICIENT_MEMORY;
301
  }
302
#else
303
6.97k
  new_scanner->profiling_info = NULL;
304
6.97k
#endif
305
306
6.97k
  external = rules->ext_vars_table;
307
308
6.97k
  while (!EXTERNAL_VARIABLE_IS_NULL(external))
309
0
  {
310
0
    YR_OBJECT* object;
311
312
0
    FAIL_ON_ERROR_WITH_CLEANUP(
313
0
        yr_object_from_external_variable(external, &object),
314
        // cleanup
315
0
        yr_scanner_destroy(new_scanner));
316
317
0
    FAIL_ON_ERROR_WITH_CLEANUP(yr_hash_table_add(
318
0
                                   new_scanner->objects_table,
319
0
                                   external->identifier,
320
0
                                   NULL,
321
0
                                   (void*) object),
322
                               // cleanup
323
0
                               yr_object_destroy(object);
324
0
                               yr_scanner_destroy(new_scanner));
325
326
0
    yr_object_set_canary(object, new_scanner->canary);
327
0
    external++;
328
0
  }
329
330
6.97k
  *scanner = new_scanner;
331
332
6.97k
  return ERROR_SUCCESS;
333
6.97k
}
334
335
YR_API void yr_scanner_destroy(YR_SCANNER* scanner)
336
6.97k
{
337
6.97k
  YR_DEBUG_FPRINTF(2, stderr, "- %s() {} \n", __FUNCTION__);
338
339
6.97k
  RE_FIBER* fiber = scanner->re_fiber_pool.fibers.head;
340
341
6.97k
  while (fiber != NULL)
342
0
  {
343
0
    RE_FIBER* next = fiber->next;
344
0
    yr_free(fiber);
345
0
    fiber = next;
346
0
  }
347
348
6.97k
  RE_FAST_EXEC_POSITION* position = scanner->re_fast_exec_position_pool.head;
349
350
6.97k
  while (position != NULL)
351
0
  {
352
0
    RE_FAST_EXEC_POSITION* next = position->next;
353
0
    yr_free(position);
354
0
    position = next;
355
0
  }
356
357
6.97k
  if (scanner->objects_table != NULL)
358
6.97k
  {
359
6.97k
    yr_hash_table_destroy(
360
6.97k
        scanner->objects_table,
361
6.97k
        (YR_HASH_TABLE_FREE_VALUE_FUNC) yr_object_destroy);
362
6.97k
  }
363
364
#ifdef YR_PROFILING_ENABLED
365
  yr_free(scanner->profiling_info);
366
#endif
367
368
6.97k
  yr_free(scanner->rule_matches_flags);
369
6.97k
  yr_free(scanner->ns_unsatisfied_flags);
370
6.97k
  yr_free(scanner->rule_evaluate_condition_flags);
371
6.97k
  yr_free(scanner->strings_temp_disabled);
372
6.97k
  yr_free(scanner->matches);
373
6.97k
  yr_free(scanner->unconfirmed_matches);
374
6.97k
  yr_free(scanner);
375
6.97k
}
376
377
YR_API void yr_scanner_set_callback(
378
    YR_SCANNER* scanner,
379
    YR_CALLBACK_FUNC callback,
380
    void* user_data)
381
6.97k
{
382
6.97k
  scanner->callback = callback;
383
6.97k
  scanner->user_data = user_data;
384
6.97k
}
385
386
YR_API void yr_scanner_set_timeout(YR_SCANNER* scanner, int timeout)
387
6.97k
{
388
  // Convert timeout from seconds to nanoseconds.
389
6.97k
  scanner->timeout = timeout * 1000000000ULL;
390
6.97k
}
391
392
YR_API void yr_scanner_set_flags(YR_SCANNER* scanner, int flags)
393
6.97k
{
394
  // For backward compatibility, if neither SCAN_FLAGS_REPORT_RULES_MATCHING
395
  // nor SCAN_FLAGS_REPORT_RULES_NOT_MATCHING are specified, both are assumed.
396
397
6.97k
  if (!(flags & SCAN_FLAGS_REPORT_RULES_MATCHING) &&
398
6.97k
      !(flags & SCAN_FLAGS_REPORT_RULES_NOT_MATCHING))
399
6.97k
  {
400
6.97k
    flags |= SCAN_FLAGS_REPORT_RULES_MATCHING |
401
6.97k
             SCAN_FLAGS_REPORT_RULES_NOT_MATCHING;
402
6.97k
  }
403
404
6.97k
  scanner->flags = flags;
405
6.97k
}
406
407
YR_API int yr_scanner_define_integer_variable(
408
    YR_SCANNER* scanner,
409
    const char* identifier,
410
    int64_t value)
411
0
{
412
0
  YR_OBJECT* obj = (YR_OBJECT*) yr_hash_table_lookup(
413
0
      scanner->objects_table, identifier, NULL);
414
415
0
  if (obj == NULL)
416
0
    return ERROR_INVALID_ARGUMENT;
417
418
0
  if (obj->type != OBJECT_TYPE_INTEGER)
419
0
    return ERROR_INVALID_EXTERNAL_VARIABLE_TYPE;
420
421
0
  return yr_object_set_integer(value, obj, NULL);
422
0
}
423
424
YR_API int yr_scanner_define_boolean_variable(
425
    YR_SCANNER* scanner,
426
    const char* identifier,
427
    int value)
428
0
{
429
0
  return yr_scanner_define_integer_variable(scanner, identifier, value);
430
0
}
431
432
YR_API int yr_scanner_define_float_variable(
433
    YR_SCANNER* scanner,
434
    const char* identifier,
435
    double value)
436
0
{
437
0
  YR_OBJECT* obj = (YR_OBJECT*) yr_hash_table_lookup(
438
0
      scanner->objects_table, identifier, NULL);
439
440
0
  if (obj == NULL)
441
0
    return ERROR_INVALID_ARGUMENT;
442
443
0
  if (obj->type != OBJECT_TYPE_FLOAT)
444
0
    return ERROR_INVALID_EXTERNAL_VARIABLE_TYPE;
445
446
0
  return yr_object_set_float(value, obj, NULL);
447
0
}
448
449
YR_API int yr_scanner_define_string_variable(
450
    YR_SCANNER* scanner,
451
    const char* identifier,
452
    const char* value)
453
0
{
454
0
  YR_OBJECT* obj = (YR_OBJECT*) yr_hash_table_lookup(
455
0
      scanner->objects_table, identifier, NULL);
456
457
0
  if (obj == NULL)
458
0
    return ERROR_INVALID_ARGUMENT;
459
460
0
  if (obj->type != OBJECT_TYPE_STRING)
461
0
    return ERROR_INVALID_EXTERNAL_VARIABLE_TYPE;
462
463
0
  return yr_object_set_string(value, strlen(value), obj, NULL);
464
0
}
465
466
YR_API int yr_scanner_scan_mem_blocks(
467
    YR_SCANNER* scanner,
468
    YR_MEMORY_BLOCK_ITERATOR* iterator)
469
6.97k
{
470
6.97k
  YR_DEBUG_FPRINTF(2, stderr, "+ %s() {\n", __FUNCTION__);
471
472
6.97k
  YR_RULES* rules;
473
6.97k
  YR_RULE* rule;
474
6.97k
  YR_MEMORY_BLOCK* block;
475
476
6.97k
  int i, result = ERROR_SUCCESS;
477
478
6.97k
  if (scanner->callback == NULL)
479
0
  {
480
0
    result = ERROR_CALLBACK_REQUIRED;
481
0
    goto _exit;
482
0
  }
483
484
6.97k
  scanner->iterator = iterator;
485
6.97k
  rules = scanner->rules;
486
487
6.97k
  if (iterator->last_error == ERROR_BLOCK_NOT_READY)
488
0
  {
489
    // The caller is invoking yr_scanner_scan_mem_blocks again because the
490
    // previous call returned ERROR_BLOCK_NOT_READY.
491
0
    block = iterator->next(iterator);
492
0
  }
493
6.97k
  else
494
6.97k
  {
495
    // Create the notebook that will hold the YR_MATCH structures representing
496
    // each match found. This notebook will also contain snippets of the
497
    // matching data (the "data" field in YR_MATCH points to the snippet
498
    // corresponding to the match). Each notebook's page can store up to 1024
499
    // matches.
500
6.97k
    uint32_t max_match_data;
501
502
6.97k
    FAIL_ON_ERROR(
503
6.97k
        yr_get_configuration_uint32(YR_CONFIG_MAX_MATCH_DATA, &max_match_data));
504
505
6.97k
    result = yr_notebook_create(
506
6.97k
        1024 * (sizeof(YR_MATCH) + max_match_data), &scanner->matches_notebook);
507
508
6.97k
    if (result != ERROR_SUCCESS)
509
0
      goto _exit;
510
511
6.97k
    memcpy(
512
6.97k
      scanner->rule_evaluate_condition_flags,
513
6.97k
      scanner->rules->rule_evaluate_condition_flags,
514
6.97k
      sizeof(YR_BITMASK) * YR_BITMASK_SIZE(rules->num_rules));
515
516
6.97k
    yr_stopwatch_start(&scanner->stopwatch);
517
518
6.97k
    block = iterator->first(iterator);
519
6.97k
  }
520
521
13.9k
  while (block != NULL)
522
6.97k
  {
523
6.97k
    const uint8_t* data = block->fetch_data(block);
524
525
    // fetch_data may fail and return NULL.
526
6.97k
    if (data == NULL)
527
0
    {
528
0
      block = iterator->next(iterator);
529
0
      continue;
530
0
    }
531
532
6.97k
    if (scanner->entry_point == YR_UNDEFINED)
533
6.97k
    {
534
6.97k
      YR_TRYCATCH(
535
6.97k
          !(scanner->flags & SCAN_FLAGS_NO_TRYCATCH),
536
6.97k
          {
537
6.97k
            if (scanner->flags & SCAN_FLAGS_PROCESS_MEMORY)
538
6.97k
              scanner->entry_point = yr_get_entry_point_address(
539
6.97k
                  data, block->size, block->base);
540
6.97k
            else
541
6.97k
              scanner->entry_point = yr_get_entry_point_offset(
542
6.97k
                  data, block->size);
543
6.97k
          },
544
6.97k
          {});
545
6.97k
    }
546
547
6.97k
    YR_TRYCATCH(
548
6.97k
        !(scanner->flags & SCAN_FLAGS_NO_TRYCATCH),
549
6.97k
        { result = _yr_scanner_scan_mem_block(scanner, data, block); },
550
6.97k
        { result = ERROR_COULD_NOT_MAP_FILE; });
551
552
6.97k
    if (result != ERROR_SUCCESS)
553
0
      goto _exit;
554
555
6.97k
    block = iterator->next(iterator);
556
6.97k
  }
557
558
6.97k
  result = iterator->last_error;
559
560
6.97k
  if (result != ERROR_SUCCESS)
561
0
    goto _exit;
562
563
  // If the iterator has a file_size function, ask the function for the file's
564
  // size, if not file size is undefined.
565
6.97k
  if (iterator->file_size != NULL)
566
6.97k
    scanner->file_size = iterator->file_size(iterator);
567
0
  else
568
0
    scanner->file_size = YR_UNDEFINED;
569
570
6.97k
  YR_TRYCATCH(
571
6.97k
      !(scanner->flags & SCAN_FLAGS_NO_TRYCATCH),
572
6.97k
      { result = yr_execute_code(scanner); },
573
6.97k
      { result = ERROR_COULD_NOT_MAP_FILE; });
574
575
6.97k
  if (result != ERROR_SUCCESS)
576
0
    goto _exit;
577
578
6.97k
  for (i = 0, rule = rules->rules_table; !RULE_IS_NULL(rule); i++, rule++)
579
0
  {
580
0
    int message = 0;
581
582
0
    if (yr_bitmask_is_set(scanner->rule_matches_flags, i) &&
583
0
        yr_bitmask_is_not_set(scanner->ns_unsatisfied_flags, rule->ns->idx))
584
0
    {
585
0
      if (scanner->flags & SCAN_FLAGS_REPORT_RULES_MATCHING)
586
0
        message = CALLBACK_MSG_RULE_MATCHING;
587
0
    }
588
0
    else
589
0
    {
590
0
      if (scanner->flags & SCAN_FLAGS_REPORT_RULES_NOT_MATCHING)
591
0
        message = CALLBACK_MSG_RULE_NOT_MATCHING;
592
0
    }
593
594
0
    if (message != 0 && !RULE_IS_PRIVATE(rule))
595
0
    {
596
0
      switch (scanner->callback(scanner, message, rule, scanner->user_data))
597
0
      {
598
0
      case CALLBACK_ABORT:
599
0
        result = ERROR_SUCCESS;
600
0
        goto _exit;
601
602
0
      case CALLBACK_ERROR:
603
0
        result = ERROR_CALLBACK_ERROR;
604
0
        goto _exit;
605
0
      }
606
0
    }
607
0
  }
608
609
6.97k
  scanner->callback(
610
6.97k
      scanner, CALLBACK_MSG_SCAN_FINISHED, NULL, scanner->user_data);
611
612
6.97k
_exit:
613
614
  // If error is ERROR_BLOCK_NOT_READY we don't clean the matches and don't
615
  // destroy the notebook yet. ERROR_BLOCK_NOT_READY is not a permament error,
616
  // the caller can still call this function again for a retry.
617
6.97k
  if (result != ERROR_BLOCK_NOT_READY)
618
6.97k
  {
619
6.97k
    _yr_scanner_clean_matches(scanner);
620
621
6.97k
    if (scanner->matches_notebook != NULL)
622
6.97k
    {
623
6.97k
      yr_notebook_destroy(scanner->matches_notebook);
624
6.97k
      scanner->matches_notebook = NULL;
625
6.97k
    }
626
6.97k
  }
627
628
6.97k
  YR_DEBUG_FPRINTF(
629
6.97k
      2,
630
6.97k
      stderr,
631
6.97k
      "} = %d AKA %s // %s()\n",
632
6.97k
      result,
633
6.97k
      yr_debug_error_as_string(result),
634
6.97k
      __FUNCTION__);
635
636
6.97k
  return result;
637
6.97k
}
638
639
static YR_MEMORY_BLOCK* _yr_get_first_block(YR_MEMORY_BLOCK_ITERATOR* iterator)
640
13.9k
{
641
13.9k
  YR_MEMORY_BLOCK* result = (YR_MEMORY_BLOCK*) iterator->context;
642
643
13.9k
  YR_DEBUG_FPRINTF(
644
13.9k
      2,
645
13.9k
      stderr,
646
13.9k
      "- %s() {} = %p // default iterator; single memory block, blocking\n",
647
13.9k
      __FUNCTION__,
648
13.9k
      result);
649
650
13.9k
  return result;
651
13.9k
}
652
653
static YR_MEMORY_BLOCK* _yr_get_next_block(YR_MEMORY_BLOCK_ITERATOR* iterator)
654
13.9k
{
655
13.9k
  YR_MEMORY_BLOCK* result = NULL;
656
657
13.9k
  YR_DEBUG_FPRINTF(
658
13.9k
      2,
659
13.9k
      stderr,
660
13.9k
      "- %s() {} = %p // default iterator; single memory block, blocking\n",
661
13.9k
      __FUNCTION__,
662
13.9k
      result);
663
664
13.9k
  return result;
665
13.9k
}
666
667
static uint64_t _yr_get_file_size(YR_MEMORY_BLOCK_ITERATOR* iterator)
668
6.97k
{
669
6.97k
  uint64_t file_size = ((YR_MEMORY_BLOCK*) iterator->context)->size;
670
671
6.97k
  YR_DEBUG_FPRINTF(
672
6.97k
      2,
673
6.97k
      stderr,
674
6.97k
      "- %s() {} = %" PRIu64
675
6.97k
      "  // default iterator; single memory block, blocking\n",
676
6.97k
      __FUNCTION__,
677
6.97k
      file_size);
678
679
6.97k
  return file_size;
680
6.97k
}
681
682
static const uint8_t* _yr_fetch_block_data(YR_MEMORY_BLOCK* block)
683
13.9k
{
684
13.9k
  return (const uint8_t*) block->context;
685
13.9k
}
686
687
YR_API int yr_scanner_scan_mem(
688
    YR_SCANNER* scanner,
689
    const uint8_t* buffer,
690
    size_t buffer_size)
691
6.97k
{
692
6.97k
  YR_DEBUG_FPRINTF(
693
6.97k
      2,
694
6.97k
      stderr,
695
6.97k
      "+ %s(buffer=%p buffer_size=%zu) {\n",
696
6.97k
      __FUNCTION__,
697
6.97k
      buffer,
698
6.97k
      buffer_size);
699
700
6.97k
  YR_MEMORY_BLOCK block;
701
6.97k
  YR_MEMORY_BLOCK_ITERATOR iterator;
702
6.97k
  int result;
703
704
6.97k
  block.size = buffer_size;
705
6.97k
  block.base = 0;
706
6.97k
  block.fetch_data = _yr_fetch_block_data;
707
6.97k
  block.context = (void*) buffer;
708
709
6.97k
  iterator.context = &block;
710
6.97k
  iterator.first = _yr_get_first_block;
711
6.97k
  iterator.next = _yr_get_next_block;
712
6.97k
  iterator.file_size = _yr_get_file_size;
713
6.97k
  iterator.last_error = ERROR_SUCCESS;
714
715
  // Detect cases where every byte of input is checked for match and input size is bigger then 0.2 MB
716
6.97k
  if (scanner->rules->ac_match_table[YR_AC_ROOT_STATE] != 0 && buffer_size > YR_FILE_SIZE_THRESHOLD)
717
0
  {
718
0
    YR_STRING* report_string = scanner->rules->ac_match_pool[YR_AC_ROOT_STATE].string;
719
0
    result = scanner->callback(
720
0
          scanner,
721
0
          CALLBACK_MSG_TOO_SLOW_SCANNING,
722
0
          (void*) report_string,
723
0
          scanner->user_data);
724
0
    if (result != CALLBACK_CONTINUE)
725
0
      return ERROR_TOO_SLOW_SCANNING;
726
0
  }
727
728
6.97k
  result = yr_scanner_scan_mem_blocks(scanner, &iterator);
729
730
6.97k
  YR_DEBUG_FPRINTF(
731
6.97k
      2,
732
6.97k
      stderr,
733
6.97k
      "} = %d AKA %s // %s()\n",
734
6.97k
      result,
735
6.97k
      yr_debug_error_as_string(result),
736
6.97k
      __FUNCTION__);
737
738
6.97k
  return result;
739
6.97k
}
740
741
YR_API int yr_scanner_scan_file(YR_SCANNER* scanner, const char* filename)
742
0
{
743
0
  YR_MAPPED_FILE mfile;
744
745
0
  int result = yr_filemap_map(filename, &mfile);
746
747
0
  if (result == ERROR_SUCCESS)
748
0
  {
749
0
    result = yr_scanner_scan_mem(scanner, mfile.data, mfile.size);
750
0
    yr_filemap_unmap(&mfile);
751
0
  }
752
753
0
  return result;
754
0
}
755
756
YR_API int yr_scanner_scan_fd(YR_SCANNER* scanner, YR_FILE_DESCRIPTOR fd)
757
0
{
758
0
  YR_MAPPED_FILE mfile;
759
760
0
  int result = yr_filemap_map_fd(fd, 0, 0, &mfile);
761
762
0
  if (result == ERROR_SUCCESS)
763
0
  {
764
0
    result = yr_scanner_scan_mem(scanner, mfile.data, mfile.size);
765
0
    yr_filemap_unmap_fd(&mfile);
766
0
  }
767
768
0
  return result;
769
0
}
770
771
YR_API int yr_scanner_scan_proc(YR_SCANNER* scanner, int pid)
772
0
{
773
0
  YR_MEMORY_BLOCK_ITERATOR iterator;
774
775
0
  int result = yr_process_open_iterator(pid, &iterator);
776
777
0
  if (result == ERROR_SUCCESS)
778
0
  {
779
0
    int prev_flags = scanner->flags;
780
0
    scanner->flags |= SCAN_FLAGS_PROCESS_MEMORY;
781
0
    result = yr_scanner_scan_mem_blocks(scanner, &iterator);
782
0
    scanner->flags = prev_flags;
783
0
    yr_process_close_iterator(&iterator);
784
0
  }
785
786
0
  return result;
787
0
}
788
789
YR_API YR_STRING* yr_scanner_last_error_string(YR_SCANNER* scanner)
790
0
{
791
0
  return scanner->last_error_string;
792
0
}
793
794
YR_API YR_RULE* yr_scanner_last_error_rule(YR_SCANNER* scanner)
795
0
{
796
0
  if (scanner->last_error_string == NULL)
797
0
    return NULL;
798
799
0
  return &scanner->rules->rules_table[scanner->last_error_string->rule_idx];
800
0
}
801
802
static int sort_by_cost_desc(
803
    const struct YR_RULE_PROFILING_INFO* r1,
804
    const struct YR_RULE_PROFILING_INFO* r2)
805
0
{
806
0
  if (r1->cost < r2->cost)
807
0
    return 1;
808
809
0
  if (r1->cost > r2->cost)
810
0
    return -1;
811
812
0
  return 0;
813
0
}
814
815
//
816
// yr_scanner_get_profiling_info
817
//
818
// Returns a pointer to an array of YR_RULE_PROFILING_INFO structures with
819
// information about the cost of each rule. The rules are sorted by cost
820
// in descending order and the last item in the array has rule == NULL.
821
// The caller is responsible for freeing the returned array by calling
822
// yr_free. Calling this function only makes sense if YR_PROFILING_ENABLED
823
// is defined, if not, the cost for each rule won't be computed, it will be
824
// set to 0 for all rules.
825
//
826
YR_API YR_RULE_PROFILING_INFO* yr_scanner_get_profiling_info(
827
    YR_SCANNER* scanner)
828
0
{
829
0
  YR_RULE_PROFILING_INFO* profiling_info = yr_malloc(
830
0
      (scanner->rules->num_rules + 1) * sizeof(YR_RULE_PROFILING_INFO));
831
832
0
  if (profiling_info == NULL)
833
0
    return NULL;
834
835
0
  for (uint32_t i = 0; i < scanner->rules->num_rules; i++)
836
0
  {
837
0
    profiling_info[i].rule = &scanner->rules->rules_table[i];
838
#ifdef YR_PROFILING_ENABLED
839
    profiling_info[i].cost = scanner->profiling_info[i].exec_time +
840
                             (scanner->profiling_info[i].atom_matches *
841
                              scanner->profiling_info[i].match_time) /
842
                                 YR_MATCH_VERIFICATION_PROFILING_RATE;
843
#else
844
0
    memset(&profiling_info[i], 0, sizeof(YR_RULE_PROFILING_INFO));
845
0
#endif
846
0
  }
847
848
0
  qsort(
849
0
      profiling_info,
850
0
      scanner->rules->num_rules,
851
0
      sizeof(YR_RULE_PROFILING_INFO),
852
0
      (int (*)(const void*, const void*)) sort_by_cost_desc);
853
854
0
  profiling_info[scanner->rules->num_rules].rule = NULL;
855
0
  profiling_info[scanner->rules->num_rules].cost = 0;
856
857
0
  return profiling_info;
858
0
}
859
860
YR_API void yr_scanner_reset_profiling_info(YR_SCANNER* scanner)
861
0
{
862
#ifdef YR_PROFILING_ENABLED
863
  memset(
864
      scanner->profiling_info,
865
      0,
866
      scanner->rules->num_rules * sizeof(YR_PROFILING_INFO));
867
#endif
868
0
}
869
870
YR_API int yr_scanner_print_profiling_info(YR_SCANNER* scanner)
871
0
{
872
0
  printf("\n===== PROFILING INFORMATION =====\n\n");
873
874
0
  YR_RULE_PROFILING_INFO* info = yr_scanner_get_profiling_info(scanner);
875
876
0
  if (info == NULL)
877
0
    return ERROR_INSUFFICIENT_MEMORY;
878
879
0
  YR_RULE_PROFILING_INFO* rpi = info;
880
881
0
  while (rpi->rule != NULL)
882
0
  {
883
0
    printf(
884
0
        "%10" PRIu64 " %s:%s: \n",
885
0
        rpi->cost,
886
0
        rpi->rule->ns->name,
887
0
        rpi->rule->identifier);
888
889
0
    rpi++;
890
0
  }
891
892
0
  printf("\n=================================\n");
893
894
0
  yr_free(info);
895
896
0
  return ERROR_SUCCESS;
897
0
}