Coverage Report

Created: 2023-09-25 07:12

/src/yara/libyara/exefiles.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
Copyright (c) 2007-2013. 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 <limits.h>
31
#include <yara/elf.h>
32
#include <yara/endian.h>
33
#include <yara/exec.h>
34
#include <yara/pe.h>
35
#include <yara/utils.h>
36
37
#ifndef NULL
38
#define NULL 0
39
#endif
40
41
#ifndef MIN
42
4.84k
#define MIN(x, y) ((x < y) ? (x) : (y))
43
#endif
44
45
PIMAGE_NT_HEADERS32 yr_get_pe_header(
46
    const uint8_t* buffer,
47
    size_t buffer_length)
48
7.33k
{
49
7.33k
  PIMAGE_DOS_HEADER mz_header;
50
7.33k
  PIMAGE_NT_HEADERS32 pe_header;
51
52
7.33k
  size_t headers_size = 0;
53
54
7.33k
  if (buffer_length < sizeof(IMAGE_DOS_HEADER))
55
431
    return NULL;
56
57
6.90k
  mz_header = (PIMAGE_DOS_HEADER) buffer;
58
59
6.90k
  if (yr_le16toh(mz_header->e_magic) != IMAGE_DOS_SIGNATURE)
60
755
    return NULL;
61
62
6.15k
  if ((int32_t) yr_le32toh(mz_header->e_lfanew) < 0)
63
32
    return NULL;
64
65
6.12k
  headers_size = yr_le32toh(mz_header->e_lfanew) +
66
6.12k
                 sizeof(pe_header->Signature) + sizeof(IMAGE_FILE_HEADER);
67
68
6.12k
  if (buffer_length < headers_size)
69
51
    return NULL;
70
71
6.06k
  pe_header = (PIMAGE_NT_HEADERS32)(buffer + yr_le32toh(mz_header->e_lfanew));
72
73
6.06k
  headers_size += sizeof(IMAGE_OPTIONAL_HEADER32);
74
75
6.06k
  if (yr_le32toh(pe_header->Signature) == IMAGE_NT_SIGNATURE &&
76
6.06k
      (yr_le16toh(pe_header->FileHeader.Machine) == IMAGE_FILE_MACHINE_I386 ||
77
6.02k
       yr_le16toh(pe_header->FileHeader.Machine) == IMAGE_FILE_MACHINE_AMD64) &&
78
6.06k
      buffer_length > headers_size)
79
844
  {
80
844
    return pe_header;
81
844
  }
82
5.22k
  else
83
5.22k
  {
84
5.22k
    return NULL;
85
5.22k
  }
86
6.06k
}
87
88
uint64_t yr_pe_rva_to_offset(
89
    PIMAGE_NT_HEADERS32 pe_header,
90
    uint64_t rva,
91
    size_t buffer_length)
