Coverage Report

Created: 2023-09-25 07:15

/src/yara/libyara/modules/macho/macho.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 <yara/endian.h>
31
#include <yara/macho.h>
32
#include <yara/mem.h>
33
#include <yara/modules.h>
34
35
#define MODULE_NAME macho
36
37
// Check for Mach-O binary magic constant.
38
39
int is_macho_file_block(const uint32_t* magic)
40
4.08k
{
41
4.08k
  return *magic == MH_MAGIC || *magic == MH_CIGAM || *magic == MH_MAGIC_64 ||
42
4.08k
         *magic == MH_CIGAM_64;
43
4.08k
}
44
45
// Check if file is for 32-bit architecture.
46
47
int macho_is_32(const uint8_t* magic)
48
63.1k
{
49
  // Magic must be [CE]FAEDFE or FEEDFA[CE].
50
63.1k
  return magic[0] == 0xce || magic[3] == 0xce;
51
63.1k
}
52
53
// Check if file is for big-endian architecture.
54
55
int macho_is_big(const uint8_t* magic)
56
0
{
57
  // Magic must be [FE]EDFACE or [FE]EDFACF.
58
0
  return magic[0] == 0xfe;
59
0
}
60
61
// Check for Mach-O fat binary magic constant.
62
63
int is_fat_macho_file_block(const uint32_t* magic)
64
2.92k
{
65
2.92k
  return *magic == FAT_MAGIC || *magic == FAT_CIGAM || *magic == FAT_MAGIC_64 ||
66
2.92k
         *magic == FAT_CIGAM_64;
67
2.92k
}
68
69
// Check if file is 32-bit fat file.
70
71
int macho_fat_is_32(const uint8_t* magic)
72
262k
{
73
  // Magic must be CAFEBA[BE].
74
262k
  return magic[3] == 0xbe;
75
262k
}
76
77
static int should_swap_bytes(const uint32_t magic)
78
735k
{
79
735k
  return magic == MH_CIGAM || magic == MH_CIGAM_64 || magic == FAT_CIGAM ||
80
735k
         magic == FAT_CIGAM_64;
81
735k
}
82
83
static void swap_mach_header(yr_mach_header_64_t* mh)
84
3.95k
{
85
  // Don't swap the magic number so we can tell if swapping is needed
86
3.95k
  mh->cputype = yr_bswap32(mh->cputype);
87
3.95k
  mh->cpusubtype = yr_bswap32(mh->cpusubtype);
88
3.95k
  mh->filetype = yr_bswap32(mh->filetype);
89
3.95k
  mh->ncmds = yr_bswap32(mh->ncmds);
90
3.95k
  mh->sizeofcmds = yr_bswap32(mh->sizeofcmds);
91
3.95k
  mh->flags = yr_bswap32(mh->flags);
92
93
3.95k
  if (!macho_is_32((const uint8_t*) &mh->magic))
94
2.19k
    mh->reserved = yr_bswap32(mh->reserved);
95
3.95k
}
96
97
static void swap_load_command(yr_load_command_t* lc)
98
739k
{
99
739k
  lc->cmd = yr_bswap32(lc->cmd);
100
739k
  lc->cmdsize = yr_bswap32(lc->cmdsize);
101
739k
}
102
103
static void swap_segment_command(yr_segment_command_32_t* sg)
104
48.9k
{
105
48.9k
  sg->cmd = yr_bswap32(sg->cmd);
106
48.9k
  sg->cmdsize = yr_bswap32(sg->cmdsize);
107
48.9k
  sg->vmaddr = yr_bswap32(sg->vmaddr);
108
48.9k
  sg->vmsize = yr_bswap32(sg->vmsize);
109
48.9k
  sg->fileoff = yr_bswap32(sg->fileoff);
110
48.9k
  sg->filesize = yr_bswap32(sg->filesize);
111
48.9k
  sg->maxprot = yr_bswap32(sg->maxprot);
112
48.9k
  sg->initprot = yr_bswap32(sg->initprot);
113
48.9k
  sg->nsects = yr_bswap32(sg->nsects);
114
48.9k
  sg->flags = yr_bswap32(sg->flags);
115
48.9k
}
116
117
static void swap_segment_command_64(yr_segment_command_64_t* sg)
118
291k
{
119
291k
  sg->cmd = yr_bswap32(sg->cmd);
120
291k
  sg->cmdsize = yr_bswap32(sg->cmdsize);
121
291k
  sg->vmaddr = yr_bswap64(sg->vmaddr);
122
291k
  sg->vmsize = yr_bswap64(sg->vmsize);
123
291k
  sg->fileoff = yr_bswap64(sg->fileoff);
124
291k
  sg->filesize = yr_bswap64(sg->filesize);
125
291k
  sg->maxprot = yr_bswap32(sg->maxprot);
126
291k
  sg->initprot = yr_bswap32(sg->initprot);
127
291k
  sg->nsects = yr_bswap32(sg->nsects);
128
291k
  sg->flags = yr_bswap32(sg->flags);
129
291k
}
130
131
static void swap_section(yr_section_32_t* sec)
132
26.4k
{
133
26.4k
  sec->addr = yr_bswap32(sec->addr);
134
26.4k
  sec->size = yr_bswap32(sec->size);
135
26.4k
  sec->offset = yr_bswap32(sec->offset);
136
26.4k
  sec->align = yr_bswap32(sec->align);
137
26.4k
  sec->reloff = yr_bswap32(sec->reloff);
138
26.4k
  sec->nreloc = yr_bswap32(sec->nreloc);
139
26.4k
  sec->flags = yr_bswap32(sec->flags);
140
26.4k
  sec->reserved1 = yr_bswap32(sec->reserved1);
141
26.4k
  sec->reserved2 = yr_bswap32(sec->reserved2);
142
26.4k
}
143
144
static void swap_section_64(yr_section_64_t* sec)
145
25.0k
{
146
25.0k
  sec->addr = yr_bswap64(sec->addr);
147
25.0k
  sec->size = yr_bswap64(sec->size);
148
25.0k
  sec->offset = yr_bswap32(sec->offset);
149
25.0k
  sec->align = yr_bswap32(sec->align);
150
25.0k
  sec->reloff = yr_bswap32(sec->reloff);
151
25.0k
  sec->nreloc = yr_bswap32(sec->nreloc);
152
25.0k
  sec->flags = yr_bswap32(sec->flags);
153
25.0k
  sec->reserved1 = yr_bswap32(sec->reserved1);
154
25.0k
  sec->reserved2 = yr_bswap32(sec->reserved2);
155
25.0k
  sec->reserved3 = yr_bswap32(sec->reserved3);
156
25.0k
}
157
158
static void swap_entry_point_command(yr_entry_point_command_t* ep_command)
159
1.04k
{
160
1.04k
  ep_command->cmd = yr_bswap32(ep_command->cmd);
161
1.04k
  ep_command->cmdsize = yr_bswap32(ep_command->cmdsize);
162
1.04k
  ep_command->entryoff = yr_bswap64(ep_command->entryoff);
163
1.04k
  ep_command->stacksize = yr_bswap64(ep_command->stacksize);
164
1.04k
}
165
166
// Convert virtual address to file offset. Segments have to be already loaded.
167
168
bool macho_rva_to_offset(uint64_t address, uint64_t* result, YR_OBJECT* object)
169
7.34k
{
170
7.34k
  uint64_t segment_count = yr_get_integer(object, "number_of_segments");
171
172
930k
  for (int i = 0; i < segment_count; i++)
173
924k
  {
174
924k
    uint64_t start = yr_get_integer(object, "segments[%i].vmaddr", i);
175
924k
    uint64_t end = start + yr_get_integer(object, "segments[%i].vmsize", i);
176
177
924k
    if (address >= start && address < end)
178
1.80k
    {
179
1.80k
      uint64_t fileoff = yr_get_integer(object, "segments[%i].fileoff", i);
180
1.80k
      *result = fileoff + (address - start);
181
1.80k
      return true;
182
1.80k
    }
183
924k
  }
184
185
5.54k
  return false;
186
7.34k
}
187
188
// Convert file offset to virtual address. Segments have to be already loaded.
189
190
int macho_offset_to_rva(uint64_t offset, uint64_t* result, YR_OBJECT* object)
191
0
{
192
0
  uint64_t segment_count = yr_get_integer(object, "number_of_segments");
193
194
0
  for (int i = 0; i < segment_count; i++)
195
0
  {
196
0
    uint64_t start = yr_get_integer(object, "segments[%i].fileoff", i);
197
0
    uint64_t end = start + yr_get_integer(object, "segments[%i].filesize", i);
198
199
0
    if (offset >= start && offset < end)
200
0
    {
201
0
      uint64_t vmaddr = yr_get_integer(object, "segments[%i].vmaddr", i);
202
0
      *result = vmaddr + (offset - start);
203
0
      return true;
204
0
    }
205
0
  }
206
207
0
  return false;
208
0
}
209
210
// Get entry point address from LC_UNIXTHREAD load command.
211
void macho_handle_unixthread(
212
    const uint8_t* data,
213
    size_t size,
214
    YR_OBJECT* object,
215
    YR_SCAN_CONTEXT* context)
