Coverage Report

Created: 2023-03-01 06:20

/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) + 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 = 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
      yr_set_integer(offset, pe->object, "export_details[%i].offset", exp_sz);
1626
0
    }
1627
1628
0
    if (names != NULL)
1629
0
    {
1630
0
      for (j = 0; j < number_of_exports; j++)
1631
0
      {
1632
0
        if (yr_le16toh(ordinals[j]) == i && j < number_of_names)
1633
0
        {
1634
0
          offset = pe_rva_to_offset(pe, yr_le32toh(names[j]));
1635
1636
0
          if (offset > 0)
1637
0
          {
1638
0
            remaining = pe->data_size - (size_t) offset;
1639
0
            name_len = strnlen((char*) (pe->data + offset), remaining);
1640
1641
0
            yr_set_sized_string(
1642
0
                (char*) (pe->data + offset),
1643
0
                yr_min(name_len, MAX_EXPORT_NAME_LENGTH),
1644
0
                pe->object,
1645
0
                "export_details[%i].name",
1646
0
                exp_sz);
1647
0
          }
1648
0
          break;
1649
0
        }
1650
0
      }
1651
0
    }
1652
0
    exp_sz++;
1653
0
  }
1654
1655
0
  yr_set_integer(exp_sz, pe->object, "number_of_exports");
1656
0
}
1657
1658
// BoringSSL (https://boringssl.googlesource.com/boringssl/) doesn't support
1659
// some features used in pe_parse_certificates, if you are using BoringSSL
1660
// instead of OpenSSL you should define BORINGSSL for YARA to compile properly,
1661
// but you won't have signature-related features in the PE module.
1662
#if defined(HAVE_LIBCRYPTO) && !defined(BORINGSSL)
1663
1664
#define write_certificate(cert, pe, fmt, ...)                                  \
1665
  do                                                                           \
1666
  {                                                                            \
1667
    char thumbprint_ascii[YR_SHA1_LEN * 2 + 1];                                \
1668
    for (int j = 0; j < cert->sha1.len; ++j)                                   \
1669
      sprintf(thumbprint_ascii + (j * 2), "%02x", cert->sha1.data[j]);         \
1670
                                                                               \
1671
    yr_set_string(                                                             \
1672
        (char*) thumbprint_ascii, pe->object, fmt ".thumbprint", __VA_ARGS__); \
1673
                                                                               \
1674
    yr_set_string(cert->issuer, pe->object, fmt ".issuer", __VA_ARGS__);       \
1675
    yr_set_string(cert->subject, pe->object, fmt ".subject", __VA_ARGS__);     \
1676
    /* Versions are zero based, so add one.  */                                \
1677
    yr_set_integer(                                                            \
1678
        cert->version + 1, pe->object, fmt ".version", __VA_ARGS__);           \
1679
    yr_set_string(cert->sig_alg, pe->object, fmt ".algorithm", __VA_ARGS__);   \
1680
    yr_set_string(                                                             \
1681
        cert->sig_alg_oid, pe->object, fmt ".algorithm_oid", __VA_ARGS__);     \
1682
    yr_set_string(cert->serial, pe->object, fmt ".serial", __VA_ARGS__);       \
1683
    yr_set_integer(                                                            \
1684
        cert->not_before, pe->object, fmt ".not_before", __VA_ARGS__);         \
1685
    yr_set_integer(                                                            \
1686
        cert->not_after, pe->object, fmt ".not_after", __VA_ARGS__);           \
1687
  } while (0)
1688
1689
void _process_authenticode(
1690
    PE* pe,
1691
    AuthenticodeArray* auth_array,
1692
    int* sig_count)
1693
{
1694
  if (!auth_array || !auth_array->count)
1695
    return;
1696
1697
  /* If any signature will be valid -> file is correctly signed */
1698
  bool signature_valid = false;
1699
1700
  for (size_t i = 0; i < auth_array->count; ++i)
1701
  {
1702
    const Authenticode* authenticode = auth_array->signatures[i];
1703
1704
    signature_valid = authenticode->verify_flags == AUTHENTICODE_VFY_VALID
1705
                          ? true
1706
                          : false;
1707
1708
    yr_set_integer(
1709
        signature_valid, pe->object, "signatures[%i].verified", *sig_count);
1710
1711
    yr_set_string(
1712
        authenticode->digest_alg,
1713
        pe->object,
1714
        "signatures[%i].digest_alg",
1715
        *sig_count);
1716
1717
    if (authenticode->digest.data)
1718
    {
1719
      char* digest_ascii = yr_malloc(authenticode->digest.len * 2 + 1);
1720
      for (int j = 0; j < authenticode->digest.len; ++j)
1721
        sprintf(digest_ascii + (j * 2), "%02x", authenticode->digest.data[j]);
1722
1723
      yr_set_string(
1724
          digest_ascii, pe->object, "signatures[%i].digest", *sig_count);
1725
      yr_free(digest_ascii);
1726
    }
1727
1728
    if (authenticode->file_digest.data)
1729
    {
1730
      char* digest_ascii = yr_malloc(authenticode->file_digest.len * 2 + 1);
1731
      for (int j = 0; j < authenticode->file_digest.len; ++j)
1732
        sprintf(
1733
            digest_ascii + (j * 2), "%02x", authenticode->file_digest.data[j]);
1734
1735
      yr_set_string(
1736
          digest_ascii, pe->object, "signatures[%i].file_digest", *sig_count);
1737
      yr_free(digest_ascii);
1738
    }
1739
1740
    yr_set_integer(
1741
        authenticode->certs ? authenticode->certs->count : 0,
1742
        pe->object,
1743
        "signatures[%i].number_of_certificates",
1744
        *sig_count);
1745
1746
    if (authenticode->certs)
1747
    {
1748
      for (int k = 0; k < authenticode->certs->count; ++k)
1749
      {
1750
        write_certificate(
1751
            authenticode->certs->certs[k],
1752
            pe,
1753
            "signatures[%i].certificates[%i]",
1754
            *sig_count,
1755
            k);
1756
      }
1757
    }
1758
1759
    const Signer* signer = authenticode->signer;
1760
    if (signer)
1761
    {
1762
      /* For compatibility with previous YARA rules, write information
1763
       * about signing certificate in the same way */
1764
      if (signer->chain && signer->chain->count >= 1)
1765
      {
1766
        const Certificate* sign_cert = signer->chain->certs[0];
1767
        write_certificate(sign_cert, pe, "signatures[%i]", *sig_count);
1768
      }
1769
1770
      yr_set_string(
1771
          signer->program_name,
1772
          pe->object,
1773
          "signatures[%i].signer_info.program_name",
1774
          *sig_count);
1775
      yr_set_string(
1776
          signer->digest_alg,
1777
          pe->object,
1778
          "signatures[%i].signer_info.digest_alg",
1779
          *sig_count);
1780
1781
      if (signer->digest.data)
1782
      {
1783
        char* digest_ascii = yr_malloc(signer->digest.len * 2 + 1);
1784
        for (int j = 0; j < signer->digest.len; ++j)
1785
          sprintf(digest_ascii + (j * 2), "%02x", signer->digest.data[j]);
1786
1787
        yr_set_string(
1788
            digest_ascii,
1789
            pe->object,
1790
            "signatures[%i].signer_info.digest",
1791
            *sig_count);
1792
        yr_free(digest_ascii);
1793
      }
1794
1795
      yr_set_integer(
1796
          signer->chain ? signer->chain->count : 0,
1797
          pe->object,
1798
          "signatures[%i].signer_info.length_of_chain",
1799
          *sig_count);
1800
1801
      if (signer->chain)
1802
      {
1803
        for (int k = 0; k < signer->chain->count; ++k)
1804
        {
1805
          write_certificate(
1806
              signer->chain->certs[k],
1807
              pe,
1808
              "signatures[%i].signer_info.chain[%i]",
1809
              *sig_count,
1810
              k);
1811
        }
1812
      }
1813
    }
1814
1815
    yr_set_integer(
1816
        authenticode->countersigs ? authenticode->countersigs->count : 0,
1817
        pe->object,
1818
        "signatures[%i].number_of_countersignatures",
1819
        *sig_count);
1820
1821
    if (authenticode->countersigs)
1822
    {
1823
      for (int j = 0; j < authenticode->countersigs->count; ++j)
1824
      {
1825
        const Countersignature* counter =
1826
            authenticode->countersigs->counters[j];
1827
1828
        yr_set_integer(
1829
            counter->verify_flags == COUNTERSIGNATURE_VFY_VALID,
1830
            pe->object,
1831
            "signatures[%i].countersignatures[%i].verified",
1832
            *sig_count,
1833
            j);
1834
        yr_set_string(
1835
            counter->digest_alg,
1836
            pe->object,
1837
            "signatures[%i].countersignatures[%i].digest_alg",
1838
            *sig_count,
1839
            j);
1840
        yr_set_integer(
1841
            counter->sign_time,
1842
            pe->object,
1843
            "signatures[%i].countersignatures[%i].sign_time",
1844
            *sig_count,
1845
            j);
1846
1847
        if (counter->digest.data)
1848
        {
1849
          char* digest_ascii = yr_malloc(counter->digest.len * 2 + 1);
1850
          for (int j = 0; j < counter->digest.len; ++j)
1851
            sprintf(digest_ascii + (j * 2), "%02x", counter->digest.data[j]);
1852
1853
          yr_set_string(
1854
              digest_ascii,
1855
              pe->object,
1856
              "signatures[%i].countersignatures[%i].digest",
1857
              *sig_count,
1858
              j);
1859
          yr_free(digest_ascii);
1860
        }
1861
1862
        yr_set_integer(
1863
            counter->chain ? counter->chain->count : 0,
1864
            pe->object,
1865
            "signatures[%i].countersignatures[%i].length_of_chain",
1866
            *sig_count,
1867
            j);
1868
1869
        if (counter->chain)
1870
        {
1871
          for (int k = 0; k < counter->chain->count; ++k)
1872
          {
1873
            write_certificate(
1874
                counter->chain->certs[k],
1875
                pe,
1876
                "signatures[%i].countersignatures[%i].chain[%i]",
1877
                *sig_count,
1878
                j,
1879
                k);
1880
          }
1881
        }
1882
      }
1883
    }
1884
1885
    (*sig_count)++;
1886
  }
1887
1888
  yr_set_integer(signature_valid, pe->object, "is_signed");
1889
}
1890
1891
static void pe_parse_certificates(PE* pe)
1892
{
1893
  int counter = 0;
1894
1895
  // Default to 0 signatures until we know otherwise.
1896
  yr_set_integer(0, pe->object, "number_of_signatures");
1897
1898
  PIMAGE_DATA_DIRECTORY directory = pe_get_directory_entry(
1899
      pe, IMAGE_DIRECTORY_ENTRY_SECURITY);
1900
1901
  if (directory == NULL)
1902
    return;
1903
1904
  // directory->VirtualAddress is a file offset. Don't call pe_rva_to_offset().
1905
  if (yr_le32toh(directory->VirtualAddress) == 0 ||
1906
      yr_le32toh(directory->VirtualAddress) > pe->data_size ||
1907
      yr_le32toh(directory->Size) > pe->data_size ||
1908
      yr_le32toh(directory->VirtualAddress) + yr_le32toh(directory->Size) >
1909
          pe->data_size)
1910
  {
1911
    return;
1912
  }
1913
1914
  AuthenticodeArray* auth_array = parse_authenticode(pe->data, pe->data_size);
1915
  _process_authenticode(pe, auth_array, &counter);
1916
  authenticode_array_free(auth_array);
1917
1918
  yr_set_integer(counter, pe->object, "number_of_signatures");
1919
}
1920
1921
#endif  // defined(HAVE_LIBCRYPTO)
1922
1923
const char* pe_get_section_full_name(
1924
    PE* pe,
1925
    const char* section_name,
1926
    uint64_t section_name_length,
1927
    uint64_t* section_full_name_length)
