Coverage Report

Created: 2026-10-17 06:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/yara/libyara/modules/pe/pe.c
Line
Count
Source
1
/*
2
Copyright (c) 2014. 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 <ctype.h>
31
#include <stdio.h>
32
#include <time.h>
33
34
#include "../crypto.h"
35
#if defined(HAVE_LIBCRYPTO)
36
#include <authenticode-parser/authenticode.h>
37
#include <openssl/evp.h>
38
#endif
39
40
#include <yara/dotnet.h>
41
#include <yara/endian.h>
42
#include <yara/limits.h>
43
#include <yara/mem.h>
44
#include <yara/modules.h>
45
#include <yara/pe.h>
46
#include <yara/pe_utils.h>
47
#include <yara/strutils.h>
48
#include <yara/unaligned.h>
49
#include <yara/utils.h>
50
51
#define MODULE_NAME pe
52
53
0
#define IMPORT_STANDARD 1
54
0
#define IMPORT_DELAYED  2
55
#define IMPORT_ANY      (~0)
56
57
// http://msdn.microsoft.com/en-us/library/ms648009(v=vs.85).aspx
58
#define RESOURCE_TYPE_CURSOR       1
59
#define RESOURCE_TYPE_BITMAP       2
60
#define RESOURCE_TYPE_ICON         3
61
#define RESOURCE_TYPE_MENU         4
62
#define RESOURCE_TYPE_DIALOG       5
63
#define RESOURCE_TYPE_STRING       6
64
#define RESOURCE_TYPE_FONTDIR      7
65
#define RESOURCE_TYPE_FONT         8
66
#define RESOURCE_TYPE_ACCELERATOR  9
67
#define RESOURCE_TYPE_RCDATA       10
68
#define RESOURCE_TYPE_MESSAGETABLE 11
69
#define RESOURCE_TYPE_GROUP_CURSOR \
70
  12  // MAKEINTRESOURCE((ULONG_PTR)(RT_CURSOR) + 11)
71
#define RESOURCE_TYPE_GROUP_ICON \
72
  14  // MAKEINTRESOURCE((ULONG_PTR)(RT_ICON) + 11)
73
0
#define RESOURCE_TYPE_VERSION    16
74
#define RESOURCE_TYPE_DLGINCLUDE 17
75
#define RESOURCE_TYPE_PLUGPLAY   19
76
#define RESOURCE_TYPE_VXD        20
77
#define RESOURCE_TYPE_ANICURSOR  21
78
#define RESOURCE_TYPE_ANIICON    22
79
#define RESOURCE_TYPE_HTML       23
80
#define RESOURCE_TYPE_MANIFEST   24
81
82
0
#define RESOURCE_CALLBACK_CONTINUE 0
83
0
#define RESOURCE_CALLBACK_ABORT    1
84
85
0
#define RESOURCE_ITERATOR_FINISHED 0
86
0
#define RESOURCE_ITERATOR_ABORTED  1
87
88
0
#define MAX_PE_IMPORTS             16384
89
#define MAX_PE_EXPORTS             16384
90
#define MAX_EXPORT_NAME_LENGTH     512
91
#define MAX_IMPORT_DLL_NAME_LENGTH 256
92
0
#define MAX_RESOURCES              65536
93
94
#define IS_RESOURCE_SUBDIRECTORY(entry) \
95
0
  (yr_le32toh((entry)->OffsetToData) & 0x80000000)
96
97
0
#define RESOURCE_OFFSET(entry) (yr_le32toh((entry)->OffsetToData) & 0x7FFFFFFF)
98
99
typedef int (*RESOURCE_CALLBACK_FUNC)(
100
    PIMAGE_RESOURCE_DATA_ENTRY rsrc_data,
101
    int rsrc_type,
102
    int rsrc_id,
103
    int rsrc_language,
104
    const IMAGE_RESOURCE_DIR_STRING_U* type_string,
105
    const IMAGE_RESOURCE_DIR_STRING_U* name_string,
106
    const IMAGE_RESOURCE_DIR_STRING_U* lang_string,
107
    void* cb_data);
108
109
static size_t available_space(PE* pe, void* pointer)
110
0
{
111
0
  if ((uint8_t*) pointer < pe->data)
112
0
    return 0;
113
114
0
  if ((uint8_t*) pointer >= pe->data + pe->data_size)
115
0
    return 0;
116
117
0
  return pe->data + pe->data_size - (uint8_t*) pointer;
118
0
}
119
120
static int wide_string_fits_in_pe(PE* pe, char* data)
121
0
{
122
0
  size_t i = 0;
123
0
  size_t space_left = available_space(pe, data);
124
125
0
  while (space_left >= 2)
126
0
  {
127
0
    if (data[i] == 0 && data[i + 1] == 0)
128
0
      return 1;
129
0
    space_left -= 2;
130
0
    i += 2;
131
0
  }
132
133
0
  return 0;
134
0
}
135
136
// Parse the rich signature.
137
// http://www.ntcore.com/files/richsign.htm
138
139
static void pe_parse_rich_signature(PE* pe, uint64_t base_address)
140
0
{
141
0
  PIMAGE_DOS_HEADER mz_header;
142
0
  PRICH_SIGNATURE rich_signature = NULL;
143
144
0
  DWORD* rich_ptr = NULL;
145
0
  BYTE* raw_data = NULL;
146
0
  BYTE* clear_data = NULL;
147
0
  BYTE* version_data = NULL;
148
0
  DWORD* p = NULL;
149
0
  uint32_t nthdr_offset = 0;
150
0
  uint32_t key = 0;
151
0
  size_t rich_len = 0;
152
0
  int64_t rich_count = 0;
153
154
0
  if (pe->data_size < sizeof(IMAGE_DOS_HEADER))
155
0
    return;
156
157
0
  mz_header = (PIMAGE_DOS_HEADER) pe->data;
158
159
0
  if (yr_le16toh(mz_header->e_magic) != IMAGE_DOS_SIGNATURE)
160
0
    return;
161
162
  // To find the Rich marker we start at the NT header and work backwards, so
163
  // make sure we have at least enough data to get to the NT header.
164
0
  nthdr_offset = yr_le32toh(mz_header->e_lfanew);
165
0
  if (nthdr_offset > pe->data_size + sizeof(uint32_t) || nthdr_offset < 4)
166
0
    return;
167
168
  // Most files have the Rich header at offset 0x80, but that is not always
169
  // true. 582ce3eea9c97d5e89f7d83953a6d518b16770e635a19a456c0225449c6967a4 is
170
  // one sample which has a Rich header starting at offset 0x200. To properly
171
  // find the Rich header we need to start at the NT header and work backwards.
172
0
  p = (DWORD*) (pe->data + nthdr_offset - 4);
173
174
0
  while (p >= (DWORD*) (pe->data + sizeof(IMAGE_DOS_HEADER)))
175
0
  {
176
0
    if (yr_le32toh(*p) == RICH_RICH)
177
0
    {
178
      // The XOR key is the dword following the Rich value. We  use this to find
179
      // DanS header only.
180
0
      key = *(p + 1);
181
0
      rich_ptr = p;
182
0
      --p;
183
0
      break;
184
0
    }
185
186
    // The NT header is 8 byte aligned so we can move back in 4 byte increments.
187
0
    --p;
188
0
  }
189
190
  // If we haven't found a key we can skip processing the rest.
191
0
  if (key == 0)
192
0
    return;
193
194
  // If we have found the key we need to now find the start (DanS).
195
0
  while (p >= (DWORD*) (pe->data + sizeof(IMAGE_DOS_HEADER)))
196
0
  {
197
0
    if (yr_le32toh((*(p) ^ key)) == RICH_DANS)
198
0
    {
199
0
      rich_signature = (PRICH_SIGNATURE) p;
200
0
      break;
201
0
    }
202
203
0
    --p;
204
0
  }
205
206
0
  if (rich_signature == NULL)
207
0
    return;
208
209
  // Multiply by 4 because we are counting in DWORDs.
210
0
  rich_len = (rich_ptr - (DWORD*) rich_signature) * 4;
211
0
  raw_data = (BYTE*) yr_malloc(rich_len);
212
213
0
  if (!raw_data)
214
0
    return;
215
216
0
  memcpy(raw_data, rich_signature, rich_len);
217
218
0
  yr_set_integer(
219
0
      base_address + ((uint8_t*) rich_signature - pe->data),
220
0
      pe->object,
221
0
      "rich_signature.offset");
222
223
0
  yr_set_integer(rich_len, pe->object, "rich_signature.length");
224
0
  yr_set_integer(yr_le32toh(key), pe->object, "rich_signature.key");
225
226
0
  clear_data = (BYTE*) yr_malloc(rich_len);
227
228
0
  if (!clear_data)
229
0
  {
230
0
    yr_free(raw_data);
231
0
    return;
232
0
  }
233
234
  // Copy the entire block here to be XORed.
235
0
  memcpy(clear_data, raw_data, rich_len);
236
237
0
  for (rich_ptr = (DWORD*) clear_data;
238
0
       rich_ptr < (DWORD*) (clear_data + rich_len);
239
0
       rich_ptr++)
240
0
  {
241
0
    *rich_ptr ^= key;
242
0
  }
243
244
0
  yr_set_sized_string(
245
0
      (char*) raw_data, rich_len, pe->object, "rich_signature.raw_data");
246
247
0
  yr_free(raw_data);
248
249
0
  yr_set_sized_string(
250
0
      (char*) clear_data, rich_len, pe->object, "rich_signature.clear_data");
251
252
  // A Rich header shorter than RICH_SIGNATURE makes the unsigned subtraction
253
  // below wrap around, producing a bogus rich_count. _rich_version guards the
254
  // same computation, do it here too.
255
0
  if (rich_len < sizeof(RICH_SIGNATURE))
256
0
  {
257
0
    yr_free(clear_data);
258
0
    return;
259
0
  }
260
261
  // Allocate space for just the version data. This is a series of every other
262
  // dword from the clear data. This is useful to be able to hash alone.
263
  // We need to skip the first 3 DWORDs of the RICH_SIGNATURE, which are DanS
264
  // and XOR keys.
265
0
  rich_count = (rich_len - sizeof(RICH_SIGNATURE)) / sizeof(RICH_VERSION_INFO);
266
0
  version_data = (BYTE*) yr_malloc(rich_count * sizeof(DWORD));
267
0
  if (!version_data)
268
0
  {
269
0
    yr_free(clear_data);
270
0
    return;
271
0
  }
272
273
0
  rich_signature = (PRICH_SIGNATURE) clear_data;
274
0
  for (int i = 0; i < rich_count; i++)
275
0
  {
276
0
    memcpy(
277
0
        version_data + (i * sizeof(DWORD)),
278
0
        &rich_signature->versions[i],
279
0
        sizeof(DWORD));
280
0
  }
281
282
0
  yr_set_sized_string(
283
0
      (char*) version_data,
284
0
      rich_count * sizeof(DWORD),
285
0
      pe->object,
286
0
      "rich_signature.version_data");
287
288
0
  yr_free(clear_data);
289
0
  yr_free(version_data);
290
0
}
291
292
static void pe_parse_debug_directory(PE* pe)
293
0
{
294
0
  PIMAGE_DATA_DIRECTORY data_dir;
295
0
  PIMAGE_DEBUG_DIRECTORY debug_dir;
296
0
  int64_t debug_dir_offset;
297
0
  int i, dcount;
298
0
  size_t pdb_path_len;
299
0
  char* pdb_path = NULL;
300
301
0
  data_dir = pe_get_directory_entry(pe, IMAGE_DIRECTORY_ENTRY_DEBUG);
302
303
0
  if (data_dir == NULL)
304
0
    return;
305
306
0
  if (yr_le32toh(data_dir->Size) == 0)
307
0
    return;
308
309
0
  if (yr_le32toh(data_dir->VirtualAddress) == 0)
310
0
    return;
311
312
0
  debug_dir_offset = pe_rva_to_offset(pe, yr_le32toh(data_dir->VirtualAddress));
313
314
0
  if (debug_dir_offset < 0)
315
0
    return;
316
317
0
  dcount = yr_le32toh(data_dir->Size) / sizeof(IMAGE_DEBUG_DIRECTORY);
318
319
0
  for (i = 0; i < dcount; i++)
320
0
  {
321
0
    int64_t pcv_hdr_offset = 0;
322
323
0
    debug_dir = (PIMAGE_DEBUG_DIRECTORY) (pe->data + debug_dir_offset +
324
0
                                          i * sizeof(IMAGE_DEBUG_DIRECTORY));
325
326
0
    if (!struct_fits_in_pe(pe, debug_dir, IMAGE_DEBUG_DIRECTORY))
327
0
      break;
328
329
0
    if (yr_le32toh(debug_dir->Type) != IMAGE_DEBUG_TYPE_CODEVIEW)
330
0
      continue;
331
332
    // The debug info offset may be present either as RVA or as raw offset
333
    // Sample: 0249e00b6d46bee5a17096559f18e671cd0ceee36373e8708f614a9a6c7c079e
334
0
    if (debug_dir->AddressOfRawData != 0)
335
0
    {
336
0
      pcv_hdr_offset = pe_rva_to_offset(
337
0
          pe, yr_le32toh(debug_dir->AddressOfRawData));
338
0
    }
339
340
    // Give it chance to read it from the RAW offset
341
    // Sample: 735f72b3fcd72789f01e923c9de2a9ab5b5ffbece23633da81d976ad0ad159e3
342
0
    if (pcv_hdr_offset <= 0 && debug_dir->PointerToRawData != 0)
343
0
    {
344
0
      pcv_hdr_offset = yr_le32toh(debug_dir->PointerToRawData);
345
0
    }
346
347
0
    if (pcv_hdr_offset <= 0)
348
0
      continue;
349
350
0
    PCV_HEADER cv_hdr = (PCV_HEADER) (pe->data + pcv_hdr_offset);
351
352
0
    if (!struct_fits_in_pe(pe, cv_hdr, CV_HEADER))
353
0
      continue;
354
355
0
    if (yr_le32toh(cv_hdr->dwSignature) == CVINFO_PDB20_CVSIGNATURE)
356
0
    {
357
0
      PCV_INFO_PDB20 pdb20 = (PCV_INFO_PDB20) cv_hdr;
358
359
0
      if (struct_fits_in_pe(pe, pdb20, CV_INFO_PDB20))
360
0
        pdb_path = (char*) (pdb20->PdbFileName);
361
0
    }
362
0
    else if (yr_le32toh(cv_hdr->dwSignature) == CVINFO_PDB70_CVSIGNATURE)
363
0
    {
364
0
      PCV_INFO_PDB70 pdb70 = (PCV_INFO_PDB70) cv_hdr;
365
366
0
      if (struct_fits_in_pe(pe, pdb70, CV_INFO_PDB70))
367
0
        pdb_path = (char*) (pdb70->PdbFileName);
368
0
    }
369
0
    else if (yr_le32toh(cv_hdr->dwSignature) == CODEVIEW_SIGNATURE_MTOC)
370
0
    {
371
0
      PMTOC_ENTRY mtoc = (PMTOC_ENTRY) cv_hdr;
372
373
0
      if (struct_fits_in_pe(pe, mtoc, MTOC_ENTRY))
374
0
        pdb_path = (char*) (mtoc->PdbFileName);
375
0
    }
376
377
0
    if (pdb_path != NULL)
378
0
    {
379
0
      pdb_path_len = strnlen(
380
0
          pdb_path, yr_min(available_space(pe, pdb_path), YR_MAX_PATH));
381
382
0
      if (pdb_path_len >= 0 && pdb_path_len < YR_MAX_PATH)
383
0
      {
384
0
        yr_set_sized_string(pdb_path, pdb_path_len, pe->object, "pdb_path");
385
0
        break;
386
0
      }
387
0
    }
388
0
  }
389
0
}
390
391
// Return a pointer to the resource directory string or NULL.
392
// The callback function will parse this and call yr_set_sized_string().
393
// The pointer is guaranteed to have enough space to contain the entire string.
394
static const PIMAGE_RESOURCE_DIR_STRING_U parse_resource_name(
395
    PE* pe,
396
    const uint8_t* rsrc_data,
397
    PIMAGE_RESOURCE_DIRECTORY_ENTRY entry)
398
0
{
399
  // If high bit is set it is an offset relative to rsrc_data, which contains
400
  // a resource directory string.
401
402
0
  if (yr_le32toh(entry->Name) & 0x80000000)
403
0
  {
404
0
    const PIMAGE_RESOURCE_DIR_STRING_U pNameString =
405
0
        (PIMAGE_RESOURCE_DIR_STRING_U) (rsrc_data +
406
0
                                        (yr_le32toh(entry->Name) & 0x7FFFFFFF));
407
408
    // A resource directory string is 2 bytes for the length and then a variable
409
    // length Unicode string. Make sure we have at least 2 bytes.
410
0
    if (!fits_in_pe(pe, pNameString, 2))
411
0
      return NULL;
412
413
    // Sanity check for strings that are excesively large.
414
0
    if (yr_le16toh(pNameString->Length) > 1000)
415
0
      return NULL;
416
417
    // Move past the length and make sure we have enough bytes for the string.
418
0
    if (!fits_in_pe(
419
0
            pe,
420
0
            pNameString,
421
0
            sizeof(uint16_t) + yr_le16toh(pNameString->Length) * 2))
422
0
      return NULL;
423
424
0
    return pNameString;
425
0
  }
426
427
0
  return NULL;
428
0
}
429
430
static int _pe_iterate_resources(
431
    PE* pe,
432
    PIMAGE_RESOURCE_DIRECTORY resource_dir,
433
    const uint8_t* rsrc_data,
434
    int rsrc_tree_level,
435
    int* type,
436
    int* id,
437
    int* language,
438
    const IMAGE_RESOURCE_DIR_STRING_U* type_string,
439
    const IMAGE_RESOURCE_DIR_STRING_U* name_string,
440
    const IMAGE_RESOURCE_DIR_STRING_U* lang_string,
441
    RESOURCE_CALLBACK_FUNC callback,
442
    void* callback_data)
443
0
{
444
0
  int i, result = RESOURCE_ITERATOR_FINISHED;
445
0
  int total_entries;
446
447
0
  PIMAGE_RESOURCE_DIRECTORY_ENTRY entry;
448
449
  // A few sanity checks to avoid corrupt files
450
451
0
  if (yr_le32toh(resource_dir->Characteristics) != 0 ||
452
0
      yr_le16toh(resource_dir->NumberOfNamedEntries) > 32768 ||
453
0
      yr_le16toh(resource_dir->NumberOfIdEntries) > 32768)
454
0
  {
455
0
    return result;
456
0
  }
457
458
0
  total_entries = yr_le16toh(resource_dir->NumberOfNamedEntries) +
459
0
                  yr_le16toh(resource_dir->NumberOfIdEntries);
460
461
  // The first directory entry is just after the resource directory,
462
  // by incrementing resource_dir we skip sizeof(resource_dir) bytes
463
  // and get a pointer to the end of the resource directory.
464
465
0
  entry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (resource_dir + 1);
466
467
0
  if (!fits_in_pe(
468
0
          pe, entry, total_entries * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY)))
469
0
    return result;
470
471
0
  for (i = 0; i < total_entries; i++)
472
0
  {
473
0
    if (yr_le32toh(entry->OffsetToData) == 0)
474
0
      continue;
475
476
0
    switch (rsrc_tree_level)
477
0
    {
478
0
    case 0:
479
0
      *type = yr_le32toh(entry->Name);
480
0
      type_string = parse_resource_name(pe, rsrc_data, entry);
481
0
      break;
482
0
    case 1:
483
0
      *id = yr_le32toh(entry->Name);
484
0
      name_string = parse_resource_name(pe, rsrc_data, entry);
485
0
      break;
486
0
    case 2:
487
0
      *language = yr_le32toh(entry->Name);
488
0
      lang_string = parse_resource_name(pe, rsrc_data, entry);
489
0
      break;
490
0
    }
491
492
0
    if (IS_RESOURCE_SUBDIRECTORY(entry) && rsrc_tree_level < 2)
493
0
    {
494
0
      PIMAGE_RESOURCE_DIRECTORY directory =
495
0
          (PIMAGE_RESOURCE_DIRECTORY) (rsrc_data + RESOURCE_OFFSET(entry));
496
497
      // Don't allow descending into a directory that is already being processed.
498
      // While this does not prevent potential cyclical infinite loops, it is good
499
      // enough to handle all known problematic cases.
500
0
      if (directory != resource_dir &&
501
0
          struct_fits_in_pe(pe, directory, IMAGE_RESOURCE_DIRECTORY))
502
0
      {
503
0
        result = _pe_iterate_resources(
504
0
            pe,
505
0
            directory,
506
0
            rsrc_data,
507
0
            rsrc_tree_level + 1,
508
0
            type,
509
0
            id,
510
0
            language,
511
0
            type_string,
512
0
            name_string,
513
0
            lang_string,
514
0
            callback,
515
0
            callback_data);
516
0
      }
517
0
    }
518
0
    else
519
0
    {
520
0
      PIMAGE_RESOURCE_DATA_ENTRY data_entry =
521
0
          (PIMAGE_RESOURCE_DATA_ENTRY) (rsrc_data + RESOURCE_OFFSET(entry));
522
523
0
      if (struct_fits_in_pe(pe, data_entry, IMAGE_RESOURCE_DATA_ENTRY))
524
0
      {
525
0
        if (yr_le32toh(data_entry->Size) > 0 &&
526
            // We could use the PE's size as an upper bound for the entry size,
527
            // but there are some truncated files where the PE size is lower.
528
            // Use a reasonably large value as the upper bound and avoid some
529
            // completely corrupt entries with random values.
530
0
            yr_le32toh(data_entry->Size) <= 0x3FFFFFFF)
531
0
        {
532
0
          if (callback(
533
0
                  data_entry,
534
0
                  *type,
535
0
                  *id,
536
0
                  *language,
537
0
                  type_string,
538
0
                  name_string,
539
0
                  lang_string,
540
0
                  callback_data) == RESOURCE_CALLBACK_ABORT)
541
0
          {
542
0
            result = RESOURCE_ITERATOR_ABORTED;
543
0
          }
544
0
        }
545
0
      }
546
0
    }
547
548
0
    if (result == RESOURCE_ITERATOR_ABORTED)
549
0
      break;
550
551
0
    entry++;
552
0
  }
553
554
0
  return result;
555
0
}
556
557
static int pe_iterate_resources(
558
    PE* pe,
559
    RESOURCE_CALLBACK_FUNC callback,
560
    void* callback_data)
561
0
{
562
0
  int64_t offset;
563
564
0
  int type = -1;
565
0
  int id = -1;
566
0
  int language = -1;
567
568
0
  IMAGE_RESOURCE_DIR_STRING_U* type_string = NULL;
569
0
  IMAGE_RESOURCE_DIR_STRING_U* name_string = NULL;
570
0
  IMAGE_RESOURCE_DIR_STRING_U* lang_string = NULL;
571
572
0
  PIMAGE_DATA_DIRECTORY directory = pe_get_directory_entry(
573
0
      pe, IMAGE_DIRECTORY_ENTRY_RESOURCE);
574
575
0
  if (directory == NULL)
576
0
    return 0;
577
578
0
  if (yr_le32toh(directory->VirtualAddress) != 0)
579
0
  {
580
0
    PIMAGE_RESOURCE_DIRECTORY rsrc_dir;
581
582
0
    offset = pe_rva_to_offset(pe, yr_le32toh(directory->VirtualAddress));
583
584
0
    if (offset < 0)
585
0
      return 0;
586
587
0
    rsrc_dir = (PIMAGE_RESOURCE_DIRECTORY) (pe->data + offset);
588
589
0
    if (struct_fits_in_pe(pe, rsrc_dir, IMAGE_RESOURCE_DIRECTORY))
590
0
    {
591
0
      yr_set_integer(
592
0
          yr_le32toh(rsrc_dir->TimeDateStamp),
593
0
          pe->object,
594
0
          "resource_timestamp");
595
596
0
      yr_set_integer(
597
0
          yr_le16toh(rsrc_dir->MajorVersion),
598
0
          pe->object,
599
0
          "resource_version.major");
600
601
0
      yr_set_integer(
602
0
          yr_le16toh(rsrc_dir->MinorVersion),
603
0
          pe->object,
604
0
          "resource_version.minor");
605
606
0
      _pe_iterate_resources(
607
0
          pe,
608
0
          rsrc_dir,
609
0
          pe->data + offset,
610
0
          0,
611
0
          &type,
612
0
          &id,
613
0
          &language,
614
0
          type_string,
615
0
          name_string,
616
0
          lang_string,
617
0
          callback,
618
0
          callback_data);
619
620
0
      return 1;
621
0
    }
622
0
  }
623
624
0
  return 0;
625
0
}
626
627
// Align offset to a 32-bit boundary and add it to a pointer
628
629
#define ADD_OFFSET(ptr, offset) \
630
0
  (PVERSION_INFO)((uint8_t*) (ptr) + ((offset + 3) & ~3))
631
632
static void pe_parse_version_info(PIMAGE_RESOURCE_DATA_ENTRY rsrc_data, PE* pe)
633
0
{
634
0
  PVERSION_INFO version_info;
635
636
0
  int64_t version_info_offset = pe_rva_to_offset(
637
0
      pe, yr_le32toh(rsrc_data->OffsetToData));
638
639
0
  if (version_info_offset < 0)
640
0
    return;
641
642
0
  version_info = (PVERSION_INFO) (pe->data + version_info_offset);
643
644
0
  if (!struct_fits_in_pe(pe, version_info, VERSION_INFO))
645
0
    return;
646
647
0
  if (!fits_in_pe(pe, version_info->Key, sizeof("VS_VERSION_INFO") * 2))
648
0
    return;
649
650
0
  if (strcmp_w(version_info->Key, "VS_VERSION_INFO") != 0)
651
0
    return;
652
653
0
  version_info = ADD_OFFSET(version_info, sizeof(VERSION_INFO) + 86);
654
655
0
  while (fits_in_pe(pe, version_info->Key, sizeof("VarFileInfo") * 2) &&
656
0
         strcmp_w(version_info->Key, "VarFileInfo") == 0 &&
657
0
         yr_le16toh(version_info->Length) != 0)
658
0
  {
659
0
    version_info = ADD_OFFSET(version_info, yr_le16toh(version_info->Length));
660
0
  }
661
662
0
  while (fits_in_pe(pe, version_info->Key, sizeof("StringFileInfo") * 2) &&
663
0
         strcmp_w(version_info->Key, "StringFileInfo") == 0 &&
664
0
         yr_le16toh(version_info->Length) != 0)
665
0
  {
666
0
    PVERSION_INFO string_table = ADD_OFFSET(
667
0
        version_info, sizeof(VERSION_INFO) + 30);
668
669
0
    version_info = ADD_OFFSET(version_info, yr_le16toh(version_info->Length));
670
671
0
    while (struct_fits_in_pe(pe, string_table, VERSION_INFO) &&
672
0
           wide_string_fits_in_pe(pe, string_table->Key) &&
673
0
           yr_le16toh(string_table->Length) != 0 && string_table < version_info)
674
0
    {
675
0
      PVERSION_INFO string = ADD_OFFSET(
676
0
          string_table,
677
0
          sizeof(VERSION_INFO) + 2 * (strnlen_w(string_table->Key) + 1));
678
679
0
      string_table = ADD_OFFSET(string_table, yr_le16toh(string_table->Length));
680
681
0
      while (struct_fits_in_pe(pe, string, VERSION_INFO) &&
682
0
             wide_string_fits_in_pe(pe, string->Key) &&
683
0
             yr_le16toh(string->Length) != 0 && string < string_table)
684
0
      {
685
0
        char* string_value = (char*) ADD_OFFSET(
686
0
            string, sizeof(VERSION_INFO) + 2 * (strnlen_w(string->Key) + 1));
687
688
0
        if (wide_string_fits_in_pe(pe, string_value))
689
0
        {
690
0
          char key[64];
691
0
          char value[256];
692
693
0
          strlcpy_w(key, string->Key, sizeof(key));
694
0
          strlcpy_w(value, string_value, sizeof(value));
695
696
          // null terminator of string is not included in version value when
697
          // ValueLength is zero
698
0
          if (yr_le16toh(string->ValueLength) == 0)
699
0
            value[yr_le16toh(string->ValueLength)] = '\0';
700
701
0
          yr_set_string(value, pe->object, "version_info[%s]", key);
702
703
0
          yr_set_string(
704
0
              key, pe->object, "version_info_list[%i].key", pe->version_infos);
705
706
0
          yr_set_string(
707
0
              value,
708
0
              pe->object,
709
0
              "version_info_list[%i].value",
710
0
              pe->version_infos);
711
712
0
          pe->version_infos += 1;
713
0
        }
714
715
0
        string = ADD_OFFSET(string, yr_le16toh(string->Length));
716
0
      }
717
0
    }
718
0
  }
719
0
}
720
721
static void pe_set_resource_string_or_id(
722
    IMAGE_RESOURCE_DIR_STRING_U* rsrc_string,
723
    int rsrc_int,
724
    const char* string_description,
725
    const char* int_description,
726
    PE* pe)
727
0
{
728
0
  if (rsrc_string)
729
0
  {
730
    // Multiply by 2 because it is a Unicode string.
731
0
    size_t length = yr_le16toh(rsrc_string->Length) * 2;
732
733
    // Check if the whole string fits in the PE image.
734
    // If not, the name becomes UNDEFINED by default.
735
0
    if (fits_in_pe(pe, rsrc_string->NameString, length))
736
0
    {
737
0
      yr_set_sized_string(
738
0
          (char*) rsrc_string->NameString,
739
0
          length,
740
0
          pe->object,
741
0
          string_description,
742
0
          pe->resources);
743
0
    }
744
0
  }
745
0
  else
746
0
  {
747
0
    if (rsrc_int != -1)
748
0
      yr_set_integer(rsrc_int, pe->object, int_description, pe->resources);
749
0
  }
750
0
}
751
752
static int pe_collect_resources(
753
    PIMAGE_RESOURCE_DATA_ENTRY rsrc_data,
754
    int rsrc_type,
755
    int rsrc_id,
756
    int rsrc_language,
757
    IMAGE_RESOURCE_DIR_STRING_U* type_string,
758
    IMAGE_RESOURCE_DIR_STRING_U* name_string,
759
    IMAGE_RESOURCE_DIR_STRING_U* lang_string,
760
    PE* pe)
761
0
{
762
  // Don't collect too many resources.
763
0
  if (pe->resources >= MAX_RESOURCES)
764
0
    return RESOURCE_CALLBACK_ABORT;
765
766
0
  yr_set_integer(
767
0
      yr_le32toh(rsrc_data->OffsetToData),
768
0
      pe->object,
769
0
      "resources[%i].rva",
770
0
      pe->resources);
771
772
0
  int64_t offset = pe_rva_to_offset(pe, yr_le32toh(rsrc_data->OffsetToData));
773
774
0
  if (offset < 0)
775
0
    offset = YR_UNDEFINED;
776
777
0
  yr_set_integer(offset, pe->object, "resources[%i].offset", pe->resources);
778
779
0
  yr_set_integer(
780
0
      yr_le32toh(rsrc_data->Size),
781
0
      pe->object,
782
0
      "resources[%i].length",
783
0
      pe->resources);
784
785
0
  pe_set_resource_string_or_id(
786
0
      type_string,
787
0
      rsrc_type,
788
0
      "resources[%i].type_string",
789
0
      "resources[%i].type",
790
0
      pe);
791
792
0
  pe_set_resource_string_or_id(
793
0
      name_string,
794
0
      rsrc_id,
795
0
      "resources[%i].name_string",
796
0
      "resources[%i].id",
797
0
      pe);
798
799
0
  pe_set_resource_string_or_id(
800
0
      lang_string,
801
0
      rsrc_language,
802
0
      "resources[%i].language_string",
803
0
      "resources[%i].language",
804
0
      pe);
805
806
  // Resources we do extra parsing on
807
0
  if (rsrc_type == RESOURCE_TYPE_VERSION)
808
0
    pe_parse_version_info(rsrc_data, pe);
809
810
0
  pe->resources += 1;
811
0
  return RESOURCE_CALLBACK_CONTINUE;
812
0
}
813
814
// Function names should have only lowercase, uppercase, digits and a small
815
// subset of special characters. This is to match behavior of pefile. See
816
// https://github.com/erocarrera/pefile/blob/593d094e35198dad92aaf040bef17eb800c8a373/pefile.py#L2326-L2348
817
static int valid_function_name(char* name)
818
0
{
819
0
  if (!strcmp(name, ""))
820
0
    return 0;
821
822
0
  size_t i = 0;
823
0
  for (char c = name[i]; c != '\x00'; c = name[++i])
824
0
  {
825
0
    if (!(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z') &&
826
0
        !(c >= '0' && c <= '9') && c != '.' && c != '_' && c != '?' &&
827
0
        c != '@' && c != '$' && c != '(' && c != ')' && c != '<' && c != '>')
828
0
      return 0;
829
0
  }
830
0
  return 1;
831
0
}
832
833
static IMPORT_FUNCTION* pe_parse_import_descriptor(
834
    PE* pe,
835
    PIMAGE_IMPORT_DESCRIPTOR import_descriptor,
836
    char* dll_name,
837
    int* num_function_imports)
838
0
{
839
0
  IMPORT_FUNCTION* head = NULL;
840
0
  IMPORT_FUNCTION* tail = NULL;
841
  // This is tracked separately from num_function_imports because that is the
842
  // number of successfully parsed imports, while this is the number of imports
843
  // attempted to be parsed. This allows us to stop parsing on too many imports
844
  // while still accurately recording the number of successfully parsed imports.
845
0
  int parsed_imports = 0;
846
847
0
  int64_t offset = pe_rva_to_offset(
848
0
      pe, yr_le32toh(import_descriptor->OriginalFirstThunk));
849
850
  // I've seen binaries where OriginalFirstThunk is zero. In this case
851
  // use FirstThunk.
852
853
0
  if (offset <= 0)
854
0
    offset = pe_rva_to_offset(pe, yr_le32toh(import_descriptor->FirstThunk));
855
856
0
  if (offset < 0)
857
0
    return NULL;
858
859
0
  if (IS_64BITS_PE(pe))
860
0
  {
861
0
    PIMAGE_THUNK_DATA64 thunks64 = (PIMAGE_THUNK_DATA64) (pe->data + offset);
862
0
    uint64_t func_idx = 0;
863
864
0
    while (struct_fits_in_pe(pe, thunks64, IMAGE_THUNK_DATA64) &&
865
0
           yr_le64toh(thunks64->u1.Ordinal) != 0 &&
866
0
           parsed_imports < MAX_PE_IMPORTS &&
867
0
           *num_function_imports < MAX_PE_IMPORTS)
868
0
    {
869
0
      char* name = NULL;
870
0
      uint16_t ordinal = 0;
871
0
      uint8_t has_ordinal = 0;
872
0
      uint64_t rva_address = 0;
873
874
0
      parsed_imports++;
875
876
0
      if (!(yr_le64toh(thunks64->u1.Ordinal) & IMAGE_ORDINAL_FLAG64))
877
0
      {
878
        // If imported by name
879
0
        offset = pe_rva_to_offset(pe, yr_le64toh(thunks64->u1.Function));
880
881
0
        if (offset >= 0)
882
0
        {
883
0
          PIMAGE_IMPORT_BY_NAME import = (PIMAGE_IMPORT_BY_NAME) (pe->data +
884
0
                                                                  offset);
885
886
0
          if (struct_fits_in_pe(pe, import, IMAGE_IMPORT_BY_NAME))
887
0
          {
888
0
            name = (char*) yr_strndup(
889
0
                (char*) import->Name,
890
0
                yr_min(available_space(pe, import->Name), 512));
891
0
          }
892
0
        }
893
0
      }
894
0
      else
895
0
      {
896
        // The maximum possible value for the ordinal is when the high
897
        // bit is set (indicating import by ordinal) and the low bits
898
        // are FFFF. The maximum number of ordinal exports is 65536.
899
0
        if (yr_le64toh(thunks64->u1.Ordinal) <= 0x800000000000ffff)
900
0
        {
901
0
          ordinal = yr_le64toh(thunks64->u1.Ordinal) & 0xFFFF;
902
0
          name = ord_lookup(dll_name, ordinal);
903
0
          has_ordinal = 1;
904
0
        }
905
0
      }
906
907
0
      rva_address = yr_le32toh(import_descriptor->FirstThunk) +
908
0
                    (sizeof(uint64_t) * func_idx);
909
910
0
      if (name != NULL && !valid_function_name(name))
911
0
      {
912
0
        yr_free(name);
913
0
        thunks64++;
914
0
        func_idx++;
915
0
        continue;
916
0
      }
917
918
0
      if (name != NULL || has_ordinal == 1)
919
0
      {
920
0
        IMPORT_FUNCTION* imported_func = (IMPORT_FUNCTION*) yr_calloc(
921
0
            1, sizeof(IMPORT_FUNCTION));
922
923
0
        if (imported_func == NULL)
924
0
        {
925
0
          yr_free(name);
926
0
        }
927
0
        else
928
0
        {
929
0
          imported_func->name = name;
930
0
          imported_func->ordinal = ordinal;
931
0
          imported_func->has_ordinal = has_ordinal;
932
0
          imported_func->rva = rva_address;
933
0
          imported_func->next = NULL;
934
935
0
          if (head == NULL)
936
0
            head = imported_func;
937
938
0
          if (tail != NULL)
939
0
            tail->next = imported_func;
940
941
0
          tail = imported_func;
942
0
          (*num_function_imports)++;
943
0
        }
944
0
      }
945
946
0
      thunks64++;
947
0
      func_idx++;
948
0
    }
949
0
  }
950
0
  else
951
0
  {
952
0
    PIMAGE_THUNK_DATA32 thunks32 = (PIMAGE_THUNK_DATA32) (pe->data + offset);
953
0
    uint32_t func_idx = 0;
954
955
0
    while (struct_fits_in_pe(pe, thunks32, IMAGE_THUNK_DATA32) &&
956
0
           yr_le32toh(thunks32->u1.Ordinal) != 0 &&
957
0
           parsed_imports < MAX_PE_IMPORTS &&
958
0
           *num_function_imports < MAX_PE_IMPORTS)
959
0
    {
960
0
      char* name = NULL;
961
0
      uint16_t ordinal = 0;
962
0
      uint8_t has_ordinal = 0;
963
0
      uint32_t rva_address = 0;
964
965
0
      parsed_imports++;
966
967
0
      if (!(yr_le32toh(thunks32->u1.Ordinal) & IMAGE_ORDINAL_FLAG32))
968
0
      {
969
        // If imported by name
970
0
        offset = pe_rva_to_offset(pe, yr_le32toh(thunks32->u1.Function));
971
972
0
        if (offset >= 0)
973
0
        {
974
0
          PIMAGE_IMPORT_BY_NAME import = (PIMAGE_IMPORT_BY_NAME) (pe->data +
975
0
                                                                  offset);
976
977
0
          if (struct_fits_in_pe(pe, import, IMAGE_IMPORT_BY_NAME))
978
0
          {
979
0
            name = (char*) yr_strndup(
980
0
                (char*) import->Name,
981
0
                yr_min(available_space(pe, import->Name), 512));
982
0
          }
983
0
        }
984
0
      }
985
0
      else
986
0
      {
987
        // The maximum possible value for the ordinal is when the high
988
        // bit is set (indicating import by ordinal) and the low bits
989
        // are FFFF. The maximum number of ordinal exports is 65536.
990
0
        if (yr_le32toh(thunks32->u1.Ordinal) <= 0x8000ffff)
991
0
        {
992
0
          ordinal = yr_le32toh(thunks32->u1.Ordinal) & 0xFFFF;
993
0
          name = ord_lookup(dll_name, ordinal);
994
0
          has_ordinal = 1;
995
0
        }
996
0
      }
997
998
0
      rva_address = yr_le32toh(import_descriptor->FirstThunk) +
999
0
                    (sizeof(uint32_t) * func_idx);
1000
1001
0
      if (name != NULL && !valid_function_name(name))
1002
0
      {
1003
0
        yr_free(name);
1004
0
        thunks32++;
1005
0
        func_idx++;
1006
0
        continue;
1007
0
      }
1008
1009
0
      if (name != NULL || has_ordinal == 1)
1010
0
      {
1011
0
        IMPORT_FUNCTION* imported_func = (IMPORT_FUNCTION*) yr_calloc(
1012
0
            1, sizeof(IMPORT_FUNCTION));
1013
1014
0
        if (imported_func == NULL)
1015
0
        {
1016
0
          yr_free(name);
1017
0
        }
1018
0
        else
1019
0
        {
1020
0
          imported_func->name = name;
1021
0
          imported_func->ordinal = ordinal;
1022
0
          imported_func->has_ordinal = has_ordinal;
1023
0
          imported_func->rva = rva_address;
1024
0
          imported_func->next = NULL;
1025
1026
0
          if (head == NULL)
1027
0
            head = imported_func;
1028
1029
0
          if (tail != NULL)
1030
0
            tail->next = imported_func;
1031
1032
0
          tail = imported_func;
1033
0
          (*num_function_imports)++;
1034
0
        }
1035
0
      }
1036
1037
0
      thunks32++;
1038
0
      func_idx++;
1039
0
    }
1040
0
  }
1041
1042
0
  return head;
1043
0
}
1044
1045
//
1046
// In Windows PE files, any printable character including 0x20 and above is
1047
// allowed. The only exceptions are characters that are invalid for file names
1048
// in Windows, which are "*<>?|. While they still can be present in the import
1049
// directory, such module can never be present in Windows, so we can treat them
1050
// as invalid.
1051
//
1052
// Explicit: The above also applies to slash, backslash (these form a relative
1053
// path in a subdirectory, which is allowed in the import directory) and colon
1054
// (which forms a file name with an Alternate Data Stream "test:file.dll" - also
1055
// allowed).
1056
//
1057
// Proof of concept: https://github.com/ladislav-zezula/ImportTest
1058
//
1059
// Samples
1060
// -------
1061
// f561d60bff4342e529b2c793e216b73a72e6256f90ab24c3cc460646371130ca (imports
1062
// "test/file.dll")
1063
// b7f7b8a001769eb0f9c36cb27626b62cabdca9a716a222066028fcd206244b40 (imports
1064
// "test\file.dll")
1065
// 94cfb8223132da0a76f9dfbd35a29ab78e5806651758650292ab9c7baf2c0bc2 (imports
1066
// "test:file.dll")
1067
// eb2e2c443840276afe095fff05a3a24c00e610ac0e020233d6cd7a0b0b340fb1 (the
1068
// imported DLL)
1069
//
1070
1071
static int pe_valid_dll_name(const char* dll_name, size_t n)
1072
0
{
1073
0
  const unsigned char* c = (const unsigned char*) dll_name;
1074
0
  size_t l = 0;
1075
1076
0
  while (l < n && *c != '\0')
1077
0
  {
1078
0
    if (*c < ' ' || *c > 0x7e || *c == '\"' || *c == '*' || *c == '<' ||
1079
0
        *c == '>' || *c == '?' || *c == '|')
1080
0
    {
1081
0
      return false;
1082
0
    }
1083
1084
0
    c++;
1085
0
    l++;
1086
0
  }
1087
1088
0
  return (l > 0 && l < n);
1089
0
}
1090
1091
void pe_set_imports(
1092
    PE* pe,
1093
    IMPORTED_DLL* dll,
1094
    const char* dll_name,
1095
    const char* dll_number_of_functions,
1096
    const char* fun_name,
1097
    const char* fun_ordinal,
1098
    const char* rva)
1099
0
{
1100
0
  int dll_cnt = 0;
1101
1102
0
  for (; dll != NULL; dll = dll->next, dll_cnt++)
1103
0
  {
1104
0
    int fun_cnt = 0;
1105
1106
0
    for (IMPORT_FUNCTION* func = dll->functions; func != NULL;
1107
0
         func = func->next, fun_cnt++)
1108
0
    {
1109
0
      yr_set_string(func->name, pe->object, fun_name, dll_cnt, fun_cnt);
1110
1111
0
      if (func->has_ordinal)
1112
0
        yr_set_integer(
1113
0
            func->ordinal, pe->object, fun_ordinal, dll_cnt, fun_cnt);
1114
0
      else
1115
0
        yr_set_integer(YR_UNDEFINED, pe->object, fun_ordinal, dll_cnt, fun_cnt);
1116
1117
0
      if (func->rva)
1118
0
        yr_set_integer(func->rva, pe->object, rva, dll_cnt, fun_cnt);
1119
0
      else
1120
0
        yr_set_integer(YR_UNDEFINED, pe->object, rva, dll_cnt, fun_cnt);
1121
0
    }
1122
0
    yr_set_string(dll->name, pe->object, dll_name, dll_cnt);
1123
0
    yr_set_integer(fun_cnt, pe->object, dll_number_of_functions, dll_cnt);
1124
0
  }
1125
0
}
1126
1127
//
1128
// Walk the imports and collect relevant information. It is used in the
1129
// "imports" function for comparison and in the "imphash" function for
1130
// calculation.
1131
//
1132
1133
static IMPORTED_DLL* pe_parse_imports(PE* pe)
1134
0
{
1135
0
  int64_t offset;
1136
0
  int parsed_imports = 0;        // Number of parsed DLLs
1137
0
  int num_imports = 0;           // Number of imported DLLs
1138
0
  int num_function_imports = 0;  // Total number of functions imported
1139
1140
0
  IMPORTED_DLL* head = NULL;
1141
0
  IMPORTED_DLL* tail = NULL;
1142
1143
0
  PIMAGE_IMPORT_DESCRIPTOR imports;
1144
0
  PIMAGE_DATA_DIRECTORY directory;
1145
1146
  // Default to 0 imports until we know there are any
1147
0
  yr_set_integer(0, pe->object, "number_of_imports");
1148
0
  yr_set_integer(0, pe->object, "number_of_imported_functions");
1149
1150
0
  directory = pe_get_directory_entry(pe, IMAGE_DIRECTORY_ENTRY_IMPORT);
1151
1152
0
  if (directory == NULL)
1153
0
    return NULL;
1154
1155
0
  if (yr_le32toh(directory->VirtualAddress) == 0)
1156
0
    return NULL;
1157
1158
0
  offset = pe_rva_to_offset(pe, yr_le32toh(directory->VirtualAddress));
1159
1160
0
  if (offset < 0)
1161
0
    return NULL;
1162
1163
0
  imports = (PIMAGE_IMPORT_DESCRIPTOR) (pe->data + offset);
1164
1165
0
  while (struct_fits_in_pe(pe, imports, IMAGE_IMPORT_DESCRIPTOR) &&
1166
0
         yr_le32toh(imports->Name) != 0 && parsed_imports < MAX_PE_IMPORTS)
1167
0
  {
1168
0
    parsed_imports++;
1169
1170
0
    int64_t offset = pe_rva_to_offset(pe, yr_le32toh(imports->Name));
1171
1172
0
    if (offset >= 0)
1173
0
    {
1174
0
      IMPORTED_DLL* imported_dll;
1175
1176
0
      char* dll_name = (char*) (pe->data + offset);
1177
1178
0
      if (!pe_valid_dll_name(
1179
0
              dll_name,
1180
0
              yr_min(
1181
                  // DLL names longer than MAX_IMPORT_DLL_NAME_LENGTH
1182
                  // are considered invalid.
1183
0
                  pe->data_size - (size_t) offset,
1184
0
                  MAX_IMPORT_DLL_NAME_LENGTH)))
1185
0
      {
1186
0
        imports++;
1187
0
        continue;
1188
0
      }
1189
1190
0
      imported_dll = (IMPORTED_DLL*) yr_calloc(1, sizeof(IMPORTED_DLL));
1191
1192
0
      if (imported_dll != NULL)
1193
0
      {
1194
0
        IMPORT_FUNCTION* functions = pe_parse_import_descriptor(
1195
0
            pe, imports, dll_name, &num_function_imports);
1196
1197
0
        if (functions != NULL)
1198
0
        {
1199
0
          imported_dll->name = yr_strdup(dll_name);
1200
0
          imported_dll->functions = functions;
1201
0
          imported_dll->next = NULL;
1202
1203
0
          if (head == NULL)
1204
0
            head = imported_dll;
1205
1206
0
          if (tail != NULL)
1207
0
            tail->next = imported_dll;
1208
1209
0
          tail = imported_dll;
1210
0
          num_imports++;
1211
0
        }
1212
0
        else
1213
0
        {
1214
0
          yr_free(imported_dll);
1215
0
        }
1216
0
      }
1217
0
    }
1218
1219
0
    imports++;
1220
0
  }
1221
1222
0
  yr_set_integer(num_imports, pe->object, "number_of_imports");
1223
0
  yr_set_integer(
1224
0
      num_function_imports, pe->object, "number_of_imported_functions");
1225
0
  pe_set_imports(
1226
0
      pe,
1227
0
      head,
1228
0
      "import_details[%i].library_name",
1229
0
      "import_details[%i].number_of_functions",
1230
0
      "import_details[%i].functions[%i].name",
1231
0
      "import_details[%i].functions[%i].ordinal",
1232
0
      "import_details[%i].functions[%i].rva");
1233
1234
0
  return head;
1235
0
}
1236
1237
// Delay-import descriptors made by MS Visual C++ 6.0 have old format
1238
// of delay import directory, where all entries are VAs (as opposite to RVAs
1239
// from newer MS compilers). We convert the delay-import directory entries to
1240
// RVAs by checking the lowest bit in the delay-import descriptor's Attributes
1241
// value
1242
uint64_t pe_normalize_delay_import_value(
1243
    uint64_t image_base,
1244
    uint64_t virtual_address)
1245
0
{
1246
  // Ignore zero items
1247
0
  if (virtual_address != 0)
1248
0
  {
1249
    // Sample: 0fc4cb0620f95bdd624f2c78eea4d2b59594244c6671cf249526adf2f2cb71ec
1250
    // Contains artificially created delay import directory with incorrect
1251
    // values:
1252
    //
1253
    //  Attributes                      0x00000000 <-- Old MS delay import
1254
    //  record, contains VAs NameRva                         0x004010e6
1255
    //  ModuleHandleRva                 0x00000000
1256
    //  DelayImportAddressTableRva      0x00001140 <-- WRONG! This is an RVA
1257
    //  DelayImportNameTableRva         0x004010c0
1258
    //  BoundDelayImportTableRva        0x00000000
1259
    //  ...
1260
1261
0
    if (virtual_address > image_base)
1262
0
    {
1263
0
      virtual_address = virtual_address - image_base;
1264
0
    }
1265
0
  }
1266
1267
0
  return virtual_address;
1268
0
}
1269
1270
int pe_is_termination_delay_import_entry(
1271
    PIMAGE_DELAYLOAD_DESCRIPTOR importDescriptor)
1272
0
{
1273
0
  return (
1274
0
      importDescriptor->Attributes.AllAttributes == 0 &&
1275
0
      importDescriptor->DllNameRVA == 0 &&
1276
0
      importDescriptor->ModuleHandleRVA == 0 &&
1277
0
      importDescriptor->ImportAddressTableRVA == 0 &&
1278
0
      importDescriptor->ImportNameTableRVA == 0 &&
1279
0
      importDescriptor->BoundImportAddressTableRVA == 0 &&
1280
0
      importDescriptor->UnloadInformationTableRVA == 0 &&
1281
0
      importDescriptor->TimeDateStamp == 0);
1282
0
}
1283
1284
char* pe_parse_delay_import_dll_name(PE* pe, uint64_t rva)
1285
0
{
1286
0
  const int64_t offset = pe_rva_to_offset(pe, rva);
1287
1288
0
  if (offset < 0)
1289
0
    return NULL;
1290
1291
0
  char* dll_name = (char*) (pe->data + offset);
1292
1293
0
  if (!pe_valid_dll_name(dll_name, pe->data_size - (size_t) offset))
1294
0
    return NULL;
1295
1296
0
  return yr_strdup(dll_name);
1297
0
}
1298
1299
uint64_t pe_parse_delay_import_pointer(
1300
    PE* pe,
1301
    uint64_t pointerSize,
1302
    uint64_t rva)
1303
0
{
1304
0
  const int64_t offset = pe_rva_to_offset(pe, rva);
1305
1306
0
  if (offset < 0)
1307
0
    return YR_UNDEFINED;
1308
1309
0
  const uint8_t* data = pe->data + offset;
1310
1311
0
  if (!fits_in_pe(pe, data, pointerSize))
1312
0
    return YR_UNDEFINED;
1313
1314
0
  if (IS_64BITS_PE(pe))
1315
0
    return yr_le64toh(yr_unaligned_u64(data));
1316
0
  else
1317
0
    return yr_le32toh(yr_unaligned_u32(data));
1318
0
}
1319
1320
static void* pe_parse_delayed_imports(PE* pe)
1321
0
{
1322
0
  int64_t offset;
1323
0
  uint64_t num_imports = 0;           // Number of imported DLLs
1324
0
  uint64_t num_function_imports = 0;  // Total number of functions imported
1325
0
  uint64_t image_base = OptionalHeader(pe, ImageBase);
1326
0
  uint64_t size_of_image = OptionalHeader(pe, SizeOfImage);
1327
0
  uint64_t pointer_size = (IS_64BITS_PE(pe)) ? 8 : 4;
1328
0
  uint64_t ordinal_mask = (IS_64BITS_PE(pe)) ? IMAGE_ORDINAL_FLAG64
1329
0
                                             : IMAGE_ORDINAL_FLAG32;
1330
1331
0
  IMPORTED_DLL* head_dll = NULL;
1332
0
  IMPORTED_DLL* tail_dll = NULL;
1333
1334
0
  IMPORT_FUNCTION* head_fun = NULL;
1335
0
  IMPORT_FUNCTION* tail_fun = NULL;
1336
1337
0
  PIMAGE_DELAYLOAD_DESCRIPTOR import_descriptor = NULL;
1338
0
  PIMAGE_DATA_DIRECTORY directory = NULL;
1339
1340
  // Default to 0 imports until we know there are any
1341
0
  yr_set_integer(0, pe->object, "number_of_delayed_imports");
1342
0
  yr_set_integer(0, pe->object, "number_of_delayed_imported_functions");
1343
1344
0
  directory = pe_get_directory_entry(pe, IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT);
1345
1346
0
  if (directory == NULL)
1347
0
    return NULL;
1348
1349
0
  if (yr_le32toh(directory->VirtualAddress) == 0)
1350
0
    return NULL;
1351
1352
0
  offset = pe_rva_to_offset(pe, yr_le32toh(directory->VirtualAddress));
1353
1354
0
  if (offset < 0)
1355
0
    return NULL;
1356
1357
0
  import_descriptor = (PIMAGE_DELAYLOAD_DESCRIPTOR) (pe->data + offset);
1358
1359
0
  for (; struct_fits_in_pe(pe, import_descriptor, IMAGE_DELAYLOAD_DESCRIPTOR) &&
1360
0
           num_imports < MAX_PE_IMPORTS;
1361
0
       import_descriptor++)
1362
0
  {
1363
    // Check for the termination entry
1364
0
    if (pe_is_termination_delay_import_entry(import_descriptor))
1365
0
      break;
1366
1367
0
    DWORD Attributes = yr_le32toh(import_descriptor->Attributes.AllAttributes);
1368
0
    DWORD DllNameRVA = yr_le32toh(import_descriptor->DllNameRVA);
1369
0
    DWORD ModuleHandleRVA = yr_le32toh(import_descriptor->ModuleHandleRVA);
1370
0
    DWORD ImportAddressTableRVA = yr_le32toh(
1371
0
        import_descriptor->ImportAddressTableRVA);
1372
0
    DWORD ImportNameTableRVA = yr_le32toh(
1373
0
        import_descriptor->ImportNameTableRVA);
1374
0
    DWORD BoundImportAddressTableRVA = yr_le32toh(
1375
0
        import_descriptor->BoundImportAddressTableRVA);
1376
0
    DWORD UnloadInformationTableRVA = yr_le32toh(
1377
0
        import_descriptor->UnloadInformationTableRVA);
1378
1379
    // Valid delayed import entry starts either with 0 or 0x01.
1380
    // We strict require one of the valid values here
1381
0
    if (Attributes > 0x1)
1382
0
      break;
1383
1384
    // Convert older (MS Visual C++ 6.0) delay-import descriptor to newer one.
1385
    // These delay-import descriptors are distinguishable by lowest bit in
1386
    // rec.Attributes to be zero. Sample:
1387
    // 2775d97f8bdb3311ace960a42eee35dbec84b9d71a6abbacb26c14e83f5897e4
1388
0
    if (!IS_64BITS_PE(pe) && !Attributes)
1389
0
    {
1390
0
      DllNameRVA = (DWORD) pe_normalize_delay_import_value(
1391
0
          image_base, DllNameRVA);
1392
0
      ModuleHandleRVA = (DWORD) pe_normalize_delay_import_value(
1393
0
          image_base, ModuleHandleRVA);
1394
0
      ImportAddressTableRVA = (DWORD) pe_normalize_delay_import_value(
1395
0
          image_base, ImportAddressTableRVA);
1396
0
      ImportNameTableRVA = (DWORD) pe_normalize_delay_import_value(
1397
0
          image_base, ImportNameTableRVA);
1398
0
      BoundImportAddressTableRVA = (DWORD) pe_normalize_delay_import_value(
1399
0
          image_base, BoundImportAddressTableRVA);
1400
0
      UnloadInformationTableRVA = (DWORD) pe_normalize_delay_import_value(
1401
0
          image_base, UnloadInformationTableRVA);
1402
0
    }
1403
1404
    // Stop on blatantly invalid delay import entries (old PELIB behavior)
1405
0
    if (ImportNameTableRVA >= size_of_image ||
1406
0
        ImportAddressTableRVA >= size_of_image ||
1407
0
        DllNameRVA < sizeof(IMAGE_DOS_HEADER) ||
1408
0
        ImportNameTableRVA < sizeof(IMAGE_DOS_HEADER))
1409
0
      break;
1410
1411
0
    char* dll_name = pe_parse_delay_import_dll_name(pe, DllNameRVA);
1412
1413
0
    if (dll_name == NULL)
1414
0
      continue;
1415
1416
0
    IMPORTED_DLL* imported_dll = (IMPORTED_DLL*) yr_calloc(
1417
0
        1, sizeof(IMPORTED_DLL));
1418
1419
0
    if (imported_dll == NULL)
1420
0
    {
1421
0
      yr_free(dll_name);
1422
0
      continue;
1423
0
    }
1424
1425
0
    imported_dll->name = dll_name;
1426
0
    imported_dll->next = NULL;
1427
0
    imported_dll->functions = NULL;
1428
1429
0
    head_fun = tail_fun = NULL;
1430
1431
0
    uint64_t name_rva = ImportNameTableRVA;
1432
0
    uint64_t func_rva = ImportAddressTableRVA;
1433
1434
0
    for (;num_function_imports < MAX_PE_IMPORTS;)
1435
0
    {
1436
0
      uint64_t nameAddress = pe_parse_delay_import_pointer(
1437
0
          pe, pointer_size, name_rva);
1438
1439
0
      uint64_t funcAddress = pe_parse_delay_import_pointer(
1440
0
          pe, pointer_size, func_rva);
1441
1442
      // Value of YR_UNDEFINED means that value is outside of pe->data
1443
0
      if (nameAddress == YR_UNDEFINED || funcAddress == YR_UNDEFINED)
1444
0
        break;
1445
1446
      // Value of zero means that this is the end of the bound import name table
1447
0
      if (nameAddress == 0 || funcAddress == 0)
1448
0
        break;
1449
1450
0
      char* func_name;
1451
0
      uint8_t has_ordinal = 0;
1452
1453
      // Check name address. It could be ordinal, VA or RVA
1454
0
      if (!(nameAddress & ordinal_mask))
1455
0
      {
1456
        // Convert name address to RVA, if needed
1457
0
        if (!Attributes)
1458
0
          nameAddress = pe_normalize_delay_import_value(
1459
0
              image_base, nameAddress);
1460
1461
0
        offset = pe_rva_to_offset(pe, nameAddress + sizeof(uint16_t));
1462
1463
0
        if (offset < 0)
1464
0
        {
1465
0
          name_rva += pointer_size;
1466
0
          func_rva += pointer_size;
1467
0
          continue;
1468
0
        }
1469
1470
0
        func_name = (char*) yr_strndup(
1471
0
            (char*) (pe->data + offset),
1472
0
            yr_min(available_space(pe, (char*) (pe->data + offset)), 512));
1473
0
      }
1474
0
      else
1475
0
      {
1476
        // If imported by ordinal. Lookup the ordinal.
1477
0
        func_name = ord_lookup(dll_name, nameAddress & 0xFFFF);
1478
0
        has_ordinal = 1;
1479
0
      }
1480
1481
0
      IMPORT_FUNCTION* imported_func = (IMPORT_FUNCTION*) yr_malloc(
1482
0
          sizeof(IMPORT_FUNCTION));
1483
1484
0
      if (imported_func == NULL)
1485
0
        break;
1486
1487
0
      imported_func->name = func_name;
1488
0
      imported_func->rva = func_rva;
1489
0
      imported_func->has_ordinal = has_ordinal;
1490
0
      imported_func->ordinal = (has_ordinal) ? nameAddress & 0xFFFF : 0;
1491
0
      imported_func->next = NULL;
1492
1493
0
      num_function_imports++;
1494
0
      name_rva += pointer_size;
1495
0
      func_rva += pointer_size;
1496
1497
0
      if (head_fun == NULL)
1498
0
        head_fun = imported_func;
1499
1500
0
      if (tail_fun != NULL)
1501
0
        tail_fun->next = imported_func;
1502
1503
0
      tail_fun = imported_func;
1504
0
    }
1505
1506
0
    num_imports++;
1507
1508
0
    imported_dll->functions = head_fun;
1509
1510
0
    if (head_dll == NULL)
1511
0
      head_dll = imported_dll;
1512
1513
0
    if (tail_dll != NULL)
1514
0
      tail_dll->next = imported_dll;
1515
1516
0
    tail_dll = imported_dll;
1517
0
  }
1518
1519
0
  yr_set_integer(num_imports, pe->object, "number_of_delayed_imports");
1520
0
  yr_set_integer(
1521
0
      num_function_imports, pe->object, "number_of_delayed_imported_functions");
1522
1523
0
  pe_set_imports(
1524
0
      pe,
1525
0
      head_dll,
1526
0
      "delayed_import_details[%i].library_name",
1527
0
      "delayed_import_details[%i].number_of_functions",
1528
0
      "delayed_import_details[%i].functions[%i].name",
1529
0
      "delayed_import_details[%i].functions[%i].ordinal",
1530
0
      "delayed_import_details[%i].functions[%i].rva");
1531
1532
0
  return head_dll;
1533
0
}
1534
1535
//
1536
// Walk the exports and collect relevant information. It is used in the
1537
// "exports" function for comparison.
1538
//
1539
1540
static void pe_parse_exports(PE* pe)
1541
0
{
1542
0
  PIMAGE_DATA_DIRECTORY directory;
1543
0
  PIMAGE_EXPORT_DIRECTORY exports;
1544
1545
0
  int64_t offset;
1546
0
  int64_t export_start;
1547
1548
0
  uint32_t i, j;
1549
0
  uint32_t number_of_exports;
1550
0
  uint32_t number_of_names;
1551
0
  uint32_t ordinal_base;
1552
1553
0
  size_t export_size;
1554
0
  size_t remaining;
1555
0
  size_t name_len;
1556
1557
0
  uint32_t exp_sz = 0;
1558
0
  DWORD* names = NULL;
1559
0
  WORD* ordinals = NULL;
1560
0
  DWORD* function_addrs = NULL;
1561
1562
  // If not a PE file, return YR_UNDEFINED
1563
1564
0
  if (pe == NULL)
1565
0
    return;
1566
1567
  // Default to 0 exports until we know there are any
1568
0
  yr_set_integer(0, pe->object, "number_of_exports");
1569
1570
0
  directory = pe_get_directory_entry(pe, IMAGE_DIRECTORY_ENTRY_EXPORT);
1571
1572
0
  if (directory == NULL)
1573
0
    return;
1574
1575
0
  if (yr_le32toh(directory->VirtualAddress) == 0)
1576
0
    return;
1577
1578
0
  offset = pe_rva_to_offset(pe, yr_le32toh(directory->VirtualAddress));
1579
1580
0
  if (offset < 0)
1581
0
    return;
1582
1583
0
  export_start = offset;
1584
0
  export_size = yr_le32toh(directory->Size);
1585
1586
0
  exports = (PIMAGE_EXPORT_DIRECTORY) (pe->data + offset);
1587
1588
0
  if (!struct_fits_in_pe(pe, exports, IMAGE_EXPORT_DIRECTORY))
1589
0
    return;
1590
1591
0
  number_of_exports = yr_min(
1592
0
      yr_le32toh(exports->NumberOfFunctions), MAX_PE_EXPORTS);
1593
1594
0
  ordinal_base = yr_le32toh(exports->Base);
1595
1596
0
  yr_set_integer(
1597
0
      yr_le32toh(exports->TimeDateStamp), pe->object, "export_timestamp");
1598
1599
0
  offset = pe_rva_to_offset(pe, yr_le32toh(exports->Name));
1600
1601
0
  if (offset > 0)
1602
0
  {
1603
0
    remaining = pe->data_size - (size_t) offset;
1604
0
    name_len = strnlen((char*) (pe->data + offset), remaining);
1605
0
    yr_set_sized_string(
1606
0
        (char*) (pe->data + offset), name_len, pe->object, "dll_name");
1607
0
  }
1608
1609
0
  if (number_of_exports * sizeof(DWORD) > pe->data_size - offset)
1610
0
    return;
1611
1612
0
  if (yr_le32toh(exports->NumberOfNames) > 0)
1613
0
  {
1614
0
    offset = pe_rva_to_offset(pe, yr_le32toh(exports->AddressOfNames));
1615
1616
0
    if (offset < 0)
1617
0
      return;
1618
1619
0
    if (yr_le32toh(exports->NumberOfNames) >
1620
0
        (pe->data_size - offset) / sizeof(DWORD))
1621
0
      return;
1622
1623
0
    names = (DWORD*) (pe->data + offset);
1624
0
  }
1625
1626
0
  offset = pe_rva_to_offset(pe, yr_le32toh(exports->AddressOfNameOrdinals));
1627
1628
0
  if (offset < 0)
1629
0
    return;
1630
1631
0
  ordinals = (WORD*) (pe->data + offset);
1632
1633
0
  if (available_space(pe, ordinals) < sizeof(WORD) * number_of_exports)
1634
0
    return;
1635
1636
0
  offset = pe_rva_to_offset(pe, yr_le32toh(exports->AddressOfFunctions));
1637
1638
0
  if (offset < 0)
1639
0
    return;
1640
1641
0
  function_addrs = (DWORD*) (pe->data + offset);
1642
1643
0
  if (available_space(pe, function_addrs) < sizeof(DWORD) * number_of_exports)
1644
0
    return;
1645
1646
0
  number_of_names = yr_min(
1647
0
      yr_le32toh(exports->NumberOfNames), number_of_exports);
1648
1649
  // Mapping out the exports is a bit janky. We start with the export address
1650
  // array. The index from that array plus the ordinal base is the ordinal for
1651
  // that export. To find the name we walk the ordinal array looking for a value
1652
  // that matches our index. If one exists we look up the corresponding RVA from
1653
  // the names array and follow it to get the name. If one does not exist then
1654
  // the export has no name.
1655
  //
1656
  // Ordinal base: 5
1657
  //                       0            1            2
1658
  // Address array: [ 0x00000011 | 0x00000022 | 0x00000033 ]
1659
  //                     0        1        2
1660
  // Ordinal array: [ 0x0000 | 0x0002 | 0x0001 ]
1661
  //                       0            1
1662
  // Names array:   [ 0x00000044 | 0x00000055 ]
1663
  //
1664
  // The function at RVA 0x00000011 (index 0) has ordinal 5 (base + index). The
1665
  // index can be found in position 0 in the ordinal array. Using 0 to index
1666
  // into the name array gives us an RVA (0x00000044) which we can follow to get
1667
  // the name.
1668
  //
1669
  // The function at RVA 0x00000022 (index 1) has ordinal 6 (base + index). The
1670
  // index can be found in position 2 in the ordinal array. 2 is out of bounds
1671
  // for the names array so this function is exported without a name.
1672
  //
1673
  // The function at RVA 0x00000033 (index 2) has ordinal 7 (base + index). The
1674
  // index can be found in position 1 in the ordinal array. Using 1 to index
1675
  // into the name array gives us an RVA (0x00000055) which we can follow to get
1676
  // the name.
1677
  //
1678
  // If the RVA from the address array is within the export directory it is a
1679
  // forwarder RVA and points to a NULL terminated ASCII string.
1680
1681
0
  for (i = 0; i < number_of_exports; i++)
1682
0
  {
1683
0
    yr_set_integer(
1684
0
        ordinal_base + i, pe->object, "export_details[%i].ordinal", exp_sz);
1685
1686
0
    yr_set_integer(
1687
0
        yr_le32toh(function_addrs[i]),
1688
0
        pe->object,
1689
0
        "export_details[%i].rva",
1690
0
        exp_sz);
1691
1692
    // Don't check for a failure here since some packers make this an invalid
1693
    // value.
1694
0
    offset = pe_rva_to_offset(pe, yr_le32toh(function_addrs[i]));
1695
1696
0
    if (offset > export_start && offset < export_start + export_size)
1697
0
    {
1698
0
      remaining = pe->data_size - (size_t) offset;
1699
0
      name_len = strnlen((char*) (pe->data + offset), remaining);
1700
1701
0
      yr_set_sized_string(
1702
0
          (char*) (pe->data + offset),
1703
0
          yr_min(name_len, MAX_EXPORT_NAME_LENGTH),
1704
0
          pe->object,
1705
0
          "export_details[%i].forward_name",
1706
0
          exp_sz);
1707
0
    }
1708
0
    else
1709
0
    {
1710
0
      if (offset < 0)
1711
0
        offset = YR_UNDEFINED;
1712
0
      yr_set_integer(offset, pe->object, "export_details[%i].offset", exp_sz);
1713
0
    }
1714
1715
0
    if (names != NULL)
1716
0
    {
1717
0
      for (j = 0; j < number_of_exports; j++)
1718
0
      {
1719
0
        if (yr_le16toh(ordinals[j]) == i && j < number_of_names)
1720
0
        {
1721
0
          offset = pe_rva_to_offset(pe, yr_le32toh(names[j]));
1722
1723
0
          if (offset > 0)
1724
0
          {
1725
0
            remaining = pe->data_size - (size_t) offset;
1726
0
            name_len = strnlen((char*) (pe->data + offset), remaining);
1727
1728
0
            yr_set_sized_string(
1729
0
                (char*) (pe->data + offset),
1730
0
                yr_min(name_len, MAX_EXPORT_NAME_LENGTH),
1731
0
                pe->object,
1732
0
                "export_details[%i].name",
1733
0
                exp_sz);
1734
0
          }
1735
0
          break;
1736
0
        }
1737
0
      }
1738
0
    }
1739
0
    exp_sz++;
1740
0
  }
1741
1742
0
  yr_set_integer(exp_sz, pe->object, "number_of_exports");
1743
0
}
1744
1745
// BoringSSL (https://boringssl.googlesource.com/boringssl/) doesn't support
1746
// some features used in pe_parse_certificates, if you are using BoringSSL
1747
// instead of OpenSSL you should define BORINGSSL for YARA to compile properly,
1748
// but you won't have signature-related features in the PE module.
1749
#if defined(HAVE_LIBCRYPTO) && !defined(BORINGSSL)
1750
1751
#define write_certificate(cert, pe, fmt, ...)                                  \
1752
  do                                                                           \
1753
  {                                                                            \
1754
    char thumbprint_ascii[YR_SHA1_LEN * 2 + 1];                                \
1755
    for (int j = 0; j < cert->sha1.len; ++j)                                   \
1756
      sprintf(thumbprint_ascii + (j * 2), "%02x", cert->sha1.data[j]);         \
1757
    thumbprint_ascii[cert->sha1.len * 2] = '\0';                               \
1758
                                                                               \
1759
    yr_set_string(                                                             \
1760
        (char*) thumbprint_ascii, pe->object, fmt ".thumbprint", __VA_ARGS__); \
1761
                                                                               \
1762
    yr_set_string(cert->issuer, pe->object, fmt ".issuer", __VA_ARGS__);       \
1763
    yr_set_string(cert->subject, pe->object, fmt ".subject", __VA_ARGS__);     \
1764
    /* Versions are zero based, so add one.  */                                \