216
11.0k
{
217
11.0k
  int should_swap = should_swap_bytes(yr_get_integer(object, "magic"));
218
11.0k
  bool is64 = false;
219
220
11.0k
  if (size < sizeof(yr_thread_command_t))
221
482
    return;
222
223
  // command_size is the size indicated in yr_thread_command_t structure, but
224
  // limited to the data's size because we can't rely on the structure having a
225
  // valid size.
226
10.6k
  uint32_t command_size = yr_min(size, ((yr_thread_command_t*) data)->cmdsize);
227
228
  // command_size should be at least the size of yr_thread_command_t.
229
10.6k
  if (command_size < sizeof(yr_thread_command_t))
230
2.40k
    return;
231
232
  // command_size includes the size of yr_thread_command_t and the thread
233
  // state structure that follows, let's compute the size of the thread state
234
  // structure.
235
8.21k
  size_t thread_state_size = command_size - sizeof(yr_thread_command_t);
236
237
  // The structure that contains the thread state starts where
238
  // yr_thread_command_t ends.
239
8.21k
  const void* thread_state = data + sizeof(yr_thread_command_t);
240
241
8.21k
  uint64_t address = 0;
242
243
8.21k
  switch (yr_get_integer(object, "cputype"))
244
8.21k
  {
245
1.55k
  case CPU_TYPE_MC680X0:
246
1.55k
  {
247
1.55k
    if (thread_state_size >= sizeof(yr_m68k_thread_state_t))
248
1.13k
      address = ((yr_m68k_thread_state_t*) thread_state)->pc;
249
1.55k
    break;
250
0
  }
251
538
  case CPU_TYPE_MC88000:
252
538
  {
253
538
    if (thread_state_size >= sizeof(yr_m88k_thread_state_t))
254
249
      address = ((yr_m88k_thread_state_t*) thread_state)->xip;
255
538
    break;
256
0
  }
257
603
  case CPU_TYPE_SPARC:
258
603
  {
259
603
    if (thread_state_size >= sizeof(yr_sparc_thread_state_t))
260
289
      address = ((yr_sparc_thread_state_t*) thread_state)->pc;
261
603
    break;
262
0
  }
263
672
  case CPU_TYPE_POWERPC:
264
672
  {
265
672
    if (thread_state_size >= sizeof(yr_ppc_thread_state_t))
266
307
      address = ((yr_ppc_thread_state_t*) thread_state)->srr0;
267
672
    break;
268
0
  }
269
927
  case CPU_TYPE_X86:
270
927
  {
271
927
    if (thread_state_size >= sizeof(yr_x86_thread_state_t))
272
648
      address = ((yr_x86_thread_state_t*) thread_state)->eip;
273
927
    break;
274
0
  }
275
987
  case CPU_TYPE_ARM:
276
987
  {
277
987
    if (thread_state_size >= sizeof(yr_arm_thread_state_t))
278
307
      address = ((yr_arm_thread_state_t*) thread_state)->pc;
279
987
    break;
280
0
  }
281
762
  case CPU_TYPE_X86_64:
282
762
  {
283
762
    if (thread_state_size >= sizeof(yr_x86_thread_state64_t))
284
313
      address = ((yr_x86_thread_state64_t*) thread_state)->rip;
285
762
    is64 = true;
286
762
    break;
287
0
  }
288
737
  case CPU_TYPE_ARM64:
289
737
  {
290
737
    if (thread_state_size >= sizeof(yr_arm_thread_state64_t))
291
416
      address = ((yr_arm_thread_state64_t*) thread_state)->pc;
292
737
    is64 = true;
293
737
    break;
294
0
  }
295
570
  case CPU_TYPE_POWERPC64:
296
570
  {
297
570
    if (thread_state_size >= sizeof(yr_ppc_thread_state64_t))
298
281
      address = ((yr_ppc_thread_state64_t*) thread_state)->srr0;
299
570
    is64 = true;
300
570
    break;
301
0
  }
302
303
868
  default:
304
868
    return;
305
8.21k
  }
306
307
7.34k
  if (should_swap)
308
6.94k
  {
309
6.94k
    if (is64)
310
2.06k
      address = yr_bswap64(address);
311
4.87k
    else
312
4.87k
      address = yr_bswap32(address);
313
6.94k
  }
314
315
7.34k
  if (context->flags & SCAN_FLAGS_PROCESS_MEMORY)
316
0
  {
317
0
    yr_set_integer(address, object, "entry_point");
318
0
  }
319
7.34k
  else
320
7.34k
  {
321
7.34k
    uint64_t offset = 0;
322
7.34k
    if (macho_rva_to_offset(address, &offset, object))
323
1.80k
    {
324
1.80k
      yr_set_integer(offset, object, "entry_point");
325
1.80k
    }
326
7.34k
  }
327
7.34k
}
328
329
// Get entry point offset and stack-size from LC_MAIN load command.
330
331
void macho_handle_main(
332
    void* data,
333
    size_t size,
334
    YR_OBJECT* object,
335
    YR_SCAN_CONTEXT* context)
336
1.56k
{
337
1.56k
  yr_entry_point_command_t ep_command;
338
339
1.56k
  if (size < sizeof(yr_entry_point_command_t))
340
170
    return;
341
342
1.39k
  memcpy(&ep_command, data, sizeof(yr_entry_point_command_t));
343
344
1.39k
  if (should_swap_bytes(yr_get_integer(object, "magic")))
345
1.04k
    swap_entry_point_command(&ep_command);
346
347
1.39k
  if (context->flags & SCAN_FLAGS_PROCESS_MEMORY)
348
0
  {
349
0
    uint64_t address = 0;
350
0
    if (macho_offset_to_rva(ep_command.entryoff, &address, object))
351
0
    {
352
0
      yr_set_integer(address, object, "entry_point");
353
0
    }
354
0
  }
355
1.39k
  else
356
1.39k
  {
357
1.39k
    yr_set_integer(ep_command.entryoff, object, "entry_point");
358
1.39k
  }
359
1.39k
  yr_set_integer(ep_command.stacksize, object, "stack_size");
360
1.39k
}
361
362
// Load segment and its sections.
363
364
void macho_handle_segment(
365
    const uint8_t* data,
366
    size_t size,
367
    const unsigned i,
368
    YR_OBJECT* object)
369
51.8k
{
370
51.8k
  if (size < sizeof(yr_segment_command_32_t))
371
1.37k
    return;
372
373
50.4k
  yr_segment_command_32_t sg;
374
375
50.4k
  memcpy(&sg, data, sizeof(yr_segment_command_32_t));
376
377
50.4k
  int should_swap = should_swap_bytes(yr_get_integer(object, "magic"));
378
379
50.4k
  if (should_swap)
380
48.9k
    swap_segment_command(&sg);
381
382
50.4k
  yr_set_sized_string(
383
50.4k
      sg.segname, strnlen(sg.segname, 16), object, "segments[%i].segname", i);
384
385
50.4k
  yr_set_integer(sg.vmaddr, object, "segments[%i].vmaddr", i);
386
50.4k
  yr_set_integer(sg.vmsize, object, "segments[%i].vmsize", i);
387
50.4k
  yr_set_integer(sg.fileoff, object, "segments[%i].fileoff", i);
388
50.4k
  yr_set_integer(sg.filesize, object, "segments[%i].fsize", i);
389
50.4k
  yr_set_integer(sg.maxprot, object, "segments[%i].maxprot", i);
390
50.4k
  yr_set_integer(sg.initprot, object, "segments[%i].initprot", i);
391
50.4k
  yr_set_integer(sg.nsects, object, "segments[%i].nsects", i);
392
50.4k
  yr_set_integer(sg.flags, object, "segments[%i].flags", i);
393
394
50.4k
  uint64_t parsed_size = sizeof(yr_segment_command_32_t);
395
396
  // The array of yr_section_32_t starts where yr_segment_command_32_t ends.
397
50.4k
  yr_section_32_t* sections =
398
50.4k
      (yr_section_32_t*) (data + sizeof(yr_segment_command_32_t));
399
400
77.3k
  for (unsigned j = 0; j < sg.nsects; ++j)
401
76.0k
  {
402
76.0k
    yr_section_32_t sec;
403
404
76.0k
    parsed_size += sizeof(yr_section_32_t);
405
406
76.0k
    if (sg.cmdsize < parsed_size)
407
49.1k
      break;
408
409
26.8k
    memcpy(&sec, &sections[j], sizeof(yr_section_32_t));
410
411
26.8k
    if (should_swap)
412
26.4k
      swap_section(&sec);
413
414
26.8k
    yr_set_sized_string(
415
26.8k
        sec.segname,
416
26.8k
        strnlen(sec.segname, 16),
417
26.8k
        object,
418
26.8k
        "segments[%i].sections[%i].segname",
419
26.8k
        i,
420
26.8k
        j);
421
422
26.8k
    yr_set_sized_string(
423
26.8k
        sec.sectname,
424
26.8k
        strnlen(sec.sectname, 16),
425
26.8k
        object,
426
26.8k
        "segments[%i].sections[%i].sectname",
427
26.8k
        i,
428
26.8k
        j);
429
430
26.8k
    yr_set_integer(sec.addr, object, "segments[%i].sections[%i].addr", i, j);
431
432
26.8k
    yr_set_integer(sec.size, object, "segments[%i].sections[%i].size", i, j);
433
434
26.8k
    yr_set_integer(sec.offset, object, "segments[%i].sections[%i].offset", i, j);
435
436
26.8k
    yr_set_integer(sec.align, object, "segments[%i].sections[%i].align", i, j);
437
438
26.8k
    yr_set_integer(sec.reloff, object, "segments[%i].sections[%i].reloff", i, j);
439
440
26.8k
    yr_set_integer(sec.nreloc, object, "segments[%i].sections[%i].nreloc", i, j);
441
442
26.8k
    yr_set_integer(sec.flags, object, "segments[%i].sections[%i].flags", i, j);
443
444
26.8k
    yr_set_integer(
445
26.8k
        sec.reserved1, object, "segments[%i].sections[%i].reserved1", i, j);
446
447
26.8k
    yr_set_integer(
448
26.8k
        sec.reserved2, object, "segments[%i].sections[%i].reserved2", i, j);
449
26.8k
  }
450
50.4k
}
451
452
void macho_handle_segment_64(
453
    const uint8_t* data,
454
    size_t size,
455
    const unsigned i,
456
    YR_OBJECT* object)
