Coverage Report

Created: 2023-06-07 07:18

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