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, §ions[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