457
648k
{
458
648k
  if (size < sizeof(yr_segment_command_64_t))
459
6.48k
    return;
460
461
642k
  yr_segment_command_64_t sg;
462
463
642k
  memcpy(&sg, data, sizeof(yr_segment_command_64_t));
464
465
642k
  int should_swap = should_swap_bytes(yr_get_integer(object, "magic"));
466
467
642k
  if (should_swap)
468
291k
    swap_segment_command_64(&sg);
469
470
642k
  yr_set_sized_string(
471
642k
      sg.segname, strnlen(sg.segname, 16), object, "segments[%i].segname", i);
472
473
642k
  yr_set_integer(sg.vmaddr, object, "segments[%i].vmaddr", i);
474
642k
  yr_set_integer(sg.vmsize, object, "segments[%i].vmsize", i);
475
642k
  yr_set_integer(sg.fileoff, object, "segments[%i].fileoff", i);
476
642k
  yr_set_integer(sg.filesize, object, "segments[%i].fsize", i);
477
642k
  yr_set_integer(sg.maxprot, object, "segments[%i].maxprot", i);
478
642k
  yr_set_integer(sg.initprot, object, "segments[%i].initprot", i);
479
642k
  yr_set_integer(sg.nsects, object, "segments[%i].nsects", i);
480
642k
  yr_set_integer(sg.flags, object, "segments[%i].flags", i);
481
482
642k
  uint64_t parsed_size = sizeof(yr_segment_command_64_t);
483
484
642k
  yr_section_64_t sec;
485
486
669k
  for (unsigned j = 0; j < sg.nsects; ++j)
487
668k
  {
488
668k
    parsed_size += sizeof(yr_section_64_t);
489
490
668k
    if (sg.cmdsize < parsed_size)
491
641k
      break;
492
493
27.0k
    memcpy(
494
27.0k
        &sec,
495
27.0k
        data + sizeof(yr_segment_command_64_t) + (j * sizeof(yr_section_64_t)),
496
27.0k
        sizeof(yr_section_64_t));
497
498
27.0k
    if (should_swap)
499
25.0k
      swap_section_64(&sec);
500
501
27.0k
    yr_set_sized_string(
502
27.0k
        sec.segname,
503
27.0k
        strnlen(sec.segname, 16),
504
27.0k
        object,
505
27.0k
        "segments[%i].sections[%i].segname",
506
27.0k
        i,
507
27.0k
        j);
508
509
27.0k
    yr_set_sized_string(
510
27.0k
        sec.sectname,
511
27.0k
        strnlen(sec.sectname, 16),
512
27.0k
        object,
513
27.0k
        "segments[%i].sections[%i].sectname",
514
27.0k
        i,
515
27.0k
        j);
516
517
27.0k
    yr_set_integer(sec.addr, object, "segments[%i].sections[%i].addr", i, j);
518
519
27.0k
    yr_set_integer(sec.size, object, "segments[%i].sections[%i].size", i, j);
520
521
27.0k
    yr_set_integer(sec.offset, object, "segments[%i].sections[%i].offset", i, j);
522
523
27.0k
    yr_set_integer(sec.align, object, "segments[%i].sections[%i].align", i, j);
524
525
27.0k
    yr_set_integer(sec.reloff, object, "segments[%i].sections[%i].reloff", i, j);
526
527
27.0k
    yr_set_integer(sec.nreloc, object, "segments[%i].sections[%i].nreloc", i, j);
528
529
27.0k
    yr_set_integer(sec.flags, object, "segments[%i].sections[%i].flags", i, j);
530
531
27.0k
    yr_set_integer(
532
27.0k
        sec.reserved1, object, "segments[%i].sections[%i].reserved1", i, j);
533
534
27.0k
    yr_set_integer(
535
27.0k
        sec.reserved2, object, "segments[%i].sections[%i].reserved2", i, j);
536
537
27.0k
    yr_set_integer(
538
27.0k
        sec.reserved3, object, "segments[%i].sections[%i].reserved3", i, j);
539
27.0k
  }
540
642k
}
541
542
// Parse Mach-O file.
543
544
void macho_parse_file(
545
    const uint8_t* data,
546
    const uint64_t size,
547
    YR_OBJECT* object,
548
    YR_SCAN_CONTEXT* context)
549
56.2k
{
550
  // Size must be large enough the hold yr_mach_header_64_t, which is larger
551
  // than yr_mach_header_32_t.
552
56.2k
  if (size < sizeof(yr_mach_header_64_t))
553
26.6k
    return;
554
555
29.5k
  size_t header_size = macho_is_32(data) ? sizeof(yr_mach_header_32_t)
556
29.5k
                                         : sizeof(yr_mach_header_64_t);
557
558
  // yr_mach_header_64_t is used for storing the header for both for 32-bits and
559
  // 64-bits files. yr_mach_header_64_t is exactly like yr_mach_header_32_t
560
  // but with an extra "reserved" field at the end.
561
29.5k
  yr_mach_header_64_t header;
562
563
29.5k
  memcpy(&header, data, header_size);
564
565
29.5k
  int should_swap = should_swap_bytes(header.magic);
566
567
29.5k
  if (should_swap)
568
3.95k
    swap_mach_header(&header);
569
570
29.5k
  yr_set_integer(header.magic, object, "magic");
571
29.5k
  yr_set_integer(header.cputype, object, "cputype");
572
29.5k
  yr_set_integer(header.cpusubtype, object, "cpusubtype");
573
29.5k
  yr_set_integer(header.filetype, object, "filetype");
574
29.5k
  yr_set_integer(header.ncmds, object, "ncmds");
575
29.5k
  yr_set_integer(header.sizeofcmds, object, "sizeofcmds");
576
29.5k
  yr_set_integer(header.flags, object, "flags");
577
578
  // The "reserved" field exists only in 64 bits files.
579
29.5k
  if (!macho_is_32(data))
580
27.1k
    yr_set_integer(header.reserved, object, "reserved");
581
582
  // The first command parsing pass handles only segments.
583
29.5k
  uint64_t seg_count = 0;
584
29.5k
  uint64_t parsed_size = header_size;
585
29.5k
  uint8_t* command = (uint8_t*) (data + header_size);
586
587
29.5k
  yr_load_command_t command_struct;
588
589
761k
  for (unsigned i = 0; i < header.ncmds; i++)
590
758k
  {
591
758k
    if (data + size < command + sizeof(yr_load_command_t))
592
2.23k
      break;
593
594
756k
    memcpy(&command_struct, command, sizeof(yr_load_command_t));
595
596
756k
    if (should_swap)
597
369k
      swap_load_command(&command_struct);
598
599
756k
    if (size - parsed_size < command_struct.cmdsize)
600
23.4k
      break;
601
602
732k
    if (command_struct.cmdsize < sizeof(yr_load_command_t))
603
690
      break;
604
605
732k
    switch (command_struct.cmd)
606
732k
    {
607
51.8k
    case LC_SEGMENT:
608
51.8k
      macho_handle_segment(command, size - parsed_size, seg_count++, object);
609
51.8k
      break;
610
648k
    case LC_SEGMENT_64:
611
648k
      macho_handle_segment_64(command, size - parsed_size, seg_count++, object);
612
648k
      break;
613
732k
    }
614
615
732k
    command += command_struct.cmdsize;
616
732k
    parsed_size += command_struct.cmdsize;
617
732k
  }
618
619
29.5k
  yr_set_integer(seg_count, object, "number_of_segments");
620
621
  // The second command parsing pass handles others, who use segment count.
622
29.5k
  parsed_size = header_size;
623
29.5k
  command = (uint8_t*) (data + header_size);
624
625
761k
  for (unsigned i = 0; i < header.ncmds; i++)
626
758k
  {
627
758k
    if (data + size < command + sizeof(yr_load_command_t))
628
2.23k
      break;
629
630
756k
    memcpy(&command_struct, command, sizeof(yr_load_command_t));
631
632
756k
    if (should_swap)
633
369k
      swap_load_command(&command_struct);
634
635
756k
    if (size - parsed_size < command_struct.cmdsize)
636
23.4k
      break;
637
638
732k
    if (command_struct.cmdsize < sizeof(yr_load_command_t))
639
690
      break;
640
641
732k
    switch (command_struct.cmd)
642
732k
    {
643
11.0k
    case LC_UNIXTHREAD:
644
11.0k
      macho_handle_unixthread(command, size - parsed_size, object, context);
645
11.0k
      break;
646
1.56k
    case LC_MAIN:
647
1.56k
      macho_handle_main(command, size - parsed_size, object, context);
648
1.56k
      break;
649
732k
    }
650
651
732k
    command += command_struct.cmdsize;
652
732k
    parsed_size += command_struct.cmdsize;
653
732k
  }
654
29.5k
}
655
656
// Parse Mach-O fat file.
657
658
void macho_load_fat_arch_header(
659
    const uint8_t* data,
660
    const uint64_t size,
661
    uint32_t num,
662
    yr_fat_arch_64_t* arch)
