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
7.37k
{
50
7.37k
  YR_DEBUG_FPRINTF(
51
7.37k
      2,
52
7.37k
      stderr,
53
7.37k
      "+ %s(block_data=%p block->base=0x%" PRIx64 " block->size=%zu) {\n",
54
7.37k
      __FUNCTION__,
55
7.37k
      block_data,
56
7.37k
      block->base,
57
7.37k
      block->size);
58
59
7.37k
  int result = ERROR_SUCCESS;
60
61
7.37k
  YR_RULES* rules = scanner->rules;
62
7.37k
  YR_AC_TRANSITION* transition_table = rules->ac_transition_table;
63
7.37k
  uint32_t* match_table = rules->ac_match_table;
64
65
7.37k
  YR_AC_MATCH* match;
66
7.37k
  YR_AC_TRANSITION transition;
67
68
7.37k
  size_t i = 0;
69
7.37k
  uint32_t state = YR_AC_ROOT_STATE;
70
7.37k
  uint16_t index;
71
72
101M
  while (i < block->size)
73
101M
  {
74
101M
    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
101M
    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
101M
    index = block_data[i++] + 1;
125
101M
    transition = transition_table[state + index];
126
127
101M
    while (YR_AC_INVALID_TRANSITION(transition, index))
128
101M
    {
129
101M
      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
101M
      else
135
101M
      {
136
101M
        transition = 0;
137
101M
        break;
138
101M
      }
139
101M
    }
140
141
101M
    state = YR_AC_NEXT_STATE(transition);
142
101M
  }
143
144
7.37k
  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
7.37k
_exit:
166
167
7.37k
  YR_DEBUG_FPRINTF(
168
7.37k
      2,
169
7.37k
      stderr,
170
7.37k
      "} = %d AKA %s // %s()\n",
171
7.37k
      result,
172
7.37k
      yr_debug_error_as_string(result),
173
7.37k
      __FUNCTION__);
174
175
7.37k
  return result;
176
7.37k
}
177
178
static void _yr_scanner_clean_matches(YR_SCANNER* scanner)
179
7.37k
{
180
7.37k
  YR_DEBUG_FPRINTF(2, stderr, "- %s() {} \n", __FUNCTION__);
181
182
7.37k
  memset(
183
7.37k
      scanner->rule_matches_flags,
184
7.37k
      0,
185
7.37k
      sizeof(YR_BITMASK) * YR_BITMASK_SIZE(scanner->rules->num_rules));
186
187
7.37k
  memset(
188
7.37k
      scanner->ns_unsatisfied_flags,
189
7.37k
      0,
190
7.37k
      sizeof(YR_BITMASK) * YR_BITMASK_SIZE(scanner->rules->num_namespaces));
191
192
7.37k
  memset(
193
7.37k
      scanner->strings_temp_disabled,
194
7.37k
      0,
195
7.37k
      sizeof(YR_BITMASK) * YR_BITMASK_SIZE(scanner->rules->num_strings));
196
197
7.37k
  memset(scanner->matches, 0, sizeof(YR_MATCHES) * scanner->rules->num_strings);
198
199
7.37k
  memset(
200
7.37k
      scanner->unconfirmed_matches,
201
7.37k
      0,
202
7.37k
      sizeof(YR_MATCHES) * scanner->rules->num_strings);
203
7.37k
}
204
205
YR_API int yr_scanner_create(YR_RULES* rules, YR_SCANNER** scanner)
206
7.37k
{
207
7.37k
  YR_DEBUG_FPRINTF(2, stderr, "- %s() {} \n", __FUNCTION__);
208
209
7.37k
  YR_EXTERNAL_VARIABLE* external;
210
7.37k
  YR_SCANNER* new_scanner;
211
212
7.37k
  new_scanner = (YR_SCANNER*) yr_calloc(1, sizeof(YR_SCANNER));
213
214
7.37k
  if (new_scanner == NULL)
215
0
    return ERROR_INSUFFICIENT_MEMORY;
216
217
7.37k
  FAIL_ON_ERROR_WITH_CLEANUP(
218
7.37k
      yr_hash_table_create(64, &new_scanner->objects_table),
219
7.37k
      yr_free(new_scanner));
220
221
7.37k
  new_scanner->rules = rules;
222
7.37k
  new_scanner->entry_point = YR_UNDEFINED;
223
7.37k
  new_scanner->file_size = YR_UNDEFINED;
224
7.37k
  new_scanner->canary = rand();
225
226
  // By default report both matching and non-matching rules.
227
7.37k
  new_scanner->flags = SCAN_FLAGS_REPORT_RULES_MATCHING |
228
7.37k
                       SCAN_FLAGS_REPORT_RULES_NOT_MATCHING;
229
230
7.37k
  new_scanner->rule_matches_flags = (YR_BITMASK*) yr_calloc(
231
7.37k
      sizeof(YR_BITMASK), YR_BITMASK_SIZE(rules->num_rules));
232
233
7.37k
  new_scanner->ns_unsatisfied_flags = (YR_BITMASK*) yr_calloc(
234
7.37k
      sizeof(YR_BITMASK), YR_BITMASK_SIZE(rules->num_namespaces));
235
236
7.37k
  new_scanner->strings_temp_disabled = (YR_BITMASK*) yr_calloc(
237
7.37k
      sizeof(YR_BITMASK), YR_BITMASK_SIZE(rules->num_strings));
238
239
7.37k
  new_scanner->matches = (YR_MATCHES*) yr_calloc(
240
7.37k
      rules->num_strings, sizeof(YR_MATCHES));
241
242
7.37k
  new_scanner->unconfirmed_matches = (YR_MATCHES*) yr_calloc(
243
7.37k
      rules->num_strings, sizeof(YR_MATCHES));
244
245
7.37k
  if (new_scanner->rule_matches_flags == NULL ||
246
7.37k
      new_scanner->ns_unsatisfied_flags == NULL ||
247
7.37k
      new_scanner->strings_temp_disabled == NULL ||
248
7.37k
      new_scanner->matches == NULL ||  //
249
7.37k
      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
7.37k
  new_scanner->profiling_info = NULL;
266
7.37k
#endif
267
268
7.37k
  external = rules->ext_vars_table;
269
270
7.37k
  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
7.37k
  *scanner = new_scanner;
293
294
7.37k
  return ERROR_SUCCESS;
295
7.37k
}
296
297
YR_API void yr_scanner_destroy(YR_SCANNER* scanner)
298
7.37k
{
299
7.37k
  YR_DEBUG_FPRINTF(2, stderr, "- %s() {} \n", __FUNCTION__);
300
301
7.37k
  RE_FIBER* fiber = scanner->re_fiber_pool.fibers.head;
302
303
7.37k
  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
7.37k
  RE_FAST_EXEC_POSITION* position = scanner->re_fast_exec_position_pool.head;
311
312
7.37k
  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
7.37k
  if (scanner->objects_table != NULL)
320
7.37k
  {
321
7.37k
    yr_hash_table_destroy(
322
7.37k
        scanner->objects_table,
323
7.37k
        (YR_HASH_TABLE_FREE_VALUE_FUNC) yr_object_destroy);
324
7.37k
  }
325
326
#ifdef YR_PROFILING_ENABLED
327
  yr_free(scanner->profiling_info);
328
#endif
329
330
7.37k
  yr_free(scanner->rule_matches_flags);
331
7.37k
  yr_free(scanner->ns_unsatisfied_flags);
332
7.37k
  yr_free(scanner->strings_temp_disabled);
333
7.37k
  yr_free(scanner->matches);
334
7.37k
  yr_free(scanner->unconfirmed_matches);
335
7.37k
  yr_free(scanner);
336
7.37k
}
337
338
YR_API void yr_scanner_set_callback(
339
    YR_SCANNER* scanner,
340
    YR_CALLBACK_FUNC callback,
341
    void* user_data)
342
7.37k
{
343
7.37k
  scanner->callback = callback;
344
7.37k
  scanner->user_data = user_data;
345
7.37k
}
346
347
YR_API void yr_scanner_set_timeout(YR_SCANNER* scanner, int timeout)
348
7.37k
{
349
  // Convert timeout from seconds to nanoseconds.
350
7.37k
  scanner->timeout = timeout * 1000000000ULL;
351
7.37k
}
352
353
YR_API void yr_scanner_set_flags(YR_SCANNER* scanner, int flags)
354
7.37k
{
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
7.37k
  if (!(flags & SCAN_FLAGS_REPORT_RULES_MATCHING) &&
359
7.37k
      !(flags & SCAN_FLAGS_REPORT_RULES_NOT_MATCHING))
360
7.37k
  {
361
7.37k
    flags |= SCAN_FLAGS_REPORT_RULES_MATCHING |
362
7.37k
             SCAN_FLAGS_REPORT_RULES_NOT_MATCHING;
363
7.37k
  }
364
365
7.37k
  scanner->flags = flags;
366
7.37k
}
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
7.37k
{
431
7.37k
  YR_DEBUG_FPRINTF(2, stderr, "+ %s() {\n", __FUNCTION__);
432
433
7.37k
  YR_RULES* rules;
434
7.37k
  YR_RULE* rule;
435
7.37k
  YR_MEMORY_BLOCK* block;
436
437
7.37k
  int i, result = ERROR_SUCCESS;
438
439
7.37k
  if (scanner->callback == NULL)
440
0
  {
441
0
    result = ERROR_CALLBACK_REQUIRED;
442
0
    goto _exit;
443
0
  }
444
445
7.37k
  scanner->iterator = iterator;
446
7.37k
  rules = scanner->rules;
447
448
7.37k
  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
7.37k
  else
455
7.37k
  {
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
7.37k
    uint32_t max_match_data;
462
463
7.37k
    FAIL_ON_ERROR(
464
7.37k
        yr_get_configuration_uint32(YR_CONFIG_MAX_MATCH_DATA, &max_match_data));
465
466
7.37k
    result = yr_notebook_create(
467
7.37k
        1024 * (sizeof(YR_MATCH) + max_match_data), &scanner->matches_notebook);
468
469
7.37k
    if (result != ERROR_SUCCESS)
470
0
      goto _exit;
471
472
7.37k
    yr_stopwatch_start(&scanner->stopwatch);
473
474
7.37k
    block = iterator->first(iterator);
475
7.37k
  }
476
477
14.7k
  while (block != NULL)
478
7.37k
  {
479
7.37k
    const uint8_t* data = block->fetch_data(block);
480
481
    // fetch_data may fail and return NULL.
482
7.37k
    if (data == NULL)
483
0
    {
484
0
      block = iterator->next(iterator);
485
0
      continue;
486
0
    }
487
488
7.37k
    if (scanner->entry_point == YR_UNDEFINED)
489
7.37k
    {
490
7.37k
      YR_TRYCATCH(
491
7.37k
          !(scanner->flags & SCAN_FLAGS_NO_TRYCATCH),
492
7.37k
          {
493
7.37k
            if (scanner->flags & SCAN_FLAGS_PROCESS_MEMORY)
494
7.37k
              scanner->entry_point = yr_get_entry_point_address(
495
7.37k
                  data, block->size, block->base);
496
7.37k
            else
497
7.37k
              scanner->entry_point = yr_get_entry_point_offset(
498
7.37k
                  data, block->size);
499
7.37k
          },
500
7.37k
          {});
501
7.37k
    }
502
503
7.37k
    YR_TRYCATCH(
504
7.37k
        !(scanner->flags & SCAN_FLAGS_NO_TRYCATCH),
505
7.37k
        { result = _yr_scanner_scan_mem_block(scanner, data, block); },
506
7.37k
        { result = ERROR_COULD_NOT_MAP_FILE; });
507
508
7.37k
    if (result != ERROR_SUCCESS)
509
0
      goto _exit;
510
511
7.37k
    block = iterator->next(iterator);
512
7.37k
  }
513
514
7.37k
  result = iterator->last_error;
515
516
7.37k
  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
7.37k
  if (iterator->file_size != NULL)
522
7.37k
    scanner->file_size = iterator->file_size(iterator);
523
0
  else
524
0
    scanner->file_size = YR_UNDEFINED;
525
526
7.37k
  YR_TRYCATCH(
527
7.37k
      !(scanner->flags & SCAN_FLAGS_NO_TRYCATCH),
528
7.37k
      { result = yr_execute_code(scanner); },
529
7.37k
      { result = ERROR_COULD_NOT_MAP_FILE; });
530
531
7.37k
  if (result != ERROR_SUCCESS)
532
0
    goto _exit;
533
534
14.7k
  for (i = 0, rule = rules->rules_table; !RULE_IS_NULL(rule); i++, rule++)
535
7.37k
  {
536
7.37k
    int message = 0;
537
538
7.37k
    if (yr_bitmask_is_set(scanner->rule_matches_flags, i) &&
539
7.37k
        yr_bitmask_is_not_set(scanner->ns_unsatisfied_flags, rule->ns->idx))
540
287
    {
541
287
      if (scanner->flags & SCAN_FLAGS_REPORT_RULES_MATCHING)
542
287
        message = CALLBACK_MSG_RULE_MATCHING;
543
287
    }
544
7.08k
    else
545
7.08k
    {
546
7.08k
      if (scanner->flags & SCAN_FLAGS_REPORT_RULES_NOT_MATCHING)
547
7.08k
        message = CALLBACK_MSG_RULE_NOT_MATCHING;
548
7.08k
    }
549
550
7.37k
    if (message != 0 && !RULE_IS_PRIVATE(rule))
551
7.37k
    {
552
7.37k
      switch (scanner->callback(scanner, message, rule, scanner->user_data))
553
7.37k
      {
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
7.37k
      }
562
7.37k
    }
563
7.37k
  }
564
565
7.37k
  scanner->callback(
566
7.37k
      scanner, CALLBACK_MSG_SCAN_FINISHED, NULL, scanner->user_data);
567
568
7.37k
_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
7.37k
  if (result != ERROR_BLOCK_NOT_READY)
574
7.37k
  {
575
7.37k
    _yr_scanner_clean_matches(scanner);
576
577
7.37k
    if (scanner->matches_notebook != NULL)
578
7.37k
    {
579
7.37k
      yr_notebook_destroy(scanner->matches_notebook);
580
7.37k
      scanner->matches_notebook = NULL;
581
7.37k
    }
582
7.37k
  }
583
584
7.37k
  YR_DEBUG_FPRINTF(
585
7.37k
      2,
586
7.37k
      stderr,
587
7.37k
      "} = %d AKA %s // %s()\n",
588
7.37k
      result,
589
7.37k
      yr_debug_error_as_string(result),
590
7.37k
      __FUNCTION__);
591
592
7.37k
  return result;
593
7.37k
}
594
595
static YR_MEMORY_BLOCK* _yr_get_first_block(YR_MEMORY_BLOCK_ITERATOR* iterator)
596
14.7k
{
597
14.7k
  YR_MEMORY_BLOCK* result = (YR_MEMORY_BLOCK*) iterator->context;
598
599
14.7k
  YR_DEBUG_FPRINTF(
600
14.7k
      2,
601
14.7k
      stderr,
602
14.7k
      "- %s() {} = %p // default iterator; single memory block, blocking\n",
603
14.7k
      __FUNCTION__,
604
14.7k
      result);
605
606
14.7k
  return result;
607
14.7k
}
608
609
static YR_MEMORY_BLOCK* _yr_get_next_block(YR_MEMORY_BLOCK_ITERATOR* iterator)
610
8.87k
{
611
8.87k
  YR_MEMORY_BLOCK* result = NULL;
612
613
8.87k
  YR_DEBUG_FPRINTF(
614
8.87k
      2,
615
8.87k
      stderr,
616
8.87k
      "- %s() {} = %p // default iterator; single memory block, blocking\n",
617
8.87k
      __FUNCTION__,
618
8.87k
      result);
619
620
8.87k
  return result;
621
8.87k
}
622
623
static uint64_t _yr_get_file_size(YR_MEMORY_BLOCK_ITERATOR* iterator)
624
7.37k
{
625
7.37k
  uint64_t file_size = ((YR_MEMORY_BLOCK*) iterator->context)->size;
626
627
7.37k
  YR_DEBUG_FPRINTF(
628
7.37k
      2,
629
7.37k
      stderr,
630
7.37k
      "- %s() {} = %" PRIu64
631
7.37k
      "  // default iterator; single memory block, blocking\n",
632
7.37k
      __FUNCTION__,
633
7.37k
      file_size);
634
635
7.37k
  return file_size;
636
7.37k
}
637
638
static const uint8_t* _yr_fetch_block_data(YR_MEMORY_BLOCK* block)
639
14.7k
{
640
14.7k
  return (const uint8_t*) block->context;
641
14.7k
}
642
643
YR_API int yr_scanner_scan_mem(
644
    YR_SCANNER* scanner,
645
    const uint8_t* buffer,
646
    size_t buffer_size)
647
7.37k
{
648
7.37k
  YR_DEBUG_FPRINTF(
649
7.37k
      2,
650
7.37k
      stderr,
651
7.37k
      "+ %s(buffer=%p buffer_size=%zu) {\n",
652
7.37k
      __FUNCTION__,
653
7.37k
      buffer,
654
7.37k
      buffer_size);
655
656
7.37k
  YR_MEMORY_BLOCK block;
657
7.37k
  YR_MEMORY_BLOCK_ITERATOR iterator;
658
659
7.37k
  block.size = buffer_size;
660
7.37k
  block.base = 0;
661
7.37k
  block.fetch_data = _yr_fetch_block_data;
662
7.37k
  block.context = (void*) buffer;
663
664
7.37k
  iterator.context = &block;
665
7.37k
  iterator.first = _yr_get_first_block;
666
7.37k
  iterator.next = _yr_get_next_block;
667
7.37k
  iterator.file_size = _yr_get_file_size;
668
7.37k
  iterator.last_error = ERROR_SUCCESS;
669
670
7.37k
  int result = yr_scanner_scan_mem_blocks(scanner, &iterator);
671
672
7.37k
  YR_DEBUG_FPRINTF(
673
7.37k
      2,
674
7.37k
      stderr,
675
7.37k
      "} = %d AKA %s // %s()\n",
676
7.37k
      result,
677
7.37k
      yr_debug_error_as_string(result),
678
7.37k
      __FUNCTION__);
679
680
7.37k
  return result;
681
7.37k
}
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
}