Coverage Report

Created: 2026-08-13 06:11

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
  yr_md5_init(&ctx);
2777
2778
  dll = pe->imported_dlls;
2779
2780
  while (dll)
2781
  {
2782
    IMPORT_FUNCTION* func;
2783
2784
    size_t dll_name_len;
2785
    char* dll_name;
2786
2787
    // If extension is 'ocx', 'sys' or 'dll', chop it.
2788
2789
    char* ext = strrchr(dll->name, '.');
2790
2791
    if (ext &&
2792
        (strncasecmp(ext, ".ocx", 4) == 0 || strncasecmp(ext, ".sys", 4) == 0 ||
2793
         strncasecmp(ext, ".dll", 4) == 0))
2794
    {
2795
      dll_name_len = (ext - dll->name);
2796
    }
2797
    else
2798
    {
2799
      dll_name_len = strlen(dll->name);
2800
    }
2801
2802
    // Allocate a new string to hold the dll name.
2803
2804
    dll_name = (char*) yr_malloc(dll_name_len + 1);
2805
2806
    if (!dll_name)
2807
      return ERROR_INSUFFICIENT_MEMORY;
2808
2809
    strlcpy(dll_name, dll->name, dll_name_len + 1);
2810
2811
    func = dll->functions;
2812
2813
    while (func)
2814
    {
2815
      char* final_name;
2816
      size_t final_name_len = dll_name_len + strlen(func->name) + 1;
2817
2818
      if (!first)
2819
        final_name_len++;  // Additional byte to accommodate the extra comma
2820
2821
      final_name = (char*) yr_malloc(final_name_len + 1);
2822
2823
      if (final_name == NULL)
2824
        break;
2825
2826
      sprintf(final_name, first ? "%s.%s" : ",%s.%s", dll_name, func->name);
2827
2828
      // Lowercase the whole thing.
2829
2830
      for (i = 0; i < final_name_len; i++)
2831
        final_name[i] = tolower((unsigned char) final_name[i]);
2832
2833
      yr_md5_update(&ctx, final_name, final_name_len);
2834
2835
      yr_free(final_name);
2836
2837
      func = func->next;
2838
      first = false;
2839
    }
2840
2841
    yr_free(dll_name);
2842
2843
    dll = dll->next;
2844
  }
2845
2846
  yr_md5_final(digest, &ctx);
2847
2848
  digest_ascii = (char*) yr_malloc(YR_MD5_LEN * 2 + 1);
2849
2850
  if (digest_ascii == NULL)
2851
    return ERROR_INSUFFICIENT_MEMORY;
2852
2853
  // Transform the binary digest to ascii
2854
2855
  for (i = 0; i < YR_MD5_LEN; i++)
2856
  {
2857
    sprintf(digest_ascii + (i * 2), "%02x", digest[i]);
2858
  }
2859
2860
  digest_ascii[YR_MD5_LEN * 2] = '\0';
2861
2862
  yr_hash_table_add(pe->hash_table, "imphash", NULL, digest_ascii);
2863
2864
  return_string(digest_ascii);
2865
}
2866
2867
#endif  // defined(HAVE_LIBCRYPTO) || defined(HAVE_WINCRYPT_H)
2868
2869
int64_t pe_imports_dll(IMPORTED_DLL* dll, char* dll_name)
2870
0
{
2871
0
  if (dll == NULL)
2872
0
    return 0;
2873
2874
0
  int64_t result = 0;
2875
2876
0
  for (; dll != NULL; dll = dll->next)
2877
0
  {
2878
0
    if (strcasecmp(dll->name, dll_name) == 0)
2879
0
    {
2880
0
      IMPORT_FUNCTION* fun = dll->functions;
2881
0
      for (; fun != NULL; fun = fun->next)
2882
0
      {
2883
0
        result++;
2884
0
      }
2885
0
    }
2886
0
  }
2887
2888
0
  return result;
2889
0
}
2890
2891
int64_t pe_imports(IMPORTED_DLL* dll, char* dll_name, char* fun_name)
2892
0
{
2893
0
  if (dll == NULL)
2894
0
    return 0;
2895
2896
0
  for (; dll != NULL; dll = dll->next)
2897
0
  {
2898
0
    if (strcasecmp(dll->name, dll_name) == 0)
2899
0
    {
2900
0
      IMPORT_FUNCTION* fun = dll->functions;
2901
0
      for (; fun != NULL; fun = fun->next)
2902
0
      {
2903
0
        if (strcasecmp(fun->name, fun_name) == 0)
2904
0
          return 1;
2905
0
      }
2906
0
    }
2907
0
  }
2908
2909
0
  return 0;
2910
0
}
2911
2912
int64_t pe_imports_regexp(
2913
    YR_SCAN_CONTEXT* context,
2914
    IMPORTED_DLL* dll,
2915
    RE* dll_name,
2916
    RE* fun_name)