1765
    yr_set_integer(                                                            \
1766
        cert->version + 1, pe->object, fmt ".version", __VA_ARGS__);           \
1767
    yr_set_string(cert->sig_alg, pe->object, fmt ".algorithm", __VA_ARGS__);   \
1768
    yr_set_string(                                                             \
1769
        cert->sig_alg_oid, pe->object, fmt ".algorithm_oid", __VA_ARGS__);     \
1770
    yr_set_string(cert->serial, pe->object, fmt ".serial", __VA_ARGS__);       \
1771
    yr_set_integer(                                                            \
1772
        cert->not_before, pe->object, fmt ".not_before", __VA_ARGS__);         \
1773
    yr_set_integer(                                                            \
1774
        cert->not_after, pe->object, fmt ".not_after", __VA_ARGS__);           \
1775
  } while (0)
1776
1777
void _process_authenticode(
1778
    PE* pe,
1779
    AuthenticodeArray* auth_array,
1780
    int* sig_count)
1781
{
1782
  if (!auth_array || !auth_array->count)
1783
    return;
1784
1785
  bool signature_valid = false;
1786
1787
  for (size_t i = 0; i < auth_array->count; ++i)
1788
  {
1789
    const Authenticode* authenticode = auth_array->signatures[i];
1790
1791
    if (authenticode->verify_flags == AUTHENTICODE_VFY_CANT_PARSE)
1792
      continue;
1793
1794
    if (authenticode->verify_flags == AUTHENTICODE_VFY_WRONG_PKCS7_TYPE)
1795
      continue;
1796
1797
    if (authenticode->verify_flags == AUTHENTICODE_VFY_NO_SIGNER_INFO)
1798
      continue;
1799
1800
    if (authenticode->verify_flags == AUTHENTICODE_VFY_NO_SIGNER_CERT)
1801
      continue;
1802
1803
    if (authenticode->verify_flags == AUTHENTICODE_VFY_INTERNAL_ERROR)
1804
      continue;
1805
1806
    bool verified = authenticode->verify_flags == AUTHENTICODE_VFY_VALID;
1807
1808
    /* If any signature is valid -> file is correctly signed */
1809
    signature_valid |= verified;
1810
1811
    yr_set_integer(verified, pe->object, "signatures[%i].verified", *sig_count);
1812
1813
    yr_set_string(
1814
        authenticode->digest_alg,
1815
        pe->object,
1816
        "signatures[%i].digest_alg",
1817
        *sig_count);
1818
1819
    if (authenticode->digest.data)
1820
    {
1821
      char* digest_ascii = yr_malloc(authenticode->digest.len * 2 + 1);
1822
      for (int j = 0; j < authenticode->digest.len; ++j)
1823
        sprintf(digest_ascii + (j * 2), "%02x", authenticode->digest.data[j]);
1824
      digest_ascii[authenticode->digest.len * 2] = '\0';
1825
1826
      yr_set_string(
1827
          digest_ascii, pe->object, "signatures[%i].digest", *sig_count);
1828
      yr_free(digest_ascii);
1829
    }
1830
1831
    if (authenticode->file_digest.data)
1832
    {
1833
      char* digest_ascii = yr_malloc(authenticode->file_digest.len * 2 + 1);
1834
      for (int j = 0; j < authenticode->file_digest.len; ++j)
1835
        sprintf(
1836
            digest_ascii + (j * 2), "%02x", authenticode->file_digest.data[j]);
1837
      digest_ascii[authenticode->file_digest.len * 2] = '\0';
1838
1839
      yr_set_string(
1840
          digest_ascii, pe->object, "signatures[%i].file_digest", *sig_count);
1841
      yr_free(digest_ascii);
1842
    }
1843
1844
    yr_set_integer(
1845
        authenticode->certs ? authenticode->certs->count : 0,
1846
        pe->object,
1847
        "signatures[%i].number_of_certificates",
1848
        *sig_count);
1849
1850
    if (authenticode->certs)
1851
    {
1852
      for (int k = 0; k < authenticode->certs->count; ++k)
1853
      {
1854
        write_certificate(
1855
            authenticode->certs->certs[k],
1856
            pe,
1857
            "signatures[%i].certificates[%i]",
1858
            *sig_count,
1859
            k);
1860
      }
1861
    }
1862
1863
    const Signer* signer = authenticode->signer;
1864
    if (signer)
1865
    {
1866
      /* For compatibility with previous YARA rules, write information
1867
       * about signing certificate in the same way */
1868
      if (signer->chain && signer->chain->count >= 1)
1869
      {
1870
        const Certificate* sign_cert = signer->chain->certs[0];
1871
        write_certificate(sign_cert, pe, "signatures[%i]", *sig_count);
1872
      }
1873
1874
      yr_set_string(
1875
          signer->program_name,
1876
          pe->object,
1877
          "signatures[%i].signer_info.program_name",
1878
          *sig_count);
1879
      yr_set_string(
1880
          signer->digest_alg,
1881
          pe->object,
1882
          "signatures[%i].signer_info.digest_alg",
1883
          *sig_count);
1884
1885
      if (signer->digest.data)
1886
      {
1887
        char* digest_ascii = yr_malloc(signer->digest.len * 2 + 1);
1888
        for (int j = 0; j < signer->digest.len; ++j)
1889
          sprintf(digest_ascii + (j * 2), "%02x", signer->digest.data[j]);
1890
        digest_ascii[signer->digest.len * 2] = '\0';
1891
1892
        yr_set_string(
1893
            digest_ascii,
1894
            pe->object,
1895
            "signatures[%i].signer_info.digest",
1896
            *sig_count);
1897
        yr_free(digest_ascii);
1898
      }
1899
1900
      yr_set_integer(
1901
          signer->chain ? signer->chain->count : 0,
1902
          pe->object,
1903
          "signatures[%i].signer_info.length_of_chain",
1904
          *sig_count);
1905
1906
      if (signer->chain)
1907
      {
1908
        for (int k = 0; k < signer->chain->count; ++k)
1909
        {
1910
          write_certificate(
1911
              signer->chain->certs[k],
1912
              pe,
1913
              "signatures[%i].signer_info.chain[%i]",
1914
              *sig_count,
1915
              k);
1916
        }
1917
      }
1918
    }
1919
1920
    yr_set_integer(
1921
        authenticode->countersigs ? authenticode->countersigs->count : 0,
1922
        pe->object,
1923
        "signatures[%i].number_of_countersignatures",
1924
        *sig_count);
1925
1926
    if (authenticode->countersigs)
1927
    {
1928
      for (int j = 0; j < authenticode->countersigs->count; ++j)
1929
      {
1930
        const Countersignature* counter =
1931
            authenticode->countersigs->counters[j];
1932
1933
        yr_set_integer(
1934
            counter->verify_flags == COUNTERSIGNATURE_VFY_VALID,
1935
            pe->object,
1936
            "signatures[%i].countersignatures[%i].verified",
1937
            *sig_count,
1938
            j);
1939
        yr_set_string(
1940
            counter->digest_alg,
1941
            pe->object,
1942
            "signatures[%i].countersignatures[%i].digest_alg",
1943
            *sig_count,
1944
            j);
1945
        yr_set_integer(
1946
            counter->sign_time,
1947
            pe->object,
1948
            "signatures[%i].countersignatures[%i].sign_time",
1949
            *sig_count,
1950
            j);
1951
1952
        if (counter->digest.data)
1953
        {
1954
          char* digest_ascii = yr_malloc(counter->digest.len * 2 + 1);
1955
          for (int j = 0; j < counter->digest.len; ++j)
1956
            sprintf(digest_ascii + (j * 2), "%02x", counter->digest.data[j]);
1957
          digest_ascii[counter->digest.len * 2] = '\0';
1958
1959
          yr_set_string(
1960
              digest_ascii,
1961
              pe->object,
1962
              "signatures[%i].countersignatures[%i].digest",
1963
              *sig_count,
1964
              j);
1965
          yr_free(digest_ascii);
1966
        }
1967
1968
        yr_set_integer(
1969
            counter->chain ? counter->chain->count : 0,
1970
            pe->object,
1971
            "signatures[%i].countersignatures[%i].length_of_chain",
1972
            *sig_count,
1973
            j);
1974
1975
        if (counter->chain)
1976
        {
1977
          for (int k = 0; k < counter->chain->count; ++k)
1978
          {
1979
            write_certificate(
1980
                counter->chain->certs[k],
1981
                pe,
1982
                "signatures[%i].countersignatures[%i].chain[%i]",
1983
                *sig_count,
1984
                j,
1985
                k);
1986
          }
1987
        }
1988
      }
1989
    }
1990
1991
    (*sig_count)++;
1992
  }
1993
1994
  yr_set_integer(signature_valid, pe->object, "is_signed");
1995
}
1996
1997
static void pe_parse_certificates(PE* pe)
1998
{
1999
  int counter = 0;
2000
2001
  // Default to 0 signatures until we know otherwise.
2002
  yr_set_integer(0, pe->object, "number_of_signatures");
2003
  // Default to not signed until we know otherwise.
2004
  yr_set_integer(0, pe->object, "is_signed");
2005
2006
  PIMAGE_DATA_DIRECTORY directory = pe_get_directory_entry(
2007
      pe, IMAGE_DIRECTORY_ENTRY_SECURITY);
2008
2009
  if (directory == NULL)
2010
    return;
2011
2012
  // directory->VirtualAddress is a file offset. Don't call pe_rva_to_offset().
2013
  if (yr_le32toh(directory->VirtualAddress) == 0 ||
2014
      yr_le32toh(directory->VirtualAddress) > pe->data_size ||
2015
      yr_le32toh(directory->Size) > pe->data_size ||
2016
      yr_le32toh(directory->VirtualAddress) + yr_le32toh(directory->Size) >
2017
          pe->data_size)
2018
  {
2019
    return;
2020
  }
2021
2022
  AuthenticodeArray* auth_array = parse_authenticode(pe->data, pe->data_size);
2023
  _process_authenticode(pe, auth_array, &counter);
2024
  authenticode_array_free(auth_array);
2025
2026
  yr_set_integer(counter, pe->object, "number_of_signatures");
2027
}
2028
2029
#endif  // defined(HAVE_LIBCRYPTO)
2030
2031
const char* pe_get_section_full_name(
2032
    PE* pe,
2033
    const char* section_name,
2034
    uint64_t section_name_length,
2035
    uint64_t* section_full_name_length)
