Coverage Report

Created: 2025-08-29 07:07

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