2917
0
{
2918
0
  if (dll == NULL)
2919
0
    return 0;
2920
2921
0
  int64_t result = 0;
2922
2923
0
  for (; dll != NULL; dll = dll->next)
2924
0
  {
2925
0
    if (yr_re_match(context, dll_name, dll->name) > 0)
2926
0
    {
2927
0
      IMPORT_FUNCTION* fun = dll->functions;
2928
0
      for (; fun != NULL; fun = fun->next)
2929
0
      {
2930
0
        if (yr_re_match(context, fun_name, fun->name) > 0)
2931
0
          result++;
2932
0
      }
2933
0
    }
2934
0
  }
2935
2936
0
  return result;
2937
0
}
2938
2939
int64_t pe_imports_ordinal(IMPORTED_DLL* dll, char* dll_name, uint64_t ordinal)
2940
0
{
2941
0
  if (dll == NULL)
2942
0
    return 0;
2943
2944
0
  for (; dll != NULL; dll = dll->next)
2945
0
  {
2946
0
    if (strcasecmp(dll->name, dll_name) == 0)
2947
0
    {
2948
0
      IMPORT_FUNCTION* fun = dll->functions;
2949
0
      for (; fun != NULL; fun = fun->next)
2950
0
      {
2951
0
        if (fun->has_ordinal && fun->ordinal == ordinal)
2952
0
          return 1;
2953
0
      }
2954
0
    }
2955
0
  }
2956
2957
0
  return 0;
2958
0
}
2959
2960
define_function(imports_standard)
2961
0
{
2962
0
  char* dll_name = string_argument(1);
2963
0
  char* function_name = string_argument(2);
2964
2965
0
  YR_OBJECT* module = yr_module();
2966
0
  PE* pe = (PE*) module->data;
2967
2968
0
  if (!pe)
2969
0
    return_integer(YR_UNDEFINED);
2970
2971
0
  return_integer(pe_imports(pe->imported_dlls, dll_name, function_name));
2972
0
}
2973
2974
define_function(imports)
2975
0
{
2976
0
  int64_t flags = integer_argument(1);
2977
0
  char* dll_name = string_argument(2);
2978
0
  char* function_name = string_argument(3);
2979
2980
0
  YR_OBJECT* module = yr_module();
2981
0
  PE* pe = (PE*) module->data;
2982
2983
0
  if (!pe)
2984
0
    return_integer(YR_UNDEFINED);
2985
2986
0
  if (flags & IMPORT_STANDARD &&
2987
0
      pe_imports(pe->imported_dlls, dll_name, function_name))
2988
0
  {
2989
0
    return_integer(1);
2990
0
  }
2991
2992
0
  if (flags & IMPORT_DELAYED &&
2993
0
      pe_imports(pe->delay_imported_dlls, dll_name, function_name))
2994
0
  {
2995
0
    return_integer(1);
2996
0
  }
2997
2998
0
  return_integer(0);
2999
0
}
3000
3001
define_function(imports_standard_ordinal)
3002
0
{
3003
0
  char* dll_name = string_argument(1);
3004
0
  int64_t ordinal = integer_argument(2);
3005
3006
0
  YR_OBJECT* module = yr_module();
3007
0
  PE* pe = (PE*) module->data;
3008
3009
0
  if (!pe)
3010
0
    return_integer(YR_UNDEFINED);
3011
3012
0
  return_integer(pe_imports_ordinal(pe->imported_dlls, dll_name, ordinal))
3013
0
}
3014
3015
define_function(imports_ordinal)
3016
0
{
3017
0
  int64_t flags = integer_argument(1);
3018
0
  char* dll_name = string_argument(2);
3019
0
  int64_t ordinal = integer_argument(3);
3020
3021
0
  YR_OBJECT* module = yr_module();
3022
0
  PE* pe = (PE*) module->data;
3023
3024
0
  if (!pe)
3025
0
    return_integer(YR_UNDEFINED);
3026
3027
0
  if (flags & IMPORT_STANDARD &&
3028
0
      pe_imports_ordinal(pe->imported_dlls, dll_name, ordinal))
3029
0
  {
3030
0
    return_integer(1);
3031
0
  }
3032
3033
0
  if (flags & IMPORT_DELAYED &&
3034
0
      pe_imports_ordinal(pe->delay_imported_dlls, dll_name, ordinal))
3035
0
  {
3036
0
    return_integer(1);
3037
0
  }
3038
3039
0
  return_integer(0);
3040
0
}
3041
3042
define_function(imports_standard_regex)
3043
0
{
3044
0
  RE* dll_name = regexp_argument(1);
3045
0
  RE* function_name = regexp_argument(2);
3046
3047
0
  YR_OBJECT* module = yr_module();
3048
0
  PE* pe = (PE*) module->data;
3049
3050
0
  if (!pe)
3051
0
    return_integer(YR_UNDEFINED);
3052
3053
0
  return_integer(pe_imports_regexp(
3054
0
      yr_scan_context(), pe->imported_dlls, dll_name, function_name))
3055
0
}
3056
3057
define_function(imports_regex)
3058
0
{
3059
0
  int64_t flags = integer_argument(1);
3060
0
  RE* dll_name = regexp_argument(2);
3061
0
  RE* function_name = regexp_argument(3);
3062
3063
0
  YR_OBJECT* module = yr_module();
3064
0
  PE* pe = (PE*) module->data;
3065
3066
0
  if (!pe)
3067
0
    return_integer(YR_UNDEFINED);
3068
3069
0
  int64_t result = 0;
3070
3071
0
  if (flags & IMPORT_STANDARD)
3072
0
    result += pe_imports_regexp(
3073
0
        yr_scan_context(), pe->imported_dlls, dll_name, function_name);
3074
3075
0
  if (flags & IMPORT_DELAYED)
3076
0
    result += pe_imports_regexp(
3077
0
        yr_scan_context(), pe->delay_imported_dlls, dll_name, function_name);
3078
3079
0
  return_integer(result);
3080
0
}
3081
3082
define_function(imports_standard_dll)
3083
0
{
3084
0
  char* dll_name = string_argument(1);
3085
3086
0
  YR_OBJECT* module = yr_module();
3087
0
  PE* pe = (PE*) module->data;
3088
3089
0
  if (!pe)
3090
0
    return_integer(YR_UNDEFINED);
3091
3092
0
  return_integer(pe_imports_dll(pe->imported_dlls, dll_name));
3093
0
}
3094
3095
define_function(imports_dll)
3096
0
{
3097
0
  int64_t flags = integer_argument(1);
3098
0
  char* dll_name = string_argument(2);
3099
3100
0
  YR_OBJECT* module = yr_module();
3101
0
  PE* pe = (PE*) module->data;
3102
3103
0
  if (!pe)
3104
0
    return_integer(YR_UNDEFINED);
3105
3106
0
  int64_t result = 0;
3107
3108
0
  if (flags & IMPORT_STANDARD)
3109
0
    result += pe_imports_dll(pe->imported_dlls, dll_name);
3110
3111
0
  if (flags & IMPORT_DELAYED)
3112
0
    result += pe_imports_dll(pe->delay_imported_dlls, dll_name);
3113
3114
0
  return_integer(result);
3115
0
}
3116
3117
define_function(import_rva)
3118
0
{
3119
0
  SIZED_STRING* in_dll_name = sized_string_argument(1);
3120
0
  SIZED_STRING* in_function_name = sized_string_argument(2);
3121
3122
0
  SIZED_STRING* dll_name;
3123
0
  SIZED_STRING* function_name;
3124
0
  YR_OBJECT* module = yr_module();
3125
0
  PE* pe = (PE*) module->data;
3126
3127
0
  if (!pe)
3128
0
    return_integer(YR_UNDEFINED);
3129
3130
0
  int64_t num_imports = yr_get_integer(pe->object, "number_of_imports");
3131
0
  if (IS_UNDEFINED(num_imports))
3132
0
    return_integer(YR_UNDEFINED);
3133
3134
0
  for (int i = 0; i < num_imports; i++)
3135
0
  {
3136
0
    dll_name = yr_get_string(module, "import_details[%i].library_name", i);
3137
0
    if (dll_name == NULL || IS_UNDEFINED(dll_name) ||
3138
0
        ss_icompare(in_dll_name, dll_name) != 0)
3139
0
      continue;
3140
3141
0
    int64_t num_functions = yr_get_integer(
3142
0
        module, "import_details[%i].number_of_functions", i);
3143
0
    if (IS_UNDEFINED(num_functions))
3144
0
      return_integer(YR_UNDEFINED);
3145
3146
0
    for (int j = 0; j < num_functions; j++)
3147
0
    {
3148
0
      function_name = yr_get_string(
3149
0
          module, "import_details[%i].functions[%i].name", i, j);
3150
0
      if (function_name == NULL || IS_UNDEFINED(function_name))
3151
0
        continue;
3152
3153
0
      if (ss_icompare(in_function_name, function_name) == 0)
3154
0
        return_integer(yr_get_integer(
3155
0
            module, "import_details[%i].functions[%i].rva", i, j));
3156
0
    }
3157
0
  }
3158
3159
0
  return_integer(YR_UNDEFINED);
3160
0
}
3161
3162
define_function(import_rva_ordinal)
3163
0
{
3164
0
  SIZED_STRING* in_dll_name = sized_string_argument(1);
3165
0
  int64_t in_ordinal = integer_argument(2);
3166
3167
0
  SIZED_STRING* dll_name;
3168
0
  int64_t ordinal;
3169
0
  YR_OBJECT* module = yr_module();
3170
0
  PE* pe = (PE*) module->data;
3171
3172
0
  if (!pe)
3173
0
    return_integer(YR_UNDEFINED);
3174
3175
0
  int64_t num_imports = yr_get_integer(pe->object, "number_of_imports");
3176
0
  if (IS_UNDEFINED(num_imports))
3177
0
    return_integer(YR_UNDEFINED);
3178
3179
0
  for (int i = 0; i < num_imports; i++)
3180
0
  {
3181
0
    dll_name = yr_get_string(module, "import_details[%i].library_name", i);
3182
0
    if (dll_name == NULL || IS_UNDEFINED(dll_name) ||
3183
0
        ss_icompare(in_dll_name, dll_name) != 0)
3184
0
      continue;
3185
3186
0
    int64_t num_functions = yr_get_integer(
3187
0
        module, "import_details[%i].number_of_functions", i);
3188
0
    if (IS_UNDEFINED(num_functions))
3189
0
      return_integer(YR_UNDEFINED);
3190
3191
0
    for (int j = 0; j < num_functions; j++)
3192
0
    {
3193
0
      ordinal = yr_get_integer(
3194
0
          module, "import_details[%i].functions[%i].ordinal", i, j);
3195
0
      if (IS_UNDEFINED(ordinal))
3196
0
        continue;
3197
3198
0
      if (ordinal == in_ordinal)
3199
0
        return_integer(yr_get_integer(
3200
0
            module, "import_details[%i].functions[%i].rva", i, j));
3201
0
    }
3202
0
  }
3203
3204
0
  return_integer(YR_UNDEFINED);
3205
0
}
3206
3207
define_function(delayed_import_rva)
3208
0
{
3209
0
  SIZED_STRING* in_dll_name = sized_string_argument(1);
3210
0
  SIZED_STRING* in_function_name = sized_string_argument(2);
3211
3212
0
  SIZED_STRING* dll_name;
3213
0
  SIZED_STRING* function_name;
3214
0
  YR_OBJECT* module = yr_module();
3215
0
  PE* pe = (PE*) module->data;
3216
3217
0
  if (!pe)
3218
0
    return_integer(YR_UNDEFINED);
3219
3220
0
  int64_t num_imports = yr_get_integer(pe->object, "number_of_delayed_imports");
3221
3222
0
  if (IS_UNDEFINED(num_imports))
3223
0
    return_integer(YR_UNDEFINED);
3224
3225
0
  for (int i = 0; i < num_imports; i++)
3226
0
  {
3227
0
    dll_name = yr_get_string(
3228
0
        module, "delayed_import_details[%i].library_name", i);
3229
3230
0
    if (dll_name == NULL || IS_UNDEFINED(dll_name) ||
3231
0
        ss_icompare(in_dll_name, dll_name) != 0)
3232
0
      continue;
3233
3234
0
    int64_t num_functions = yr_get_integer(
3235
0
        module, "delayed_import_details[%i].number_of_functions", i);
3236
3237
0
    if (IS_UNDEFINED(num_functions))
3238
0
      return_integer(YR_UNDEFINED);
3239
3240
0
    for (int j = 0; j < num_functions; j++)
3241
0
    {
3242
0
      function_name = yr_get_string(
3243
0
          module, "delayed_import_details[%i].functions[%i].name", i, j);
3244
3245
0
      if (function_name == NULL || IS_UNDEFINED(function_name))
3246
0
        continue;
3247
3248
0
      if (ss_icompare(in_function_name, function_name) == 0)
3249
0
        return_integer(yr_get_integer(
3250
0
            module, "delayed_import_details[%i].functions[%i].rva", i, j));
3251
0
    }
3252
0
  }
3253
3254
0
  return_integer(YR_UNDEFINED);
3255
0
}
3256
3257
define_function(delayed_import_rva_ordinal)
3258
0
{
3259
0
  SIZED_STRING* in_dll_name = sized_string_argument(1);
3260
0
  int64_t in_ordinal = integer_argument(2);
3261
3262
0
  SIZED_STRING* dll_name;
3263
0
  int64_t ordinal;
3264
0
  YR_OBJECT* module = yr_module();
3265
0
  PE* pe = (PE*) module->data;
3266
3267
0
  if (!pe)
3268
0
    return_integer(YR_UNDEFINED);
3269
3270
0
  int64_t num_imports = yr_get_integer(pe->object, "number_of_delayed_imports");
3271
0
  if (IS_UNDEFINED(num_imports))
3272
0
    return_integer(YR_UNDEFINED);
3273
3274
0
  for (int i = 0; i < num_imports; i++)
3275
0
  {
3276
0
    dll_name = yr_get_string(
3277
0
        module, "delayed_import_details[%i].library_name", i);
3278
3279
0
    if (dll_name == NULL || IS_UNDEFINED(dll_name) ||
3280
0
        ss_icompare(in_dll_name, dll_name) != 0)
3281
0
      continue;
3282
3283
0
    int64_t num_functions = yr_get_integer(
3284
0
        module, "delayed_import_details[%i].number_of_functions", i);
3285
3286
0
    if (IS_UNDEFINED(num_functions))
3287
0
      return_integer(YR_UNDEFINED);
3288
3289
0
    for (int j = 0; j < num_functions; j++)
3290
0
    {
3291
0
      ordinal = yr_get_integer(
3292
0
          module, "delayed_import_details[%i].functions[%i].ordinal", i, j);
3293
3294
0
      if (IS_UNDEFINED(ordinal))
3295
0
        continue;
3296
3297
0
      if (ordinal == in_ordinal)
3298
0
        return_integer(yr_get_integer(
3299
0
            module, "delayed_import_details[%i].functions[%i].rva", i, j));
3300
0
    }
3301
0
  }
3302
3303
0
  return_integer(YR_UNDEFINED);
3304
0
}
3305
3306
define_function(locale)
3307
0
{
3308
0
  YR_OBJECT* module = yr_module();
3309
0
  PE* pe = (PE*) module->data;
3310
3311
0
  uint64_t locale = integer_argument(1);
3312
3313
0
  if (yr_is_undefined(module, "number_of_resources"))
3314
0
    return_integer(YR_UNDEFINED);
3315
3316
  // If not a PE file, return YR_UNDEFINED
3317
3318
0
  if (pe == NULL)
3319
0
    return_integer(YR_UNDEFINED);
3320
3321
0
  int n = (int) yr_get_integer(module, "number_of_resources");
3322
3323
0
  for (int i = 0; i < n; i++)
3324
0
  {
3325
0
    uint64_t rsrc_language = yr_get_integer(
3326
0
        module, "resources[%i].language", i);
3327
3328
0
    if ((rsrc_language & 0xFFFF) == locale)
3329
0
      return_integer(1);
3330
0
  }
3331
3332
0
  return_integer(0);
3333
0
}
3334
3335
define_function(language)
3336
0
{
3337
0
  YR_OBJECT* module = yr_module();
3338
0
  PE* pe = (PE*) module->data;
3339
3340
0
  uint64_t language = integer_argument(1);
3341
3342
0
  if (yr_is_undefined(module, "number_of_resources"))
3343
0
    return_integer(YR_UNDEFINED);
3344
3345
  // If not a PE file, return YR_UNDEFINED
3346
3347
0
  if (pe == NULL)
3348
0
    return_integer(YR_UNDEFINED);
3349
3350
0
  int n = (int) yr_get_integer(module, "number_of_resources");
3351
3352
0
  for (int i = 0; i < n; i++)
3353
0
  {
3354
0
    uint64_t rsrc_language = yr_get_integer(
3355
0
        module, "resources[%i].language", i);
3356
3357
0
    if ((rsrc_language & 0xFF) == language)
3358
0
      return_integer(1);
3359
0
  }
3360
3361
0
  return_integer(0);
3362
0
}
3363
3364
define_function(is_dll)
3365
0
{
3366
0
  int64_t characteristics;
3367
0
  YR_OBJECT* module = yr_module();
3368
3369
0
  if (yr_is_undefined(module, "characteristics"))
3370
0
    return_integer(YR_UNDEFINED);
3371
3372
0
  characteristics = yr_get_integer(module, "characteristics");
3373
0
  return_integer(characteristics & IMAGE_FILE_DLL);
3374
0
}
3375
3376
define_function(is_32bit)
3377
0
{
3378
0
  YR_OBJECT* module = yr_module();
3379
0
  PE* pe = (PE*) module->data;
3380
3381
0
  if (pe == NULL)
3382
0
    return_integer(YR_UNDEFINED);
3383
3384
0
  return_integer(IS_64BITS_PE(pe) ? 0 : 1);
3385
0
}
3386
3387
define_function(is_64bit)
3388
0
{
3389
0
  YR_OBJECT* module = yr_module();
3390
0
  PE* pe = (PE*) module->data;
3391
3392
0
  if (pe == NULL)
3393
0
    return_integer(YR_UNDEFINED);
3394
3395
0
  return_integer(IS_64BITS_PE(pe) ? 1 : 0);
3396
0
}
3397
3398
// _rich_version
3399
//
3400
// Returns the number of rich signatures that match the specified version and
3401
// toolid numbers.
3402
//
3403
static int64_t _rich_version(
3404
    YR_OBJECT* module,
3405
    uint64_t version,
3406
    uint64_t toolid)