2036
0
{
2037
  // section_name is an 8-byte, null-padded UTF-8 encoded string. If the string
2038
  // is exactly 8 characters long, there is no terminating null. For longer
2039
  // names, this field contains a slash (/) that is followed by an ASCII
2040
  // representation of a decimal number that is an offset into the string table.
2041
2042
  // Sample: 2e9c671b8a0411f2b397544b368c44d7f095eb395779de0ad1ac946914dfa34c
2043
2044
  // Check if any param is NULL
2045
0
  if (pe == NULL || section_name == NULL || section_full_name_length == NULL)
2046
0
    return NULL;
2047
2048
  // Set length to zero
2049
0
  *section_full_name_length = 0;
2050
2051
  // Offset and number of records in coff table
2052
0
  uint64_t coff_offset = yr_le32toh(
2053
0
      pe->header->FileHeader.PointerToSymbolTable);
2054
0
  uint64_t coff_number = yr_le32toh(pe->header->FileHeader.NumberOfSymbols);
2055
2056
  // If section name start with '/' and file contain coff table then section
2057
  // name is stored in string table
2058
0
  if (coff_offset == 0 || section_name[0] != '/')
2059
0
  {
2060
0
    *section_full_name_length = section_name_length;
2061
0
    return section_name;
2062
0
  }
2063
2064
  // Calculate offset of string table (String table is immediately after coff
2065
  // table)
2066
0
  uint64_t string_offset = coff_offset + coff_number * sizeof(IMAGE_SYMBOL);
2067
0
  uint64_t string_index = 0;
2068
2069
  // Calculate string index/offset in string table
2070
0
  for (int i = 1;
2071
0
       i < IMAGE_SIZEOF_SHORT_NAME && isdigit((unsigned char) section_name[i]);
2072
0
       i++)
2073
0
    string_index = (string_index * 10) + (section_name[i] - '0');
2074
2075
  // Calculate string pointer
2076
0
  const char* string = (char*) (pe->data + string_offset + string_index);
2077
2078
  // Check string
2079
0
  for (uint64_t len = 0; fits_in_pe(pe, string, len + 1); len++)
2080
0
  {
2081
    // Prevent sign extension to 32-bits on bytes > 0x7F
2082
    // The result negative integer would cause assert in MSVC debug version of
2083
    // isprint()
2084
0
    unsigned int one_char = (unsigned char) (string[len]);
2085
2086
    // Valid string
2087
0
    if (one_char == 0)
2088
0
    {
2089
0
      *section_full_name_length = len;
2090
0
      return string;
2091
0
    }
2092
2093
    // string contain unprintable character
2094
0
    if (!isprint(one_char))
2095
0
      return NULL;
2096
0
  }
2097
2098
  // String do not fit into pe file
2099
0
  return NULL;
2100
0
}
2101
2102
static void pe_parse_header(PE* pe, uint64_t base_address, int flags)
2103
0
{
2104
0
  PIMAGE_SECTION_HEADER section;
2105
0
  PIMAGE_DATA_DIRECTORY data_dir;
2106
2107
0
  char section_name[IMAGE_SIZEOF_SHORT_NAME + 1];
2108
0
  int sect_name_length;
2109
2110
0
  uint16_t scount;
2111
0
  uint32_t ddcount;
2112
2113
0
  uint64_t highest_sec_siz = 0;
2114
0
  uint64_t highest_sec_ofs = 0;
2115
0
  uint64_t section_end;
2116
0
  uint64_t last_section_end;
2117
2118
0
  yr_set_integer(1, pe->object, "is_pe");
2119
2120
0
  yr_set_integer(
2121
0
      yr_le16toh(pe->header->FileHeader.Machine), pe->object, "machine");
2122
2123
0
  yr_set_integer(
2124
0
      yr_le16toh(pe->header->FileHeader.NumberOfSections),
2125
0
      pe->object,
2126
0
      "number_of_sections");
2127
2128
0
  yr_set_integer(
2129
0
      yr_le32toh(pe->header->FileHeader.TimeDateStamp),
2130
0
      pe->object,
2131
0
      "timestamp");
2132
2133
0
  yr_set_integer(
2134
0
      yr_le32toh(pe->header->FileHeader.PointerToSymbolTable),
2135
0
      pe->object,
2136
0
      "pointer_to_symbol_table");
2137
2138
0
  yr_set_integer(
2139
0
      yr_le32toh(pe->header->FileHeader.NumberOfSymbols),
2140
0
      pe->object,
2141
0
      "number_of_symbols");
2142
2143
0
  yr_set_integer(
2144
0
      yr_le16toh(pe->header->FileHeader.SizeOfOptionalHeader),
2145
0
      pe->object,
2146
0
      "size_of_optional_header");
2147
2148
0
  yr_set_integer(
2149
0
      yr_le16toh(pe->header->FileHeader.Characteristics),
2150
0
      pe->object,
2151
0
      "characteristics");
2152
2153
0
  yr_set_integer(
2154
0
      flags & SCAN_FLAGS_PROCESS_MEMORY
2155
0
          ? base_address + yr_le32toh(OptionalHeader(pe, AddressOfEntryPoint))
2156
0
          : pe_rva_to_offset(
2157
0
                pe, yr_le32toh(OptionalHeader(pe, AddressOfEntryPoint))),
2158
0
      pe->object,
2159
0
      "entry_point");
2160
2161
0
  yr_set_integer(
2162
0
      yr_le32toh(OptionalHeader(pe, AddressOfEntryPoint)),
2163
0
      pe->object,
2164
0
      "entry_point_raw");
2165
2166
0
  yr_set_integer(
2167
0
      IS_64BITS_PE(pe) ? yr_le64toh(OptionalHeader(pe, ImageBase))
2168
0
                       : yr_le32toh(OptionalHeader(pe, ImageBase)),
2169
0
      pe->object,
2170
0
      "image_base");
2171
2172
0
  yr_set_integer(
2173
0
      yr_le32toh(OptionalHeader(pe, NumberOfRvaAndSizes)),
2174
0
      pe->object,
2175
0
      "number_of_rva_and_sizes");
2176
2177
0
  yr_set_integer(
2178
0
      yr_le16toh(OptionalHeader(pe, Magic)), pe->object, "opthdr_magic");
2179
2180
0
  yr_set_integer(
2181
0
      OptionalHeader(pe, MajorLinkerVersion),
2182
0
      pe->object,
2183
0
      "linker_version.major");
2184
2185
0
  yr_set_integer(
2186
0
      OptionalHeader(pe, MinorLinkerVersion),
2187
0
      pe->object,
2188
0
      "linker_version.minor");
2189
2190
0
  yr_set_integer(
2191
0
      yr_le32toh(OptionalHeader(pe, SizeOfCode)), pe->object, "size_of_code");
2192
2193
0
  yr_set_integer(
2194
0
      yr_le32toh(OptionalHeader(pe, SizeOfInitializedData)),
2195
0
      pe->object,
2196
0
      "size_of_initialized_data");
2197
2198
0
  yr_set_integer(
2199
0
      yr_le32toh(OptionalHeader(pe, SizeOfUninitializedData)),
2200
0
      pe->object,
2201
0
      "size_of_uninitialized_data");
2202
2203
0
  yr_set_integer(
2204
0
      yr_le32toh(OptionalHeader(pe, BaseOfCode)), pe->object, "base_of_code");
2205
2206
0
  if (!IS_64BITS_PE(pe))
2207
0
  {
2208
0
    yr_set_integer(
2209
0
        yr_le32toh(pe->header->OptionalHeader.BaseOfData),
2210
0
        pe->object,
2211
0
        "base_of_data");
2212
0
  }
2213
2214
0
  yr_set_integer(
2215
0
      yr_le32toh(OptionalHeader(pe, SectionAlignment)),
2216
0
      pe->object,
2217
0
      "section_alignment");
2218
2219
0
  yr_set_integer(
2220
0
      yr_le32toh(OptionalHeader(pe, FileAlignment)),
2221
0
      pe->object,
2222
0
      "file_alignment");
2223
2224
0
  yr_set_integer(
2225
0
      yr_le16toh(OptionalHeader(pe, MajorOperatingSystemVersion)),
2226
0
      pe->object,
2227
0
      "os_version.major");
2228
2229
0
  yr_set_integer(
2230
0
      yr_le16toh(OptionalHeader(pe, MinorOperatingSystemVersion)),
2231
0
      pe->object,
2232
0
      "os_version.minor");
2233
2234
0
  yr_set_integer(
2235
0
      yr_le16toh(OptionalHeader(pe, MajorImageVersion)),
2236
0
      pe->object,
2237
0
      "image_version.major");
2238
2239
0
  yr_set_integer(
2240
0
      yr_le16toh(OptionalHeader(pe, MinorImageVersion)),
2241
0
      pe->object,
2242
0
      "image_version.minor");
2243
2244
0
  yr_set_integer(
2245
0
      yr_le16toh(OptionalHeader(pe, MajorSubsystemVersion)),
2246
0
      pe->object,
2247
0
      "subsystem_version.major");
2248
2249
0
  yr_set_integer(
2250
0
      yr_le16toh(OptionalHeader(pe, MinorSubsystemVersion)),
2251
0
      pe->object,
2252
0
      "subsystem_version.minor");
2253
2254
0
  yr_set_integer(
2255
0
      yr_le32toh(OptionalHeader(pe, Win32VersionValue)),
2256
0
      pe->object,
2257
0
      "win32_version_value");
2258
2259
0
  yr_set_integer(
2260
0
      yr_le32toh(OptionalHeader(pe, SizeOfImage)), pe->object, "size_of_image");
2261
2262
0
  yr_set_integer(
2263
0
      yr_le32toh(OptionalHeader(pe, SizeOfHeaders)),
2264
0
      pe->object,
2265
0
      "size_of_headers");
2266
2267
0
  yr_set_integer(
2268
0
      yr_le32toh(OptionalHeader(pe, CheckSum)), pe->object, "checksum");
2269
2270
0
  yr_set_integer(
2271
0
      yr_le16toh(OptionalHeader(pe, Subsystem)), pe->object, "subsystem");
2272
2273
0
  yr_set_integer(
2274
0
      yr_le16toh(OptionalHeader(pe, DllCharacteristics)),
2275
0
      pe->object,
2276
0
      "dll_characteristics");
2277
2278
0
  yr_set_integer(
2279
0
      IS_64BITS_PE(pe) ? yr_le64toh(OptionalHeader(pe, SizeOfStackReserve))
2280
0
                       : yr_le32toh(OptionalHeader(pe, SizeOfStackReserve)),
2281
0
      pe->object,
2282
0
      "size_of_stack_reserve");
2283
2284
0
  yr_set_integer(
2285
0
      IS_64BITS_PE(pe) ? yr_le64toh(OptionalHeader(pe, SizeOfStackCommit))
2286
0
                       : yr_le32toh(OptionalHeader(pe, SizeOfStackCommit)),
2287
0
      pe->object,
2288
0
      "size_of_stack_commit");
2289
2290
0
  yr_set_integer(
2291
0
      IS_64BITS_PE(pe) ? yr_le64toh(OptionalHeader(pe, SizeOfHeapReserve))
2292
0
                       : yr_le32toh(OptionalHeader(pe, SizeOfHeapReserve)),
2293
0
      pe->object,
2294
0
      "size_of_heap_reserve");
2295
2296
0
  yr_set_integer(
2297
0
      IS_64BITS_PE(pe) ? yr_le64toh(OptionalHeader(pe, SizeOfHeapCommit))
2298
0
                       : yr_le32toh(OptionalHeader(pe, SizeOfHeapCommit)),
2299
0
      pe->object,
2300
0
      "size_of_heap_commit");
2301
2302
0
  yr_set_integer(
2303
0
      yr_le32toh(OptionalHeader(pe, LoaderFlags)), pe->object, "loader_flags");
2304
2305
0
  data_dir = IS_64BITS_PE(pe) ? pe->header64->OptionalHeader.DataDirectory
2306
0
                              : pe->header->OptionalHeader.DataDirectory;
2307
2308
0
  ddcount = yr_le32toh(OptionalHeader(pe, NumberOfRvaAndSizes));
2309
0
  ddcount = yr_min(ddcount, IMAGE_NUMBEROF_DIRECTORY_ENTRIES);
2310
2311
0
  for (int i = 0; i < ddcount; i++)
2312
0
  {
2313
0
    if (!struct_fits_in_pe(pe, data_dir, IMAGE_DATA_DIRECTORY))
2314
0
      break;
2315
2316
0
    yr_set_integer(
2317
0
        yr_le32toh(data_dir->VirtualAddress),
2318
0
        pe->object,
2319
0
        "data_directories[%i].virtual_address",
2320
0
        i);
2321
2322
0
    yr_set_integer(
2323
0
        yr_le32toh(data_dir->Size), pe->object, "data_directories[%i].size", i);
2324
2325
0
    data_dir++;
2326
0
  }
2327
2328
0
  pe_iterate_resources(
2329
0
      pe, (RESOURCE_CALLBACK_FUNC) pe_collect_resources, (void*) pe);
2330
2331
0
  yr_set_integer(pe->resources, pe->object, "number_of_resources");
2332
0
  yr_set_integer(pe->version_infos, pe->object, "number_of_version_infos");
2333
2334
0
  section = IMAGE_FIRST_SECTION(pe->header);
2335
2336
0
  scount = yr_min(
2337
0
      yr_le16toh(pe->header->FileHeader.NumberOfSections), MAX_PE_SECTIONS);
2338
2339
0
  for (int i = 0; i < scount; i++)
2340
0
  {
2341
0
    if (!struct_fits_in_pe(pe, section, IMAGE_SECTION_HEADER))
2342
0
      break;
2343
2344
0
    memcpy(section_name, section->Name, IMAGE_SIZEOF_SHORT_NAME);
2345
0
    section_name[IMAGE_SIZEOF_SHORT_NAME] = '\0';
2346
2347
    // Basically do rstrip('\0'), find the rightmost non-null character.
2348
    // Samples like
2349
    // 0043812838495a45449a0ac61a81b9c16eddca1ad249fb4f7fdb1c4505e9bb34 contain
2350
    // sections with additional characters after the first null.
2351
0
    for (sect_name_length = IMAGE_SIZEOF_SHORT_NAME - 1; sect_name_length >= 0;
2352
0
         --sect_name_length)
2353
0
    {
2354
0
      if (section_name[sect_name_length] != '\0')
2355
0
        break;
2356
0
    }
2357
2358
0
    uint64_t sect_full_name_length = 0;
2359
0
    const char* full_section_name = pe_get_section_full_name(
2360
0
        pe, section_name, sect_name_length + 1, &sect_full_name_length);
2361
2362
0
    yr_set_sized_string(
2363
0
        (char*) section_name,
2364
0
        sect_name_length + 1,
2365
0
        pe->object,
2366
0
        "sections[%i].name",
2367
0
        i);
2368
2369
0
    yr_set_sized_string(
2370
0
        full_section_name,
2371
0
        sect_full_name_length,
2372
0
        pe->object,
2373
0
        "sections[%i].full_name",
2374
0
        i);
2375
2376
0
    yr_set_integer(
2377
0
        yr_le32toh(section->Characteristics),
2378
0
        pe->object,
2379
0
        "sections[%i].characteristics",
2380
0
        i);
2381
2382
0
    yr_set_integer(
2383
0
        yr_le32toh(section->SizeOfRawData),
2384
0
        pe->object,
2385
0
        "sections[%i].raw_data_size",
2386
0
        i);
2387
2388
0
    yr_set_integer(
2389
0
        yr_le32toh(section->PointerToRawData),
2390
0
        pe->object,
2391
0
        "sections[%i].raw_data_offset",
2392
0
        i);
2393
2394
0
    yr_set_integer(
2395
0
        yr_le32toh(section->VirtualAddress),
2396
0
        pe->object,
2397
0
        "sections[%i].virtual_address",
2398
0
        i);
2399
2400
0
    yr_set_integer(
2401
0
        yr_le32toh(section->Misc.VirtualSize),
2402
0
        pe->object,
2403
0
        "sections[%i].virtual_size",
2404
0
        i);
2405
2406
0
    yr_set_integer(
2407
0
        yr_le32toh(section->PointerToRelocations),
2408
0
        pe->object,
2409
0
        "sections[%i].pointer_to_relocations",
2410
0
        i);
2411
2412
0
    yr_set_integer(
2413
0
        yr_le32toh(section->PointerToLinenumbers),
2414
0
        pe->object,
2415
0
        "sections[%i].pointer_to_line_numbers",
2416
0
        i);
2417
2418
0
    yr_set_integer(
2419
0
        yr_le32toh(section->NumberOfRelocations),
2420
0
        pe->object,
2421
0
        "sections[%i].number_of_relocations",
2422
0
        i);
2423
2424
0
    yr_set_integer(
2425
0
        yr_le32toh(section->NumberOfLinenumbers),
2426
0
        pe->object,
2427
0
        "sections[%i].number_of_line_numbers",
2428
0
        i);
2429
2430
    // This will catch the section with the highest raw offset to help checking
2431
    // if overlay data is present. If two sections have the same raw pointer
2432
    // but different raw sizes the largest one is used. An example of this case
2433
    // is file: cf62bf1815a93e68e6c5189f689286b66c4088b9507cf3ecf835e4ac3f9ededa
2434
2435
0
    section_end = yr_le32toh(section->PointerToRawData) +
2436
0
                  yr_le32toh(section->SizeOfRawData);
2437
2438
0
    if (section_end > highest_sec_ofs + highest_sec_siz)
2439
0
    {
2440
0
      highest_sec_ofs = yr_le32toh(section->PointerToRawData);
2441
0
      highest_sec_siz = yr_le32toh(section->SizeOfRawData);
2442
0
    }
2443
2444
0
    section++;
2445
0
  }
2446
2447
  // An overlay is data appended to a PE file. Its location is at
2448
  // RawData + RawOffset of the last section on the physical file
2449
0
  last_section_end = highest_sec_siz + highest_sec_ofs;
2450
2451
  // For PE files that have overlaid data overlay.offset contains the offset
2452
  // within the file where the overlay starts and overlay.size contains the
2453
  // size. If the PE file doesn't have an overlay both fields are 0, if the
2454
  // file is not a PE file (or is a malformed PE) both fields are YR_UNDEFINED.
2455
0
  if (last_section_end && (pe->data_size > last_section_end))
2456
0
  {
2457
0
    yr_set_integer(last_section_end, pe->object, "overlay.offset");
2458
0
    yr_set_integer(
2459
0
        pe->data_size - last_section_end, pe->object, "overlay.size");
2460
0
  }
2461
0
  else
2462
0
  {
2463
0
    yr_set_integer(0, pe->object, "overlay.offset");
2464
0
    yr_set_integer(0, pe->object, "overlay.size");
2465
0
  }
2466
0
}
2467
2468
//
2469
// Given a posix timestamp argument, make sure not_before <= arg <= not_after
2470
//
2471
2472
define_function(valid_on)
2473
0
{
2474
0
  int64_t timestamp;
2475
0
  int64_t not_before;
2476
0
  int64_t not_after;
2477
2478
0
  if (yr_is_undefined(yr_parent(), "not_before") ||
2479
0
      yr_is_undefined(yr_parent(), "not_after"))
2480
0
  {
2481
0
    return_integer(YR_UNDEFINED);
2482
0
  }
2483
2484
0
  timestamp = integer_argument(1);
2485
2486
0
  not_before = yr_get_integer(yr_parent(), "not_before");
2487
0
  not_after = yr_get_integer(yr_parent(), "not_after");
2488
2489
0
  return_integer(timestamp >= not_before && timestamp <= not_after);
2490
0
}
2491
2492
define_function(section_index_addr)
2493
0
{
2494
0
  YR_OBJECT* module = yr_module();
2495
0
  YR_SCAN_CONTEXT* context = yr_scan_context();
2496
2497
0
  int64_t offset;
2498
0
  int64_t size;
2499
2500
0
  int64_t addr = integer_argument(1);
2501
0
  int64_t n = yr_get_integer(module, "number_of_sections");
2502
2503
0
  if (yr_is_undefined(module, "number_of_sections"))
2504
0
    return_integer(YR_UNDEFINED);
2505
2506
0
  for (int i = 0; i < yr_min(n, MAX_PE_SECTIONS); i++)
2507
0
  {
2508
0
    if (context->flags & SCAN_FLAGS_PROCESS_MEMORY)
2509
0
    {
2510
0
      offset = yr_get_integer(module, "sections[%i].virtual_address", i);
2511
0
      size = yr_get_integer(module, "sections[%i].virtual_size", i);
2512
0
    }
2513
0
    else
2514
0
    {
2515
0
      offset = yr_get_integer(module, "sections[%i].raw_data_offset", i);
2516
0
      size = yr_get_integer(module, "sections[%i].raw_data_size", i);
2517
0
    }
2518
2519
0
    if (addr >= offset && addr < offset + size)
2520
0
      return_integer(i);
2521
0
  }
2522
2523
0
  return_integer(YR_UNDEFINED);
2524
0
}
2525
2526
define_function(section_index_name)
2527
0
{
2528
0
  YR_OBJECT* module = yr_module();
2529
2530
0
  char* name = string_argument(1);
2531
2532
0
  int64_t n = yr_get_integer(module, "number_of_sections");
2533
2534
0
  if (yr_is_undefined(module, "number_of_sections"))
2535
0
    return_integer(YR_UNDEFINED);
2536
2537
0
  for (int i = 0; i < yr_min(n, MAX_PE_SECTIONS); i++)
2538
0
  {
2539
0
    SIZED_STRING* sect = yr_get_string(module, "sections[%i].name", i);
2540
2541
0
    if (sect != NULL && strcmp(name, sect->c_string) == 0)
2542
0
      return_integer(i);
2543
0
  }
2544
2545
0
  return_integer(YR_UNDEFINED);
2546
0
}
2547
2548
define_function(exports)
2549
0
{
2550
0
  SIZED_STRING* search_name = sized_string_argument(1);
2551
2552
0
  SIZED_STRING* function_name = NULL;
2553
0
  YR_OBJECT* module = yr_module();
2554
0
  PE* pe = (PE*) module->data;
2555
2556
  // If not a PE, return YR_UNDEFINED.
2557
0
  if (pe == NULL)
2558
0
    return_integer(YR_UNDEFINED);
2559
2560
  // If PE, but no exported functions, return false.
2561
0
  int n = (int) yr_get_integer(module, "number_of_exports");
2562
2563
0
  if (n == 0)
2564
0
    return_integer(0);
2565
2566
0
  for (int i = 0; i < n; i++)
2567
0
  {
2568
0
    function_name = yr_get_string(module, "export_details[%i].name", i);
2569
2570
0
    if (function_name == NULL)
2571
0
      continue;
2572
2573
0
    if (ss_icompare(function_name, search_name) == 0)
2574
0
      return_integer(1);
2575
0
  }
2576
2577
0
  return_integer(0);
2578
0
}
2579
2580
define_function(exports_regexp)
2581
0
{
2582
0
  RE* regex = regexp_argument(1);
2583
2584
0
  SIZED_STRING* function_name = NULL;
2585
0
  YR_OBJECT* module = yr_module();
2586
0
  PE* pe = (PE*) module->data;
2587
2588
  // If not a PE, return YR_UNDEFINED.
2589
0
  if (pe == NULL)
2590
0
    return_integer(YR_UNDEFINED);
2591
2592
  // If PE, but no exported functions, return false.
2593
0
  int n = (int) yr_get_integer(module, "number_of_exports");
2594
2595
0
  if (n == 0)
2596
0
    return_integer(0);
2597
2598
0
  for (int i = 0; i < n; i++)
2599
0
  {
2600
0
    function_name = yr_get_string(module, "export_details[%i].name", i);
2601
0
    if (function_name == NULL)
2602
0
      continue;
2603
2604
0
    if (yr_re_match(yr_scan_context(), regex, function_name->c_string) != -1)
2605
0
      return_integer(1);
2606
0
  }
2607
2608
0
  return_integer(0);
2609
0
}
2610
2611
define_function(exports_ordinal)
2612
0
{
2613
0
  int64_t ordinal = integer_argument(1);
2614
2615
0
  YR_OBJECT* module = yr_module();
2616
0
  PE* pe = (PE*) module->data;
2617
2618
  // If not a PE, return YR_UNDEFINED.
2619
0
  if (pe == NULL)
2620
0
    return_integer(YR_UNDEFINED);
2621
2622
  // If PE, but no exported functions, return false.
2623
0
  int n = (int) yr_get_integer(module, "number_of_exports");
2624
2625
0
  if (n == 0)
2626
0
    return_integer(0);
2627
2628
0
  if (ordinal == 0 || ordinal > n)
2629
0
    return_integer(0);
2630
2631
0
  for (int i = 0; i < n; i++)
2632
0
  {
2633
0
    int64_t exported_ordinal = yr_object_get_integer(
2634
0
        module, "export_details[%i].ordinal", i);
2635
2636
0
    if (exported_ordinal == ordinal)
2637
0
      return_integer(1);
2638
0
  }
2639
2640
0
  return_integer(0);
2641
0
}
2642
2643
define_function(exports_index_name)
2644
0
{
2645
0
  SIZED_STRING* search_name = sized_string_argument(1);
2646
2647
0
  SIZED_STRING* function_name = NULL;
2648
0
  YR_OBJECT* module = yr_module();
2649
0
  PE* pe = (PE*) module->data;
2650
2651
  // If not a PE, return YR_UNDEFINED.
2652
0
  if (pe == NULL)
2653
0
    return_integer(YR_UNDEFINED);
2654
2655
  // If PE, but no exported functions, return false.
2656
0
  int n = (int) yr_get_integer(module, "number_of_exports");
2657
2658
0
  if (n == 0)
2659
0
    return_integer(YR_UNDEFINED);
2660
2661
0
  for (int i = 0; i < n; i++)
2662
0
  {
2663
0
    function_name = yr_get_string(module, "export_details[%i].name", i);
2664
2665
0
    if (function_name == NULL)
2666
0
      continue;
2667
2668
0
    if (ss_icompare(function_name, search_name) == 0)
2669
0
      return_integer(i);
2670
0
  }
2671
2672
0
  return_integer(YR_UNDEFINED);
2673
0
}
2674
2675
define_function(exports_index_ordinal)
2676
0
{
2677
0
  int64_t ordinal = integer_argument(1);
2678
2679
0
  YR_OBJECT* module = yr_module();
2680
0
  PE* pe = (PE*) module->data;
2681
2682
  // If not a PE, return YR_UNDEFINED.
2683
0
  if (pe == NULL)
2684
0
    return_integer(YR_UNDEFINED);
2685
2686
  // If PE, but no exported functions, return false.
2687
0
  int n = (int) yr_get_integer(module, "number_of_exports");
2688
2689
0
  if (n == 0)
2690
0
    return_integer(YR_UNDEFINED);
2691
2692
0
  if (ordinal == 0 || ordinal > n)
2693
0
    return_integer(YR_UNDEFINED);
2694
2695
0
  for (int i = 0; i < n; i++)
2696
0
  {
2697
0
    int64_t exported_ordinal = yr_object_get_integer(
2698
0
        module, "export_details[%i].ordinal", i);
2699
2700
0
    if (exported_ordinal == ordinal)
2701
0
      return_integer(i);
2702
0
  }
2703
2704
0
  return_integer(YR_UNDEFINED);
2705
0
}
2706
2707
define_function(exports_index_regex)
2708
0
{
2709
0
  RE* regex = regexp_argument(1);
2710
2711
0
  SIZED_STRING* function_name = NULL;
2712
0
  YR_OBJECT* module = yr_module();
2713
0
  PE* pe = (PE*) module->data;
2714
2715
  // If not a PE, return YR_UNDEFINED.
2716
0
  if (pe == NULL)
2717
0
    return_integer(YR_UNDEFINED);
2718
2719
  // If PE, but no exported functions, return false.
2720
0
  int n = (int) yr_get_integer(module, "number_of_exports");
2721
2722
0
  if (n == 0)
2723
0
    return_integer(YR_UNDEFINED);
2724
2725
0
  for (int i = 0; i < n; i++)
2726
0
  {
2727
0
    function_name = yr_get_string(module, "export_details[%i].name", i);
2728
0
    if (function_name == NULL)
2729
0
      continue;
2730
2731
0
    if (yr_re_match(yr_scan_context(), regex, function_name->c_string) != -1)
2732
0
    {
2733
0
      return_integer(i);
2734
0
    }
2735
0
  }
2736
2737
0
  return_integer(YR_UNDEFINED);
2738
0
}
2739
2740
#if defined(HAVE_LIBCRYPTO) || defined(HAVE_WINCRYPT_H) || \
2741
    defined(HAVE_COMMONCRYPTO_COMMONCRYPTO_H)
