This commit is contained in:
Karmaz95
2024-02-04 19:39:27 +01:00
parent c5c1aeef65
commit bf82224406
6 changed files with 1377 additions and 103 deletions

5
.gitignore vendored
View File

@@ -8,4 +8,7 @@
__pycache__/
# Exclude pytest_cache directories
.pytest_cache/
.pytest_cache/
# Exclude changes_release.md
changes_release.md

View File

@@ -1,3 +1,4 @@
// clang -fobjc-arc -framework Foundation example.m -o arc_example
#import <Foundation/Foundation.h>
@interface Person : NSObject

View File

@@ -21,19 +21,20 @@ class MachOProcessor:
'''Return Fat Binary object.'''
return lief.MachO.parse(self.file_path)
def process(self):
def process(self, args):
'''Executes the code for the SnakeI: Mach-O.'''
if not os.path.exists(self.file_path): # Check if file_path specified in the --path argument exists.
print(f'The file {self.file_path} does not exist.')
exit()
global binaries # It must be global, becuase after the class is destructed, the snake_instance would point to invalid memory ("binary" is dependant on "binaries").
global binaries # It must be global, becuase after the MachOProcessor object is destructed, the snake_instance would point to invalid memory ("binary" is dependant on "binaries").
global snake_instance # Must be global for further processors classes.
binaries = self.parseFatBinary()
if binaries == None:
exit() # Exit if not
global snake_instance # Must be globall for further processors classes.
snake_instance = SnakeV(binaries, self.file_path) # Initialize the latest Snake class
if args.file_type: # Print binary file type
@@ -356,21 +357,21 @@ class CodeSigningProcessor:
'''This class contains part of the code from the main() for the SnakeII: Code Signing.'''
pass
def process(self):
def process(self, args):
if args.verify_signature: # Verify if Code Signature match the binary content ()
if snake_instance.isSigValid(file_path):
if snake_instance.isSigValid(snake_instance.file_path):
print("Valid Code Signature (matches the content)")
else:
print("Invalid Code Signature (does not match the content)")
if args.cd_info: # Print Code Signature information
print(snake_instance.getCodeSignature(file_path).decode('utf-8'))
print(snake_instance.getCodeSignature(snake_instance.file_path).decode('utf-8'))
if args.cd_requirements: # Print Requirements.
print(snake_instance.getCodeSignatureRequirements(file_path).decode('utf-8'))
print(snake_instance.getCodeSignatureRequirements(snake_instance.file_path).decode('utf-8'))
if args.entitlements: # Print Entitlements.
print(snake_instance.getEntitlementsFromCodeSignature(file_path,args.entitlements))
print(snake_instance.getEntitlementsFromCodeSignature(snake_instance.file_path, args.entitlements))
if args.extract_cms: # Extract the CMS Signature and save it to a given file.
cms_signature = snake_instance.extractCMS()
@@ -436,21 +437,21 @@ class SnakeII(SnakeI):
def extractCertificatesFromCodeSignature(self, cert_name):
'''Extracts certificates from the CMS Signature and saves them to a file with _0, _1, _2 indexes at the end of the file names.'''
subprocess.run(["codesign", "-d", f"--extract-certificates={cert_name}_", file_path], capture_output=True)
subprocess.run(["codesign", "-d", f"--extract-certificates={cert_name}_", self.file_path], capture_output=True)
def removeCodeSignature(self, new_name):
'''Save new file on a disk with removed signature.'''
self.binary.remove_signature()
self.binary.write(new_name)
def signBinary(self,security_identity=None):
def signBinary(self, security_identity=None):
'''Sign binary using pseudo identity (adhoc) or specified identity.'''
if security_identity == 'adhoc' or security_identity == None:
result = subprocess.run(["codesign", "-s", "-", "-f", file_path], capture_output=True)
result = subprocess.run(["codesign", "-s", "-", "-f", self.file_path], capture_output=True)
return result.stdout.decode('utf-8')
else:
try:
result = subprocess.run(["codesign", "-s", security_identity, "-f", file_path], capture_output=True)
result = subprocess.run(["codesign", "-s", security_identity, "-f", self.file_path], capture_output=True)
except Exception as e:
print(f"An error occurred during Code Signing using {security_identity}\n {e}")
@@ -460,7 +461,7 @@ class ChecksecProcessor:
'''This class contains part of the code from the main() for the SnakeIII: Checksec.'''
pass
def process(self):
def process(self, args):
if args.has_pie: # Check if PIE is set in the header flags
print("PIE: " + str(snake_instance.hasPIE()))
@@ -713,7 +714,7 @@ class DylibsProcessor:
'''This class contains part of the code from the main() for the SnakeIV: Dylibs.'''
pass
def process(self):
def process(self, args):
if args.dylibs: # Shared dylibs with unresolved paths
snake_instance.printDylibs()
@@ -744,7 +745,7 @@ class DylibsProcessor:
print(*snake_instance.getReExportPaths(), sep="\n")
if args.hijack_sec: # Check Dylib Hijacking protection on binary
print("DYLIB HIJACKIG PROTECTION: " + str(snake_instance.checkDylibHijackingProtections(file_path)))
print("DYLIB HIJACKIG PROTECTION: " + str(snake_instance.checkDylibHijackingProtections(snake_instance.file_path)))
if args.dylib_hijacking: # Direct & Indirect Dylib Hijacking check
if args.dylib_hijacking == 'default':
@@ -1376,7 +1377,7 @@ class DyldProcessor:
'''This class contains part of the code from the main() for the SnakeV: Dyld.'''
pass
def process(self):
def process(self, args):
if args.is_built_for_sim: # Check if binary is build for a simulator
snake_instance.printIsBuiltForSimulator()
@@ -1562,20 +1563,20 @@ if __name__ == "__main__":
### --- I. MACH-O --- ###
macho_processor = MachOProcessor(file_path)
macho_processor.process()
macho_processor.process(args)
### --- II. CODE SIGNING --- ###
code_signing_processor = CodeSigningProcessor()
code_signing_processor.process()
code_signing_processor.process(args)
### --- III. CHECKSEC --- ###
checksec_processor = ChecksecProcessor()
checksec_processor.process()
checksec_processor.process(args)
### --- IV. DYLIBS --- ###
dylibs_processor = DylibsProcessor()
dylibs_processor.process()
dylibs_processor.process(args)
### --- V. DYLD --- ###
dyld_processor = DyldProcessor()
dyld_processor.process()
dyld_processor.process(args)