3407
0
{
3408
0
  int64_t rich_length;
3409
0
  int64_t rich_count;
3410
3411
0
  PRICH_SIGNATURE clear_rich_signature;
3412
0
  SIZED_STRING* rich_string;
3413
3414
0
  int64_t result = 0;
3415
3416
  // Check if the required fields are set
3417
0
  if (yr_is_undefined(module, "rich_signature.length"))
3418
0
    return YR_UNDEFINED;
3419
3420
0
  rich_length = yr_get_integer(module, "rich_signature.length");
3421
0
  rich_string = yr_get_string(module, "rich_signature.clear_data");
3422
3423
  // If clear_data was not set, return YR_UNDEFINED
3424
0
  if (rich_string == NULL)
3425
0
    return YR_UNDEFINED;
3426
3427
  // File e77b007c9a964411c5e33afeec18be32c86963b78f3c3e906b28fcf1382f46c3
3428
  // has a Rich header of length 8, which is smaller than RICH_SIGNATURE and
3429
  // causes a crash.
3430
0
  if (rich_length < sizeof(RICH_SIGNATURE))
3431
0
    return YR_UNDEFINED;
3432
3433
0
  if (version == YR_UNDEFINED && toolid == YR_UNDEFINED)
3434
0
    return 0;
3435
3436
0
  clear_rich_signature = (PRICH_SIGNATURE) rich_string->c_string;
3437
3438
  // Loop over the versions in the rich signature
3439
0
  rich_count = (rich_length - sizeof(RICH_SIGNATURE)) /
3440
0
               sizeof(RICH_VERSION_INFO);
3441
3442
0
  for (int i = 0; i < rich_count; i++)
3443
0
  {
3444
0
    DWORD id_version = yr_le32toh(clear_rich_signature->versions[i].id_version);
3445
3446
0
    int match_version = (version == RICH_VERSION_VERSION(id_version));
3447
0
    int match_toolid = (toolid == RICH_VERSION_ID(id_version));
3448
3449
0
    if ((version == YR_UNDEFINED || match_version) &&
3450
0
        (toolid == YR_UNDEFINED || match_toolid))
3451
0
    {
3452
0
      result += yr_le32toh(clear_rich_signature->versions[i].times);
3453
0
    }
3454
0
  }
3455
3456
0
  return result;
3457
0
}
3458
3459
define_function(rich_version)
3460
0
{
3461
0
  return_integer(_rich_version(yr_module(), integer_argument(1), YR_UNDEFINED));
3462
0
}
3463
3464
define_function(rich_version_toolid)
3465
0
{
3466
0
  return_integer(
3467
0
      _rich_version(yr_module(), integer_argument(1), integer_argument(2)));
3468
0
}
3469
3470
define_function(rich_toolid)
3471
0
{
3472
0
  return_integer(_rich_version(yr_module(), YR_UNDEFINED, integer_argument(1)));
3473
0
}
3474
3475
define_function(rich_toolid_version)
3476
0
{
3477
0
  return_integer(
3478
0
      _rich_version(yr_module(), integer_argument(2), integer_argument(1)));
3479
0
}
3480
3481
define_function(calculate_checksum)
3482
0
{
3483
0
  YR_OBJECT* module = yr_module();
3484
0
  PE* pe = (PE*) module->data;
3485
3486
0
  uint64_t csum = 0;
3487
0
  size_t csum_offset;
3488
3489
0
  if (pe == NULL)
3490
0
    return_integer(YR_UNDEFINED);
3491
3492
0
  csum_offset = ((uint8_t*) &(pe->header->OptionalHeader) +
3493
0
                 offsetof(IMAGE_OPTIONAL_HEADER32, CheckSum)) -
3494
0
                pe->data;
3495
3496
0
  for (size_t i = 0; i <= pe->data_size / 4; i++)
3497
0
  {
3498
    // Treat the CheckSum field as 0 -- the offset is the same for
3499
    // PE32 and PE64.
3500
3501
0
    if (4 * i == csum_offset)
3502
0
      continue;
3503
3504
0
    if (4 * i + 4 <= pe->data_size)
3505
0
    {
3506
0
      csum +=
3507
0
          ((uint64_t) pe->data[4 * i] + ((uint64_t) pe->data[4 * i + 1] << 8) +
3508
0
           ((uint64_t) pe->data[4 * i + 2] << 16) +
3509
0
           ((uint64_t) pe->data[4 * i + 3] << 24));
3510
0
    }
3511
0
    else
3512
0
    {
3513
0
      for (size_t j = 0; j < pe->data_size % 4; j++)
3514
0
        csum += (uint64_t) pe->data[4 * i + j] << (8 * j);
3515
0
    }
3516
3517
0
    if (csum > 0xffffffff)
3518
0
      csum = (csum & 0xffffffff) + (csum >> 32);
3519
0
  }
3520
3521
0
  csum = (csum & 0xffff) + (csum >> 16);
3522
0
  csum += (csum >> 16);
3523
0
  csum &= 0xffff;
3524
0
  csum += pe->data_size;
3525
3526
0
  return_integer(csum);
3527
0
}
3528
3529
define_function(rva_to_offset)
3530
0
{
3531
0
  YR_OBJECT* module = yr_module();
3532
0
  PE* pe = (PE*) module->data;
3533
3534
0
  uint64_t rva;
3535
0
  int64_t offset;
3536
3537
0
  if (pe == NULL)
3538
0
    return_integer(YR_UNDEFINED);
3539
3540
0
  rva = integer_argument(1);
3541
0
  offset = pe_rva_to_offset(pe, rva);
3542
3543
0
  if (offset == -1)
3544
0
    return_integer(YR_UNDEFINED);
3545
3546
0
  return_integer(offset);
3547
0
}
3548
3549
1
begin_declarations
3550
1
  declare_integer("MACHINE_UNKNOWN");
3551
1
  declare_integer("MACHINE_AM33");
3552
1
  declare_integer("MACHINE_AMD64");
3553
1
  declare_integer("MACHINE_ARM");
3554
1
  declare_integer("MACHINE_ARMNT");
3555
1
  declare_integer("MACHINE_ARM64");
3556
1
  declare_integer("MACHINE_EBC");
3557
1
  declare_integer("MACHINE_I386");
3558
1
  declare_integer("MACHINE_IA64");
3559
1
  declare_integer("MACHINE_M32R");
3560
1
  declare_integer("MACHINE_MIPS16");
3561
1
  declare_integer("MACHINE_MIPSFPU");
3562
1
  declare_integer("MACHINE_MIPSFPU16");
3563
1
  declare_integer("MACHINE_POWERPC");
3564
1
  declare_integer("MACHINE_POWERPCFP");
3565
1
  declare_integer("MACHINE_R4000");
3566
1
  declare_integer("MACHINE_SH3");
3567
1
  declare_integer("MACHINE_SH3DSP");
3568
1
  declare_integer("MACHINE_SH4");
3569
1
  declare_integer("MACHINE_SH5");
3570
1
  declare_integer("MACHINE_THUMB");
3571
1
  declare_integer("MACHINE_WCEMIPSV2");
3572
1
  declare_integer("MACHINE_TARGET_HOST");
3573
1
  declare_integer("MACHINE_R3000");
3574
1
  declare_integer("MACHINE_R10000");
3575
1
  declare_integer("MACHINE_ALPHA");
3576
1
  declare_integer("MACHINE_SH3E");
3577
1
  declare_integer("MACHINE_ALPHA64");
3578
1
  declare_integer("MACHINE_AXP64");
3579
1
  declare_integer("MACHINE_TRICORE");
3580
1
  declare_integer("MACHINE_CEF");
3581
1
  declare_integer("MACHINE_CEE");
3582
3583
1
  declare_integer("SUBSYSTEM_UNKNOWN");
3584
1
  declare_integer("SUBSYSTEM_NATIVE");
3585
1
  declare_integer("SUBSYSTEM_WINDOWS_GUI");
3586
1
  declare_integer("SUBSYSTEM_WINDOWS_CUI");
3587
1
  declare_integer("SUBSYSTEM_OS2_CUI");
3588
1
  declare_integer("SUBSYSTEM_POSIX_CUI");
3589
1
  declare_integer("SUBSYSTEM_NATIVE_WINDOWS");
3590
1
  declare_integer("SUBSYSTEM_WINDOWS_CE_GUI");
3591
1
  declare_integer("SUBSYSTEM_EFI_APPLICATION");
3592
1
  declare_integer("SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER");
3593
1
  declare_integer("SUBSYSTEM_EFI_RUNTIME_DRIVER");