2742
2743
//
2744
// Generate an import hash:
2745
// https://www.mandiant.com/blog/tracking-malware-import-hashing/
2746
// It is important to make duplicates of the strings as we don't want
2747
// to alter the contents of the parsed import structures.
2748
//
2749
2750
define_function(imphash)
2751
{
2752
  YR_OBJECT* module = yr_module();
2753
2754
  IMPORTED_DLL* dll;
2755
  yr_md5_ctx ctx;
2756
2757
  unsigned char digest[YR_MD5_LEN];
2758
  char* digest_ascii;
2759
2760
  size_t i;
2761
  bool first = true;
2762
2763
  PE* pe = (PE*) module->data;
2764
2765
  // If not a PE, return YR_UNDEFINED.
2766
2767
  if (!pe)
2768
    return_string(YR_UNDEFINED);
2769
2770
  // Lookup in cache first.
2771
  digest_ascii = (char*) yr_hash_table_lookup(pe->hash_table, "imphash", NULL);
2772
2773
  if (digest_ascii != NULL)
2774
    return_string(digest_ascii);
2775
2776
  if (!yr_md5_init(&ctx))
2777
    return_string(YR_UNDEFINED);
2778
2779
  dll = pe->imported_dlls;
2780
2781
  while (dll)
2782
  {
2783
    IMPORT_FUNCTION* func;
2784
2785
    size_t dll_name_len;
2786
    char* dll_name;
2787
2788
    // If extension is 'ocx', 'sys' or 'dll', chop it.
2789
2790
    char* ext = strrchr(dll->name, '.');
2791
2792
    if (ext &&
2793
        (strncasecmp(ext, ".ocx", 4) == 0 || strncasecmp(ext, ".sys", 4) == 0 ||
2794
         strncasecmp(ext, ".dll", 4) == 0))
2795
    {
2796
      dll_name_len = (ext - dll->name);
2797
    }
2798
    else
2799
    {
2800
      dll_name_len = strlen(dll->name);
2801
    }
2802
2803
    // Allocate a new string to hold the dll name.
2804
2805
    dll_name = (char*) yr_malloc(dll_name_len + 1);
2806
2807
    if (!dll_name)
2808
      return ERROR_INSUFFICIENT_MEMORY;
2809
2810
    strlcpy(dll_name, dll->name, dll_name_len + 1);
2811
2812
    func = dll->functions;
2813
2814
    while (func)
2815
    {
2816
      char* final_name;
2817
      size_t final_name_len = dll_name_len + strlen(func->name) + 1;
2818
2819
      if (!first)
2820
        final_name_len++;  // Additional byte to accommodate the extra comma
2821
2822
      final_name = (char*) yr_malloc(final_name_len + 1);
2823
2824
      if (final_name == NULL)
2825
        break;
2826
2827
      sprintf(final_name, first ? "%s.%s" : ",%s.%s", dll_name, func->name);
2828
2829
      // Lowercase the whole thing.
2830
2831
      for (i = 0; i < final_name_len; i++)
2832
        final_name[i] = tolower((unsigned char) final_name[i]);
2833
2834
      yr_md5_update(&ctx, final_name, final_name_len);
2835
2836
      yr_free(final_name);
2837
2838
      func = func->next;
2839
      first = false;
2840
    }
2841
2842
    yr_free(dll_name);
2843
2844
    dll = dll->next;
2845
  }
2846
2847
  yr_md5_final(digest, &ctx);
2848
2849
  digest_ascii = (char*) yr_malloc(YR_MD5_LEN * 2 + 1);
2850
2851
  if (digest_ascii == NULL)
2852
    return ERROR_INSUFFICIENT_MEMORY;
2853
2854
  // Transform the binary digest to ascii
2855
2856
  for (i = 0; i < YR_MD5_LEN; i++)
2857
  {
2858
    sprintf(digest_ascii + (i * 2), "%02x", digest[i]);
2859
  }
2860
2861
  digest_ascii[YR_MD5_LEN * 2] = '\0';
2862
2863
  yr_hash_table_add(pe->hash_table, "imphash", NULL, digest_ascii);
2864
2865
  return_string(digest_ascii);
2866
}
2867
2868
#endif  // defined(HAVE_LIBCRYPTO) || defined(HAVE_WINCRYPT_H)
2869
2870
int64_t pe_imports_dll(IMPORTED_DLL* dll, char* dll_name)
2871
0
{
2872
0
  if (dll == NULL)
2873
0
    return 0;
2874
2875
0
  int64_t result = 0;
2876
2877
0
  for (; dll != NULL; dll = dll->next)
2878
0
  {
2879
0
    if (strcasecmp(dll->name, dll_name) == 0)
2880
0
    {
2881
0
      IMPORT_FUNCTION* fun = dll->functions;
2882
0
      for (; fun != NULL; fun = fun->next)
2883
0
      {
2884
0
        result++;
2885
0
      }
2886
0
    }
2887
0
  }
2888
2889
0
  return result;
2890
0
}
2891
2892
int64_t pe_imports(IMPORTED_DLL* dll, char* dll_name, char* fun_name)
2893
0
{
2894
0
  if (dll == NULL)
2895
0
    return 0;
2896
2897
0
  for (; dll != NULL; dll = dll->next)
2898
0
  {
2899
0
    if (strcasecmp(dll->name, dll_name) == 0)
2900
0
    {
2901
0
      IMPORT_FUNCTION* fun = dll->functions;
2902
0
      for (; fun != NULL; fun = fun->next)
2903
0
      {
2904
0
        if (strcasecmp(fun->name, fun_name) == 0)
2905
0
          return 1;
2906
0
      }
2907
0
    }
2908
0
  }
2909
2910
0
  return 0;
2911
0
}
2912
2913
int64_t pe_imports_regexp(
2914
    YR_SCAN_CONTEXT* context,
2915
    IMPORTED_DLL* dll,
2916
    RE* dll_name,
2917
    RE* fun_name)
