Coverage Report

Created: 2026-02-26 06:40

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