Coverage Report

Created: 2023-03-26 07:38

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