2918
0
{
2919
0
  if (dll == NULL)
2920
0
    return 0;
2921
2922
0
  int64_t result = 0;
2923
2924
0
  for (; dll != NULL; dll = dll->next)
2925
0
  {
2926
0
    if (yr_re_match(context, dll_name, dll->name) > 0)
2927
0
    {
2928
0
      IMPORT_FUNCTION* fun = dll->functions;
2929
0
      for (; fun != NULL; fun = fun->next)
2930
0
      {
2931
0
        if (yr_re_match(context, fun_name, fun->name) > 0)
2932
0
          result++;
2933
0
      }
2934
0
    }
2935
0
  }
2936
2937
0
  return result;
2938
0
}
2939
2940
int64_t pe_imports_ordinal(IMPORTED_DLL* dll, char* dll_name, uint64_t ordinal)
2941
0
{
2942
0
  if (dll == NULL)
2943
0
    return 0;
2944
2945
0
  for (; dll != NULL; dll = dll->next)
2946
0
  {
2947
0
    if (strcasecmp(dll->name, dll_name) == 0)
2948
0
    {
2949
0
      IMPORT_FUNCTION* fun = dll->functions;
2950
0
      for (; fun != NULL; fun = fun->next)
2951
0
      {
2952
0
        if (fun->has_ordinal && fun->ordinal == ordinal)
2953
0
          return 1;
2954
0
      }
2955
0
    }
2956
0
  }
2957
2958
0
  return 0;
2959
0
}
2960
2961
define_function(imports_standard)
2962
0
{
2963
0
  char* dll_name = string_argument(1);
2964
0
  char* function_name = string_argument(2);
2965
2966
0
  YR_OBJECT* module = yr_module();
2967
0
  PE* pe = (PE*) module->data;
2968
2969
0
  if (!pe)
2970
0
    return_integer(YR_UNDEFINED);
2971
2972
0
  return_integer(pe_imports(pe->imported_dlls, dll_name, function_name));
2973
0
}
2974
2975
define_function(imports)
2976
0
{
2977
0
  int64_t flags = integer_argument(1);
2978
0
  char* dll_name = string_argument(2);
2979
0
  char* function_name = string_argument(3);
2980
2981
0
  YR_OBJECT* module = yr_module();
2982
0
  PE* pe = (PE*) module->data;
2983
2984
0
  if (!pe)
2985
0
    return_integer(YR_UNDEFINED);
2986
2987
0
  if (flags & IMPORT_STANDARD &&
2988
0
      pe_imports(pe->imported_dlls, dll_name, function_name))
2989
0
  {
2990
0
    return_integer(1);
2991
0
  }
2992
2993
0
  if (flags & IMPORT_DELAYED &&
2994
0
      pe_imports(pe->delay_imported_dlls, dll_name, function_name))
2995
0
  {
2996
0
    return_integer(1);
2997
0
  }
2998
2999
0
  return_integer(0);
3000
0
}
3001
3002
define_function(imports_standard_ordinal)
3003
0
{
3004
0
  char* dll_name = string_argument(1);
3005
0
  int64_t ordinal = integer_argument(2);
3006
3007
0
  YR_OBJECT* module = yr_module();
3008
0
  PE* pe = (PE*) module->data;
3009
3010
0
  if (!pe)
3011
0
    return_integer(YR_UNDEFINED);
3012
3013
0
  return_integer(pe_imports_ordinal(pe->imported_dlls, dll_name, ordinal))
3014
0
}
3015
3016
define_function(imports_ordinal)
3017
0
{
3018
0
  int64_t flags = integer_argument(1);
3019
0
  char* dll_name = string_argument(2);
3020
0
  int64_t ordinal = integer_argument(3);
3021
3022
0
  YR_OBJECT* module = yr_module();
3023
0
  PE* pe = (PE*) module->data;
3024
3025
0
  if (!pe)
3026
0
    return_integer(YR_UNDEFINED);
3027
3028
0
  if (flags & IMPORT_STANDARD &&
3029
0
      pe_imports_ordinal(pe->imported_dlls, dll_name, ordinal))
3030
0
  {
3031
0
    return_integer(1);
3032
0
  }
3033
3034
0
  if (flags & IMPORT_DELAYED &&
3035
0
      pe_imports_ordinal(pe->delay_imported_dlls, dll_name, ordinal))
3036
0
  {
3037
0
    return_integer(1);
3038
0
  }
3039
3040
0
  return_integer(0);
3041
0
}
3042
3043
define_function(imports_standard_regex)
3044
0
{
3045
0
  RE* dll_name = regexp_argument(1);
3046
0
  RE* function_name = regexp_argument(2);
3047
3048
0
  YR_OBJECT* module = yr_module();
3049
0
  PE* pe = (PE*) module->data;
3050
3051
0
  if (!pe)
3052
0
    return_integer(YR_UNDEFINED);
3053
3054
0
  return_integer(pe_imports_regexp(
3055
0
      yr_scan_context(), pe->imported_dlls, dll_name, function_name))
3056
0
}
3057
3058
define_function(imports_regex)
3059
0
{
3060
0
  int64_t flags = integer_argument(1);
3061
0
  RE* dll_name = regexp_argument(2);
3062
0
  RE* function_name = regexp_argument(3);
3063
3064
0
  YR_OBJECT* module = yr_module();
3065
0
  PE* pe = (PE*) module->data;
3066
3067
0
  if (!pe)
3068
0
    return_integer(YR_UNDEFINED);
3069
3070
0
  int64_t result = 0;
3071
3072
0
  if (flags & IMPORT_STANDARD)
3073
0
    result += pe_imports_regexp(
3074
0
        yr_scan_context(), pe->imported_dlls, dll_name, function_name);
3075
3076
0
  if (flags & IMPORT_DELAYED)
3077
0
    result += pe_imports_regexp(
3078
0
        yr_scan_context(), pe->delay_imported_dlls, dll_name, function_name);
3079
3080
0
  return_integer(result);
3081
0
}
3082
3083
define_function(imports_standard_dll)
3084
0
{
3085
0
  char* dll_name = string_argument(1);
3086
3087
0
  YR_OBJECT* module = yr_module();
3088
0
  PE* pe = (PE*) module->data;
3089
3090
0
  if (!pe)
3091
0
    return_integer(YR_UNDEFINED);
3092
3093
0
  return_integer(pe_imports_dll(pe->imported_dlls, dll_name));
3094
0
}
3095
3096
define_function(imports_dll)
3097
0
{
3098
0
  int64_t flags = integer_argument(1);
3099
0
  char* dll_name = string_argument(2);
3100
3101
0
  YR_OBJECT* module = yr_module();
3102
0
  PE* pe = (PE*) module->data;
3103
3104
0
  if (!pe)
3105
0
    return_integer(YR_UNDEFINED);
3106
3107
0
  int64_t result = 0;
3108
3109
0
  if (flags & IMPORT_STANDARD)
3110
0
    result += pe_imports_dll(pe->imported_dlls, dll_name);
3111
3112
0
  if (flags & IMPORT_DELAYED)
3113
0
    result += pe_imports_dll(pe->delay_imported_dlls, dll_name);
3114
3115
0
  return_integer(result);
3116
0
}
3117
3118
define_function(import_rva)
3119
0
{
3120
0
  SIZED_STRING* in_dll_name = sized_string_argument(1);
3121
0
  SIZED_STRING* in_function_name = sized_string_argument(2);
3122
3123
0
  SIZED_STRING* dll_name;
3124
0
  SIZED_STRING* function_name;
3125
0
  YR_OBJECT* module = yr_module();
3126
0
  PE* pe = (PE*) module->data;
3127
3128
0
  if (!pe)
3129
0
    return_integer(YR_UNDEFINED);
3130
3131
0
  int64_t num_imports = yr_get_integer(pe->object, "number_of_imports");
3132
0
  if (IS_UNDEFINED(num_imports))
3133
0
    return_integer(YR_UNDEFINED);
3134
3135
0
  for (int i = 0; i < num_imports; i++)
3136
0
  {
3137
0
    dll_name = yr_get_string(module, "import_details[%i].library_name", i);
3138
0
    if (dll_name == NULL || IS_UNDEFINED(dll_name) ||
3139
0
        ss_icompare(in_dll_name, dll_name) != 0)
3140
0
      continue;
3141
3142
0
    int64_t num_functions = yr_get_integer(
3143
0
        module, "import_details[%i].number_of_functions", i);
3144
0
    if (IS_UNDEFINED(num_functions))
3145
0
      return_integer(YR_UNDEFINED);
3146
3147
0
    for (int j = 0; j < num_functions; j++)
3148
0
    {
3149
0
      function_name = yr_get_string(
3150
0
          module, "import_details[%i].functions[%i].name", i, j);
3151
0
      if (function_name == NULL || IS_UNDEFINED(function_name))
3152
0
        continue;
3153
3154
0
      if (ss_icompare(in_function_name, function_name) == 0)
3155
0
        return_integer(yr_get_integer(
3156
0
            module, "import_details[%i].functions[%i].rva", i, j));
3157
0
    }
3158
0
  }
3159
3160
0
  return_integer(YR_UNDEFINED);
3161
0
}
3162
3163
define_function(import_rva_ordinal)
3164
0
{
3165
0
  SIZED_STRING* in_dll_name = sized_string_argument(1);
3166
0
  int64_t in_ordinal = integer_argument(2);
3167
3168
0
  SIZED_STRING* dll_name;
3169
0
  int64_t ordinal;
3170
0
  YR_OBJECT* module = yr_module();
3171
0
  PE* pe = (PE*) module->data;
3172
3173
0
  if (!pe)
3174
0
    return_integer(YR_UNDEFINED);
3175
3176
0
  int64_t num_imports = yr_get_integer(pe->object, "number_of_imports");
3177
0
  if (IS_UNDEFINED(num_imports))
3178
0
    return_integer(YR_UNDEFINED);
3179
3180
0
  for (int i = 0; i < num_imports; i++)
3181
0
  {
3182
0
    dll_name = yr_get_string(module, "import_details[%i].library_name", i);
3183
0
    if (dll_name == NULL || IS_UNDEFINED(dll_name) ||
3184
0
        ss_icompare(in_dll_name, dll_name) != 0)
3185
0
      continue;
3186
3187
0
    int64_t num_functions = yr_get_integer(
3188
0
        module, "import_details[%i].number_of_functions", i);
3189
0
    if (IS_UNDEFINED(num_functions))
3190
0
      return_integer(YR_UNDEFINED);
3191
3192
0
    for (int j = 0; j < num_functions; j++)
3193
0
    {
3194
0
      ordinal = yr_get_integer(
3195
0
          module, "import_details[%i].functions[%i].ordinal", i, j);
3196
0
      if (IS_UNDEFINED(ordinal))
3197
0
        continue;
3198
3199
0
      if (ordinal == in_ordinal)
3200
0
        return_integer(yr_get_integer(
3201
0
            module, "import_details[%i].functions[%i].rva", i, j));
3202
0
    }
3203
0
  }
3204
3205
0
  return_integer(YR_UNDEFINED);
3206
0
}
3207
3208
define_function(delayed_import_rva)
3209
0
{
3210
0
  SIZED_STRING* in_dll_name = sized_string_argument(1);
3211
0
  SIZED_STRING* in_function_name = sized_string_argument(2);
3212
3213
0
  SIZED_STRING* dll_name;
3214
0
  SIZED_STRING* function_name;
3215
0
  YR_OBJECT* module = yr_module();
3216
0
  PE* pe = (PE*) module->data;
3217
3218
0
  if (!pe)
3219
0
    return_integer(YR_UNDEFINED);
3220
3221
0
  int64_t num_imports = yr_get_integer(pe->object, "number_of_delayed_imports");
3222
3223
0
  if (IS_UNDEFINED(num_imports))
3224
0
    return_integer(YR_UNDEFINED);
3225
3226
0
  for (int i = 0; i < num_imports; i++)
3227
0
  {
3228
0
    dll_name = yr_get_string(
3229
0
        module, "delayed_import_details[%i].library_name", i);
3230
3231
0
    if (dll_name == NULL || IS_UNDEFINED(dll_name) ||
3232
0
        ss_icompare(in_dll_name, dll_name) != 0)
3233
0
      continue;
3234
3235
0
    int64_t num_functions = yr_get_integer(
3236
0
        module, "delayed_import_details[%i].number_of_functions", i);
3237
3238
0
    if (IS_UNDEFINED(num_functions))
3239
0
      return_integer(YR_UNDEFINED);
3240
3241
0
    for (int j = 0; j < num_functions; j++)
3242
0
    {
3243
0
      function_name = yr_get_string(
3244
0
          module, "delayed_import_details[%i].functions[%i].name", i, j);
3245
3246
0
      if (function_name == NULL || IS_UNDEFINED(function_name))
3247
0
        continue;
3248
3249
0
      if (ss_icompare(in_function_name, function_name) == 0)
3250
0
        return_integer(yr_get_integer(
3251
0
            module, "delayed_import_details[%i].functions[%i].rva", i, j));
3252
0
    }
3253
0
  }
3254
3255
0
  return_integer(YR_UNDEFINED);
3256
0
}
3257
3258
define_function(delayed_import_rva_ordinal)
3259
0
{
3260
0
  SIZED_STRING* in_dll_name = sized_string_argument(1);
3261
0
  int64_t in_ordinal = integer_argument(2);
3262
3263
0
  SIZED_STRING* dll_name;
3264
0
  int64_t ordinal;
3265
0
  YR_OBJECT* module = yr_module();
3266
0
  PE* pe = (PE*) module->data;
3267
3268
0
  if (!pe)
3269
0
    return_integer(YR_UNDEFINED);
3270
3271
0
  int64_t num_imports = yr_get_integer(pe->object, "number_of_delayed_imports");
3272
0
  if (IS_UNDEFINED(num_imports))
3273
0
    return_integer(YR_UNDEFINED);
3274
3275
0
  for (int i = 0; i < num_imports; i++)
3276
0
  {
3277
0
    dll_name = yr_get_string(
3278
0
        module, "delayed_import_details[%i].library_name", i);
3279
3280
0
    if (dll_name == NULL || IS_UNDEFINED(dll_name) ||
3281
0
        ss_icompare(in_dll_name, dll_name) != 0)
3282
0
      continue;
3283
3284
0
    int64_t num_functions = yr_get_integer(
3285
0
        module, "delayed_import_details[%i].number_of_functions", i);
3286
3287
0
    if (IS_UNDEFINED(num_functions))
3288
0
      return_integer(YR_UNDEFINED);
3289
3290
0
    for (int j = 0; j < num_functions; j++)
3291
0
    {
3292
0
      ordinal = yr_get_integer(
3293
0
          module, "delayed_import_details[%i].functions[%i].ordinal", i, j);
3294
3295
0
      if (IS_UNDEFINED(ordinal))
3296
0
        continue;
3297
3298
0
      if (ordinal == in_ordinal)
3299
0
        return_integer(yr_get_integer(
3300
0
            module, "delayed_import_details[%i].functions[%i].rva", i, j));
3301
0
    }
3302
0
  }
3303
3304
0
  return_integer(YR_UNDEFINED);
3305
0
}
3306
3307
define_function(locale)
3308
0
{
3309
0
  YR_OBJECT* module = yr_module();
3310
0
  PE* pe = (PE*) module->data;
3311
3312
0
  uint64_t locale = integer_argument(1);
3313
3314
0
  if (yr_is_undefined(module, "number_of_resources"))
3315
0
    return_integer(YR_UNDEFINED);
3316
3317
  // If not a PE file, return YR_UNDEFINED
3318
3319
0
  if (pe == NULL)
3320
0
    return_integer(YR_UNDEFINED);
3321
3322
0
  int n = (int) yr_get_integer(module, "number_of_resources");
3323
3324
0
  for (int i = 0; i < n; i++)
3325
0
  {
3326
0
    uint64_t rsrc_language = yr_get_integer(
3327
0
        module, "resources[%i].language", i);
3328
3329
0
    if ((rsrc_language & 0xFFFF) == locale)
3330
0
      return_integer(1);
3331
0
  }
3332
3333
0
  return_integer(0);
3334
0
}
3335
3336
define_function(language)
3337
0
{
3338
0
  YR_OBJECT* module = yr_module();
3339
0
  PE* pe = (PE*) module->data;
3340
3341
0
  uint64_t language = integer_argument(1);
3342
3343
0
  if (yr_is_undefined(module, "number_of_resources"))
3344
0
    return_integer(YR_UNDEFINED);
3345
3346
  // If not a PE file, return YR_UNDEFINED
3347
3348
0
  if (pe == NULL)
3349
0
    return_integer(YR_UNDEFINED);
3350
3351
0
  int n = (int) yr_get_integer(module, "number_of_resources");
3352
3353
0
  for (int i = 0; i < n; i++)
3354
0
  {
3355
0
    uint64_t rsrc_language = yr_get_integer(
3356
0
        module, "resources[%i].language", i);
3357
3358
0
    if ((rsrc_language & 0xFF) == language)
3359
0
      return_integer(1);
3360
0
  }
3361
3362
0
  return_integer(0);
3363
0
}
3364
3365
define_function(is_dll)
3366
0
{
3367
0
  int64_t characteristics;
3368
0
  YR_OBJECT* module = yr_module();
3369
3370
0
  if (yr_is_undefined(module, "characteristics"))
3371
0
    return_integer(YR_UNDEFINED);
3372
3373
0
  characteristics = yr_get_integer(module, "characteristics");
3374
0
  return_integer(characteristics & IMAGE_FILE_DLL);
3375
0
}
3376
3377
define_function(is_32bit)
3378
0
{
3379
0
  YR_OBJECT* module = yr_module();
3380
0
  PE* pe = (PE*) module->data;
3381
3382
0
  if (pe == NULL)
3383
0
    return_integer(YR_UNDEFINED);
3384
3385
0
  return_integer(IS_64BITS_PE(pe) ? 0 : 1);
3386
0
}
3387
3388
define_function(is_64bit)
3389
0
{
3390
0
  YR_OBJECT* module = yr_module();
3391
0
  PE* pe = (PE*) module->data;
3392
3393
0
  if (pe == NULL)
3394
0
    return_integer(YR_UNDEFINED);
3395
3396
0
  return_integer(IS_64BITS_PE(pe) ? 1 : 0);
3397
0
}
3398
3399
// _rich_version
3400
//
3401
// Returns the number of rich signatures that match the specified version and
3402
// toolid numbers.
3403
//
3404
static int64_t _rich_version(
3405
    YR_OBJECT* module,
3406
    uint64_t version,
3407
    uint64_t toolid)