663
260k
{
664
260k
  if (macho_fat_is_32(data))
665
260k
  {
666
260k
    yr_fat_arch_32_t* arch32 =
667
260k
        (yr_fat_arch_32_t*) (data + sizeof(yr_fat_header_t) + (num * sizeof(yr_fat_arch_32_t)));
668
669
260k
    arch->cputype = yr_be32toh(arch32->cputype);
670
260k
    arch->cpusubtype = yr_be32toh(arch32->cpusubtype);
671
260k
    arch->offset = yr_be32toh(arch32->offset);
672
260k
    arch->size = yr_be32toh(arch32->size);
673
260k
    arch->align = yr_be32toh(arch32->align);
674
260k
    arch->reserved = 0;
675
260k
  }
676
532
  else
677
532
  {
678
532
    yr_fat_arch_64_t* arch64 =
679
532
        (yr_fat_arch_64_t*) (data + sizeof(yr_fat_header_t) + (num * sizeof(yr_fat_arch_64_t)));
680
681
532
    arch->cputype = yr_be32toh(arch64->cputype);
682
532
    arch->cpusubtype = yr_be32toh(arch64->cpusubtype);
683
532
    arch->offset = yr_be64toh(arch64->offset);
684
532
    arch->size = yr_be64toh(arch64->size);
685
532
    arch->align = yr_be32toh(arch64->align);
686
532
    arch->reserved = yr_be32toh(arch64->reserved);
687
532
  }
688
260k
}
689
690
void macho_parse_fat_file(
691
    const uint8_t* data,
692
    const uint64_t size,
693
    YR_OBJECT* object,
694
    YR_SCAN_CONTEXT* context)
