Coverage Report

Created: 2023-06-07 07:19

/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
28.7k
{
50
28.7k
  YR_DEBUG_FPRINTF(
51
28.7k
      2,
52
28.7k
      stderr,
53
28.7k
      "+ %s(block_data=%p block->base=0x%" PRIx64 " block->size=%zu) {\n",
54
28.7k
      __FUNCTION__,
55
28.7k
      block_data,
56
28.7k
      block->base,
57
28.7k
      block->size);
58
59
28.7k
  int result = ERROR_SUCCESS;
60
61
28.7k
  YR_RULES* rules = scanner->rules;
62
28.7k
  YR_AC_TRANSITION* transition_table = rules->ac_transition_table;
63
28.7k
  uint32_t* match_table = rules->ac_match_table;
64
65
28.7k
  YR_AC_MATCH* match;
66
28.7k
  YR_AC_TRANSITION transition;
67
68
28.7k
  size_t i = 0;
69
28.7k
  uint32_t state = YR_AC_ROOT_STATE;
70
28.7k
  uint16_t index;
71
28.7k
  YR_STRING* report_string = NULL;
72
28.7k
  YR_RULE* rule = NULL;
73
74
388M
  while (i < block->size)
75
388M
  {
76
388M
    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
388M
    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
388M
    index = block_data[i++] + 1;
135
388M
    transition = transition_table[state + index];
136
137
388M
    while (YR_AC_INVALID_TRANSITION(transition, index))
138
388M
    {
139
388M
      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
388M
      else
145
388M
      {
146
388M
        transition = 0;
147
388M
        break;
148
388M
      }
149
388M
    }
150
151
388M
    state = YR_AC_NEXT_STATE(transition);
152
388M
  }
153
154
28.7k
  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
28.7k
  if (rule != NULL &&
176
28.7k
      scanner->matches->count >= YR_SLOW_STRING_MATCHES &&
177
28.7k
      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
28.7k
_exit:
195
196
28.7k
  YR_DEBUG_FPRINTF(
197
28.7k
      2,
198
28.7k
      stderr,
199
28.7k
      "} = %d AKA %s // %s()\n",
200
28.7k
      result,
201
28.7k
      yr_debug_error_as_string(result),
202
28.7k
      __FUNCTION__);
203
204
28.7k
  return result;
205
28.7k
}
206
207
static void _yr_scanner_clean_matches(YR_SCANNER* scanner)
208
28.7k
{
209
28.7k
  YR_DEBUG_FPRINTF(2, stderr, "- %s() {} \n", __FUNCTION__);
210
211
28.7k
  memset(
212
28.7k
      scanner->rule_matches_flags,
213
28.7k
      0,
214
28.7k
      sizeof(YR_BITMASK) * YR_BITMASK_SIZE(scanner->rules->num_rules));
215
216
28.7k
  memset(
217
28.7k
      scanner->ns_unsatisfied_flags,
218
28.7k
      0,
219
28.7k
      sizeof(YR_BITMASK) * YR_BITMASK_SIZE(scanner->rules->num_namespaces));
220
221
28.7k
  memset(
222
28.7k
      scanner->strings_temp_disabled,
223
28.7k
      0,
224
28.7k
      sizeof(YR_BITMASK) * YR_BITMASK_SIZE(scanner->rules->num_strings));
225
226
28.7k
  memset(scanner->matches, 0, sizeof(YR_MATCHES) * scanner->rules->num_strings);
227
228
28.7k
  memset(
229
28.7k
      scanner->unconfirmed_matches,
230
28.7k
      0,
231
28.7k
      sizeof(YR_MATCHES) * scanner->rules->num_strings);
232
28.7k
}
233
234
YR_API int yr_scanner_create(YR_RULES* rules, YR_SCANNER** scanner)
235
28.7k
{
236
28.7k
  YR_DEBUG_FPRINTF(2, stderr, "- %s() {} \n", __FUNCTION__);
237
238
28.7k
  YR_EXTERNAL_VARIABLE* external;
239
28.7k
  YR_SCANNER* new_scanner;
240
241
28.7k
  new_scanner = (YR_SCANNER*) yr_calloc(1, sizeof(YR_SCANNER));
242
243
28.7k
  if (new_scanner == NULL)
244
0
    return ERROR_INSUFFICIENT_MEMORY;
245
246
28.7k
  FAIL_ON_ERROR_WITH_CLEANUP(
247
28.7k
      yr_hash_table_create(64, &new_scanner->objects_table),
248
28.7k
      yr_free(new_scanner));
249
250
28.7k
  new_scanner->rules = rules;
251
28.7k
  new_scanner->entry_point = YR_UNDEFINED;
252
28.7k
  new_scanner->file_size = YR_UNDEFINED;
253
28.7k
  new_scanner->canary = rand();
254
255
  // By default report both matching and non-matching rules.
256
28.7k
  new_scanner->flags = SCAN_FLAGS_REPORT_RULES_MATCHING |
257
28.7k
                       SCAN_FLAGS_REPORT_RULES_NOT_MATCHING;
258
259
28.7k
  new_scanner->rule_matches_flags = (YR_BITMASK*) yr_calloc(
260
28.7k
      sizeof(YR_BITMASK), YR_BITMASK_SIZE(rules->num_rules));
261
262
28.7k
  new_scanner->ns_unsatisfied_flags = (YR_BITMASK*) yr_calloc(
263
28.7k
      sizeof(YR_BITMASK), YR_BITMASK_SIZE(rules->num_namespaces));
264
265
28.7k
  new_scanner->strings_temp_disabled = (YR_BITMASK*) yr_calloc(
266
28.7k
      sizeof(YR_BITMASK), YR_BITMASK_SIZE(rules->num_strings));
267
268
28.7k
  new_scanner->matches = (YR_MATCHES*) yr_calloc(
269
28.7k
      rules->num_strings, sizeof(YR_MATCHES));
270
271
28.7k
  new_scanner->unconfirmed_matches = (YR_MATCHES*) yr_calloc(
272
28.7k
      rules->num_strings, sizeof(YR_MATCHES));
273
274
28.7k
  if (new_scanner->rule_matches_flags == NULL ||
275
28.7k
      new_scanner->ns_unsatisfied_flags == NULL ||
276
28.7k
      new_scanner->strings_temp_disabled == NULL ||
277
28.7k
      new_scanner->matches == NULL ||  //
278
28.7k
      new_scanner->unconfirmed_matches == NULL)
279
0
  {
280
0
    yr_scanner_destroy(new_scanner);
281
0
    return ERROR_INSUFFICIENT_MEMORY;
282
0
  }
283
284
#ifdef YR_PROFILING_ENABLED
285
  new_scanner->profiling_info = yr_calloc(
286
      rules->num_rules, sizeof(YR_PROFILING_INFO));
287
288
  if (new_scanner->profiling_info == NULL)
289
  {
290
    yr_scanner_destroy(new_scanner);
291
    return ERROR_INSUFFICIENT_MEMORY;
292
  }
293
#else
294
28.7k
  new_scanner->profiling_info = NULL;
295
28.7k
#endif
296
297
28.7k
  external = rules->ext_vars_table;
298
299
28.7k
  while (!EXTERNAL_VARIABLE_IS_NULL(external))
300
0
  {
301
0
    YR_OBJECT* object;
302
303
0
    FAIL_ON_ERROR_WITH_CLEANUP(
304
0
        yr_object_from_external_variable(external, &object),
305
        // cleanup
306
0
        yr_scanner_destroy(new_scanner));
307
308
0
    FAIL_ON_ERROR_WITH_CLEANUP(yr_hash_table_add(
309
0
                                   new_scanner->objects_table,
310
0
                                   external->identifier,
311
0
                                   NULL,
312
0
                                   (void*) object),
313
                               // cleanup
314
0
                               yr_object_destroy(object);
315
0
                               yr_scanner_destroy(new_scanner));
316
317
0
    yr_object_set_canary(object, new_scanner->canary);
318
0
    external++;
319
0
  }
320
321
28.7k
  *scanner = new_scanner;
322
323
28.7k
  return ERROR_SUCCESS;
324
28.7k
}
325
326
YR_API void yr_scanner_destroy(YR_SCANNER* scanner)
327
28.7k
{
328
28.7k
  YR_DEBUG_FPRINTF(2, stderr, "- %s() {} \n", __FUNCTION__);
329
330
28.7k
  RE_FIBER* fiber = scanner->re_fiber_pool.fibers.head;
331
332
28.7k
  while (fiber != NULL)
333
0
  {
334
0
    RE_FIBER* next = fiber->next;
335
0
    yr_free(fiber);
336
0
    fiber = next;
337
0
  }
338
339
28.7k
  RE_FAST_EXEC_POSITION* position = scanner->re_fast_exec_position_pool.head;
340
341
28.7k
  while (position != NULL)
342
0
  {
343
0
    RE_FAST_EXEC_POSITION* next = position->next;
344
0
    yr_free(position);
345
0
    position = next;
346
0
  }
347
348
28.7k
  if (scanner->objects_table != NULL)
349
28.7k
  {
350
28.7k
    yr_hash_table_destroy(
351
28.7k
        scanner->objects_table,
352
28.7k
        (YR_HASH_TABLE_FREE_VALUE_FUNC) yr_object_destroy);
353
28.7k
  }
354
355
#ifdef YR_PROFILING_ENABLED
356
  yr_free(scanner->profiling_info);
357
#endif
358
359
28.7k
  yr_free(scanner->rule_matches_flags);
360
28.7k
  yr_free(scanner->ns_unsatisfied_flags);
361
28.7k
  yr_free(scanner->strings_temp_disabled);
362
28.7k
  yr_free(scanner->matches);
363
28.7k
  yr_free(scanner->unconfirmed_matches);
364
28.7k
  yr_free(scanner);
365
28.7k
}
366
367
YR_API void yr_scanner_set_callback(
368
    YR_SCANNER* scanner,
369
    YR_CALLBACK_FUNC callback,
370
    void* user_data)
371
28.7k
{
372
28.7k
  scanner->callback = callback;
373
28.7k
  scanner->user_data = user_data;
374
28.7k
}
375
376
YR_API void yr_scanner_set_timeout(YR_SCANNER* scanner, int timeout)
377
28.7k
{
378
  // Convert timeout from seconds to nanoseconds.
379
28.7k
  scanner->timeout = timeout * 1000000000ULL;
380
28.7k
}
381
382
YR_API void yr_scanner_set_flags(YR_SCANNER* scanner, int flags)
383
28.7k
{
384
  // For backward compatibility, if neither SCAN_FLAGS_REPORT_RULES_MATCHING
385
  // nor SCAN_FLAGS_REPORT_RULES_NOT_MATCHING are specified, both are assumed.
386
387
28.7k
  if (!(flags & SCAN_FLAGS_REPORT_RULES_MATCHING) &&
388
28.7k
      !(flags & SCAN_FLAGS_REPORT_RULES_NOT_MATCHING))
389
28.7k
  {
390
28.7k
    flags |= SCAN_FLAGS_REPORT_RULES_MATCHING |
391
28.7k
             SCAN_FLAGS_REPORT_RULES_NOT_MATCHING;
392
28.7k
  }
393
394
28.7k
  scanner->flags = flags;
395
28.7k
}
396
397
YR_API int yr_scanner_define_integer_variable(
398
    YR_SCANNER* scanner,
399
    const char* identifier,
400
    int64_t value)
401
0
{
402
0
  YR_OBJECT* obj = (YR_OBJECT*) yr_hash_table_lookup(
403
0
      scanner->objects_table, identifier, NULL);
404
405
0
  if (obj == NULL)
406
0
    return ERROR_INVALID_ARGUMENT;
407
408
0
  if (obj->type != OBJECT_TYPE_INTEGER)
409
0
    return ERROR_INVALID_EXTERNAL_VARIABLE_TYPE;
410
411
0
  return yr_object_set_integer(value, obj, NULL);
412
0
}
413
414
YR_API int yr_scanner_define_boolean_variable(
415
    YR_SCANNER* scanner,
416
    const char* identifier,
417
    int value)
418
0
{
419
0
  return yr_scanner_define_integer_variable(scanner, identifier, value);
420
0
}
421
422
YR_API int yr_scanner_define_float_variable(
423
    YR_SCANNER* scanner,
424
    const char* identifier,
425
    double value)
426
0
{
427
0
  YR_OBJECT* obj = (YR_OBJECT*) yr_hash_table_lookup(
428
0
      scanner->objects_table, identifier, NULL);
429
430
0
  if (obj == NULL)
431
0
    return ERROR_INVALID_ARGUMENT;
432
433
0
  if (obj->type != OBJECT_TYPE_FLOAT)
434
0
    return ERROR_INVALID_EXTERNAL_VARIABLE_TYPE;
435
436
0
  return yr_object_set_float(value, obj, NULL);
437
0
}
438
439
YR_API int yr_scanner_define_string_variable(
440
    YR_SCANNER* scanner,
441
    const char* identifier,
442
    const char* value)
443
0
{
444
0
  YR_OBJECT* obj = (YR_OBJECT*) yr_hash_table_lookup(
445
0
      scanner->objects_table, identifier, NULL);
446
447
0
  if (obj == NULL)
448
0
    return ERROR_INVALID_ARGUMENT;
449
450
0
  if (obj->type != OBJECT_TYPE_STRING)
451
0
    return ERROR_INVALID_EXTERNAL_VARIABLE_TYPE;
452
453
0
  return yr_object_set_string(value, strlen(value), obj, NULL);
454
0
}
455
456
YR_API int yr_scanner_scan_mem_blocks(
457
    YR_SCANNER* scanner,
458
    YR_MEMORY_BLOCK_ITERATOR* iterator)
459
28.7k
{
460
28.7k
  YR_DEBUG_FPRINTF(2, stderr, "+ %s() {\n", __FUNCTION__);
461
462
28.7k
  YR_RULES* rules;
463
28.7k
  YR_RULE* rule;
464
28.7k
  YR_MEMORY_BLOCK* block;
465
466
28.7k
  int i, result = ERROR_SUCCESS;
467
468
28.7k
  if (scanner->callback == NULL)
469
0
  {
470
0
    result = ERROR_CALLBACK_REQUIRED;
471
0
    goto _exit;
472
0
  }
473
474
28.7k
  scanner->iterator = iterator;
475
28.7k
  rules = scanner->rules;
476
477
28.7k
  if (iterator->last_error == ERROR_BLOCK_NOT_READY)
478
0
  {
479
    // The caller is invoking yr_scanner_scan_mem_blocks again because the
480
    // previous call returned ERROR_BLOCK_NOT_READY.
481
0
    block = iterator->next(iterator);
482
0
  }
483
28.7k
  else
484
28.7k
  {
485
    // Create the notebook that will hold the YR_MATCH structures representing
486
    // each match found. This notebook will also contain snippets of the
487
    // matching data (the "data" field in YR_MATCH points to the snippet
488
    // corresponding to the match). Each notebook's page can store up to 1024
489
    // matches.
490
28.7k
    uint32_t max_match_data;
491
492
28.7k
    FAIL_ON_ERROR(
493
28.7k
        yr_get_configuration_uint32(YR_CONFIG_MAX_MATCH_DATA, &max_match_data));
494
495
28.7k
    result = yr_notebook_create(
496
28.7k
        1024 * (sizeof(YR_MATCH) + max_match_data), &scanner->matches_notebook);
497
498
28.7k
    if (result != ERROR_SUCCESS)
499
0
      goto _exit;
500
501
28.7k
    yr_stopwatch_start(&scanner->stopwatch);
502
503
28.7k
    block = iterator->first(iterator);
504
28.7k
  }
505
506
57.5k
  while (block != NULL)
507
28.7k
  {
508
28.7k
    const uint8_t* data = block->fetch_data(block);
509
510
    // fetch_data may fail and return NULL.
511
28.7k
    if (data == NULL)
512
0
    {
513
0
      block = iterator->next(iterator);
514
0
      continue;
515
0
    }
516
517
28.7k
    if (scanner->entry_point == YR_UNDEFINED)
518
28.7k
    {
519
28.7k
      YR_TRYCATCH(
520
28.7k
          !(scanner->flags & SCAN_FLAGS_NO_TRYCATCH),
521
28.7k
          {
522
28.7k
            if (scanner->flags & SCAN_FLAGS_PROCESS_MEMORY)
523
28.7k
              scanner->entry_point = yr_get_entry_point_address(
524
28.7k
                  data, block->size, block->base);
525
28.7k
            else
526
28.7k
              scanner->entry_point = yr_get_entry_point_offset(
527
28.7k
                  data, block->size);
528
28.7k
          },
529
28.7k
          {});
530
28.7k
    }
531
532
28.7k
    YR_TRYCATCH(
533
28.7k
        !(scanner->flags & SCAN_FLAGS_NO_TRYCATCH),
534
28.7k
        { result = _yr_scanner_scan_mem_block(scanner, data, block); },
535
28.7k
        { result = ERROR_COULD_NOT_MAP_FILE; });
536
537
28.7k
    if (result != ERROR_SUCCESS)
538
0
      goto _exit;
539
540
28.7k
    block = iterator->next(iterator);
541
28.7k
  }
542
543
28.7k
  result = iterator->last_error;
544
545
28.7k
  if (result != ERROR_SUCCESS)
546
0
    goto _exit;
547
548
  // If the iterator has a file_size function, ask the function for the file's
549
  // size, if not file size is undefined.
550
28.7k
  if (iterator->file_size != NULL)
551
28.7k
    scanner->file_size = iterator->file_size(iterator);
552
0
  else
553
0
    scanner->file_size = YR_UNDEFINED;
554
555
28.7k
  YR_TRYCATCH(
556
28.7k
      !(scanner->flags & SCAN_FLAGS_NO_TRYCATCH),
557
28.7k
      { result = yr_execute_code(scanner); },
558
28.7k
      { result = ERROR_COULD_NOT_MAP_FILE; });
559
560
28.7k
  if (result != ERROR_SUCCESS)
561
0
    goto _exit;
562
563
47.1k
  for (i = 0, rule = rules->rules_table; !RULE_IS_NULL(rule); i++, rule++)
564
18.4k
  {
565
18.4k
    int message = 0;
566
567
18.4k
    if (yr_bitmask_is_set(scanner->rule_matches_flags, i) &&
568
18.4k
        yr_bitmask_is_not_set(scanner->ns_unsatisfied_flags, rule->ns->idx))
569
321
    {
570
321
      if (scanner->flags & SCAN_FLAGS_REPORT_RULES_MATCHING)
571
321
        message = CALLBACK_MSG_RULE_MATCHING;
572
321
    }
573
18.1k
    else
574
18.1k
    {
575
18.1k
      if (scanner->flags & SCAN_FLAGS_REPORT_RULES_NOT_MATCHING)
576
18.1k
        message = CALLBACK_MSG_RULE_NOT_MATCHING;
577
18.1k
    }
578
579
18.4k
    if (message != 0 && !RULE_IS_PRIVATE(rule))
580
18.4k
    {
581
18.4k
      switch (scanner->callback(scanner, message, rule, scanner->user_data))
582
18.4k
      {
583
0
      case CALLBACK_ABORT:
584
0
        result = ERROR_SUCCESS;
585
0
        goto _exit;
586
587
0
      case CALLBACK_ERROR:
588
0
        result = ERROR_CALLBACK_ERROR;
589
0
        goto _exit;
590
18.4k
      }
591
18.4k
    }
592
18.4k
  }
593
594
28.7k
  scanner->callback(
595
28.7k
      scanner, CALLBACK_MSG_SCAN_FINISHED, NULL, scanner->user_data);
596
597
28.7k
_exit:
598
599
  // If error is ERROR_BLOCK_NOT_READY we don't clean the matches and don't
600
  // destroy the notebook yet. ERROR_BLOCK_NOT_READY is not a permament error,
601
  // the caller can still call this function again for a retry.
602
28.7k
  if (result != ERROR_BLOCK_NOT_READY)
603
28.7k
  {
604
28.7k
    _yr_scanner_clean_matches(scanner);
605
606
28.7k
    if (scanner->matches_notebook != NULL)
607
28.7k
    {
608
28.7k
      yr_notebook_destroy(scanner->matches_notebook);
609
28.7k
      scanner->matches_notebook = NULL;
610
28.7k
    }
611
28.7k
  }
612
613
28.7k
  YR_DEBUG_FPRINTF(
614
28.7k
      2,
615
28.7k
      stderr,
616
28.7k
      "} = %d AKA %s // %s()\n",
617
28.7k
      result,
618
28.7k
      yr_debug_error_as_string(result),
619
28.7k
      __FUNCTION__);
620
621
28.7k
  return result;
622
28.7k
}
623
624
static YR_MEMORY_BLOCK* _yr_get_first_block(YR_MEMORY_BLOCK_ITERATOR* iterator)
625
57.5k
{
626
57.5k
  YR_MEMORY_BLOCK* result = (YR_MEMORY_BLOCK*) iterator->context;
627
628
57.5k
  YR_DEBUG_FPRINTF(
629
57.5k
      2,
630
57.5k
      stderr,
631
57.5k
      "- %s() {} = %p // default iterator; single memory block, blocking\n",
632
57.5k
      __FUNCTION__,
633
57.5k
      result);
634
635
57.5k
  return result;
636
57.5k
}
637
638
static YR_MEMORY_BLOCK* _yr_get_next_block(YR_MEMORY_BLOCK_ITERATOR* iterator)
639
42.3k
{
640
42.3k
  YR_MEMORY_BLOCK* result = NULL;
641
642
42.3k
  YR_DEBUG_FPRINTF(
643
42.3k
      2,
644
42.3k
      stderr,
645
42.3k
      "- %s() {} = %p // default iterator; single memory block, blocking\n",
646
42.3k
      __FUNCTION__,
647
42.3k
      result);
648
649
42.3k
  return result;
650
42.3k
}
651
652
static uint64_t _yr_get_file_size(YR_MEMORY_BLOCK_ITERATOR* iterator)
653
28.7k
{
654
28.7k
  uint64_t file_size = ((YR_MEMORY_BLOCK*) iterator->context)->size;
655
656
28.7k
  YR_DEBUG_FPRINTF(
657
28.7k
      2,
658
28.7k
      stderr,
659
28.7k
      "- %s() {} = %" PRIu64
660
28.7k
      "  // default iterator; single memory block, blocking\n",
661
28.7k
      __FUNCTION__,
662
28.7k
      file_size);
663
664
28.7k
  return file_size;
665
28.7k
}
666
667
static const uint8_t* _yr_fetch_block_data(YR_MEMORY_BLOCK* block)
668
57.5k
{
669
57.5k
  return (const uint8_t*) block->context;
670
57.5k
}
671
672
YR_API int yr_scanner_scan_mem(
673
    YR_SCANNER* scanner,
674
    const uint8_t* buffer,
675
    size_t buffer_size)
676
28.7k
{
677
28.7k
  YR_DEBUG_FPRINTF(
678
28.7k
      2,
679
28.7k
      stderr,
680
28.7k
      "+ %s(buffer=%p buffer_size=%zu) {\n",
681
28.7k
      __FUNCTION__,
682
28.7k
      buffer,
683
28.7k
      buffer_size);
684
685
28.7k
  YR_MEMORY_BLOCK block;
686
28.7k
  YR_MEMORY_BLOCK_ITERATOR iterator;
687
28.7k
  int result;
688
689
28.7k
  block.size = buffer_size;
690
28.7k
  block.base = 0;
691
28.7k
  block.fetch_data = _yr_fetch_block_data;
692
28.7k
  block.context = (void*) buffer;
693
694
28.7k
  iterator.context = &block;
695
28.7k
  iterator.first = _yr_get_first_block;
696
28.7k
  iterator.next = _yr_get_next_block;
697
28.7k
  iterator.file_size = _yr_get_file_size;
698
28.7k
  iterator.last_error = ERROR_SUCCESS;
699
700
  // Detect cases where every byte of input is checked for match and input size is bigger then 0.2 MB
701
28.7k
  if (scanner->rules->ac_match_table[YR_AC_ROOT_STATE] != 0 && buffer_size > YR_FILE_SIZE_THRESHOLD)
702
0
  {
703
0
    YR_STRING* report_string = scanner->rules->ac_match_pool[YR_AC_ROOT_STATE].string;
704
0
    result = scanner->callback(
705
0
          scanner,
706
0
          CALLBACK_MSG_TOO_SLOW_SCANNING,
707
0
          (void*) report_string,
708
0
          scanner->user_data);
709
0
    if (result != CALLBACK_CONTINUE)
710
0
      return ERROR_TOO_SLOW_SCANNING;
711
0
  }
712
713
28.7k
  result = yr_scanner_scan_mem_blocks(scanner, &iterator);
714
715
28.7k
  YR_DEBUG_FPRINTF(
716
28.7k
      2,
717
28.7k
      stderr,
718
28.7k
      "} = %d AKA %s // %s()\n",
719
28.7k
      result,
720
28.7k
      yr_debug_error_as_string(result),
721
28.7k
      __FUNCTION__);
722
723
28.7k
  return result;
724
28.7k
}
725
726
YR_API int yr_scanner_scan_file(YR_SCANNER* scanner, const char* filename)
727
0
{
728
0
  YR_MAPPED_FILE mfile;
729
730
0
  int result = yr_filemap_map(filename, &mfile);
731
732
0
  if (result == ERROR_SUCCESS)
733
0
  {
734
0
    result = yr_scanner_scan_mem(scanner, mfile.data, mfile.size);
735
0
    yr_filemap_unmap(&mfile);
736
0
  }
737
738
0
  return result;
739
0
}
740
741
YR_API int yr_scanner_scan_fd(YR_SCANNER* scanner, YR_FILE_DESCRIPTOR fd)
742
0
{
743
0
  YR_MAPPED_FILE mfile;
744
745
0
  int result = yr_filemap_map_fd(fd, 0, 0, &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_fd(&mfile);
751
0
  }
752
753
0
  return result;
754
0
}
755
756
YR_API int yr_scanner_scan_proc(YR_SCANNER* scanner, int pid)
757
0
{
758
0
  YR_MEMORY_BLOCK_ITERATOR iterator;
759
760
0
  int result = yr_process_open_iterator(pid, &iterator);
761
762
0
  if (result == ERROR_SUCCESS)
763
0
  {
764
0
    int prev_flags = scanner->flags;
765
0
    scanner->flags |= SCAN_FLAGS_PROCESS_MEMORY;
766
0
    result = yr_scanner_scan_mem_blocks(scanner, &iterator);
767
0
    scanner->flags = prev_flags;
768
0
    yr_process_close_iterator(&iterator);
769
0
  }
770
771
0
  return result;
772
0
}
773
774
YR_API YR_STRING* yr_scanner_last_error_string(YR_SCANNER* scanner)
775
0
{
776
0
  return scanner->last_error_string;
777
0
}
778
779
YR_API YR_RULE* yr_scanner_last_error_rule(YR_SCANNER* scanner)
780
0
{
781
0
  if (scanner->last_error_string == NULL)
782
0
    return NULL;
783
784
0
  return &scanner->rules->rules_table[scanner->last_error_string->rule_idx];
785
0
}
786
787
static int sort_by_cost_desc(
788
    const struct YR_RULE_PROFILING_INFO* r1,
789
    const struct YR_RULE_PROFILING_INFO* r2)
790
0
{
791
0
  if (r1->cost < r2->cost)
792
0
    return 1;
793
794
0
  if (r1->cost > r2->cost)
795
0
    return -1;
796
797
0
  return 0;
798
0
}
799
800
//
801
// yr_scanner_get_profiling_info
802
//
803
// Returns a pointer to an array of YR_RULE_PROFILING_INFO structures with
804
// information about the cost of each rule. The rules are sorted by cost
805
// in descending order and the last item in the array has rule == NULL.
806
// The caller is responsible for freeing the returned array by calling
807
// yr_free. Calling this function only makes sense if YR_PROFILING_ENABLED
808
// is defined, if not, the cost for each rule won't be computed, it will be
809
// set to 0 for all rules.
810
//
811
YR_API YR_RULE_PROFILING_INFO* yr_scanner_get_profiling_info(
812
    YR_SCANNER* scanner)
813
0
{
814
0
  YR_RULE_PROFILING_INFO* profiling_info = yr_malloc(
815
0
      (scanner->rules->num_rules + 1) * sizeof(YR_RULE_PROFILING_INFO));
816
817
0
  if (profiling_info == NULL)
818
0
    return NULL;
819
820
0
  for (uint32_t i = 0; i < scanner->rules->num_rules; i++)
821
0
  {
822
0
    profiling_info[i].rule = &scanner->rules->rules_table[i];
823
#ifdef YR_PROFILING_ENABLED
824
    profiling_info[i].cost = scanner->profiling_info[i].exec_time +
825
                             (scanner->profiling_info[i].atom_matches *
826
                              scanner->profiling_info[i].match_time) /
827
                                 YR_MATCH_VERIFICATION_PROFILING_RATE;
828
#else
829
0
    memset(&profiling_info[i], 0, sizeof(YR_RULE_PROFILING_INFO));
830
0
#endif
831
0
  }
832
833
0
  qsort(
834
0
      profiling_info,
835
0
      scanner->rules->num_rules,
836
0
      sizeof(YR_RULE_PROFILING_INFO),
837
0
      (int (*)(const void*, const void*)) sort_by_cost_desc);
838
839
0
  profiling_info[scanner->rules->num_rules].rule = NULL;
840
0
  profiling_info[scanner->rules->num_rules].cost = 0;
841
842
0
  return profiling_info;
843
0
}
844
845
YR_API void yr_scanner_reset_profiling_info(YR_SCANNER* scanner)
846
0
{
847
#ifdef YR_PROFILING_ENABLED
848
  memset(
849
      scanner->profiling_info,
850
      0,
851
      scanner->rules->num_rules * sizeof(YR_PROFILING_INFO));
852
#endif
853
0
}
854
855
YR_API int yr_scanner_print_profiling_info(YR_SCANNER* scanner)
856
0
{
857
0
  printf("\n===== PROFILING INFORMATION =====\n\n");
858
859
0
  YR_RULE_PROFILING_INFO* info = yr_scanner_get_profiling_info(scanner);
860
861
0
  if (info == NULL)
862
0
    return ERROR_INSUFFICIENT_MEMORY;
863
864
0
  YR_RULE_PROFILING_INFO* rpi = info;
865
866
0
  while (rpi->rule != NULL)
867
0
  {
868
0
    printf(
869
0
        "%10" PRIu64 " %s:%s: \n",
870
0
        rpi->cost,
871
0
        rpi->rule->ns->name,
872
0
        rpi->rule->identifier);
873
874
0
    rpi++;
875
0
  }
876
877
0
  printf("\n=================================\n");
878
879
0
  yr_free(info);
880
881
0
  return ERROR_SUCCESS;
882
0
}