1928
0
{
1929
  // section_name is an 8-byte, null-padded UTF-8 encoded string. If the string
1930
  // is exactly 8 characters long, there is no terminating null. For longer
1931
  // names, this field contains a slash (/) that is followed by an ASCII
1932
  // representation of a decimal number that is an offset into the string table.
1933
1934
  // Sample: 2e9c671b8a0411f2b397544b368c44d7f095eb395779de0ad1ac946914dfa34c
1935
1936
  // Check if any param is NULL
1937
0
  if (pe == NULL || section_name == NULL || section_full_name_length == NULL)
1938
0
    return NULL;
1939
1940
  // Set length to zero
1941
0
  *section_full_name_length = 0;
1942
1943
  // Offset and number of records in coff table
1944
0
  uint64_t coff_offset = yr_le32toh(
1945
0
      pe->header->FileHeader.PointerToSymbolTable);
1946
0
  uint64_t coff_number = yr_le32toh(pe->header->FileHeader.NumberOfSymbols);
1947
1948
  // If section name start with '/' and file contain coff table then section
1949
  // name is stored in string table
1950
0
  if (coff_offset == 0 || section_name[0] != '/')
1951
0
  {
1952
0
    *section_full_name_length = section_name_length;
1953
0
    return section_name;
1954
0
  }
1955
1956
  // Calculate offset of string table (String table is immediately after coff
1957
  // table)
1958
0
  uint64_t string_offset = coff_offset + coff_number * sizeof(IMAGE_SYMBOL);
1959
0
  uint64_t string_index = 0;
1960
1961
  // Calculate string index/offset in string table
1962
0
  for (int i = 1; i < IMAGE_SIZEOF_SHORT_NAME && isdigit(section_name[i]); i++)
1963
0
    string_index = (string_index * 10) + (section_name[i] - '0');
1964
1965
  // Calculate string pointer
1966
0
  const char* string = (char*) (pe->data + string_offset + string_index);
1967
1968
  // Check string
1969
0
  for (uint64_t len = 0; fits_in_pe(pe, string, len + 1); len++)
1970
0
  {
1971
    // Valid string
1972
0
    if (string[len] == 0)
1973
0
    {
1974
0
      *section_full_name_length = len;
1975
0
      return string;
1976
0
    }
1977
1978
    // string contain unprintable character
1979
0
    if (!isprint(string[len]))
1980
0
      return NULL;
1981
0
  }
1982
1983
  // String do not fit into pe file
1984
0
  return NULL;
1985
0
}
1986
1987
static void pe_parse_header(PE* pe, uint64_t base_address, int flags)
1988
0
{
1989
0
  PIMAGE_SECTION_HEADER section;
1990
0
  PIMAGE_DATA_DIRECTORY data_dir;
1991
1992
0
  char section_name[IMAGE_SIZEOF_SHORT_NAME + 1];
1993
0
  int sect_name_length, scount, ddcount;
1994
1995
0
  uint64_t highest_sec_siz = 0;
1996
0
  uint64_t highest_sec_ofs = 0;
1997
0
  uint64_t section_end;
1998
0
  uint64_t last_section_end;
1999
2000
0
  yr_set_integer(1, pe->object, "is_pe");
2001
2002
0
  yr_set_integer(
2003
0
      yr_le16toh(pe->header->FileHeader.Machine), pe->object, "machine");
2004
2005
0
  yr_set_integer(
2006
0
      yr_le16toh(pe->header->FileHeader.NumberOfSections),
2007
0
      pe->object,
2008
0
      "number_of_sections");
2009
2010
0
  yr_set_integer(
2011
0
      yr_le32toh(pe->header->FileHeader.TimeDateStamp),
2012
0
      pe->object,
2013
0
      "timestamp");
2014
2015
0
  yr_set_integer(
2016
0
      yr_le32toh(pe->header->FileHeader.PointerToSymbolTable),
2017
0
      pe->object,
2018
0
      "pointer_to_symbol_table");
2019
2020
0
  yr_set_integer(
2021
0
      yr_le32toh(pe->header->FileHeader.NumberOfSymbols),
2022
0
      pe->object,
2023
0
      "number_of_symbols");
2024
2025
0
  yr_set_integer(
2026
0
      yr_le32toh(pe->header->FileHeader.SizeOfOptionalHeader),
2027
0
      pe->object,
2028
0
      "size_of_optional_header");
2029
2030
0
  yr_set_integer(
2031
0
      yr_le16toh(pe->header->FileHeader.Characteristics),
2032
0
      pe->object,
2033
0
      "characteristics");
2034
2035
0
  yr_set_integer(
2036
0
      flags & SCAN_FLAGS_PROCESS_MEMORY
2037
0
          ? base_address + yr_le32toh(OptionalHeader(pe, AddressOfEntryPoint))
2038
0
          : pe_rva_to_offset(
2039
0
                pe, yr_le32toh(OptionalHeader(pe, AddressOfEntryPoint))),
2040
0
      pe->object,
2041
0
      "entry_point");
2042
2043
0
  yr_set_integer(
2044
0
      yr_le32toh(OptionalHeader(pe, AddressOfEntryPoint)),
2045
0
      pe->object,
2046
0
      "entry_point_raw");
2047
2048
0
  yr_set_integer(
2049
0
      IS_64BITS_PE(pe) ? yr_le64toh(OptionalHeader(pe, ImageBase))
2050
0
                       : yr_le32toh(OptionalHeader(pe, ImageBase)),
2051
0
      pe->object,
2052
0
      "image_base");
2053
2054
0
  yr_set_integer(
2055
0
      yr_le32toh(OptionalHeader(pe, NumberOfRvaAndSizes)),
2056
0
      pe->object,
2057
0
      "number_of_rva_and_sizes");
2058
2059
0
  yr_set_integer(
2060
0
      yr_le32toh(OptionalHeader(pe, Magic)), pe->object, "opthdr_magic");
2061
2062
0
  yr_set_integer(
2063
0
      OptionalHeader(pe, MajorLinkerVersion),
2064
0
      pe->object,
2065
0
      "linker_version.major");
2066
2067
0
  yr_set_integer(
2068
0
      OptionalHeader(pe, MinorLinkerVersion),
2069
0
      pe->object,
2070
0
      "linker_version.minor");
2071
2072
0
  yr_set_integer(
2073
0
      yr_le32toh(OptionalHeader(pe, SizeOfCode)), pe->object, "size_of_code");
2074
2075
0
  yr_set_integer(
2076
0
      yr_le32toh(OptionalHeader(pe, SizeOfInitializedData)),
2077
0
      pe->object,
2078
0
      "size_of_initialized_data");
2079
2080
0
  yr_set_integer(
2081
0
      yr_le32toh(OptionalHeader(pe, SizeOfUninitializedData)),
2082
0
      pe->object,
2083
0
      "size_of_uninitialized_data");
2084
2085
0
  yr_set_integer(
2086
0
      yr_le32toh(OptionalHeader(pe, BaseOfCode)), pe->object, "base_of_code");
2087
2088
0
  if (!IS_64BITS_PE(pe))
2089
0
  {
2090
0
    yr_set_integer(
2091
0
        yr_le32toh(pe->header->OptionalHeader.BaseOfData),
2092
0
        pe->object,
2093
0
        "base_of_data");
2094
0
  }
2095
2096
0
  yr_set_integer(
2097
0
      yr_le32toh(OptionalHeader(pe, SectionAlignment)),
2098
0
      pe->object,
2099
0
      "section_alignment");
2100
2101
0
  yr_set_integer(
2102
0
      yr_le32toh(OptionalHeader(pe, FileAlignment)),
2103
0
      pe->object,
2104
0
      "file_alignment");
2105
2106
0
  yr_set_integer(
2107
0
      yr_le16toh(OptionalHeader(pe, MajorOperatingSystemVersion)),
2108
0
      pe->object,
2109
0
      "os_version.major");
2110
2111
0
  yr_set_integer(
2112
0
      yr_le16toh(OptionalHeader(pe, MinorOperatingSystemVersion)),
2113
0
      pe->object,
2114
0
      "os_version.minor");
2115
2116
0
  yr_set_integer(
2117
0
      yr_le16toh(OptionalHeader(pe, MajorImageVersion)),
2118
0
      pe->object,
2119
0
      "image_version.major");
2120
2121
0
  yr_set_integer(
2122
0
      yr_le16toh(OptionalHeader(pe, MinorImageVersion)),
2123
0
      pe->object,
2124
0
      "image_version.minor");
2125
2126
0
  yr_set_integer(
2127
0
      yr_le16toh(OptionalHeader(pe, MajorSubsystemVersion)),
2128
0
      pe->object,
2129
0
      "subsystem_version.major");
2130
2131
0
  yr_set_integer(
2132
0
      yr_le16toh(OptionalHeader(pe, MinorSubsystemVersion)),
2133
0
      pe->object,
2134
0
      "subsystem_version.minor");
2135
2136
0
  yr_set_integer(
2137
0
      yr_le32toh(OptionalHeader(pe, Win32VersionValue)),
2138
0
      pe->object,
2139
0
      "win32_version_value");
2140
2141
0
  yr_set_integer(
2142
0
      yr_le32toh(OptionalHeader(pe, SizeOfImage)), pe->object, "size_of_image");
2143
2144
0
  yr_set_integer(
2145
0
      yr_le32toh(OptionalHeader(pe, SizeOfHeaders)),
2146
0
      pe->object,
2147
0
      "size_of_headers");
2148
2149
0
  yr_set_integer(
2150
0
      yr_le32toh(OptionalHeader(pe, CheckSum)), pe->object, "checksum");
2151
2152
0
  yr_set_integer(
2153
0
      yr_le16toh(OptionalHeader(pe, Subsystem)), pe->object, "subsystem");
2154
2155
0
  yr_set_integer(
2156
0
      OptionalHeader(pe, DllCharacteristics),
2157
0
      pe->object,
2158
0
      "dll_characteristics");
2159
2160
0
  yr_set_integer(
2161
0
      IS_64BITS_PE(pe) ? yr_le64toh(OptionalHeader(pe, SizeOfStackReserve))
2162
0
                       : yr_le32toh(OptionalHeader(pe, SizeOfStackReserve)),
2163
0
      pe->object,
2164
0
      "size_of_stack_reserve");
2165
2166
0
  yr_set_integer(
2167
0
      IS_64BITS_PE(pe) ? yr_le64toh(OptionalHeader(pe, SizeOfStackCommit))
2168
0
                       : yr_le32toh(OptionalHeader(pe, SizeOfStackCommit)),
2169
0
      pe->object,
2170
0
      "size_of_stack_commit");
2171
2172
0
  yr_set_integer(
2173
0
      IS_64BITS_PE(pe) ? yr_le64toh(OptionalHeader(pe, SizeOfHeapReserve))
2174
0
                       : yr_le32toh(OptionalHeader(pe, SizeOfHeapReserve)),
2175
0
      pe->object,
2176
0
      "size_of_heap_reserve");
2177
2178
0
  yr_set_integer(
2179
0
      IS_64BITS_PE(pe) ? yr_le64toh(OptionalHeader(pe, SizeOfHeapCommit))
2180
0
                       : yr_le32toh(OptionalHeader(pe, SizeOfHeapCommit)),
2181
0
      pe->object,
2182
0
      "size_of_heap_commit");
2183
2184
0
  yr_set_integer(
2185
0
      yr_le32toh(OptionalHeader(pe, LoaderFlags)), pe->object, "loader_flags");
2186
2187
0
  data_dir = IS_64BITS_PE(pe) ? pe->header64->OptionalHeader.DataDirectory
2188
0
                              : pe->header->OptionalHeader.DataDirectory;
2189
2190
0
  ddcount = yr_le16toh(OptionalHeader(pe, NumberOfRvaAndSizes));
2191
0
  ddcount = yr_min(ddcount, IMAGE_NUMBEROF_DIRECTORY_ENTRIES);
2192
2193
0
  for (int i = 0; i < ddcount; i++)
2194
0
  {
2195
0
    if (!struct_fits_in_pe(pe, data_dir, IMAGE_DATA_DIRECTORY))
2196
0
      break;
2197
2198
0
    yr_set_integer(
2199
0
        yr_le32toh(data_dir->VirtualAddress),
2200
0
        pe->object,
2201
0
        "data_directories[%i].virtual_address",
2202
0
        i);
2203
2204
0
    yr_set_integer(
2205
0
        yr_le32toh(data_dir->Size), pe->object, "data_directories[%i].size", i);
2206
2207
0
    data_dir++;
2208
0
  }
2209
2210
0
  pe_iterate_resources(
2211
0
      pe, (RESOURCE_CALLBACK_FUNC) pe_collect_resources, (void*) pe);
2212
2213
0
  yr_set_integer(pe->resources, pe->object, "number_of_resources");
2214
0
  yr_set_integer(pe->version_infos, pe->object, "number_of_version_infos");
2215
2216
0
  section = IMAGE_FIRST_SECTION(pe->header);
2217
2218
0
  scount = yr_min(
2219
0
      yr_le16toh(pe->header->FileHeader.NumberOfSections), MAX_PE_SECTIONS);
2220
2221
0
  for (int i = 0; i < scount; i++)
2222
0
  {
2223
0
    if (!struct_fits_in_pe(pe, section, IMAGE_SECTION_HEADER))
2224
0
      break;
2225
2226
0
    memcpy(section_name, section->Name, IMAGE_SIZEOF_SHORT_NAME);
2227
0
    section_name[IMAGE_SIZEOF_SHORT_NAME] = '\0';
2228
2229
    // Basically do rstrip('\0'), find the rightmost non-null character.
2230
    // Samples like
2231
    // 0043812838495a45449a0ac61a81b9c16eddca1ad249fb4f7fdb1c4505e9bb34 contain
2232
    // sections with additional characters after the first null.
2233
0
    for (sect_name_length = IMAGE_SIZEOF_SHORT_NAME - 1; sect_name_length >= 0;
2234
0
         --sect_name_length)
2235
0
    {
2236
0
      if (section_name[sect_name_length] != '\0')
2237
0
        break;
2238
0
    }
2239
2240
0
    uint64_t sect_full_name_length = 0;
2241
0
    const char* full_section_name = pe_get_section_full_name(
2242
0
        pe, section_name, sect_name_length + 1, &sect_full_name_length);
2243
2244
0
    yr_set_sized_string(
2245
0
        (char*) section_name,
2246
0
        sect_name_length + 1,
2247
0
        pe->object,
2248
0
        "sections[%i].name",
2249
0
        i);
2250
2251
0
    yr_set_sized_string(
2252
0
        full_section_name,
2253
0
        sect_full_name_length,
2254
0
        pe->object,
2255
0
        "sections[%i].full_name",
2256
0
        i);
2257
2258
0
    yr_set_integer(
2259
0
        yr_le32toh(section->Characteristics),
2260
0
        pe->object,
2261
0
        "sections[%i].characteristics",
2262
0
        i);
2263
2264
0
    yr_set_integer(
2265
0
        yr_le32toh(section->SizeOfRawData),
2266
0
        pe->object,
2267
0
        "sections[%i].raw_data_size",
2268
0
        i);
2269
2270
0
    yr_set_integer(
2271
0
        yr_le32toh(section->PointerToRawData),
2272
0
        pe->object,
2273
0
        "sections[%i].raw_data_offset",
2274
0
        i);
2275
2276
0
    yr_set_integer(
2277
0
        yr_le32toh(section->VirtualAddress),
2278
0
        pe->object,
2279
0
        "sections[%i].virtual_address",
2280
0
        i);
2281
2282
0
    yr_set_integer(
2283
0
        yr_le32toh(section->Misc.VirtualSize),
2284
0
        pe->object,
2285
0
        "sections[%i].virtual_size",
2286
0
        i);
2287
2288
0
    yr_set_integer(
2289
0
        yr_le32toh(section->PointerToRelocations),
2290
0
        pe->object,
2291
0
        "sections[%i].pointer_to_relocations",
2292
0
        i);
2293
2294
0
    yr_set_integer(
2295
0
        yr_le32toh(section->PointerToLinenumbers),
2296
0
        pe->object,
2297
0
        "sections[%i].pointer_to_line_numbers",
2298
0
        i);
2299
2300
0
    yr_set_integer(
2301
0
        yr_le32toh(section->NumberOfRelocations),
2302
0
        pe->object,
2303
0
        "sections[%i].number_of_relocations",
2304
0
        i);
2305
2306
0
    yr_set_integer(
2307
0
        yr_le32toh(section->NumberOfLinenumbers),
2308
0
        pe->object,
2309
0
        "sections[%i].number_of_line_numbers",
2310
0
        i);
2311
2312
    // This will catch the section with the highest raw offset to help checking
2313
    // if overlay data is present. If two sections have the same raw pointer
2314
    // but different raw sizes the largest one is used. An example of this case
2315
    // is file: cf62bf1815a93e68e6c5189f689286b66c4088b9507cf3ecf835e4ac3f9ededa
2316
2317
0
    section_end = yr_le32toh(section->PointerToRawData) +
2318
0
                  yr_le32toh(section->SizeOfRawData);
2319
2320
0
    if (section_end > highest_sec_ofs + highest_sec_siz)
2321
0
    {
2322
0
      highest_sec_ofs = yr_le32toh(section->PointerToRawData);
2323
0
      highest_sec_siz = yr_le32toh(section->SizeOfRawData);
2324
0
    }
2325
2326
0
    section++;
2327
0
  }
2328
2329
  // An overlay is data appended to a PE file. Its location is at
2330
  // RawData + RawOffset of the last section on the physical file
2331
0
  last_section_end = highest_sec_siz + highest_sec_ofs;
2332
2333
  // For PE files that have overlaid data overlay.offset contains the offset
2334
  // within the file where the overlay starts and overlay.size contains the
2335
  // size. If the PE file doesn't have an overlay both fields are 0, if the
2336
  // file is not a PE file (or is a malformed PE) both fields are YR_UNDEFINED.
2337
0
  if (last_section_end && (pe->data_size > last_section_end))
2338
0
  {
2339
0
    yr_set_integer(last_section_end, pe->object, "overlay.offset");
2340
0
    yr_set_integer(
2341
0
        pe->data_size - last_section_end, pe->object, "overlay.size");
2342
0
  }
2343
0
  else
2344
0
  {
2345
0
    yr_set_integer(0, pe->object, "overlay.offset");
2346
0
    yr_set_integer(0, pe->object, "overlay.size");
2347
0
  }
2348
0
}
2349
2350
//
2351
// Given a posix timestamp argument, make sure not_before <= arg <= not_after
2352
//
2353
2354
define_function(valid_on)
2355
0
{
2356
0
  int64_t timestamp;
2357
0
  int64_t not_before;
2358
0
  int64_t not_after;
2359
2360
0
  if (yr_is_undefined(yr_parent(), "not_before") ||
2361
0
      yr_is_undefined(yr_parent(), "not_after"))
2362
0
  {
2363
0
    return_integer(YR_UNDEFINED);
2364
0
  }
2365
2366
0
  timestamp = integer_argument(1);
2367
2368
0
  not_before = yr_get_integer(yr_parent(), "not_before");
2369
0
  not_after = yr_get_integer(yr_parent(), "not_after");
2370
2371
0
  return_integer(timestamp >= not_before && timestamp <= not_after);
2372
0
}
2373
2374
define_function(section_index_addr)
2375
0
{
2376
0
  YR_OBJECT* module = yr_module();
2377
0
  YR_SCAN_CONTEXT* context = yr_scan_context();
2378
2379
0
  int64_t offset;
2380
0
  int64_t size;
2381
2382
0
  int64_t addr = integer_argument(1);
2383
0
  int64_t n = yr_get_integer(module, "number_of_sections");
2384
2385
0
  if (yr_is_undefined(module, "number_of_sections"))
2386
0
    return_integer(YR_UNDEFINED);
2387
2388
0
  for (int i = 0; i < yr_min(n, MAX_PE_SECTIONS); i++)
2389
0
  {
2390
0
    if (context->flags & SCAN_FLAGS_PROCESS_MEMORY)
2391
0
    {
2392
0
      offset = yr_get_integer(module, "sections[%i].virtual_address", i);
2393
0
      size = yr_get_integer(module, "sections[%i].virtual_size", i);
2394
0
    }
2395
0
    else
2396
0
    {
2397
0
      offset = yr_get_integer(module, "sections[%i].raw_data_offset", i);
2398
0
      size = yr_get_integer(module, "sections[%i].raw_data_size", i);
2399
0
    }
2400
2401
0
    if (addr >= offset && addr < offset + size)
2402
0
      return_integer(i);
2403
0
  }
2404
2405
0
  return_integer(YR_UNDEFINED);
2406
0
}
2407
2408
define_function(section_index_name)
2409
0
{
2410
0
  YR_OBJECT* module = yr_module();
2411
2412
0
  char* name = string_argument(1);
2413
2414
0
  int64_t n = yr_get_integer(module, "number_of_sections");
2415
2416
0
  if (yr_is_undefined(module, "number_of_sections"))
2417
0
    return_integer(YR_UNDEFINED);
2418
2419
0
  for (int i = 0; i < yr_min(n, MAX_PE_SECTIONS); i++)
2420
0
  {
2421
0
    SIZED_STRING* sect = yr_get_string(module, "sections[%i].name", i);
2422
2423
0
    if (sect != NULL && strcmp(name, sect->c_string) == 0)
2424
0
      return_integer(i);
2425
0
  }
2426
2427
0
  return_integer(YR_UNDEFINED);
2428
0
}
2429
2430
define_function(exports)
2431
0
{
2432
0
  SIZED_STRING* search_name = sized_string_argument(1);
2433
2434
0
  SIZED_STRING* function_name = NULL;
2435
0
  YR_OBJECT* module = yr_module();
2436
0
  PE* pe = (PE*) module->data;
2437
2438
  // If not a PE, return YR_UNDEFINED.
2439
0
  if (pe == NULL)
2440
0
    return_integer(YR_UNDEFINED);
2441
2442
  // If PE, but no exported functions, return false.
2443
0
  int n = (int) yr_get_integer(module, "number_of_exports");
2444
2445
0
  if (n == 0)
2446
0
    return_integer(0);
2447
2448
0
  for (int i = 0; i < n; i++)
2449
0
  {
2450
0
    function_name = yr_get_string(module, "export_details[%i].name", i);
2451
2452
0
    if (function_name == NULL)
2453
0
      continue;
2454
2455
0
    if (ss_icompare(function_name, search_name) == 0)
2456
0
      return_integer(1);
2457
0
  }
2458
2459
0
  return_integer(0);
2460
0
}
2461
2462
define_function(exports_regexp)
2463
0
{
2464
0
  RE* regex = regexp_argument(1);
2465
2466
0
  SIZED_STRING* function_name = NULL;
2467
0
  YR_OBJECT* module = yr_module();
2468
0
  PE* pe = (PE*) module->data;
2469
2470
  // If not a PE, return YR_UNDEFINED.
2471
0
  if (pe == NULL)
2472
0
    return_integer(YR_UNDEFINED);
2473
2474
  // If PE, but no exported functions, return false.
2475
0
  int n = (int) yr_get_integer(module, "number_of_exports");
2476
2477
0
  if (n == 0)
2478
0
    return_integer(0);
2479
2480
0
  for (int i = 0; i < n; i++)
2481
0
  {
2482
0
    function_name = yr_get_string(module, "export_details[%i].name", i);
2483
0
    if (function_name == NULL)
2484
0
      continue;
2485
2486
0
    if (yr_re_match(yr_scan_context(), regex, function_name->c_string) != -1)
2487
0
      return_integer(1);
2488
0
  }
2489
2490
0
  return_integer(0);
2491
0
}
2492
2493
define_function(exports_ordinal)
2494
0
{
2495
0
  int64_t ordinal = integer_argument(1);
2496
2497
0
  YR_OBJECT* module = yr_module();
2498
0
  PE* pe = (PE*) module->data;
2499
2500
  // If not a PE, return YR_UNDEFINED.
2501
0
  if (pe == NULL)
2502
0
    return_integer(YR_UNDEFINED);
2503
2504
  // If PE, but no exported functions, return false.
2505
0
  int n = (int) yr_get_integer(module, "number_of_exports");
2506
2507
0
  if (n == 0)
2508
0
    return_integer(0);
2509
2510
0
  if (ordinal == 0 || ordinal > n)
2511
0
    return_integer(0);
2512
2513
0
  for (int i = 0; i < n; i++)
2514
0
  {
2515
0
    int64_t exported_ordinal = yr_object_get_integer(
2516
0
        module, "export_details[%i].ordinal", i);
2517
2518
0
    if (exported_ordinal == ordinal)
2519
0
      return_integer(1);
2520
0
  }
2521
2522
0
  return_integer(0);
2523
0
}
2524
2525
define_function(exports_index_name)
2526
0
{
2527
0
  SIZED_STRING* search_name = sized_string_argument(1);
2528
2529
0
  SIZED_STRING* function_name = NULL;
2530
0
  YR_OBJECT* module = yr_module();
2531
0
  PE* pe = (PE*) module->data;
2532
2533
  // If not a PE, return YR_UNDEFINED.
2534
0
  if (pe == NULL)
2535
0
    return_integer(YR_UNDEFINED);
2536
2537
  // If PE, but no exported functions, return false.
2538
0
  int n = (int) yr_get_integer(module, "number_of_exports");
2539
2540
0
  if (n == 0)
2541
0
    return_integer(YR_UNDEFINED);
2542
2543
0
  for (int i = 0; i < n; i++)
2544
0
  {
2545
0
    function_name = yr_get_string(module, "export_details[%i].name", i);
2546
2547
0
    if (function_name == NULL)
2548
0
      continue;
2549
2550
0
    if (ss_icompare(function_name, search_name) == 0)
2551
0
      return_integer(i);
2552
0
  }
2553
2554
0
  return_integer(YR_UNDEFINED);
2555
0
}
2556
2557
define_function(exports_index_ordinal)
2558
0
{
2559
0
  int64_t ordinal = integer_argument(1);
2560
2561
0
  YR_OBJECT* module = yr_module();
2562
0
  PE* pe = (PE*) module->data;
2563
2564
  // If not a PE, return YR_UNDEFINED.
2565
0
  if (pe == NULL)
2566
0
    return_integer(YR_UNDEFINED);
2567
2568
  // If PE, but no exported functions, return false.
2569
0
  int n = (int) yr_get_integer(module, "number_of_exports");
2570
2571
0
  if (n == 0)
2572
0
    return_integer(YR_UNDEFINED);
2573
2574
0
  if (ordinal == 0 || ordinal > n)
2575
0
    return_integer(YR_UNDEFINED);
2576
2577
0
  for (int i = 0; i < n; i++)
2578
0
  {
2579
0
    int64_t exported_ordinal = yr_object_get_integer(
2580
0
        module, "export_details[%i].ordinal", i);
2581
2582
0
    if (exported_ordinal == ordinal)
2583
0
      return_integer(i);
2584
0
  }
2585
2586
0
  return_integer(YR_UNDEFINED);
2587
0
}
2588
2589
define_function(exports_index_regex)
2590
0
{
2591
0
  RE* regex = regexp_argument(1);
2592
2593
0
  SIZED_STRING* function_name = NULL;
2594
0
  YR_OBJECT* module = yr_module();
2595
0
  PE* pe = (PE*) module->data;
2596
2597
  // If not a PE, return YR_UNDEFINED.
2598
0
  if (pe == NULL)
2599
0
    return_integer(YR_UNDEFINED);
2600
2601
  // If PE, but no exported functions, return false.
2602
0
  int n = (int) yr_get_integer(module, "number_of_exports");
2603
2604
0
  if (n == 0)
2605
0
    return_integer(YR_UNDEFINED);
2606
2607
0
  for (int i = 0; i < n; i++)
2608
0
  {
2609
0
    function_name = yr_get_string(module, "export_details[%i].name", i);
2610
0
    if (function_name == NULL)
2611
0
      continue;
2612
2613
0
    if (yr_re_match(yr_scan_context(), regex, function_name->c_string) != -1)
2614
0
    {
2615
0
      return_integer(i);
2616
0
    }
2617
0
  }
2618
2619
0
  return_integer(YR_UNDEFINED);
2620
0
}
2621
2622
#if defined(HAVE_LIBCRYPTO) || defined(HAVE_WINCRYPT_H) || \
2623
    defined(HAVE_COMMONCRYPTO_COMMONCRYPTO_H)