695
1.26k
{
696
1.26k
  size_t fat_arch_sz = sizeof(yr_fat_arch_64_t);
697
698
1.26k
  if (macho_fat_is_32(data))
699
1.16k
    fat_arch_sz = sizeof(yr_fat_arch_32_t);
700
701
1.26k
  if (size < sizeof(yr_fat_header_t))
702
6
    return;
703
704
  /* All data in Mach-O fat binary headers are in big-endian byte order. */
705
706
1.26k
  const yr_fat_header_t* header = (yr_fat_header_t*) data;
707
1.26k
  yr_set_integer(yr_be32toh(header->magic), object, "fat_magic");
708
709
1.26k
  uint32_t count = yr_be32toh(header->nfat_arch);
710
1.26k
  yr_set_integer(count, object, "nfat_arch");
711
712
1.26k
  if (size < sizeof(yr_fat_header_t) + count * fat_arch_sz)
713
21
    return;
714
715
1.24k
  yr_fat_arch_64_t arch;
716
717
262k
  for (uint32_t i = 0; i < count; i++)
718
260k
  {
719
260k
    macho_load_fat_arch_header(data, size, i, &arch);
720
721
260k
    yr_set_integer(arch.cputype, object, "fat_arch[%i].cputype", i);
722
260k
    yr_set_integer(arch.cpusubtype, object, "fat_arch[%i].cpusubtype", i);
723
260k
    yr_set_integer(arch.offset, object, "fat_arch[%i].offset", i);
724
260k
    yr_set_integer(arch.size, object, "fat_arch[%i].size", i);
725
260k
    yr_set_integer(arch.align, object, "fat_arch[%i].align", i);
726
260k
    yr_set_integer(arch.reserved, object, "fat_arch[%i].reserved", i);
727
728
    // Check for integer overflow.
729
260k
    if (arch.offset + arch.size < arch.offset)
730
256
      continue;
731
732
260k
    if (size < arch.offset + arch.size)
733
205k
      continue;
734
735
    // Force 'file' array entry creation.
736
55.1k
    yr_set_integer(YR_UNDEFINED, object, "file[%i].magic", i);
737
738
    // Get specific Mach-O file data.
739
55.1k
    macho_parse_file(
740
55.1k
        data + arch.offset,
741
55.1k
        arch.size,
742
55.1k
        yr_get_object(object, "file[%i]", i),
743
55.1k
        context);
744
55.1k
  }
745
1.24k
}
746
747
// Sets all necessary Mach-O constants and definitions.
748
749
void macho_set_definitions(YR_OBJECT* object)
750
4.10k
{
751
  // Magic constants
752
753
4.10k
  yr_set_integer(MH_MAGIC, object, "MH_MAGIC");
754
4.10k
  yr_set_integer(MH_CIGAM, object, "MH_CIGAM");
755
4.10k
  yr_set_integer(MH_MAGIC_64, object, "MH_MAGIC_64");
756
4.10k
  yr_set_integer(MH_CIGAM_64, object, "MH_CIGAM_64");
757
758
  // Fat magic constants
759
760
4.10k
  yr_set_integer(FAT_MAGIC, object, "FAT_MAGIC");
761
4.10k
  yr_set_integer(FAT_CIGAM, object, "FAT_CIGAM");
762
4.10k
  yr_set_integer(FAT_MAGIC_64, object, "FAT_MAGIC_64");
763
4.10k
  yr_set_integer(FAT_CIGAM_64, object, "FAT_CIGAM_64");
764
765
  // 64-bit masks
766
767
4.10k
  yr_set_integer(CPU_ARCH_ABI64, object, "CPU_ARCH_ABI64");
768
4.10k
  yr_set_integer(CPU_SUBTYPE_LIB64, object, "CPU_SUBTYPE_LIB64");
769
770
  // CPU types
771
772
4.10k
  yr_set_integer(CPU_TYPE_MC680X0, object, "CPU_TYPE_MC680X0");
773
4.10k
  yr_set_integer(CPU_TYPE_X86, object, "CPU_TYPE_X86");
774
4.10k
  yr_set_integer(CPU_TYPE_X86, object, "CPU_TYPE_I386");
775
4.10k
  yr_set_integer(CPU_TYPE_X86_64, object, "CPU_TYPE_X86_64");
776
4.10k
  yr_set_integer(CPU_TYPE_MIPS, object, "CPU_TYPE_MIPS");
777
4.10k
  yr_set_integer(CPU_TYPE_MC98000, object, "CPU_TYPE_MC98000");
778
4.10k
  yr_set_integer(CPU_TYPE_ARM, object, "CPU_TYPE_ARM");
779
4.10k
  yr_set_integer(CPU_TYPE_ARM64, object, "CPU_TYPE_ARM64");
780
4.10k
  yr_set_integer(CPU_TYPE_MC88000, object, "CPU_TYPE_MC88000");
781
4.10k
  yr_set_integer(CPU_TYPE_SPARC, object, "CPU_TYPE_SPARC");
782
4.10k
  yr_set_integer(CPU_TYPE_POWERPC, object, "CPU_TYPE_POWERPC");
783
4.10k
  yr_set_integer(CPU_TYPE_POWERPC64, object, "CPU_TYPE_POWERPC64");
784
785
  // CPU sub-types
786
787
4.10k
  yr_set_integer(
788
4.10k
      CPU_SUBTYPE_INTEL_MODEL_ALL, object, "CPU_SUBTYPE_INTEL_MODEL_ALL");
789
4.10k
  yr_set_integer(CPU_SUBTYPE_386, object, "CPU_SUBTYPE_386");
790
4.10k
  yr_set_integer(CPU_SUBTYPE_386, object, "CPU_SUBTYPE_I386_ALL");
791
4.10k
  yr_set_integer(CPU_SUBTYPE_386, object, "CPU_SUBTYPE_X86_64_ALL");
792
4.10k
  yr_set_integer(CPU_SUBTYPE_486, object, "CPU_SUBTYPE_486");
793
4.10k
  yr_set_integer(CPU_SUBTYPE_486SX, object, "CPU_SUBTYPE_486SX");
794
4.10k
  yr_set_integer(CPU_SUBTYPE_586, object, "CPU_SUBTYPE_586");
795
4.10k
  yr_set_integer(CPU_SUBTYPE_PENT, object, "CPU_SUBTYPE_PENT");
796
4.10k
  yr_set_integer(CPU_SUBTYPE_PENTPRO, object, "CPU_SUBTYPE_PENTPRO");
797
4.10k
  yr_set_integer(CPU_SUBTYPE_PENTII_M3, object, "CPU_SUBTYPE_PENTII_M3");
798
4.10k
  yr_set_integer(CPU_SUBTYPE_PENTII_M5, object, "CPU_SUBTYPE_PENTII_M5");
799
4.10k
  yr_set_integer(CPU_SUBTYPE_CELERON, object, "CPU_SUBTYPE_CELERON");
800
4.10k
  yr_set_integer(CPU_SUBTYPE_CELERON_MOBILE, object, "CPU_SUBTYPE_CELERON_MOBILE");
801
4.10k
  yr_set_integer(CPU_SUBTYPE_PENTIUM_3, object, "CPU_SUBTYPE_PENTIUM_3");
802
4.10k
  yr_set_integer(CPU_SUBTYPE_PENTIUM_3_M, object, "CPU_SUBTYPE_PENTIUM_3_M");
803
4.10k
  yr_set_integer(CPU_SUBTYPE_PENTIUM_3_XEON, object, "CPU_SUBTYPE_PENTIUM_3_XEON");
804
4.10k
  yr_set_integer(CPU_SUBTYPE_PENTIUM_M, object, "CPU_SUBTYPE_PENTIUM_M");
805
4.10k
  yr_set_integer(CPU_SUBTYPE_PENTIUM_4, object, "CPU_SUBTYPE_PENTIUM_4");
806
4.10k
  yr_set_integer(CPU_SUBTYPE_PENTIUM_4_M, object, "CPU_SUBTYPE_PENTIUM_4_M");
807
4.10k
  yr_set_integer(CPU_SUBTYPE_ITANIUM, object, "CPU_SUBTYPE_ITANIUM");
808
4.10k
  yr_set_integer(CPU_SUBTYPE_ITANIUM_2, object, "CPU_SUBTYPE_ITANIUM_2");
809
4.10k
  yr_set_integer(CPU_SUBTYPE_XEON, object, "CPU_SUBTYPE_XEON");
810
4.10k
  yr_set_integer(CPU_SUBTYPE_XEON_MP, object, "CPU_SUBTYPE_XEON_MP");
811
4.10k
  yr_set_integer(CPU_SUBTYPE_ARM_ALL, object, "CPU_SUBTYPE_ARM_ALL");
812
4.10k
  yr_set_integer(CPU_SUBTYPE_ARM_V4T, object, "CPU_SUBTYPE_ARM_V4T");
813
4.10k
  yr_set_integer(CPU_SUBTYPE_ARM_V6, object, "CPU_SUBTYPE_ARM_V6");
814
4.10k
  yr_set_integer(CPU_SUBTYPE_ARM_V5, object, "CPU_SUBTYPE_ARM_V5");
815
4.10k
  yr_set_integer(CPU_SUBTYPE_ARM_V5TEJ, object, "CPU_SUBTYPE_ARM_V5TEJ");
816
4.10k
  yr_set_integer(CPU_SUBTYPE_ARM_XSCALE, object, "CPU_SUBTYPE_ARM_XSCALE");
817
4.10k
  yr_set_integer(CPU_SUBTYPE_ARM_V7, object, "CPU_SUBTYPE_ARM_V7");
818
4.10k
  yr_set_integer(CPU_SUBTYPE_ARM_V7F, object, "CPU_SUBTYPE_ARM_V7F");
819
4.10k
  yr_set_integer(CPU_SUBTYPE_ARM_V7S, object, "CPU_SUBTYPE_ARM_V7S");
820
4.10k
  yr_set_integer(CPU_SUBTYPE_ARM_V7K, object, "CPU_SUBTYPE_ARM_V7K");
821
4.10k
  yr_set_integer(CPU_SUBTYPE_ARM_V6M, object, "CPU_SUBTYPE_ARM_V6M");
822
4.10k
  yr_set_integer(CPU_SUBTYPE_ARM_V7M, object, "CPU_SUBTYPE_ARM_V7M");
823
4.10k
  yr_set_integer(CPU_SUBTYPE_ARM_V7EM, object, "CPU_SUBTYPE_ARM_V7EM");
824
4.10k
  yr_set_integer(CPU_SUBTYPE_ARM64_ALL, object, "CPU_SUBTYPE_ARM64_ALL");
825
4.10k
  yr_set_integer(CPU_SUBTYPE_SPARC_ALL, object, "CPU_SUBTYPE_SPARC_ALL");
826
4.10k
  yr_set_integer(CPU_SUBTYPE_POWERPC_ALL, object, "CPU_SUBTYPE_POWERPC_ALL");
827
4.10k
  yr_set_integer(CPU_SUBTYPE_MC980000_ALL, object, "CPU_SUBTYPE_MC980000_ALL");
828
4.10k
  yr_set_integer(CPU_SUBTYPE_POWERPC_601, object, "CPU_SUBTYPE_POWERPC_601");
829
4.10k
  yr_set_integer(CPU_SUBTYPE_MC98601, object, "CPU_SUBTYPE_MC98601");
830
4.10k
  yr_set_integer(CPU_SUBTYPE_POWERPC_602, object, "CPU_SUBTYPE_POWERPC_602");
831
4.10k
  yr_set_integer(CPU_SUBTYPE_POWERPC_603, object, "CPU_SUBTYPE_POWERPC_603");
832
4.10k
  yr_set_integer(CPU_SUBTYPE_POWERPC_603e, object, "CPU_SUBTYPE_POWERPC_603e");
833
4.10k
  yr_set_integer(CPU_SUBTYPE_POWERPC_603ev, object, "CPU_SUBTYPE_POWERPC_603ev");
834
4.10k
  yr_set_integer(CPU_SUBTYPE_POWERPC_604, object, "CPU_SUBTYPE_POWERPC_604");
835
4.10k
  yr_set_integer(CPU_SUBTYPE_POWERPC_604e, object, "CPU_SUBTYPE_POWERPC_604e");
836
4.10k
  yr_set_integer(CPU_SUBTYPE_POWERPC_620, object, "CPU_SUBTYPE_POWERPC_620");
837
4.10k
  yr_set_integer(CPU_SUBTYPE_POWERPC_750, object, "CPU_SUBTYPE_POWERPC_750");
838
4.10k
  yr_set_integer(CPU_SUBTYPE_POWERPC_7400, object, "CPU_SUBTYPE_POWERPC_7400");
839
4.10k
  yr_set_integer(CPU_SUBTYPE_POWERPC_7450, object, "CPU_SUBTYPE_POWERPC_7450");
840
4.10k
  yr_set_integer(CPU_SUBTYPE_POWERPC_970, object, "CPU_SUBTYPE_POWERPC_970");
841
842
  // File types
843
844
4.10k
  yr_set_integer(MH_OBJECT, object, "MH_OBJECT");
845
4.10k
  yr_set_integer(MH_EXECUTE, object, "MH_EXECUTE");
846
4.10k
  yr_set_integer(MH_FVMLIB, object, "MH_FVMLIB");
847
4.10k
  yr_set_integer(MH_CORE, object, "MH_CORE");
848
4.10k
  yr_set_integer(MH_PRELOAD, object, "MH_PRELOAD");
849
4.10k
  yr_set_integer(MH_DYLIB, object, "MH_DYLIB");
850
4.10k
  yr_set_integer(MH_DYLINKER, object, "MH_DYLINKER");
851
4.10k
  yr_set_integer(MH_BUNDLE, object, "MH_BUNDLE");
852
4.10k
  yr_set_integer(MH_DYLIB_STUB, object, "MH_DYLIB_STUB");
853
4.10k
  yr_set_integer(MH_DSYM, object, "MH_DSYM");
854
4.10k
  yr_set_integer(MH_KEXT_BUNDLE, object, "MH_KEXT_BUNDLE");
855
856
  // Header flags
857
858
4.10k
  yr_set_integer(MH_NOUNDEFS, object, "MH_NOUNDEFS");
859
4.10k
  yr_set_integer(MH_INCRLINK, object, "MH_INCRLINK");
860
4.10k
  yr_set_integer(MH_DYLDLINK, object, "MH_DYLDLINK");
861
4.10k
  yr_set_integer(MH_BINDATLOAD, object, "MH_BINDATLOAD");
862
4.10k
  yr_set_integer(MH_PREBOUND, object, "MH_PREBOUND");
863
4.10k
  yr_set_integer(MH_SPLIT_SEGS, object, "MH_SPLIT_SEGS");
864
4.10k
  yr_set_integer(MH_LAZY_INIT, object, "MH_LAZY_INIT");
865
4.10k
  yr_set_integer(MH_TWOLEVEL, object, "MH_TWOLEVEL");
866
4.10k
  yr_set_integer(MH_FORCE_FLAT, object, "MH_FORCE_FLAT");
867
4.10k
  yr_set_integer(MH_NOMULTIDEFS, object, "MH_NOMULTIDEFS");
868
4.10k
  yr_set_integer(MH_NOFIXPREBINDING, object, "MH_NOFIXPREBINDING");
869
4.10k
  yr_set_integer(MH_PREBINDABLE, object, "MH_PREBINDABLE");
870
4.10k
  yr_set_integer(MH_ALLMODSBOUND, object, "MH_ALLMODSBOUND");
871
4.10k
  yr_set_integer(MH_SUBSECTIONS_VIA_SYMBOLS, object, "MH_SUBSECTIONS_VIA_SYMBOLS");
872
4.10k
  yr_set_integer(MH_CANONICAL, object, "MH_CANONICAL");
873
4.10k
  yr_set_integer(MH_WEAK_DEFINES, object, "MH_WEAK_DEFINES");
874
4.10k
  yr_set_integer(MH_BINDS_TO_WEAK, object, "MH_BINDS_TO_WEAK");
875
4.10k
  yr_set_integer(MH_ALLOW_STACK_EXECUTION, object, "MH_ALLOW_STACK_EXECUTION");
876
4.10k
  yr_set_integer(MH_ROOT_SAFE, object, "MH_ROOT_SAFE");
877
4.10k
  yr_set_integer(MH_SETUID_SAFE, object, "MH_SETUID_SAFE");
878
4.10k
  yr_set_integer(MH_NO_REEXPORTED_DYLIBS, object, "MH_NO_REEXPORTED_DYLIBS");
879
4.10k
  yr_set_integer(MH_PIE, object, "MH_PIE");
880
4.10k
  yr_set_integer(MH_DEAD_STRIPPABLE_DYLIB, object, "MH_DEAD_STRIPPABLE_DYLIB");
881
4.10k
  yr_set_integer(MH_HAS_TLV_DESCRIPTORS, object, "MH_HAS_TLV_DESCRIPTORS");
882
4.10k
  yr_set_integer(MH_NO_HEAP_EXECUTION, object, "MH_NO_HEAP_EXECUTION");
883
4.10k
  yr_set_integer(MH_APP_EXTENSION_SAFE, object, "MH_APP_EXTENSION_SAFE");
884
885
  // Segment flags masks
886
887
4.10k
  yr_set_integer(SG_HIGHVM, object, "SG_HIGHVM");
888
4.10k
  yr_set_integer(SG_FVMLIB, object, "SG_FVMLIB");
889
4.10k
  yr_set_integer(SG_NORELOC, object, "SG_NORELOC");
890
4.10k
  yr_set_integer(SG_PROTECTED_VERSION_1, object, "SG_PROTECTED_VERSION_1");
891
892
  // Section flags masks
893
894
4.10k
  yr_set_integer(SECTION_TYPE, object, "SECTION_TYPE");
895
4.10k
  yr_set_integer(SECTION_ATTRIBUTES, object, "SECTION_ATTRIBUTES");
896
897
  // Section types
898
899
4.10k
  yr_set_integer(S_REGULAR, object, "S_REGULAR");
900
4.10k
  yr_set_integer(S_ZEROFILL, object, "S_ZEROFILL");
901
4.10k
  yr_set_integer(S_CSTRING_LITERALS, object, "S_CSTRING_LITERALS");
902
4.10k
  yr_set_integer(S_4BYTE_LITERALS, object, "S_4BYTE_LITERALS");
903
4.10k
  yr_set_integer(S_8BYTE_LITERALS, object, "S_8BYTE_LITERALS");
904
4.10k
  yr_set_integer(S_NON_LAZY_SYMBOL_POINTERS, object, "S_NON_LAZY_SYMBOL_POINTERS");
905
4.10k
  yr_set_integer(S_LAZY_SYMBOL_POINTERS, object, "S_LAZY_SYMBOL_POINTERS");
906
4.10k
  yr_set_integer(S_LITERAL_POINTERS, object, "S_LITERAL_POINTERS");
907
4.10k
  yr_set_integer(S_SYMBOL_STUBS, object, "S_SYMBOL_STUBS");
908
4.10k
  yr_set_integer(S_MOD_INIT_FUNC_POINTERS, object, "S_MOD_INIT_FUNC_POINTERS");
909
4.10k
  yr_set_integer(S_MOD_TERM_FUNC_POINTERS, object, "S_MOD_TERM_FUNC_POINTERS");
910
4.10k
  yr_set_integer(S_COALESCED, object, "S_COALESCED");
911
4.10k
  yr_set_integer(S_GB_ZEROFILL, object, "S_GB_ZEROFILL");
912
4.10k
  yr_set_integer(S_INTERPOSING, object, "S_INTERPOSING");
913
4.10k
  yr_set_integer(S_16BYTE_LITERALS, object, "S_16BYTE_LITERALS");
914
4.10k
  yr_set_integer(S_DTRACE_DOF, object, "S_DTRACE_DOF");
915
4.10k
  yr_set_integer(
916
4.10k
      S_LAZY_DYLIB_SYMBOL_POINTERS, object, "S_LAZY_DYLIB_SYMBOL_POINTERS");
917
4.10k
  yr_set_integer(S_THREAD_LOCAL_REGULAR, object, "S_THREAD_LOCAL_REGULAR");
918
4.10k
  yr_set_integer(S_THREAD_LOCAL_ZEROFILL, object, "S_THREAD_LOCAL_ZEROFILL");
919
4.10k
  yr_set_integer(S_THREAD_LOCAL_VARIABLES, object, "S_THREAD_LOCAL_VARIABLES");
920
4.10k
  yr_set_integer(
921
4.10k
      S_THREAD_LOCAL_VARIABLE_POINTERS,
922
4.10k
      object,
923
4.10k
      "S_THREAD_LOCAL_VARIABLE_POINTERS");
924
4.10k
  yr_set_integer(
925
4.10k
      S_THREAD_LOCAL_INIT_FUNCTION_POINTERS,
926
4.10k
      object,
927
4.10k
      "S_THREAD_LOCAL_INIT_FUNCTION_POINTERS");
928
929
  // Section attributes
930
931
4.10k
  yr_set_integer(S_ATTR_PURE_INSTRUCTIONS, object, "S_ATTR_PURE_INSTRUCTIONS");
932
4.10k
  yr_set_integer(S_ATTR_NO_TOC, object, "S_ATTR_NO_TOC");
933
4.10k
  yr_set_integer(S_ATTR_STRIP_STATIC_SYMS, object, "S_ATTR_STRIP_STATIC_SYMS");
934
4.10k
  yr_set_integer(S_ATTR_NO_DEAD_STRIP, object, "S_ATTR_NO_DEAD_STRIP");
935
4.10k
  yr_set_integer(S_ATTR_LIVE_SUPPORT, object, "S_ATTR_LIVE_SUPPORT");
936
4.10k
  yr_set_integer(S_ATTR_SELF_MODIFYING_CODE, object, "S_ATTR_SELF_MODIFYING_CODE");
937
4.10k
  yr_set_integer(S_ATTR_DEBUG, object, "S_ATTR_DEBUG");
938
4.10k
  yr_set_integer(S_ATTR_SOME_INSTRUCTIONS, object, "S_ATTR_SOME_INSTRUCTIONS");
939
4.10k
  yr_set_integer(S_ATTR_EXT_RELOC, object, "S_ATTR_EXT_RELOC");
940
4.10k
  yr_set_integer(S_ATTR_LOC_RELOC, object, "S_ATTR_LOC_RELOC");
941
4.10k
}
942
943
// Get Mach-O file index in fat file by cputype field.
944
945
define_function(file_index_type)
946
0
{
947
0
  YR_OBJECT* module = yr_module();
948
0
  int64_t type_arg = integer_argument(1);
949
950
0
  uint64_t nfat = yr_get_integer(module, "nfat_arch");
951
0
  if (yr_is_undefined(module, "nfat_arch"))
952
0
    return_integer(YR_UNDEFINED);
953
954
0
  for (int i = 0; i < nfat; i++)
955
0
  {
956
0
    int64_t type = yr_get_integer(module, "file[%i].cputype", i);
957
0
    if (type == type_arg)
958
0
    {
959
0
      return_integer(i);
960
0
    }
961
0
  }
962
0
  return_integer(YR_UNDEFINED);
963
0
}
964
965
// Get Mach-O file index in fat file by cputype and cpusubtype fields.
966
967
define_function(file_index_subtype)
968
0
{
969
0
  YR_OBJECT* module = yr_module();
970
0
  int64_t type_arg = integer_argument(1);
971
0
  int64_t subtype_arg = integer_argument(2);
972
0
  uint64_t nfat = yr_get_integer(module, "nfat_arch");
973
974
0
  if (yr_is_undefined(module, "nfat_arch"))
975
0
    return_integer(YR_UNDEFINED);
976
977
0
  for (int i = 0; i < nfat; i++)
978
0
  {
979
0
    int64_t type = yr_get_integer(module, "file[%i].cputype", i);
980
0
    int64_t subtype = yr_get_integer(module, "file[%i].cpusubtype", i);
981
982
0
    if (type == type_arg && subtype == subtype_arg)
983
0
    {
984
0
      return_integer(i);
985
0
    }
986
0
  }
987
988
0
  return_integer(YR_UNDEFINED);
989
0
}
990
991
// Get real entry point offset for specific architecture in fat Mach-O.
992
993
define_function(ep_for_arch_type)
994
0
{
995
0
  YR_OBJECT* module = yr_module();
996
0
  int64_t type_arg = integer_argument(1);
997
0
  uint64_t nfat = yr_get_integer(module, "nfat_arch");
998
999
0
  if (yr_is_undefined(module, "nfat_arch"))
1000
0
    return_integer(YR_UNDEFINED);
1001
1002
0
  for (int i = 0; i < nfat; i++)
1003
0
  {
1004
0
    int64_t type = yr_get_integer(module, "fat_arch[%i].cputype", i);
1005
0
    if (type == type_arg)
1006
0
    {
1007
0
      uint64_t file_offset = yr_get_integer(module, "fat_arch[%i].offset", i);
1008
0
      uint64_t entry_point = yr_get_integer(module, "file[%i].entry_point", i);
1009
0
      return_integer(file_offset + entry_point);
1010
0
    }
1011
0
  }
1012
1013
0
  return_integer(YR_UNDEFINED);
1014
0
}
1015
1016
// Get real entry point offset for specific architecture in fat Mach-O.
1017
1018
define_function(ep_for_arch_subtype)
1019
0
{
1020
0
  YR_OBJECT* module = yr_module();
1021
0
  int64_t type_arg = integer_argument(1);
1022
0
  int64_t subtype_arg = integer_argument(2);
1023
0
  uint64_t nfat = yr_get_integer(module, "nfat_arch");
1024
1025
0
  if (yr_is_undefined(module, "nfat_arch"))
1026
0
    return_integer(YR_UNDEFINED);
1027
1028
0
  for (int i = 0; i < nfat; i++)
1029
0
  {
1030
0
    int64_t type = yr_get_integer(module, "fat_arch[%i].cputype", i);
1031
0
    int64_t subtype = yr_get_integer(module, "fat_arch[%i].cpusubtype", i);
1032
1033
0
    if (type == type_arg && subtype == subtype_arg)
1034
0
    {
1035
0
      uint64_t entry_point = yr_get_integer(module, "file[%i].entry_point", i);
1036
0
      uint64_t file_offset = yr_get_integer(module, "fat_arch[%i].offset", i);
1037
1038
0
      if (entry_point == YR_UNDEFINED) {
1039
0
        return_integer(YR_UNDEFINED);
1040
0
      } else {
1041
0
        return_integer(file_offset + entry_point);
1042
0
      }
1043
0
    }
1044
0
  }
1045
1046
0
  return_integer(YR_UNDEFINED);
1047
0
}
1048
1049
4.11k
begin_declarations
1050
  // Magic constants