3594
1
  declare_integer("SUBSYSTEM_EFI_ROM_IMAGE");
3595
1
  declare_integer("SUBSYSTEM_XBOX");
3596
1
  declare_integer("SUBSYSTEM_WINDOWS_BOOT_APPLICATION");
3597
3598
1
  declare_integer("HIGH_ENTROPY_VA");
3599
1
  declare_integer("DYNAMIC_BASE");
3600
1
  declare_integer("FORCE_INTEGRITY");
3601
1
  declare_integer("NX_COMPAT");
3602
1
  declare_integer("NO_ISOLATION");
3603
1
  declare_integer("NO_SEH");
3604
1
  declare_integer("NO_BIND");
3605
1
  declare_integer("APPCONTAINER");
3606
1
  declare_integer("WDM_DRIVER");
3607
1
  declare_integer("GUARD_CF");
3608
1
  declare_integer("TERMINAL_SERVER_AWARE");
3609
3610
1
  declare_integer("RELOCS_STRIPPED");
3611
1
  declare_integer("EXECUTABLE_IMAGE");
3612
1
  declare_integer("LINE_NUMS_STRIPPED");
3613
1
  declare_integer("LOCAL_SYMS_STRIPPED");
3614
1
  declare_integer("AGGRESIVE_WS_TRIM");
3615
1
  declare_integer("LARGE_ADDRESS_AWARE");
3616
1
  declare_integer("BYTES_REVERSED_LO");
3617
1
  declare_integer("MACHINE_32BIT");
3618
1
  declare_integer("DEBUG_STRIPPED");
3619
1
  declare_integer("REMOVABLE_RUN_FROM_SWAP");
3620
1
  declare_integer("NET_RUN_FROM_SWAP");
3621
1
  declare_integer("SYSTEM");
3622
1
  declare_integer("DLL");
3623
1
  declare_integer("UP_SYSTEM_ONLY");
3624
1
  declare_integer("BYTES_REVERSED_HI");
3625
3626
1
  declare_integer("IMAGE_DIRECTORY_ENTRY_EXPORT");
3627
1
  declare_integer("IMAGE_DIRECTORY_ENTRY_IMPORT");
3628
1
  declare_integer("IMAGE_DIRECTORY_ENTRY_RESOURCE");
3629
1
  declare_integer("IMAGE_DIRECTORY_ENTRY_EXCEPTION");
3630
1
  declare_integer("IMAGE_DIRECTORY_ENTRY_SECURITY");
3631
1
  declare_integer("IMAGE_DIRECTORY_ENTRY_BASERELOC");
3632
1
  declare_integer("IMAGE_DIRECTORY_ENTRY_DEBUG");
3633
1
  declare_integer("IMAGE_DIRECTORY_ENTRY_ARCHITECTURE");
3634
1
  declare_integer("IMAGE_DIRECTORY_ENTRY_COPYRIGHT");
3635
1
  declare_integer("IMAGE_DIRECTORY_ENTRY_GLOBALPTR");
3636
1
  declare_integer("IMAGE_DIRECTORY_ENTRY_TLS");
3637
1
  declare_integer("IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG");
3638
1
  declare_integer("IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT");
3639
1
  declare_integer("IMAGE_DIRECTORY_ENTRY_IAT");
3640
1
  declare_integer("IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT");
3641
1
  declare_integer("IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR");
3642
3643
1
  declare_integer("IMAGE_NT_OPTIONAL_HDR32_MAGIC");
3644
1
  declare_integer("IMAGE_NT_OPTIONAL_HDR64_MAGIC");
3645
1
  declare_integer("IMAGE_ROM_OPTIONAL_HDR_MAGIC");
3646
3647
1
  declare_integer("SECTION_NO_PAD");
3648
1
  declare_integer("SECTION_CNT_CODE");
3649
1
  declare_integer("SECTION_CNT_INITIALIZED_DATA");
3650
1
  declare_integer("SECTION_CNT_UNINITIALIZED_DATA");
3651
1
  declare_integer("SECTION_LNK_OTHER");
3652
1
  declare_integer("SECTION_LNK_INFO");
3653
1
  declare_integer("SECTION_LNK_REMOVE");
3654
1
  declare_integer("SECTION_LNK_COMDAT");
3655
1
  declare_integer("SECTION_NO_DEFER_SPEC_EXC");
3656
1
  declare_integer("SECTION_GPREL");
3657
1
  declare_integer("SECTION_MEM_FARDATA");
3658
1
  declare_integer("SECTION_MEM_PURGEABLE");
3659
1
  declare_integer("SECTION_MEM_16BIT");
3660
1
  declare_integer("SECTION_MEM_LOCKED");
3661
1
  declare_integer("SECTION_MEM_PRELOAD");
3662
1
  declare_integer("SECTION_ALIGN_1BYTES");
3663
1
  declare_integer("SECTION_ALIGN_2BYTES");
3664
1
  declare_integer("SECTION_ALIGN_4BYTES");
3665
1
  declare_integer("SECTION_ALIGN_8BYTES");
3666
1
  declare_integer("SECTION_ALIGN_16BYTES");
3667
1
  declare_integer("SECTION_ALIGN_32BYTES");
3668
1
  declare_integer("SECTION_ALIGN_64BYTES");
3669
1
  declare_integer("SECTION_ALIGN_128BYTES");
3670
1
  declare_integer("SECTION_ALIGN_256BYTES");
3671
1
  declare_integer("SECTION_ALIGN_512BYTES");
3672
1
  declare_integer("SECTION_ALIGN_1024BYTES");
3673
1
  declare_integer("SECTION_ALIGN_2048BYTES");
3674
1
  declare_integer("SECTION_ALIGN_4096BYTES");
3675
1
  declare_integer("SECTION_ALIGN_8192BYTES");
3676
1
  declare_integer("SECTION_ALIGN_MASK");
3677
1
  declare_integer("SECTION_LNK_NRELOC_OVFL");
3678
1
  declare_integer("SECTION_MEM_DISCARDABLE");
3679
1
  declare_integer("SECTION_MEM_NOT_CACHED");
3680
1
  declare_integer("SECTION_MEM_NOT_PAGED");
3681
1
  declare_integer("SECTION_MEM_SHARED");
3682
1
  declare_integer("SECTION_MEM_EXECUTE");
3683
1
  declare_integer("SECTION_MEM_READ");
3684
1
  declare_integer("SECTION_MEM_WRITE");
3685
1
  declare_integer("SECTION_SCALE_INDEX");
3686
3687
1
  declare_integer("RESOURCE_TYPE_CURSOR");
3688
1
  declare_integer("RESOURCE_TYPE_BITMAP");
3689
1
  declare_integer("RESOURCE_TYPE_ICON");
3690
1
  declare_integer("RESOURCE_TYPE_MENU");
3691
1
  declare_integer("RESOURCE_TYPE_DIALOG");
3692
1
  declare_integer("RESOURCE_TYPE_STRING");
3693
1
  declare_integer("RESOURCE_TYPE_FONTDIR");
3694
1
  declare_integer("RESOURCE_TYPE_FONT");
3695
1
  declare_integer("RESOURCE_TYPE_ACCELERATOR");
3696
1
  declare_integer("RESOURCE_TYPE_RCDATA");
3697
1
  declare_integer("RESOURCE_TYPE_MESSAGETABLE");
3698
1
  declare_integer("RESOURCE_TYPE_GROUP_CURSOR");
3699
1
  declare_integer("RESOURCE_TYPE_GROUP_ICON");
3700
1
  declare_integer("RESOURCE_TYPE_VERSION");
3701
1
  declare_integer("RESOURCE_TYPE_DLGINCLUDE");
3702
1
  declare_integer("RESOURCE_TYPE_PLUGPLAY");
3703
1
  declare_integer("RESOURCE_TYPE_VXD");
3704
1
  declare_integer("RESOURCE_TYPE_ANICURSOR");
3705
1
  declare_integer("RESOURCE_TYPE_ANIICON");
3706
1
  declare_integer("RESOURCE_TYPE_HTML");
3707
1
  declare_integer("RESOURCE_TYPE_MANIFEST");
3708
3709
1
  declare_integer("IMAGE_DEBUG_TYPE_UNKNOWN");
3710
1
  declare_integer("IMAGE_DEBUG_TYPE_COFF");
3711
1
  declare_integer("IMAGE_DEBUG_TYPE_CODEVIEW");
3712
1
  declare_integer("IMAGE_DEBUG_TYPE_FPO");
3713
1
  declare_integer("IMAGE_DEBUG_TYPE_MISC");
3714
1
  declare_integer("IMAGE_DEBUG_TYPE_EXCEPTION");
3715
1
  declare_integer("IMAGE_DEBUG_TYPE_FIXUP");
3716
1
  declare_integer("IMAGE_DEBUG_TYPE_OMAP_TO_SRC");
3717
1
  declare_integer("IMAGE_DEBUG_TYPE_OMAP_FROM_SRC");
3718
1
  declare_integer("IMAGE_DEBUG_TYPE_BORLAND");
3719
1
  declare_integer("IMAGE_DEBUG_TYPE_RESERVED10");
3720
1
  declare_integer("IMAGE_DEBUG_TYPE_CLSID");
3721
1
  declare_integer("IMAGE_DEBUG_TYPE_VC_FEATURE");
3722
1
  declare_integer("IMAGE_DEBUG_TYPE_POGO");
3723
1
  declare_integer("IMAGE_DEBUG_TYPE_ILTCG");
3724
1
  declare_integer("IMAGE_DEBUG_TYPE_MPX");
3725
1
  declare_integer("IMAGE_DEBUG_TYPE_REPRO");
3726
3727
1
  declare_integer("IMPORT_DELAYED");
3728
1
  declare_integer("IMPORT_STANDARD");
3729
1
  declare_integer("IMPORT_ANY");
3730
3731
1
  declare_integer("is_pe");
3732
1
  declare_integer("machine");
3733
1
  declare_integer("number_of_sections");
3734
1
  declare_integer("timestamp");
3735
1
  declare_integer("pointer_to_symbol_table");
3736
1
  declare_integer("number_of_symbols");
3737
1
  declare_integer("size_of_optional_header");
3738
1
  declare_integer("characteristics");
3739
3740
1
  declare_integer("entry_point");
3741
1
  declare_integer("entry_point_raw");
3742
1
  declare_integer("image_base");
3743
1
  declare_integer("number_of_rva_and_sizes");
3744
1
  declare_integer("number_of_version_infos");
3745
3746
2
  declare_string_dictionary("version_info");
3747
3748
3
  begin_struct_array("version_info_list")
3749
1
    declare_string("key");
3750
1
    declare_string("value");
3751
2
  end_struct_array("version_info_list");
3752
3753
2
  declare_integer("opthdr_magic");