2624
2625
//
2626
// Generate an import hash:
2627
// https://www.mandiant.com/blog/tracking-malware-import-hashing/
2628
// It is important to make duplicates of the strings as we don't want
2629
// to alter the contents of the parsed import structures.
2630
//
2631
2632
define_function(imphash)
2633
{
2634
  YR_OBJECT* module = yr_module();
2635
2636
  IMPORTED_DLL* dll;
2637
  yr_md5_ctx ctx;
2638
2639
  unsigned char digest[YR_MD5_LEN];
2640
  char* digest_ascii;
2641
2642
  size_t i;
2643
  bool first = true;
2644
2645
  PE* pe = (PE*) module->data;
2646
2647
  // If not a PE, return YR_UNDEFINED.
2648
2649
  if (!pe)
2650
    return_string(YR_UNDEFINED);
2651
2652
  // Lookup in cache first.
2653
  digest_ascii = (char*) yr_hash_table_lookup(pe->hash_table, "imphash", NULL);
2654
2655
  if (digest_ascii != NULL)
2656
    return_string(digest_ascii);
2657
2658
  yr_md5_init(&ctx);
2659
2660
  dll = pe->imported_dlls;
2661
2662
  while (dll)
2663
  {
2664
    IMPORT_FUNCTION* func;
2665
2666
    size_t dll_name_len;
2667
    char* dll_name;
2668
2669
    // If extension is 'ocx', 'sys' or 'dll', chop it.
2670
2671
    char* ext = strstr(dll->name, ".");
2672
2673
    if (ext &&
2674
        (strncasecmp(ext, ".ocx", 4) == 0 || strncasecmp(ext, ".sys", 4) == 0 ||
2675
         strncasecmp(ext, ".dll", 4) == 0))
2676
    {
2677
      dll_name_len = (ext - dll->name);
2678
    }
2679
    else
2680
    {
2681
      dll_name_len = strlen(dll->name);
2682
    }
2683
2684
    // Allocate a new string to hold the dll name.
2685
2686
    dll_name = (char*) yr_malloc(dll_name_len + 1);
2687
2688
    if (!dll_name)
2689
      return ERROR_INSUFFICIENT_MEMORY;
2690
2691
    strlcpy(dll_name, dll->name, dll_name_len + 1);
2692
2693
    func = dll->functions;
2694
2695
    while (func)
2696
    {
2697
      char* final_name;
2698
      size_t final_name_len = dll_name_len + strlen(func->name) + 1;
2699
2700
      if (!first)
2701
        final_name_len++;  // Additional byte to accommodate the extra comma
2702
2703
      final_name = (char*) yr_malloc(final_name_len + 1);
2704
2705
      if (final_name == NULL)
2706
        break;
2707
2708
      sprintf(final_name, first ? "%s.%s" : ",%s.%s", dll_name, func->name);
2709
2710
      // Lowercase the whole thing.
2711
2712
      for (i = 0; i < final_name_len; i++)
2713
        final_name[i] = tolower(final_name[i]);
2714
2715
      yr_md5_update(&ctx, final_name, final_name_len);
2716
2717
      yr_free(final_name);
2718
2719
      func = func->next;
2720
      first = false;
2721
    }
2722
2723
    yr_free(dll_name);
2724
2725
    dll = dll->next;
2726
  }
2727
2728
  yr_md5_final(digest, &ctx);
2729
2730
  digest_ascii = (char*) yr_malloc(YR_MD5_LEN * 2 + 1);
2731
2732
  if (digest_ascii == NULL)
2733
    return ERROR_INSUFFICIENT_MEMORY;
2734
2735
  // Transform the binary digest to ascii
2736
2737
  for (i = 0; i < YR_MD5_LEN; i++)
2738
  {
2739
    sprintf(digest_ascii + (i * 2), "%02x", digest[i]);
2740
  }
2741
2742
  digest_ascii[YR_MD5_LEN * 2] = '\0';
2743
2744
  yr_hash_table_add(pe->hash_table, "imphash", NULL, digest_ascii);
2745
2746
  return_string(digest_ascii);
2747
}
2748
2749
#endif  // defined(HAVE_LIBCRYPTO) || defined(HAVE_WINCRYPT_H)
2750
2751
int64_t pe_imports_dll(IMPORTED_DLL* dll, char* dll_name)
2752
0
{
2753
0
  if (dll == NULL)
2754
0
    return 0;
2755
2756
0
  int64_t result = 0;
2757
2758
0
  for (; dll != NULL; dll = dll->next)
2759
0
  {
2760
0
    if (strcasecmp(dll->name, dll_name) == 0)
2761
0
    {
2762
0
      IMPORT_FUNCTION* fun = dll->functions;
2763
0
      for (; fun != NULL; fun = fun->next)
2764
0
      {
2765
0
        result++;
2766
0
      }
2767
0
    }
2768
0
  }
2769
2770
0
  return result;
2771
0
}
2772
2773
int64_t pe_imports(IMPORTED_DLL* dll, char* dll_name, char* fun_name)
2774
0
{
2775
0
  if (dll == NULL)
2776
0
    return 0;
2777
2778
0
  for (; dll != NULL; dll = dll->next)
2779
0
  {
2780
0
    if (strcasecmp(dll->name, dll_name) == 0)
2781
0
    {
2782
0
      IMPORT_FUNCTION* fun = dll->functions;
2783
0
      for (; fun != NULL; fun = fun->next)
2784
0
      {
2785
0
        if (strcasecmp(fun->name, fun_name) == 0)
2786
0
          return 1;
2787
0
      }
2788
0
    }
2789
0
  }
2790
2791
0
  return 0;
2792
0
}
2793
2794
int64_t pe_imports_regexp(
2795
    YR_SCAN_CONTEXT* context,
2796
    IMPORTED_DLL* dll,
2797
    RE* dll_name,
2798
    RE* fun_name)