View File

@@ -4,3 +4,4 @@ argparse
asn1crypto
pyimg4
treelib
xattr

View File

@@ -1,81 +0,0 @@
import pytest
import subprocess
from CrimsonUroboros import * # Symlinked to the source file, which is the latest version of the CrimsonUroboros.py file.
class Compiler:
def __init__(self):
self.compiled_files = [] # Stores the paths to the compiled files.
def compile(self, cmd):
"""
Compile C code using the given compile command.
Args:
cmd (str): The compile command to run.
Returns:
int: Return code of the compilation process.
"""
result = subprocess.run(cmd, shell=True)
return result.returncode
def buildClangCommand(self, source, output, flags=None):
"""
Build a clang compile command string based on the source file, output file, and optional flags.
Args:
source (str): Path to the source file.
output (str): Path to the output file.
flags (list, optional): List of additional flags. Defaults to None.
Returns:
str: Compiled clang command string.
"""
cmd_parts = ["clang"]
cmd_parts.append(source)
cmd_parts.extend(["-o", output])
if flags:
cmd_parts.extend(flags)
return ' '.join(cmd_parts)
def compileIt(self, source, output, flags=None):
"""
Compile the given source file using clang.
Args:
source (str): The path to the source file.
output (str): The path to the output file.
flags (list, optional): Additional compilation flags. Defaults to None.
Returns:
int: The exit code of the compilation process.
"""
cmd = self.buildClangCommand(source, output, flags)
result = self.compile(cmd)
self.compiled_files.append(output)
return result
def purgeCompiledFiles(self):
"""
Remove all compiled files.
"""
for file in self.compiled_files:
subprocess.run(["rm", file])
'''# TODO:
compiler = Compiler()
compiler.compileIt("../I.\ Mach-O/custom/hello.c", "hello")
print(compiler.compiled_files)
class TestSnakeI:
def test_method1(self):
''''''
# Test_
obj = CrimsonUroboros()
input_data = 1
expected_output = 2
assert obj.method1(input_data) == expected_output
'''

File diff suppressed because it is too large Load Diff