3408
0
{
3409
0
  int64_t rich_length;
3410
0
  int64_t rich_count;
3411
3412
0
  PRICH_SIGNATURE clear_rich_signature;
3413
0
  SIZED_STRING* rich_string;
3414
3415
0
  int64_t result = 0;
3416
3417
  // Check if the required fields are set
3418
0
  if (yr_is_undefined(module, "rich_signature.length"))
3419
0
    return YR_UNDEFINED;
3420
3421
0
  rich_length = yr_get_integer(module, "rich_signature.length");
3422
0
  rich_string = yr_get_string(module, "rich_signature.clear_data");
3423
3424
  // If clear_data was not set, return YR_UNDEFINED
3425
0
  if (rich_string == NULL)
3426
0
    return YR_UNDEFINED;
3427
3428
  // File e77b007c9a964411c5e33afeec18be32c86963b78f3c3e906b28fcf1382f46c3
3429
  // has a Rich header of length 8, which is smaller than RICH_SIGNATURE and
3430
  // causes a crash.
3431
0
  if (rich_length < sizeof(RICH_SIGNATURE))
3432
0
    return YR_UNDEFINED;
3433
3434
0
  if (version == YR_UNDEFINED && toolid == YR_UNDEFINED)
3435
0
    return 0;
3436
3437
0
  clear_rich_signature = (PRICH_SIGNATURE) rich_string->c_string;
3438
3439
  // Loop over the versions in the rich signature
3440
0
  rich_count = (rich_length - sizeof(RICH_SIGNATURE)) /
3441
0
               sizeof(RICH_VERSION_INFO);
3442
3443
0
  for (int i = 0; i < rich_count; i++)
3444
0
  {
3445
0
    DWORD id_version = yr_le32toh(clear_rich_signature->versions[i].id_version);
3446
3447
0
    int match_version = (version == RICH_VERSION_VERSION(id_version));
3448
0
    int match_toolid = (toolid == RICH_VERSION_ID(id_version));
3449
3450
0
    if ((version == YR_UNDEFINED || match_version) &&
3451
0
        (toolid == YR_UNDEFINED || match_toolid))
3452
0
    {
3453
0
      result += yr_le32toh(clear_rich_signature->versions[i].times);
3454
0
    }
3455
0
  }
3456
3457
0
  return result;
3458
0
}
3459
3460
define_function(rich_version)
3461
0
{
3462
0
  return_integer(_rich_version(yr_module(), integer_argument(1), YR_UNDEFINED));
3463
0
}
3464
3465
define_function(rich_version_toolid)
3466
0
{
3467
0
  return_integer(
3468
0
      _rich_version(yr_module(), integer_argument(1), integer_argument(2)));
3469
0
}
3470
3471
define_function(rich_toolid)
3472
0
{
3473
0
  return_integer(_rich_version(yr_module(), YR_UNDEFINED, integer_argument(1)));
3474
0
}
3475
3476
define_function(rich_toolid_version)
3477
0
{
3478
0
  return_integer(
3479
0
      _rich_version(yr_module(), integer_argument(2), integer_argument(1)));
3480
0
}
3481
3482
define_function(calculate_checksum)
3483
0
{
3484
0
  YR_OBJECT* module = yr_module();
3485
0
  PE* pe = (PE*) module->data;
3486
3487
0
  uint64_t csum = 0;
3488
0
  size_t csum_offset;
3489
3490
0
  if (pe == NULL)
3491
0
    return_integer(YR_UNDEFINED);
3492
3493
0
  csum_offset = ((uint8_t*) &(pe->header->OptionalHeader) +
3494
0
                 offsetof(IMAGE_OPTIONAL_HEADER32, CheckSum)) -
3495
0
                pe->data;
3496
3497
0
  for (size_t i = 0; i <= pe->data_size / 4; i++)
3498
0
  {
3499
    // Treat the CheckSum field as 0 -- the offset is the same for
3500
    // PE32 and PE64.
3501
3502
0
    if (4 * i == csum_offset)
3503
0
      continue;
3504
3505
0
    if (4 * i + 4 <= pe->data_size)
3506
0
    {
3507
0
      csum +=
3508
0
          ((uint64_t) pe->data[4 * i] + ((uint64_t) pe->data[4 * i + 1] << 8) +
3509
0
           ((uint64_t) pe->data[4 * i + 2] << 16) +
3510
0
           ((uint64_t) pe->data[4 * i + 3] << 24));
3511
0
    }
3512
0
    else
3513
0
    {
3514
0
      for (size_t j = 0; j < pe->data_size % 4; j++)
3515
0
        csum += (uint64_t) pe->data[4 * i + j] << (8 * j);
3516
0
    }
3517
3518
0
    if (csum > 0xffffffff)
3519
0
      csum = (csum & 0xffffffff) + (csum >> 32);
3520
0
  }
3521
3522
0
  csum = (csum & 0xffff) + (csum >> 16);
3523
0
  csum += (csum >> 16);
3524
0
  csum &= 0xffff;
3525
0
  csum += pe->data_size;
3526
3527
0
  return_integer(csum);
3528
0
}
3529
3530
define_function(rva_to_offset)
3531
0
{
3532
0
  YR_OBJECT* module = yr_module();
3533
0
  PE* pe = (PE*) module->data;
3534
3535
0
  uint64_t rva;
3536
0
  int64_t offset;
3537
3538
0
  if (pe == NULL)
3539
0
    return_integer(YR_UNDEFINED);
3540
3541
0
  rva = integer_argument(1);
3542
0
  offset = pe_rva_to_offset(pe, rva);
3543
3544
0
  if (offset == -1)
3545
0
    return_integer(YR_UNDEFINED);
3546
3547
0
  return_integer(offset);
3548
0
}
3549
3550
0
begin_declarations
3551
0
  declare_integer("MACHINE_UNKNOWN");
3552
0
  declare_integer("MACHINE_AM33");
3553
0
  declare_integer("MACHINE_AMD64");
3554
0
  declare_integer("MACHINE_ARM");
3555
0
  declare_integer("MACHINE_ARMNT");
3556
0
  declare_integer("MACHINE_ARM64");
3557
0
  declare_integer("MACHINE_EBC");
3558
0
  declare_integer("MACHINE_I386");
3559
0
  declare_integer("MACHINE_IA64");
3560
0
  declare_integer("MACHINE_M32R");
3561
0
  declare_integer("MACHINE_MIPS16");
3562
0
  declare_integer("MACHINE_MIPSFPU");
3563
0
  declare_integer("MACHINE_MIPSFPU16");
3564
0
  declare_integer("MACHINE_POWERPC");
3565
0
  declare_integer("MACHINE_POWERPCFP");
3566
0
  declare_integer("MACHINE_R4000");
3567
0
  declare_integer("MACHINE_SH3");
3568
0
  declare_integer("MACHINE_SH3DSP");
3569
0
  declare_integer("MACHINE_SH4");
3570
0
  declare_integer("MACHINE_SH5");
3571
0
  declare_integer("MACHINE_THUMB");
3572
0
  declare_integer("MACHINE_WCEMIPSV2");
3573
0
  declare_integer("MACHINE_TARGET_HOST");
3574
0
  declare_integer("MACHINE_R3000");
3575
0
  declare_integer("MACHINE_R10000");
3576
0
  declare_integer("MACHINE_ALPHA");
3577
0
  declare_integer("MACHINE_SH3E");
3578
0
  declare_integer("MACHINE_ALPHA64");
3579
0
  declare_integer("MACHINE_AXP64");
3580
0
  declare_integer("MACHINE_TRICORE");
3581
0
  declare_integer("MACHINE_CEF");
3582
0
  declare_integer("MACHINE_CEE");
3583
3584
0
  declare_integer("SUBSYSTEM_UNKNOWN");
3585
0
  declare_integer("SUBSYSTEM_NATIVE");
3586
0
  declare_integer("SUBSYSTEM_WINDOWS_GUI");
3587
0
  declare_integer("SUBSYSTEM_WINDOWS_CUI");
3588
0
  declare_integer("SUBSYSTEM_OS2_CUI");
3589
0
  declare_integer("SUBSYSTEM_POSIX_CUI");
3590
0
  declare_integer("SUBSYSTEM_NATIVE_WINDOWS");
3591
0
  declare_integer("SUBSYSTEM_WINDOWS_CE_GUI");
3592
0
  declare_integer("SUBSYSTEM_EFI_APPLICATION");
3593
0
  declare_integer("SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER");
3594
0
  declare_integer("SUBSYSTEM_EFI_RUNTIME_DRIVER");
3595
0
  declare_integer("SUBSYSTEM_EFI_ROM_IMAGE");
3596
0
  declare_integer("SUBSYSTEM_XBOX");
3597
0
  declare_integer("SUBSYSTEM_WINDOWS_BOOT_APPLICATION");
3598
3599
0
  declare_integer("HIGH_ENTROPY_VA");
3600
0
  declare_integer("DYNAMIC_BASE");
3601
0
  declare_integer("FORCE_INTEGRITY");
3602
0
  declare_integer("NX_COMPAT");
3603
0
  declare_integer("NO_ISOLATION");
3604
0
  declare_integer("NO_SEH");
3605
0
  declare_integer("NO_BIND");
3606
0
  declare_integer("APPCONTAINER");
3607
0
  declare_integer("WDM_DRIVER");
3608
0
  declare_integer("GUARD_CF");
3609
0
  declare_integer("TERMINAL_SERVER_AWARE");
3610
3611
0
  declare_integer("RELOCS_STRIPPED");
3612
0
  declare_integer("EXECUTABLE_IMAGE");
3613
0
  declare_integer("LINE_NUMS_STRIPPED");
3614
0
  declare_integer("LOCAL_SYMS_STRIPPED");
3615
0
  declare_integer("AGGRESIVE_WS_TRIM");
3616
0
  declare_integer("LARGE_ADDRESS_AWARE");
3617
0
  declare_integer("BYTES_REVERSED_LO");
3618
0
  declare_integer("MACHINE_32BIT");
3619
0
  declare_integer("DEBUG_STRIPPED");
3620
0
  declare_integer("REMOVABLE_RUN_FROM_SWAP");
3621
0
  declare_integer("NET_RUN_FROM_SWAP");
3622
0
  declare_integer("SYSTEM");
3623
0
  declare_integer("DLL");
3624
0
  declare_integer("UP_SYSTEM_ONLY");
3625
0
  declare_integer("BYTES_REVERSED_HI");
3626
3627
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_EXPORT");
3628
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_IMPORT");
3629
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_RESOURCE");
3630
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_EXCEPTION");
3631
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_SECURITY");
3632
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_BASERELOC");
3633
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_DEBUG");
3634
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_ARCHITECTURE");
3635
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_COPYRIGHT");
3636
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_GLOBALPTR");
3637
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_TLS");
3638
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG");
3639
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT");
3640
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_IAT");
3641
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT");
3642
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR");
3643
3644
0
  declare_integer("IMAGE_NT_OPTIONAL_HDR32_MAGIC");
3645
0
  declare_integer("IMAGE_NT_OPTIONAL_HDR64_MAGIC");
3646
0
  declare_integer("IMAGE_ROM_OPTIONAL_HDR_MAGIC");
3647
3648
0
  declare_integer("SECTION_NO_PAD");