2799
0
{
2800
0
  if (dll == NULL)
2801
0
    return 0;
2802
2803
0
  int64_t result = 0;
2804
2805
0
  for (; dll != NULL; dll = dll->next)
2806
0
  {
2807
0
    if (yr_re_match(context, dll_name, dll->name) > 0)
2808
0
    {
2809
0
      IMPORT_FUNCTION* fun = dll->functions;
2810
0
      for (; fun != NULL; fun = fun->next)
2811
0
      {
2812
0
        if (yr_re_match(context, fun_name, fun->name) > 0)
2813
0
          result++;
2814
0
      }
2815
0
    }
2816
0
  }
2817
2818
0
  return result;
2819
0
}
2820
2821
int64_t pe_imports_ordinal(IMPORTED_DLL* dll, char* dll_name, uint64_t ordinal)
2822
0
{
2823
0
  if (dll == NULL)
2824
0
    return 0;
2825
2826
0
  for (; dll != NULL; dll = dll->next)
2827
0
  {
2828
0
    if (strcasecmp(dll->name, dll_name) == 0)
2829
0
    {
2830
0
      IMPORT_FUNCTION* fun = dll->functions;
2831
0
      for (; fun != NULL; fun = fun->next)
2832
0
      {
2833
0
        if (fun->has_ordinal && fun->ordinal == ordinal)
2834
0
          return 1;
2835
0
      }
2836
0
    }
2837
0
  }
2838
2839
0
  return 0;
2840
0
}
2841
2842
define_function(imports_standard)
2843
0
{
2844
0
  char* dll_name = string_argument(1);
2845
0
  char* function_name = string_argument(2);
2846
2847
0
  YR_OBJECT* module = yr_module();
2848
0
  PE* pe = (PE*) module->data;
2849
2850
0
  if (!pe)
2851
0
    return_integer(YR_UNDEFINED);
2852
2853
0
  return_integer(pe_imports(pe->imported_dlls, dll_name, function_name));
2854
0
}
2855
2856
define_function(imports)
2857
0
{
2858
0
  int64_t flags = integer_argument(1);
2859
0
  char* dll_name = string_argument(2);
2860
0
  char* function_name = string_argument(3);
2861
2862
0
  YR_OBJECT* module = yr_module();
2863
0
  PE* pe = (PE*) module->data;
2864
2865
0
  if (!pe)
2866
0
    return_integer(YR_UNDEFINED);
2867
2868
0
  if (flags & IMPORT_STANDARD &&
2869
0
      pe_imports(pe->imported_dlls, dll_name, function_name))
2870
0
  {
2871
0
    return_integer(1);
2872
0
  }
2873
2874
0
  if (flags & IMPORT_DELAYED &&
2875
0
      pe_imports(pe->delay_imported_dlls, dll_name, function_name))
2876
0
  {
2877
0
    return_integer(1);
2878
0
  }
2879
2880
0
  return_integer(0);
2881
0
}
2882
2883
define_function(imports_standard_ordinal)
2884
0
{
2885
0
  char* dll_name = string_argument(1);
2886
0
  int64_t ordinal = integer_argument(2);
2887
2888
0
  YR_OBJECT* module = yr_module();
2889
0
  PE* pe = (PE*) module->data;
2890
2891
0
  if (!pe)
2892
0
    return_integer(YR_UNDEFINED);
2893
2894
0
  return_integer(pe_imports_ordinal(pe->imported_dlls, dll_name, ordinal))
2895
0
}
2896
2897
define_function(imports_ordinal)
2898
0
{
2899
0
  int64_t flags = integer_argument(1);
2900
0
  char* dll_name = string_argument(2);
2901
0
  int64_t ordinal = integer_argument(3);
2902
2903
0
  YR_OBJECT* module = yr_module();
2904
0
  PE* pe = (PE*) module->data;
2905
2906
0
  if (!pe)
2907
0
    return_integer(YR_UNDEFINED);
2908
2909
0
  if (flags & IMPORT_STANDARD &&
2910
0
      pe_imports_ordinal(pe->imported_dlls, dll_name, ordinal))
2911
0
  {
2912
0
    return_integer(1);
2913
0
  }
2914
2915
0
  if (flags & IMPORT_DELAYED &&
2916
0
      pe_imports_ordinal(pe->delay_imported_dlls, dll_name, ordinal))
2917
0
  {
2918
0
    return_integer(1);
2919
0
  }
2920
2921
0
  return_integer(0);
2922
0
}
2923
2924
define_function(imports_standard_regex)
2925
0
{
2926
0
  RE* dll_name = regexp_argument(1);
2927
0
  RE* function_name = regexp_argument(2);
2928
2929
0
  YR_OBJECT* module = yr_module();
2930
0
  PE* pe = (PE*) module->data;
2931
2932
0
  if (!pe)
2933
0
    return_integer(YR_UNDEFINED);
2934
2935
0
  return_integer(pe_imports_regexp(
2936
0
      yr_scan_context(), pe->imported_dlls, dll_name, function_name))
2937
0
}
2938
2939
define_function(imports_regex)
2940
0
{
2941
0
  int64_t flags = integer_argument(1);
2942
0
  RE* dll_name = regexp_argument(2);
2943
0
  RE* function_name = regexp_argument(3);
2944
2945
0
  YR_OBJECT* module = yr_module();
2946
0
  PE* pe = (PE*) module->data;
2947
2948
0
  if (!pe)
2949
0
    return_integer(YR_UNDEFINED);
2950
2951
0
  int64_t result = 0;
2952
2953
0
  if (flags & IMPORT_STANDARD)
2954
0
    result += pe_imports_regexp(
2955
0
        yr_scan_context(), pe->imported_dlls, dll_name, function_name);
2956
2957
0
  if (flags & IMPORT_DELAYED)
2958
0
    result += pe_imports_regexp(
2959
0
        yr_scan_context(), pe->delay_imported_dlls, dll_name, function_name);
2960
2961
0
  return_integer(result);
2962
0
}
2963
2964
define_function(imports_standard_dll)
2965
0
{
2966
0
  char* dll_name = string_argument(1);
2967
2968
0
  YR_OBJECT* module = yr_module();
2969
0
  PE* pe = (PE*) module->data;
2970
2971
0
  if (!pe)
2972
0
    return_integer(YR_UNDEFINED);
2973
2974
0
  return_integer(pe_imports_dll(pe->imported_dlls, dll_name));
2975
0
}
2976
2977
define_function(imports_dll)
2978
0
{
2979
0
  int64_t flags = integer_argument(1);
2980
0
  char* dll_name = string_argument(2);
2981
2982
0
  YR_OBJECT* module = yr_module();
2983
0
  PE* pe = (PE*) module->data;
2984
2985
0
  if (!pe)
2986
0
    return_integer(YR_UNDEFINED);
2987
2988
0
  int64_t result = 0;
2989
2990
0
  if (flags & IMPORT_STANDARD)
2991
0
    result += pe_imports_dll(pe->imported_dlls, dll_name);
2992
2993
0
  if (flags & IMPORT_DELAYED)
2994
0
    result += pe_imports_dll(pe->delay_imported_dlls, dll_name);
2995
2996
0
  return_integer(result);
2997
0
}
2998
2999
define_function(import_rva)
3000
0
{
3001
0
  SIZED_STRING* in_dll_name = sized_string_argument(1);
3002
0
  SIZED_STRING* in_function_name = sized_string_argument(2);
3003
3004
0
  SIZED_STRING* dll_name;
3005
0
  SIZED_STRING* function_name;
3006
0
  YR_OBJECT* module = yr_module();
3007
0
  PE* pe = (PE*) module->data;
3008
3009
0
  if (!pe)
3010
0
    return_integer(YR_UNDEFINED);
3011
3012
0
  int64_t num_imports = yr_get_integer(pe->object, "number_of_imports");
3013
0
  if (IS_UNDEFINED(num_imports))
3014
0
    return_integer(YR_UNDEFINED);
3015
3016
0
  for (int i = 0; i < num_imports; i++)
3017
0
  {
3018
0
    dll_name = yr_get_string(module, "import_details[%i].library_name", i);
3019
0
    if (dll_name == NULL || IS_UNDEFINED(dll_name) ||
3020
0
        ss_compare(in_dll_name, dll_name) != 0)
3021
0
      continue;
3022
3023
0
    int64_t num_functions = yr_get_integer(
3024
0
        module, "import_details[%i].number_of_functions", i);
3025
0
    if (IS_UNDEFINED(num_functions))
3026
0
      return_integer(YR_UNDEFINED);
3027
3028
0
    for (int j = 0; j < num_functions; j++)
3029
0
    {
3030
0
      function_name = yr_get_string(
3031
0
          module, "import_details[%i].functions[%i].name", i, j);
3032
0
      if (function_name == NULL || IS_UNDEFINED(function_name))
3033
0
        continue;
3034
3035
0
      if (ss_compare(in_function_name, function_name) == 0)
3036
0
        return_integer(yr_get_integer(
3037
0
            module, "import_details[%i].functions[%i].rva", i, j));
3038
0
    }
3039
0
  }
3040
3041
0
  return_integer(YR_UNDEFINED);
3042
0
}
3043
3044
define_function(import_rva_ordinal)
3045
0
{
3046
0
  SIZED_STRING* in_dll_name = sized_string_argument(1);
3047
0
  int64_t in_ordinal = integer_argument(2);
3048
3049
0
  SIZED_STRING* dll_name;
3050
0
  int64_t ordinal;
3051
0
  YR_OBJECT* module = yr_module();
3052
0
  PE* pe = (PE*) module->data;
3053
3054
0
  if (!pe)
3055
0
    return_integer(YR_UNDEFINED);
3056
3057
0
  int64_t num_imports = yr_get_integer(pe->object, "number_of_imports");
3058
0
  if (IS_UNDEFINED(num_imports))
3059
0
    return_integer(YR_UNDEFINED);
3060
3061
0
  for (int i = 0; i < num_imports; i++)
3062
0
  {
3063
0
    dll_name = yr_get_string(module, "import_details[%i].library_name", i);
3064
0
    if (dll_name == NULL || IS_UNDEFINED(dll_name) ||
3065
0
        ss_compare(in_dll_name, dll_name) != 0)
3066
0
      continue;
3067
3068
0
    int64_t num_functions = yr_get_integer(
3069
0
        module, "import_details[%i].number_of_functions", i);
3070
0
    if (IS_UNDEFINED(num_functions))
3071
0
      return_integer(YR_UNDEFINED);
3072
3073
0
    for (int j = 0; j < num_functions; j++)
3074
0
    {
3075
0
      ordinal = yr_get_integer(
3076
0
          module, "import_details[%i].functions[%i].ordinal", i, j);
3077
0
      if (IS_UNDEFINED(ordinal))
3078
0
        continue;
3079
3080
0
      if (ordinal == in_ordinal)
3081
0
        return_integer(yr_get_integer(
3082
0
            module, "import_details[%i].functions[%i].rva", i, j));
3083
0
    }
3084
0
  }
3085
3086
0
  return_integer(YR_UNDEFINED);
3087
0
}
3088
3089
define_function(delayed_import_rva)
3090
0
{
3091
0
  SIZED_STRING* in_dll_name = sized_string_argument(1);
3092
0
  SIZED_STRING* in_function_name = sized_string_argument(2);
3093
3094
0
  SIZED_STRING* dll_name;
3095
0
  SIZED_STRING* function_name;
3096
0
  YR_OBJECT* module = yr_module();
3097
0
  PE* pe = (PE*) module->data;
3098
3099
0
  if (!pe)
3100
0
    return_integer(YR_UNDEFINED);
3101
3102
0
  int64_t num_imports = yr_get_integer(pe->object, "number_of_delayed_imports");
3103
3104
0
  if (IS_UNDEFINED(num_imports))
3105
0
    return_integer(YR_UNDEFINED);
3106
3107
0
  for (int i = 0; i < num_imports; i++)
3108
0
  {
3109
0
    dll_name = yr_get_string(
3110
0
        module, "delayed_import_details[%i].library_name", i);
3111
3112
0
    if (dll_name == NULL || IS_UNDEFINED(dll_name) ||
3113
0
        ss_compare(in_dll_name, dll_name) != 0)
3114
0
      continue;
3115
3116
0
    int64_t num_functions = yr_get_integer(
3117
0
        module, "delayed_import_details[%i].number_of_functions", i);
3118
3119
0
    if (IS_UNDEFINED(num_functions))
3120
0
      return_integer(YR_UNDEFINED);
3121
3122
0
    for (int j = 0; j < num_functions; j++)
3123
0
    {
3124
0
      function_name = yr_get_string(
3125
0
          module, "delayed_import_details[%i].functions[%i].name", i, j);
3126
3127
0
      if (function_name == NULL || IS_UNDEFINED(function_name))
3128
0
        continue;
3129
3130
0
      if (ss_compare(in_function_name, function_name) == 0)
3131
0
        return_integer(yr_get_integer(
3132
0
            module, "delayed_import_details[%i].functions[%i].rva", i, j));
3133
0
    }
3134
0
  }
3135
3136
0
  return_integer(YR_UNDEFINED);
3137
0
}
3138
3139
define_function(delayed_import_rva_ordinal)
3140
0
{
3141
0
  SIZED_STRING* in_dll_name = sized_string_argument(1);
3142
0
  int64_t in_ordinal = integer_argument(2);
3143
3144
0
  SIZED_STRING* dll_name;
3145
0
  int64_t ordinal;
3146
0
  YR_OBJECT* module = yr_module();
3147
0
  PE* pe = (PE*) module->data;
3148
3149
0
  if (!pe)
3150
0
    return_integer(YR_UNDEFINED);
3151
3152
0
  int64_t num_imports = yr_get_integer(pe->object, "number_of_delayed_imports");
3153
0
  if (IS_UNDEFINED(num_imports))
3154
0
    return_integer(YR_UNDEFINED);
3155
3156
0
  for (int i = 0; i < num_imports; i++)
3157
0
  {
3158
0
    dll_name = yr_get_string(
3159
0
        module, "delayed_import_details[%i].library_name", i);
3160
3161
0
    if (dll_name == NULL || IS_UNDEFINED(dll_name) ||
3162
0
        ss_compare(in_dll_name, dll_name) != 0)
3163
0
      continue;
3164
3165
0
    int64_t num_functions = yr_get_integer(
3166
0
        module, "delayed_import_details[%i].number_of_functions", i);
3167
3168
0
    if (IS_UNDEFINED(num_functions))
3169
0
      return_integer(YR_UNDEFINED);
3170
3171
0
    for (int j = 0; j < num_functions; j++)
3172
0
    {
3173
0
      ordinal = yr_get_integer(
3174
0
          module, "delayed_import_details[%i].functions[%i].ordinal", i, j);
3175
3176
0
      if (IS_UNDEFINED(ordinal))
3177
0
        continue;
3178
3179
0
      if (ordinal == in_ordinal)
3180
0
        return_integer(yr_get_integer(
3181
0
            module, "delayed_import_details[%i].functions[%i].rva", i, j));
3182
0
    }
3183
0
  }
3184
3185
0
  return_integer(YR_UNDEFINED);
3186
0
}
3187
3188
define_function(locale)
3189
0
{
3190
0
  YR_OBJECT* module = yr_module();
3191
0
  PE* pe = (PE*) module->data;
3192
3193
0
  uint64_t locale = integer_argument(1);
3194
3195
0
  if (yr_is_undefined(module, "number_of_resources"))
3196
0
    return_integer(YR_UNDEFINED);
3197
3198
  // If not a PE file, return YR_UNDEFINED
3199
3200
0
  if (pe == NULL)
3201
0
    return_integer(YR_UNDEFINED);
3202
3203
0
  int n = (int) yr_get_integer(module, "number_of_resources");
3204
3205
0
  for (int i = 0; i < n; i++)
3206
0
  {
3207
0
    uint64_t rsrc_language = yr_get_integer(
3208
0
        module, "resources[%i].language", i);
3209
3210
0
    if ((rsrc_language & 0xFFFF) == locale)
3211
0
      return_integer(1);
3212
0
  }
3213
3214
0
  return_integer(0);
3215
0
}
3216
3217
define_function(language)
3218
0
{
3219
0
  YR_OBJECT* module = yr_module();
3220
0
  PE* pe = (PE*) module->data;
3221
3222
0
  uint64_t language = integer_argument(1);
3223
3224
0
  if (yr_is_undefined(module, "number_of_resources"))
3225
0
    return_integer(YR_UNDEFINED);
3226
3227
  // If not a PE file, return YR_UNDEFINED
3228
3229
0
  if (pe == NULL)
3230
0
    return_integer(YR_UNDEFINED);
3231
3232
0
  int n = (int) yr_get_integer(module, "number_of_resources");
3233
3234
0
  for (int i = 0; i < n; i++)
3235
0
  {
3236
0
    uint64_t rsrc_language = yr_get_integer(
3237
0
        module, "resources[%i].language", i);
3238
3239
0
    if ((rsrc_language & 0xFF) == language)
3240
0
      return_integer(1);
3241
0
  }
3242
3243
0
  return_integer(0);
3244
0
}
3245
3246
define_function(is_dll)
3247
0
{
3248
0
  int64_t characteristics;
3249
0
  YR_OBJECT* module = yr_module();
3250
3251
0
  if (yr_is_undefined(module, "characteristics"))
3252
0
    return_integer(YR_UNDEFINED);
3253
3254
0
  characteristics = yr_get_integer(module, "characteristics");
3255
0
  return_integer(characteristics & IMAGE_FILE_DLL);
3256
0
}
3257
3258
define_function(is_32bit)
3259
0
{
3260
0
  YR_OBJECT* module = yr_module();
3261
0
  PE* pe = (PE*) module->data;
3262
3263
0
  if (pe == NULL)
3264
0
    return_integer(YR_UNDEFINED);
3265
3266
0
  return_integer(IS_64BITS_PE(pe) ? 0 : 1);
3267
0
}
3268
3269
define_function(is_64bit)
3270
0
{
3271
0
  YR_OBJECT* module = yr_module();
3272
0
  PE* pe = (PE*) module->data;
3273
3274
0
  if (pe == NULL)
3275
0
    return_integer(YR_UNDEFINED);
3276
3277
0
  return_integer(IS_64BITS_PE(pe) ? 1 : 0);
3278
0
}
3279
3280
// _rich_version
3281
//
3282
// Returns the number of rich signatures that match the specified version and
3283
// toolid numbers.
3284
//
3285
static uint64_t _rich_version(
3286
    YR_OBJECT* module,
3287
    uint64_t version,
3288
    uint64_t toolid)