92
844
{
93
844
  int i = 0;
94
844
  PIMAGE_SECTION_HEADER section;
95
844
  DWORD section_rva;
96
844
  DWORD section_offset;
97
98
844
  section = IMAGE_FIRST_SECTION(pe_header);
99
844
  section_rva = 0;
100
844
  section_offset = 0;
101
102
4.84k
  while (i < MIN(yr_le16toh(pe_header->FileHeader.NumberOfSections), 60))
103
4.11k
  {
104
4.11k
    if ((uint8_t*) section - (uint8_t*) pe_header +
105
4.11k
            sizeof(IMAGE_SECTION_HEADER) <
106
4.11k
        buffer_length)
107
4.00k
    {
108
4.00k
      if (rva >= yr_le32toh(section->VirtualAddress) &&
109
4.00k
          section_rva <= yr_le32toh(section->VirtualAddress))
110
830
      {
111
830
        section_rva = yr_le32toh(section->VirtualAddress);
112
830
        section_offset = yr_le32toh(section->PointerToRawData);
113
830
      }
114
115
4.00k
      section++;
116
4.00k
      i++;
117
4.00k
    }
118
116
    else
119
116
    {
120
116
      return 0;
121
116
    }
122
4.11k
  }
123
124
728
  return section_offset + (rva - section_rva);
125
844
}
126
127
int yr_get_elf_type(const uint8_t* buffer, size_t buffer_length)
128
6.49k
{
129
6.49k
  elf_ident_t* elf_ident;
130
131
6.49k
  if (buffer_length < sizeof(elf_ident_t))
132
25
    return 0;
133
134
6.46k
  elf_ident = (elf_ident_t*) buffer;
135
136
6.46k
  if (yr_le32toh(elf_ident->magic) != ELF_MAGIC)
137
5.39k
  {
138
5.39k
    return 0;
139
5.39k
  }
140
141
1.07k
  switch (elf_ident->_class)
142
1.07k
  {
143
396
  case ELF_CLASS_32:
144
396
    if (buffer_length < sizeof(elf32_header_t))
145
9
    {
146
9
      return 0;
147
9
    }
148
387
    break;
149
680
  case ELF_CLASS_64:
150
680
    if (buffer_length < sizeof(elf64_header_t))
151
4
    {
152
4
      return 0;
153
4
    }
154
676
    break;
155
676
  default:
156
    /* Unexpected class */
157
1
    return 0;
158
1.07k
  }
159
160
1.06k
  return elf_ident->_class;
161
1.07k
}
162
163
static uint64_t yr_elf_rva_to_offset_32(
164
    elf32_header_t* elf_header,
165
    uint64_t rva,
166
    size_t buffer_length)
167
387
{
168
  // if the binary is an executable then prefer the program headers to resolve
169
  // the offset
170
387
  if (yr_le16toh(elf_header->type) == ELF_ET_EXEC)
171
164
  {
172
164
    int i;
173
164
    elf32_program_header_t* program;
174
164
    if (yr_le32toh(elf_header->ph_offset) == 0 ||
175
164
        yr_le16toh(elf_header->ph_entry_count == 0))
176
9
      return 0;
177
178
    // check to prevent integer wraps
179
155
    if (ULONG_MAX - yr_le16toh(elf_header->ph_entry_count) <
180
155
        sizeof(elf32_program_header_t) * yr_le16toh(elf_header->ph_entry_count))
181
0
      return 0;
182
183
    // check that 'ph_offset' doesn't wrap when added to the
184
    // size of entries.
185
155
    if (ULONG_MAX - yr_le32toh(elf_header->ph_offset) <
186
155
        sizeof(elf32_program_header_t) * yr_le16toh(elf_header->ph_entry_count))
187
0
      return 0;
188
189
    // ensure we don't exceed the buffer size
190
155
    if (yr_le32toh(elf_header->ph_offset) +
191
155
            sizeof(elf32_program_header_t) *
192
155
                yr_le16toh(elf_header->ph_entry_count) >
193
155
        buffer_length)
194
73
      return 0;
195
196
82
    program =
197
82
        (elf32_program_header_t*) ((uint8_t*) elf_header + yr_le32toh(elf_header->ph_offset));
198
199
572
    for (i = 0; i < yr_le16toh(elf_header->ph_entry_count); i++)
200
520
    {
201
520
      if (rva >= yr_le32toh(program->virt_addr) &&
202
520
          rva < yr_le32toh(program->virt_addr) + yr_le32toh(program->mem_size))
203
30
      {
204
30
        return yr_le32toh(program->offset) +
205
30
               (rva - yr_le32toh(program->virt_addr));
206
30
      }
207
208
490
      program++;
209
490
    }
210
82
  }
211
223
  else
212
223
  {
213
223
    int i;
214
223
    elf32_section_header_t* section;
215
216
223
    if (yr_le32toh(elf_header->sh_offset) == 0 ||
217
223
        yr_le16toh(elf_header->sh_entry_count == 0))
218
4
      return 0;
219
220
    // check to prevent integer wraps
221
222
219
    if (ULONG_MAX - yr_le16toh(elf_header->sh_entry_count) <
223
219
        sizeof(elf32_section_header_t) * yr_le16toh(elf_header->sh_entry_count))
224
0
      return 0;
225
226
    // check that 'sh_offset' doesn't wrap when added to the
227
    // size of entries.
228
229
219
    if (ULONG_MAX - yr_le32toh(elf_header->sh_offset) <
230
219
        sizeof(elf32_section_header_t) * yr_le16toh(elf_header->sh_entry_count))
231
0
      return 0;
232
233
219
    if (yr_le32toh(elf_header->sh_offset) +
234
219
            sizeof(elf32_section_header_t) *
235
219
                yr_le16toh(elf_header->sh_entry_count) >
236
219
        buffer_length)
237
80
      return 0;
238
239
139
    section = (elf32_section_header_t*)
240
139
      ((unsigned char*) elf_header + yr_le32toh(elf_header->sh_offset));
241
242
2.56k
    for (i = 0; i < yr_le16toh(elf_header->sh_entry_count); i++)
243
2.49k
    {
244
2.49k
      if (yr_le32toh(section->type) != ELF_SHT_NULL &&
245
2.49k
          yr_le32toh(section->type) != ELF_SHT_NOBITS &&
246
2.49k
          rva >= yr_le32toh(section->addr) &&
247
2.49k
          rva < yr_le32toh(section->addr) + yr_le32toh(section->size))
248
75
      {
249
        // prevent integer wrapping with the return value
250
251
75
        if (ULONG_MAX - yr_le32toh(section->offset) <
252
75
            (rva - yr_le32toh(section->addr)))
253
0
          return 0;
254
75
        else
255
75
          return yr_le32toh(section->offset) +
256
75
                 (rva - yr_le32toh(section->addr));
257
75
      }
258
259
2.42k
      section++;
260
2.42k
    }
261
139
  }
262
263
116
  return 0;
264
387
}
265
266
static uint64_t yr_elf_rva_to_offset_64(
267
    elf64_header_t* elf_header,
268
    uint64_t rva,
269
    size_t buffer_length)