3754
1
  declare_integer("size_of_code");
3755
1
  declare_integer("size_of_initialized_data");
3756
1
  declare_integer("size_of_uninitialized_data");
3757
1
  declare_integer("base_of_code");
3758
1
  declare_integer("base_of_data");
3759
1
  declare_integer("section_alignment");
3760
1
  declare_integer("file_alignment");
3761
3762
2
  begin_struct("linker_version")
3763
1
    declare_integer("major");
3764
1
    declare_integer("minor");
3765
2
  end_struct("linker_version");
3766
3767
2
  begin_struct("os_version")
3768
1
    declare_integer("major");
3769
1
    declare_integer("minor");
3770
2
  end_struct("os_version");
3771
3772
2
  begin_struct("image_version")
3773
1
    declare_integer("major");
3774
1
    declare_integer("minor");
3775
2
  end_struct("image_version");
3776
3777
2
  begin_struct("subsystem_version")
3778
1
    declare_integer("major");
3779
1
    declare_integer("minor");
3780
2
  end_struct("subsystem_version");
3781
3782
2
  declare_integer("win32_version_value");
3783
1
  declare_integer("size_of_image");
3784
1
  declare_integer("size_of_headers");
3785
3786
1
  declare_integer("checksum");
3787
1
  declare_function("calculate_checksum", "", "i", calculate_checksum);
3788
1
  declare_integer("subsystem");
3789
3790
1
  declare_integer("dll_characteristics");
3791
1
  declare_integer("size_of_stack_reserve");
3792
1
  declare_integer("size_of_stack_commit");
3793
1
  declare_integer("size_of_heap_reserve");
3794
1
  declare_integer("size_of_heap_commit");
3795
1
  declare_integer("loader_flags");
3796
3797
3
  begin_struct_array("data_directories")
3798
1
    declare_integer("virtual_address");
3799
1
    declare_integer("size");
3800
2
  end_struct_array("data_directories");
3801
3802
3
  begin_struct_array("sections")
3803
1
    declare_string("name");
3804
1
    declare_string("full_name");
3805
1
    declare_integer("characteristics");
3806
1
    declare_integer("virtual_address");
3807
1
    declare_integer("virtual_size");
3808
1
    declare_integer("raw_data_offset");
3809
1
    declare_integer("raw_data_size");
3810
1
    declare_integer("pointer_to_relocations");
3811
1
    declare_integer("pointer_to_line_numbers");
3812
1
    declare_integer("number_of_relocations");
3813
1
    declare_integer("number_of_line_numbers");
3814
2
  end_struct_array("sections");
3815
3816
2
  begin_struct("overlay")
3817
1
    declare_integer("offset");
3818
1
    declare_integer("size");
3819
2
  end_struct("overlay");
3820
3821
2
  begin_struct("rich_signature")
3822
1
    declare_integer("offset");
3823
1
    declare_integer("length");
3824
1
    declare_integer("key");
3825
1
    declare_string("raw_data");
3826
1
    declare_string("clear_data");
3827
1
    declare_string("version_data");
3828
1
    declare_function("version", "i", "i", rich_version);
3829
1
    declare_function("version", "ii", "i", rich_version_toolid);
3830
1
    declare_function("toolid", "i", "i", rich_toolid);
3831
1
    declare_function("toolid", "ii", "i", rich_toolid_version);
3832
2
  end_struct("rich_signature");
3833
3834
#if defined(HAVE_LIBCRYPTO) || defined(HAVE_WINCRYPT_H) || \
3835
    defined(HAVE_COMMONCRYPTO_COMMONCRYPTO_H)
3836
  declare_function("imphash", "", "s", imphash);
3837
#endif
3838
3839
2
  declare_function("section_index", "s", "i", section_index_name);
3840
1
  declare_function("section_index", "i", "i", section_index_addr);
3841
1
  declare_function("exports", "s", "i", exports);
3842
1
  declare_function("exports", "r", "i", exports_regexp);
3843
1
  declare_function("exports", "i", "i", exports_ordinal);
3844
1
  declare_function("exports_index", "s", "i", exports_index_name);
3845
1
  declare_function("exports_index", "i", "i", exports_index_ordinal);
3846
1
  declare_function("exports_index", "r", "i", exports_index_regex);
3847
1
  declare_function("imports", "ss", "i", imports_standard);
3848
1
  declare_function("imports", "si", "i", imports_standard_ordinal);
3849
1
  declare_function("imports", "s", "i", imports_standard_dll);
3850
1
  declare_function("imports", "rr", "i", imports_standard_regex);
3851
1
  declare_function("imports", "iss", "i", imports);
3852
1
  declare_function("imports", "isi", "i", imports_ordinal);
3853
1
  declare_function("imports", "is", "i", imports_dll);
3854
1
  declare_function("imports", "irr", "i", imports_regex);
3855
1
  declare_function("import_rva", "ss", "i", import_rva);
3856
1
  declare_function("import_rva", "si", "i", import_rva_ordinal);
3857
1
  declare_function("delayed_import_rva", "ss", "i", delayed_import_rva);
3858
1
  declare_function("delayed_import_rva", "si", "i", delayed_import_rva_ordinal);
3859
1
  declare_function("locale", "i", "i", locale);
3860
1
  declare_function("language", "i", "i", language);
3861
1
  declare_function("is_dll", "", "i", is_dll);
3862
1
  declare_function("is_32bit", "", "i", is_32bit);
3863
1
  declare_function("is_64bit", "", "i", is_64bit);
3864
3865
1
  declare_integer("number_of_imports");
3866
1
  declare_integer("number_of_imported_functions");
3867
1
  declare_integer("number_of_delayed_imports");
3868
1
  declare_integer("number_of_delayed_imported_functions");
3869
1
  declare_integer("number_of_exports");
3870
3871
1
  declare_string("dll_name");
3872
1
  declare_integer("export_timestamp");
3873
3
  begin_struct_array("export_details")
3874
1
    declare_integer("offset");
3875
1
    declare_string("name");
3876
1
    declare_string("forward_name");
3877
1
    declare_integer("ordinal");
3878
1
    declare_integer("rva");
3879
2
  end_struct_array("export_details")
3880
3881
3
  begin_struct_array("import_details")
3882
1
    declare_string("library_name");
3883
1
    declare_integer("number_of_functions");
3884
3
    begin_struct_array("functions")
3885
1
      declare_string("name");
3886
1
      declare_integer("ordinal");
3887
1
      declare_integer("rva");
3888
2
    end_struct_array("functions");
3889
2
  end_struct_array("import_details");
3890
3891
3
  begin_struct_array("delayed_import_details")
3892
1
    declare_string("library_name");
3893
1
    declare_integer("number_of_functions");
3894
3
    begin_struct_array("functions")
3895
1
      declare_string("name");
3896
1
      declare_integer("ordinal");
3897
1
      declare_integer("rva");
3898
2
    end_struct_array("functions");
3899
2
  end_struct_array("delayed_import_details");
3900
3901
2
  declare_integer("resource_timestamp");
3902
3903
2
  begin_struct("resource_version")
3904
1
    declare_integer("major");
3905
1
    declare_integer("minor");
3906
2
  end_struct("resource_version")
3907
3908
3
  begin_struct_array("resources")
3909
1
    declare_integer("rva");
3910
1
    declare_integer("offset");
3911
1
    declare_integer("length");
3912
1
    declare_integer("type");
3913
1
    declare_integer("id");
3914
1
    declare_integer("language");
3915
1
    declare_string("type_string");
3916
1
    declare_string("name_string");
3917
1
    declare_string("language_string");
3918
2
  end_struct_array("resources")
3919
3920
1
  declare_integer("number_of_resources");
3921
1
  declare_string("pdb_path");
3922
3923
#if defined(HAVE_LIBCRYPTO) && !defined(BORINGSSL)
3924
  begin_struct_array("signatures")
3925
    declare_string("thumbprint");
3926
    declare_string("issuer");
3927
    declare_string("subject");
3928
    declare_integer("version");
3929
    declare_string("algorithm");
3930
    declare_string("algorithm_oid");
3931
    declare_string("serial");
3932
    declare_integer("not_before");
3933
    declare_integer("not_after");
3934
3935
    declare_integer("verified");
3936
    declare_string("digest_alg");
3937
    declare_string("digest");
3938
    declare_string("file_digest");
3939
    declare_integer("number_of_certificates");
3940
    begin_struct_array("certificates")
3941
      ;
3942
      declare_string("thumbprint");
3943
      declare_string("issuer");
3944
      declare_string("subject");
3945
      declare_integer("version");
3946
      declare_string("algorithm");
3947
      declare_string("algorithm_oid");
3948
      declare_string("serial");
3949
      declare_integer("not_before");
3950
      declare_integer("not_after");
3951
    end_struct_array("certificates");
3952
3953
    begin_struct("signer_info")
3954
      ;
3955
      declare_string("program_name");
3956
      declare_string("digest");
3957
      declare_string("digest_alg");
3958
      declare_integer("length_of_chain");
3959
      begin_struct_array("chain")
3960
        ;
3961
        declare_string("thumbprint");
3962
        declare_string("issuer");
3963
        declare_string("subject");
3964
        declare_integer("version");
3965
        declare_string("algorithm");
3966
        declare_string("algorithm_oid");
3967
        declare_string("serial");
3968
        declare_integer("not_before");
3969
        declare_integer("not_after");
3970
      end_struct_array("chain");
3971
    end_struct("signer_info");
3972
3973
    declare_integer("number_of_countersignatures");
3974
    begin_struct_array("countersignatures")
3975
      ;
3976
      declare_integer("verified");
3977
      declare_integer("sign_time");
3978
      declare_string("digest_alg");
3979
      declare_string("digest");
3980
      declare_integer("length_of_chain");
3981
      begin_struct_array("chain")
3982
        ;
3983
        declare_string("thumbprint");
3984
        declare_string("issuer");
3985
        declare_string("subject");
3986
        declare_integer("version");
3987
        declare_string("algorithm");
3988
        declare_string("algorithm_oid");
3989
        declare_string("serial");
3990
        declare_integer("not_before");
3991
        declare_integer("not_after");
3992
      end_struct_array("chain");
3993
    end_struct_array("countersignatures")
3994
3995
    declare_function("valid_on", "i", "i", valid_on);
3996
3997
  end_struct_array("signatures")
3998
3999
  // If any of the signatures correctly signs the binary
4000
  declare_integer("is_signed");
4001
  declare_integer("number_of_signatures");
4002
#endif
4003
4004
1
  declare_function("rva_to_offset", "i", "i", rva_to_offset);
