Coverage Report

Created: 2025-07-23 06:46

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