Coverage Report

Created: 2025-07-23 06:46

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