270
676
{
271
  // if the binary is an executable then prefer the program headers to resolve
272
  // the offset
273
676
  if (yr_le16toh(elf_header->type) == ELF_ET_EXEC)
274
313
  {
275
313
    int i;
276
313
    elf64_program_header_t* program;
277
313
    if (yr_le64toh(elf_header->ph_offset) == 0 ||
278
313
        yr_le16toh(elf_header->ph_entry_count == 0))
279
10
      return 0;
280
281
    // check that 'ph_offset' doesn't wrap when added to the
282
    // size of entries.
283
303
    if (ULONG_MAX - yr_le64toh(elf_header->ph_offset) <
284
303
        sizeof(elf64_program_header_t) * yr_le16toh(elf_header->ph_entry_count))
285
17
      return 0;
286
287
    // ensure we don't exceed the buffer size
288
286
    if (yr_le64toh(elf_header->ph_offset) +
289
286
            sizeof(elf64_program_header_t) *
290
286
                yr_le16toh(elf_header->ph_entry_count) >
291
286
        buffer_length)
292
137
      return 0;
293
294
149
    program =
295
149
        (elf64_program_header_t*) ((uint8_t*) elf_header + yr_le64toh(elf_header->ph_offset));
296
297
813
    for (i = 0; i < yr_le16toh(elf_header->ph_entry_count); i++)
298
705
    {
299
705
      if (rva >= yr_le64toh(program->virt_addr) &&
300
705
          rva < yr_le64toh(program->virt_addr) + yr_le64toh(program->mem_size))
301
41
      {
302
41
        return yr_le64toh(program->offset) +
303
41
               (rva - yr_le64toh(program->virt_addr));
304
41
      }
305
306
664
      program++;
307
664
    }
308
149
  }
309
363
  else
310
363
  {
311
363
    int i;
312
363
    elf64_section_header_t* section;
313
314
363
    if (yr_le64toh(elf_header->sh_offset) == 0 ||
315
363
        yr_le16toh(elf_header->sh_entry_count) == 0)
316
3
      return 0;
317
318
    // check that 'sh_offset' doesn't wrap when added to the
319
    // size of entries.
320
360
    if (ULONG_MAX - yr_le64toh(elf_header->sh_offset) <
321
360
        sizeof(elf64_section_header_t) * yr_le16toh(elf_header->sh_entry_count))
322
21
      return 0;
323
324
339
    if (yr_le64toh(elf_header->sh_offset) +
325
339
            sizeof(elf64_section_header_t) *
326
339
                yr_le16toh(elf_header->sh_entry_count) >
327
339
        buffer_length)
328
140
      return 0;
329
330
199
    section =
331
199
        (elf64_section_header_t*) ((uint8_t*) elf_header + yr_le64toh(elf_header->sh_offset));
332
333
2.71k
    for (i = 0; i < yr_le16toh(elf_header->sh_entry_count); i++)
334
2.61k
    {
335
2.61k
      if (yr_le32toh(section->type) != ELF_SHT_NULL &&
336
2.61k
          yr_le32toh(section->type) != ELF_SHT_NOBITS &&
337
2.61k
          rva >= yr_le64toh(section->addr) &&
338
2.61k
          rva < yr_le64toh(section->addr) + yr_le64toh(section->size))
339
94
      {
340
94
        return yr_le64toh(section->offset) + (rva - yr_le64toh(section->addr));
341
94
      }
342
343
2.51k
      section++;
344
2.51k
    }
345
199
  }
346
347
213
  return 0;
348
676
}
349
350
uint64_t yr_get_entry_point_offset(const uint8_t* buffer, size_t buffer_length)
351
7.33k
{
352
7.33k
  PIMAGE_NT_HEADERS32 pe_header;
353
7.33k
  elf32_header_t* elf_header32;
354
7.33k
  elf64_header_t* elf_header64;
355
356
7.33k
  pe_header = yr_get_pe_header(buffer, buffer_length);
357
358
7.33k
  if (pe_header != NULL)
359
844
  {
360
844
    return yr_pe_rva_to_offset(
361
844
        pe_header,
362
844
        yr_le32toh(pe_header->OptionalHeader.AddressOfEntryPoint),
363
844
        buffer_length - ((uint8_t*) pe_header - buffer));
364
844
  }
365
366
6.49k
  switch (yr_get_elf_type(buffer, buffer_length))
367
6.49k
  {
368
387
  case ELF_CLASS_32:
369
387
    elf_header32 = (elf32_header_t*) buffer;
370
387
    return yr_elf_rva_to_offset_32(
371
387
        elf_header32, yr_le32toh(elf_header32->entry), buffer_length);
372
373
676
  case ELF_CLASS_64:
374
676
    elf_header64 = (elf64_header_t*) buffer;
375
676
    return yr_elf_rva_to_offset_64(
376
676
        elf_header64, yr_le64toh(elf_header64->entry), buffer_length);
377
6.49k
  }
378
379
5.43k
  return YR_UNDEFINED;
380
6.49k
}
381
382
uint64_t yr_get_entry_point_address(
383
    const uint8_t* buffer,
384
    size_t buffer_length,
385
    uint64_t base_address)