3289
0
{
3290
0
  int64_t rich_length;
3291
0
  int64_t rich_count;
3292
3293
0
  PRICH_SIGNATURE clear_rich_signature;
3294
0
  SIZED_STRING* rich_string;
3295
3296
0
  uint64_t result = 0;
3297
3298
  // Check if the required fields are set
3299
0
  if (yr_is_undefined(module, "rich_signature.length"))
3300
0
    return YR_UNDEFINED;
3301
3302
0
  rich_length = yr_get_integer(module, "rich_signature.length");
3303
0
  rich_string = yr_get_string(module, "rich_signature.clear_data");
3304
3305
  // If the clear_data was not set, return YR_UNDEFINED
3306
0
  if (rich_string == NULL)
3307
0
    return YR_UNDEFINED;
3308
3309
0
  if (version == YR_UNDEFINED && toolid == YR_UNDEFINED)
3310
0
    return false;
3311
3312
0
  clear_rich_signature = (PRICH_SIGNATURE) rich_string->c_string;
3313
3314
  // Loop over the versions in the rich signature
3315
3316
0
  rich_count = (rich_length - sizeof(RICH_SIGNATURE)) /
3317
0
               sizeof(RICH_VERSION_INFO);
3318
3319
0
  for (int i = 0; i < rich_count; i++)
3320
0
  {
3321
0
    DWORD id_version = yr_le32toh(clear_rich_signature->versions[i].id_version);
3322
3323
0
    int match_version = (version == RICH_VERSION_VERSION(id_version));
3324
0
    int match_toolid = (toolid == RICH_VERSION_ID(id_version));
3325
3326
0
    if ((version == YR_UNDEFINED || match_version) &&
3327
0
        (toolid == YR_UNDEFINED || match_toolid))
3328
0
    {
3329
0
      result += yr_le32toh(clear_rich_signature->versions[i].times);
3330
0
    }
3331
0
  }
3332
3333
0
  return result;
3334
0
}
3335
3336
define_function(rich_version)
3337
0
{
3338
0
  return_integer(_rich_version(yr_module(), integer_argument(1), YR_UNDEFINED));
3339
0
}
3340
3341
define_function(rich_version_toolid)
3342
0
{
3343
0
  return_integer(
3344
0
      _rich_version(yr_module(), integer_argument(1), integer_argument(2)));
3345
0
}
3346
3347
define_function(rich_toolid)
3348
0
{
3349
0
  return_integer(_rich_version(yr_module(), YR_UNDEFINED, integer_argument(1)));
3350
0
}
3351
3352
define_function(rich_toolid_version)
3353
0
{
3354
0
  return_integer(
3355
0
      _rich_version(yr_module(), integer_argument(2), integer_argument(1)));
3356
0
}
3357
3358
define_function(calculate_checksum)
3359
0
{
3360
0
  YR_OBJECT* module = yr_module();
3361
0
  PE* pe = (PE*) module->data;
3362
3363
0
  uint64_t csum = 0;
3364
0
  size_t csum_offset;
3365
3366
0
  if (pe == NULL)
3367
0
    return_integer(YR_UNDEFINED);
3368
3369
0
  csum_offset = ((uint8_t*) &(pe->header->OptionalHeader) +
3370
0
                 offsetof(IMAGE_OPTIONAL_HEADER32, CheckSum)) -
3371
0
                pe->data;
3372
3373
0
  for (size_t i = 0; i <= pe->data_size / 4; i++)
3374
0
  {
3375
    // Treat the CheckSum field as 0 -- the offset is the same for
3376
    // PE32 and PE64.
3377
3378
0
    if (4 * i == csum_offset)
3379
0
      continue;
3380
3381
0
    if (4 * i + 4 <= pe->data_size)
3382
0
    {
3383
0
      csum +=
3384
0
          ((uint64_t) pe->data[4 * i] + ((uint64_t) pe->data[4 * i + 1] << 8) +
3385
0
           ((uint64_t) pe->data[4 * i + 2] << 16) +
3386
0
           ((uint64_t) pe->data[4 * i + 3] << 24));
3387
0
    }
3388
0
    else
3389
0
    {
3390
0
      for (size_t j = 0; j < pe->data_size % 4; j++)
3391
0
        csum += (uint64_t) pe->data[4 * i + j] << (8 * j);
3392
0
    }
3393
3394
0
    if (csum > 0xffffffff)
3395
0
      csum = (csum & 0xffffffff) + (csum >> 32);
3396
0
  }
3397
3398
0
  csum = (csum & 0xffff) + (csum >> 16);
3399
0
  csum += (csum >> 16);
3400
0
  csum &= 0xffff;
3401
0
  csum += pe->data_size;
3402
3403
0
  return_integer(csum);
3404
0
}
3405
3406
define_function(rva_to_offset)
3407
0
{
3408
0
  YR_OBJECT* module = yr_module();
3409
0
  PE* pe = (PE*) module->data;
3410
3411
0
  uint64_t rva;
3412
0
  int64_t offset;
3413
3414
0
  if (pe == NULL)
3415
0
    return_integer(YR_UNDEFINED);
3416
3417
0
  rva = integer_argument(1);
3418
0
  offset = pe_rva_to_offset(pe, rva);
3419
3420
0
  if (offset == -1)
3421
0
    return_integer(YR_UNDEFINED);
3422
3423
0
  return_integer(offset);
3424
0
}
3425
3426
0
begin_declarations
3427
0
  declare_integer("MACHINE_UNKNOWN");
3428
0
  declare_integer("MACHINE_AM33");
3429
0
  declare_integer("MACHINE_AMD64");
3430
0
  declare_integer("MACHINE_ARM");
3431
0
  declare_integer("MACHINE_ARMNT");
3432
0
  declare_integer("MACHINE_ARM64");
3433
0
  declare_integer("MACHINE_EBC");
3434
0
  declare_integer("MACHINE_I386");
3435
0
  declare_integer("MACHINE_IA64");
3436
0
  declare_integer("MACHINE_M32R");
3437
0
  declare_integer("MACHINE_MIPS16");
3438
0
  declare_integer("MACHINE_MIPSFPU");
3439
0
  declare_integer("MACHINE_MIPSFPU16");
3440
0
  declare_integer("MACHINE_POWERPC");
3441
0
  declare_integer("MACHINE_POWERPCFP");
3442
0
  declare_integer("MACHINE_R4000");
3443
0
  declare_integer("MACHINE_SH3");
3444
0
  declare_integer("MACHINE_SH3DSP");
3445
0
  declare_integer("MACHINE_SH4");
3446
0
  declare_integer("MACHINE_SH5");
3447
0
  declare_integer("MACHINE_THUMB");
3448
0
  declare_integer("MACHINE_WCEMIPSV2");
3449
0
  declare_integer("MACHINE_TARGET_HOST");
3450
0
  declare_integer("MACHINE_R3000");
3451
0
  declare_integer("MACHINE_R10000");
3452
0
  declare_integer("MACHINE_ALPHA");
3453
0
  declare_integer("MACHINE_SH3E");
3454
0
  declare_integer("MACHINE_ALPHA64");
3455
0
  declare_integer("MACHINE_AXP64");
3456
0
  declare_integer("MACHINE_TRICORE");
3457
0
  declare_integer("MACHINE_CEF");
3458
0
  declare_integer("MACHINE_CEE");
3459
3460
0
  declare_integer("SUBSYSTEM_UNKNOWN");
3461
0
  declare_integer("SUBSYSTEM_NATIVE");
3462
0
  declare_integer("SUBSYSTEM_WINDOWS_GUI");
3463
0
  declare_integer("SUBSYSTEM_WINDOWS_CUI");
3464
0
  declare_integer("SUBSYSTEM_OS2_CUI");
3465
0
  declare_integer("SUBSYSTEM_POSIX_CUI");
3466
0
  declare_integer("SUBSYSTEM_NATIVE_WINDOWS");
3467
0
  declare_integer("SUBSYSTEM_WINDOWS_CE_GUI");
3468
0
  declare_integer("SUBSYSTEM_EFI_APPLICATION");
3469
0
  declare_integer("SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER");
3470
0
  declare_integer("SUBSYSTEM_EFI_RUNTIME_DRIVER");
3471
0
  declare_integer("SUBSYSTEM_EFI_ROM_IMAGE");
3472
0
  declare_integer("SUBSYSTEM_XBOX");
3473
0
  declare_integer("SUBSYSTEM_WINDOWS_BOOT_APPLICATION");
3474
3475
0
  declare_integer("HIGH_ENTROPY_VA");
3476
0
  declare_integer("DYNAMIC_BASE");
3477
0
  declare_integer("FORCE_INTEGRITY");
3478
0
  declare_integer("NX_COMPAT");
3479
0
  declare_integer("NO_ISOLATION");
3480
0
  declare_integer("NO_SEH");
3481
0
  declare_integer("NO_BIND");
3482
0
  declare_integer("APPCONTAINER");
3483
0
  declare_integer("WDM_DRIVER");
3484
0
  declare_integer("GUARD_CF");
3485
0
  declare_integer("TERMINAL_SERVER_AWARE");
3486
3487
0
  declare_integer("RELOCS_STRIPPED");
3488
0
  declare_integer("EXECUTABLE_IMAGE");
3489
0
  declare_integer("LINE_NUMS_STRIPPED");
3490
0
  declare_integer("LOCAL_SYMS_STRIPPED");
3491
0
  declare_integer("AGGRESIVE_WS_TRIM");
3492
0
  declare_integer("LARGE_ADDRESS_AWARE");
3493
0
  declare_integer("BYTES_REVERSED_LO");
3494
0
  declare_integer("MACHINE_32BIT");
3495
0
  declare_integer("DEBUG_STRIPPED");
3496
0
  declare_integer("REMOVABLE_RUN_FROM_SWAP");
3497
0
  declare_integer("NET_RUN_FROM_SWAP");
3498
0
  declare_integer("SYSTEM");
3499
0
  declare_integer("DLL");
3500
0
  declare_integer("UP_SYSTEM_ONLY");
3501
0
  declare_integer("BYTES_REVERSED_HI");
3502
3503
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_EXPORT");
3504
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_IMPORT");
3505
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_RESOURCE");
3506
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_EXCEPTION");
3507
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_SECURITY");
3508
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_BASERELOC");
3509
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_DEBUG");
3510
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_ARCHITECTURE");
3511
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_COPYRIGHT");
3512
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_GLOBALPTR");
3513
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_TLS");
3514
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG");
3515
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT");
3516
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_IAT");
3517
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT");
3518
0
  declare_integer("IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR");
3519
3520
0
  declare_integer("IMAGE_NT_OPTIONAL_HDR32_MAGIC");
3521
0
  declare_integer("IMAGE_NT_OPTIONAL_HDR64_MAGIC");
3522
0
  declare_integer("IMAGE_ROM_OPTIONAL_HDR_MAGIC");
3523
3524
0
  declare_integer("SECTION_NO_PAD");
3525
0
  declare_integer("SECTION_CNT_CODE");
3526
0
  declare_integer("SECTION_CNT_INITIALIZED_DATA");
3527
0
  declare_integer("SECTION_CNT_UNINITIALIZED_DATA");
3528
0
  declare_integer("SECTION_LNK_OTHER");
3529
0
  declare_integer("SECTION_LNK_INFO");
3530
0
  declare_integer("SECTION_LNK_REMOVE");
3531
0
  declare_integer("SECTION_LNK_COMDAT");
3532
0
  declare_integer("SECTION_NO_DEFER_SPEC_EXC");
3533
0
  declare_integer("SECTION_GPREL");
3534
0
  declare_integer("SECTION_MEM_FARDATA");
3535
0
  declare_integer("SECTION_MEM_PURGEABLE");
3536
0
  declare_integer("SECTION_MEM_16BIT");
3537
0
  declare_integer("SECTION_MEM_LOCKED");
3538
0
  declare_integer("SECTION_MEM_PRELOAD");
3539
0
  declare_integer("SECTION_ALIGN_1BYTES");
3540
0
  declare_integer("SECTION_ALIGN_2BYTES");
3541
0
  declare_integer("SECTION_ALIGN_4BYTES");
3542
0
  declare_integer("SECTION_ALIGN_8BYTES");
3543
0
  declare_integer("SECTION_ALIGN_16BYTES");
3544
0
  declare_integer("SECTION_ALIGN_32BYTES");
3545
0
  declare_integer("SECTION_ALIGN_64BYTES");
3546
0
  declare_integer("SECTION_ALIGN_128BYTES");
3547
0
  declare_integer("SECTION_ALIGN_256BYTES");
3548
0
  declare_integer("SECTION_ALIGN_512BYTES");
3549
0
  declare_integer("SECTION_ALIGN_1024BYTES");
3550
0
  declare_integer("SECTION_ALIGN_2048BYTES");
3551
0
  declare_integer("SECTION_ALIGN_4096BYTES");
3552
0
  declare_integer("SECTION_ALIGN_8192BYTES");
3553
0
  declare_integer("SECTION_ALIGN_MASK");
3554
0
  declare_integer("SECTION_LNK_NRELOC_OVFL");
3555
0
  declare_integer("SECTION_MEM_DISCARDABLE");
3556
0
  declare_integer("SECTION_MEM_NOT_CACHED");
3557
0
  declare_integer("SECTION_MEM_NOT_PAGED");
