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