mirror of
https://github.com/Karmaz95/Snake_Apple.git
synced 2026-03-30 14:00:16 +02:00
Uploading UUIDFinder tool
This commit is contained in:
225
IX. TCC/python/UUIDFinder.py
Normal file
225
IX. TCC/python/UUIDFinder.py
Normal file
@@ -0,0 +1,225 @@
|
||||
import os
|
||||
import json
|
||||
import subprocess
|
||||
import argparse
|
||||
from typing import List, Optional, Dict
|
||||
|
||||
DEFAULT_DATABASE_FILE = 'uuid_database.json'
|
||||
|
||||
class UUIDFinder:
|
||||
def __init__(self, db_location: str = DEFAULT_DATABASE_FILE):
|
||||
"""Initialize UUIDFinder with database location."""
|
||||
self.db_location = db_location
|
||||
self.database = self.load_database()
|
||||
|
||||
def load_database(self) -> dict:
|
||||
"""Load the UUID database from a JSON file."""
|
||||
if os.path.exists(self.db_location):
|
||||
with open(self.db_location, 'r') as file:
|
||||
return json.load(file)
|
||||
return {}
|
||||
|
||||
def save_database(self):
|
||||
"""Save the UUID database to a JSON file."""
|
||||
with open(self.db_location, 'w') as file:
|
||||
json.dump(self.database, file, indent=4)
|
||||
|
||||
def extract_uuids(self, path: str) -> List[str]:
|
||||
"""Extract UUIDs from a Mach-O file using dwarfdump."""
|
||||
uuids = []
|
||||
try:
|
||||
result = subprocess.run(['dwarfdump', '--uuid', path],
|
||||
capture_output=True, text=True)
|
||||
if result.returncode == 0:
|
||||
for line in result.stdout.splitlines():
|
||||
if 'UUID:' in line:
|
||||
uuid = line.split(':')[1].strip().split()[0].lower()
|
||||
uuids.append(uuid)
|
||||
except Exception as e:
|
||||
print(f"Error extracting UUIDs from {path}: {e}")
|
||||
return uuids
|
||||
|
||||
def get_path_uuids(self, path: str) -> Optional[List[str]]:
|
||||
"""Get UUIDs for a given path from the database."""
|
||||
return self.database.get(path)
|
||||
|
||||
def get_path_by_uuid(self, uuid: str) -> Optional[str]:
|
||||
"""Find path corresponding to a given UUID."""
|
||||
uuid = uuid.lower()
|
||||
for path, uuids in self.database.items():
|
||||
if uuid in uuids:
|
||||
return path
|
||||
return None
|
||||
|
||||
def handle_path_uuid(self, path: str, uuid: str):
|
||||
"""Handle path and UUID combination for database operations."""
|
||||
absolute_path = os.path.abspath(path)
|
||||
uuid = uuid.lower()
|
||||
|
||||
if absolute_path in self.database:
|
||||
if uuid in self.database[absolute_path]:
|
||||
print(f"Record with UUID {uuid} already exists for {absolute_path}")
|
||||
else:
|
||||
print(f"Adding UUID {uuid} to existing record for {absolute_path}")
|
||||
self.database[absolute_path].append(uuid)
|
||||
else:
|
||||
print(f"Creating new record for {absolute_path} with UUID {uuid}")
|
||||
self.database[absolute_path] = [uuid]
|
||||
|
||||
def delete_path(self, path: str):
|
||||
"""Delete a path and its UUIDs from the database."""
|
||||
absolute_path = os.path.abspath(path)
|
||||
if absolute_path in self.database:
|
||||
print(f"Deleting record for: {absolute_path}")
|
||||
del self.database[absolute_path]
|
||||
else:
|
||||
print(f"No record found for: {absolute_path}")
|
||||
|
||||
def resolve_uuid(self, path: str):
|
||||
"""Get UUIDs for a path and add them to the database."""
|
||||
absolute_path = os.path.abspath(path)
|
||||
if not os.path.isfile(absolute_path) or not os.access(absolute_path, os.X_OK):
|
||||
print(f"Invalid path or not an executable: {absolute_path}")
|
||||
return
|
||||
|
||||
uuids = self.extract_uuids(absolute_path)
|
||||
if uuids:
|
||||
print(f"{absolute_path}: {', '.join(uuids)}")
|
||||
self.database[absolute_path] = uuids
|
||||
else:
|
||||
print(f"No UUIDs found in {absolute_path}")
|
||||
|
||||
def show_database(self):
|
||||
"""Display all records in the database."""
|
||||
if not self.database:
|
||||
print("Database is empty")
|
||||
return
|
||||
|
||||
print("\nDatabase contents:")
|
||||
print("-----------------")
|
||||
for path, uuids in self.database.items():
|
||||
print(f"{path}", end="")
|
||||
print(f"{', '.join(uuids)}")
|
||||
print("\n-----------------")
|
||||
|
||||
def process_paths(args):
|
||||
"""Process paths based on provided arguments."""
|
||||
finder = UUIDFinder(args.db_location)
|
||||
|
||||
# Handle show_db flag
|
||||
if args.show_db:
|
||||
finder.show_database()
|
||||
return
|
||||
|
||||
# Handle UUID lookup without path
|
||||
if args.uuid and not args.path and not args.list:
|
||||
path = finder.get_path_by_uuid(args.uuid)
|
||||
if path:
|
||||
print(f"Path for UUID {args.uuid}: {path}")
|
||||
else:
|
||||
print(f"No path found for UUID: {args.uuid}")
|
||||
return
|
||||
|
||||
paths = []
|
||||
if args.path:
|
||||
paths = [args.path]
|
||||
elif args.list:
|
||||
if os.path.isfile(args.list):
|
||||
with open(args.list, 'r') as file:
|
||||
paths = [line.strip() for line in file if line.strip()]
|
||||
else:
|
||||
print(f"Invalid list file: {args.list}")
|
||||
return
|
||||
|
||||
for path in paths:
|
||||
absolute_path = os.path.abspath(path)
|
||||
|
||||
if args.delete:
|
||||
finder.delete_path(absolute_path)
|
||||
elif args.uuid:
|
||||
finder.handle_path_uuid(absolute_path, args.uuid)
|
||||
elif args.resolve:
|
||||
finder.resolve_uuid(absolute_path)
|
||||
else:
|
||||
# Default behavior: display UUIDs for the path
|
||||
uuids = finder.get_path_uuids(absolute_path)
|
||||
if uuids:
|
||||
print(f"UUIDs for {absolute_path}: {', '.join(uuids)}")
|
||||
else:
|
||||
print(f"No UUIDs found for {absolute_path}")
|
||||
|
||||
finder.save_database()
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description='UUIDFinder - A tool for managing Mach-O executable UUIDs',
|
||||
formatter_class=argparse.RawTextHelpFormatter,
|
||||
epilog="""
|
||||
Examples:
|
||||
---------
|
||||
|
||||
1. Display UUIDs for a single executable from database:
|
||||
--path /path/to/executable
|
||||
-p /path/to/executable
|
||||
|
||||
2. Find path for a specific UUID in database:
|
||||
--uuid 123e4567-e89b-12d3-a456-426614174000
|
||||
-u 123e4567-e89b-12d3-a456-426614174000
|
||||
|
||||
3. Add or update UUID for a path:
|
||||
--path /path/to/executable --uuid 123e4567-e89b-12d3-a456-426614174000
|
||||
-p /path/to/executable -u 123e4567-e89b-12d3-a456-426614174000
|
||||
|
||||
4. Extract and add UUIDs from executable to database:
|
||||
--path /path/to/executable --resolve
|
||||
-p /path/to/executable -r
|
||||
|
||||
5. Delete path and its UUIDs from database:
|
||||
--path /path/to/executable --delete
|
||||
-p /path/to/executable -d
|
||||
|
||||
6. Process multiple executables from a list file:
|
||||
--list /path/to/list.txt --resolve
|
||||
-l /path/to/list.txt -r
|
||||
|
||||
7. Show all records in the database:
|
||||
--show_db
|
||||
-s
|
||||
|
||||
8. Use custom database location:
|
||||
--path /path/to/executable --db_location /custom/path/db.json
|
||||
-p /path/to/executable --db_location /custom/path/db.json
|
||||
|
||||
Notes:
|
||||
------
|
||||
- All UUIDs are stored in lowercase in the database
|
||||
- The default database file is 'uuid_database.json' in the current directory
|
||||
- When using --list, each path should be on a new line in the list file
|
||||
- The tool automatically converts relative paths to absolute paths
|
||||
""")
|
||||
|
||||
# Path specification group
|
||||
path_group = parser.add_mutually_exclusive_group()
|
||||
path_group.add_argument('--path', '-p', help='Path to the executable')
|
||||
path_group.add_argument('--list', '-l', help='Path to a file containing a list of executables')
|
||||
|
||||
# Action group
|
||||
parser.add_argument('--uuid', '-u', help='UUID to lookup or add')
|
||||
parser.add_argument('--delete', '-d', action='store_true', help='Delete the path record from database')
|
||||
parser.add_argument('--resolve', '-r', action='store_true', help='Get UUIDs for the path and add to database')
|
||||
parser.add_argument('--show_db', '-s', action='store_true', help='Show all records in the database')
|
||||
|
||||
# Database location
|
||||
parser.add_argument('--db_location', default=DEFAULT_DATABASE_FILE,
|
||||
help='Location of the UUID database file')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Validate that at least one argument is provided
|
||||
if not any([args.path, args.list, args.show_db, args.uuid]):
|
||||
parser.error("At least one of --path, --list, --show_db, or --uuid is required")
|
||||
|
||||
process_paths(args)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user