Coverage Report

Created: 2025-12-14 06:59

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