1051
4.11k
  declare_integer("MH_MAGIC");
1052
4.11k
  declare_integer("MH_CIGAM");
1053
4.11k
  declare_integer("MH_MAGIC_64");
1054
4.11k
  declare_integer("MH_CIGAM_64");
1055
1056
  // Fat magic constants
1057
4.11k
  declare_integer("FAT_MAGIC");
1058
4.11k
  declare_integer("FAT_CIGAM");
1059
4.11k
  declare_integer("FAT_MAGIC_64");
1060
4.11k
  declare_integer("FAT_CIGAM_64");
1061
1062
  // 64-bit masks
1063
4.11k
  declare_integer("CPU_ARCH_ABI64");
1064
4.11k
  declare_integer("CPU_SUBTYPE_LIB64");
1065
1066
  // CPU types
1067
4.11k
  declare_integer("CPU_TYPE_MC680X0");
1068
4.11k
  declare_integer("CPU_TYPE_X86");
1069
4.11k
  declare_integer("CPU_TYPE_I386");
1070
4.11k
  declare_integer("CPU_TYPE_X86_64");
1071
4.11k
  declare_integer("CPU_TYPE_MIPS");
1072
4.11k
  declare_integer("CPU_TYPE_MC98000");
1073
4.11k
  declare_integer("CPU_TYPE_ARM");
