Coverage Report

Created: 2026-02-09 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
727k
#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
764k
#define RESOURCE_CALLBACK_CONTINUE 0
82
764k
#define RESOURCE_CALLBACK_ABORT    1
83
84
21.6k
#define RESOURCE_ITERATOR_FINISHED 0
85
2.58M
#define RESOURCE_ITERATOR_ABORTED  1
86
87
1.35G
#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
764k
#define MAX_RESOURCES              65536
92
93
#define IS_RESOURCE_SUBDIRECTORY(entry) \
94
5.17M
  (yr_le32toh((entry)->OffsetToData) & 0x80000000)
95
96
2.58M
#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.96M
{
110
3.96M
  if ((uint8_t*) pointer < pe->data)
111
0
    return 0;
112
113
3.96M
  if ((uint8_t*) pointer >= pe->data + pe->data_size)
114
946
    return 0;
115
116
3.96M
  return pe->data + pe->data_size - (uint8_t*) pointer;
117
3.96M
}
118
119
static int wide_string_fits_in_pe(PE* pe, char* data)
120
18.0k
{
121
18.0k
  size_t i = 0;
122
18.0k
  size_t space_left = available_space(pe, data);
123
124
2.67M
  while (space_left >= 2)
125
2.66M
  {
126
2.66M
    if (data[i] == 0 && data[i + 1] == 0)
127
15.6k
      return 1;
128
2.65M
    space_left -= 2;
129
2.65M
    i += 2;
130
2.65M
  }
131
132
2.41k
  return 0;
133
18.0k
}
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.00k
{
140
7.00k
  PIMAGE_DOS_HEADER mz_header;
141
7.00k
  PRICH_SIGNATURE rich_signature = NULL;
142
143
7.00k
  DWORD* rich_ptr = NULL;
144
7.00k
  BYTE* raw_data = NULL;
145
7.00k
  BYTE* clear_data = NULL;
146
7.00k
  BYTE* version_data = NULL;
147
7.00k
  DWORD* p = NULL;
148
7.00k
  uint32_t nthdr_offset = 0;
149
7.00k
  uint32_t key = 0;
150
7.00k
  size_t rich_len = 0;
151
7.00k
  int64_t rich_count = 0;
152
153
7.00k
  if (pe->data_size < sizeof(IMAGE_DOS_HEADER))
154
0
    return;
155
156
7.00k
  mz_header = (PIMAGE_DOS_HEADER) pe->data;
157
158
7.00k
  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.00k
  nthdr_offset = yr_le32toh(mz_header->e_lfanew);
164
7.00k
  if (nthdr_offset > pe->data_size + sizeof(uint32_t) || nthdr_offset < 4)
165
2.32k
    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.68k
  p = (DWORD*) (pe->data + nthdr_offset - 4);
172
173
105k
  while (p >= (DWORD*) (pe->data + sizeof(IMAGE_DOS_HEADER)))
174
100k
  {
175
100k
    if (yr_le32toh(*p) == RICH_RICH)
176
389
    {
177
      // The XOR key is the dword following the Rich value. We  use this to find
178
      // DanS header only.
179
389
      key = *(p + 1);
180
389
      rich_ptr = p;
181
389
      --p;
182
389
      break;
183
389
    }
184
185
    // The NT header is 8 byte aligned so we can move back in 4 byte increments.
186
100k
    --p;
187
100k
  }
188
189
  // If we haven't found a key we can skip processing the rest.
190
4.68k
  if (key == 0)
191
4.29k
    return;
192
193
  // If we have found the key we need to now find the start (DanS).
194
144k
  while (p >= (DWORD*) (pe->data + sizeof(IMAGE_DOS_HEADER)))
195
144k
  {
196
144k
    if (yr_le32toh((*(p) ^ key)) == RICH_DANS)
197
314
    {
198
314
      rich_signature = (PRICH_SIGNATURE) p;
199
314
      break;
200
314
    }
201
202
144k
    --p;
203
144k
  }
204
205
389
  if (rich_signature == NULL)
206
75
    return;
207
208
  // Multiply by 4 because we are counting in DWORDs.
209
314
  rich_len = (rich_ptr - (DWORD*) rich_signature) * 4;
210
314
  raw_data = (BYTE*) yr_malloc(rich_len);
211
212
314
  if (!raw_data)
213
0
    return;
214
215
314
  memcpy(raw_data, rich_signature, rich_len);
216
217
314
  yr_set_integer(
218
314
      base_address + ((uint8_t*) rich_signature - pe->data),
219
314
      pe->object,
220
314
      "rich_signature.offset");
221
222
314
  yr_set_integer(rich_len, pe->object, "rich_signature.length");
223
314
  yr_set_integer(yr_le32toh(key), pe->object, "rich_signature.key");
224
225
314
  clear_data = (BYTE*) yr_malloc(rich_len);
226
227
314
  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
314
  memcpy(clear_data, raw_data, rich_len);
235
236
314
  for (rich_ptr = (DWORD*) clear_data;
237
102k
       rich_ptr < (DWORD*) (clear_data + rich_len);
238
102k
       rich_ptr++)
239
102k
  {
240
102k
    *rich_ptr ^= key;
241
102k
  }
242
243
314
  yr_set_sized_string(
244
314
      (char*) raw_data, rich_len, pe->object, "rich_signature.raw_data");
245
246
314
  yr_free(raw_data);
247
248
314
  yr_set_sized_string(
249
314
      (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
314
  rich_count = (rich_len - sizeof(RICH_SIGNATURE)) / sizeof(RICH_VERSION_INFO);
256
314
  version_data = (BYTE*) yr_malloc(rich_count * sizeof(DWORD));
257
314
  if (!version_data)
258
3
  {
259
3
    yr_free(clear_data);
260
3
    return;
261
3
  }
262
263
311
  rich_signature = (PRICH_SIGNATURE) clear_data;
264
50.9k
  for (int i = 0; i < rich_count; i++)
265
50.6k
  {
266
50.6k
    memcpy(
267
50.6k
        version_data + (i * sizeof(DWORD)),
268
50.6k
        &rich_signature->versions[i],
269
50.6k
        sizeof(DWORD));
270
50.6k
  }
271
272
311
  yr_set_sized_string(
273
311
      (char*) version_data,
274
311
      rich_count * sizeof(DWORD),
275
311
      pe->object,
276
311
      "rich_signature.version_data");
277
278
311
  yr_free(clear_data);
279
311
  yr_free(version_data);
280
311
}
281
282
static void pe_parse_debug_directory(PE* pe)
283
7.00k
{
284
7.00k
  PIMAGE_DATA_DIRECTORY data_dir;
285
7.00k
  PIMAGE_DEBUG_DIRECTORY debug_dir;
286
7.00k
  int64_t debug_dir_offset;
287
7.00k
  int i, dcount;
288
7.00k
  size_t pdb_path_len;
289
7.00k
  char* pdb_path = NULL;
290
291
7.00k
  data_dir = pe_get_directory_entry(pe, IMAGE_DIRECTORY_ENTRY_DEBUG);
292
293
7.00k
  if (data_dir == NULL)
294
0
    return;
295
296
7.00k
  if (yr_le32toh(data_dir->Size) == 0)
297
713
    return;
298
299
6.29k
  if (yr_le32toh(data_dir->VirtualAddress) == 0)
300
195
    return;
301
302
6.09k
  debug_dir_offset = pe_rva_to_offset(pe, yr_le32toh(data_dir->VirtualAddress));
303
304
6.09k
  if (debug_dir_offset < 0)
305
4.82k
    return;
306
307
1.27k
  dcount = yr_le32toh(data_dir->Size) / sizeof(IMAGE_DEBUG_DIRECTORY);
308
309
2.04M
  for (i = 0; i < dcount; i++)
310
2.04M
  {
311
2.04M
    int64_t pcv_hdr_offset = 0;
312
313
2.04M
    debug_dir = (PIMAGE_DEBUG_DIRECTORY) (pe->data + debug_dir_offset +
314
2.04M
                                          i * sizeof(IMAGE_DEBUG_DIRECTORY));
315
316
2.04M
    if (!struct_fits_in_pe(pe, debug_dir, IMAGE_DEBUG_DIRECTORY))
317
1.14k
      break;
318
319
2.04M
    if (yr_le32toh(debug_dir->Type) != IMAGE_DEBUG_TYPE_CODEVIEW)
320
2.03M
      continue;
321
322
    // The debug info offset may be present either as RVA or as raw offset
323
    // Sample: 0249e00b6d46bee5a17096559f18e671cd0ceee36373e8708f614a9a6c7c079e
324
5.84k
    if (debug_dir->AddressOfRawData != 0)
325
4.47k
    {
326
4.47k
      pcv_hdr_offset = pe_rva_to_offset(
327
4.47k
          pe, yr_le32toh(debug_dir->AddressOfRawData));
328
4.47k
    }
329
330
    // Give it chance to read it from the RAW offset
331
    // Sample: 735f72b3fcd72789f01e923c9de2a9ab5b5ffbece23633da81d976ad0ad159e3
332
5.84k
    if (pcv_hdr_offset <= 0 && debug_dir->PointerToRawData != 0)
333
2.40k
    {
334
2.40k
      pcv_hdr_offset = yr_le32toh(debug_dir->PointerToRawData);
335
2.40k
    }
336
337
5.84k
    if (pcv_hdr_offset <= 0)
338
642
      continue;
339
340
5.20k
    PCV_HEADER cv_hdr = (PCV_HEADER) (pe->data + pcv_hdr_offset);
341
342
5.20k
    if (!struct_fits_in_pe(pe, cv_hdr, CV_HEADER))
343
1.76k
      continue;
344
345
3.43k
    if (yr_le32toh(cv_hdr->dwSignature) == CVINFO_PDB20_CVSIGNATURE)
346
276
    {
347
276
      PCV_INFO_PDB20 pdb20 = (PCV_INFO_PDB20) cv_hdr;
348
349
276
      if (struct_fits_in_pe(pe, pdb20, CV_INFO_PDB20))
350
265
        pdb_path = (char*) (pdb20->PdbFileName);
351
276
    }
352
3.16k
    else if (yr_le32toh(cv_hdr->dwSignature) == CVINFO_PDB70_CVSIGNATURE)
353
261
    {
354
261
      PCV_INFO_PDB70 pdb70 = (PCV_INFO_PDB70) cv_hdr;
355
356
261
      if (struct_fits_in_pe(pe, pdb70, CV_INFO_PDB70))
357
251
        pdb_path = (char*) (pdb70->PdbFileName);
358
261
    }
359
2.90k
    else if (yr_le32toh(cv_hdr->dwSignature) == CODEVIEW_SIGNATURE_MTOC)
360
247
    {
361
247
      PMTOC_ENTRY mtoc = (PMTOC_ENTRY) cv_hdr;
362
363
247
      if (struct_fits_in_pe(pe, mtoc, MTOC_ENTRY))
364
234
        pdb_path = (char*) (mtoc->PdbFileName);
365
247
    }
366
367
3.43k
    if (pdb_path != NULL)
368
775
    {
369
775
      pdb_path_len = strnlen(
370
775
          pdb_path, yr_min(available_space(pe, pdb_path), YR_MAX_PATH));
371
372
775
      if (pdb_path_len >= 0 && pdb_path_len < YR_MAX_PATH)
373
95
      {
374
95
        yr_set_sized_string(pdb_path, pdb_path_len, pe->object, "pdb_path");
375
95
        break;
376
95
      }
377
775
    }
378
3.43k
  }
379
1.27k
}
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.58M
{
389
  // If high bit is set it is an offset relative to rsrc_data, which contains
390
  // a resource directory string.
391
392
2.58M
  if (yr_le32toh(entry->Name) & 0x80000000)
393
1.44M
  {
394
1.44M
    const PIMAGE_RESOURCE_DIR_STRING_U pNameString =
395
1.44M
        (PIMAGE_RESOURCE_DIR_STRING_U) (rsrc_data +
396
1.44M
                                        (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.44M
    if (!fits_in_pe(pe, pNameString, 2))
401
766k
      return NULL;
402
403
    // Sanity check for strings that are excesively large.
404
683k
    if (pNameString->Length > 1000)
405
74.6k
      return NULL;
406
407
    // Move past the length and make sure we have enough bytes for the string.
408
609k
    if (!fits_in_pe(
409
609k
            pe,
410
609k
            pNameString,
411
609k
            sizeof(uint16_t) + yr_le16toh(pNameString->Length) * 2))
412
2.03k
      return NULL;
413
414
607k
    return pNameString;
415
609k
  }
416
417
1.13M
  return NULL;
418
2.58M
}
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
21.6k
{
434
21.6k
  int i, result = RESOURCE_ITERATOR_FINISHED;
435
21.6k
  int total_entries;
436
437
21.6k
  PIMAGE_RESOURCE_DIRECTORY_ENTRY entry;
438
439
  // A few sanity checks to avoid corrupt files
440
441
21.6k
  if (yr_le32toh(resource_dir->Characteristics) != 0 ||
442
16.1k
      yr_le16toh(resource_dir->NumberOfNamedEntries) > 32768 ||
443
15.6k
      yr_le16toh(resource_dir->NumberOfIdEntries) > 32768)
444
6.28k
  {
445
6.28k
    return result;
446
6.28k
  }
447
448
15.3k
  total_entries = yr_le16toh(resource_dir->NumberOfNamedEntries) +
449
15.3k
                  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
15.3k
  entry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (resource_dir + 1);
456
457
15.3k
  if (!fits_in_pe(
458
15.3k
          pe, entry, total_entries * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY)))
459
744
    return result;
460
461
7.38M
  for (i = 0; i < total_entries; i++)
462
7.36M
  {
463
7.36M
    if (yr_le32toh(entry->OffsetToData) == 0)
464
4.78M
      continue;
465
466
2.58M
    switch (rsrc_tree_level)
467
2.58M
    {
468
67.6k
    case 0:
469
67.6k
      *type = yr_le32toh(entry->Name);
470
67.6k
      type_string = parse_resource_name(pe, rsrc_data, entry);
471
67.6k
      break;
472
405k
    case 1:
473
405k
      *id = yr_le32toh(entry->Name);
474
405k
      name_string = parse_resource_name(pe, rsrc_data, entry);
475
405k
      break;
476
2.11M
    case 2:
477
2.11M
      *language = yr_le32toh(entry->Name);
478
2.11M
      lang_string = parse_resource_name(pe, rsrc_data, entry);
479
2.11M
      break;
480
2.58M
    }
481
482
2.58M
    if (IS_RESOURCE_SUBDIRECTORY(entry) && rsrc_tree_level < 2)
483
160k
    {
484
160k
      PIMAGE_RESOURCE_DIRECTORY directory =
485
160k
          (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
160k
      if (directory != resource_dir &&
491
145k
          struct_fits_in_pe(pe, directory, IMAGE_RESOURCE_DIRECTORY))
492
20.0k
      {
493
20.0k
        result = _pe_iterate_resources(
494
20.0k
            pe,
495
20.0k
            directory,
496
20.0k
            rsrc_data,
497
20.0k
            rsrc_tree_level + 1,
498
20.0k
            type,
499
20.0k
            id,
500
20.0k
            language,
501
20.0k
            type_string,
502
20.0k
            name_string,
503
20.0k
            lang_string,
504
20.0k
            callback,
505
20.0k
            callback_data);
506
20.0k
      }
507
160k
    }
508
2.42M
    else
509
2.42M
    {
510
2.42M
      PIMAGE_RESOURCE_DATA_ENTRY data_entry =
511
2.42M
          (PIMAGE_RESOURCE_DATA_ENTRY) (rsrc_data + RESOURCE_OFFSET(entry));
512
513
2.42M
      if (struct_fits_in_pe(pe, data_entry, IMAGE_RESOURCE_DATA_ENTRY))
514
847k
      {
515
847k
        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
841k
            yr_le32toh(data_entry->Size) <= 0x3FFFFFFF)
521
764k
        {
522
764k
          if (callback(
523
764k
                  data_entry,
524
764k
                  *type,
525
764k
                  *id,
526
764k
                  *language,
527
764k
                  type_string,
528
764k
                  name_string,
529
764k
                  lang_string,
530
764k
                  callback_data) == RESOURCE_CALLBACK_ABORT)
531
0
          {
532
0
            result = RESOURCE_ITERATOR_ABORTED;
533
0
          }
534
764k
        }
535
847k
      }
536
2.42M
    }
537
538
2.58M
    if (result == RESOURCE_ITERATOR_ABORTED)
539
0
      break;
540
541
2.58M
    entry++;
542
2.58M
  }
543
544
14.6k
  return result;
545
14.6k
}
546
547
static int pe_iterate_resources(
548
    PE* pe,
549
    RESOURCE_CALLBACK_FUNC callback,
550
    void* callback_data)
551
7.00k
{
552
7.00k
  int64_t offset;
553
554
7.00k
  int type = -1;
555
7.00k
  int id = -1;
556
7.00k
  int language = -1;
557
558
7.00k
  IMAGE_RESOURCE_DIR_STRING_U* type_string = NULL;
559
7.00k
  IMAGE_RESOURCE_DIR_STRING_U* name_string = NULL;
560
7.00k
  IMAGE_RESOURCE_DIR_STRING_U* lang_string = NULL;
561
562
7.00k
  PIMAGE_DATA_DIRECTORY directory = pe_get_directory_entry(
563
7.00k
      pe, IMAGE_DIRECTORY_ENTRY_RESOURCE);
564
565
7.00k
  if (directory == NULL)
566
0
    return 0;
567
568
7.00k
  if (yr_le32toh(directory->VirtualAddress) != 0)
569
6.61k
  {
570
6.61k
    PIMAGE_RESOURCE_DIRECTORY rsrc_dir;
571
572
6.61k
    offset = pe_rva_to_offset(pe, yr_le32toh(directory->VirtualAddress));
573
574
6.61k
    if (offset < 0)
575
4.92k
      return 0;
576
577
1.69k
    rsrc_dir = (PIMAGE_RESOURCE_DIRECTORY) (pe->data + offset);
578
579
1.69k
    if (struct_fits_in_pe(pe, rsrc_dir, IMAGE_RESOURCE_DIRECTORY))
580
1.66k
    {
581
1.66k
      yr_set_integer(
582
1.66k
          yr_le32toh(rsrc_dir->TimeDateStamp),
583
1.66k
          pe->object,
584
1.66k
          "resource_timestamp");
585
586
1.66k
      yr_set_integer(
587
1.66k
          yr_le16toh(rsrc_dir->MajorVersion),
588
1.66k
          pe->object,
589
1.66k
          "resource_version.major");
590
591
1.66k
      yr_set_integer(
592
1.66k
          yr_le16toh(rsrc_dir->MinorVersion),
593
1.66k
          pe->object,
594
1.66k
          "resource_version.minor");
595
596
1.66k
      _pe_iterate_resources(
597
1.66k
          pe,
598
1.66k
          rsrc_dir,
599
1.66k
          pe->data + offset,
600
1.66k
          0,
601
1.66k
          &type,
602
1.66k
          &id,
603
1.66k
          &language,
604
1.66k
          type_string,
605
1.66k
          name_string,
606
1.66k
          lang_string,
607
1.66k
          callback,
608
1.66k
          callback_data);
609
610
1.66k
      return 1;
611
1.66k
    }
612
1.69k
  }
613
614
412
  return 0;
615
7.00k
}
616
617
// Align offset to a 32-bit boundary and add it to a pointer
618
619
#define ADD_OFFSET(ptr, offset) \
620
28.6k
  (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
18.4k
{
624
18.4k
  PVERSION_INFO version_info;
625
626
18.4k
  int64_t version_info_offset = pe_rva_to_offset(
627
18.4k
      pe, yr_le32toh(rsrc_data->OffsetToData));
628
629
18.4k
  if (version_info_offset < 0)
630
10.7k
    return;
631
632
7.69k
  version_info = (PVERSION_INFO) (pe->data + version_info_offset);
633
634
7.69k
  if (!struct_fits_in_pe(pe, version_info, VERSION_INFO))
635
289
    return;
636
637
7.40k
  if (!fits_in_pe(pe, version_info->Key, sizeof("VS_VERSION_INFO") * 2))
638
359
    return;
639
640
7.04k
  if (strcmp_w(version_info->Key, "VS_VERSION_INFO") != 0)
641
3.01k
    return;
642
643
4.03k
  version_info = ADD_OFFSET(version_info, sizeof(VERSION_INFO) + 86);
644
645
4.04k
  while (fits_in_pe(pe, version_info->Key, sizeof("VarFileInfo") * 2) &&
646
3.71k
         strcmp_w(version_info->Key, "VarFileInfo") == 0 &&
647
11
         yr_le16toh(version_info->Length) != 0)
648
10
  {
649
10
    version_info = ADD_OFFSET(version_info, yr_le16toh(version_info->Length));
650
10
  }
651
652
7.22k
  while (fits_in_pe(pe, version_info->Key, sizeof("StringFileInfo") * 2) &&
653
3.96k
         strcmp_w(version_info->Key, "StringFileInfo") == 0 &&
654
3.25k
         yr_le16toh(version_info->Length) != 0)
655
3.18k
  {
656
3.18k
    PVERSION_INFO string_table = ADD_OFFSET(
657
3.18k
        version_info, sizeof(VERSION_INFO) + 30);
658
659
3.18k
    version_info = ADD_OFFSET(version_info, yr_le16toh(version_info->Length));
660
661
7.12k
    while (struct_fits_in_pe(pe, string_table, VERSION_INFO) &&
662
5.19k
           wide_string_fits_in_pe(pe, string_table->Key) &&
663
4.50k
           yr_le16toh(string_table->Length) != 0 && string_table < version_info)
664
3.94k
    {
665
3.94k
      PVERSION_INFO string = ADD_OFFSET(
666
3.94k
          string_table,
667
3.94k
          sizeof(VERSION_INFO) + 2 * (strnlen_w(string_table->Key) + 1));
668
669
3.94k
      string_table = ADD_OFFSET(string_table, yr_le16toh(string_table->Length));
670
671
9.12k
      while (struct_fits_in_pe(pe, string, VERSION_INFO) &&
672
7.63k
             wide_string_fits_in_pe(pe, string->Key) &&
673
6.65k
             yr_le16toh(string->Length) != 0 && string < string_table)
674
5.18k
      {
675
5.18k
        char* string_value = (char*) ADD_OFFSET(
676
5.18k
            string, sizeof(VERSION_INFO) + 2 * (strnlen_w(string->Key) + 1));
677
678
5.18k
        if (wide_string_fits_in_pe(pe, string_value))
679
4.44k
        {
680
4.44k
          char key[64];
681
4.44k
          char value[256];
682
683
4.44k
          strlcpy_w(key, string->Key, sizeof(key));
684
4.44k
          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.44k
          if (yr_le16toh(string->ValueLength) == 0)
689
410
            value[yr_le16toh(string->ValueLength)] = '\0';
690
691
4.44k
          yr_set_string(value, pe->object, "version_info[%s]", key);
692
693
4.44k
          yr_set_string(
694
4.44k
              key, pe->object, "version_info_list[%i].key", pe->version_infos);
695
696
4.44k
          yr_set_string(
697
4.44k
              value,
698
4.44k
              pe->object,
699
4.44k
              "version_info_list[%i].value",
700
4.44k
              pe->version_infos);
701
702
4.44k
          pe->version_infos += 1;
703
4.44k
        }
704
705
5.18k
        string = ADD_OFFSET(string, yr_le16toh(string->Length));
706
5.18k
      }
707
3.94k
    }
708
3.18k
  }
709
4.03k
}
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
2.18M
{
718
2.18M
  if (rsrc_string)
719
886k
  {
720
    // Multiply by 2 because it is a Unicode string.
721
886k
    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
886k
    if (fits_in_pe(pe, rsrc_string->NameString, length))
726
886k
    {
727
886k
      yr_set_sized_string(
728
886k
          (char*) rsrc_string->NameString,
729
886k
          length,
730
886k
          pe->object,
731
886k
          string_description,
732
886k
          pe->resources);
733
886k
    }
734
886k
  }
735
1.29M
  else
736
1.29M
  {
737
1.29M
    if (rsrc_int != -1)
738
1.29M
      yr_set_integer(rsrc_int, pe->object, int_description, pe->resources);
739
1.29M
  }
740
2.18M
}
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
764k
{
752
  // Don't collect too many resources.
753
764k
  if (pe->resources >= MAX_RESOURCES)
754
36.8k
    return RESOURCE_CALLBACK_CONTINUE;
755
756
727k
  yr_set_integer(
757
727k
      yr_le32toh(rsrc_data->OffsetToData),
758
727k
      pe->object,
759
727k
      "resources[%i].rva",
760
727k
      pe->resources);
761
762
727k
  int64_t offset = pe_rva_to_offset(pe, yr_le32toh(rsrc_data->OffsetToData));
763
764
727k
  if (offset < 0)
765
55.9k
    offset = YR_UNDEFINED;
766
767
727k
  yr_set_integer(offset, pe->object, "resources[%i].offset", pe->resources);
768
769
727k
  yr_set_integer(
770
727k
      yr_le32toh(rsrc_data->Size),
771
727k
      pe->object,
772
727k
      "resources[%i].length",
773
727k
      pe->resources);
774
775
727k
  pe_set_resource_string_or_id(
776
727k
      type_string,
777
727k
      rsrc_type,
778
727k
      "resources[%i].type_string",
779
727k
      "resources[%i].type",
780
727k
      pe);
781
782
727k
  pe_set_resource_string_or_id(
783
727k
      name_string,
784
727k
      rsrc_id,
785
727k
      "resources[%i].name_string",
786
727k
      "resources[%i].id",
787
727k
      pe);
788
789
727k
  pe_set_resource_string_or_id(
790
727k
      lang_string,
791
727k
      rsrc_language,
792
727k
      "resources[%i].language_string",
793
727k
      "resources[%i].language",
794
727k
      pe);
795
796
  // Resources we do extra parsing on
797
727k
  if (rsrc_type == RESOURCE_TYPE_VERSION)
798
18.4k
    pe_parse_version_info(rsrc_data, pe);
799
800
727k
  pe->resources += 1;
801
727k
  return RESOURCE_CALLBACK_CONTINUE;
802
764k
}
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
4.01M
{
809
4.01M
  if (!strcmp(name, ""))
810
827k
    return 0;
811
812
3.19M
  size_t i = 0;
813
24.4M
  for (char c = name[i]; c != '\x00'; c = name[++i])
814
23.1M
  {
815
23.1M
    if (!(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z') &&
816
4.19M
        !(c >= '0' && c <= '9') && c != '.' && c != '_' && c != '?' &&
817
1.96M
        c != '@' && c != '$' && c != '(' && c != ')' && c != '<' && c != '>')
818
1.87M
      return 0;
819
23.1M
  }
820
1.31M
  return 1;
821
3.19M
}
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
81.8k
{
829
81.8k
  IMPORT_FUNCTION* head = NULL;
830
81.8k
  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
81.8k
  int parsed_imports = 0;
836
837
81.8k
  int64_t offset = pe_rva_to_offset(
838
81.8k
      pe, yr_le32toh(import_descriptor->OriginalFirstThunk));
839
840
  // I've seen binaries where OriginalFirstThunk is zero. In this case
841
  // use FirstThunk.
842
843
81.8k
  if (offset <= 0)
844
63.1k
    offset = pe_rva_to_offset(pe, yr_le32toh(import_descriptor->FirstThunk));
845
846
81.8k
  if (offset < 0)
847
12.1k
    return NULL;
848
849
69.6k
  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
55.2M
    while (struct_fits_in_pe(pe, thunks64, IMAGE_THUNK_DATA64) &&
855
55.2M
           yr_le64toh(thunks64->u1.Ordinal) != 0 &&
856
55.2M
           parsed_imports < MAX_PE_IMPORTS &&
857
55.2M
           *num_function_imports < MAX_PE_IMPORTS)
858
55.2M
    {
859
55.2M
      char* name = NULL;
860
55.2M
      uint16_t ordinal = 0;
861
55.2M
      uint8_t has_ordinal = 0;
862
55.2M
      uint64_t rva_address = 0;
863
864
55.2M
      parsed_imports++;
865
866
55.2M
      if (!(yr_le64toh(thunks64->u1.Ordinal) & IMAGE_ORDINAL_FLAG64))
867
34.3M
      {
868
        // If imported by name
869
34.3M
        offset = pe_rva_to_offset(pe, yr_le64toh(thunks64->u1.Function));
870
871
34.3M
        if (offset >= 0)
872
164k
        {
873
164k
          PIMAGE_IMPORT_BY_NAME import = (PIMAGE_IMPORT_BY_NAME) (pe->data +
874
164k
                                                                  offset);
875
876
164k
          if (struct_fits_in_pe(pe, import, IMAGE_IMPORT_BY_NAME))
877
164k
          {
878
164k
            name = (char*) yr_strndup(
879
164k
                (char*) import->Name,
880
164k
                yr_min(available_space(pe, import->Name), 512));
881
164k
          }
882
164k
        }
883
34.3M
      }
884
20.8M
      else
885
20.8M
      {
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
20.8M
        if (yr_le64toh(thunks64->u1.Ordinal) <= 0x800000000000ffff)
890
1.93k
        {
891
1.93k
          ordinal = yr_le64toh(thunks64->u1.Ordinal) & 0xFFFF;
892
1.93k
          name = ord_lookup(dll_name, ordinal);
893
1.93k
          has_ordinal = 1;
894
1.93k
        }
895
20.8M
      }
896
897
55.2M
      rva_address = yr_le32toh(import_descriptor->FirstThunk) +
898
55.2M
                    (sizeof(uint64_t) * func_idx);
899
900
55.2M
      if (name != NULL && !valid_function_name(name))
901
40.6k
      {
902
40.6k
        yr_free(name);
903
40.6k
        thunks64++;
904
40.6k
        func_idx++;
905
40.6k
        continue;
906
40.6k
      }
907
908
55.2M
      if (name != NULL || has_ordinal == 1)
909
125k
      {
910
125k
        IMPORT_FUNCTION* imported_func = (IMPORT_FUNCTION*) yr_calloc(
911
125k
            1, sizeof(IMPORT_FUNCTION));
912
913
125k
        if (imported_func == NULL)
914
0
        {
915
0
          yr_free(name);
916
0
        }
917
125k
        else
918
125k
        {
919
125k
          imported_func->name = name;
920
125k
          imported_func->ordinal = ordinal;
921
125k
          imported_func->has_ordinal = has_ordinal;
922
125k
          imported_func->rva = rva_address;
923
125k
          imported_func->next = NULL;
924
925
125k
          if (head == NULL)
926
5.84k
            head = imported_func;
927
928
125k
          if (tail != NULL)
929
119k
            tail->next = imported_func;
930
931
125k
          tail = imported_func;
932
125k
          (*num_function_imports)++;
933
125k
        }
934
125k
      }
935
936
55.2M
      thunks64++;
937
55.2M
      func_idx++;
938
55.2M
    }
939
10.4k
  }
940
59.1k
  else
941
59.1k
  {
942
59.1k
    PIMAGE_THUNK_DATA32 thunks32 = (PIMAGE_THUNK_DATA32) (pe->data + offset);
943
59.1k
    uint32_t func_idx = 0;
944
945
397M
    while (struct_fits_in_pe(pe, thunks32, IMAGE_THUNK_DATA32) &&
946
397M
           yr_le32toh(thunks32->u1.Ordinal) != 0 &&
947
397M
           parsed_imports < MAX_PE_IMPORTS &&
948
397M
           *num_function_imports < MAX_PE_IMPORTS)
949
397M
    {
950
397M
      char* name = NULL;
951
397M
      uint16_t ordinal = 0;
952
397M
      uint8_t has_ordinal = 0;
953
397M
      uint32_t rva_address = 0;
954
955
397M
      parsed_imports++;
956
957
397M
      if (!(yr_le32toh(thunks32->u1.Ordinal) & IMAGE_ORDINAL_FLAG32))
958
17.2M
      {
959
        // If imported by name
960
17.2M
        offset = pe_rva_to_offset(pe, yr_le32toh(thunks32->u1.Function));
961
962
17.2M
        if (offset >= 0)
963
3.27M
        {
964
3.27M
          PIMAGE_IMPORT_BY_NAME import = (PIMAGE_IMPORT_BY_NAME) (pe->data +
965
3.27M
                                                                  offset);
966
967
3.27M
          if (struct_fits_in_pe(pe, import, IMAGE_IMPORT_BY_NAME))
968
3.26M
          {
969
3.26M
            name = (char*) yr_strndup(
970
3.26M
                (char*) import->Name,
971
3.26M
                yr_min(available_space(pe, import->Name), 512));
972
3.26M
          }
973
3.27M
        }
974
17.2M
      }
975
379M
      else
976
379M
      {
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
379M
        if (yr_le32toh(thunks32->u1.Ordinal) <= 0x8000ffff)
981
591k
        {
982
591k
          ordinal = yr_le32toh(thunks32->u1.Ordinal) & 0xFFFF;
983
591k
          name = ord_lookup(dll_name, ordinal);
984
591k
          has_ordinal = 1;
985
591k
        }
986
379M
      }
987
988
397M
      rva_address = yr_le32toh(import_descriptor->FirstThunk) +
989
397M
                    (sizeof(uint32_t) * func_idx);
990
991
397M
      if (name != NULL && !valid_function_name(name))
992
2.66M
      {
993
2.66M
        yr_free(name);
994
2.66M
        thunks32++;
995
2.66M
        func_idx++;
996
2.66M
        continue;
997
2.66M
      }
998
999
394M
      if (name != NULL || has_ordinal == 1)
1000
1.18M
      {
1001
1.18M
        IMPORT_FUNCTION* imported_func = (IMPORT_FUNCTION*) yr_calloc(
1002
1.18M
            1, sizeof(IMPORT_FUNCTION));
1003
1004
1.18M
        if (imported_func == NULL)
1005
0
        {
1006
0
          yr_free(name);
1007
0
        }
1008
1.18M
        else
1009
1.18M
        {
1010
1.18M
          imported_func->name = name;
1011
1.18M
          imported_func->ordinal = ordinal;
1012
1.18M
          imported_func->has_ordinal = has_ordinal;
1013
1.18M
          imported_func->rva = rva_address;
1014
1.18M
          imported_func->next = NULL;
1015
1016
1.18M
          if (head == NULL)
1017
53.0k
            head = imported_func;
1018
1019
1.18M
          if (tail != NULL)
1020
1.13M
            tail->next = imported_func;
1021
1022
1.18M
          tail = imported_func;
1023
1.18M
          (*num_function_imports)++;
1024
1.18M
        }
1025
1.18M
      }
1026
1027
394M
      thunks32++;
1028
394M
      func_idx++;
1029
394M
    }
1030
59.1k
  }
1031
1032
69.6k
  return head;
1033
81.8k
}
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
182k
{
1063
182k
  const unsigned char* c = (const unsigned char*) dll_name;
1064
182k
  size_t l = 0;
1065
1066
6.08M
  while (l < n && *c != '\0')
1067
5.96M
  {
1068
5.96M
    if (*c < ' ' || *c > 0x7e || *c == '\"' || *c == '*' || *c == '<' ||
1069
5.90M
        *c == '>' || *c == '?' || *c == '|')
1070
62.5k
    {
1071
62.5k
      return false;
1072
62.5k
    }
1073
1074
5.89M
    c++;
1075
5.89M
    l++;
1076
5.89M
  }
1077
1078
120k
  return (l > 0 && l < n);
1079
182k
}
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.17k
{
1090
6.17k
  int dll_cnt = 0;
1091
1092
70.9k
  for (; dll != NULL; dll = dll->next, dll_cnt++)
1093
64.7k
  {
1094
64.7k
    int fun_cnt = 0;
1095
1096
9.27M
    for (IMPORT_FUNCTION* func = dll->functions; func != NULL;
1097
9.20M
         func = func->next, fun_cnt++)
1098
9.20M
    {
1099
9.20M
      yr_set_string(func->name, pe->object, fun_name, dll_cnt, fun_cnt);
1100
1101
9.20M
      if (func->has_ordinal)
1102
8.03M
        yr_set_integer(
1103
9.20M
            func->ordinal, pe->object, fun_ordinal, dll_cnt, fun_cnt);
1104
1.17M
      else
1105
1.17M
        yr_set_integer(YR_UNDEFINED, pe->object, fun_ordinal, dll_cnt, fun_cnt);
1106
1107
9.20M
      if (func->rva)
1108
9.20M
        yr_set_integer(func->rva, pe->object, rva, dll_cnt, fun_cnt);
1109
115
      else
1110
115
        yr_set_integer(YR_UNDEFINED, pe->object, rva, dll_cnt, fun_cnt);
1111
9.20M
    }
1112
64.7k
    yr_set_string(dll->name, pe->object, dll_name, dll_cnt);
1113
64.7k
    yr_set_integer(fun_cnt, pe->object, dll_number_of_functions, dll_cnt);
1114
64.7k
  }
1115
6.17k
}
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.00k
{
1125
7.00k
  int64_t offset;
1126
7.00k
  int parsed_imports = 0;        // Number of parsed DLLs
1127
7.00k
  int num_imports = 0;           // Number of imported DLLs
1128
7.00k
  int num_function_imports = 0;  // Total number of functions imported
1129
1130
7.00k
  IMPORTED_DLL* head = NULL;
1131
7.00k
  IMPORTED_DLL* tail = NULL;
1132
1133
7.00k
  PIMAGE_IMPORT_DESCRIPTOR imports;
1134
7.00k
  PIMAGE_DATA_DIRECTORY directory;
1135
1136
  // Default to 0 imports until we know there are any
1137
7.00k
  yr_set_integer(0, pe->object, "number_of_imports");
1138
7.00k
  yr_set_integer(0, pe->object, "number_of_imported_functions");
1139
1140
7.00k
  directory = pe_get_directory_entry(pe, IMAGE_DIRECTORY_ENTRY_IMPORT);
1141
1142
7.00k
  if (directory == NULL)
1143
0
    return NULL;
1144
1145
7.00k
  if (yr_le32toh(directory->VirtualAddress) == 0)
1146
542
    return NULL;
1147
1148
6.46k
  offset = pe_rva_to_offset(pe, yr_le32toh(directory->VirtualAddress));
1149
1150
6.46k
  if (offset < 0)
1151
1.79k
    return NULL;
1152
1153
4.67k
  imports = (PIMAGE_IMPORT_DESCRIPTOR) (pe->data + offset);
1154
1155
514k
  while (struct_fits_in_pe(pe, imports, IMAGE_IMPORT_DESCRIPTOR) &&
1156
511k
         yr_le32toh(imports->Name) != 0 && parsed_imports < MAX_PE_IMPORTS)
1157
510k
  {
1158
510k
    parsed_imports++;
1159
1160
510k
    int64_t offset = pe_rva_to_offset(pe, yr_le32toh(imports->Name));
1161
1162
510k
    if (offset >= 0)
1163
174k
    {
1164
174k
      IMPORTED_DLL* imported_dll;
1165
1166
174k
      char* dll_name = (char*) (pe->data + offset);
1167
1168
174k
      if (!pe_valid_dll_name(
1169
174k
              dll_name,
1170
174k
              yr_min(
1171
                  // DLL names longer than MAX_IMPORT_DLL_NAME_LENGTH
1172
                  // are considered invalid.
1173
174k
                  pe->data_size - (size_t) offset,
1174
174k
                  MAX_IMPORT_DLL_NAME_LENGTH)))
1175
92.2k
      {
1176
92.2k
        imports++;
1177
92.2k
        continue;
1178
92.2k
      }
1179
1180
81.8k
      imported_dll = (IMPORTED_DLL*) yr_calloc(1, sizeof(IMPORTED_DLL));
1181
1182
81.8k
      if (imported_dll != NULL)
1183
81.8k
      {
1184
81.8k
        IMPORT_FUNCTION* functions = pe_parse_import_descriptor(
1185
81.8k
            pe, imports, dll_name, &num_function_imports);
1186
1187
81.8k
        if (functions != NULL)
1188
58.8k
        {
1189
58.8k
          imported_dll->name = yr_strdup(dll_name);
1190
58.8k
          imported_dll->functions = functions;
1191
58.8k
          imported_dll->next = NULL;
1192
1193
58.8k
          if (head == NULL)
1194
3.95k
            head = imported_dll;
1195
1196
58.8k
          if (tail != NULL)
1197
54.8k
            tail->next = imported_dll;
1198
1199
58.8k
          tail = imported_dll;
1200
58.8k
          num_imports++;
1201
58.8k
        }
1202
22.9k
        else
1203
22.9k
        {
1204
22.9k
          yr_free(imported_dll);
1205
22.9k
        }
1206
81.8k
      }
1207
81.8k
    }
1208
1209
418k
    imports++;
1210
418k
  }
1211
1212
4.67k
  yr_set_integer(num_imports, pe->object, "number_of_imports");
1213
4.67k
  yr_set_integer(
1214
4.67k
      num_function_imports, pe->object, "number_of_imported_functions");
1215
4.67k
  pe_set_imports(
1216
4.67k
      pe,
1217
4.67k
      head,
1218
4.67k
      "import_details[%i].library_name",
1219
4.67k
      "import_details[%i].number_of_functions",
1220
4.67k
      "import_details[%i].functions[%i].name",
1221
4.67k
      "import_details[%i].functions[%i].ordinal",
1222
4.67k
      "import_details[%i].functions[%i].rva");
1223
1224
4.67k
  return head;
1225
6.46k
}
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
19.5M
{
1236
  // Ignore zero items
1237
19.5M
  if (virtual_address != 0)
1238
19.5M
  {
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
19.5M
    if (virtual_address > image_base)
1252
8.57M
    {
1253
8.57M
      virtual_address = virtual_address - image_base;
1254
8.57M
    }
1255
19.5M
  }
1256
1257
19.5M
  return virtual_address;
1258
19.5M
}
1259
1260
int pe_is_termination_delay_import_entry(
1261
    PIMAGE_DELAYLOAD_DESCRIPTOR importDescriptor)
1262
11.6k
{
1263
11.6k
  return (
1264
11.6k
      importDescriptor->Attributes.AllAttributes == 0 &&
1265
10.5k
      importDescriptor->DllNameRVA == 0 &&
1266
219
      importDescriptor->ModuleHandleRVA == 0 &&
1267
204
      importDescriptor->ImportAddressTableRVA == 0 &&
1268
152
      importDescriptor->ImportNameTableRVA == 0 &&
1269
133
      importDescriptor->BoundImportAddressTableRVA == 0 &&
1270
91
      importDescriptor->UnloadInformationTableRVA == 0 &&
1271
44
      importDescriptor->TimeDateStamp == 0);
1272
11.6k
}
1273
1274
char* pe_parse_delay_import_dll_name(PE* pe, uint64_t rva)
1275
10.2k
{
1276
10.2k
  const int64_t offset = pe_rva_to_offset(pe, rva);
1277
1278
10.2k
  if (offset < 0)
1279
1.75k
    return NULL;
1280
1281
8.54k
  char* dll_name = (char*) (pe->data + offset);
1282
1283
8.54k
  if (!pe_valid_dll_name(dll_name, pe->data_size - (size_t) offset))
1284
2.59k
    return NULL;
1285
1286
5.94k
  return yr_strdup(dll_name);
1287
8.54k
}
1288
1289
uint64_t pe_parse_delay_import_pointer(
1290
    PE* pe,
1291
    uint64_t pointerSize,
1292
    uint64_t rva)
1293
53.9M
{
1294
53.9M
  const int64_t offset = pe_rva_to_offset(pe, rva);
1295
1296
53.9M
  if (offset < 0)
1297
2.43k
    return YR_UNDEFINED;
1298
1299
53.9M
  const uint8_t* data = pe->data + offset;
1300
1301
53.9M
  if (!fits_in_pe(pe, data, pointerSize))
1302
3.01k
    return YR_UNDEFINED;
1303
1304
53.9M
  if (IS_64BITS_PE(pe))
1305
52.8M
    return yr_le64toh(*(uint64_t*) data);
1306
1.10M
  else
1307
1.10M
    return yr_le32toh(*(uint32_t*) data);
1308
53.9M
}
1309
1310
static void* pe_parse_delayed_imports(PE* pe)
1311
7.00k
{
1312
7.00k
  int64_t offset;
1313
7.00k
  uint64_t num_imports = 0;           // Number of imported DLLs
1314
7.00k
  uint64_t num_function_imports = 0;  // Total number of functions imported
1315
7.00k
  uint64_t image_base = OptionalHeader(pe, ImageBase);
1316
7.00k
  uint64_t size_of_image = OptionalHeader(pe, SizeOfImage);
1317
7.00k
  uint64_t pointer_size = (IS_64BITS_PE(pe)) ? 8 : 4;
1318
7.00k
  uint64_t ordinal_mask = (IS_64BITS_PE(pe)) ? IMAGE_ORDINAL_FLAG64
1319
7.00k
                                             : IMAGE_ORDINAL_FLAG32;
1320
1321
7.00k
  IMPORTED_DLL* head_dll = NULL;
1322
7.00k
  IMPORTED_DLL* tail_dll = NULL;
1323
1324
7.00k
  IMPORT_FUNCTION* head_fun = NULL;
1325
7.00k
  IMPORT_FUNCTION* tail_fun = NULL;
1326
1327
7.00k
  PIMAGE_DELAYLOAD_DESCRIPTOR import_descriptor = NULL;
1328
7.00k
  PIMAGE_DATA_DIRECTORY directory = NULL;
1329
1330
  // Default to 0 imports until we know there are any
1331
7.00k
  yr_set_integer(0, pe->object, "number_of_delayed_imports");
1332
7.00k
  yr_set_integer(0, pe->object, "number_of_delayed_imported_functions");
1333
1334
7.00k
  directory = pe_get_directory_entry(pe, IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT);
1335
1336
7.00k
  if (directory == NULL)
1337
0
    return NULL;
1338
1339
7.00k
  if (yr_le32toh(directory->VirtualAddress) == 0)
1340
442
    return NULL;
1341
1342
6.56k
  offset = pe_rva_to_offset(pe, yr_le32toh(directory->VirtualAddress));
1343
1344
6.56k
  if (offset < 0)
1345
5.06k
    return NULL;
1346
1347
1.50k
  import_descriptor = (PIMAGE_DELAYLOAD_DESCRIPTOR) (pe->data + offset);
1348
1349
1.50k
  for (; struct_fits_in_pe(pe, import_descriptor, IMAGE_DELAYLOAD_DESCRIPTOR);
1350
10.2k
       import_descriptor++)
1351
11.6k
  {
1352
    // Check for the termination entry
1353
11.6k
    if (pe_is_termination_delay_import_entry(import_descriptor))
1354
5
      break;
1355
1356
11.6k
    DWORD Attributes = yr_le32toh(import_descriptor->Attributes.AllAttributes);
1357
11.6k
    DWORD DllNameRVA = yr_le32toh(import_descriptor->DllNameRVA);
1358
11.6k
    DWORD ModuleHandleRVA = yr_le32toh(import_descriptor->ModuleHandleRVA);
1359
11.6k
    DWORD ImportAddressTableRVA = yr_le32toh(
1360
11.6k
        import_descriptor->ImportAddressTableRVA);
1361
11.6k
    DWORD ImportNameTableRVA = yr_le32toh(
1362
11.6k
        import_descriptor->ImportNameTableRVA);
1363
11.6k
    DWORD BoundImportAddressTableRVA = yr_le32toh(
1364
11.6k
        import_descriptor->BoundImportAddressTableRVA);
1365
11.6k
    DWORD UnloadInformationTableRVA = yr_le32toh(
1366
11.6k
        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
11.6k
    if (Attributes > 0x1)
1371
924
      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
10.6k
    if (!IS_64BITS_PE(pe) && !Attributes)
1378
4.59k
    {
1379
4.59k
      DllNameRVA = (DWORD) pe_normalize_delay_import_value(
1380
4.59k
          image_base, DllNameRVA);
1381
4.59k
      ModuleHandleRVA = (DWORD) pe_normalize_delay_import_value(
1382
4.59k
          image_base, ModuleHandleRVA);
1383
4.59k
      ImportAddressTableRVA = (DWORD) pe_normalize_delay_import_value(
1384
4.59k
          image_base, ImportAddressTableRVA);
1385
4.59k
      ImportNameTableRVA = (DWORD) pe_normalize_delay_import_value(
1386
4.59k
          image_base, ImportNameTableRVA);
1387
4.59k
      BoundImportAddressTableRVA = (DWORD) pe_normalize_delay_import_value(
1388
4.59k
          image_base, BoundImportAddressTableRVA);
1389
4.59k
      UnloadInformationTableRVA = (DWORD) pe_normalize_delay_import_value(
1390
4.59k
          image_base, UnloadInformationTableRVA);
1391
4.59k
    }
1392
1393
    // Stop on blatantly invalid delay import entries (old PELIB behavior)
1394
10.6k
    if (ImportNameTableRVA >= size_of_image ||
1395
10.5k
        ImportAddressTableRVA >= size_of_image ||
1396
10.4k
        DllNameRVA < sizeof(IMAGE_DOS_HEADER) ||
1397
10.3k
        ImportNameTableRVA < sizeof(IMAGE_DOS_HEADER))
1398
380
      break;
1399
1400
10.2k
    char* dll_name = pe_parse_delay_import_dll_name(pe, DllNameRVA);
1401
1402
10.2k
    if (dll_name == NULL)
1403
4.34k
      continue;
1404
1405
5.94k
    IMPORTED_DLL* imported_dll = (IMPORTED_DLL*) yr_calloc(
1406
5.94k
        1, sizeof(IMPORTED_DLL));
1407
1408
5.94k
    if (imported_dll == NULL)
1409
0
    {
1410
0
      yr_free(dll_name);
1411
0
      continue;
1412
0
    }
1413
1414
5.94k
    imported_dll->name = dll_name;
1415
5.94k
    imported_dll->next = NULL;
1416
5.94k
    imported_dll->functions = NULL;
1417
1418
5.94k
    head_fun = tail_fun = NULL;
1419
1420
5.94k
    uint64_t name_rva = ImportNameTableRVA;
1421
5.94k
    uint64_t func_rva = ImportAddressTableRVA;
1422
1423
5.94k
    for (;;)
1424
26.9M
    {
1425
26.9M
      uint64_t nameAddress = pe_parse_delay_import_pointer(
1426
26.9M
          pe, pointer_size, name_rva);
1427
1428
26.9M
      uint64_t funcAddress = pe_parse_delay_import_pointer(
1429
26.9M
          pe, pointer_size, func_rva);
1430
1431
      // Value of YR_UNDEFINED means that value is outside of pe->data
1432
26.9M
      if (nameAddress == YR_UNDEFINED || funcAddress == YR_UNDEFINED)
1433
4.56k
        break;
1434
1435
      // Value of zero means that this is the end of the bound import name table
1436
26.9M
      if (nameAddress == 0 || funcAddress == 0)
1437
1.38k
        break;
1438
1439
26.9M
      char* func_name;
1440
26.9M
      uint8_t has_ordinal = 0;
1441
1442
      // Check name address. It could be ordinal, VA or RVA
1443
26.9M
      if (!(nameAddress & ordinal_mask))
1444
19.5M
      {
1445
        // Convert name address to RVA, if needed
1446
19.5M
        if (!Attributes)
1447
19.5M
          nameAddress = pe_normalize_delay_import_value(
1448
19.5M
              image_base, nameAddress);
1449
1450
19.5M
        offset = pe_rva_to_offset(pe, nameAddress + sizeof(uint16_t));
1451
1452
19.5M
        if (offset < 0)
1453
19.0M
        {
1454
19.0M
          name_rva += pointer_size;
1455
19.0M
          func_rva += pointer_size;
1456
19.0M
          continue;
1457
19.0M
        }
1458
1459
454k
        func_name = (char*) yr_strndup(
1460
454k
            (char*) (pe->data + offset),
1461
454k
            yr_min(available_space(pe, (char*) (pe->data + offset)), 512));
1462
454k
      }
1463
7.44M
      else
1464
7.44M
      {
1465
        // If imported by ordinal. Lookup the ordinal.
1466
7.44M
        func_name = ord_lookup(dll_name, nameAddress & 0xFFFF);
1467
7.44M
        has_ordinal = 1;
1468
7.44M
      }
1469
1470
7.89M
      IMPORT_FUNCTION* imported_func = (IMPORT_FUNCTION*) yr_malloc(
1471
7.89M
          sizeof(IMPORT_FUNCTION));
1472
1473
7.89M
      if (imported_func == NULL)
1474
0
        break;
1475
1476
7.89M
      imported_func->name = func_name;
1477
7.89M
      imported_func->rva = func_rva;
1478
7.89M
      imported_func->has_ordinal = has_ordinal;
1479
7.89M
      imported_func->ordinal = (has_ordinal) ? nameAddress & 0xFFFF : 0;
1480
7.89M
      imported_func->next = NULL;
1481
1482
7.89M
      num_function_imports++;
1483
7.89M
      name_rva += pointer_size;
1484
7.89M
      func_rva += pointer_size;
1485
1486
7.89M
      if (head_fun == NULL)
1487
4.01k
        head_fun = imported_func;
1488
1489
7.89M
      if (tail_fun != NULL)
1490
7.89M
        tail_fun->next = imported_func;
1491
1492
7.89M
      tail_fun = imported_func;
1493
7.89M
    }
1494
1495
5.94k
    num_imports++;
1496
1497
5.94k
    imported_dll->functions = head_fun;
1498
1499
5.94k
    if (head_dll == NULL)
1500
528
      head_dll = imported_dll;
1501
1502
5.94k
    if (tail_dll != NULL)
1503
5.42k
      tail_dll->next = imported_dll;
1504
1505
5.94k
    tail_dll = imported_dll;
1506
5.94k
  }
1507
1508
1.50k
  yr_set_integer(num_imports, pe->object, "number_of_delayed_imports");
1509
1.50k
  yr_set_integer(
1510
1.50k
      num_function_imports, pe->object, "number_of_delayed_imported_functions");
1511
1512
1.50k
  pe_set_imports(
1513
1.50k
      pe,
1514
1.50k
      head_dll,
1515
1.50k
      "delayed_import_details[%i].library_name",
1516
1.50k
      "delayed_import_details[%i].number_of_functions",
1517
1.50k
      "delayed_import_details[%i].functions[%i].name",
1518
1.50k
      "delayed_import_details[%i].functions[%i].ordinal",
1519
1.50k
      "delayed_import_details[%i].functions[%i].rva");
1520
1521
1.50k
  return head_dll;
1522
6.56k
}
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.00k
{
1531
7.00k
  PIMAGE_DATA_DIRECTORY directory;
1532
7.00k
  PIMAGE_EXPORT_DIRECTORY exports;
1533
1534
7.00k
  int64_t offset;
1535
7.00k
  int64_t export_start;
1536
1537
7.00k
  uint32_t i, j;
1538
7.00k
  uint32_t number_of_exports;
1539
7.00k
  uint32_t number_of_names;
1540
7.00k
  uint32_t ordinal_base;
1541
1542
7.00k
  size_t export_size;
1543
7.00k
  size_t remaining;
1544
7.00k
  size_t name_len;
1545
1546
7.00k
  uint32_t exp_sz = 0;
1547
7.00k
  DWORD* names = NULL;
1548
7.00k
  WORD* ordinals = NULL;
1549
7.00k
  DWORD* function_addrs = NULL;
1550
1551
  // If not a PE file, return YR_UNDEFINED
1552
1553
7.00k
  if (pe == NULL)
1554
0
    return;
1555
1556
  // Default to 0 exports until we know there are any
1557
7.00k
  yr_set_integer(0, pe->object, "number_of_exports");
1558
1559
7.00k
  directory = pe_get_directory_entry(pe, IMAGE_DIRECTORY_ENTRY_EXPORT);
1560
1561
7.00k
  if (directory == NULL)
1562
0
    return;
1563
1564
7.00k
  if (yr_le32toh(directory->VirtualAddress) == 0)
1565
468
    return;
1566
1567
6.53k
  offset = pe_rva_to_offset(pe, yr_le32toh(directory->VirtualAddress));
1568
1569
6.53k
  if (offset < 0)
1570
5.47k
    return;
1571
1572
1.05k
  export_start = offset;
1573
1.05k
  export_size = yr_le32toh(directory->Size);
1574
1575
1.05k
  exports = (PIMAGE_EXPORT_DIRECTORY) (pe->data + offset);
1576
1577
1.05k
  if (!struct_fits_in_pe(pe, exports, IMAGE_EXPORT_DIRECTORY))
1578
37
    return;
1579
1580
1.02k
  number_of_exports = yr_min(
1581
1.02k
      yr_le32toh(exports->NumberOfFunctions), MAX_PE_EXPORTS);
1582
1583
1.02k
  ordinal_base = yr_le32toh(exports->Base);
1584
1585
1.02k
  yr_set_integer(
1586
1.02k
      yr_le32toh(exports->TimeDateStamp), pe->object, "export_timestamp");
1587
1588
1.02k
  offset = pe_rva_to_offset(pe, yr_le32toh(exports->Name));
1589
1590
1.02k
  if (offset > 0)
1591
168
  {
1592
168
    remaining = pe->data_size - (size_t) offset;
1593
168
    name_len = strnlen((char*) (pe->data + offset), remaining);
1594
168
    yr_set_sized_string(
1595
168
        (char*) (pe->data + offset), name_len, pe->object, "dll_name");
1596
168
  }
1597
1598
1.02k
  if (number_of_exports * sizeof(DWORD) > pe->data_size - offset)
1599
474
    return;
1600
1601
547
  if (yr_le32toh(exports->NumberOfNames) > 0)
1602
437
  {
1603
437
    offset = pe_rva_to_offset(pe, yr_le32toh(exports->AddressOfNames));
1604
1605
437
    if (offset < 0)
1606
120
      return;
1607
1608
317
    if (yr_le32toh(exports->NumberOfNames) * sizeof(DWORD) >
1609
317
        pe->data_size - offset)
1610
143
      return;
1611
1612
174
    names = (DWORD*) (pe->data + offset);
1613
174
  }
1614
1615
284
  offset = pe_rva_to_offset(pe, yr_le32toh(exports->AddressOfNameOrdinals));
1616
1617
284
  if (offset < 0)
1618
10
    return;
1619
1620
274
  ordinals = (WORD*) (pe->data + offset);
1621
1622
274
  if (available_space(pe, ordinals) < sizeof(WORD) * number_of_exports)
1623
4
    return;
1624
1625
270
  offset = pe_rva_to_offset(pe, yr_le32toh(exports->AddressOfFunctions));
1626
1627
270
  if (offset < 0)
1628
11
    return;
1629
1630
259
  function_addrs = (DWORD*) (pe->data + offset);
1631
1632
259
  if (available_space(pe, function_addrs) < sizeof(DWORD) * number_of_exports)
1633
8
    return;
1634
1635
251
  number_of_names = yr_min(
1636
251
      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
560k
  for (i = 0; i < number_of_exports; i++)
1671
560k
  {
1672
560k
    yr_set_integer(
1673
560k
        ordinal_base + i, pe->object, "export_details[%i].ordinal", exp_sz);
1674
1675
560k
    yr_set_integer(
1676
560k
        yr_le32toh(function_addrs[i]),
1677
560k
        pe->object,
1678
560k
        "export_details[%i].rva",
1679
560k
        exp_sz);
1680
1681
    // Don't check for a failure here since some packers make this an invalid
1682
    // value.
1683
560k
    offset = pe_rva_to_offset(pe, yr_le32toh(function_addrs[i]));
1684
1685
560k
    if (offset > export_start && offset < export_start + export_size)
1686
8.36k
    {
1687
8.36k
      remaining = pe->data_size - (size_t) offset;
1688
8.36k
      name_len = strnlen((char*) (pe->data + offset), remaining);
1689
1690
8.36k
      yr_set_sized_string(
1691
8.36k
          (char*) (pe->data + offset),
1692
8.36k
          yr_min(name_len, MAX_EXPORT_NAME_LENGTH),
1693
8.36k
          pe->object,
1694
8.36k
          "export_details[%i].forward_name",
1695
8.36k
          exp_sz);
1696
8.36k
    }
1697
552k
    else
1698
552k
    {
1699
552k
      if (offset < 0)
1700
464k
        offset = YR_UNDEFINED;
1701
552k
      yr_set_integer(offset, pe->object, "export_details[%i].offset", exp_sz);
1702
552k
    }
1703
1704
560k
    if (names != NULL)
1705
342k
    {
1706
4.69G
      for (j = 0; j < number_of_exports; j++)
1707
4.69G
      {
1708
4.69G
        if (yr_le16toh(ordinals[j]) == i && j < number_of_names)
1709
18.0k
        {
1710
18.0k
          offset = pe_rva_to_offset(pe, yr_le32toh(names[j]));
1711
1712
18.0k
          if (offset > 0)
1713
2.60k
          {
1714
2.60k
            remaining = pe->data_size - (size_t) offset;
1715
2.60k
            name_len = strnlen((char*) (pe->data + offset), remaining);
1716
1717
2.60k
            yr_set_sized_string(
1718
2.60k
                (char*) (pe->data + offset),
1719
2.60k
                yr_min(name_len, MAX_EXPORT_NAME_LENGTH),
1720
2.60k
                pe->object,
1721
2.60k
                "export_details[%i].name",
1722
2.60k
                exp_sz);
1723
2.60k
          }
1724
18.0k
          break;
1725
18.0k
        }
1726
4.69G
      }
1727
342k
    }
1728
560k
    exp_sz++;
1729
560k
  }
1730
1731
251
  yr_set_integer(exp_sz, pe->object, "number_of_exports");
1732
251
}
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.96k
{
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.96k
  if (pe == NULL || section_name == NULL || section_full_name_length == NULL)
2030
0
    return NULL;
2031
2032
  // Set length to zero
2033
8.96k
  *section_full_name_length = 0;
2034
2035
  // Offset and number of records in coff table
2036
8.96k
  uint64_t coff_offset = yr_le32toh(
2037
8.96k
      pe->header->FileHeader.PointerToSymbolTable);
2038
8.96k
  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.96k
  if (coff_offset == 0 || section_name[0] != '/')
2043
8.35k
  {
2044
8.35k
    *section_full_name_length = section_name_length;
2045
8.35k
    return section_name;
2046
8.35k
  }
2047
2048
  // Calculate offset of string table (String table is immediately after coff
2049
  // table)
2050
612
  uint64_t string_offset = coff_offset + coff_number * sizeof(IMAGE_SYMBOL);
2051
612
  uint64_t string_index = 0;
2052
2053
  // Calculate string index/offset in string table
2054
1.48k
  for (int i = 1; i < IMAGE_SIZEOF_SHORT_NAME && isdigit(section_name[i]); i++)
2055
876
    string_index = (string_index * 10) + (section_name[i] - '0');
2056
2057
  // Calculate string pointer
2058
612
  const char* string = (char*) (pe->data + string_offset + string_index);
2059
2060
  // Check string
2061
652k
  for (uint64_t len = 0; fits_in_pe(pe, string, len + 1); len++)
2062
651k
  {
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
651k
    unsigned int one_char = (unsigned char) (string[len]);
2067
2068
    // Valid string
2069
651k
    if (one_char == 0)
2070
108
    {
2071
108
      *section_full_name_length = len;
2072
108
      return string;
2073
108
    }
2074
2075
    // string contain unprintable character
2076
651k
    if (!isprint(one_char))
2077
244
      return NULL;
2078
651k
  }
2079
2080
  // String do not fit into pe file
2081
260
  return NULL;
2082
612
}
2083
2084
static void pe_parse_header(PE* pe, uint64_t base_address, int flags)
2085
7.00k
{
2086
7.00k
  PIMAGE_SECTION_HEADER section;
2087
7.00k
  PIMAGE_DATA_DIRECTORY data_dir;
2088
2089
7.00k
  char section_name[IMAGE_SIZEOF_SHORT_NAME + 1];
2090
7.00k
  int sect_name_length;
2091
2092
7.00k
  uint16_t scount;
2093
7.00k
  uint32_t ddcount;
2094
2095
7.00k
  uint64_t highest_sec_siz = 0;
2096
7.00k
  uint64_t highest_sec_ofs = 0;
2097
7.00k
  uint64_t section_end;
2098
7.00k
  uint64_t last_section_end;
2099
2100
7.00k
  yr_set_integer(1, pe->object, "is_pe");
2101
2102
7.00k
  yr_set_integer(
2103
7.00k
      yr_le16toh(pe->header->FileHeader.Machine), pe->object, "machine");
2104
2105
7.00k
  yr_set_integer(
2106
7.00k
      yr_le16toh(pe->header->FileHeader.NumberOfSections),
2107
7.00k
      pe->object,
2108
7.00k
      "number_of_sections");
2109
2110
7.00k
  yr_set_integer(
2111
7.00k
      yr_le32toh(pe->header->FileHeader.TimeDateStamp),
2112
7.00k
      pe->object,
2113
7.00k
      "timestamp");
2114
2115
7.00k
  yr_set_integer(
2116
7.00k
      yr_le32toh(pe->header->FileHeader.PointerToSymbolTable),
2117
7.00k
      pe->object,
2118
7.00k
      "pointer_to_symbol_table");
2119
2120
7.00k
  yr_set_integer(
2121
7.00k
      yr_le32toh(pe->header->FileHeader.NumberOfSymbols),
2122
7.00k
      pe->object,
2123
7.00k
      "number_of_symbols");
2124
2125
7.00k
  yr_set_integer(
2126
7.00k
      yr_le16toh(pe->header->FileHeader.SizeOfOptionalHeader),
2127
7.00k
      pe->object,
2128
7.00k
      "size_of_optional_header");
2129
2130
7.00k
  yr_set_integer(
2131
7.00k
      yr_le16toh(pe->header->FileHeader.Characteristics),
2132
7.00k
      pe->object,
2133
7.00k
      "characteristics");
2134
2135
7.00k
  yr_set_integer(
2136
7.00k
      flags & SCAN_FLAGS_PROCESS_MEMORY
2137
7.00k
          ? base_address + yr_le32toh(OptionalHeader(pe, AddressOfEntryPoint))
2138
7.00k
          : pe_rva_to_offset(
2139
7.00k
                pe, yr_le32toh(OptionalHeader(pe, AddressOfEntryPoint))),
2140
7.00k
      pe->object,
2141
7.00k
      "entry_point");
2142
2143
7.00k
  yr_set_integer(
2144
7.00k
      yr_le32toh(OptionalHeader(pe, AddressOfEntryPoint)),
2145
7.00k
      pe->object,
2146
7.00k
      "entry_point_raw");
2147
2148
7.00k
  yr_set_integer(
2149
7.00k
      IS_64BITS_PE(pe) ? yr_le64toh(OptionalHeader(pe, ImageBase))
2150
7.00k
                       : yr_le32toh(OptionalHeader(pe, ImageBase)),
2151
7.00k
      pe->object,
2152
7.00k
      "image_base");
2153
2154
7.00k
  yr_set_integer(
2155
7.00k
      yr_le32toh(OptionalHeader(pe, NumberOfRvaAndSizes)),
2156
7.00k
      pe->object,
2157
7.00k
      "number_of_rva_and_sizes");
2158
2159
7.00k
  yr_set_integer(
2160
7.00k
      yr_le16toh(OptionalHeader(pe, Magic)), pe->object, "opthdr_magic");
2161
2162
7.00k
  yr_set_integer(
2163
7.00k
      OptionalHeader(pe, MajorLinkerVersion),
2164
7.00k
      pe->object,
2165
7.00k
      "linker_version.major");
2166
2167
7.00k
  yr_set_integer(
2168
7.00k
      OptionalHeader(pe, MinorLinkerVersion),
2169
7.00k
      pe->object,
2170
7.00k
      "linker_version.minor");
2171
2172
7.00k
  yr_set_integer(
2173
7.00k
      yr_le32toh(OptionalHeader(pe, SizeOfCode)), pe->object, "size_of_code");
2174
2175
7.00k
  yr_set_integer(
2176
7.00k
      yr_le32toh(OptionalHeader(pe, SizeOfInitializedData)),
2177
7.00k
      pe->object,
2178
7.00k
      "size_of_initialized_data");
2179
2180
7.00k
  yr_set_integer(
2181
7.00k
      yr_le32toh(OptionalHeader(pe, SizeOfUninitializedData)),
2182
7.00k
      pe->object,
2183
7.00k
      "size_of_uninitialized_data");
2184
2185
7.00k
  yr_set_integer(
2186
7.00k
      yr_le32toh(OptionalHeader(pe, BaseOfCode)), pe->object, "base_of_code");
2187
2188
7.00k
  if (!IS_64BITS_PE(pe))
2189
5.99k
  {
2190
5.99k
    yr_set_integer(
2191
5.99k
        yr_le32toh(pe->header->OptionalHeader.BaseOfData),
2192
5.99k
        pe->object,
2193
5.99k
        "base_of_data");
2194
5.99k
  }
2195
2196
7.00k
  yr_set_integer(
2197
7.00k
      yr_le32toh(OptionalHeader(pe, SectionAlignment)),
2198
7.00k
      pe->object,
2199
7.00k
      "section_alignment");
2200
2201
7.00k
  yr_set_integer(
2202
7.00k
      yr_le32toh(OptionalHeader(pe, FileAlignment)),
2203
7.00k
      pe->object,
2204
7.00k
      "file_alignment");
2205
2206
7.00k
  yr_set_integer(
2207
7.00k
      yr_le16toh(OptionalHeader(pe, MajorOperatingSystemVersion)),
2208
7.00k
      pe->object,
2209
7.00k
      "os_version.major");
2210
2211
7.00k
  yr_set_integer(
2212
7.00k
      yr_le16toh(OptionalHeader(pe, MinorOperatingSystemVersion)),
2213
7.00k
      pe->object,
2214
7.00k
      "os_version.minor");
2215
2216
7.00k
  yr_set_integer(
2217
7.00k
      yr_le16toh(OptionalHeader(pe, MajorImageVersion)),
2218
7.00k
      pe->object,
2219
7.00k
      "image_version.major");
2220
2221
7.00k
  yr_set_integer(
2222
7.00k
      yr_le16toh(OptionalHeader(pe, MinorImageVersion)),
2223
7.00k
      pe->object,
2224
7.00k
      "image_version.minor");
2225
2226
7.00k
  yr_set_integer(
2227
7.00k
      yr_le16toh(OptionalHeader(pe, MajorSubsystemVersion)),
2228
7.00k
      pe->object,
2229
7.00k
      "subsystem_version.major");
2230
2231
7.00k
  yr_set_integer(
2232
7.00k
      yr_le16toh(OptionalHeader(pe, MinorSubsystemVersion)),
2233
7.00k
      pe->object,
2234
7.00k
      "subsystem_version.minor");
2235
2236
7.00k
  yr_set_integer(
2237
7.00k
      yr_le32toh(OptionalHeader(pe, Win32VersionValue)),
2238
7.00k
      pe->object,
2239
7.00k
      "win32_version_value");
2240
2241
7.00k
  yr_set_integer(
2242
7.00k
      yr_le32toh(OptionalHeader(pe, SizeOfImage)), pe->object, "size_of_image");
2243
2244
7.00k
  yr_set_integer(
2245
7.00k
      yr_le32toh(OptionalHeader(pe, SizeOfHeaders)),
2246
7.00k
      pe->object,
2247
7.00k
      "size_of_headers");
2248
2249
7.00k
  yr_set_integer(
2250
7.00k
      yr_le32toh(OptionalHeader(pe, CheckSum)), pe->object, "checksum");
2251
2252
7.00k
  yr_set_integer(
2253
7.00k
      yr_le16toh(OptionalHeader(pe, Subsystem)), pe->object, "subsystem");
2254
2255
7.00k
  yr_set_integer(
2256
7.00k
      yr_le16toh(OptionalHeader(pe, DllCharacteristics)),
2257
7.00k
      pe->object,
2258
7.00k
      "dll_characteristics");
2259
2260
7.00k
  yr_set_integer(
2261
7.00k
      IS_64BITS_PE(pe) ? yr_le64toh(OptionalHeader(pe, SizeOfStackReserve))
2262
7.00k
                       : yr_le32toh(OptionalHeader(pe, SizeOfStackReserve)),
2263
7.00k
      pe->object,
2264
7.00k
      "size_of_stack_reserve");
2265
2266
7.00k
  yr_set_integer(
2267
7.00k
      IS_64BITS_PE(pe) ? yr_le64toh(OptionalHeader(pe, SizeOfStackCommit))
2268
7.00k
                       : yr_le32toh(OptionalHeader(pe, SizeOfStackCommit)),
2269
7.00k
      pe->object,
2270
7.00k
      "size_of_stack_commit");
2271
2272
7.00k
  yr_set_integer(
2273
7.00k
      IS_64BITS_PE(pe) ? yr_le64toh(OptionalHeader(pe, SizeOfHeapReserve))
2274
7.00k
                       : yr_le32toh(OptionalHeader(pe, SizeOfHeapReserve)),
2275
7.00k
      pe->object,
2276
7.00k
      "size_of_heap_reserve");
2277
2278
7.00k
  yr_set_integer(
2279
7.00k
      IS_64BITS_PE(pe) ? yr_le64toh(OptionalHeader(pe, SizeOfHeapCommit))
2280
7.00k
                       : yr_le32toh(OptionalHeader(pe, SizeOfHeapCommit)),
2281
7.00k
      pe->object,
2282
7.00k
      "size_of_heap_commit");
2283
2284
7.00k
  yr_set_integer(
2285
7.00k
      yr_le32toh(OptionalHeader(pe, LoaderFlags)), pe->object, "loader_flags");
2286
2287
7.00k
  data_dir = IS_64BITS_PE(pe) ? pe->header64->OptionalHeader.DataDirectory
2288
7.00k
                              : pe->header->OptionalHeader.DataDirectory;
2289
2290
7.00k
  ddcount = yr_le32toh(OptionalHeader(pe, NumberOfRvaAndSizes));
2291
7.00k
  ddcount = yr_min(ddcount, IMAGE_NUMBEROF_DIRECTORY_ENTRIES);
2292
2293
113k
  for (int i = 0; i < ddcount; i++)
2294
106k
  {
2295
106k
    if (!struct_fits_in_pe(pe, data_dir, IMAGE_DATA_DIRECTORY))
2296
0
      break;
2297
2298
106k
    yr_set_integer(
2299
106k
        yr_le32toh(data_dir->VirtualAddress),
2300
106k
        pe->object,
2301
106k
        "data_directories[%i].virtual_address",
2302
106k
        i);
2303
2304
106k
    yr_set_integer(
2305
106k
        yr_le32toh(data_dir->Size), pe->object, "data_directories[%i].size", i);
2306
2307
106k
    data_dir++;
2308
106k
  }
2309
2310
7.00k
  pe_iterate_resources(
2311
7.00k
      pe, (RESOURCE_CALLBACK_FUNC) pe_collect_resources, (void*) pe);
2312
2313
7.00k
  yr_set_integer(pe->resources, pe->object, "number_of_resources");
2314
7.00k
  yr_set_integer(pe->version_infos, pe->object, "number_of_version_infos");
2315
2316
7.00k
  section = IMAGE_FIRST_SECTION(pe->header);
2317
2318
7.00k
  scount = yr_min(
2319
7.00k
      yr_le16toh(pe->header->FileHeader.NumberOfSections), MAX_PE_SECTIONS);
2320
2321
15.9k
  for (int i = 0; i < scount; i++)
2322
9.24k
  {
2323
9.24k
    if (!struct_fits_in_pe(pe, section, IMAGE_SECTION_HEADER))
2324
280
      break;
2325
2326
8.96k
    memcpy(section_name, section->Name, IMAGE_SIZEOF_SHORT_NAME);
2327
8.96k
    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.2k
    for (sect_name_length = IMAGE_SIZEOF_SHORT_NAME - 1; sect_name_length >= 0;
2334
8.96k
         --sect_name_length)
2335
15.9k
    {
2336
15.9k
      if (section_name[sect_name_length] != '\0')
2337
8.67k
        break;
2338
15.9k
    }
2339
2340
8.96k
    uint64_t sect_full_name_length = 0;
2341
8.96k
    const char* full_section_name = pe_get_section_full_name(
2342
8.96k
        pe, section_name, sect_name_length + 1, &sect_full_name_length);
2343
2344
8.96k
    yr_set_sized_string(
2345
8.96k
        (char*) section_name,
2346
8.96k
        sect_name_length + 1,
2347
8.96k
        pe->object,
2348
8.96k
        "sections[%i].name",
2349
8.96k
        i);
2350
2351
8.96k
    yr_set_sized_string(
2352
8.96k
        full_section_name,
2353
8.96k
        sect_full_name_length,
2354
8.96k
        pe->object,
2355
8.96k
        "sections[%i].full_name",
2356
8.96k
        i);
2357
2358
8.96k
    yr_set_integer(
2359
8.96k
        yr_le32toh(section->Characteristics),
2360
8.96k
        pe->object,
2361
8.96k
        "sections[%i].characteristics",
2362
8.96k
        i);
2363
2364
8.96k
    yr_set_integer(
2365
8.96k
        yr_le32toh(section->SizeOfRawData),
2366
8.96k
        pe->object,
2367
8.96k
        "sections[%i].raw_data_size",
2368
8.96k
        i);
2369
2370
8.96k
    yr_set_integer(
2371
8.96k
        yr_le32toh(section->PointerToRawData),
2372
8.96k
        pe->object,
2373
8.96k
        "sections[%i].raw_data_offset",
2374
8.96k
        i);
2375
2376
8.96k
    yr_set_integer(
2377
8.96k
        yr_le32toh(section->VirtualAddress),
2378
8.96k
        pe->object,
2379
8.96k
        "sections[%i].virtual_address",
2380
8.96k
        i);
2381
2382
8.96k
    yr_set_integer(
2383
8.96k
        yr_le32toh(section->Misc.VirtualSize),
2384
8.96k
        pe->object,
2385
8.96k
        "sections[%i].virtual_size",
2386
8.96k
        i);
2387
2388
8.96k
    yr_set_integer(
2389
8.96k
        yr_le32toh(section->PointerToRelocations),
2390
8.96k
        pe->object,
2391
8.96k
        "sections[%i].pointer_to_relocations",
2392
8.96k
        i);
2393
2394
8.96k
    yr_set_integer(
2395
8.96k
        yr_le32toh(section->PointerToLinenumbers),
2396
8.96k
        pe->object,
2397
8.96k
        "sections[%i].pointer_to_line_numbers",
2398
8.96k
        i);
2399
2400
8.96k
    yr_set_integer(
2401
8.96k
        yr_le32toh(section->NumberOfRelocations),
2402
8.96k
        pe->object,
2403
8.96k
        "sections[%i].number_of_relocations",
2404
8.96k
        i);
2405
2406
8.96k
    yr_set_integer(
2407
8.96k
        yr_le32toh(section->NumberOfLinenumbers),
2408
8.96k
        pe->object,
2409
8.96k
        "sections[%i].number_of_line_numbers",
2410
8.96k
        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.96k
    section_end = yr_le32toh(section->PointerToRawData) +
2418
8.96k
                  yr_le32toh(section->SizeOfRawData);
2419
2420
8.96k
    if (section_end > highest_sec_ofs + highest_sec_siz)
2421
2.81k
    {
2422
2.81k
      highest_sec_ofs = yr_le32toh(section->PointerToRawData);
2423
2.81k
      highest_sec_siz = yr_le32toh(section->SizeOfRawData);
2424
2.81k
    }
2425
2426
8.96k
    section++;
2427
8.96k
  }
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.00k
  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.00k
  if (last_section_end && (pe->data_size > last_section_end))
2438
158
  {
2439
158
    yr_set_integer(last_section_end, pe->object, "overlay.offset");
2440
158
    yr_set_integer(
2441
158
        pe->data_size - last_section_end, pe->object, "overlay.size");
2442
158
  }
2443
6.84k
  else
2444
6.84k
  {
2445
6.84k
    yr_set_integer(0, pe->object, "overlay.offset");
2446
6.84k
    yr_set_integer(0, pe->object, "overlay.size");
2447
6.84k
  }
2448
7.00k
}
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.12k
{
3513
2.12k
  YR_OBJECT* module = yr_module();
3514
2.12k
  PE* pe = (PE*) module->data;
3515
3516
2.12k
  uint64_t rva;
3517
2.12k
  int64_t offset;
3518
3519
2.12k
  if (pe == NULL)
3520
2.12k
    return_integer(YR_UNDEFINED);
3521
3522
2.12k
  rva = integer_argument(1);
3523
2.12k
  offset = pe_rva_to_offset(pe, rva);
3524
3525
2.12k
  if (offset == -1)
3526
1.57k
    return_integer(YR_UNDEFINED);
3527
3528
1.57k
  return_integer(offset);
3529
0
}
3530
3531
8.53k
begin_declarations
3532
8.53k
  declare_integer("MACHINE_UNKNOWN");
3533
8.53k
  declare_integer("MACHINE_AM33");
3534
8.53k
  declare_integer("MACHINE_AMD64");
3535
8.53k
  declare_integer("MACHINE_ARM");
3536
8.53k
  declare_integer("MACHINE_ARMNT");
3537
8.53k
  declare_integer("MACHINE_ARM64");
3538
8.53k
  declare_integer("MACHINE_EBC");
3539
8.53k
  declare_integer("MACHINE_I386");
3540
8.53k
  declare_integer("MACHINE_IA64");
3541
8.53k
  declare_integer("MACHINE_M32R");
3542
8.53k
  declare_integer("MACHINE_MIPS16");
3543
8.53k
  declare_integer("MACHINE_MIPSFPU");
3544
8.53k
  declare_integer("MACHINE_MIPSFPU16");
3545
8.53k
  declare_integer("MACHINE_POWERPC");
3546
8.53k
  declare_integer("MACHINE_POWERPCFP");
3547
8.53k
  declare_integer("MACHINE_R4000");
3548
8.53k
  declare_integer("MACHINE_SH3");
3549
8.53k
  declare_integer("MACHINE_SH3DSP");
3550
8.53k
  declare_integer("MACHINE_SH4");
3551
8.53k
  declare_integer("MACHINE_SH5");
3552
8.53k
  declare_integer("MACHINE_THUMB");
3553
8.53k
  declare_integer("MACHINE_WCEMIPSV2");
3554
8.53k
  declare_integer("MACHINE_TARGET_HOST");
3555
8.53k
  declare_integer("MACHINE_R3000");
3556
8.53k
  declare_integer("MACHINE_R10000");
3557
8.53k
  declare_integer("MACHINE_ALPHA");
3558
8.53k
  declare_integer("MACHINE_SH3E");
3559
8.53k
  declare_integer("MACHINE_ALPHA64");
3560
8.53k
  declare_integer("MACHINE_AXP64");
3561
8.53k
  declare_integer("MACHINE_TRICORE");
3562
8.53k
  declare_integer("MACHINE_CEF");
3563
8.53k
  declare_integer("MACHINE_CEE");
3564
3565
8.53k
  declare_integer("SUBSYSTEM_UNKNOWN");
3566
8.53k
  declare_integer("SUBSYSTEM_NATIVE");
3567
8.53k
  declare_integer("SUBSYSTEM_WINDOWS_GUI");
3568
8.53k
  declare_integer("SUBSYSTEM_WINDOWS_CUI");
3569
8.53k
  declare_integer("SUBSYSTEM_OS2_CUI");
3570
8.53k
  declare_integer("SUBSYSTEM_POSIX_CUI");
3571
8.53k
  declare_integer("SUBSYSTEM_NATIVE_WINDOWS");
3572
8.53k
  declare_integer("SUBSYSTEM_WINDOWS_CE_GUI");
3573
8.53k
  declare_integer("SUBSYSTEM_EFI_APPLICATION");
3574
8.53k
  declare_integer("SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER");
3575
8.53k
  declare_integer("SUBSYSTEM_EFI_RUNTIME_DRIVER");
3576
8.53k
  declare_integer("SUBSYSTEM_EFI_ROM_IMAGE");
3577
8.53k
  declare_integer("SUBSYSTEM_XBOX");
3578
8.53k
  declare_integer("SUBSYSTEM_WINDOWS_BOOT_APPLICATION");
3579
3580
8.53k
  declare_integer("HIGH_ENTROPY_VA");
3581
8.53k
  declare_integer("DYNAMIC_BASE");
3582
8.53k
  declare_integer("FORCE_INTEGRITY");
3583
8.53k
  declare_integer("NX_COMPAT");
3584
8.53k
  declare_integer("NO_ISOLATION");
3585
8.53k
  declare_integer("NO_SEH");
3586
8.53k
  declare_integer("NO_BIND");
3587
8.53k
  declare_integer("APPCONTAINER");
3588
8.53k
  declare_integer("WDM_DRIVER");
3589
8.53k
  declare_integer("GUARD_CF");
3590
8.53k
  declare_integer("TERMINAL_SERVER_AWARE");
3591
3592
8.53k
  declare_integer("RELOCS_STRIPPED");
3593
8.53k
  declare_integer("EXECUTABLE_IMAGE");
3594
8.53k
  declare_integer("LINE_NUMS_STRIPPED");
3595
8.53k
  declare_integer("LOCAL_SYMS_STRIPPED");
3596
8.53k
  declare_integer("AGGRESIVE_WS_TRIM");
3597
8.53k
  declare_integer("LARGE_ADDRESS_AWARE");
3598
8.53k
  declare_integer("BYTES_REVERSED_LO");
3599
8.53k
  declare_integer("MACHINE_32BIT");
3600
8.53k
  declare_integer("DEBUG_STRIPPED");
3601
8.53k
  declare_integer("REMOVABLE_RUN_FROM_SWAP");
3602
8.53k
  declare_integer("NET_RUN_FROM_SWAP");
3603
8.53k
  declare_integer("SYSTEM");
3604
8.53k
  declare_integer("DLL");
3605
8.53k
  declare_integer("UP_SYSTEM_ONLY");
3606
8.53k
  declare_integer("BYTES_REVERSED_HI");
3607
3608
8.53k
  declare_integer("IMAGE_DIRECTORY_ENTRY_EXPORT");
3609
8.53k
  declare_integer("IMAGE_DIRECTORY_ENTRY_IMPORT");
3610
8.53k
  declare_integer("IMAGE_DIRECTORY_ENTRY_RESOURCE");
3611
8.53k
  declare_integer("IMAGE_DIRECTORY_ENTRY_EXCEPTION");
3612
8.53k
  declare_integer("IMAGE_DIRECTORY_ENTRY_SECURITY");
3613
8.53k
  declare_integer("IMAGE_DIRECTORY_ENTRY_BASERELOC");
3614
8.53k
  declare_integer("IMAGE_DIRECTORY_ENTRY_DEBUG");
3615
8.53k
  declare_integer("IMAGE_DIRECTORY_ENTRY_ARCHITECTURE");
3616
8.53k
  declare_integer("IMAGE_DIRECTORY_ENTRY_COPYRIGHT");
3617
8.53k
  declare_integer("IMAGE_DIRECTORY_ENTRY_GLOBALPTR");
3618
8.53k
  declare_integer("IMAGE_DIRECTORY_ENTRY_TLS");
3619
8.53k
  declare_integer("IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG");
3620
8.53k
  declare_integer("IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT");
3621
8.53k
  declare_integer("IMAGE_DIRECTORY_ENTRY_IAT");
3622
8.53k
  declare_integer("IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT");
3623
8.53k
  declare_integer("IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR");
3624
3625
8.53k
  declare_integer("IMAGE_NT_OPTIONAL_HDR32_MAGIC");
3626
8.53k
  declare_integer("IMAGE_NT_OPTIONAL_HDR64_MAGIC");
3627
8.53k
  declare_integer("IMAGE_ROM_OPTIONAL_HDR_MAGIC");
3628
3629
8.53k
  declare_integer("SECTION_NO_PAD");
3630
8.53k
  declare_integer("SECTION_CNT_CODE");
3631
8.53k
  declare_integer("SECTION_CNT_INITIALIZED_DATA");
3632
8.53k
  declare_integer("SECTION_CNT_UNINITIALIZED_DATA");
3633
8.53k
  declare_integer("SECTION_LNK_OTHER");
3634
8.53k
  declare_integer("SECTION_LNK_INFO");
3635
8.53k
  declare_integer("SECTION_LNK_REMOVE");
3636
8.53k
  declare_integer("SECTION_LNK_COMDAT");
3637
8.53k
  declare_integer("SECTION_NO_DEFER_SPEC_EXC");
3638
8.53k
  declare_integer("SECTION_GPREL");
3639
8.53k
  declare_integer("SECTION_MEM_FARDATA");
3640
8.53k
  declare_integer("SECTION_MEM_PURGEABLE");
3641
8.53k
  declare_integer("SECTION_MEM_16BIT");
3642
8.53k
  declare_integer("SECTION_MEM_LOCKED");
3643
8.53k
  declare_integer("SECTION_MEM_PRELOAD");
3644
8.53k
  declare_integer("SECTION_ALIGN_1BYTES");
3645
8.53k
  declare_integer("SECTION_ALIGN_2BYTES");
3646
8.53k
  declare_integer("SECTION_ALIGN_4BYTES");
3647
8.53k
  declare_integer("SECTION_ALIGN_8BYTES");
3648
8.53k
  declare_integer("SECTION_ALIGN_16BYTES");
3649
8.53k
  declare_integer("SECTION_ALIGN_32BYTES");
3650
8.53k
  declare_integer("SECTION_ALIGN_64BYTES");
3651
8.53k
  declare_integer("SECTION_ALIGN_128BYTES");
3652
8.53k
  declare_integer("SECTION_ALIGN_256BYTES");
3653
8.53k
  declare_integer("SECTION_ALIGN_512BYTES");
3654
8.53k
  declare_integer("SECTION_ALIGN_1024BYTES");
3655
8.53k
  declare_integer("SECTION_ALIGN_2048BYTES");
3656
8.53k
  declare_integer("SECTION_ALIGN_4096BYTES");
3657
8.53k
  declare_integer("SECTION_ALIGN_8192BYTES");
3658
8.53k
  declare_integer("SECTION_ALIGN_MASK");
3659
8.53k
  declare_integer("SECTION_LNK_NRELOC_OVFL");
3660
8.53k
  declare_integer("SECTION_MEM_DISCARDABLE");
3661
8.53k
  declare_integer("SECTION_MEM_NOT_CACHED");
3662
8.53k
  declare_integer("SECTION_MEM_NOT_PAGED");
3663
8.53k
  declare_integer("SECTION_MEM_SHARED");
3664
8.53k
  declare_integer("SECTION_MEM_EXECUTE");
3665
8.53k
  declare_integer("SECTION_MEM_READ");
3666
8.53k
  declare_integer("SECTION_MEM_WRITE");
3667
8.53k
  declare_integer("SECTION_SCALE_INDEX");
3668
3669
8.53k
  declare_integer("RESOURCE_TYPE_CURSOR");
3670
8.53k
  declare_integer("RESOURCE_TYPE_BITMAP");
3671
8.53k
  declare_integer("RESOURCE_TYPE_ICON");
3672
8.53k
  declare_integer("RESOURCE_TYPE_MENU");
3673
8.53k
  declare_integer("RESOURCE_TYPE_DIALOG");
3674
8.53k
  declare_integer("RESOURCE_TYPE_STRING");
3675
8.53k
  declare_integer("RESOURCE_TYPE_FONTDIR");
3676
8.53k
  declare_integer("RESOURCE_TYPE_FONT");
3677
8.53k
  declare_integer("RESOURCE_TYPE_ACCELERATOR");
3678
8.53k
  declare_integer("RESOURCE_TYPE_RCDATA");
3679
8.53k
  declare_integer("RESOURCE_TYPE_MESSAGETABLE");
3680
8.53k
  declare_integer("RESOURCE_TYPE_GROUP_CURSOR");
3681
8.53k
  declare_integer("RESOURCE_TYPE_GROUP_ICON");
3682
8.53k
  declare_integer("RESOURCE_TYPE_VERSION");
3683
8.53k
  declare_integer("RESOURCE_TYPE_DLGINCLUDE");
3684
8.53k
  declare_integer("RESOURCE_TYPE_PLUGPLAY");
3685
8.53k
  declare_integer("RESOURCE_TYPE_VXD");
3686
8.53k
  declare_integer("RESOURCE_TYPE_ANICURSOR");
3687
8.53k
  declare_integer("RESOURCE_TYPE_ANIICON");
3688
8.53k
  declare_integer("RESOURCE_TYPE_HTML");
3689
8.53k
  declare_integer("RESOURCE_TYPE_MANIFEST");
3690
3691
8.53k
  declare_integer("IMAGE_DEBUG_TYPE_UNKNOWN");
3692
8.53k
  declare_integer("IMAGE_DEBUG_TYPE_COFF");
3693
8.53k
  declare_integer("IMAGE_DEBUG_TYPE_CODEVIEW");
3694
8.53k
  declare_integer("IMAGE_DEBUG_TYPE_FPO");
3695
8.53k
  declare_integer("IMAGE_DEBUG_TYPE_MISC");
3696
8.53k
  declare_integer("IMAGE_DEBUG_TYPE_EXCEPTION");
3697
8.53k
  declare_integer("IMAGE_DEBUG_TYPE_FIXUP");
3698
8.53k
  declare_integer("IMAGE_DEBUG_TYPE_OMAP_TO_SRC");
3699
8.53k
  declare_integer("IMAGE_DEBUG_TYPE_OMAP_FROM_SRC");
3700
8.53k
  declare_integer("IMAGE_DEBUG_TYPE_BORLAND");
3701
8.53k
  declare_integer("IMAGE_DEBUG_TYPE_RESERVED10");
3702
8.53k
  declare_integer("IMAGE_DEBUG_TYPE_CLSID");
3703
8.53k
  declare_integer("IMAGE_DEBUG_TYPE_VC_FEATURE");
3704
8.53k
  declare_integer("IMAGE_DEBUG_TYPE_POGO");
3705
8.53k
  declare_integer("IMAGE_DEBUG_TYPE_ILTCG");
3706
8.53k
  declare_integer("IMAGE_DEBUG_TYPE_MPX");
3707
8.53k
  declare_integer("IMAGE_DEBUG_TYPE_REPRO");
3708
3709
8.53k
  declare_integer("IMPORT_DELAYED");
3710
8.53k
  declare_integer("IMPORT_STANDARD");
3711
8.53k
  declare_integer("IMPORT_ANY");
3712
3713
8.53k
  declare_integer("is_pe");
3714
8.53k
  declare_integer("machine");
3715
8.53k
  declare_integer("number_of_sections");
3716
8.53k
  declare_integer("timestamp");
3717
8.53k
  declare_integer("pointer_to_symbol_table");
3718
8.53k
  declare_integer("number_of_symbols");
3719
8.53k
  declare_integer("size_of_optional_header");
3720
8.53k
  declare_integer("characteristics");
3721
3722
8.53k
  declare_integer("entry_point");
3723
8.53k
  declare_integer("entry_point_raw");
3724
8.53k
  declare_integer("image_base");
3725
8.53k
  declare_integer("number_of_rva_and_sizes");
3726
8.53k
  declare_integer("number_of_version_infos");
3727
3728
17.0k
  declare_string_dictionary("version_info");
3729
3730
25.6k
  begin_struct_array("version_info_list")
3731
8.53k
    declare_string("key");
3732
8.53k
    declare_string("value");
3733
17.0k
  end_struct_array("version_info_list");
3734
3735
17.0k
  declare_integer("opthdr_magic");
3736
8.53k
  declare_integer("size_of_code");
3737
8.53k
  declare_integer("size_of_initialized_data");
3738
8.53k
  declare_integer("size_of_uninitialized_data");
3739
8.53k
  declare_integer("base_of_code");
3740
8.53k
  declare_integer("base_of_data");
3741
8.53k
  declare_integer("section_alignment");
3742
8.53k
  declare_integer("file_alignment");
3743
3744
17.0k
  begin_struct("linker_version")
3745
8.53k
    declare_integer("major");
3746
8.53k
    declare_integer("minor");
3747
17.0k
  end_struct("linker_version");
3748
3749
17.0k
  begin_struct("os_version")
3750
8.53k
    declare_integer("major");
3751
8.53k
    declare_integer("minor");
3752
17.0k
  end_struct("os_version");
3753
3754
17.0k
  begin_struct("image_version")
3755
8.53k
    declare_integer("major");
3756
8.53k
    declare_integer("minor");
3757
17.0k
  end_struct("image_version");
3758
3759
17.0k
  begin_struct("subsystem_version")
3760
8.53k
    declare_integer("major");
3761
8.53k
    declare_integer("minor");
3762
17.0k
  end_struct("subsystem_version");
3763
3764
17.0k
  declare_integer("win32_version_value");
3765
8.53k
  declare_integer("size_of_image");
3766
8.53k
  declare_integer("size_of_headers");
3767
3768
8.53k
  declare_integer("checksum");
3769
8.53k
  declare_function("calculate_checksum", "", "i", calculate_checksum);
3770
8.53k
  declare_integer("subsystem");
3771
3772
8.53k
  declare_integer("dll_characteristics");
3773
8.53k
  declare_integer("size_of_stack_reserve");
3774
8.53k
  declare_integer("size_of_stack_commit");
3775
8.53k
  declare_integer("size_of_heap_reserve");
3776
8.53k
  declare_integer("size_of_heap_commit");
3777
8.53k
  declare_integer("loader_flags");
3778
3779
25.6k
  begin_struct_array("data_directories")
3780
8.53k
    declare_integer("virtual_address");
3781
8.53k
    declare_integer("size");
3782
17.0k
  end_struct_array("data_directories");
3783
3784
25.6k
  begin_struct_array("sections")
3785
8.53k
    declare_string("name");
3786
8.53k
    declare_string("full_name");
3787
8.53k
    declare_integer("characteristics");
3788
8.53k
    declare_integer("virtual_address");
3789
8.53k
    declare_integer("virtual_size");
3790
8.53k
    declare_integer("raw_data_offset");
3791
8.53k
    declare_integer("raw_data_size");
3792
8.53k
    declare_integer("pointer_to_relocations");
3793
8.53k
    declare_integer("pointer_to_line_numbers");
3794
8.53k
    declare_integer("number_of_relocations");
3795
8.53k
    declare_integer("number_of_line_numbers");
3796
17.0k
  end_struct_array("sections");
3797
3798
17.0k
  begin_struct("overlay")
3799
8.53k
    declare_integer("offset");
3800
8.53k
    declare_integer("size");
3801
17.0k
  end_struct("overlay");
3802
3803
17.0k
  begin_struct("rich_signature")
3804
8.53k
    declare_integer("offset");
3805
8.53k
    declare_integer("length");
3806
8.53k
    declare_integer("key");
3807
8.53k
    declare_string("raw_data");
3808
8.53k
    declare_string("clear_data");
3809
8.53k
    declare_string("version_data");
3810
8.53k
    declare_function("version", "i", "i", rich_version);
3811
8.53k
    declare_function("version", "ii", "i", rich_version_toolid);
3812
8.53k
    declare_function("toolid", "i", "i", rich_toolid);
3813
8.53k
    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.53k
  declare_function("section_index", "i", "i", section_index_addr);
3823
8.53k
  declare_function("exports", "s", "i", exports);
3824
8.53k
  declare_function("exports", "r", "i", exports_regexp);
3825
8.53k
  declare_function("exports", "i", "i", exports_ordinal);
3826
8.53k
  declare_function("exports_index", "s", "i", exports_index_name);
3827
8.53k
  declare_function("exports_index", "i", "i", exports_index_ordinal);
3828
8.53k
  declare_function("exports_index", "r", "i", exports_index_regex);
3829
8.53k
  declare_function("imports", "ss", "i", imports_standard);
3830
8.53k
  declare_function("imports", "si", "i", imports_standard_ordinal);
3831
8.53k
  declare_function("imports", "s", "i", imports_standard_dll);
3832
8.53k
  declare_function("imports", "rr", "i", imports_standard_regex);
3833
8.53k
  declare_function("imports", "iss", "i", imports);
3834
8.53k
  declare_function("imports", "isi", "i", imports_ordinal);
3835
8.53k
  declare_function("imports", "is", "i", imports_dll);
3836
8.53k
  declare_function("imports", "irr", "i", imports_regex);
3837
8.53k
  declare_function("import_rva", "ss", "i", import_rva);
3838
8.53k
  declare_function("import_rva", "si", "i", import_rva_ordinal);
3839
8.53k
  declare_function("delayed_import_rva", "ss", "i", delayed_import_rva);
3840
8.53k
  declare_function("delayed_import_rva", "si", "i", delayed_import_rva_ordinal);
3841
8.53k
  declare_function("locale", "i", "i", locale);
3842
8.53k
  declare_function("language", "i", "i", language);
3843
8.53k
  declare_function("is_dll", "", "i", is_dll);
3844
8.53k
  declare_function("is_32bit", "", "i", is_32bit);
3845
8.53k
  declare_function("is_64bit", "", "i", is_64bit);
3846
3847
8.53k
  declare_integer("number_of_imports");
3848
8.53k
  declare_integer("number_of_imported_functions");
3849
8.53k
  declare_integer("number_of_delayed_imports");
3850
8.53k
  declare_integer("number_of_delayed_imported_functions");
3851
8.53k
  declare_integer("number_of_exports");
3852
3853
8.53k
  declare_string("dll_name");
3854
8.53k
  declare_integer("export_timestamp");
3855
25.6k
  begin_struct_array("export_details")
3856
8.53k
    declare_integer("offset");
3857
8.53k
    declare_string("name");
3858
8.53k
    declare_string("forward_name");
3859
8.53k
    declare_integer("ordinal");
3860
8.53k
    declare_integer("rva");
3861
17.0k
  end_struct_array("export_details")
3862
3863
25.6k
  begin_struct_array("import_details")
3864
8.53k
    declare_string("library_name");
3865
8.53k
    declare_integer("number_of_functions");
3866
25.6k
    begin_struct_array("functions")
3867
8.53k
      declare_string("name");
3868
8.53k
      declare_integer("ordinal");
3869
8.53k
      declare_integer("rva");
3870
17.0k
    end_struct_array("functions");
3871
17.0k
  end_struct_array("import_details");
3872
3873
25.6k
  begin_struct_array("delayed_import_details")
3874
8.53k
    declare_string("library_name");
3875
8.53k
    declare_integer("number_of_functions");
3876
25.6k
    begin_struct_array("functions")
3877
8.53k
      declare_string("name");
3878
8.53k
      declare_integer("ordinal");
3879
8.53k
      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.53k
    declare_integer("major");
3887
8.53k
    declare_integer("minor");
3888
17.0k
  end_struct("resource_version")
3889
3890
25.6k
  begin_struct_array("resources")
3891
8.53k
    declare_integer("rva");
3892
8.53k
    declare_integer("offset");
3893
8.53k
    declare_integer("length");
3894
8.53k
    declare_integer("type");
3895
8.53k
    declare_integer("id");
3896
8.53k
    declare_integer("language");
3897
8.53k
    declare_string("type_string");
3898
8.53k
    declare_string("name_string");
3899
8.53k
    declare_string("language_string");
3900
17.0k
  end_struct_array("resources")
3901
3902
8.53k
  declare_integer("number_of_resources");
3903
8.53k
  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.53k
  declare_function("rva_to_offset", "i", "i", rva_to_offset);
3987
8.53k
end_declarations
3988
3989
int module_initialize(YR_MODULE* module)
3990
11
{
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
11
  return ERROR_SUCCESS;
4004
11
}
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.39k
{
4017
8.39k
  YR_MEMORY_BLOCK* block;
4018
8.39k
  YR_MEMORY_BLOCK_ITERATOR* iterator = context->iterator;
4019
4020
8.39k
  PIMAGE_NT_HEADERS32 pe_header;
4021
8.39k
  const uint8_t* block_data = NULL;
4022
8.39k
  PE* pe = NULL;
4023
4024
8.39k
  yr_set_integer(IMPORT_DELAYED, module_object, "IMPORT_DELAYED");
4025
8.39k
  yr_set_integer(IMPORT_STANDARD, module_object, "IMPORT_STANDARD");
4026
8.39k
  yr_set_integer(IMPORT_ANY, module_object, "IMPORT_ANY");
4027
4028
8.39k
  yr_set_integer(IMAGE_FILE_MACHINE_UNKNOWN, module_object, "MACHINE_UNKNOWN");
4029
8.39k
  yr_set_integer(IMAGE_FILE_MACHINE_AM33, module_object, "MACHINE_AM33");
4030
8.39k
  yr_set_integer(IMAGE_FILE_MACHINE_AMD64, module_object, "MACHINE_AMD64");
4031
8.39k
  yr_set_integer(IMAGE_FILE_MACHINE_ARM, module_object, "MACHINE_ARM");
4032
8.39k
  yr_set_integer(IMAGE_FILE_MACHINE_ARMNT, module_object, "MACHINE_ARMNT");
4033
8.39k
  yr_set_integer(IMAGE_FILE_MACHINE_ARM64, module_object, "MACHINE_ARM64");
4034
8.39k
  yr_set_integer(IMAGE_FILE_MACHINE_EBC, module_object, "MACHINE_EBC");
4035
8.39k
  yr_set_integer(IMAGE_FILE_MACHINE_I386, module_object, "MACHINE_I386");
4036
8.39k
  yr_set_integer(IMAGE_FILE_MACHINE_IA64, module_object, "MACHINE_IA64");
4037
8.39k
  yr_set_integer(IMAGE_FILE_MACHINE_M32R, module_object, "MACHINE_M32R");
4038
8.39k
  yr_set_integer(IMAGE_FILE_MACHINE_MIPS16, module_object, "MACHINE_MIPS16");
4039
8.39k
  yr_set_integer(IMAGE_FILE_MACHINE_MIPSFPU, module_object, "MACHINE_MIPSFPU");
4040
8.39k
  yr_set_integer(
4041
8.39k
      IMAGE_FILE_MACHINE_MIPSFPU16, module_object, "MACHINE_MIPSFPU16");
4042
8.39k
  yr_set_integer(IMAGE_FILE_MACHINE_POWERPC, module_object, "MACHINE_POWERPC");
4043
8.39k
  yr_set_integer(
4044
8.39k
      IMAGE_FILE_MACHINE_POWERPCFP, module_object, "MACHINE_POWERPCFP");
4045
8.39k
  yr_set_integer(IMAGE_FILE_MACHINE_R4000, module_object, "MACHINE_R4000");
4046
8.39k
  yr_set_integer(IMAGE_FILE_MACHINE_SH3, module_object, "MACHINE_SH3");
4047
8.39k
  yr_set_integer(IMAGE_FILE_MACHINE_SH3DSP, module_object, "MACHINE_SH3DSP");
4048
8.39k
  yr_set_integer(IMAGE_FILE_MACHINE_SH4, module_object, "MACHINE_SH4");
4049
8.39k
  yr_set_integer(IMAGE_FILE_MACHINE_SH5, module_object, "MACHINE_SH5");
4050
8.39k
  yr_set_integer(IMAGE_FILE_MACHINE_THUMB, module_object, "MACHINE_THUMB");
4051
8.39k
  yr_set_integer(
4052
8.39k
      IMAGE_FILE_MACHINE_WCEMIPSV2, module_object, "MACHINE_WCEMIPSV2");
4053
8.39k
  yr_set_integer(
4054
8.39k
      IMAGE_FILE_MACHINE_TARGET_HOST, module_object, "MACHINE_TARGET_HOST");
4055
8.39k
  yr_set_integer(IMAGE_FILE_MACHINE_R3000, module_object, "MACHINE_R3000");
4056
8.39k
  yr_set_integer(IMAGE_FILE_MACHINE_R10000, module_object, "MACHINE_R10000");
4057
8.39k
  yr_set_integer(IMAGE_FILE_MACHINE_ALPHA, module_object, "MACHINE_ALPHA");
4058
8.39k
  yr_set_integer(IMAGE_FILE_MACHINE_SH3E, module_object, "MACHINE_SH3E");
4059
8.39k
  yr_set_integer(IMAGE_FILE_MACHINE_ALPHA64, module_object, "MACHINE_ALPHA64");
4060
8.39k
  yr_set_integer(IMAGE_FILE_MACHINE_AXP64, module_object, "MACHINE_AXP64");
4061
8.39k
  yr_set_integer(IMAGE_FILE_MACHINE_TRICORE, module_object, "MACHINE_TRICORE");
4062
8.39k
  yr_set_integer(IMAGE_FILE_MACHINE_CEF, module_object, "MACHINE_CEF");
4063
8.39k
  yr_set_integer(IMAGE_FILE_MACHINE_CEE, module_object, "MACHINE_CEE");
4064
4065
8.39k
  yr_set_integer(IMAGE_SUBSYSTEM_UNKNOWN, module_object, "SUBSYSTEM_UNKNOWN");
4066
8.39k
  yr_set_integer(IMAGE_SUBSYSTEM_NATIVE, module_object, "SUBSYSTEM_NATIVE");
4067
8.39k
  yr_set_integer(
4068
8.39k
      IMAGE_SUBSYSTEM_WINDOWS_GUI, module_object, "SUBSYSTEM_WINDOWS_GUI");
4069
8.39k
  yr_set_integer(
4070
8.39k
      IMAGE_SUBSYSTEM_WINDOWS_CUI, module_object, "SUBSYSTEM_WINDOWS_CUI");
4071
8.39k
  yr_set_integer(IMAGE_SUBSYSTEM_OS2_CUI, module_object, "SUBSYSTEM_OS2_CUI");
4072
8.39k
  yr_set_integer(
4073
8.39k
      IMAGE_SUBSYSTEM_POSIX_CUI, module_object, "SUBSYSTEM_POSIX_CUI");
4074
8.39k
  yr_set_integer(
4075
8.39k
      IMAGE_SUBSYSTEM_NATIVE_WINDOWS,
4076
8.39k
      module_object,
4077
8.39k
      "SUBSYSTEM_NATIVE_WINDOWS");
4078
8.39k
  yr_set_integer(
4079
8.39k
      IMAGE_SUBSYSTEM_WINDOWS_CE_GUI,
4080
8.39k
      module_object,
4081
8.39k
      "SUBSYSTEM_WINDOWS_CE_GUI");
4082
8.39k
  yr_set_integer(
4083
8.39k
      IMAGE_SUBSYSTEM_EFI_APPLICATION,
4084
8.39k
      module_object,
4085
8.39k
      "SUBSYSTEM_EFI_APPLICATION");
4086
8.39k
  yr_set_integer(
4087
8.39k
      IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER,
4088
8.39k
      module_object,
4089
8.39k
      "SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER");
4090
8.39k
  yr_set_integer(
4091
8.39k
      IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER,
4092
8.39k
      module_object,
4093
8.39k
      "SUBSYSTEM_EFI_RUNTIME_DRIVER");
4094
8.39k
  yr_set_integer(
4095
8.39k
      IMAGE_SUBSYSTEM_EFI_ROM_IMAGE, module_object, "SUBSYSTEM_EFI_ROM_IMAGE");
4096
8.39k
  yr_set_integer(IMAGE_SUBSYSTEM_XBOX, module_object, "SUBSYSTEM_XBOX");
4097
8.39k
  yr_set_integer(
4098
8.39k
      IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION,
4099
8.39k
      module_object,
4100
8.39k
      "SUBSYSTEM_WINDOWS_BOOT_APPLICATION");
4101
4102
8.39k
  yr_set_integer(
4103
8.39k
      IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA,
4104
8.39k
      module_object,
4105
8.39k
      "HIGH_ENTROPY_VA");
4106
8.39k
  yr_set_integer(
4107
8.39k
      IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE, module_object, "DYNAMIC_BASE");
4108
8.39k
  yr_set_integer(
4109
8.39k
      IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY,
4110
8.39k
      module_object,
4111
8.39k
      "FORCE_INTEGRITY");
4112
8.39k
  yr_set_integer(
4113
8.39k
      IMAGE_DLLCHARACTERISTICS_NX_COMPAT, module_object, "NX_COMPAT");
4114
8.39k
  yr_set_integer(
4115
8.39k
      IMAGE_DLLCHARACTERISTICS_NO_ISOLATION, module_object, "NO_ISOLATION");
4116
8.39k
  yr_set_integer(IMAGE_DLLCHARACTERISTICS_NO_SEH, module_object, "NO_SEH");
4117
8.39k
  yr_set_integer(IMAGE_DLLCHARACTERISTICS_NO_BIND, module_object, "NO_BIND");
4118
8.39k
  yr_set_integer(
4119
8.39k
      IMAGE_DLLCHARACTERISTICS_APPCONTAINER, module_object, "APPCONTAINER");
4120
8.39k
  yr_set_integer(
4121
8.39k
      IMAGE_DLLCHARACTERISTICS_WDM_DRIVER, module_object, "WDM_DRIVER");
4122
8.39k
  yr_set_integer(IMAGE_DLLCHARACTERISTICS_GUARD_CF, module_object, "GUARD_CF");
4123
8.39k
  yr_set_integer(
4124
8.39k
      IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE,
4125
8.39k
      module_object,
4126
8.39k
      "TERMINAL_SERVER_AWARE");
4127
4128
8.39k
  yr_set_integer(IMAGE_FILE_RELOCS_STRIPPED, module_object, "RELOCS_STRIPPED");
4129
8.39k
  yr_set_integer(
4130
8.39k
      IMAGE_FILE_EXECUTABLE_IMAGE, module_object, "EXECUTABLE_IMAGE");
4131
8.39k
  yr_set_integer(
4132
8.39k
      IMAGE_FILE_LINE_NUMS_STRIPPED, module_object, "LINE_NUMS_STRIPPED");
4133
8.39k
  yr_set_integer(
4134
8.39k
      IMAGE_FILE_LOCAL_SYMS_STRIPPED, module_object, "LOCAL_SYMS_STRIPPED");
4135
8.39k
  yr_set_integer(
4136
8.39k
      IMAGE_FILE_AGGRESIVE_WS_TRIM, module_object, "AGGRESIVE_WS_TRIM");
4137
8.39k
  yr_set_integer(
4138
8.39k
      IMAGE_FILE_LARGE_ADDRESS_AWARE, module_object, "LARGE_ADDRESS_AWARE");
4139
8.39k
  yr_set_integer(
4140
8.39k
      IMAGE_FILE_BYTES_REVERSED_LO, module_object, "BYTES_REVERSED_LO");
4141
8.39k
  yr_set_integer(IMAGE_FILE_32BIT_MACHINE, module_object, "MACHINE_32BIT");
4142
8.39k
  yr_set_integer(IMAGE_FILE_DEBUG_STRIPPED, module_object, "DEBUG_STRIPPED");
4143
8.39k
  yr_set_integer(
4144
8.39k
      IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP,
4145
8.39k
      module_object,
4146
8.39k
      "REMOVABLE_RUN_FROM_SWAP");
4147
8.39k
  yr_set_integer(
4148
8.39k
      IMAGE_FILE_NET_RUN_FROM_SWAP, module_object, "NET_RUN_FROM_SWAP");
4149
8.39k
  yr_set_integer(IMAGE_FILE_SYSTEM, module_object, "SYSTEM");
4150
8.39k
  yr_set_integer(IMAGE_FILE_DLL, module_object, "DLL");
4151
8.39k
  yr_set_integer(IMAGE_FILE_UP_SYSTEM_ONLY, module_object, "UP_SYSTEM_ONLY");
4152
8.39k
  yr_set_integer(
4153
8.39k
      IMAGE_FILE_BYTES_REVERSED_HI, module_object, "BYTES_REVERSED_HI");
4154
4155
8.39k
  yr_set_integer(
4156
8.39k
      IMAGE_DIRECTORY_ENTRY_EXPORT,
4157
8.39k
      module_object,
4158
8.39k
      "IMAGE_DIRECTORY_ENTRY_EXPORT");
4159
8.39k
  yr_set_integer(
4160
8.39k
      IMAGE_DIRECTORY_ENTRY_IMPORT,
4161
8.39k
      module_object,
4162
8.39k
      "IMAGE_DIRECTORY_ENTRY_IMPORT");
4163
8.39k
  yr_set_integer(
4164
8.39k
      IMAGE_DIRECTORY_ENTRY_RESOURCE,
4165
8.39k
      module_object,
4166
8.39k
      "IMAGE_DIRECTORY_ENTRY_RESOURCE");
4167
8.39k
  yr_set_integer(
4168
8.39k
      IMAGE_DIRECTORY_ENTRY_EXCEPTION,
4169
8.39k
      module_object,
4170
8.39k
      "IMAGE_DIRECTORY_ENTRY_EXCEPTION");
4171
8.39k
  yr_set_integer(
4172
8.39k
      IMAGE_DIRECTORY_ENTRY_SECURITY,
4173
8.39k
      module_object,
4174
8.39k
      "IMAGE_DIRECTORY_ENTRY_SECURITY");
4175
8.39k
  yr_set_integer(
4176
8.39k
      IMAGE_DIRECTORY_ENTRY_BASERELOC,
4177
8.39k
      module_object,
4178
8.39k
      "IMAGE_DIRECTORY_ENTRY_BASERELOC");
4179
8.39k
  yr_set_integer(
4180
8.39k
      IMAGE_DIRECTORY_ENTRY_DEBUG,
4181
8.39k
      module_object,
4182
8.39k
      "IMAGE_DIRECTORY_ENTRY_DEBUG");
4183
8.39k
  yr_set_integer(
4184
8.39k
      IMAGE_DIRECTORY_ENTRY_ARCHITECTURE,
4185
8.39k
      module_object,
4186
8.39k
      "IMAGE_DIRECTORY_ENTRY_ARCHITECTURE");
4187
8.39k
  yr_set_integer(
4188
8.39k
      IMAGE_DIRECTORY_ENTRY_COPYRIGHT,
4189
8.39k
      module_object,
4190
8.39k
      "IMAGE_DIRECTORY_ENTRY_COPYRIGHT");
4191
8.39k
  yr_set_integer(
4192
8.39k
      IMAGE_DIRECTORY_ENTRY_GLOBALPTR,
4193
8.39k
      module_object,
4194
8.39k
      "IMAGE_DIRECTORY_ENTRY_GLOBALPTR");
4195
8.39k
  yr_set_integer(
4196
8.39k
      IMAGE_DIRECTORY_ENTRY_TLS, module_object, "IMAGE_DIRECTORY_ENTRY_TLS");
4197
8.39k
  yr_set_integer(
4198
8.39k
      IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
4199
8.39k
      module_object,
4200
8.39k
      "IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG");
4201
8.39k
  yr_set_integer(
4202
8.39k
      IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT,
4203
8.39k
      module_object,
4204
8.39k
      "IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT");
4205
8.39k
  yr_set_integer(
4206
8.39k
      IMAGE_DIRECTORY_ENTRY_IAT, module_object, "IMAGE_DIRECTORY_ENTRY_IAT");
4207
8.39k
  yr_set_integer(
4208
8.39k
      IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT,
4209
8.39k
      module_object,
4210
8.39k
      "IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT");
4211
8.39k
  yr_set_integer(
4212
8.39k
      IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR,
4213
8.39k
      module_object,
4214
8.39k
      "IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR");
4215
4216
8.39k
  yr_set_integer(
4217
8.39k
      IMAGE_NT_OPTIONAL_HDR32_MAGIC,
4218
8.39k
      module_object,
4219
8.39k
      "IMAGE_NT_OPTIONAL_HDR32_MAGIC");
4220
8.39k
  yr_set_integer(
4221
8.39k
      IMAGE_NT_OPTIONAL_HDR64_MAGIC,
4222
8.39k
      module_object,
4223
8.39k
      "IMAGE_NT_OPTIONAL_HDR64_MAGIC");
4224
8.39k
  yr_set_integer(
4225
8.39k
      IMAGE_ROM_OPTIONAL_HDR_MAGIC,
4226
8.39k
      module_object,
4227
8.39k
      "IMAGE_ROM_OPTIONAL_HDR_MAGIC");
4228
4229
8.39k
  yr_set_integer(IMAGE_SCN_TYPE_NO_PAD, module_object, "SECTION_NO_PAD");
4230
8.39k
  yr_set_integer(IMAGE_SCN_CNT_CODE, module_object, "SECTION_CNT_CODE");
4231
8.39k
  yr_set_integer(
4232
8.39k
      IMAGE_SCN_CNT_INITIALIZED_DATA,
4233
8.39k
      module_object,
4234
8.39k
      "SECTION_CNT_INITIALIZED_DATA");
4235
8.39k
  yr_set_integer(
4236
8.39k
      IMAGE_SCN_CNT_UNINITIALIZED_DATA,
4237
8.39k
      module_object,
4238
8.39k
      "SECTION_CNT_UNINITIALIZED_DATA");
4239
8.39k
  yr_set_integer(IMAGE_SCN_LNK_OTHER, module_object, "SECTION_LNK_OTHER");
4240
8.39k
  yr_set_integer(IMAGE_SCN_LNK_INFO, module_object, "SECTION_LNK_INFO");
4241
8.39k
  yr_set_integer(IMAGE_SCN_LNK_REMOVE, module_object, "SECTION_LNK_REMOVE");
4242
8.39k
  yr_set_integer(IMAGE_SCN_LNK_COMDAT, module_object, "SECTION_LNK_COMDAT");
4243
8.39k
  yr_set_integer(
4244
8.39k
      IMAGE_SCN_NO_DEFER_SPEC_EXC, module_object, "SECTION_NO_DEFER_SPEC_EXC");
4245
8.39k
  yr_set_integer(IMAGE_SCN_GPREL, module_object, "SECTION_GPREL");
4246
8.39k
  yr_set_integer(IMAGE_SCN_MEM_FARDATA, module_object, "SECTION_MEM_FARDATA");
4247
8.39k
  yr_set_integer(
4248
8.39k
      IMAGE_SCN_MEM_PURGEABLE, module_object, "SECTION_MEM_PURGEABLE");
4249
8.39k
  yr_set_integer(IMAGE_SCN_MEM_16BIT, module_object, "SECTION_MEM_16BIT");
4250
8.39k
  yr_set_integer(IMAGE_SCN_MEM_LOCKED, module_object, "SECTION_MEM_LOCKED");
4251
8.39k
  yr_set_integer(IMAGE_SCN_MEM_PRELOAD, module_object, "SECTION_MEM_PRELOAD");
4252
8.39k
  yr_set_integer(IMAGE_SCN_ALIGN_1BYTES, module_object, "SECTION_ALIGN_1BYTES");
4253
8.39k
  yr_set_integer(IMAGE_SCN_ALIGN_2BYTES, module_object, "SECTION_ALIGN_2BYTES");
4254
8.39k
  yr_set_integer(IMAGE_SCN_ALIGN_4BYTES, module_object, "SECTION_ALIGN_4BYTES");
4255
8.39k
  yr_set_integer(IMAGE_SCN_ALIGN_8BYTES, module_object, "SECTION_ALIGN_8BYTES");
4256
8.39k
  yr_set_integer(
4257
8.39k
      IMAGE_SCN_ALIGN_16BYTES, module_object, "SECTION_ALIGN_16BYTES");
4258
8.39k
  yr_set_integer(
4259
8.39k
      IMAGE_SCN_ALIGN_32BYTES, module_object, "SECTION_ALIGN_32BYTES");
4260
8.39k
  yr_set_integer(
4261
8.39k
      IMAGE_SCN_ALIGN_64BYTES, module_object, "SECTION_ALIGN_64BYTES");
4262
8.39k
  yr_set_integer(
4263
8.39k
      IMAGE_SCN_ALIGN_128BYTES, module_object, "SECTION_ALIGN_128BYTES");
4264
8.39k
  yr_set_integer(
4265
8.39k
      IMAGE_SCN_ALIGN_256BYTES, module_object, "SECTION_ALIGN_256BYTES");
4266
8.39k
  yr_set_integer(
4267
8.39k
      IMAGE_SCN_ALIGN_512BYTES, module_object, "SECTION_ALIGN_512BYTES");
4268
8.39k
  yr_set_integer(
4269
8.39k
      IMAGE_SCN_ALIGN_1024BYTES, module_object, "SECTION_ALIGN_1024BYTES");
4270
8.39k
  yr_set_integer(
4271
8.39k
      IMAGE_SCN_ALIGN_2048BYTES, module_object, "SECTION_ALIGN_2048BYTES");
4272
8.39k
  yr_set_integer(
4273
8.39k
      IMAGE_SCN_ALIGN_4096BYTES, module_object, "SECTION_ALIGN_4096BYTES");
4274
8.39k
  yr_set_integer(
4275
8.39k
      IMAGE_SCN_ALIGN_8192BYTES, module_object, "SECTION_ALIGN_8192BYTES");
4276
8.39k
  yr_set_integer(IMAGE_SCN_ALIGN_MASK, module_object, "SECTION_ALIGN_MASK");
4277
8.39k
  yr_set_integer(
4278
8.39k
      IMAGE_SCN_LNK_NRELOC_OVFL, module_object, "SECTION_LNK_NRELOC_OVFL");
4279
8.39k
  yr_set_integer(
4280
8.39k
      IMAGE_SCN_MEM_DISCARDABLE, module_object, "SECTION_MEM_DISCARDABLE");
4281
8.39k
  yr_set_integer(
4282
8.39k
      IMAGE_SCN_MEM_NOT_CACHED, module_object, "SECTION_MEM_NOT_CACHED");
4283
8.39k
  yr_set_integer(
4284
8.39k
      IMAGE_SCN_MEM_NOT_PAGED, module_object, "SECTION_MEM_NOT_PAGED");
4285
8.39k
  yr_set_integer(IMAGE_SCN_MEM_SHARED, module_object, "SECTION_MEM_SHARED");
4286
8.39k
  yr_set_integer(IMAGE_SCN_MEM_EXECUTE, module_object, "SECTION_MEM_EXECUTE");
4287
8.39k
  yr_set_integer(IMAGE_SCN_MEM_READ, module_object, "SECTION_MEM_READ");
4288
8.39k
  yr_set_integer(IMAGE_SCN_MEM_WRITE, module_object, "SECTION_MEM_WRITE");
4289
8.39k
  yr_set_integer(IMAGE_SCN_SCALE_INDEX, module_object, "SECTION_SCALE_INDEX");
4290
4291
8.39k
  yr_set_integer(RESOURCE_TYPE_CURSOR, module_object, "RESOURCE_TYPE_CURSOR");
4292
8.39k
  yr_set_integer(RESOURCE_TYPE_BITMAP, module_object, "RESOURCE_TYPE_BITMAP");
4293
8.39k
  yr_set_integer(RESOURCE_TYPE_ICON, module_object, "RESOURCE_TYPE_ICON");
4294
8.39k
  yr_set_integer(RESOURCE_TYPE_MENU, module_object, "RESOURCE_TYPE_MENU");
4295
8.39k
  yr_set_integer(RESOURCE_TYPE_DIALOG, module_object, "RESOURCE_TYPE_DIALOG");
4296
8.39k
  yr_set_integer(RESOURCE_TYPE_STRING, module_object, "RESOURCE_TYPE_STRING");
4297
8.39k
  yr_set_integer(RESOURCE_TYPE_FONTDIR, module_object, "RESOURCE_TYPE_FONTDIR");
4298
8.39k
  yr_set_integer(RESOURCE_TYPE_FONT, module_object, "RESOURCE_TYPE_FONT");
4299
8.39k
  yr_set_integer(
4300
8.39k
      RESOURCE_TYPE_ACCELERATOR, module_object, "RESOURCE_TYPE_ACCELERATOR");
4301
8.39k
  yr_set_integer(RESOURCE_TYPE_RCDATA, module_object, "RESOURCE_TYPE_RCDATA");
4302
8.39k
  yr_set_integer(
4303
8.39k
      RESOURCE_TYPE_MESSAGETABLE, module_object, "RESOURCE_TYPE_MESSAGETABLE");
4304
8.39k
  yr_set_integer(
4305
8.39k
      RESOURCE_TYPE_GROUP_CURSOR, module_object, "RESOURCE_TYPE_GROUP_CURSOR");
4306
8.39k
  yr_set_integer(
4307
8.39k
      RESOURCE_TYPE_GROUP_ICON, module_object, "RESOURCE_TYPE_GROUP_ICON");
4308
8.39k
  yr_set_integer(RESOURCE_TYPE_VERSION, module_object, "RESOURCE_TYPE_VERSION");
4309
8.39k
  yr_set_integer(
4310
8.39k
      RESOURCE_TYPE_DLGINCLUDE, module_object, "RESOURCE_TYPE_DLGINCLUDE");
4311
8.39k
  yr_set_integer(
4312
8.39k
      RESOURCE_TYPE_PLUGPLAY, module_object, "RESOURCE_TYPE_PLUGPLAY");
4313
8.39k
  yr_set_integer(RESOURCE_TYPE_VXD, module_object, "RESOURCE_TYPE_VXD");
4314
8.39k
  yr_set_integer(
4315
8.39k
      RESOURCE_TYPE_ANICURSOR, module_object, "RESOURCE_TYPE_ANICURSOR");
4316
8.39k
  yr_set_integer(RESOURCE_TYPE_ANIICON, module_object, "RESOURCE_TYPE_ANIICON");
4317
8.39k
  yr_set_integer(RESOURCE_TYPE_HTML, module_object, "RESOURCE_TYPE_HTML");
4318
8.39k
  yr_set_integer(
4319
8.39k
      RESOURCE_TYPE_MANIFEST, module_object, "RESOURCE_TYPE_MANIFEST");
4320
4321
8.39k
  yr_set_integer(
4322
8.39k
      IMAGE_DEBUG_TYPE_UNKNOWN, module_object, "IMAGE_DEBUG_TYPE_UNKNOWN");
4323
8.39k
  yr_set_integer(IMAGE_DEBUG_TYPE_COFF, module_object, "IMAGE_DEBUG_TYPE_COFF");
4324
8.39k
  yr_set_integer(
4325
8.39k
      IMAGE_DEBUG_TYPE_CODEVIEW, module_object, "IMAGE_DEBUG_TYPE_CODEVIEW");
4326
8.39k
  yr_set_integer(IMAGE_DEBUG_TYPE_FPO, module_object, "IMAGE_DEBUG_TYPE_FPO");
4327
8.39k
  yr_set_integer(IMAGE_DEBUG_TYPE_MISC, module_object, "IMAGE_DEBUG_TYPE_MISC");
4328
8.39k
  yr_set_integer(
4329
8.39k
      IMAGE_DEBUG_TYPE_EXCEPTION, module_object, "IMAGE_DEBUG_TYPE_EXCEPTION");
4330
8.39k
  yr_set_integer(
4331
8.39k
      IMAGE_DEBUG_TYPE_FIXUP, module_object, "IMAGE_DEBUG_TYPE_FIXUP");
4332
8.39k
  yr_set_integer(
4333
8.39k
      IMAGE_DEBUG_TYPE_OMAP_TO_SRC,
4334
8.39k
      module_object,
4335
8.39k
      "IMAGE_DEBUG_TYPE_OMAP_TO_SRC");
4336
8.39k
  yr_set_integer(
4337
8.39k
      IMAGE_DEBUG_TYPE_OMAP_FROM_SRC,
4338
8.39k
      module_object,
4339
8.39k
      "IMAGE_DEBUG_TYPE_OMAP_FROM_SRC");
4340
8.39k
  yr_set_integer(
4341
8.39k
      IMAGE_DEBUG_TYPE_BORLAND, module_object, "IMAGE_DEBUG_TYPE_BORLAND");
4342
8.39k
  yr_set_integer(
4343
8.39k
      IMAGE_DEBUG_TYPE_RESERVED10,
4344
8.39k
      module_object,
4345
8.39k
      "IMAGE_DEBUG_TYPE_RESERVED10");
4346
8.39k
  yr_set_integer(
4347
8.39k
      IMAGE_DEBUG_TYPE_CLSID, module_object, "IMAGE_DEBUG_TYPE_CLSID");
4348
8.39k
  yr_set_integer(
4349
8.39k
      IMAGE_DEBUG_TYPE_VC_FEATURE,
4350
8.39k
      module_object,
4351
8.39k
      "IMAGE_DEBUG_TYPE_VC_FEATURE");
4352
8.39k
  yr_set_integer(IMAGE_DEBUG_TYPE_POGO, module_object, "IMAGE_DEBUG_TYPE_POGO");
4353
8.39k
  yr_set_integer(
4354
8.39k
      IMAGE_DEBUG_TYPE_ILTCG, module_object, "IMAGE_DEBUG_TYPE_ILTCG");
4355
8.39k
  yr_set_integer(IMAGE_DEBUG_TYPE_MPX, module_object, "IMAGE_DEBUG_TYPE_MPX");
4356
8.39k
  yr_set_integer(
4357
8.39k
      IMAGE_DEBUG_TYPE_REPRO, module_object, "IMAGE_DEBUG_TYPE_REPRO");
4358
4359
8.39k
  yr_set_integer(0, module_object, "is_pe");
4360
4361
8.39k
  foreach_memory_block(iterator, block)
4362
8.39k
  {
4363
8.39k
    block_data = yr_fetch_block_data(block);
4364
4365
8.39k
    if (block_data == NULL)
4366
0
      continue;
4367
4368
8.39k
    pe_header = pe_get_header(block_data, block->size);
4369
4370
8.39k
    if (pe_header != NULL)
4371
7.00k
    {
4372
      // Ignore DLLs while scanning a process
4373
4374
7.00k
      if (!(context->flags & SCAN_FLAGS_PROCESS_MEMORY) ||
4375
0
          !(yr_le16toh(pe_header->FileHeader.Characteristics) & IMAGE_FILE_DLL))
4376
7.00k
      {
4377
7.00k
        pe = (PE*) yr_malloc(sizeof(PE));
4378
4379
7.00k
        if (pe == NULL)
4380
0
          return ERROR_INSUFFICIENT_MEMORY;
4381
4382
7.00k
        FAIL_ON_ERROR_WITH_CLEANUP(
4383
7.00k
            yr_hash_table_create(17, &pe->hash_table), yr_free(pe));
4384
4385
7.00k
        pe->data = block_data;
4386
7.00k
        pe->data_size = block->size;
4387
7.00k
        pe->header = pe_header;
4388
7.00k
        pe->object = module_object;
4389
7.00k
        pe->resources = 0;
4390
7.00k
        pe->version_infos = 0;
4391
4392
7.00k
        module_object->data = pe;
4393
4394
7.00k
        pe_parse_header(pe, block->base, context->flags);
4395
7.00k
        pe_parse_rich_signature(pe, block->base);
4396
7.00k
        pe_parse_debug_directory(pe);
4397
4398
#if defined(HAVE_LIBCRYPTO) && !defined(BORINGSSL)
4399
        pe_parse_certificates(pe);
4400
#endif
4401
4402
7.00k
        pe->imported_dlls = pe_parse_imports(pe);
4403
7.00k
        pe->delay_imported_dlls = pe_parse_delayed_imports(pe);
4404
7.00k
        pe_parse_exports(pe);
4405
4406
7.00k
        break;
4407
7.00k
      }
4408
7.00k
    }
4409
8.39k
  }
4410
4411
8.39k
  return ERROR_SUCCESS;
4412
8.39k
}
4413
4414
void free_dlls(IMPORTED_DLL* dll)
4415
14.0k
{
4416
14.0k
  IMPORTED_DLL* next_dll = NULL;
4417
14.0k
  IMPORT_FUNCTION* func = NULL;
4418
14.0k
  IMPORT_FUNCTION* next_func = NULL;
4419
4420
78.8k
  while (dll)
4421
64.7k
  {
4422
64.7k
    if (dll->name)
4423
64.7k
      yr_free(dll->name);
4424
4425
64.7k
    func = dll->functions;
4426
4427
9.27M
    while (func)
4428
9.20M
    {
4429
9.20M
      if (func->name)
4430
9.20M
        yr_free(func->name);
4431
4432
9.20M
      next_func = func->next;
4433
9.20M
      yr_free(func);
4434
9.20M
      func = next_func;
4435
9.20M
    }
4436
4437
64.7k
    next_dll = dll->next;
4438
64.7k
    yr_free(dll);
4439
64.7k
    dll = next_dll;
4440
64.7k
  }
4441
14.0k
}
4442
4443
int module_unload(YR_OBJECT* module_object)
4444
8.39k
{
4445
8.39k
  PE* pe = (PE*) module_object->data;
4446
4447
8.39k
  if (pe == NULL)
4448
1.38k
    return ERROR_SUCCESS;
4449
4450
7.00k
  if (pe->hash_table != NULL)
4451
7.00k
    yr_hash_table_destroy(
4452
7.00k
        pe->hash_table, (YR_HASH_TABLE_FREE_VALUE_FUNC) yr_free);
4453
4454
7.00k
  free_dlls(pe->imported_dlls);
4455
7.00k
  free_dlls(pe->delay_imported_dlls);
4456
4457
7.00k
  yr_free(pe);
4458
4459
7.00k
  return ERROR_SUCCESS;
4460
8.39k
}