3558
0
  declare_integer("SECTION_MEM_SHARED");
3559
0
  declare_integer("SECTION_MEM_EXECUTE");
3560
0
  declare_integer("SECTION_MEM_READ");
3561
0
  declare_integer("SECTION_MEM_WRITE");
3562
0
  declare_integer("SECTION_SCALE_INDEX");
3563
3564
0
  declare_integer("RESOURCE_TYPE_CURSOR");
3565
0
  declare_integer("RESOURCE_TYPE_BITMAP");
3566
0
  declare_integer("RESOURCE_TYPE_ICON");
3567
0
  declare_integer("RESOURCE_TYPE_MENU");
3568
0
  declare_integer("RESOURCE_TYPE_DIALOG");
3569
0
  declare_integer("RESOURCE_TYPE_STRING");
3570
0
  declare_integer("RESOURCE_TYPE_FONTDIR");
3571
0
  declare_integer("RESOURCE_TYPE_FONT");
3572
0
  declare_integer("RESOURCE_TYPE_ACCELERATOR");
3573
0
  declare_integer("RESOURCE_TYPE_RCDATA");
3574
0
  declare_integer("RESOURCE_TYPE_MESSAGETABLE");
3575
0
  declare_integer("RESOURCE_TYPE_GROUP_CURSOR");
3576
0
  declare_integer("RESOURCE_TYPE_GROUP_ICON");
3577
0
  declare_integer("RESOURCE_TYPE_VERSION");
3578
0
  declare_integer("RESOURCE_TYPE_DLGINCLUDE");
3579
0
  declare_integer("RESOURCE_TYPE_PLUGPLAY");
3580
0
  declare_integer("RESOURCE_TYPE_VXD");
3581
0
  declare_integer("RESOURCE_TYPE_ANICURSOR");
3582
0
  declare_integer("RESOURCE_TYPE_ANIICON");
3583
0
  declare_integer("RESOURCE_TYPE_HTML");
3584
0
  declare_integer("RESOURCE_TYPE_MANIFEST");
3585
3586
0
  declare_integer("IMAGE_DEBUG_TYPE_UNKNOWN");
3587
0
  declare_integer("IMAGE_DEBUG_TYPE_COFF");
3588
0
  declare_integer("IMAGE_DEBUG_TYPE_CODEVIEW");
3589
0
  declare_integer("IMAGE_DEBUG_TYPE_FPO");
3590
0
  declare_integer("IMAGE_DEBUG_TYPE_MISC");
3591
0
  declare_integer("IMAGE_DEBUG_TYPE_EXCEPTION");
3592
0
  declare_integer("IMAGE_DEBUG_TYPE_FIXUP");
3593
0
  declare_integer("IMAGE_DEBUG_TYPE_OMAP_TO_SRC");
3594
0
  declare_integer("IMAGE_DEBUG_TYPE_OMAP_FROM_SRC");
3595
0
  declare_integer("IMAGE_DEBUG_TYPE_BORLAND");
3596
0
  declare_integer("IMAGE_DEBUG_TYPE_RESERVED10");
3597
0
  declare_integer("IMAGE_DEBUG_TYPE_CLSID");
3598
0
  declare_integer("IMAGE_DEBUG_TYPE_VC_FEATURE");
3599
0
  declare_integer("IMAGE_DEBUG_TYPE_POGO");
3600
0
  declare_integer("IMAGE_DEBUG_TYPE_ILTCG");
3601
0
  declare_integer("IMAGE_DEBUG_TYPE_MPX");
3602
0
  declare_integer("IMAGE_DEBUG_TYPE_REPRO");
3603
3604
0
  declare_integer("is_pe");
3605
0
  declare_integer("machine");
3606
0
  declare_integer("number_of_sections");
3607
0
  declare_integer("timestamp");
3608
0
  declare_integer("pointer_to_symbol_table");
3609
0
  declare_integer("number_of_symbols");
3610
0
  declare_integer("size_of_optional_header");
3611
0
  declare_integer("characteristics");
3612
3613
0
  declare_integer("entry_point");
3614
0
  declare_integer("entry_point_raw");
3615
0
  declare_integer("image_base");
3616
0
  declare_integer("number_of_rva_and_sizes");
3617
0
  declare_integer("number_of_version_infos");
3618
3619
0
  declare_string_dictionary("version_info");
3620
3621
0
  begin_struct_array("version_info_list")
3622
0
    declare_string("key");
3623
0
    declare_string("value");
3624
0
  end_struct_array("version_info_list");
3625
3626
0
  declare_integer("opthdr_magic");
3627
0
  declare_integer("size_of_code");
3628
0
  declare_integer("size_of_initialized_data");
3629
0
  declare_integer("size_of_uninitialized_data");
3630
0
  declare_integer("base_of_code");
3631
0
  declare_integer("base_of_data");
3632
0
  declare_integer("section_alignment");
3633
0
  declare_integer("file_alignment");
3634
3635
0
  begin_struct("linker_version")
3636
0
    declare_integer("major");
3637
0
    declare_integer("minor");
3638
0
  end_struct("linker_version");
3639
3640
0
  begin_struct("os_version")
3641
0
    declare_integer("major");
3642
0
    declare_integer("minor");
3643
0
  end_struct("os_version");
3644
3645
0
  begin_struct("image_version")
3646
0
    declare_integer("major");
3647
0
    declare_integer("minor");
3648
0
  end_struct("image_version");
3649
3650
0
  begin_struct("subsystem_version")
3651
0
    declare_integer("major");
3652
0
    declare_integer("minor");
3653
0
  end_struct("subsystem_version");
3654
3655
0
  declare_integer("win32_version_value");
3656
0
  declare_integer("size_of_image");
3657
0
  declare_integer("size_of_headers");
3658
3659
0
  declare_integer("checksum");
3660
0
  declare_function("calculate_checksum", "", "i", calculate_checksum);
3661
0
  declare_integer("subsystem");
3662
3663
0
  declare_integer("dll_characteristics");
3664
0
  declare_integer("size_of_stack_reserve");
3665
0
  declare_integer("size_of_stack_commit");
3666
0
  declare_integer("size_of_heap_reserve");
3667
0
  declare_integer("size_of_heap_commit");
3668
0
  declare_integer("loader_flags");
3669
3670
0
  begin_struct_array("data_directories")
3671
0
    declare_integer("virtual_address");
3672
0
    declare_integer("size");
3673
0
  end_struct_array("data_directories");
3674
3675
0
  begin_struct_array("sections")
3676
0
    declare_string("name");
3677
0
    declare_string("full_name");
3678
0
    declare_integer("characteristics");
3679
0
    declare_integer("virtual_address");
3680
0
    declare_integer("virtual_size");
3681
0
    declare_integer("raw_data_offset");
3682
0
    declare_integer("raw_data_size");
3683
0
    declare_integer("pointer_to_relocations");
3684
0
    declare_integer("pointer_to_line_numbers");
3685
0
    declare_integer("number_of_relocations");
3686
0
    declare_integer("number_of_line_numbers");
3687
0
  end_struct_array("sections");
3688
3689
0
  begin_struct("overlay")
3690
0
    declare_integer("offset");
3691
0
    declare_integer("size");
3692
0
  end_struct("overlay");
3693
3694
0
  begin_struct("rich_signature")
3695
0
    declare_integer("offset");
3696
0
    declare_integer("length");
3697
0
    declare_integer("key");
3698
0
    declare_string("raw_data");
3699
0
    declare_string("clear_data");
3700
0
    declare_string("version_data");
3701
0
    declare_function("version", "i", "i", rich_version);
3702
0
    declare_function("version", "ii", "i", rich_version_toolid);
3703
0
    declare_function("toolid", "i", "i", rich_toolid);
3704
0
    declare_function("toolid", "ii", "i", rich_toolid_version);
3705
0
  end_struct("rich_signature");
3706
3707
#if defined(HAVE_LIBCRYPTO) || defined(HAVE_WINCRYPT_H) || \
3708
    defined(HAVE_COMMONCRYPTO_COMMONCRYPTO_H)
3709
  declare_function("imphash", "", "s", imphash);
3710
#endif
3711
3712
0
  declare_integer("IMPORT_DELAYED");
3713
0
  declare_integer("IMPORT_STANDARD");
3714
0
  declare_integer("IMPORT_ANY");
3715
3716
0
  declare_function("section_index", "s", "i", section_index_name);
3717
0
  declare_function("section_index", "i", "i", section_index_addr);
3718
0
  declare_function("exports", "s", "i", exports);
3719
0
  declare_function("exports", "r", "i", exports_regexp);
3720
0
  declare_function("exports", "i", "i", exports_ordinal);
3721
0
  declare_function("exports_index", "s", "i", exports_index_name);
3722
0
  declare_function("exports_index", "i", "i", exports_index_ordinal);
3723
0
  declare_function("exports_index", "r", "i", exports_index_regex);
3724
0
  declare_function("imports", "ss", "i", imports_standard);
3725
0
  declare_function("imports", "si", "i", imports_standard_ordinal);
3726
0
  declare_function("imports", "s", "i", imports_standard_dll);
3727
0
  declare_function("imports", "rr", "i", imports_standard_regex);
3728
0
  declare_function("imports", "iss", "i", imports);
3729
0
  declare_function("imports", "isi", "i", imports_ordinal);
3730
0
  declare_function("imports", "is", "i", imports_dll);
3731
0
  declare_function("imports", "irr", "i", imports_regex);
3732
0
  declare_function("import_rva", "ss", "i", import_rva);
3733
0
  declare_function("import_rva", "si", "i", import_rva_ordinal);
3734
0
  declare_function("delayed_import_rva", "ss", "i", delayed_import_rva);
3735
0
  declare_function("delayed_import_rva", "si", "i", delayed_import_rva_ordinal);
3736
0
  declare_function("locale", "i", "i", locale);
3737
0
  declare_function("language", "i", "i", language);
3738
0
  declare_function("is_dll", "", "i", is_dll);
3739
0
  declare_function("is_32bit", "", "i", is_32bit);
3740
0
  declare_function("is_64bit", "", "i", is_64bit);
3741
3742
0
  declare_integer("number_of_imports");
3743
0
  declare_integer("number_of_imported_functions");
3744
0
  declare_integer("number_of_delayed_imports");
3745
0
  declare_integer("number_of_delayed_imported_functions");
3746
0
  declare_integer("number_of_exports");
3747
3748
0
  declare_string("dll_name");
3749
0
  declare_integer("export_timestamp");
3750
0
  begin_struct_array("export_details")
3751
0
    declare_integer("offset");
3752
0
    declare_string("name");
3753
0
    declare_string("forward_name");
3754
0
    declare_integer("ordinal");
3755
0
  end_struct_array("export_details")
3756
3757
0
  begin_struct_array("import_details")
3758
0
    declare_string("library_name");
3759
0
    declare_integer("number_of_functions");
3760
0
    begin_struct_array("functions")
3761
0
      declare_string("name");
3762
0
      declare_integer("ordinal");
3763
0
      declare_integer("rva");
3764
0
    end_struct_array("functions");
3765
0
  end_struct_array("import_details");
3766
3767
0
  begin_struct_array("delayed_import_details")
3768
0
    declare_string("library_name");
3769
0
    declare_integer("number_of_functions");
3770
0
    begin_struct_array("functions")
3771
0
      declare_string("name");
3772
0
      declare_integer("ordinal");
3773
0
      declare_integer("rva");
3774
0
    end_struct_array("functions");
3775
0
  end_struct_array("delayed_import_details");
3776
3777
0
  declare_integer("resource_timestamp");
3778
3779
0
  begin_struct("resource_version")
3780
0
    declare_integer("major");
3781
0
    declare_integer("minor");
3782
0
  end_struct("resource_version")
3783
3784
0
  begin_struct_array("resources")
3785
0
    declare_integer("rva");
3786
0
    declare_integer("offset");
3787
0
    declare_integer("length");
3788
0
    declare_integer("type");
3789
0
    declare_integer("id");
3790
0
    declare_integer("language");
3791
0
    declare_string("type_string");
3792
0
    declare_string("name_string");
3793
0
    declare_string("language_string");
3794
0
  end_struct_array("resources")
3795
3796
0
  declare_integer("number_of_resources");
3797
0
  declare_string("pdb_path");
3798
3799
#if defined(HAVE_LIBCRYPTO) && !defined(BORINGSSL)
3800
  begin_struct_array("signatures")
3801
    declare_string("thumbprint");
3802
    declare_string("issuer");
3803
    declare_string("subject");
3804
    declare_integer("version");
3805
    declare_string("algorithm");
3806
    declare_string("algorithm_oid");
3807
    declare_string("serial");
3808
    declare_integer("not_before");
3809
    declare_integer("not_after");
3810
3811
    declare_integer("verified");
3812
    declare_string("digest_alg");
3813
    declare_string("digest");
3814
    declare_string("file_digest");
3815
    declare_integer("number_of_certificates");
3816
    begin_struct_array("certificates")
3817
      ;
3818
      declare_string("thumbprint");
3819
      declare_string("issuer");
3820
      declare_string("subject");
3821
      declare_integer("version");
3822
      declare_string("algorithm");
3823
      declare_string("algorithm_oid");
3824
      declare_string("serial");
3825
      declare_integer("not_before");
3826
      declare_integer("not_after");
3827
    end_struct_array("certificates");
3828
3829
    begin_struct("signer_info")
3830
      ;
3831
      declare_string("program_name");
3832
      declare_string("digest");
3833
      declare_string("digest_alg");
3834
      declare_integer("length_of_chain");
3835
      begin_struct_array("chain")
3836
        ;
3837
        declare_string("thumbprint");
3838
        declare_string("issuer");
3839
        declare_string("subject");
3840
        declare_integer("version");
3841
        declare_string("algorithm");
3842
        declare_string("algorithm_oid");
3843
        declare_string("serial");
3844
        declare_integer("not_before");
3845
        declare_integer("not_after");
3846
      end_struct_array("chain");
3847
    end_struct("signer_info");
3848
3849
    declare_integer("number_of_countersignatures");
3850
    begin_struct_array("countersignatures")
3851
      ;
3852
      declare_integer("verified");
3853
      declare_integer("sign_time");
3854
      declare_string("digest_alg");
3855
      declare_string("digest");
3856
      declare_integer("length_of_chain");
3857
      begin_struct_array("chain")
3858
        ;
3859
        declare_string("thumbprint");
3860
        declare_string("issuer");
3861
        declare_string("subject");
3862
        declare_integer("version");
3863
        declare_string("algorithm");
3864
        declare_string("algorithm_oid");
3865
        declare_string("serial");
3866
        declare_integer("not_before");
3867
        declare_integer("not_after");
3868
      end_struct_array("chain");
3869
    end_struct_array("countersignatures")
3870
3871
    declare_function("valid_on", "i", "i", valid_on);
3872
3873
  end_struct_array("signatures")
3874
3875
  // If any of the signatures correctly signs the binary
3876
  declare_integer("is_signed");
3877
  declare_integer("number_of_signatures");
3878
#endif
3879
3880
0
  declare_function("rva_to_offset", "i", "i", rva_to_offset);
3881
0
end_declarations
3882
3883
int module_initialize(YR_MODULE* module)
3884
2
{
3885
#if defined(HAVE_LIBCRYPTO)
3886
  // Initialize OpenSSL global objects for the auth library before any
3887
  // multithreaded environment as it is not thread-safe
3888
  initialize_authenticode_parser();
3889
#endif
3890
2
  return ERROR_SUCCESS;
3891
2
}
3892
3893
int module_finalize(YR_MODULE* module)
3894
0
{
3895
0
  return ERROR_SUCCESS;
3896
0
}
3897
3898
int module_load(
3899
    YR_SCAN_CONTEXT* context,
3900
    YR_OBJECT* module_object,
3901
    void* module_data,
3902
    size_t module_data_size)
