mirror of
https://github.com/Karmaz95/Snake_Apple.git
synced 2026-03-30 14:00:16 +02:00
100 lines
3.8 KiB
Python
100 lines
3.8 KiB
Python
#!/usr/bin/env python3
|
|
import os
|
|
import lief
|
|
|
|
|
|
class MachODylibLoadCommandsFinder:
|
|
'''
|
|
Recursively crawl the system and parse Mach-O files to find DYLIB related load commands.
|
|
1. Check if the file is a Mach-O.
|
|
2. List all Load Commands.
|
|
3. Check if any DYLIB-related LC exists.
|
|
LC_LOAD_DYLIB
|
|
LC_ID_DYLIB
|
|
LC_PREBOUND_DYLIB
|
|
LC_LOAD_WEAK_DYLIB
|
|
LC_REEXPORT_DYLIB
|
|
LC_LAZY_LOAD_DYLIB
|
|
LC_LOAD_UPWARD_DYLIB
|
|
LC_RPATH
|
|
4. Print the total Mach-O files analyzed and how many DYLIB-related LCs existed.
|
|
'''
|
|
def __init__(self):
|
|
self.total_files_analyzed = 0
|
|
self.binary_dylibs = {}
|
|
self.dylib_counts = {
|
|
"LC_LOAD_DYLIB" : 0,
|
|
"LC_ID_DYLIB": 0,
|
|
"LC_PREBOUND_DYLIB": 0,
|
|
"LC_LOAD_WEAK_DYLIB": 0,
|
|
"LC_REEXPORT_DYLIB": 0,
|
|
"LC_LAZY_LOAD_DYLIB": 0,
|
|
"LC_LOAD_UPWARD_DYLIB": 0,
|
|
"LC_RPATH": 0,
|
|
}
|
|
|
|
def parseDirectory(self, directory_path):
|
|
'''Recursively check if the path is a file. If it is, use checkIfMacho method.'''
|
|
for root, dirs, files in os.walk(directory_path):
|
|
for file in files:
|
|
file_path = os.path.join(root, file)
|
|
if os.path.isfile(file_path):
|
|
self.checkIfMacho(file_path)
|
|
|
|
def checkIfMacho(self, file_path):
|
|
binaries = lief.MachO.parse(file_path)
|
|
if binaries:
|
|
self.parseFatBinary(binaries, file_path)
|
|
|
|
def parseFatBinary(self, binaries, file_path):
|
|
for binary in binaries:
|
|
if binary.header.cpu_type == lief.MachO.CPU_TYPES.ARM64:
|
|
self.total_files_analyzed += 1
|
|
self.checkDylibLoadCommands(binary, file_path)
|
|
|
|
def checkDylibLoadCommands(self, binary, file_path):
|
|
dylib_related_lcs = {
|
|
lief.MachO.LOAD_COMMAND_TYPES.LOAD_DYLIB: "LC_LOAD_DYLIB",
|
|
lief.MachO.LOAD_COMMAND_TYPES.ID_DYLIB: "LC_ID_DYLIB",
|
|
lief.MachO.LOAD_COMMAND_TYPES.PREBOUND_DYLIB: "LC_PREBOUND_DYLIB",
|
|
lief.MachO.LOAD_COMMAND_TYPES.LOAD_WEAK_DYLIB: "LC_LOAD_WEAK_DYLIB",
|
|
lief.MachO.LOAD_COMMAND_TYPES.REEXPORT_DYLIB: "LC_REEXPORT_DYLIB",
|
|
lief.MachO.LOAD_COMMAND_TYPES.LAZY_LOAD_DYLIB: "LC_LAZY_LOAD_DYLIB",
|
|
lief.MachO.LOAD_COMMAND_TYPES.LOAD_UPWARD_DYLIB: "LC_LOAD_UPWARD_DYLIB",
|
|
lief.MachO.LOAD_COMMAND_TYPES.RPATH: "LC_RPATH",
|
|
}
|
|
|
|
binary_dylibs_set = set()
|
|
|
|
for cmd in binary.commands:
|
|
if cmd.command in dylib_related_lcs:
|
|
lc_name = dylib_related_lcs[cmd.command]
|
|
self.dylib_counts[lc_name] += 1
|
|
binary_dylibs_set.add(lc_name)
|
|
|
|
self.binary_dylibs[file_path] = binary_dylibs_set
|
|
|
|
def print_results(self):
|
|
print(f"Total Mach-O files analyzed: {self.total_files_analyzed}")
|
|
print("DYLIB-related LC counts:")
|
|
for lc, count in self.dylib_counts.items():
|
|
print(f"{lc}: {count}")
|
|
|
|
print("\nBinary Dylibs:")
|
|
for binary, dylibs in self.binary_dylibs.items():
|
|
print(f"{binary}: {dylibs}")
|
|
|
|
def save_results(self):
|
|
with open("MachODylibLoadCommandsFinder_results.txt", "a") as f:
|
|
f.write(f"Total Mach-O files analyzed: {self.total_files_analyzed}\n")
|
|
f.write("DYLIB-related LC counts:\n")
|
|
for lc, count in self.dylib_counts.items():
|
|
f.write(f"{lc}: {count}\n")
|
|
for binary, dylibs in self.binary_dylibs.items():
|
|
f.write(f"{binary}: {', '.join(dylibs)}\n")
|
|
|
|
|
|
macho_checker = MachODylibLoadCommandsFinder()
|
|
macho_checker.parseDirectory("/")
|
|
macho_checker.print_results()
|
|
macho_checker.save_results() |