1074
4.11k
  declare_integer("CPU_TYPE_ARM64");
1075
4.11k
  declare_integer("CPU_TYPE_MC88000");
1076
4.11k
  declare_integer("CPU_TYPE_SPARC");
1077
4.11k
  declare_integer("CPU_TYPE_POWERPC");
1078
4.11k
  declare_integer("CPU_TYPE_POWERPC64");
1079
1080
  // CPU sub-types
1081
4.11k
  declare_integer("CPU_SUBTYPE_INTEL_MODEL_ALL");
1082
4.11k
  declare_integer("CPU_SUBTYPE_386");
1083
4.11k
  declare_integer("CPU_SUBTYPE_I386_ALL");
1084
4.11k
  declare_integer("CPU_SUBTYPE_X86_64_ALL");
1085
4.11k
  declare_integer("CPU_SUBTYPE_486");
1086
4.11k
  declare_integer("CPU_SUBTYPE_486SX");
1087
4.11k
  declare_integer("CPU_SUBTYPE_586");
1088
4.11k
  declare_integer("CPU_SUBTYPE_PENT");
1089
4.11k
  declare_integer("CPU_SUBTYPE_PENTPRO");
1090
4.11k
  declare_integer("CPU_SUBTYPE_PENTII_M3");
1091
4.11k
  declare_integer("CPU_SUBTYPE_PENTII_M5");
1092
4.11k
  declare_integer("CPU_SUBTYPE_CELERON");
1093
4.11k
  declare_integer("CPU_SUBTYPE_CELERON_MOBILE");
1094
4.11k
  declare_integer("CPU_SUBTYPE_PENTIUM_3");
1095
4.11k
  declare_integer("CPU_SUBTYPE_PENTIUM_3_M");
1096
4.11k
  declare_integer("CPU_SUBTYPE_PENTIUM_3_XEON");
1097
4.11k
  declare_integer("CPU_SUBTYPE_PENTIUM_M");
1098
4.11k
  declare_integer("CPU_SUBTYPE_PENTIUM_4");
1099
4.11k
  declare_integer("CPU_SUBTYPE_PENTIUM_4_M");
1100
4.11k
  declare_integer("CPU_SUBTYPE_ITANIUM");
1101
4.11k
  declare_integer("CPU_SUBTYPE_ITANIUM_2");
1102
4.11k
  declare_integer("CPU_SUBTYPE_XEON");
1103
4.11k
  declare_integer("CPU_SUBTYPE_XEON_MP");
1104
4.11k
  declare_integer("CPU_SUBTYPE_ARM_ALL");
1105
4.11k
  declare_integer("CPU_SUBTYPE_ARM_V4T");
1106
4.11k
  declare_integer("CPU_SUBTYPE_ARM_V6");
1107
4.11k
  declare_integer("CPU_SUBTYPE_ARM_V5");
1108
4.11k
  declare_integer("CPU_SUBTYPE_ARM_V5TEJ");
1109
4.11k
  declare_integer("CPU_SUBTYPE_ARM_XSCALE");
1110
4.11k
  declare_integer("CPU_SUBTYPE_ARM_V7");
1111
4.11k
  declare_integer("CPU_SUBTYPE_ARM_V7F");
1112
4.11k
  declare_integer("CPU_SUBTYPE_ARM_V7S");
1113
4.11k
  declare_integer("CPU_SUBTYPE_ARM_V7K");
1114
4.11k
  declare_integer("CPU_SUBTYPE_ARM_V6M");
1115
4.11k
  declare_integer("CPU_SUBTYPE_ARM_V7M");
1116
4.11k
  declare_integer("CPU_SUBTYPE_ARM_V7EM");
1117
4.11k
  declare_integer("CPU_SUBTYPE_ARM64_ALL");
1118
4.11k
  declare_integer("CPU_SUBTYPE_SPARC_ALL");
1119
4.11k
  declare_integer("CPU_SUBTYPE_POWERPC_ALL");
1120
4.11k
  declare_integer("CPU_SUBTYPE_MC980000_ALL");
1121
4.11k
  declare_integer("CPU_SUBTYPE_POWERPC_601");
1122
4.11k
  declare_integer("CPU_SUBTYPE_MC98601");
1123
4.11k
  declare_integer("CPU_SUBTYPE_POWERPC_602");
1124
4.11k
  declare_integer("CPU_SUBTYPE_POWERPC_603");
1125
4.11k
  declare_integer("CPU_SUBTYPE_POWERPC_603e");
1126
4.11k
  declare_integer("CPU_SUBTYPE_POWERPC_603ev");
1127
4.11k
  declare_integer("CPU_SUBTYPE_POWERPC_604");
1128
4.11k
  declare_integer("CPU_SUBTYPE_POWERPC_604e");
1129
4.11k
  declare_integer("CPU_SUBTYPE_POWERPC_620");
1130
4.11k
  declare_integer("CPU_SUBTYPE_POWERPC_750");
1131
4.11k
  declare_integer("CPU_SUBTYPE_POWERPC_7400");
1132
4.11k
  declare_integer("CPU_SUBTYPE_POWERPC_7450");
1133
4.11k
  declare_integer("CPU_SUBTYPE_POWERPC_970");
1134
1135
  // File types
1136
4.11k
  declare_integer("MH_OBJECT");
1137
4.11k
  declare_integer("MH_EXECUTE");
1138
4.11k
  declare_integer("MH_FVMLIB");
1139
4.11k
  declare_integer("MH_CORE");
1140
4.11k
  declare_integer("MH_PRELOAD");
1141
4.11k
  declare_integer("MH_DYLIB");
1142
4.11k
  declare_integer("MH_DYLINKER");
1143
4.11k
  declare_integer("MH_BUNDLE");
1144
4.11k
  declare_integer("MH_DYLIB_STUB");
1145
4.11k
  declare_integer("MH_DSYM");
1146
4.11k
  declare_integer("MH_KEXT_BUNDLE");
1147
1148
  // Header flags
1149
4.11k
  declare_integer("MH_NOUNDEFS");
1150
4.11k
  declare_integer("MH_INCRLINK");
1151
4.11k
  declare_integer("MH_DYLDLINK");
1152
4.11k
  declare_integer("MH_BINDATLOAD");
1153
4.11k
  declare_integer("MH_PREBOUND");
1154
4.11k
  declare_integer("MH_SPLIT_SEGS");
1155
4.11k
  declare_integer("MH_LAZY_INIT");
1156
4.11k
  declare_integer("MH_TWOLEVEL");
1157
4.11k
  declare_integer("MH_FORCE_FLAT");
1158
4.11k
  declare_integer("MH_NOMULTIDEFS");
1159
4.11k
  declare_integer("MH_NOFIXPREBINDING");
1160
4.11k
  declare_integer("MH_PREBINDABLE");
1161
4.11k
  declare_integer("MH_ALLMODSBOUND");
1162
4.11k
  declare_integer("MH_SUBSECTIONS_VIA_SYMBOLS");
1163
4.11k
  declare_integer("MH_CANONICAL");
1164
4.11k
  declare_integer("MH_WEAK_DEFINES");
1165
4.11k
  declare_integer("MH_BINDS_TO_WEAK");
1166
4.11k
  declare_integer("MH_ALLOW_STACK_EXECUTION");
1167
4.11k
  declare_integer("MH_ROOT_SAFE");
1168
4.11k
  declare_integer("MH_SETUID_SAFE");
1169
4.11k
  declare_integer("MH_NO_REEXPORTED_DYLIBS");
1170
4.11k
  declare_integer("MH_PIE");
1171
4.11k
  declare_integer("MH_DEAD_STRIPPABLE_DYLIB");
1172
4.11k
  declare_integer("MH_HAS_TLV_DESCRIPTORS");
1173
4.11k
  declare_integer("MH_NO_HEAP_EXECUTION");
1174
4.11k
  declare_integer("MH_APP_EXTENSION_SAFE");
1175
1176
  // Segment flags
1177
4.11k
  declare_integer("SG_HIGHVM");
1178
4.11k
  declare_integer("SG_FVMLIB");
1179
4.11k
  declare_integer("SG_NORELOC");
1180
4.11k
  declare_integer("SG_PROTECTED_VERSION_1");
1181
1182
  // Section masks
1183
4.11k
  declare_integer("SECTION_TYPE");
1184
4.11k
  declare_integer("SECTION_ATTRIBUTES");
1185
1186
  // Section types