3903
0
{
3904
0
  YR_MEMORY_BLOCK* block;
3905
0
  YR_MEMORY_BLOCK_ITERATOR* iterator = context->iterator;
3906
3907
0
  PIMAGE_NT_HEADERS32 pe_header;
3908
0
  const uint8_t* block_data = NULL;
3909
0
  PE* pe = NULL;
3910
3911
0
  yr_set_integer(IMPORT_DELAYED, module_object, "IMPORT_DELAYED");
3912
0
  yr_set_integer(IMPORT_STANDARD, module_object, "IMPORT_STANDARD");
3913
0
  yr_set_integer(IMPORT_ANY, module_object, "IMPORT_ANY");
3914
3915
0
  yr_set_integer(IMAGE_FILE_MACHINE_UNKNOWN, module_object, "MACHINE_UNKNOWN");
3916
0
  yr_set_integer(IMAGE_FILE_MACHINE_AM33, module_object, "MACHINE_AM33");
3917
0
  yr_set_integer(IMAGE_FILE_MACHINE_AMD64, module_object, "MACHINE_AMD64");
3918
0
  yr_set_integer(IMAGE_FILE_MACHINE_ARM, module_object, "MACHINE_ARM");
3919
0
  yr_set_integer(IMAGE_FILE_MACHINE_ARMNT, module_object, "MACHINE_ARMNT");
3920
0
  yr_set_integer(IMAGE_FILE_MACHINE_ARM64, module_object, "MACHINE_ARM64");
3921
0
  yr_set_integer(IMAGE_FILE_MACHINE_EBC, module_object, "MACHINE_EBC");
3922
0
  yr_set_integer(IMAGE_FILE_MACHINE_I386, module_object, "MACHINE_I386");
3923
0
  yr_set_integer(IMAGE_FILE_MACHINE_IA64, module_object, "MACHINE_IA64");
3924
0
  yr_set_integer(IMAGE_FILE_MACHINE_M32R, module_object, "MACHINE_M32R");
3925
0
  yr_set_integer(IMAGE_FILE_MACHINE_MIPS16, module_object, "MACHINE_MIPS16");
3926
0
  yr_set_integer(IMAGE_FILE_MACHINE_MIPSFPU, module_object, "MACHINE_MIPSFPU");
3927
0
  yr_set_integer(
3928
0
      IMAGE_FILE_MACHINE_MIPSFPU16, module_object, "MACHINE_MIPSFPU16");
3929
0
  yr_set_integer(IMAGE_FILE_MACHINE_POWERPC, module_object, "MACHINE_POWERPC");
3930
0
  yr_set_integer(
3931
0
      IMAGE_FILE_MACHINE_POWERPCFP, module_object, "MACHINE_POWERPCFP");
3932
0
  yr_set_integer(IMAGE_FILE_MACHINE_R4000, module_object, "MACHINE_R4000");
3933
0
  yr_set_integer(IMAGE_FILE_MACHINE_SH3, module_object, "MACHINE_SH3");
3934
0
  yr_set_integer(IMAGE_FILE_MACHINE_SH3DSP, module_object, "MACHINE_SH3DSP");
3935
0
  yr_set_integer(IMAGE_FILE_MACHINE_SH4, module_object, "MACHINE_SH4");
3936
0
  yr_set_integer(IMAGE_FILE_MACHINE_SH5, module_object, "MACHINE_SH5");
3937
0
  yr_set_integer(IMAGE_FILE_MACHINE_THUMB, module_object, "MACHINE_THUMB");
3938
0
  yr_set_integer(
3939
0
      IMAGE_FILE_MACHINE_WCEMIPSV2, module_object, "MACHINE_WCEMIPSV2");
3940
0
  yr_set_integer(
3941
0
      IMAGE_FILE_MACHINE_TARGET_HOST, module_object, "MACHINE_TARGET_HOST");
3942
0
  yr_set_integer(IMAGE_FILE_MACHINE_R3000, module_object, "MACHINE_R3000");
3943
0
  yr_set_integer(IMAGE_FILE_MACHINE_R10000, module_object, "MACHINE_R10000");
3944
0
  yr_set_integer(IMAGE_FILE_MACHINE_ALPHA, module_object, "MACHINE_ALPHA");
3945
0
  yr_set_integer(IMAGE_FILE_MACHINE_SH3E, module_object, "MACHINE_SH3E");
3946
0
  yr_set_integer(IMAGE_FILE_MACHINE_ALPHA64, module_object, "MACHINE_ALPHA64");
3947
0
  yr_set_integer(IMAGE_FILE_MACHINE_AXP64, module_object, "MACHINE_AXP64");
3948
0
  yr_set_integer(IMAGE_FILE_MACHINE_TRICORE, module_object, "MACHINE_TRICORE");
3949
0
  yr_set_integer(IMAGE_FILE_MACHINE_CEF, module_object, "MACHINE_CEF");
3950
0
  yr_set_integer(IMAGE_FILE_MACHINE_CEE, module_object, "MACHINE_CEE");
3951
3952
0
  yr_set_integer(IMAGE_SUBSYSTEM_UNKNOWN, module_object, "SUBSYSTEM_UNKNOWN");
3953
0
  yr_set_integer(IMAGE_SUBSYSTEM_NATIVE, module_object, "SUBSYSTEM_NATIVE");
3954
0
  yr_set_integer(
3955
0
      IMAGE_SUBSYSTEM_WINDOWS_GUI, module_object, "SUBSYSTEM_WINDOWS_GUI");
3956
0
  yr_set_integer(
3957
0
      IMAGE_SUBSYSTEM_WINDOWS_CUI, module_object, "SUBSYSTEM_WINDOWS_CUI");
3958
0
  yr_set_integer(IMAGE_SUBSYSTEM_OS2_CUI, module_object, "SUBSYSTEM_OS2_CUI");
3959
0
  yr_set_integer(
3960
0
      IMAGE_SUBSYSTEM_POSIX_CUI, module_object, "SUBSYSTEM_POSIX_CUI");
3961
0
  yr_set_integer(
3962
0
      IMAGE_SUBSYSTEM_NATIVE_WINDOWS,
3963
0
      module_object,
3964
0
      "SUBSYSTEM_NATIVE_WINDOWS");
3965
0
  yr_set_integer(
3966
0
      IMAGE_SUBSYSTEM_WINDOWS_CE_GUI,
3967
0
      module_object,
3968
0
      "SUBSYSTEM_WINDOWS_CE_GUI");
3969
0
  yr_set_integer(
3970
0
      IMAGE_SUBSYSTEM_EFI_APPLICATION,
3971
0
      module_object,
3972
0
      "SUBSYSTEM_EFI_APPLICATION");
3973
0
  yr_set_integer(
3974
0
      IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER,
3975
0
      module_object,
3976
0
      "SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER");
3977
0
  yr_set_integer(
3978
0
      IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER,
3979
0
      module_object,
3980
0
      "SUBSYSTEM_EFI_RUNTIME_DRIVER");
3981
0
  yr_set_integer(
3982
0
      IMAGE_SUBSYSTEM_EFI_ROM_IMAGE, module_object, "SUBSYSTEM_EFI_ROM_IMAGE");
3983
0
  yr_set_integer(IMAGE_SUBSYSTEM_XBOX, module_object, "SUBSYSTEM_XBOX");
3984
0
  yr_set_integer(
3985
0
      IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION,
3986
0
      module_object,
3987
0
      "SUBSYSTEM_WINDOWS_BOOT_APPLICATION");
3988
3989
0
  yr_set_integer(
3990
0
      IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA,
3991
0
      module_object,
3992
0
      "HIGH_ENTROPY_VA");
3993
0
  yr_set_integer(
3994
0
      IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE, module_object, "DYNAMIC_BASE");
3995
0
  yr_set_integer(
3996
0
      IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY,
3997
0
      module_object,
3998
0
      "FORCE_INTEGRITY");
3999
0
  yr_set_integer(
4000
0
      IMAGE_DLLCHARACTERISTICS_NX_COMPAT, module_object, "NX_COMPAT");
4001
0
  yr_set_integer(
4002
0
      IMAGE_DLLCHARACTERISTICS_NO_ISOLATION, module_object, "NO_ISOLATION");
4003
0
  yr_set_integer(IMAGE_DLLCHARACTERISTICS_NO_SEH, module_object, "NO_SEH");
4004
0
  yr_set_integer(IMAGE_DLLCHARACTERISTICS_NO_BIND, module_object, "NO_BIND");
4005
0
  yr_set_integer(
4006
0
      IMAGE_DLLCHARACTERISTICS_APPCONTAINER, module_object, "APPCONTAINER");
4007
0
  yr_set_integer(
4008
0
      IMAGE_DLLCHARACTERISTICS_WDM_DRIVER, module_object, "WDM_DRIVER");
4009
0
  yr_set_integer(IMAGE_DLLCHARACTERISTICS_GUARD_CF, module_object, "GUARD_CF");
4010
0
  yr_set_integer(
4011
0
      IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE,
4012
0
      module_object,
4013
0
      "TERMINAL_SERVER_AWARE");
4014
4015
0
  yr_set_integer(IMAGE_FILE_RELOCS_STRIPPED, module_object, "RELOCS_STRIPPED");
4016
0
  yr_set_integer(
4017
0
      IMAGE_FILE_EXECUTABLE_IMAGE, module_object, "EXECUTABLE_IMAGE");
4018
0
  yr_set_integer(
4019
0
      IMAGE_FILE_LINE_NUMS_STRIPPED, module_object, "LINE_NUMS_STRIPPED");
4020
0
  yr_set_integer(
4021
0
      IMAGE_FILE_LOCAL_SYMS_STRIPPED, module_object, "LOCAL_SYMS_STRIPPED");
4022
0
  yr_set_integer(
4023
0
      IMAGE_FILE_AGGRESIVE_WS_TRIM, module_object, "AGGRESIVE_WS_TRIM");
4024
0
  yr_set_integer(
4025
0
      IMAGE_FILE_LARGE_ADDRESS_AWARE, module_object, "LARGE_ADDRESS_AWARE");
4026
0
  yr_set_integer(
4027
0
      IMAGE_FILE_BYTES_REVERSED_LO, module_object, "BYTES_REVERSED_LO");
4028
0
  yr_set_integer(IMAGE_FILE_32BIT_MACHINE, module_object, "MACHINE_32BIT");
4029
0
  yr_set_integer(IMAGE_FILE_DEBUG_STRIPPED, module_object, "DEBUG_STRIPPED");
4030
0
  yr_set_integer(
4031
0
      IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP,
4032
0
      module_object,
4033
0
      "REMOVABLE_RUN_FROM_SWAP");
4034
0
  yr_set_integer(
4035
0
      IMAGE_FILE_NET_RUN_FROM_SWAP, module_object, "NET_RUN_FROM_SWAP");
4036
0
  yr_set_integer(IMAGE_FILE_SYSTEM, module_object, "SYSTEM");
4037
0
  yr_set_integer(IMAGE_FILE_DLL, module_object, "DLL");
4038
0
  yr_set_integer(IMAGE_FILE_UP_SYSTEM_ONLY, module_object, "UP_SYSTEM_ONLY");
4039
0
  yr_set_integer(
4040
0
      IMAGE_FILE_BYTES_REVERSED_HI, module_object, "BYTES_REVERSED_HI");
4041
4042
0
  yr_set_integer(
4043
0
      IMAGE_DIRECTORY_ENTRY_EXPORT,
4044
0
      module_object,
4045
0
      "IMAGE_DIRECTORY_ENTRY_EXPORT");
4046
0
  yr_set_integer(
4047
0
      IMAGE_DIRECTORY_ENTRY_IMPORT,
4048
0
      module_object,
4049
0
      "IMAGE_DIRECTORY_ENTRY_IMPORT");
4050
0
  yr_set_integer(
4051
0
      IMAGE_DIRECTORY_ENTRY_RESOURCE,
4052
0
      module_object,
4053
0
      "IMAGE_DIRECTORY_ENTRY_RESOURCE");
4054
0
  yr_set_integer(
4055
0
      IMAGE_DIRECTORY_ENTRY_EXCEPTION,
4056
0
      module_object,
4057
0
      "IMAGE_DIRECTORY_ENTRY_EXCEPTION");
4058
0
  yr_set_integer(
4059
0
      IMAGE_DIRECTORY_ENTRY_SECURITY,
4060
0
      module_object,
4061
0
      "IMAGE_DIRECTORY_ENTRY_SECURITY");
4062
0
  yr_set_integer(
4063
0
      IMAGE_DIRECTORY_ENTRY_BASERELOC,
4064
0
      module_object,
4065
0
      "IMAGE_DIRECTORY_ENTRY_BASERELOC");
4066
0
  yr_set_integer(
4067
0
      IMAGE_DIRECTORY_ENTRY_DEBUG,
4068
0
      module_object,
4069
0
      "IMAGE_DIRECTORY_ENTRY_DEBUG");
4070
0
  yr_set_integer(
4071
0
      IMAGE_DIRECTORY_ENTRY_ARCHITECTURE,
4072
0
      module_object,
4073
0
      "IMAGE_DIRECTORY_ENTRY_ARCHITECTURE");
4074
0
  yr_set_integer(
4075
0
      IMAGE_DIRECTORY_ENTRY_COPYRIGHT,
4076
0
      module_object,
4077
0
      "IMAGE_DIRECTORY_ENTRY_COPYRIGHT");
4078
0
  yr_set_integer(
4079
0
      IMAGE_DIRECTORY_ENTRY_GLOBALPTR,
4080
0
      module_object,
4081
0
      "IMAGE_DIRECTORY_ENTRY_GLOBALPTR");
4082
0
  yr_set_integer(
4083
0
      IMAGE_DIRECTORY_ENTRY_TLS, module_object, "IMAGE_DIRECTORY_ENTRY_TLS");
4084
0
  yr_set_integer(
4085
0
      IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
4086
0
      module_object,
4087
0
      "IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG");
4088
0
  yr_set_integer(
4089
0
      IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT,
4090
0
      module_object,
4091
0
      "IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT");
4092
0
  yr_set_integer(
4093
0
      IMAGE_DIRECTORY_ENTRY_IAT, module_object, "IMAGE_DIRECTORY_ENTRY_IAT");
4094
0
  yr_set_integer(
4095
0
      IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT,
4096
0
      module_object,
4097
0
      "IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT");
4098
0
  yr_set_integer(
4099
0
      IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR,
4100
0
      module_object,
4101
0
      "IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR");
4102
4103
0
  yr_set_integer(
4104
0
      IMAGE_NT_OPTIONAL_HDR32_MAGIC,
4105
0
      module_object,
4106
0
      "IMAGE_NT_OPTIONAL_HDR32_MAGIC");
4107
0
  yr_set_integer(
4108
0
      IMAGE_NT_OPTIONAL_HDR64_MAGIC,
4109
0
      module_object,
4110
0
      "IMAGE_NT_OPTIONAL_HDR64_MAGIC");
4111
0
  yr_set_integer(
4112
0
      IMAGE_ROM_OPTIONAL_HDR_MAGIC,
4113
0
      module_object,
4114
0
      "IMAGE_ROM_OPTIONAL_HDR_MAGIC");
4115
4116
0
  yr_set_integer(IMAGE_SCN_TYPE_NO_PAD, module_object, "SECTION_NO_PAD");
4117
0
  yr_set_integer(IMAGE_SCN_CNT_CODE, module_object, "SECTION_CNT_CODE");
4118
0
  yr_set_integer(
4119
0
      IMAGE_SCN_CNT_INITIALIZED_DATA,
4120
0
      module_object,
4121
0
      "SECTION_CNT_INITIALIZED_DATA");
4122
0
  yr_set_integer(
4123
0
      IMAGE_SCN_CNT_UNINITIALIZED_DATA,
4124
0
      module_object,
4125
0
      "SECTION_CNT_UNINITIALIZED_DATA");
4126
0
  yr_set_integer(IMAGE_SCN_LNK_OTHER, module_object, "SECTION_LNK_OTHER");
4127
0
  yr_set_integer(IMAGE_SCN_LNK_INFO, module_object, "SECTION_LNK_INFO");
4128
0
  yr_set_integer(IMAGE_SCN_LNK_REMOVE, module_object, "SECTION_LNK_REMOVE");
4129
0
  yr_set_integer(IMAGE_SCN_LNK_COMDAT, module_object, "SECTION_LNK_COMDAT");
4130
0
  yr_set_integer(
4131
0
      IMAGE_SCN_NO_DEFER_SPEC_EXC, module_object, "SECTION_NO_DEFER_SPEC_EXC");
4132
0
  yr_set_integer(IMAGE_SCN_GPREL, module_object, "SECTION_GPREL");
4133
0
  yr_set_integer(IMAGE_SCN_MEM_FARDATA, module_object, "SECTION_MEM_FARDATA");
4134
0
  yr_set_integer(
4135
0
      IMAGE_SCN_MEM_PURGEABLE, module_object, "SECTION_MEM_PURGEABLE");
4136
0
  yr_set_integer(IMAGE_SCN_MEM_16BIT, module_object, "SECTION_MEM_16BIT");
4137
0
  yr_set_integer(IMAGE_SCN_MEM_LOCKED, module_object, "SECTION_MEM_LOCKED");
4138
0
  yr_set_integer(IMAGE_SCN_MEM_PRELOAD, module_object, "SECTION_MEM_PRELOAD");
4139
0
  yr_set_integer(IMAGE_SCN_ALIGN_1BYTES, module_object, "SECTION_ALIGN_1BYTES");
4140
0
  yr_set_integer(IMAGE_SCN_ALIGN_2BYTES, module_object, "SECTION_ALIGN_2BYTES");
4141
0
  yr_set_integer(IMAGE_SCN_ALIGN_4BYTES, module_object, "SECTION_ALIGN_4BYTES");
4142
0
  yr_set_integer(IMAGE_SCN_ALIGN_8BYTES, module_object, "SECTION_ALIGN_8BYTES");
4143
0
  yr_set_integer(
4144
0
      IMAGE_SCN_ALIGN_16BYTES, module_object, "SECTION_ALIGN_16BYTES");
4145
0
  yr_set_integer(
4146
0
      IMAGE_SCN_ALIGN_32BYTES, module_object, "SECTION_ALIGN_32BYTES");
4147
0
  yr_set_integer(
4148
0
      IMAGE_SCN_ALIGN_64BYTES, module_object, "SECTION_ALIGN_64BYTES");
4149
0
  yr_set_integer(
4150
0
      IMAGE_SCN_ALIGN_128BYTES, module_object, "SECTION_ALIGN_128BYTES");
4151
0
  yr_set_integer(
4152
0
      IMAGE_SCN_ALIGN_256BYTES, module_object, "SECTION_ALIGN_256BYTES");
4153
0
  yr_set_integer(
4154
0
      IMAGE_SCN_ALIGN_512BYTES, module_object, "SECTION_ALIGN_512BYTES");
4155
0
  yr_set_integer(
4156
0
      IMAGE_SCN_ALIGN_1024BYTES, module_object, "SECTION_ALIGN_1024BYTES");
4157
0
  yr_set_integer(
4158
0
      IMAGE_SCN_ALIGN_2048BYTES, module_object, "SECTION_ALIGN_2048BYTES");
4159
0
  yr_set_integer(
4160
0
      IMAGE_SCN_ALIGN_4096BYTES, module_object, "SECTION_ALIGN_4096BYTES");
4161
0
  yr_set_integer(
4162
0
      IMAGE_SCN_ALIGN_8192BYTES, module_object, "SECTION_ALIGN_8192BYTES");
4163
0
  yr_set_integer(IMAGE_SCN_ALIGN_MASK, module_object, "SECTION_ALIGN_MASK");
4164
0
  yr_set_integer(
4165
0
      IMAGE_SCN_LNK_NRELOC_OVFL, module_object, "SECTION_LNK_NRELOC_OVFL");
4166
0
  yr_set_integer(
4167
0
      IMAGE_SCN_MEM_DISCARDABLE, module_object, "SECTION_MEM_DISCARDABLE");
4168
0
  yr_set_integer(
4169
0
      IMAGE_SCN_MEM_NOT_CACHED, module_object, "SECTION_MEM_NOT_CACHED");
4170
0
  yr_set_integer(
4171
0
      IMAGE_SCN_MEM_NOT_PAGED, module_object, "SECTION_MEM_NOT_PAGED");
4172
0
  yr_set_integer(IMAGE_SCN_MEM_SHARED, module_object, "SECTION_MEM_SHARED");
4173
0
  yr_set_integer(IMAGE_SCN_MEM_EXECUTE, module_object, "SECTION_MEM_EXECUTE");
4174
0
  yr_set_integer(IMAGE_SCN_MEM_READ, module_object, "SECTION_MEM_READ");
4175
0
  yr_set_integer(IMAGE_SCN_MEM_WRITE, module_object, "SECTION_MEM_WRITE");
4176
0
  yr_set_integer(IMAGE_SCN_SCALE_INDEX, module_object, "SECTION_SCALE_INDEX");
4177
4178
0
  yr_set_integer(RESOURCE_TYPE_CURSOR, module_object, "RESOURCE_TYPE_CURSOR");
4179
0
  yr_set_integer(RESOURCE_TYPE_BITMAP, module_object, "RESOURCE_TYPE_BITMAP");
4180
0
  yr_set_integer(RESOURCE_TYPE_ICON, module_object, "RESOURCE_TYPE_ICON");
4181
0
  yr_set_integer(RESOURCE_TYPE_MENU, module_object, "RESOURCE_TYPE_MENU");
4182
0
  yr_set_integer(RESOURCE_TYPE_DIALOG, module_object, "RESOURCE_TYPE_DIALOG");
4183
0
  yr_set_integer(RESOURCE_TYPE_STRING, module_object, "RESOURCE_TYPE_STRING");
4184
0
  yr_set_integer(RESOURCE_TYPE_FONTDIR, module_object, "RESOURCE_TYPE_FONTDIR");
4185
0
  yr_set_integer(RESOURCE_TYPE_FONT, module_object, "RESOURCE_TYPE_FONT");
4186
0
  yr_set_integer(
4187
0
      RESOURCE_TYPE_ACCELERATOR, module_object, "RESOURCE_TYPE_ACCELERATOR");
4188
0
  yr_set_integer(RESOURCE_TYPE_RCDATA, module_object, "RESOURCE_TYPE_RCDATA");
4189
0
  yr_set_integer(
4190
0
      RESOURCE_TYPE_MESSAGETABLE, module_object, "RESOURCE_TYPE_MESSAGETABLE");
4191
0
  yr_set_integer(
4192
0
      RESOURCE_TYPE_GROUP_CURSOR, module_object, "RESOURCE_TYPE_GROUP_CURSOR");
4193
0
  yr_set_integer(
4194
0
      RESOURCE_TYPE_GROUP_ICON, module_object, "RESOURCE_TYPE_GROUP_ICON");
4195
0
  yr_set_integer(RESOURCE_TYPE_VERSION, module_object, "RESOURCE_TYPE_VERSION");
4196
0
  yr_set_integer(
4197
0
      RESOURCE_TYPE_DLGINCLUDE, module_object, "RESOURCE_TYPE_DLGINCLUDE");
4198
0
  yr_set_integer(
4199
0
      RESOURCE_TYPE_PLUGPLAY, module_object, "RESOURCE_TYPE_PLUGPLAY");
4200
0
  yr_set_integer(RESOURCE_TYPE_VXD, module_object, "RESOURCE_TYPE_VXD");
4201
0
  yr_set_integer(
4202
0
      RESOURCE_TYPE_ANICURSOR, module_object, "RESOURCE_TYPE_ANICURSOR");
4203
0
  yr_set_integer(RESOURCE_TYPE_ANIICON, module_object, "RESOURCE_TYPE_ANIICON");
4204
0
  yr_set_integer(RESOURCE_TYPE_HTML, module_object, "RESOURCE_TYPE_HTML");
4205
0
  yr_set_integer(
4206
0
      RESOURCE_TYPE_MANIFEST, module_object, "RESOURCE_TYPE_MANIFEST");
4207
4208
0
  yr_set_integer(
4209
0
      IMAGE_DEBUG_TYPE_UNKNOWN, module_object, "IMAGE_DEBUG_TYPE_UNKNOWN");
4210
0
  yr_set_integer(IMAGE_DEBUG_TYPE_COFF, module_object, "IMAGE_DEBUG_TYPE_COFF");
4211
0
  yr_set_integer(
4212
0
      IMAGE_DEBUG_TYPE_CODEVIEW, module_object, "IMAGE_DEBUG_TYPE_CODEVIEW");
4213
0
  yr_set_integer(IMAGE_DEBUG_TYPE_FPO, module_object, "IMAGE_DEBUG_TYPE_FPO");
4214
0
  yr_set_integer(IMAGE_DEBUG_TYPE_MISC, module_object, "IMAGE_DEBUG_TYPE_MISC");
4215
0
  yr_set_integer(
4216
0
      IMAGE_DEBUG_TYPE_EXCEPTION, module_object, "IMAGE_DEBUG_TYPE_EXCEPTION");
4217
0
  yr_set_integer(
4218
0
      IMAGE_DEBUG_TYPE_FIXUP, module_object, "IMAGE_DEBUG_TYPE_FIXUP");
4219
0
  yr_set_integer(
4220
0
      IMAGE_DEBUG_TYPE_OMAP_TO_SRC,
4221
0
      module_object,
4222
0
      "IMAGE_DEBUG_TYPE_OMAP_TO_SRC");
4223
0
  yr_set_integer(
4224
0
      IMAGE_DEBUG_TYPE_OMAP_FROM_SRC,
4225
0
      module_object,
4226
0
      "IMAGE_DEBUG_TYPE_OMAP_FROM_SRC");
4227
0
  yr_set_integer(
4228
0
      IMAGE_DEBUG_TYPE_BORLAND, module_object, "IMAGE_DEBUG_TYPE_BORLAND");
4229
0
  yr_set_integer(
4230
0
      IMAGE_DEBUG_TYPE_RESERVED10,
4231
0
      module_object,
4232
0
      "IMAGE_DEBUG_TYPE_RESERVED10");
4233
0
  yr_set_integer(
4234
0
      IMAGE_DEBUG_TYPE_CLSID, module_object, "IMAGE_DEBUG_TYPE_CLSID");
4235
0
  yr_set_integer(
4236
0
      IMAGE_DEBUG_TYPE_VC_FEATURE,
4237
0
      module_object,
4238
0
      "IMAGE_DEBUG_TYPE_VC_FEATURE");
4239
0
  yr_set_integer(IMAGE_DEBUG_TYPE_POGO, module_object, "IMAGE_DEBUG_TYPE_POGO");
4240
0
  yr_set_integer(
4241
0
      IMAGE_DEBUG_TYPE_ILTCG, module_object, "IMAGE_DEBUG_TYPE_ILTCG");
4242
0
  yr_set_integer(IMAGE_DEBUG_TYPE_MPX, module_object, "IMAGE_DEBUG_TYPE_MPX");
4243
0
  yr_set_integer(
4244
0
      IMAGE_DEBUG_TYPE_REPRO, module_object, "IMAGE_DEBUG_TYPE_REPRO");
4245
4246
0
  yr_set_integer(0, module_object, "is_pe");
4247
4248
0
  foreach_memory_block(iterator, block)
4249
0
  {
4250
0
    block_data = block->fetch_data(block);
4251
4252
0
    if (block_data == NULL)
4253
0
      continue;
4254
4255
0
    pe_header = pe_get_header(block_data, block->size);
4256
4257
0
    if (pe_header != NULL)
4258
0
    {
4259
      // Ignore DLLs while scanning a process
4260
4261
0
      if (!(context->flags & SCAN_FLAGS_PROCESS_MEMORY) ||
4262
0
          !(yr_le16toh(pe_header->FileHeader.Characteristics) & IMAGE_FILE_DLL))
4263
0
      {
4264
0
        pe = (PE*) yr_malloc(sizeof(PE));
4265
4266
0
        if (pe == NULL)
4267
0
          return ERROR_INSUFFICIENT_MEMORY;
4268
4269
0
        FAIL_ON_ERROR_WITH_CLEANUP(
4270
0
            yr_hash_table_create(17, &pe->hash_table), yr_free(pe));
4271
4272
0
        pe->data = block_data;
4273
0
        pe->data_size = block->size;
4274
0
        pe->header = pe_header;
4275
0
        pe->object = module_object;
4276
0
        pe->resources = 0;
4277
0
        pe->version_infos = 0;
4278
4279
0
        module_object->data = pe;
4280
4281
0
        pe_parse_header(pe, block->base, context->flags);
4282
0
        pe_parse_rich_signature(pe, block->base);
4283
0
        pe_parse_debug_directory(pe);
4284
4285
#if defined(HAVE_LIBCRYPTO) && !defined(BORINGSSL)
4286
        pe_parse_certificates(pe);
4287
#endif
4288
4289
0
        pe->imported_dlls = pe_parse_imports(pe);
4290
0
        pe->delay_imported_dlls = pe_parse_delayed_imports(pe);
4291
0
        pe_parse_exports(pe);
4292
4293
0
        break;
4294
0
      }
4295
0
    }
4296
0
  }
4297
4298
0
  return ERROR_SUCCESS;
4299
0
}
4300
4301
void free_dlls(IMPORTED_DLL* dll)
4302
0
{
4303
0
  IMPORTED_DLL* next_dll = NULL;
4304
0
  IMPORT_FUNCTION* func = NULL;
4305
0
  IMPORT_FUNCTION* next_func = NULL;
4306
4307
0
  while (dll)
4308
0
  {
4309
0
    if (dll->name)
4310
0
      yr_free(dll->name);
4311
4312
0
    func = dll->functions;
4313
4314
0
    while (func)
4315
0
    {
4316
0
      if (func->name)
4317
0
        yr_free(func->name);
4318
4319
0
      next_func = func->next;
4320
0
      yr_free(func);
4321
0
      func = next_func;
4322
0
    }
4323
4324
0
    next_dll = dll->next;
4325
0
    yr_free(dll);
4326
0
    dll = next_dll;
4327
0
  }
4328
0
}
4329
4330
int module_unload(YR_OBJECT* module_object)
4331
0
{
4332
0
  PE* pe = (PE*) module_object->data;
4333
4334
0
  if (pe == NULL)
4335
0
    return ERROR_SUCCESS;
4336
4337
0
  if (pe->hash_table != NULL)
4338
0
    yr_hash_table_destroy(
4339
0
        pe->hash_table, (YR_HASH_TABLE_FREE_VALUE_FUNC) yr_free);
4340
4341
0
  free_dlls(pe->imported_dlls);
4342
0
  free_dlls(pe->delay_imported_dlls);
4343
4344
0
  yr_free(pe);
4345
4346
0
  return ERROR_SUCCESS;
4347
0
}