4005
1
end_declarations
4006
4007
int module_initialize(YR_MODULE* module)
4008
12
{
4009
#if defined(HAVE_LIBCRYPTO) && !defined(BORINGSSL)
4010
  // Initialize OpenSSL global objects for the auth library before any
4011
  // multithreaded environment as it is not thread-safe. This can
4012
  // only be called once per process.
4013
  static bool s_initialized = false;
4014
4015
  if (!s_initialized)
4016
  {
4017
    s_initialized = true;
4018
    initialize_authenticode_parser();
4019
  }
4020
#endif
4021
12
  return ERROR_SUCCESS;
4022
12
}
4023
4024
int module_finalize(YR_MODULE* module)
4025
0
{
4026
0
  return ERROR_SUCCESS;
4027
0
}
4028
4029
int module_load(
4030
    YR_SCAN_CONTEXT* context,
4031
    YR_OBJECT* module_object,
4032
    void* module_data,
4033
    size_t module_data_size)
4034
0
{
4035
0
  YR_MEMORY_BLOCK* block;
4036
0
  YR_MEMORY_BLOCK_ITERATOR* iterator = context->iterator;
4037
4038
0
  PIMAGE_NT_HEADERS32 pe_header;
4039
0
  const uint8_t* block_data = NULL;
4040
0
  PE* pe = NULL;
4041
4042
0
  yr_set_integer(IMPORT_DELAYED, module_object, "IMPORT_DELAYED");
4043
0
  yr_set_integer(IMPORT_STANDARD, module_object, "IMPORT_STANDARD");
4044
0
  yr_set_integer(IMPORT_ANY, module_object, "IMPORT_ANY");
4045
4046
0
  yr_set_integer(IMAGE_FILE_MACHINE_UNKNOWN, module_object, "MACHINE_UNKNOWN");
4047
0
  yr_set_integer(IMAGE_FILE_MACHINE_AM33, module_object, "MACHINE_AM33");
4048
0
  yr_set_integer(IMAGE_FILE_MACHINE_AMD64, module_object, "MACHINE_AMD64");
4049
0
  yr_set_integer(IMAGE_FILE_MACHINE_ARM, module_object, "MACHINE_ARM");
4050
0
  yr_set_integer(IMAGE_FILE_MACHINE_ARMNT, module_object, "MACHINE_ARMNT");
4051
0
  yr_set_integer(IMAGE_FILE_MACHINE_ARM64, module_object, "MACHINE_ARM64");
4052
0
  yr_set_integer(IMAGE_FILE_MACHINE_EBC, module_object, "MACHINE_EBC");
4053
0
  yr_set_integer(IMAGE_FILE_MACHINE_I386, module_object, "MACHINE_I386");
4054
0
  yr_set_integer(IMAGE_FILE_MACHINE_IA64, module_object, "MACHINE_IA64");
4055
0
  yr_set_integer(IMAGE_FILE_MACHINE_M32R, module_object, "MACHINE_M32R");
4056
0
  yr_set_integer(IMAGE_FILE_MACHINE_MIPS16, module_object, "MACHINE_MIPS16");
4057
0
  yr_set_integer(IMAGE_FILE_MACHINE_MIPSFPU, module_object, "MACHINE_MIPSFPU");
4058
0
  yr_set_integer(
4059
0
      IMAGE_FILE_MACHINE_MIPSFPU16, module_object, "MACHINE_MIPSFPU16");
4060
0
  yr_set_integer(IMAGE_FILE_MACHINE_POWERPC, module_object, "MACHINE_POWERPC");
4061
0
  yr_set_integer(
4062
0
      IMAGE_FILE_MACHINE_POWERPCFP, module_object, "MACHINE_POWERPCFP");
4063
0
  yr_set_integer(IMAGE_FILE_MACHINE_R4000, module_object, "MACHINE_R4000");
4064
0
  yr_set_integer(IMAGE_FILE_MACHINE_SH3, module_object, "MACHINE_SH3");
4065
0
  yr_set_integer(IMAGE_FILE_MACHINE_SH3DSP, module_object, "MACHINE_SH3DSP");
4066
0
  yr_set_integer(IMAGE_FILE_MACHINE_SH4, module_object, "MACHINE_SH4");
4067
0
  yr_set_integer(IMAGE_FILE_MACHINE_SH5, module_object, "MACHINE_SH5");
4068
0
  yr_set_integer(IMAGE_FILE_MACHINE_THUMB, module_object, "MACHINE_THUMB");
4069
0
  yr_set_integer(
4070
0
      IMAGE_FILE_MACHINE_WCEMIPSV2, module_object, "MACHINE_WCEMIPSV2");
4071
0
  yr_set_integer(
4072
0
      IMAGE_FILE_MACHINE_TARGET_HOST, module_object, "MACHINE_TARGET_HOST");
4073
0
  yr_set_integer(IMAGE_FILE_MACHINE_R3000, module_object, "MACHINE_R3000");
4074
0
  yr_set_integer(IMAGE_FILE_MACHINE_R10000, module_object, "MACHINE_R10000");
4075
0
  yr_set_integer(IMAGE_FILE_MACHINE_ALPHA, module_object, "MACHINE_ALPHA");
4076
0
  yr_set_integer(IMAGE_FILE_MACHINE_SH3E, module_object, "MACHINE_SH3E");
4077
0
  yr_set_integer(IMAGE_FILE_MACHINE_ALPHA64, module_object, "MACHINE_ALPHA64");
4078
0
  yr_set_integer(IMAGE_FILE_MACHINE_AXP64, module_object, "MACHINE_AXP64");
4079
0
  yr_set_integer(IMAGE_FILE_MACHINE_TRICORE, module_object, "MACHINE_TRICORE");
4080
0
  yr_set_integer(IMAGE_FILE_MACHINE_CEF, module_object, "MACHINE_CEF");
4081
0
  yr_set_integer(IMAGE_FILE_MACHINE_CEE, module_object, "MACHINE_CEE");
4082
4083
0
  yr_set_integer(IMAGE_SUBSYSTEM_UNKNOWN, module_object, "SUBSYSTEM_UNKNOWN");
4084
0
  yr_set_integer(IMAGE_SUBSYSTEM_NATIVE, module_object, "SUBSYSTEM_NATIVE");
4085
0
  yr_set_integer(
4086
0
      IMAGE_SUBSYSTEM_WINDOWS_GUI, module_object, "SUBSYSTEM_WINDOWS_GUI");
4087
0
  yr_set_integer(
4088
0
      IMAGE_SUBSYSTEM_WINDOWS_CUI, module_object, "SUBSYSTEM_WINDOWS_CUI");
4089
0
  yr_set_integer(IMAGE_SUBSYSTEM_OS2_CUI, module_object, "SUBSYSTEM_OS2_CUI");
4090
0
  yr_set_integer(
4091
0
      IMAGE_SUBSYSTEM_POSIX_CUI, module_object, "SUBSYSTEM_POSIX_CUI");
4092
0
  yr_set_integer(
4093
0
      IMAGE_SUBSYSTEM_NATIVE_WINDOWS,
4094
0
      module_object,
4095
0
      "SUBSYSTEM_NATIVE_WINDOWS");
4096
0
  yr_set_integer(
4097
0
      IMAGE_SUBSYSTEM_WINDOWS_CE_GUI,
4098
0
      module_object,
4099
0
      "SUBSYSTEM_WINDOWS_CE_GUI");
4100
0
  yr_set_integer(
4101
0
      IMAGE_SUBSYSTEM_EFI_APPLICATION,
4102
0
      module_object,
4103
0
      "SUBSYSTEM_EFI_APPLICATION");
4104
0
  yr_set_integer(
4105
0
      IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER,
4106
0
      module_object,
4107
0
      "SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER");
4108
0
  yr_set_integer(
4109
0
      IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER,
4110
0
      module_object,
4111
0
      "SUBSYSTEM_EFI_RUNTIME_DRIVER");
4112
0
  yr_set_integer(
4113
0
      IMAGE_SUBSYSTEM_EFI_ROM_IMAGE, module_object, "SUBSYSTEM_EFI_ROM_IMAGE");
4114
0
  yr_set_integer(IMAGE_SUBSYSTEM_XBOX, module_object, "SUBSYSTEM_XBOX");
4115
0
  yr_set_integer(
4116
0
      IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION,
4117
0
      module_object,
4118
0
      "SUBSYSTEM_WINDOWS_BOOT_APPLICATION");
4119
4120
0
  yr_set_integer(
4121
0
      IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA,
4122
0
      module_object,
4123
0
      "HIGH_ENTROPY_VA");
4124
0
  yr_set_integer(
4125
0
      IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE, module_object, "DYNAMIC_BASE");
4126
0
  yr_set_integer(
4127
0
      IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY,
4128
0
      module_object,
4129
0
      "FORCE_INTEGRITY");
4130
0
  yr_set_integer(
4131
0
      IMAGE_DLLCHARACTERISTICS_NX_COMPAT, module_object, "NX_COMPAT");
4132
0
  yr_set_integer(
4133
0
      IMAGE_DLLCHARACTERISTICS_NO_ISOLATION, module_object, "NO_ISOLATION");
4134
0
  yr_set_integer(IMAGE_DLLCHARACTERISTICS_NO_SEH, module_object, "NO_SEH");
4135
0
  yr_set_integer(IMAGE_DLLCHARACTERISTICS_NO_BIND, module_object, "NO_BIND");
4136
0
  yr_set_integer(
4137
0
      IMAGE_DLLCHARACTERISTICS_APPCONTAINER, module_object, "APPCONTAINER");
4138
0
  yr_set_integer(
4139
0
      IMAGE_DLLCHARACTERISTICS_WDM_DRIVER, module_object, "WDM_DRIVER");
4140
0
  yr_set_integer(IMAGE_DLLCHARACTERISTICS_GUARD_CF, module_object, "GUARD_CF");
4141
0
  yr_set_integer(
4142
0
      IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE,
4143
0
      module_object,
4144
0
      "TERMINAL_SERVER_AWARE");
4145
4146
0
  yr_set_integer(IMAGE_FILE_RELOCS_STRIPPED, module_object, "RELOCS_STRIPPED");
4147
0
  yr_set_integer(
4148
0
      IMAGE_FILE_EXECUTABLE_IMAGE, module_object, "EXECUTABLE_IMAGE");
4149
0
  yr_set_integer(
4150
0
      IMAGE_FILE_LINE_NUMS_STRIPPED, module_object, "LINE_NUMS_STRIPPED");
4151
0
  yr_set_integer(
4152
0
      IMAGE_FILE_LOCAL_SYMS_STRIPPED, module_object, "LOCAL_SYMS_STRIPPED");
4153
0
  yr_set_integer(
4154
0
      IMAGE_FILE_AGGRESIVE_WS_TRIM, module_object, "AGGRESIVE_WS_TRIM");
4155
0
  yr_set_integer(
4156
0
      IMAGE_FILE_LARGE_ADDRESS_AWARE, module_object, "LARGE_ADDRESS_AWARE");
4157
0
  yr_set_integer(
4158
0
      IMAGE_FILE_BYTES_REVERSED_LO, module_object, "BYTES_REVERSED_LO");
4159
0
  yr_set_integer(IMAGE_FILE_32BIT_MACHINE, module_object, "MACHINE_32BIT");
4160
0
  yr_set_integer(IMAGE_FILE_DEBUG_STRIPPED, module_object, "DEBUG_STRIPPED");
4161
0
  yr_set_integer(
4162
0
      IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP,
4163
0
      module_object,
4164
0
      "REMOVABLE_RUN_FROM_SWAP");
4165
0
  yr_set_integer(
4166
0
      IMAGE_FILE_NET_RUN_FROM_SWAP, module_object, "NET_RUN_FROM_SWAP");
4167
0
  yr_set_integer(IMAGE_FILE_SYSTEM, module_object, "SYSTEM");
4168
0
  yr_set_integer(IMAGE_FILE_DLL, module_object, "DLL");
4169
0
  yr_set_integer(IMAGE_FILE_UP_SYSTEM_ONLY, module_object, "UP_SYSTEM_ONLY");
4170
0
  yr_set_integer(
4171
0
      IMAGE_FILE_BYTES_REVERSED_HI, module_object, "BYTES_REVERSED_HI");
4172
4173
0
  yr_set_integer(
4174
0
      IMAGE_DIRECTORY_ENTRY_EXPORT,
4175
0
      module_object,
4176
0
      "IMAGE_DIRECTORY_ENTRY_EXPORT");
4177
0
  yr_set_integer(
4178
0
      IMAGE_DIRECTORY_ENTRY_IMPORT,
4179
0
      module_object,
4180
0
      "IMAGE_DIRECTORY_ENTRY_IMPORT");
4181
0
  yr_set_integer(
4182
0
      IMAGE_DIRECTORY_ENTRY_RESOURCE,
4183
0
      module_object,
4184
0
      "IMAGE_DIRECTORY_ENTRY_RESOURCE");
4185
0
  yr_set_integer(
4186
0
      IMAGE_DIRECTORY_ENTRY_EXCEPTION,
4187
0
      module_object,
4188
0
      "IMAGE_DIRECTORY_ENTRY_EXCEPTION");
4189
0
  yr_set_integer(
4190
0
      IMAGE_DIRECTORY_ENTRY_SECURITY,
4191
0
      module_object,
4192
0
      "IMAGE_DIRECTORY_ENTRY_SECURITY");
4193
0
  yr_set_integer(
4194
0
      IMAGE_DIRECTORY_ENTRY_BASERELOC,
4195
0
      module_object,
4196
0
      "IMAGE_DIRECTORY_ENTRY_BASERELOC");
4197
0
  yr_set_integer(
4198
0
      IMAGE_DIRECTORY_ENTRY_DEBUG,
4199
0
      module_object,
4200
0
      "IMAGE_DIRECTORY_ENTRY_DEBUG");
4201
0
  yr_set_integer(
4202
0
      IMAGE_DIRECTORY_ENTRY_ARCHITECTURE,
4203
0
      module_object,
4204
0
      "IMAGE_DIRECTORY_ENTRY_ARCHITECTURE");
4205
0
  yr_set_integer(
4206
0
      IMAGE_DIRECTORY_ENTRY_COPYRIGHT,
4207
0
      module_object,
4208
0
      "IMAGE_DIRECTORY_ENTRY_COPYRIGHT");
4209
0
  yr_set_integer(
4210
0
      IMAGE_DIRECTORY_ENTRY_GLOBALPTR,
4211
0
      module_object,
4212
0
      "IMAGE_DIRECTORY_ENTRY_GLOBALPTR");
4213
0
  yr_set_integer(
4214
0
      IMAGE_DIRECTORY_ENTRY_TLS, module_object, "IMAGE_DIRECTORY_ENTRY_TLS");
4215
0
  yr_set_integer(
4216
0
      IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
4217
0
      module_object,
4218
0
      "IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG");
4219
0
  yr_set_integer(
4220
0
      IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT,
4221
0
      module_object,
4222
0
      "IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT");
4223
0
  yr_set_integer(
4224
0
      IMAGE_DIRECTORY_ENTRY_IAT, module_object, "IMAGE_DIRECTORY_ENTRY_IAT");
4225
0
  yr_set_integer(
4226
0
      IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT,
4227
0
      module_object,
4228
0
      "IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT");
4229
0
  yr_set_integer(
4230
0
      IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR,
4231
0
      module_object,
4232
0
      "IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR");
4233
4234
0
  yr_set_integer(
4235
0
      IMAGE_NT_OPTIONAL_HDR32_MAGIC,
4236
0
      module_object,
4237
0
      "IMAGE_NT_OPTIONAL_HDR32_MAGIC");
4238
0
  yr_set_integer(
4239
0
      IMAGE_NT_OPTIONAL_HDR64_MAGIC,
4240
0
      module_object,
4241
0
      "IMAGE_NT_OPTIONAL_HDR64_MAGIC");
4242
0
  yr_set_integer(
4243
0
      IMAGE_ROM_OPTIONAL_HDR_MAGIC,
4244
0
      module_object,
4245
0
      "IMAGE_ROM_OPTIONAL_HDR_MAGIC");
4246
4247
0
  yr_set_integer(IMAGE_SCN_TYPE_NO_PAD, module_object, "SECTION_NO_PAD");
4248
0
  yr_set_integer(IMAGE_SCN_CNT_CODE, module_object, "SECTION_CNT_CODE");
4249
0
  yr_set_integer(
4250
0
      IMAGE_SCN_CNT_INITIALIZED_DATA,
4251
0
      module_object,
4252
0
      "SECTION_CNT_INITIALIZED_DATA");
4253
0
  yr_set_integer(
4254
0
      IMAGE_SCN_CNT_UNINITIALIZED_DATA,
4255
0
      module_object,
4256
0
      "SECTION_CNT_UNINITIALIZED_DATA");
4257
0
  yr_set_integer(IMAGE_SCN_LNK_OTHER, module_object, "SECTION_LNK_OTHER");
4258
0
  yr_set_integer(IMAGE_SCN_LNK_INFO, module_object, "SECTION_LNK_INFO");
4259
0
  yr_set_integer(IMAGE_SCN_LNK_REMOVE, module_object, "SECTION_LNK_REMOVE");
4260
0
  yr_set_integer(IMAGE_SCN_LNK_COMDAT, module_object, "SECTION_LNK_COMDAT");
4261
0
  yr_set_integer(
4262
0
      IMAGE_SCN_NO_DEFER_SPEC_EXC, module_object, "SECTION_NO_DEFER_SPEC_EXC");
4263
0
  yr_set_integer(IMAGE_SCN_GPREL, module_object, "SECTION_GPREL");
4264
0
  yr_set_integer(IMAGE_SCN_MEM_FARDATA, module_object, "SECTION_MEM_FARDATA");
4265
0
  yr_set_integer(
4266
0
      IMAGE_SCN_MEM_PURGEABLE, module_object, "SECTION_MEM_PURGEABLE");
4267
0
  yr_set_integer(IMAGE_SCN_MEM_16BIT, module_object, "SECTION_MEM_16BIT");
4268
0
  yr_set_integer(IMAGE_SCN_MEM_LOCKED, module_object, "SECTION_MEM_LOCKED");
4269
0
  yr_set_integer(IMAGE_SCN_MEM_PRELOAD, module_object, "SECTION_MEM_PRELOAD");
4270
0
  yr_set_integer(IMAGE_SCN_ALIGN_1BYTES, module_object, "SECTION_ALIGN_1BYTES");
4271
0
  yr_set_integer(IMAGE_SCN_ALIGN_2BYTES, module_object, "SECTION_ALIGN_2BYTES");
4272
0
  yr_set_integer(IMAGE_SCN_ALIGN_4BYTES, module_object, "SECTION_ALIGN_4BYTES");
4273
0
  yr_set_integer(IMAGE_SCN_ALIGN_8BYTES, module_object, "SECTION_ALIGN_8BYTES");
4274
0
  yr_set_integer(
4275
0
      IMAGE_SCN_ALIGN_16BYTES, module_object, "SECTION_ALIGN_16BYTES");
4276
0
  yr_set_integer(
4277
0
      IMAGE_SCN_ALIGN_32BYTES, module_object, "SECTION_ALIGN_32BYTES");
4278
0
  yr_set_integer(
4279
0
      IMAGE_SCN_ALIGN_64BYTES, module_object, "SECTION_ALIGN_64BYTES");
4280
0
  yr_set_integer(
4281
0
      IMAGE_SCN_ALIGN_128BYTES, module_object, "SECTION_ALIGN_128BYTES");
4282
0
  yr_set_integer(
4283
0
      IMAGE_SCN_ALIGN_256BYTES, module_object, "SECTION_ALIGN_256BYTES");
4284
0
  yr_set_integer(
4285
0
      IMAGE_SCN_ALIGN_512BYTES, module_object, "SECTION_ALIGN_512BYTES");
4286
0
  yr_set_integer(
4287
0
      IMAGE_SCN_ALIGN_1024BYTES, module_object, "SECTION_ALIGN_1024BYTES");
4288
0
  yr_set_integer(
4289
0
      IMAGE_SCN_ALIGN_2048BYTES, module_object, "SECTION_ALIGN_2048BYTES");
4290
0
  yr_set_integer(
4291
0
      IMAGE_SCN_ALIGN_4096BYTES, module_object, "SECTION_ALIGN_4096BYTES");
4292
0
  yr_set_integer(
4293
0
      IMAGE_SCN_ALIGN_8192BYTES, module_object, "SECTION_ALIGN_8192BYTES");
4294
0
  yr_set_integer(IMAGE_SCN_ALIGN_MASK, module_object, "SECTION_ALIGN_MASK");
4295
0
  yr_set_integer(
4296
0
      IMAGE_SCN_LNK_NRELOC_OVFL, module_object, "SECTION_LNK_NRELOC_OVFL");
4297
0
  yr_set_integer(
4298
0
      IMAGE_SCN_MEM_DISCARDABLE, module_object, "SECTION_MEM_DISCARDABLE");
4299
0
  yr_set_integer(
4300
0
      IMAGE_SCN_MEM_NOT_CACHED, module_object, "SECTION_MEM_NOT_CACHED");
4301
0
  yr_set_integer(
4302
0
      IMAGE_SCN_MEM_NOT_PAGED, module_object, "SECTION_MEM_NOT_PAGED");
4303
0
  yr_set_integer(IMAGE_SCN_MEM_SHARED, module_object, "SECTION_MEM_SHARED");
4304
0
  yr_set_integer(IMAGE_SCN_MEM_EXECUTE, module_object, "SECTION_MEM_EXECUTE");
4305
0
  yr_set_integer(IMAGE_SCN_MEM_READ, module_object, "SECTION_MEM_READ");
4306
0
  yr_set_integer(IMAGE_SCN_MEM_WRITE, module_object, "SECTION_MEM_WRITE");
4307
0
  yr_set_integer(IMAGE_SCN_SCALE_INDEX, module_object, "SECTION_SCALE_INDEX");
4308
4309
0
  yr_set_integer(RESOURCE_TYPE_CURSOR, module_object, "RESOURCE_TYPE_CURSOR");
4310
0
  yr_set_integer(RESOURCE_TYPE_BITMAP, module_object, "RESOURCE_TYPE_BITMAP");
4311
0
  yr_set_integer(RESOURCE_TYPE_ICON, module_object, "RESOURCE_TYPE_ICON");
4312
0
  yr_set_integer(RESOURCE_TYPE_MENU, module_object, "RESOURCE_TYPE_MENU");
4313
0
  yr_set_integer(RESOURCE_TYPE_DIALOG, module_object, "RESOURCE_TYPE_DIALOG");
4314
0
  yr_set_integer(RESOURCE_TYPE_STRING, module_object, "RESOURCE_TYPE_STRING");
4315
0
  yr_set_integer(RESOURCE_TYPE_FONTDIR, module_object, "RESOURCE_TYPE_FONTDIR");
4316
0
  yr_set_integer(RESOURCE_TYPE_FONT, module_object, "RESOURCE_TYPE_FONT");
4317
0
  yr_set_integer(
4318
0
      RESOURCE_TYPE_ACCELERATOR, module_object, "RESOURCE_TYPE_ACCELERATOR");
4319
0
  yr_set_integer(RESOURCE_TYPE_RCDATA, module_object, "RESOURCE_TYPE_RCDATA");
4320
0
  yr_set_integer(
4321
0
      RESOURCE_TYPE_MESSAGETABLE, module_object, "RESOURCE_TYPE_MESSAGETABLE");
4322
0
  yr_set_integer(
4323
0
      RESOURCE_TYPE_GROUP_CURSOR, module_object, "RESOURCE_TYPE_GROUP_CURSOR");
4324
0
  yr_set_integer(
4325
0
      RESOURCE_TYPE_GROUP_ICON, module_object, "RESOURCE_TYPE_GROUP_ICON");
4326
0
  yr_set_integer(RESOURCE_TYPE_VERSION, module_object, "RESOURCE_TYPE_VERSION");
4327
0
  yr_set_integer(
4328
0
      RESOURCE_TYPE_DLGINCLUDE, module_object, "RESOURCE_TYPE_DLGINCLUDE");
4329
0
  yr_set_integer(
4330
0
      RESOURCE_TYPE_PLUGPLAY, module_object, "RESOURCE_TYPE_PLUGPLAY");
4331
0
  yr_set_integer(RESOURCE_TYPE_VXD, module_object, "RESOURCE_TYPE_VXD");
4332
0
  yr_set_integer(
4333
0
      RESOURCE_TYPE_ANICURSOR, module_object, "RESOURCE_TYPE_ANICURSOR");
4334
0
  yr_set_integer(RESOURCE_TYPE_ANIICON, module_object, "RESOURCE_TYPE_ANIICON");
4335
0
  yr_set_integer(RESOURCE_TYPE_HTML, module_object, "RESOURCE_TYPE_HTML");
4336
0
  yr_set_integer(
4337
0
      RESOURCE_TYPE_MANIFEST, module_object, "RESOURCE_TYPE_MANIFEST");
4338
4339
0
  yr_set_integer(
4340
0
      IMAGE_DEBUG_TYPE_UNKNOWN, module_object, "IMAGE_DEBUG_TYPE_UNKNOWN");
4341
0
  yr_set_integer(IMAGE_DEBUG_TYPE_COFF, module_object, "IMAGE_DEBUG_TYPE_COFF");
4342
0
  yr_set_integer(
4343
0
      IMAGE_DEBUG_TYPE_CODEVIEW, module_object, "IMAGE_DEBUG_TYPE_CODEVIEW");
4344
0
  yr_set_integer(IMAGE_DEBUG_TYPE_FPO, module_object, "IMAGE_DEBUG_TYPE_FPO");
4345
0
  yr_set_integer(IMAGE_DEBUG_TYPE_MISC, module_object, "IMAGE_DEBUG_TYPE_MISC");
4346
0
  yr_set_integer(
4347
0
      IMAGE_DEBUG_TYPE_EXCEPTION, module_object, "IMAGE_DEBUG_TYPE_EXCEPTION");
4348
0
  yr_set_integer(
4349
0
      IMAGE_DEBUG_TYPE_FIXUP, module_object, "IMAGE_DEBUG_TYPE_FIXUP");
4350
0
  yr_set_integer(
4351
0
      IMAGE_DEBUG_TYPE_OMAP_TO_SRC,
4352
0
      module_object,
4353
0
      "IMAGE_DEBUG_TYPE_OMAP_TO_SRC");
4354
0
  yr_set_integer(
4355
0
      IMAGE_DEBUG_TYPE_OMAP_FROM_SRC,
4356
0
      module_object,
4357
0
      "IMAGE_DEBUG_TYPE_OMAP_FROM_SRC");
4358
0
  yr_set_integer(
4359
0
      IMAGE_DEBUG_TYPE_BORLAND, module_object, "IMAGE_DEBUG_TYPE_BORLAND");
4360
0
  yr_set_integer(
4361
0
      IMAGE_DEBUG_TYPE_RESERVED10,
4362
0
      module_object,
4363
0
      "IMAGE_DEBUG_TYPE_RESERVED10");
4364
0
  yr_set_integer(
4365
0
      IMAGE_DEBUG_TYPE_CLSID, module_object, "IMAGE_DEBUG_TYPE_CLSID");
4366
0
  yr_set_integer(
4367
0
      IMAGE_DEBUG_TYPE_VC_FEATURE,
4368
0
      module_object,
4369
0
      "IMAGE_DEBUG_TYPE_VC_FEATURE");
4370
0
  yr_set_integer(IMAGE_DEBUG_TYPE_POGO, module_object, "IMAGE_DEBUG_TYPE_POGO");
4371
0
  yr_set_integer(
4372
0
      IMAGE_DEBUG_TYPE_ILTCG, module_object, "IMAGE_DEBUG_TYPE_ILTCG");
4373
0
  yr_set_integer(IMAGE_DEBUG_TYPE_MPX, module_object, "IMAGE_DEBUG_TYPE_MPX");
4374
0
  yr_set_integer(
4375
0
      IMAGE_DEBUG_TYPE_REPRO, module_object, "IMAGE_DEBUG_TYPE_REPRO");
4376
4377
0
  yr_set_integer(0, module_object, "is_pe");
4378
4379
0
  foreach_memory_block(iterator, block)
4380
0
  {
4381
0
    block_data = yr_fetch_block_data(block);
4382
4383
0
    if (block_data == NULL)
4384
0
      continue;
4385
4386
0
    pe_header = pe_get_header(block_data, block->size);
4387
4388
0
    if (pe_header != NULL)
4389
0
    {
4390
      // Ignore DLLs while scanning a process
4391
4392
0
      if (!(context->flags & SCAN_FLAGS_PROCESS_MEMORY) ||
4393
0
          !(yr_le16toh(pe_header->FileHeader.Characteristics) & IMAGE_FILE_DLL))
4394
0
      {
4395
0
        pe = (PE*) yr_malloc(sizeof(PE));
4396
4397
0
        if (pe == NULL)
4398
0
          return ERROR_INSUFFICIENT_MEMORY;
4399
4400
0
        FAIL_ON_ERROR_WITH_CLEANUP(
4401
0
            yr_hash_table_create(17, &pe->hash_table), yr_free(pe));
4402
4403
0
        pe->data = block_data;
4404
0
        pe->data_size = block->size;
4405
0
        pe->header = pe_header;
4406
0
        pe->object = module_object;
4407
0
        pe->resources = 0;
4408
0
        pe->version_infos = 0;
4409
4410
0
        module_object->data = pe;
4411
4412
0
        pe_parse_header(pe, block->base, context->flags);
4413
0
        pe_parse_rich_signature(pe, block->base);
4414
0
        pe_parse_debug_directory(pe);
4415
4416
#if defined(HAVE_LIBCRYPTO) && !defined(BORINGSSL)
4417
        pe_parse_certificates(pe);
4418
#endif
4419
4420
0
        pe->imported_dlls = pe_parse_imports(pe);
4421
0
        pe->delay_imported_dlls = pe_parse_delayed_imports(pe);
4422
0
        pe_parse_exports(pe);
4423
4424
0
        break;
4425
0
      }
4426
0
    }
4427
0
  }
4428
4429
0
  return ERROR_SUCCESS;
4430
0
}
4431
4432
void free_dlls(IMPORTED_DLL* dll)
4433
0
{
4434
0
  IMPORTED_DLL* next_dll = NULL;
4435
0
  IMPORT_FUNCTION* func = NULL;
4436
0
  IMPORT_FUNCTION* next_func = NULL;
4437
4438
0
  while (dll)
4439
0
  {
4440
0
    if (dll->name)
4441
0
      yr_free(dll->name);
4442
4443
0
    func = dll->functions;
4444
4445
0
    while (func)
4446
0
    {
4447
0
      if (func->name)
4448
0
        yr_free(func->name);
4449
4450
0
      next_func = func->next;
4451
0
      yr_free(func);
4452
0
      func = next_func;
4453
0
    }
4454
4455
0
    next_dll = dll->next;
4456
0
    yr_free(dll);
4457
0
    dll = next_dll;
4458
0
  }
4459
0
}
4460
4461
int module_unload(YR_OBJECT* module_object)
4462
0
{
4463
0
  PE* pe = (PE*) module_object->data;
4464
4465
0
  if (pe == NULL)
4466
0
    return ERROR_SUCCESS;
4467
4468
0
  if (pe->hash_table != NULL)
4469
0
    yr_hash_table_destroy(
4470
0
        pe->hash_table, (YR_HASH_TABLE_FREE_VALUE_FUNC) yr_free);
4471
4472
0
  free_dlls(pe->imported_dlls);
4473
0
  free_dlls(pe->delay_imported_dlls);
4474
4475
0
  yr_free(pe);
4476
4477
0
  return ERROR_SUCCESS;
4478
0
}