Releases: Karmaz95/Snake_Apple
v1.1
MAJOR
- Added
SnakeXclass - Added
driversandmach_ipcsubdirectories inX. NU/custom- Added IDAPython script
format_externalmethods.py - Added
CommPageParser.c - Added example codes how to communicate with drivers
- Added example kernel extension
- Added IDAPython script
- Added LLDB helper script
set_xpc_breaks.py - Added article about Snake & Apple X.NU
- Added article about Exceptions on macOS
- Added article about MACF on macOS
- Added article about Kernel Extensions on macOS
- Added article about Mach IPC Security on macOS
- Added article about Drivers on macOS
- Added article about XPC Programming on macOS
- Moved all KEXT related functions to XNU from other Snakes.
--dump_prelink_info [(optional) out_name]
Dump "__PRELINK_INFO,__info" to a given file (default: "PRELINK_info.txt")
--dump_prelink_text [(optional) out_name]
Dump "__PRELINK_TEXT,__text" to a given file (default: "PRELINK_text.txt")
--dump_prelink_kext [kext_name]
Dump prelinked KEXT {kext_name} from decompressed Kernel Cache PRELINK_TEXT segment to a
file named: prelinked_{kext_name}.bin
--kext_prelinkinfo [kext_name]
Print _Prelink properties from PRELINK_INFO,__info for a give {kext_name}
--kmod_info kext_name
Parse kmod_info structure for the given {kext_name} from Kernel Cache
--kext_entry kext_name
Calculate the virtual memory address of the __start (entrypoint) for the given {kext_name}
Kernel Extension
--kext_exit kext_name
Calculate the virtual memory address of the __stop (exitpoint) for the given {kext_name}
Kernel Extension
--mig Search for MIG subsystem and prints message handlers
--dump_kext kext_name
Dump the kernel extension binary from the kernelcache.decompressed fileMINOR
- Added MPO parser to XNU.
- Added
extract_sandbox_platform_profiletoSnakeVIII - Added example XPC client-helper app bundle in
App Bundle Extensions/custom/XPC/
Full Changelog: v1.0...v1.1
Snake&Apple IX — TCC
MAJOR
- Added
SnakeIXclass - Added
sip_check.candsip_check.pyscripts - Added System Intigrity Protection article
- Added
uuid_manager.py - Added
uuid_checker.sh - Added Apple UUID Finder article
- Added
get_uuid.py - Added
app_UUID_finder_v1.shandapp_UUID_finder_v2.sh - Added
UUIDFinder.py - Big changes for
MachOFileFinder- faster and more error resistance - Added Optimizing Mach-O Detection
- Added Fixing an Infinite Loop article
MINOR
- Bug fix - file_path was missing self ()
❯ CrimsonUroboros -b /Applications/Safari.app --checksec
<==== CHECKSEC ======
PIE: True
ARC: False
STRIPPED: True
CANARY: False
NX STACK: True
NX HEAP: False
Traceback (most recent call last):
File "/Users/karmaz/.local/bin/CrimsonUroboros", line 3664, in <module>
checksec_processor.process(args)
File "/Users/karmaz/.local/bin/CrimsonUroboros", line 1203, in process
print("XN:".ljust(16) + str(snake_instance.hasXN()))
^^^^^^^^^^^^^^^^^^^^^^
File "/Users/karmaz/.local/bin/CrimsonUroboros", line 1325, in hasXN
if self.hasAllowJITentitlement(self.file_path) or self.checkIfCompiledForOtherThanARM():
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/karmaz/.local/bin/CrimsonUroboros", line 1319, in checkIfCompiledForOtherThanARM
print(f"[INFO -> XN]: {os.path.basename(file_path)} is compiled for other CPUs than ARM or ARM64.")
^^^^^^^^^
NameError: name 'file_path' is not defined. Did you mean: 'self.file_path'?- Bug fix - LIEF in version 0.15.0 re-scoped
CPU_TYPESintolief.MachO.Header.CPU_TYPE.
File "/Users/karmaz/.local/bin/CrimsonUroboros", line 510, in extractArm64MachOFromUniversalBinary
if binary.header.cpu_type == lief.MachO.CPU_TYPES.ARM64:
- Bug fix - LIEF Re-scope
HEADER_FLAGSintolief.MachO.Header.FLAGS
File "/Users/karmaz/.local/bin/CrimsonUroboros", line 1255, in hasNXstack
return not bool(self.binary.header.flags & lief.MachO.HEADER_FLAGS.ALLOW_STACK_EXECUTION.value
- Other similar issues patched according to
lief15.0.1changelog changes and some modification intest_CrimsonUroboros.py - Set stable versions of the dependant pip libraries in
requirements.txtso the tool can be stable:
lief=0.15.1
uuid=1.30
argparse=1.4.0
asn1crypto=1.5.1
pyimg4=0.8
treelib=1.7.0
xattr=1.1.0
python-magic=0.4.27- Adding
sip_entitlements.txtlist of SIP-specific entitlements. - Uploaded all
kTCCService*constants inkTCCService_constants.txtfrom macOS 15. - Modify the
MachOFileFinderso it works with lief 15.0.1. Moreover,parse_fat_binaryfunction check for any architecture by default but allow filtering for ARM64 when the--only_arm64option is specified. - Added
uuid_checker.shthat takes a UUID as the first argument and a path to a file list as the second argument. The script will iterate through each file path in the list, usingdwarfdump --uuidto check for the specified UUID. If a match is found, it prints the file path. - Bug fix in
MachOFileFinder.pyto make it work with lief15.0.1 - Updated
Readme.md MachOFileFinder.pyoptimization changes, output is still the same:
❯ MachOFileFinder .
BUNDLE:/Users/karmaz/snake_apple/macho_files/samples/BUNDLE_type
DSYM:/Users/karmaz/snake_apple/macho_files/samples/DSYM_type
PRELOAD:/Users/karmaz/snake_apple/macho_files/samples/PRELOAD_type
FVMLIB:/Users/karmaz/snake_apple/macho_files/samples/FVMLIB_type
DYLINKER:/Users/karmaz/snake_apple/macho_files/samples/DYLINKER_type
DYLIB:/Users/karmaz/snake_apple/macho_files/samples/DYLIB_STUB_type
BUNDLE:/Users/karmaz/snake_apple/macho_files/samples/KEXT_BUNDLE_type
DYLIB:/Users/karmaz/snake_apple/macho_files/samples/DYLIB_type
UNKNOWN:/Users/karmaz/snake_apple/macho_files/samples/UNKNOWN_type
CORE:/Users/karmaz/snake_apple/macho_files/samples/CORE_type
OBJECT:/Users/karmaz/snake_apple/macho_files/samples/OBJECT_type
EXECUTE:/Users/karmaz/snake_apple/macho_files/samples/EXECUTE_type
- Added
create_macho_samples.pytemplate for creating macho headers samples. - Added
python-magic=0.4.27torequirements.txt - Further
MachOFileFinder.pypatches (output is still the same).
Full Changelog: v0.9...v1.0
Snake&Apple VIII — App Sandbox
MAJOR
- Added
SnakeVIIIclass. - Added
spbl_compilator_wrapper.cfor compiling Sandbox Profile files.sb. - Added
make_plist.pyfor converting XML back to PLIST. - Added
sandbox_inspectorfor various tasks related to App Sandbox (it is standalone, but I also implemented all functionalities to the latest SnakeVIII) - Added
sandbox_validatorfor checking if a given operation is allowed for the sandboxed process - Added
sandbox_detectorfor checking if the process is sandboxed - Some modifications & additions to the current code (see below).
SnakeI
- Added
--dump_binaryfor extracting binary from Fat archives. - Modified
--dump_sectionto dump raw bytes (no more b'\x01......') just raw binary to stdout. - Modified
getStringSectionso it now returns strings in the order they appear in the binary (not in random order like previously)
def getStringSection(self):
'''Return strings from the __cstring (string table).'''
extracted_strings = []
for section in self.binary.sections:
if section.type == lief.MachO.SECTION_TYPES.CSTRING_LITERALS:
strings_bytes = section.content.tobytes()
strings = strings_bytes.decode('utf-8', errors='ignore')
extracted_strings.extend(strings.split('\x00'))
return extracted_strings- Bug patch in
MachOFileFinder.py, it did not print file type correctly, due toliefupdate.
print(f"{binary.header.file_type.__name__}:{file_path}")
SnakeAppExtension
- Added
--bundle_idflag for printing theCFBundleIdentifiervalue from theInfo.plistfile if it exists.
MINOR
- Added decompiled code of Sandbox components.
- Added
sandbox_operations_extractor.pya simple script for extracting Sandbox Operations fromSandbox.kext - Added
sonoma_sandbox_operations.txtlist of all Sandbox Operations extracted fromSandbox.kexton Sonoma usingsandbox_operations_extractor.py - Added
SBPL Compilatorarticle link. - Added
Sandbox Detectorarticle link. - Added
Sandbox Validatorarticle link. - Added
Unexpected but expected behaviorarticle link. - Updated README.md
- Patched one of the helper testing functions because it could not handle some bytes while decoding. Now it looks like this:
def run_and_get_stdout(command):
command_with_stdout = f"{command} 2>&1"
# Run the command and capture the output in bytes
result = subprocess.run(command_with_stdout, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
# Decode with utf-8, ignoring invalid characters or replacing them
return result.stdout.decode('utf-8', errors='replace').strip()Snake & Apple: App Bundle Extension
MAJOR
- This update changed the concept of the tool, which at the beginning had to be only a Mach-O analyzer.
- From now on, it will also support app bundles as it grows.
- There is a new
APP BUNDLE EXTENSION - Adding new tools for working with App Bundles:
- Added
BundleProcessorclass:
'''This class contains part of the code related to the App Bundle Extension.
It extends the Snake instance abilities beyond only Mach-O analysis.
When -b/--bundle flag is used, it will analyze the App Bundle when an instance of this (BundleProcessor) class is created.
Then, it can be communicated from Snake object with the new methods dependent on the files in App Bundle.'''- Now tool can work without
-p, if-bis used (it supports Codeless bundles - if no valid executable is in a bundle):
def parseArgs(self):
args = self.parser.parse_args()
if not args.path and not args.bundle:
self.parser.error('One of arguments: -p/--path or -b/--bundle is required.')
return args- We can use
-pand-btogether if we want to change thepathof analyzed binary in context of the bundled app by default binary path is taken fromInfo.plistor if it not exists from:/target.app/Contents/MacOS/target. The logic behind it lies in a new class method:SnakeHatchery.hatch()
def hatch(self):
''' This function initiates 3 global classes:
1. bundle_processor - BundleProcessor class instance, which is used to parse the App Bundle.
2. binaries - Universal binary from wich arm64 Mach-O is extracted (used for most of the flags in CrimsonUroboros).
3. snake_instance - the latest Snake class instance, which holds all the CrimsonUroboros flags logic (inherited starting from SnakeAppBundleExtension).
In the end, it process the arguments related to --bundle flag.
'''
self.pathExistanceCheck()
if self.bundleInit():
self.filePathInit()
self.binaryInit()
if binaries is None and bundle_processor is None:
print('QUITING: The file used in -p is not a valid Mach-O and you did not specify a bundle (-b).')
print('It will only work if bundle is specified AND|OR file is a valid Mach-O.')
exit() # Exit if the file is not valid macho and bundle is not specified
global snake_instance # Must be global for further processors classes.
snake_instance = self.snake_class(binaries, self.file_path)
if bundle_processor is not None:
bundle_processor.process(self.args)- The biggest change is the new class
SnakeHatchery. All starting logic fromMachOAnalyzerwas moved to this class. Basically, the whole startup is rebuild. - Usually
processmethods are exeuted in main. There is one exception in withBundleProcessorclass, as it is executed insideSnakeHatcheryin the end ofhatchmethod.
if __name__ == "__main__":
arg_parser = ArgumentParser()
args = arg_parser.parseArgs()
### --- APP BUNDLE EXTENSION --- ###
snake_hatchery = SnakeHatchery(args, SnakeVII)
snake_hatchery.hatch()
### --- I. MACH-O --- ###
macho_processor = MachOProcessor()
macho_processor.process(args)- The extension itself does not provide much flags, instead, there are new options for existing modules that uses information stored in the object of the extension class
bundle_processor = BundleProcessor(bundle_path)
SnakeAppExtension
- This is a new class, it is a part of
APP BUNDLE EXTENSIONand it stores only logic for CrimsonUroboros flags. Most of the code related to parsing and extracting data from App Bundle is inBundleProcessorclass:
* Added `--bundle_structure` for printing bundle structure in Tree format.
* Added `--bundle_info` for printing `Info.plist` in JSON format.
* Added `--bundle_info_syntax_check`for checking inf `Info.plist` has correct sytnax.
* Added `--bundle_frameworks` for enumerating bundled `Frameworks`.
* Added `--bundle_plugins` for enumerating bundled `PlugIns`.SnakeI
- Added
--dump_sectionfor dumping section by its name. - Added logic for Mach-O verification:
if binaries is not None: # Exception for bundles where binaries are not valid Mach-O
self.binary = self.parseFatBinary(binaries)
self.segments_count, self.file_start, self.file_size, self.file_end = self.getSegmentsInfo()
self.load_commands = self.getLoadCommands()
self.endianess = self.getEndianess()
self.format_specifier = '<I' if self.getEndianess() == 'little' else '>I' # For struct.pack
self.reversed_format_specifier = '>I' if self.getEndianess() == 'little' else '<I' # For CS blob which is in Big Endian.
self.fat_offset = self.binary.fat_offset # For various calculations, if ARM64 Mach-O extracted from Universal Binary - The exception related to the wrong Mach-O file specified in the path can now be bypassed by specifying
-bfor bundle analysis (it is because the executable in the bundle can be a script, for instance).
if binaries is None and bundle_processor.bundle_path is None:
exit() # Exit if the file is not valid macho and bundle is not specified- Bug fixes related to section dumping - the code changes are implemented in
SnakeI, but they are related to usage of these functions in theSnakeIV.
def dumpSection(self, segment_name, section_name, filename):
...
segment_name = segment_name.lower()
section_name = section_name.lower()
...def getSectionRange(self, segment_name, section_name):
...
segment_name = segment_name.lower()
section_name = section_name.lower()
...- Added
printEntitlementsfor printing XML entitlements withoutb'...\n'.
def printEntitlements(self, file_path, format=None):
''' Helper function for printing entitlements. '''
entitlements = self.getEntitlementsFromCodeSignature(file_path, format)
try:
print(entitlements.decode('utf-8'))
except:
print(entitlements)SnakeII
- Added
--remove_sig_from_bundlefor removing the signature from application. - Added
-verify_bundle_signaturefor validating the app's code signature.
SnakeIV
- Added similar logic as in
SnakeIfor handling Codeless bundles.
if binaries is not None: # Exception for bundles where binaries are not valid Mach-O
self.dylib_id_path = self.getPathFromDylibID() # Get Dylib ID for @loader_path resolving
self.dylib_loading_commands, self.dylib_loading_commands_names = self.getDylibLoadCommands() # 1. Get dylib specific load commands
self.rpath_list = self.resolveRunPathLoadCommands() # 2. Get LC_RPATH list
self.absolute_paths = self.resolveDylibPaths() # 3. Get all dylib absolute paths dictionary {dylib_name[dylib_paths]}MINOR
- Added new tests for all new flags.
- Changed all tests to inlcude app bundle extension, the big change is how
bundle_processoris passed to theMachOProcessorduring initial logic:- In main we pass bundle_processor
macho_processor = MachOProcessor(file_path, bundle_processor)* It is then updated to global scope in MachOProcessor:
global bundle_processor
bundle_processor = self.bundle_processor- Added
Cracking macOS appsarticle link. - Added
App Bundle Extensionarticle link. - Created an
Article_tags.mdfor hashtags related to the articles, because the list of articles did not look very aesthetic. - Until now, only the Dyld series had hashtags - I added them for the rest of the articles.
README.mdupdate
Snake & Apple: Antivirus
MAJOR
-
Repaired bug in
checkDyldInsertLibrariesthat was missing the case for0x10000+ insecure entitlements -
I repaired all the bugs I missed after the latest updates to the
lieflibrary. -
All tests were successful, so it should work for the latest
liefversion. -
Added
testDyldSLCandprinttestDyldSLCto support--test_dyld_SLCoption to test for code injection usingDYLD_SHARED_CACHE_DIR. -
New Snake VII. Antivirus class with bunch of new functionalities.
-
Added
AMFI_test.shscript.
MINOR
- Patched Type-error because of changes in
lieflibrary:
if arm64_bin == None:
^^^^^^^^^^^^^^^^^
TypeError: __eq__(): incompatible function arguments. The following argument types are supported:
1. __eq__(self, arg: lief._lief.Object, /) -> bool
Invoked with types: lief._lief.MachO.Binary, NoneType
Now it cannot use == as the operator arm64_bin is None.
- Patched the
getEndianessfunction because of changes in thelieflibrary.
File "/Users/karmaz/.local/bin/CrimsonUroboros", line 261, in getEndianess
magic = self.binary.header.magic.name
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'lief._lief.MachO.MACHO_TYPES' object has no attribute 'name
Now we must use __name__ property.
__name__patch ingetDylibID
File "/Users/karmaz/.local/bin/CrimsonUroboros", line 1365, in getDylibID
if cmd.command.name == 'ID_DYLIB':
^^^^^^^^^^^^^^^^
AttributeError: 'lief._lief.MachO.LOAD_COMMAND_TYPES' object has no attribute 'name'
__name__patch ingetDylibLoadCommands
File "/Users/karmaz/.local/bin/CrimsonUroboros", line 1176, in getDylibLoadCommands
cmd_name = cmd.command.name
^^^^^^^^^^^^^^^^
AttributeError: 'lief._lief.MachO.LOAD_COMMAND_TYPES' object has no attribute 'name'
__name__patch ingetUnresolvedRunPathLoadCommandsPaths
File "/Users/karmaz/.local/bin/CrimsonUroboros", line 1188, in getUnresolvedRunPathLoadCommandsPaths
return [cmd.path for cmd in self.load_commands if cmd.command.name == 'RPATH']
^^^^^^^^^^^^^^^^
AttributeError: 'lief._lief.MachO.LOAD_COMMAND_TYPES' object has no attribute 'name'
- ... and other places where
__name__should be used instead of.nameas from lief verion 14.0 - Minor bug patch with
getSectionswhere byte string was returned instead of decoded utf. - Added information about success in
dumpPrelink_infoanddumpPrelink_text - Patched
getSectionRangebug withif section_name == section.fullname- lack od.decode()after changes inlief.
def getSectionRange(self, segment_name, section_name):
'''
Return section start and end file offset.
If there is no such section return False, False.
'''
for section in self.binary.sections:
if segment_name == section.segment_name:
if section_name == section.fullname.decode():
-
Modified some tests.
-
Added some RE to Dyld according to DYLD VII.
-
Fix the name in Arg parser for amfi_group.
-
Added X. NU directory for storing materials related to macOS kernel.
-
Added some presentations and decompiled code to the
macdirectory ofAntivirus
Snake & Apple: AMFI
MAJOR
- Added
SnakeVIclass! - Added decompiled AMFI code to the
VI. AMFI/mac/AMFI_REdirectory (the ones withPSEUDO_prefix are my own more readable interpretation) - Added
AppleStructuresManagerclass, which stores Apple structures and their parsers - Added
Utilsclass, which stores custom tools for debugging CrimsonUroboros code - Partially did one of the TODO points from README.md about building my own Code Signature parser in Python by implementing the
parseCodeDirectoryBlobmethodin SnakeIIand theCodeDirectoryclass inAppleStructuresManager
SNAKE I: Mach-O
- Added
calcSectionRange,getSectionRange,extractSectionanddumpSection - Modified
getSectionswithcalcSectionRange - Modified
getMainso now it also finds Thread Command (LC_THREAD / LC_UNIXTHREAD) - Added
hasLoadCommandandprintHasLoadCommandfor a new option--has_cmd - Added
hasSectionandprintHasSectionfor a new option--has_section - Moved the
saveBytesToFilemethod fromSnakeIItoSnakeI - Added
dumpDataanddumpDataArgParserfor a new option--dump_data - Added
hasSegmentandprintHasSegmentfor a new option--has_segment - Added
getVirtualMemoryStartingAddress,calcRealAddressFromVM - Added
calcRealAddressFromVMandprintCalcRealAddressFromVMfor a new option--calc_offset - Added
getSectionandgetSegmentfunctions - Added
self.symbol_typesthat stores symbol types masks - Added
getImportsandprintImportsfor a new option--imports - Added
getExportsandprintExportsfor a new option--exports - Added
getSegmentsInfohelper function for initialization so we can access properties:segments_count,file_start,file_size,file_end - Added
printConstructorsfor a new option--constructors
SNAKE II: Code Signing
- Added
getCodeSignatureOffsetandprintCodeSignatureOffsetfor a new option--cs_offset - Added
printCodeSignatureOffset,extractCodeSignatureBytes,findBytes,parseCodeDirectoryBlob,getCodeSignatureOffsetandprintCodeSignatureFlagsfor a new option--cs_flags
MINOR
- Added tags to the
DYLDarticle series - Added
self.prefix tofile_pathinextractBytesAtOffset. - Added some new TODO's to
README.md - Added tests for all new flags
- Added
crimson_stalkertoSourceCodeManager - Added
MIG_detect.pyfrom knightsc repo - Added
check_amfi.pyscript for calculatingamfiFlags(described here inProcessConfig — AMFI properties)
Snake & Apple: Dyld
MAJOR
- Added
SnakeVclass! - Implemented tests
SNAKE I: Mach-O
- I added the
--imported_symbolsflag, which prints external symbols grouped, sorted, and in a grepable form. Example:
symbol_name : library1
symbol_name : library1
symbol_name : library2
symbol_name : library3
SNAKE IV: DYLIBS
- Added
--dylib_hijacking_aflag - it prints only possible Dylib Hijacking vectors
❯ CrimsonUroboros --dylib_hijacking_a -p executable
VULNERABLE ROOT BINARY: /Users/karmaz95/t/indirect_dylib_hijacking/executable
WRITEABLE EXISTING PATHS: /Users/karmaz95/t/indirect_dylib_hijacking/lib1.dylib
VULNERABLE DEPENDENCY: /Users/karmaz95/t/indirect_dylib_hijacking/lib1.dylib
WRITEABLE EXISTING PATHS: /Users/karmaz95/t/indirect_dylib_hijacking/lib2.dylib- Cosmetic changes to
--dylib_hijackingflag. Now it prints if the binary is ROOT and starts from the status, then path:
CrimsonUroboros -p executable --dylib_hijacking
ROOT BINARY NOT PROTECTED: /Users/karmaz95/t/indirect_dylib_hijacking/executable
WRITEABLE EXISTING PATHS: /Users/karmaz95/t/indirect_dylib_hijacking/lib1.dylib
----------------------------
NOT PROTECTED: /Users/karmaz95/t/indirect_dylib_hijacking/lib1.dylib
WRITEABLE EXISTING PATHS: /Users/karmaz95/t/indirect_dylib_hijacking/lib2.dylib
----------------------------
NOT PROTECTED: /Users/karmaz95/t/indirect_dylib_hijacking/lib2.dylib
----------------------------- I repaired the
prepareRogueDylibfunction for--prepare_dylib. The option was broken because it works on absolute paths, whileDYLIB_IDcould contain unresolved paths like@rpath/something.dylib. For this reason, the function now works on dylib names:
--prepare_dylib target_dylib_name
SNAKE III: CHECKSEC
- Added Library Validation
--has_lv.
❯ CrimsonUroboros --has_lv -p executable
LIBRARY VALIDATION: False- I added LV (Library Validation) to the --checksec option.
❯ CrimsonUroboros --checksec -p executable
<==== CHECKSEC ======
PIE: True
ARC: False
STRIPPED: False
CANARY: False
NX STACK: True
NX HEAP: False
XN: True
NOTARIZED: False
ENCRYPTED: False
RESTRICTED: False
HARDENED: False
APP SANDBOX: False
FORTIFIED: False
RPATH: False
LV: False
=====================>- Added check for
CS_RESTRICT(0x800) in--checksectoRESTRICTED; now, it returns True if the__RESTRICTsegment is used or the0x800flag is set.
MINOR
- Repaired install section (removed uninstallable requirements)
- Completed TODO tasks
- Add check for
DYLIB HIJACKINGto--checksec - Add check for
CS_RESTRICT(0x800) in--checksectoRESTRICTED
- Add check for
- Updated README.md
- Overall code maintenance for a better reader experience
- Removed try-except blocks in each Snake class for more verbose error logging.
- Added
argsargument to all.process()methods to make thetest_CrimsonUroboros.pycode simpler. This is just passing theargsto the method.
Snake & Apple: Dylibs
MAJOR
- Added
SnakeIVclass! - Added
MachODylibLoadCommandsFinder - Added the
### --- SOURCE CODE --- ###section with theSourceCodeManagerclass for the C code storage to keep it in one Python file. This class stores only thedylib_hijackingC code and compiles rogue dylib. In the future, the class will store Assembly code and other tricks for injections.
MINOR
- Added
self.file_pathas the property forSnakesclasses. From now on, it must be initialized for every Snake. So it is now:
def __init__(self, binaries, file_path):
super().__init__(binaries, file_path)- Changed handling any unexpected errors in
except Exception as e:in each processor class to print the name for the Snake. For example:
print(f"An error occurred during SnakeI: Mach-O processing: {e}")
- Added
load_commandsandendiannessproperties to Snake class:
self.load_commands = self.getLoadCommands()
self.endianess = self.getEndianess()- Added
dyld-shared-cache-extractorto theINSTALLsection inREADME.md. - Added
ipswto theINSTALLsection inREADME.md. - Added
--dylib_hijackingand--dylibtreeflags to theLIMITATIONSsection inREADME.md. - Added some points to the
TODO - IDEAS / IMPROVESsection inREADME.md.
Snake & Apple: Checksec
MAJOR
- Added
SnakeIIIclass! - Added
LCFinder! - Added
ModifyMachOFlags! - Added
getEncryptionInfo()to theSnakeI: Mach-O class and--encryption_infoflag for this functionality- If the encryption info load command exists, the information will be printed in the
--infoflag - The user can also specify the output path if he wants to dump the encrypted (or not if
cryptid=0) data sector from the file (it works with fat binaries)
- If the encryption info load command exists, the information will be printed in the
MINOR
- Wrapped
lief.MachO.parse(self.file_path)in aparseFatBinary()method inside aMachOProcessorclass.
Snake & Apple: Code Signing
MAJOR
- I created an additional class,
ArgumentParser, that stores the code from themain()responsible for argument parsing from CLI - I created processor classes for each article/snake - this class stores the code from the main. I did it to make the code cleaner in the
main(), and it is better for the reader because he can read Snake class and then code from the main rather than scrolling to the main to see it Main()stores only the initialization of the class and processor method to execute the code- Added
SnakeIIclass! - Added
TrustCacheParserprogram! - Added
SingatureReaderprogram! - Added
extract_cms.shscript!
MINOR
- Grouped arguments in argument parser for better readability for the end-user in helper and easier code maintenance
- Added ADDITIONAL LINKS to the
README.md - Updated description in
README.md - Removed bug in
SnakeI: Mach-Ocode, where program could run even whenbinaries = lief.MachO.parse(file_path)return None (not Mach-O). - Added the file_path variable for snake_instance initialization so it can be used locally in classes.
- Added
TrustCacheParser,SingatureReaderandextract_cms.shtoREADME.md - Added
.gitignore - Added
requirements.txt - Made
README.mdbetter - Updated links to articles