386
0
{
387
0
  PIMAGE_NT_HEADERS32 pe_header;
388
389
0
  elf32_header_t* elf_header32;
390
0
  elf64_header_t* elf_header64;
391
392
0
  pe_header = yr_get_pe_header(buffer, buffer_length);
393
394
  // If file is PE but not a DLL.
395
396
0
  if (pe_header != NULL &&
397
0
      !(pe_header->FileHeader.Characteristics & IMAGE_FILE_DLL))
398
0
    return base_address + pe_header->OptionalHeader.AddressOfEntryPoint;
399
400
  // If file is executable ELF, not shared library.
401
402
0
  switch (yr_get_elf_type(buffer, buffer_length))
403
0
  {
404
0
  case ELF_CLASS_32:
405
0
    elf_header32 = (elf32_header_t*) buffer;
406
407
0
    if (elf_header32->type == ELF_ET_EXEC)
408
0
      return elf_header32->entry;
409
410
0
    break;
411
412
0
  case ELF_CLASS_64:
413
0
    elf_header64 = (elf64_header_t*) buffer;
414
415
0
    if (elf_header64->type == ELF_ET_EXEC)
416
0
      return elf_header64->entry;
417
418
0
    break;
419
0
  }
420
421
0
  return YR_UNDEFINED;
422
0
}