1187
4.11k
  declare_integer("S_REGULAR");
1188
4.11k
  declare_integer("S_ZEROFILL");
1189
4.11k
  declare_integer("S_CSTRING_LITERALS");
1190
4.11k
  declare_integer("S_4BYTE_LITERALS");
1191
4.11k
  declare_integer("S_8BYTE_LITERALS");
1192
4.11k
  declare_integer("S_LITERAL_POINTERS");
1193
4.11k
  declare_integer("S_NON_LAZY_SYMBOL_POINTERS");
1194
4.11k
  declare_integer("S_LAZY_SYMBOL_POINTERS");
1195
4.11k
  declare_integer("S_SYMBOL_STUBS");
1196
4.11k
  declare_integer("S_MOD_INIT_FUNC_POINTERS");
1197
4.11k
  declare_integer("S_MOD_TERM_FUNC_POINTERS");
1198
4.11k
  declare_integer("S_COALESCED");
1199
4.11k
  declare_integer("S_GB_ZEROFILL");
1200
4.11k
  declare_integer("S_INTERPOSING");
1201
4.11k
  declare_integer("S_16BYTE_LITERALS");
1202
4.11k
  declare_integer("S_DTRACE_DOF");
1203
4.11k
  declare_integer("S_LAZY_DYLIB_SYMBOL_POINTERS");
1204
4.11k
  declare_integer("S_THREAD_LOCAL_REGULAR");
1205
4.11k
  declare_integer("S_THREAD_LOCAL_ZEROFILL");
1206
4.11k
  declare_integer("S_THREAD_LOCAL_VARIABLES");
1207
4.11k
  declare_integer("S_THREAD_LOCAL_VARIABLE_POINTERS");
1208
4.11k
  declare_integer("S_THREAD_LOCAL_INIT_FUNCTION_POINTERS");
1209
1210
  // Section attributes
1211
4.11k
  declare_integer("S_ATTR_PURE_INSTRUCTIONS");
1212
4.11k
  declare_integer("S_ATTR_NO_TOC");
1213
4.11k
  declare_integer("S_ATTR_STRIP_STATIC_SYMS");
1214
4.11k
  declare_integer("S_ATTR_NO_DEAD_STRIP");
1215
4.11k
  declare_integer("S_ATTR_LIVE_SUPPORT");
1216
4.11k
  declare_integer("S_ATTR_SELF_MODIFYING_CODE");
1217
4.11k
  declare_integer("S_ATTR_DEBUG");
1218
4.11k
  declare_integer("S_ATTR_SOME_INSTRUCTIONS");
1219
4.11k
  declare_integer("S_ATTR_EXT_RELOC");
1220
4.11k
  declare_integer("S_ATTR_LOC_RELOC");
1221
1222
  // Header
1223
4.11k
  declare_integer("magic");
1224
4.11k
  declare_integer("cputype");
1225
4.11k
  declare_integer("cpusubtype");
1226
4.11k
  declare_integer("filetype");
1227
4.11k
  declare_integer("ncmds");
1228
4.11k
  declare_integer("sizeofcmds");
1229
4.11k
  declare_integer("flags");
1230
4.11k
  declare_integer("reserved");
1231
1232
  // Segments and nested sections
1233
4.11k
  declare_integer("number_of_segments");
1234
1235
12.3k
  begin_struct_array("segments")
1236
4.11k
    declare_string("segname");
1237
4.11k
    declare_integer("vmaddr");
1238
4.11k
    declare_integer("vmsize");
1239
4.11k
    declare_integer("fileoff");
1240
4.11k
    declare_integer("fsize");
1241
4.11k
    declare_integer("maxprot");
1242
4.11k
    declare_integer("initprot");
1243
4.11k
    declare_integer("nsects");
1244
4.11k
    declare_integer("flags");
1245
12.3k
    begin_struct_array("sections")
1246
4.11k
      declare_string("sectname");
1247
4.11k
      declare_string("segname");
1248
4.11k
      declare_integer("addr");
1249
4.11k
      declare_integer("size");
1250
4.11k
      declare_integer("offset");
1251
4.11k
      declare_integer("align");
1252
4.11k
      declare_integer("reloff");
1253
4.11k
      declare_integer("nreloc");
1254
4.11k
      declare_integer("flags");
1255
4.11k
      declare_integer("reserved1");
1256
4.11k
      declare_integer("reserved2");
1257
4.11k
      declare_integer("reserved3");
1258
8.22k
    end_struct_array("sections");
1259
8.22k
  end_struct_array("segments")
1260
1261
  // Entry point and stack size
1262
4.11k
  declare_integer("entry_point");
1263
4.11k
  declare_integer("stack_size");
1264
1265
  // Mach-O fat binary header
1266
4.11k
  declare_integer("fat_magic");
1267
4.11k
  declare_integer("nfat_arch");
1268
1269
12.3k
  begin_struct_array("fat_arch")
1270
4.11k
    declare_integer("cputype");
1271
4.11k
    declare_integer("cpusubtype");
1272
4.11k
    declare_integer("offset");
1273
4.11k
    declare_integer("size");
1274
4.11k
    declare_integer("align");
1275
8.22k
  end_struct_array("fat_arch")
1276
1277
  // Included Mach-O files (must be same as single file structure above)
1278
12.3k
  begin_struct_array("file")
1279
1280
    // Single file header
1281
4.11k
    declare_integer("magic");
1282
4.11k
    declare_integer("cputype");
1283
4.11k
    declare_integer("cpusubtype");
1284
4.11k
    declare_integer("filetype");
1285
4.11k
    declare_integer("ncmds");
1286
4.11k
    declare_integer("sizeofcmds");
1287
4.11k
    declare_integer("flags");
1288
4.11k
    declare_integer("reserved");
1289
1290
    // Segments and nested sections
1291
4.11k
    declare_integer("number_of_segments");
1292
1293
12.3k
    begin_struct_array("segments")
1294
4.11k
      declare_string("segname");
1295
4.11k
      declare_integer("vmaddr");
1296
4.11k
      declare_integer("vmsize");
1297
4.11k
      declare_integer("fileoff");
1298
4.11k
      declare_integer("fsize");
1299
4.11k
      declare_integer("maxprot");
1300
4.11k
      declare_integer("initprot");
1301
4.11k
      declare_integer("nsects");
1302
4.11k
      declare_integer("flags");
1303
12.3k
      begin_struct_array("sections")
1304
4.11k
        declare_string("sectname");
1305
4.11k
        declare_string("segname");
1306
4.11k
        declare_integer("addr");
1307
4.11k
        declare_integer("size");
1308
4.11k
        declare_integer("offset");
1309
4.11k
        declare_integer("align");
1310
4.11k
        declare_integer("reloff");
1311
4.11k
        declare_integer("nreloc");
1312
4.11k
        declare_integer("flags");
1313
4.11k
        declare_integer("reserved1");
1314
4.11k
        declare_integer("reserved2");
1315
4.11k
        declare_integer("reserved3");
1316
8.22k
      end_struct_array("sections");
1317
8.22k
    end_struct_array("segments")
1318
1319
    // Entry point and stack size
1320
4.11k
    declare_integer("entry_point");
1321
4.11k
    declare_integer("stack_size");
1322
1323
8.22k
  end_struct_array("file");
1324
1325
  // Mach-O fat binary helper functions
1326
8.22k
  declare_function("file_index_for_arch", "i", "i", file_index_type);
1327
4.11k
  declare_function("file_index_for_arch", "ii", "i", file_index_subtype);
1328
4.11k
  declare_function("entry_point_for_arch", "i", "i", ep_for_arch_type);
1329
4.11k
  declare_function("entry_point_for_arch", "ii", "i", ep_for_arch_subtype);
1330
4.11k
end_declarations
1331
1332
int module_initialize(YR_MODULE* module)
1333
12
{
1334
12
  return ERROR_SUCCESS;
1335
12
}
1336
1337
int module_finalize(YR_MODULE* module)
1338
0
{
1339
0
  return ERROR_SUCCESS;
1340
0
}
1341
1342
int module_load(
1343
    YR_SCAN_CONTEXT* context,
1344
    YR_OBJECT* module_object,
1345
    void* module_data,
1346
    size_t module_data_size)
1347
4.10k
{
1348
4.10k
  YR_MEMORY_BLOCK* block;
1349
4.10k
  YR_MEMORY_BLOCK_ITERATOR* iterator = context->iterator;
1350
1351
4.10k
  foreach_memory_block(iterator, block)
1352
4.10k
  {
1353
4.10k
    const uint8_t* block_data = block->fetch_data(block);
1354
1355
4.10k
    if (block_data == NULL || block->size < 4)
1356
18
      continue;
1357
1358
    // Parse Mach-O binary.
1359
4.08k
    if (is_macho_file_block((uint32_t*) block_data))
1360
1.16k
    {
1361
1.16k
      macho_parse_file(block_data, block->size, module_object, context);
1362
1.16k
      break;
1363
1.16k
    }
1364
1365
    // Parse fat Mach-O binary.
1366
2.92k
    if (is_fat_macho_file_block((uint32_t*) block_data))
1367
1.26k
    {
1368
1.26k
      macho_parse_fat_file(block_data, block->size, module_object, context);
1369
1.26k
      break;
1370
1.26k
    }
1371
2.92k
  }
1372
1373
4.10k
  macho_set_definitions(module_object);
1374
4.10k
  return ERROR_SUCCESS;
1375
4.10k
}
1376
1377
int module_unload(YR_OBJECT* module_object)
1378
4.10k
{
1379
4.10k
  return ERROR_SUCCESS;
1380
4.10k
}