3649
0
  declare_integer("SECTION_CNT_CODE");
3650
0
  declare_integer("SECTION_CNT_INITIALIZED_DATA");
3651
0
  declare_integer("SECTION_CNT_UNINITIALIZED_DATA");
3652
0
  declare_integer("SECTION_LNK_OTHER");
3653
0
  declare_integer("SECTION_LNK_INFO");
3654
0
  declare_integer("SECTION_LNK_REMOVE");
3655
0
  declare_integer("SECTION_LNK_COMDAT");
3656
0
  declare_integer("SECTION_NO_DEFER_SPEC_EXC");
3657
0
  declare_integer("SECTION_GPREL");
3658
0
  declare_integer("SECTION_MEM_FARDATA");
3659
0
  declare_integer("SECTION_MEM_PURGEABLE");
3660
0
  declare_integer("SECTION_MEM_16BIT");
3661
0
  declare_integer("SECTION_MEM_LOCKED");
3662
0
  declare_integer("SECTION_MEM_PRELOAD");
3663
0
  declare_integer("SECTION_ALIGN_1BYTES");
3664
0
  declare_integer("SECTION_ALIGN_2BYTES");
3665
0
  declare_integer("SECTION_ALIGN_4BYTES");
3666
0
  declare_integer("SECTION_ALIGN_8BYTES");
3667
0
  declare_integer("SECTION_ALIGN_16BYTES");
3668
0
  declare_integer("SECTION_ALIGN_32BYTES");
3669
0
  declare_integer("SECTION_ALIGN_64BYTES");
3670
0
  declare_integer("SECTION_ALIGN_128BYTES");
3671
0
  declare_integer("SECTION_ALIGN_256BYTES");
3672
0
  declare_integer("SECTION_ALIGN_512BYTES");
3673
0
  declare_integer("SECTION_ALIGN_1024BYTES");
3674
0
  declare_integer("SECTION_ALIGN_2048BYTES");
3675
0
  declare_integer("SECTION_ALIGN_4096BYTES");
3676
0
  declare_integer("SECTION_ALIGN_8192BYTES");
3677
0
  declare_integer("SECTION_ALIGN_MASK");
3678
0
  declare_integer("SECTION_LNK_NRELOC_OVFL");
3679
0
  declare_integer("SECTION_MEM_DISCARDABLE");
3680
0
  declare_integer("SECTION_MEM_NOT_CACHED");
3681
0
  declare_integer("SECTION_MEM_NOT_PAGED");
3682
0
  declare_integer("SECTION_MEM_SHARED");
3683
0
  declare_integer("SECTION_MEM_EXECUTE");
3684
0
  declare_integer("SECTION_MEM_READ");
3685
0
  declare_integer("SECTION_MEM_WRITE");
3686
0
  declare_integer("SECTION_SCALE_INDEX");
3687
3688
0
  declare_integer("RESOURCE_TYPE_CURSOR");
3689
0
  declare_integer("RESOURCE_TYPE_BITMAP");
3690
0
  declare_integer("RESOURCE_TYPE_ICON");
3691
0
  declare_integer("RESOURCE_TYPE_MENU");
3692
0
  declare_integer("RESOURCE_TYPE_DIALOG");
3693
0
  declare_integer("RESOURCE_TYPE_STRING");
3694
0
  declare_integer("RESOURCE_TYPE_FONTDIR");
3695
0
  declare_integer("RESOURCE_TYPE_FONT");
3696
0
  declare_integer("RESOURCE_TYPE_ACCELERATOR");
3697
0
  declare_integer("RESOURCE_TYPE_RCDATA");
3698
0
  declare_integer("RESOURCE_TYPE_MESSAGETABLE");
3699
0
  declare_integer("RESOURCE_TYPE_GROUP_CURSOR");
3700
0
  declare_integer("RESOURCE_TYPE_GROUP_ICON");
3701
0
  declare_integer("RESOURCE_TYPE_VERSION");
3702
0
  declare_integer("RESOURCE_TYPE_DLGINCLUDE");
3703
0
  declare_integer("RESOURCE_TYPE_PLUGPLAY");
3704
0
  declare_integer("RESOURCE_TYPE_VXD");
3705
0
  declare_integer("RESOURCE_TYPE_ANICURSOR");
3706
0
  declare_integer("RESOURCE_TYPE_ANIICON");
3707
0
  declare_integer("RESOURCE_TYPE_HTML");
3708
0
  declare_integer("RESOURCE_TYPE_MANIFEST");
3709
3710
0
  declare_integer("IMAGE_DEBUG_TYPE_UNKNOWN");
3711
0
  declare_integer("IMAGE_DEBUG_TYPE_COFF");
3712
0
  declare_integer("IMAGE_DEBUG_TYPE_CODEVIEW");
3713
0
  declare_integer("IMAGE_DEBUG_TYPE_FPO");
3714
0
  declare_integer("IMAGE_DEBUG_TYPE_MISC");
3715
0
  declare_integer("IMAGE_DEBUG_TYPE_EXCEPTION");
3716
0
  declare_integer("IMAGE_DEBUG_TYPE_FIXUP");
3717
0
  declare_integer("IMAGE_DEBUG_TYPE_OMAP_TO_SRC");
3718
0
  declare_integer("IMAGE_DEBUG_TYPE_OMAP_FROM_SRC");
3719
0
  declare_integer("IMAGE_DEBUG_TYPE_BORLAND");
3720
0
  declare_integer("IMAGE_DEBUG_TYPE_RESERVED10");
3721
0
  declare_integer("IMAGE_DEBUG_TYPE_CLSID");
3722
0
  declare_integer("IMAGE_DEBUG_TYPE_VC_FEATURE");
3723
0
  declare_integer("IMAGE_DEBUG_TYPE_POGO");
3724
0
  declare_integer("IMAGE_DEBUG_TYPE_ILTCG");
3725
0
  declare_integer("IMAGE_DEBUG_TYPE_MPX");
3726
0
  declare_integer("IMAGE_DEBUG_TYPE_REPRO");
3727
3728
0
  declare_integer("IMPORT_DELAYED");
3729
0
  declare_integer("IMPORT_STANDARD");
3730
0
  declare_integer("IMPORT_ANY");
3731
3732
0
  declare_integer("is_pe");
3733
0
  declare_integer("machine");
3734
0
  declare_integer("number_of_sections");
3735
0
  declare_integer("timestamp");
3736
0
  declare_integer("pointer_to_symbol_table");
3737
0
  declare_integer("number_of_symbols");
3738
0
  declare_integer("size_of_optional_header");
3739
0
  declare_integer("characteristics");
3740
3741
0
  declare_integer("entry_point");
3742
0
  declare_integer("entry_point_raw");
3743
0
  declare_integer("image_base");
3744
0
  declare_integer("number_of_rva_and_sizes");
3745
0
  declare_integer("number_of_version_infos");
3746
3747
0
  declare_string_dictionary("version_info");
3748
3749
0
  begin_struct_array("version_info_list")
3750
0
    declare_string("key");
3751
0
    declare_string("value");
3752
0
  end_struct_array("version_info_list");
3753
3754
0
  declare_integer("opthdr_magic");
3755
0
  declare_integer("size_of_code");
3756
0
  declare_integer("size_of_initialized_data");
3757
0
  declare_integer("size_of_uninitialized_data");
3758
0
  declare_integer("base_of_code");
3759
0
  declare_integer("base_of_data");
3760
0
  declare_integer("section_alignment");
3761
0
  declare_integer("file_alignment");
3762
3763
0
  begin_struct("linker_version")
3764
0
    declare_integer("major");
3765
0
    declare_integer("minor");
3766
0
  end_struct("linker_version");
3767
3768
0
  begin_struct("os_version")
3769
0
    declare_integer("major");
3770
0
    declare_integer("minor");
3771
0
  end_struct("os_version");
3772
3773
0
  begin_struct("image_version")
3774
0
    declare_integer("major");
3775
0
    declare_integer("minor");
3776
0
  end_struct("image_version");
3777
3778
0
  begin_struct("subsystem_version")
3779
0
    declare_integer("major");
3780
0
    declare_integer("minor");
3781
0
  end_struct("subsystem_version");
3782
3783
0
  declare_integer("win32_version_value");
3784
0
  declare_integer("size_of_image");
3785
0
  declare_integer("size_of_headers");
3786
3787
0
  declare_integer("checksum");
3788
0
  declare_function("calculate_checksum", "", "i", calculate_checksum);
3789
0
  declare_integer("subsystem");
3790
3791
0
  declare_integer("dll_characteristics");
3792
0
  declare_integer("size_of_stack_reserve");
3793
0
  declare_integer("size_of_stack_commit");
3794
0
  declare_integer("size_of_heap_reserve");
3795
0
  declare_integer("size_of_heap_commit");
3796
0
  declare_integer("loader_flags");
3797
3798
0
  begin_struct_array("data_directories")
3799
0
    declare_integer("virtual_address");
3800
0
    declare_integer("size");
3801
0
  end_struct_array("data_directories");
3802
3803
0
  begin_struct_array("sections")
3804
0
    declare_string("name");
3805
0
    declare_string("full_name");
3806
0
    declare_integer("characteristics");
3807
0
    declare_integer("virtual_address");
3808
0
    declare_integer("virtual_size");
3809
0
    declare_integer("raw_data_offset");
3810
0
    declare_integer("raw_data_size");
3811
0
    declare_integer("pointer_to_relocations");
3812
0
    declare_integer("pointer_to_line_numbers");
3813
0
    declare_integer("number_of_relocations");
3814
0
    declare_integer("number_of_line_numbers");
3815
0
  end_struct_array("sections");
3816
3817
0
  begin_struct("overlay")
3818
0
    declare_integer("offset");
3819
0
    declare_integer("size");
3820
0
  end_struct("overlay");
3821
3822
0
  begin_struct("rich_signature")
3823
0
    declare_integer("offset");
3824
0
    declare_integer("length");
3825
0
    declare_integer("key");
3826
0
    declare_string("raw_data");
3827
0
    declare_string("clear_data");
3828
0
    declare_string("version_data");
3829
0
    declare_function("version", "i", "i", rich_version);
3830
0
    declare_function("version", "ii", "i", rich_version_toolid);
3831
0
    declare_function("toolid", "i", "i", rich_toolid);
3832
0
    declare_function("toolid", "ii", "i", rich_toolid_version);
3833
0
  end_struct("rich_signature");
3834
3835
#if defined(HAVE_LIBCRYPTO) || defined(HAVE_WINCRYPT_H) || \
3836
    defined(HAVE_COMMONCRYPTO_COMMONCRYPTO_H)
3837
  declare_function("imphash", "", "s", imphash);
3838
#endif
3839
3840
0
  declare_function("section_index", "s", "i", section_index_name);
3841
0
  declare_function("section_index", "i", "i", section_index_addr);
3842
0
  declare_function("exports", "s", "i", exports);
3843
0
  declare_function("exports", "r", "i", exports_regexp);
3844
0
  declare_function("exports", "i", "i", exports_ordinal);
3845
0
  declare_function("exports_index", "s", "i", exports_index_name);
3846
0
  declare_function("exports_index", "i", "i", exports_index_ordinal);
3847
0
  declare_function("exports_index", "r", "i", exports_index_regex);
3848
0
  declare_function("imports", "ss", "i", imports_standard);
3849
0
  declare_function("imports", "si", "i", imports_standard_ordinal);
3850
0
  declare_function("imports", "s", "i", imports_standard_dll);
3851
0
  declare_function("imports", "rr", "i", imports_standard_regex);
3852
0
  declare_function("imports", "iss", "i", imports);
3853
0
  declare_function("imports", "isi", "i", imports_ordinal);
3854
0
  declare_function("imports", "is", "i", imports_dll);
3855
0
  declare_function("imports", "irr", "i", imports_regex);
3856
0
  declare_function("import_rva", "ss", "i", import_rva);
3857
0
  declare_function("import_rva", "si", "i", import_rva_ordinal);
3858
0
  declare_function("delayed_import_rva", "ss", "i", delayed_import_rva);
3859
0
  declare_function("delayed_import_rva", "si", "i", delayed_import_rva_ordinal);
3860
0
  declare_function("locale", "i", "i", locale);
3861
0
  declare_function("language", "i", "i", language);
3862
0
  declare_function("is_dll", "", "i", is_dll);
3863
0
  declare_function("is_32bit", "", "i", is_32bit);
3864
0
  declare_function("is_64bit", "", "i", is_64bit);
3865
3866
0
  declare_integer("number_of_imports");
3867
0
  declare_integer("number_of_imported_functions");
3868
0
  declare_integer("number_of_delayed_imports");
3869
0
  declare_integer("number_of_delayed_imported_functions");
3870
0
  declare_integer("number_of_exports");
3871
3872
0
  declare_string("dll_name");
3873
0
  declare_integer("export_timestamp");
3874
0
  begin_struct_array("export_details")
3875
0
    declare_integer("offset");
3876
0
    declare_string("name");
3877
0
    declare_string("forward_name");
3878
0
    declare_integer("ordinal");
3879
0
    declare_integer("rva");
3880
0
  end_struct_array("export_details")
3881
3882
0
  begin_struct_array("import_details")
3883
0
    declare_string("library_name");
3884
0
    declare_integer("number_of_functions");
3885
0
    begin_struct_array("functions")
3886
0
      declare_string("name");
3887
0
      declare_integer("ordinal");
3888
0
      declare_integer("rva");
3889
0
    end_struct_array("functions");
3890
0
  end_struct_array("import_details");
3891
3892
0
  begin_struct_array("delayed_import_details")
3893
0
    declare_string("library_name");
3894
0
    declare_integer("number_of_functions");
3895
0
    begin_struct_array("functions")
3896
0
      declare_string("name");
3897
0
      declare_integer("ordinal");
3898
0
      declare_integer("rva");
3899
0
    end_struct_array("functions");
3900
0
  end_struct_array("delayed_import_details");
3901
3902
0
  declare_integer("resource_timestamp");
3903
3904
0
  begin_struct("resource_version")
3905
0
    declare_integer("major");
3906
0
    declare_integer("minor");
3907
0
  end_struct("resource_version")
3908
3909
0
  begin_struct_array("resources")
3910
0
    declare_integer("rva");
3911
0
    declare_integer("offset");
3912
0
    declare_integer("length");
3913
0
    declare_integer("type");
3914
0
    declare_integer("id");
3915
0
    declare_integer("language");
3916
0
    declare_string("type_string");
3917
0
    declare_string("name_string");
3918
0
    declare_string("language_string");
3919
0
  end_struct_array("resources")
3920
3921
0
  declare_integer("number_of_resources");
3922
0
  declare_string("pdb_path");
3923
3924
#if defined(HAVE_LIBCRYPTO) && !defined(BORINGSSL)
3925
  begin_struct_array("signatures")
3926
    declare_string("thumbprint");
3927
    declare_string("issuer");
3928
    declare_string("subject");
3929
    declare_integer("version");
3930
    declare_string("algorithm");
3931
    declare_string("algorithm_oid");
3932
    declare_string("serial");
3933
    declare_integer("not_before");
3934
    declare_integer("not_after");
3935
3936
    declare_integer("verified");
3937
    declare_string("digest_alg");
3938
    declare_string("digest");
3939
    declare_string("file_digest");
3940
    declare_integer("number_of_certificates");
3941
    begin_struct_array("certificates")
3942
      ;
3943
      declare_string("thumbprint");
3944
      declare_string("issuer");
3945
      declare_string("subject");
3946
      declare_integer("version");
3947
      declare_string("algorithm");
3948
      declare_string("algorithm_oid");
3949
      declare_string("serial");
3950
      declare_integer("not_before");
3951
      declare_integer("not_after");
3952
    end_struct_array("certificates");
3953
3954
    begin_struct("signer_info")
3955
      ;
3956
      declare_string("program_name");
3957
      declare_string("digest");
3958
      declare_string("digest_alg");
3959
      declare_integer("length_of_chain");
3960
      begin_struct_array("chain")
3961
        ;
3962
        declare_string("thumbprint");
3963
        declare_string("issuer");
3964
        declare_string("subject");
3965
        declare_integer("version");
3966
        declare_string("algorithm");
3967
        declare_string("algorithm_oid");
3968
        declare_string("serial");
3969
        declare_integer("not_before");
3970
        declare_integer("not_after");
3971
      end_struct_array("chain");
3972
    end_struct("signer_info");
3973
3974
    declare_integer("number_of_countersignatures");
3975
    begin_struct_array("countersignatures")
3976
      ;
3977
      declare_integer("verified");
3978
      declare_integer("sign_time");
3979
      declare_string("digest_alg");
3980
      declare_string("digest");
3981
      declare_integer("length_of_chain");
3982
      begin_struct_array("chain")
3983
        ;
3984
        declare_string("thumbprint");
3985
        declare_string("issuer");
3986
        declare_string("subject");
3987
        declare_integer("version");
3988
        declare_string("algorithm");
3989
        declare_string("algorithm_oid");
3990
        declare_string("serial");
3991
        declare_integer("not_before");
3992
        declare_integer("not_after");
3993
      end_struct_array("chain");
3994
    end_struct_array("countersignatures")
3995
3996
    declare_function("valid_on", "i", "i", valid_on);
3997
3998
  end_struct_array("signatures")
3999
4000
  // If any of the signatures correctly signs the binary
4001
  declare_integer("is_signed");
4002
  declare_integer("number_of_signatures");
4003
#endif
4004
4005
0
  declare_function("rva_to_offset", "i", "i", rva_to_offset);
4006
0
end_declarations
4007
4008
int module_initialize(YR_MODULE* module)
4009
2
{
4010
#if defined(HAVE_LIBCRYPTO) && !defined(BORINGSSL)
4011
  // Initialize OpenSSL global objects for the auth library before any
4012
  // multithreaded environment as it is not thread-safe. This can
4013
  // only be called once per process.
4014
  static bool s_initialized = false;
4015
4016
  if (!s_initialized)
4017
  {
4018
    s_initialized = true;
4019
    initialize_authenticode_parser();
4020
  }
4021
#endif
4022
2
  return ERROR_SUCCESS;
4023
2
}
4024
4025
int module_finalize(YR_MODULE* module)
4026
0
{
4027
0
  return ERROR_SUCCESS;
4028
0
}
4029
4030
int module_load(
4031
    YR_SCAN_CONTEXT* context,
4032
    YR_OBJECT* module_object,
4033
    void* module_data,
4034
    size_t module_data_size)
