Skip to content

Commit cc34b9e

Browse files
committed
feat: add macho fat parser
1 parent 9caea3c commit cc34b9e

File tree

2 files changed

+106
-0
lines changed

2 files changed

+106
-0
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
2+
3+
import kaitaistruct
4+
from kaitaistruct import KaitaiStruct, KaitaiStream, BytesIO
5+
6+
7+
if getattr(kaitaistruct, 'API_VERSION', (0, 9)) < (0, 9):
8+
raise Exception("Incompatible Kaitai Struct Python API: 0.9 or later is required, but you have %s" % (kaitaistruct.__version__))
9+
10+
from scripts.extractors.kaitai.mach_o import MachO
11+
class MachOFat(KaitaiStruct):
12+
"""This is a simple container format that encapsulates multiple Mach-O files,
13+
each generally for a different architecture. XNU can execute these files just
14+
like single-arch Mach-Os and will pick the appropriate entry.
15+
16+
.. seealso::
17+
Source - https://opensource.apple.com/source/xnu/xnu-7195.121.3/EXTERNAL_HEADERS/mach-o/fat.h.auto.html
18+
"""
19+
def __init__(self, _io, _parent=None, _root=None):
20+
self._io = _io
21+
self._parent = _parent
22+
self._root = _root if _root else self
23+
self._read()
24+
25+
def _read(self):
26+
self.magic = self._io.read_bytes(4)
27+
if not self.magic == b"\xCA\xFE\xBA\xBE":
28+
raise kaitaistruct.ValidationNotEqualError(b"\xCA\xFE\xBA\xBE", self.magic, self._io, u"/seq/0")
29+
self.num_fat_arch = self._io.read_u4be()
30+
self.fat_archs = []
31+
for i in range(self.num_fat_arch):
32+
self.fat_archs.append(MachOFat.FatArch(self._io, self, self._root))
33+
34+
35+
class FatArch(KaitaiStruct):
36+
def __init__(self, _io, _parent=None, _root=None):
37+
self._io = _io
38+
self._parent = _parent
39+
self._root = _root if _root else self
40+
self._read()
41+
42+
def _read(self):
43+
self.cpu_type = KaitaiStream.resolve_enum(MachO.CpuType, self._io.read_u4be())
44+
self.cpu_subtype = self._io.read_u4be()
45+
self.ofs_object = self._io.read_u4be()
46+
self.len_object = self._io.read_u4be()
47+
self.align = self._io.read_u4be()
48+
49+
@property
50+
def object(self):
51+
if hasattr(self, '_m_object'):
52+
return self._m_object
53+
54+
_pos = self._io.pos()
55+
self._io.seek(self.ofs_object)
56+
self._raw__m_object = self._io.read_bytes(self.len_object)
57+
_io__raw__m_object = KaitaiStream(BytesIO(self._raw__m_object))
58+
self._m_object = MachO(_io__raw__m_object)
59+
self._io.seek(_pos)
60+
return getattr(self, '_m_object', None)
61+
62+
63+

scripts/macho_fat_parser.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
"""!
2+
@brief uses Kaitai (https://github.com/kaitai-io/kaitai_struct_compiler) to parse Mach-o Fat files.
3+
@details Can supply a section name to extract out of the Mach-o Fat.
4+
By default runs macho_parser_misc() from macho_parser plugin
5+
"""
6+
from deject.plugins import Deject
7+
from kaitaistruct import KaitaiStream, BytesIO
8+
from scripts.extractors.kaitai.mach_o_fat import MachOFat
9+
import scripts.macho_parser
10+
from typer import secho,colors
11+
from enum import Flag
12+
13+
@Deject.plugin
14+
def macho_fat_parser():
15+
"""Used to parse information from a Mach-o file"""
16+
data = MachOFat.from_file(Deject.file_path)
17+
args = str(Deject.plugin_args).split(" ")
18+
if args[0] == "False":
19+
secho(f"Please select a CPU Arch from the following: {[x.cpu_type.name for x in data.fat_archs]})")
20+
return
21+
args.append("")
22+
for archs in data.fat_archs:
23+
if archs.cpu_type.name == args[0]:
24+
match args[1]:
25+
case "extract":
26+
result = scripts.macho_parser.macho_parser_extract(archs.object,args[2])
27+
case "sections":
28+
result = scripts.macho_parser.macho_parser_sections(archs.object)
29+
case _:
30+
result = scripts.macho_parser.macho_parser_misc(archs.object)
31+
return result
32+
33+
def help():
34+
print("""
35+
Mach-o Fat Parser plugin
36+
37+
SYNOPSIS <filename> "[options]"
38+
39+
Select the Architecture to get information about, running without the architechure will print available architectures in the file.
40+
41+
Uses the Mach-o Fat parser from Kaitai to read information from a Mach-o Fat file.
42+
If extract and a section name is added, extract data from that section (enclose additional options in quotes).
43+
""")

0 commit comments

Comments
 (0)