Coverage Report

Created: 2023-06-07 07:19

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