4035
0
{
4036
0
  YR_MEMORY_BLOCK* block;
4037
0
  YR_MEMORY_BLOCK_ITERATOR* iterator = context->iterator;
4038
4039
0
  PIMAGE_NT_HEADERS32 pe_header;
4040
0
  const uint8_t* block_data = NULL;
4041
0
  PE* pe = NULL;
4042
4043
0
  yr_set_integer(IMPORT_DELAYED, module_object, "IMPORT_DELAYED");
4044
0
  yr_set_integer(IMPORT_STANDARD, module_object, "IMPORT_STANDARD");
4045
0
  yr_set_integer(IMPORT_ANY, module_object, "IMPORT_ANY");
4046
4047
0
  yr_set_integer(IMAGE_FILE_MACHINE_UNKNOWN, module_object, "MACHINE_UNKNOWN");
4048
0
  yr_set_integer(IMAGE_FILE_MACHINE_AM33, module_object, "MACHINE_AM33");
4049
0
  yr_set_integer(IMAGE_FILE_MACHINE_AMD64, module_object, "MACHINE_AMD64");
4050
0
  yr_set_integer(IMAGE_FILE_MACHINE_ARM, module_object, "MACHINE_ARM");
4051
0
  yr_set_integer(IMAGE_FILE_MACHINE_ARMNT, module_object, "MACHINE_ARMNT");
4052
0
  yr_set_integer(IMAGE_FILE_MACHINE_ARM64, module_object, "MACHINE_ARM64");
4053
0
  yr_set_integer(IMAGE_FILE_MACHINE_EBC, module_object, "MACHINE_EBC");
4054
0
  yr_set_integer(IMAGE_FILE_MACHINE_I386, module_object, "MACHINE_I386");
4055
0
  yr_set_integer(IMAGE_FILE_MACHINE_IA64, module_object, "MACHINE_IA64");
4056
0
  yr_set_integer(IMAGE_FILE_MACHINE_M32R, module_object, "MACHINE_M32R");
4057
0
  yr_set_integer(IMAGE_FILE_MACHINE_MIPS16, module_object, "MACHINE_MIPS16");
4058
0
  yr_set_integer(IMAGE_FILE_MACHINE_MIPSFPU, module_object, "MACHINE_MIPSFPU");
4059
0
  yr_set_integer(
4060
0
      IMAGE_FILE_MACHINE_MIPSFPU16, module_object, "MACHINE_MIPSFPU16");
4061
0
  yr_set_integer(IMAGE_FILE_MACHINE_POWERPC, module_object, "MACHINE_POWERPC");
4062
0
  yr_set_integer(
4063
0
      IMAGE_FILE_MACHINE_POWERPCFP, module_object, "MACHINE_POWERPCFP");
4064
0
  yr_set_integer(IMAGE_FILE_MACHINE_R4000, module_object, "MACHINE_R4000");
4065
0
  yr_set_integer(IMAGE_FILE_MACHINE_SH3, module_object, "MACHINE_SH3");
4066
0
  yr_set_integer(IMAGE_FILE_MACHINE_SH3DSP, module_object, "MACHINE_SH3DSP");
4067
0
  yr_set_integer(IMAGE_FILE_MACHINE_SH4, module_object, "MACHINE_SH4");
4068
0
  yr_set_integer(IMAGE_FILE_MACHINE_SH5, module_object, "MACHINE_SH5");
4069
0
  yr_set_integer(IMAGE_FILE_MACHINE_THUMB, module_object, "MACHINE_THUMB");
4070
0
  yr_set_integer(
4071
0
      IMAGE_FILE_MACHINE_WCEMIPSV2, module_object, "MACHINE_WCEMIPSV2");
4072
0
  yr_set_integer(
4073
0
      IMAGE_FILE_MACHINE_TARGET_HOST, module_object, "MACHINE_TARGET_HOST");
4074
0
  yr_set_integer(IMAGE_FILE_MACHINE_R3000, module_object, "MACHINE_R3000");
4075
0
  yr_set_integer(IMAGE_FILE_MACHINE_R10000, module_object, "MACHINE_R10000");
4076
0
  yr_set_integer(IMAGE_FILE_MACHINE_ALPHA, module_object, "MACHINE_ALPHA");
4077
0
  yr_set_integer(IMAGE_FILE_MACHINE_SH3E, module_object, "MACHINE_SH3E");
4078
0
  yr_set_integer(IMAGE_FILE_MACHINE_ALPHA64, module_object, "MACHINE_ALPHA64");
4079
0
  yr_set_integer(IMAGE_FILE_MACHINE_AXP64, module_object, "MACHINE_AXP64");
4080
0
  yr_set_integer(IMAGE_FILE_MACHINE_TRICORE, module_object, "MACHINE_TRICORE");
4081
0
  yr_set_integer(IMAGE_FILE_MACHINE_CEF, module_object, "MACHINE_CEF");
4082
0
  yr_set_integer(IMAGE_FILE_MACHINE_CEE, module_object, "MACHINE_CEE");
4083
4084
0
  yr_set_integer(IMAGE_SUBSYSTEM_UNKNOWN, module_object, "SUBSYSTEM_UNKNOWN");
4085
0
  yr_set_integer(IMAGE_SUBSYSTEM_NATIVE, module_object, "SUBSYSTEM_NATIVE");
4086
0
  yr_set_integer(
4087
0
      IMAGE_SUBSYSTEM_WINDOWS_GUI, module_object, "SUBSYSTEM_WINDOWS_GUI");
4088
0
  yr_set_integer(
4089
0
      IMAGE_SUBSYSTEM_WINDOWS_CUI, module_object, "SUBSYSTEM_WINDOWS_CUI");
4090
0
  yr_set_integer(IMAGE_SUBSYSTEM_OS2_CUI, module_object, "SUBSYSTEM_OS2_CUI");
4091
0
  yr_set_integer(
4092
0
      IMAGE_SUBSYSTEM_POSIX_CUI, module_object, "SUBSYSTEM_POSIX_CUI");
4093
0
  yr_set_integer(
4094
0
      IMAGE_SUBSYSTEM_NATIVE_WINDOWS,
4095
0
      module_object,
4096
0
      "SUBSYSTEM_NATIVE_WINDOWS");
4097
0
  yr_set_integer(
4098
0
      IMAGE_SUBSYSTEM_WINDOWS_CE_GUI,
4099
0
      module_object,
4100
0
      "SUBSYSTEM_WINDOWS_CE_GUI");
4101
0
  yr_set_integer(
4102
0
      IMAGE_SUBSYSTEM_EFI_APPLICATION,
4103
0
      module_object,
4104
0
      "SUBSYSTEM_EFI_APPLICATION");
4105
0
  yr_set_integer(
4106
0
      IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER,
4107
0
      module_object,
4108
0
      "SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER");
4109
0
  yr_set_integer(
4110
0
      IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER,
4111
0
      module_object,
4112
0
      "SUBSYSTEM_EFI_RUNTIME_DRIVER");
4113
0
  yr_set_integer(
4114
0
      IMAGE_SUBSYSTEM_EFI_ROM_IMAGE, module_object, "SUBSYSTEM_EFI_ROM_IMAGE");
4115
0
  yr_set_integer(IMAGE_SUBSYSTEM_XBOX, module_object, "SUBSYSTEM_XBOX");
4116
0
  yr_set_integer(
4117
0
      IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION,
4118
0
      module_object,
4119
0
      "SUBSYSTEM_WINDOWS_BOOT_APPLICATION");
4120
4121
0
  yr_set_integer(
4122
0
      IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA,
4123
0
      module_object,
4124
0
      "HIGH_ENTROPY_VA");
4125
0
  yr_set_integer(
4126
0
      IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE, module_object, "DYNAMIC_BASE");
4127
0
  yr_set_integer(
4128
0
      IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY,
4129
0
      module_object,
4130
0
      "FORCE_INTEGRITY");
4131
0
  yr_set_integer(
4132
0
      IMAGE_DLLCHARACTERISTICS_NX_COMPAT, module_object, "NX_COMPAT");
4133
0
  yr_set_integer(
4134
0
      IMAGE_DLLCHARACTERISTICS_NO_ISOLATION, module_object, "NO_ISOLATION");
4135
0
  yr_set_integer(IMAGE_DLLCHARACTERISTICS_NO_SEH, module_object, "NO_SEH");
4136
0
  yr_set_integer(IMAGE_DLLCHARACTERISTICS_NO_BIND, module_object, "NO_BIND");
4137
0
  yr_set_integer(
4138
0
      IMAGE_DLLCHARACTERISTICS_APPCONTAINER, module_object, "APPCONTAINER");
4139
0
  yr_set_integer(
4140
0
      IMAGE_DLLCHARACTERISTICS_WDM_DRIVER, module_object, "WDM_DRIVER");
4141
0
  yr_set_integer(IMAGE_DLLCHARACTERISTICS_GUARD_CF, module_object, "GUARD_CF");
4142
0
  yr_set_integer(
4143
0
      IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE,
4144
0
      module_object,
4145
0
      "TERMINAL_SERVER_AWARE");
4146
4147
0
  yr_set_integer(IMAGE_FILE_RELOCS_STRIPPED, module_object, "RELOCS_STRIPPED");
4148
0
  yr_set_integer(
4149
0
      IMAGE_FILE_EXECUTABLE_IMAGE, module_object, "EXECUTABLE_IMAGE");
4150
0
  yr_set_integer(
4151
0
      IMAGE_FILE_LINE_NUMS_STRIPPED, module_object, "LINE_NUMS_STRIPPED");
4152
0
  yr_set_integer(
4153
0
      IMAGE_FILE_LOCAL_SYMS_STRIPPED, module_object, "LOCAL_SYMS_STRIPPED");
4154
0
  yr_set_integer(
4155
0
      IMAGE_FILE_AGGRESIVE_WS_TRIM, module_object, "AGGRESIVE_WS_TRIM");
4156
0
  yr_set_integer(
4157
0
      IMAGE_FILE_LARGE_ADDRESS_AWARE, module_object, "LARGE_ADDRESS_AWARE");
4158
0
  yr_set_integer(
4159
0
      IMAGE_FILE_BYTES_REVERSED_LO, module_object, "BYTES_REVERSED_LO");
4160
0
  yr_set_integer(IMAGE_FILE_32BIT_MACHINE, module_object, "MACHINE_32BIT");
4161
0
  yr_set_integer(IMAGE_FILE_DEBUG_STRIPPED, module_object, "DEBUG_STRIPPED");
4162
0
  yr_set_integer(
4163
0
      IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP,
4164
0
      module_object,
4165
0
      "REMOVABLE_RUN_FROM_SWAP");
4166
0
  yr_set_integer(
4167
0
      IMAGE_FILE_NET_RUN_FROM_SWAP, module_object, "NET_RUN_FROM_SWAP");
4168
0
  yr_set_integer(IMAGE_FILE_SYSTEM, module_object, "SYSTEM");
4169
0
  yr_set_integer(IMAGE_FILE_DLL, module_object, "DLL");
4170
0
  yr_set_integer(IMAGE_FILE_UP_SYSTEM_ONLY, module_object, "UP_SYSTEM_ONLY");
4171
0
  yr_set_integer(
4172
0
      IMAGE_FILE_BYTES_REVERSED_HI, module_object, "BYTES_REVERSED_HI");
4173
4174
0
  yr_set_integer(
4175
0
      IMAGE_DIRECTORY_ENTRY_EXPORT,
4176
0
      module_object,
4177
0
      "IMAGE_DIRECTORY_ENTRY_EXPORT");
4178
0
  yr_set_integer(
4179
0
      IMAGE_DIRECTORY_ENTRY_IMPORT,
4180
0
      module_object,
4181
0
      "IMAGE_DIRECTORY_ENTRY_IMPORT");
4182
0
  yr_set_integer(
4183
0
      IMAGE_DIRECTORY_ENTRY_RESOURCE,
4184
0
      module_object,
4185
0
      "IMAGE_DIRECTORY_ENTRY_RESOURCE");
4186
0
  yr_set_integer(
4187
0
      IMAGE_DIRECTORY_ENTRY_EXCEPTION,
4188
0
      module_object,
4189
0
      "IMAGE_DIRECTORY_ENTRY_EXCEPTION");
4190
0
  yr_set_integer(
4191
0
      IMAGE_DIRECTORY_ENTRY_SECURITY,
4192
0
      module_object,
4193
0
      "IMAGE_DIRECTORY_ENTRY_SECURITY");
4194
0
  yr_set_integer(
4195
0
      IMAGE_DIRECTORY_ENTRY_BASERELOC,
4196
0
      module_object,
4197
0
      "IMAGE_DIRECTORY_ENTRY_BASERELOC");
4198
0
  yr_set_integer(
4199
0
      IMAGE_DIRECTORY_ENTRY_DEBUG,
4200
0
      module_object,
4201
0
      "IMAGE_DIRECTORY_ENTRY_DEBUG");
4202
0
  yr_set_integer(
4203
0
      IMAGE_DIRECTORY_ENTRY_ARCHITECTURE,
4204
0
      module_object,
4205
0
      "IMAGE_DIRECTORY_ENTRY_ARCHITECTURE");
4206
0
  yr_set_integer(
4207
0
      IMAGE_DIRECTORY_ENTRY_COPYRIGHT,
4208
0
      module_object,
4209
0
      "IMAGE_DIRECTORY_ENTRY_COPYRIGHT");
4210
0
  yr_set_integer(
4211
0
      IMAGE_DIRECTORY_ENTRY_GLOBALPTR,
4212
0
      module_object,
4213
0
      "IMAGE_DIRECTORY_ENTRY_GLOBALPTR");
4214
0
  yr_set_integer(
4215
0
      IMAGE_DIRECTORY_ENTRY_TLS, module_object, "IMAGE_DIRECTORY_ENTRY_TLS");
4216
0
  yr_set_integer(
4217
0
      IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
4218
0
      module_object,
4219
0
      "IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG");
4220
0
  yr_set_integer(
4221
0
      IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT,
4222
0
      module_object,
4223
0
      "IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT");
4224
0
  yr_set_integer(
4225
0
      IMAGE_DIRECTORY_ENTRY_IAT, module_object, "IMAGE_DIRECTORY_ENTRY_IAT");
4226
0
  yr_set_integer(
4227
0
      IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT,
4228
0
      module_object,
4229
0
      "IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT");
4230
0
  yr_set_integer(
4231
0
      IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR,
4232
0
      module_object,
4233
0
      "IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR");
4234
4235
0
  yr_set_integer(
4236
0
      IMAGE_NT_OPTIONAL_HDR32_MAGIC,
4237
0
      module_object,
4238
0
      "IMAGE_NT_OPTIONAL_HDR32_MAGIC");
4239
0
  yr_set_integer(
4240
0
      IMAGE_NT_OPTIONAL_HDR64_MAGIC,
4241
0
      module_object,
4242
0
      "IMAGE_NT_OPTIONAL_HDR64_MAGIC");
4243
0
  yr_set_integer(
4244
0
      IMAGE_ROM_OPTIONAL_HDR_MAGIC,
4245
0
      module_object,
4246
0
      "IMAGE_ROM_OPTIONAL_HDR_MAGIC");
4247
4248
0
  yr_set_integer(IMAGE_SCN_TYPE_NO_PAD, module_object, "SECTION_NO_PAD");
4249
0
  yr_set_integer(IMAGE_SCN_CNT_CODE, module_object, "SECTION_CNT_CODE");
4250
0
  yr_set_integer(
4251
0
      IMAGE_SCN_CNT_INITIALIZED_DATA,
4252
0
      module_object,
4253
0
      "SECTION_CNT_INITIALIZED_DATA");
4254
0
  yr_set_integer(
4255
0
      IMAGE_SCN_CNT_UNINITIALIZED_DATA,
4256
0
      module_object,
4257
0
      "SECTION_CNT_UNINITIALIZED_DATA");
4258
0
  yr_set_integer(IMAGE_SCN_LNK_OTHER, module_object, "SECTION_LNK_OTHER");
4259
0
  yr_set_integer(IMAGE_SCN_LNK_INFO, module_object, "SECTION_LNK_INFO");
4260
0
  yr_set_integer(IMAGE_SCN_LNK_REMOVE, module_object, "SECTION_LNK_REMOVE");
4261
0
  yr_set_integer(IMAGE_SCN_LNK_COMDAT, module_object, "SECTION_LNK_COMDAT");
4262
0
  yr_set_integer(
4263
0
      IMAGE_SCN_NO_DEFER_SPEC_EXC, module_object, "SECTION_NO_DEFER_SPEC_EXC");
4264
0
  yr_set_integer(IMAGE_SCN_GPREL, module_object, "SECTION_GPREL");
4265
0
  yr_set_integer(IMAGE_SCN_MEM_FARDATA, module_object, "SECTION_MEM_FARDATA");
4266
0
  yr_set_integer(
4267
0
      IMAGE_SCN_MEM_PURGEABLE, module_object, "SECTION_MEM_PURGEABLE");
4268
0
  yr_set_integer(IMAGE_SCN_MEM_16BIT, module_object, "SECTION_MEM_16BIT");
4269
0
  yr_set_integer(IMAGE_SCN_MEM_LOCKED, module_object, "SECTION_MEM_LOCKED");
4270
0
  yr_set_integer(IMAGE_SCN_MEM_PRELOAD, module_object, "SECTION_MEM_PRELOAD");
4271
0
  yr_set_integer(IMAGE_SCN_ALIGN_1BYTES, module_object, "SECTION_ALIGN_1BYTES");
4272
0
  yr_set_integer(IMAGE_SCN_ALIGN_2BYTES, module_object, "SECTION_ALIGN_2BYTES");
4273
0
  yr_set_integer(IMAGE_SCN_ALIGN_4BYTES, module_object, "SECTION_ALIGN_4BYTES");
4274
0
  yr_set_integer(IMAGE_SCN_ALIGN_8BYTES, module_object, "SECTION_ALIGN_8BYTES");
4275
0
  yr_set_integer(
4276
0
      IMAGE_SCN_ALIGN_16BYTES, module_object, "SECTION_ALIGN_16BYTES");
4277
0
  yr_set_integer(
4278
0
      IMAGE_SCN_ALIGN_32BYTES, module_object, "SECTION_ALIGN_32BYTES");
4279
0
  yr_set_integer(
4280
0
      IMAGE_SCN_ALIGN_64BYTES, module_object, "SECTION_ALIGN_64BYTES");
4281
0
  yr_set_integer(
4282
0
      IMAGE_SCN_ALIGN_128BYTES, module_object, "SECTION_ALIGN_128BYTES");
4283
0
  yr_set_integer(
4284
0
      IMAGE_SCN_ALIGN_256BYTES, module_object, "SECTION_ALIGN_256BYTES");
4285
0
  yr_set_integer(
4286
0
      IMAGE_SCN_ALIGN_512BYTES, module_object, "SECTION_ALIGN_512BYTES");
4287
0
  yr_set_integer(
4288
0
      IMAGE_SCN_ALIGN_1024BYTES, module_object, "SECTION_ALIGN_1024BYTES");
4289
0
  yr_set_integer(
4290
0
      IMAGE_SCN_ALIGN_2048BYTES, module_object, "SECTION_ALIGN_2048BYTES");
4291
0
  yr_set_integer(
4292
0
      IMAGE_SCN_ALIGN_4096BYTES, module_object, "SECTION_ALIGN_4096BYTES");
4293
0
  yr_set_integer(
4294
0
      IMAGE_SCN_ALIGN_8192BYTES, module_object, "SECTION_ALIGN_8192BYTES");
4295
0
  yr_set_integer(IMAGE_SCN_ALIGN_MASK, module_object, "SECTION_ALIGN_MASK");
4296
0
  yr_set_integer(
4297
0
      IMAGE_SCN_LNK_NRELOC_OVFL, module_object, "SECTION_LNK_NRELOC_OVFL");
4298
0
  yr_set_integer(
4299
0
      IMAGE_SCN_MEM_DISCARDABLE, module_object, "SECTION_MEM_DISCARDABLE");
4300
0
  yr_set_integer(
4301
0
      IMAGE_SCN_MEM_NOT_CACHED, module_object, "SECTION_MEM_NOT_CACHED");
4302
0
  yr_set_integer(
4303
0
      IMAGE_SCN_MEM_NOT_PAGED, module_object, "SECTION_MEM_NOT_PAGED");
4304
0
  yr_set_integer(IMAGE_SCN_MEM_SHARED, module_object, "SECTION_MEM_SHARED");
4305
0
  yr_set_integer(IMAGE_SCN_MEM_EXECUTE, module_object, "SECTION_MEM_EXECUTE");
4306
0
  yr_set_integer(IMAGE_SCN_MEM_READ, module_object, "SECTION_MEM_READ");
4307
0
  yr_set_integer(IMAGE_SCN_MEM_WRITE, module_object, "SECTION_MEM_WRITE");
4308
0
  yr_set_integer(IMAGE_SCN_SCALE_INDEX, module_object, "SECTION_SCALE_INDEX");
4309
4310
0
  yr_set_integer(RESOURCE_TYPE_CURSOR, module_object, "RESOURCE_TYPE_CURSOR");
4311
0
  yr_set_integer(RESOURCE_TYPE_BITMAP, module_object, "RESOURCE_TYPE_BITMAP");
4312
0
  yr_set_integer(RESOURCE_TYPE_ICON, module_object, "RESOURCE_TYPE_ICON");
4313
0
  yr_set_integer(RESOURCE_TYPE_MENU, module_object, "RESOURCE_TYPE_MENU");
4314
0
  yr_set_integer(RESOURCE_TYPE_DIALOG, module_object, "RESOURCE_TYPE_DIALOG");
4315
0
  yr_set_integer(RESOURCE_TYPE_STRING, module_object, "RESOURCE_TYPE_STRING");
4316
0
  yr_set_integer(RESOURCE_TYPE_FONTDIR, module_object, "RESOURCE_TYPE_FONTDIR");
4317
0
  yr_set_integer(RESOURCE_TYPE_FONT, module_object, "RESOURCE_TYPE_FONT");
4318
0
  yr_set_integer(
4319
0
      RESOURCE_TYPE_ACCELERATOR, module_object, "RESOURCE_TYPE_ACCELERATOR");
4320
0
  yr_set_integer(RESOURCE_TYPE_RCDATA, module_object, "RESOURCE_TYPE_RCDATA");
4321
0
  yr_set_integer(
4322
0
      RESOURCE_TYPE_MESSAGETABLE, module_object, "RESOURCE_TYPE_MESSAGETABLE");
4323
0
  yr_set_integer(
4324
0
      RESOURCE_TYPE_GROUP_CURSOR, module_object, "RESOURCE_TYPE_GROUP_CURSOR");
4325
0
  yr_set_integer(
4326
0
      RESOURCE_TYPE_GROUP_ICON, module_object, "RESOURCE_TYPE_GROUP_ICON");
4327
0
  yr_set_integer(RESOURCE_TYPE_VERSION, module_object, "RESOURCE_TYPE_VERSION");
4328
0
  yr_set_integer(
4329
0
      RESOURCE_TYPE_DLGINCLUDE, module_object, "RESOURCE_TYPE_DLGINCLUDE");
4330
0
  yr_set_integer(
4331
0
      RESOURCE_TYPE_PLUGPLAY, module_object, "RESOURCE_TYPE_PLUGPLAY");
4332
0
  yr_set_integer(RESOURCE_TYPE_VXD, module_object, "RESOURCE_TYPE_VXD");
4333
0
  yr_set_integer(
4334
0
      RESOURCE_TYPE_ANICURSOR, module_object, "RESOURCE_TYPE_ANICURSOR");
4335
0
  yr_set_integer(RESOURCE_TYPE_ANIICON, module_object, "RESOURCE_TYPE_ANIICON");
4336
0
  yr_set_integer(RESOURCE_TYPE_HTML, module_object, "RESOURCE_TYPE_HTML");
4337
0
  yr_set_integer(
4338
0
      RESOURCE_TYPE_MANIFEST, module_object, "RESOURCE_TYPE_MANIFEST");
4339
4340
0
  yr_set_integer(
4341
0
      IMAGE_DEBUG_TYPE_UNKNOWN, module_object, "IMAGE_DEBUG_TYPE_UNKNOWN");
4342
0
  yr_set_integer(IMAGE_DEBUG_TYPE_COFF, module_object, "IMAGE_DEBUG_TYPE_COFF");
4343
0
  yr_set_integer(
4344
0
      IMAGE_DEBUG_TYPE_CODEVIEW, module_object, "IMAGE_DEBUG_TYPE_CODEVIEW");
4345
0
  yr_set_integer(IMAGE_DEBUG_TYPE_FPO, module_object, "IMAGE_DEBUG_TYPE_FPO");
4346
0
  yr_set_integer(IMAGE_DEBUG_TYPE_MISC, module_object, "IMAGE_DEBUG_TYPE_MISC");
4347
0
  yr_set_integer(
4348
0
      IMAGE_DEBUG_TYPE_EXCEPTION, module_object, "IMAGE_DEBUG_TYPE_EXCEPTION");
4349
0
  yr_set_integer(
4350
0
      IMAGE_DEBUG_TYPE_FIXUP, module_object, "IMAGE_DEBUG_TYPE_FIXUP");
4351
0
  yr_set_integer(
4352
0
      IMAGE_DEBUG_TYPE_OMAP_TO_SRC,
4353
0
      module_object,
4354
0
      "IMAGE_DEBUG_TYPE_OMAP_TO_SRC");
4355
0
  yr_set_integer(
4356
0
      IMAGE_DEBUG_TYPE_OMAP_FROM_SRC,
4357
0
      module_object,
4358
0
      "IMAGE_DEBUG_TYPE_OMAP_FROM_SRC");
4359
0
  yr_set_integer(
4360
0
      IMAGE_DEBUG_TYPE_BORLAND, module_object, "IMAGE_DEBUG_TYPE_BORLAND");
4361
0
  yr_set_integer(
4362
0
      IMAGE_DEBUG_TYPE_RESERVED10,
4363
0
      module_object,
4364
0
      "IMAGE_DEBUG_TYPE_RESERVED10");
4365
0
  yr_set_integer(
4366
0
      IMAGE_DEBUG_TYPE_CLSID, module_object, "IMAGE_DEBUG_TYPE_CLSID");
4367
0
  yr_set_integer(
4368
0
      IMAGE_DEBUG_TYPE_VC_FEATURE,
4369
0
      module_object,
4370
0
      "IMAGE_DEBUG_TYPE_VC_FEATURE");
4371
0
  yr_set_integer(IMAGE_DEBUG_TYPE_POGO, module_object, "IMAGE_DEBUG_TYPE_POGO");
4372
0
  yr_set_integer(
4373
0
      IMAGE_DEBUG_TYPE_ILTCG, module_object, "IMAGE_DEBUG_TYPE_ILTCG");
4374
0
  yr_set_integer(IMAGE_DEBUG_TYPE_MPX, module_object, "IMAGE_DEBUG_TYPE_MPX");
4375
0
  yr_set_integer(
4376
0
      IMAGE_DEBUG_TYPE_REPRO, module_object, "IMAGE_DEBUG_TYPE_REPRO");
4377
4378
0
  yr_set_integer(0, module_object, "is_pe");
4379
4380
0
  foreach_memory_block(iterator, block)
4381
0
  {
4382
0
    block_data = yr_fetch_block_data(block);
4383
4384
0
    if (block_data == NULL)
4385
0
      continue;
4386
4387
0
    pe_header = pe_get_header(block_data, block->size);
4388
4389
0
    if (pe_header != NULL)
4390
0
    {
4391
      // Ignore DLLs while scanning a process
4392
4393
0
      if (!(context->flags & SCAN_FLAGS_PROCESS_MEMORY) ||
4394
0
          !(yr_le16toh(pe_header->FileHeader.Characteristics) & IMAGE_FILE_DLL))
4395
0
      {
4396
0
        pe = (PE*) yr_malloc(sizeof(PE));
4397
4398
0
        if (pe == NULL)
4399
0
          return ERROR_INSUFFICIENT_MEMORY;
4400
4401
0
        FAIL_ON_ERROR_WITH_CLEANUP(
4402
0
            yr_hash_table_create(17, &pe->hash_table), yr_free(pe));
4403
4404
0
        pe->data = block_data;
4405
0
        pe->data_size = block->size;
4406
0
        pe->header = pe_header;
4407
0
        pe->object = module_object;
4408
0
        pe->resources = 0;
4409
0
        pe->version_infos = 0;
4410
4411
0
        module_object->data = pe;
4412
4413
0
        pe_parse_header(pe, block->base, context->flags);
4414
0
        pe_parse_rich_signature(pe, block->base);
4415
0
        pe_parse_debug_directory(pe);
4416
4417
#if defined(HAVE_LIBCRYPTO) && !defined(BORINGSSL)
4418
        pe_parse_certificates(pe);
4419
#endif
4420
4421
0
        pe->imported_dlls = pe_parse_imports(pe);
4422
0
        pe->delay_imported_dlls = pe_parse_delayed_imports(pe);
4423
0
        pe_parse_exports(pe);
4424
4425
0
        break;
4426
0
      }
4427
0
    }
4428
0
  }
4429
4430
0
  return ERROR_SUCCESS;
4431
0
}
4432
4433
void free_dlls(IMPORTED_DLL* dll)
4434
0
{
4435
0
  IMPORTED_DLL* next_dll = NULL;
4436
0
  IMPORT_FUNCTION* func = NULL;
4437
0
  IMPORT_FUNCTION* next_func = NULL;
4438
4439
0
  while (dll)
4440
0
  {
4441
0
    if (dll->name)
4442
0
      yr_free(dll->name);
4443
4444
0
    func = dll->functions;
4445
4446
0
    while (func)
4447
0
    {
4448
0
      if (func->name)
4449
0
        yr_free(func->name);
4450
4451
0
      next_func = func->next;
4452
0
      yr_free(func);
4453
0
      func = next_func;
4454
0
    }
4455
4456
0
    next_dll = dll->next;
4457
0
    yr_free(dll);
4458
0
    dll = next_dll;
4459
0
  }
4460
0
}
4461
4462
int module_unload(YR_OBJECT* module_object)
4463
0
{
4464
0
  PE* pe = (PE*) module_object->data;
4465
4466
0
  if (pe == NULL)
4467
0
    return ERROR_SUCCESS;
4468
4469
0
  if (pe->hash_table != NULL)
4470
0
    yr_hash_table_destroy(
4471
0
        pe->hash_table, (YR_HASH_TABLE_FREE_VALUE_FUNC) yr_free);
4472
4473
0
  free_dlls(pe->imported_dlls);
4474
0
  free_dlls(pe->delay_imported_dlls);
4475
4476
0
  yr_free(pe);
4477
4478
0
  return ERROR_SUCCESS;
4479
0
}