mirror of
https://github.com/leminlimez/Nugget.git
synced 2025-04-08 04:23:05 +08:00
all of nugget's features
This commit is contained in:
0
devicemanagement/__init__.py
Normal file
0
devicemanagement/__init__.py
Normal file
BIN
devicemanagement/__pycache__/__init__.cpython-312.pyc
Normal file
BIN
devicemanagement/__pycache__/__init__.cpython-312.pyc
Normal file
Binary file not shown.
BIN
devicemanagement/__pycache__/constants.cpython-312.pyc
Normal file
BIN
devicemanagement/__pycache__/constants.cpython-312.pyc
Normal file
Binary file not shown.
BIN
devicemanagement/__pycache__/data_singleton.cpython-312.pyc
Normal file
BIN
devicemanagement/__pycache__/data_singleton.cpython-312.pyc
Normal file
Binary file not shown.
BIN
devicemanagement/__pycache__/device_manager.cpython-312.pyc
Normal file
BIN
devicemanagement/__pycache__/device_manager.cpython-312.pyc
Normal file
Binary file not shown.
94
devicemanagement/constants.py
Normal file
94
devicemanagement/constants.py
Normal file
@@ -0,0 +1,94 @@
|
||||
from enum import Enum
|
||||
from pymobiledevice3.lockdown import LockdownClient
|
||||
|
||||
class Device:
|
||||
def __init__(self, uuid: int, name: str, version: str, model: str, locale: str, ld: LockdownClient):
|
||||
self.uuid = uuid
|
||||
self.name = name
|
||||
self.version = version
|
||||
self.model = model
|
||||
self.locale = locale
|
||||
self.ld = ld
|
||||
|
||||
class Version:
|
||||
def __init__(self, major: int, minor: int = 0, patch: int = 0):
|
||||
self.major = major
|
||||
self.minor = minor
|
||||
self.patch = patch
|
||||
|
||||
def __init__(self, ver: str):
|
||||
nums: list[str] = ver.split(".")
|
||||
self.major = int(nums[0])
|
||||
self.minor = int(nums[1]) if len(nums) > 1 else 0
|
||||
self.patch = int(nums[2]) if len(nums) > 2 else 0
|
||||
|
||||
# Comparison Functions
|
||||
def compare_to(self, other) -> int:
|
||||
if self.major > other.major:
|
||||
return 1
|
||||
elif self.major < other.major:
|
||||
return -1
|
||||
if self.minor > other.minor:
|
||||
return 1
|
||||
elif self.minor < other.minor:
|
||||
return -1
|
||||
if self.patch > other.patch:
|
||||
return 1
|
||||
elif self.patch < other.patch:
|
||||
return -1
|
||||
return 0
|
||||
|
||||
def __gt__(self, other) -> bool:
|
||||
return self.compare_to(other) == 1
|
||||
def __ge__(self, other) -> bool:
|
||||
comp: int = self.compare_to(other)
|
||||
return comp == 0 or comp == 1
|
||||
|
||||
def __lt__(self, other) -> bool:
|
||||
return self.compare_to(other) == -1
|
||||
def __le__(self, other) -> bool:
|
||||
comp: int = self.compare_to(other)
|
||||
return comp == 0 or comp == -1
|
||||
|
||||
def __eq__(self, other) -> bool:
|
||||
return self.compare_to(other) == 0
|
||||
|
||||
class Tweak(Enum):
|
||||
StatusBar = 'Status Bar'
|
||||
SpringboardOptions = 'Springboard Options'
|
||||
InternalOptions = 'Internal Options'
|
||||
SkipSetup = 'Setup Options'
|
||||
|
||||
class FileLocation(Enum):
|
||||
# Control Center
|
||||
mute = "ControlCenter/ManagedPreferencesDomain/mobile/com.apple.control-center.MuteModule.plist"
|
||||
focus = "ControlCenter/ManagedPreferencesDomain/mobile/com.apple.FocusUIModule.plist"
|
||||
spoken = "ControlCenter/ManagedPreferencesDomain/mobile/com.apple.siri.SpokenNotificationsModule.plist"
|
||||
module_config = "ControlCenter/HomeDomain/Library/ControlCenter/ModuleConfiguration.plist"
|
||||
replay_kit_audio = "ControlCenter/ManagedPreferencesDomain/mobile/com.apple.replaykit.AudioConferenceControlCenterModule.plist"
|
||||
replay_kit_video = "ControlCenter/ManagedPreferencesDomain/mobile/com.apple.replaykit.VideoConferenceControlCenterModule.plist"
|
||||
|
||||
# Status Bar
|
||||
status_bar = "StatusBar/HomeDomain/Library/SpringBoard/statusBarOverrides"
|
||||
|
||||
# Springboard Options
|
||||
springboard = "SpringboardOptions/ManagedPreferencesDomain/mobile/com.apple.springboard.plist"
|
||||
footnote = "SpringboardOptions/ConfigProfileDomain/Library/ConfigurationProfiles/SharedDeviceConfiguration.plist"
|
||||
wifi = "SpringboardOptions/SystemPreferencesDomain/SystemConfiguration/com.apple.wifi.plist"
|
||||
uikit = "SpringboardOptions/ManagedPreferencesDomain/mobile/com.apple.UIKit.plist"
|
||||
accessibility = "SpringboardOptions/ManagedPreferencesDomain/mobile/com.apple.Accessibility.plist"
|
||||
wifi_debug = "SpringboardOptions/ManagedPreferencesDomain/mobile/com.apple.MobileWiFi.debug.plist"
|
||||
airdrop = "SpringboardOptions/ManagedPreferencesDomain/mobile/com.apple.sharingd.plist"
|
||||
|
||||
# Internal Options
|
||||
global_prefs = "InternalOptions/ManagedPreferencesDomain/mobile/hiddendotGlobalPreferences.plist"
|
||||
app_store = "InternalOptions/ManagedPreferencesDomain/mobile/com.apple.AppStore.plist"
|
||||
backboardd = "InternalOptions/ManagedPreferencesDomain/mobile/com.apple.backboardd.plist"
|
||||
core_motion = "InternalOptions/ManagedPreferencesDomain/mobile/com.apple.CoreMotion.plist"
|
||||
pasteboard = "InternalOptions/HomeDomain/Library/Preferences/com.apple.Pasteboard.plist"
|
||||
notes = "InternalOptions/ManagedPreferencesDomain/mobile/com.apple.mobilenotes.plist"
|
||||
maps = "InternalOptions/AppDomain-com.apple.Maps/Library/Preferences/com.apple.Maps.plist"
|
||||
weather = "InternalOptions/AppDomain-com.apple.weather/Library/Preferences/com.apple.weather.plist"
|
||||
|
||||
# Setup Options
|
||||
cloud_config = "SkipSetup/ConfigProfileDomain/Library/ConfigurationProfiles/CloudConfigurationDetails.plist"
|
||||
9
devicemanagement/data_singleton.py
Normal file
9
devicemanagement/data_singleton.py
Normal file
@@ -0,0 +1,9 @@
|
||||
from pathlib import Path
|
||||
|
||||
from devicemanagement.constants import Device, Tweak
|
||||
|
||||
class DataSingleton:
|
||||
def __init__(self):
|
||||
self.current_device: Device
|
||||
self.device_available: bool = False
|
||||
self.gestalt_path = None
|
||||
182
devicemanagement/device_manager.py
Normal file
182
devicemanagement/device_manager.py
Normal file
@@ -0,0 +1,182 @@
|
||||
import traceback
|
||||
import plistlib
|
||||
from pathlib import Path
|
||||
|
||||
from PySide6.QtWidgets import QMessageBox
|
||||
|
||||
from pymobiledevice3 import usbmux
|
||||
from pymobiledevice3.lockdown import create_using_usbmux
|
||||
|
||||
from devicemanagement.constants import Device, Version
|
||||
from devicemanagement.data_singleton import DataSingleton
|
||||
|
||||
from tweaks.tweaks import tweaks, FeatureFlagTweak, EligibilityTweak
|
||||
from exploit.restore import restore_files, FileToRestore
|
||||
|
||||
def show_error_msg(txt: str):
|
||||
detailsBox = QMessageBox()
|
||||
detailsBox.setIcon(QMessageBox.Critical)
|
||||
detailsBox.setWindowTitle("Error!")
|
||||
detailsBox.setText(txt)
|
||||
detailsBox.setDetailedText(str(traceback.format_exc()))
|
||||
detailsBox.exec()
|
||||
|
||||
class DeviceManager:
|
||||
min_version: Version = Version("17")
|
||||
|
||||
## Class Functions
|
||||
def __init__(self):
|
||||
self.devices: list[Device] = []
|
||||
self.data_singleton = DataSingleton()
|
||||
self.current_device_index = 0
|
||||
self.apply_over_wifi = True
|
||||
|
||||
def get_devices(self):
|
||||
self.devices.clear()
|
||||
connected_devices = usbmux.list_devices()
|
||||
# Connect via usbmuxd
|
||||
for device in connected_devices:
|
||||
if self.apply_over_wifi or device.is_usb:
|
||||
try:
|
||||
ld = create_using_usbmux(serial=device.serial)
|
||||
vals = ld.all_values
|
||||
dev = Device(
|
||||
uuid=device.serial,
|
||||
name=vals['DeviceName'],
|
||||
version=vals['ProductVersion'],
|
||||
model=vals['ProductType'],
|
||||
locale=ld.locale,
|
||||
ld=ld
|
||||
)
|
||||
self.devices.append(dev)
|
||||
except Exception as e:
|
||||
print(f"ERROR with lockdown device with UUID {device.serial}")
|
||||
show_error_msg(type(e).__name__)
|
||||
|
||||
if len(connected_devices) > 0:
|
||||
self.set_current_device(index=0)
|
||||
else:
|
||||
self.set_current_device(index=None)
|
||||
|
||||
## CURRENT DEVICE
|
||||
def set_current_device(self, index: int = None):
|
||||
if index == None:
|
||||
self.data_singleton.current_device = None
|
||||
self.data_singleton.device_available = False
|
||||
self.data_singleton.gestalt_path = None
|
||||
self.current_device_index = 0
|
||||
else:
|
||||
self.data_singleton.current_device = self.devices[index]
|
||||
if Version(self.devices[index].version) < DeviceManager.min_version:
|
||||
self.data_singleton.device_available = False
|
||||
self.data_singleton.gestalt_path = None
|
||||
else:
|
||||
self.data_singleton.device_available = True
|
||||
self.current_device_index = index
|
||||
|
||||
def get_current_device_name(self) -> str:
|
||||
if self.data_singleton.current_device == None:
|
||||
return "No Device"
|
||||
else:
|
||||
return self.data_singleton.current_device.name
|
||||
|
||||
def get_current_device_version(self) -> str:
|
||||
if self.data_singleton.current_device == None:
|
||||
return ""
|
||||
else:
|
||||
return self.data_singleton.current_device.version
|
||||
|
||||
def get_current_device_uuid(self) -> str:
|
||||
if self.data_singleton.current_device == None:
|
||||
return ""
|
||||
else:
|
||||
return self.data_singleton.current_device.uuid
|
||||
|
||||
|
||||
## APPLYING OR REMOVING TWEAKS AND RESTORING
|
||||
def apply_changes(self, resetting: bool = False, update_label=lambda x: None):
|
||||
# set the tweaks and apply
|
||||
# first open the file in read mode
|
||||
update_label("Applying changes to files...")
|
||||
gestalt_plist = None
|
||||
if self.data_singleton.gestalt_path != None:
|
||||
with open(self.data_singleton.gestalt_path, 'rb') as in_fp:
|
||||
gestalt_plist = plistlib.load(in_fp)
|
||||
# create the other plists
|
||||
flag_plist: dict = {}
|
||||
eligibility_files = None
|
||||
|
||||
# set the plist keys
|
||||
if not resetting:
|
||||
for tweak_name in tweaks:
|
||||
tweak = tweaks[tweak_name]
|
||||
if isinstance(tweak, FeatureFlagTweak):
|
||||
flag_plist = tweak.apply_tweak(flag_plist)
|
||||
elif isinstance(tweak, EligibilityTweak):
|
||||
eligibility_files = tweak.apply_tweak()
|
||||
else:
|
||||
if gestalt_plist != None:
|
||||
gestalt_plist = tweak.apply_tweak(gestalt_plist)
|
||||
|
||||
# Generate backup
|
||||
update_label("Generating backup...")
|
||||
# create the restore file list
|
||||
files_to_restore = [
|
||||
FileToRestore(
|
||||
contents=plistlib.dumps(flag_plist),
|
||||
restore_path="/var/preferences/FeatureFlags/",
|
||||
restore_name="Global.plist"
|
||||
)
|
||||
]
|
||||
if gestalt_plist != None:
|
||||
files_to_restore.append(FileToRestore(
|
||||
contents=plistlib.dumps(gestalt_plist),
|
||||
restore_path="/var/containers/Shared/SystemGroup/systemgroup.com.apple.mobilegestaltcache/Library/Caches/",
|
||||
restore_name="com.apple.MobileGestalt.plist"
|
||||
))
|
||||
if eligibility_files:
|
||||
files_to_restore += eligibility_files
|
||||
|
||||
# restore to the device
|
||||
update_label("Restoring to device...")
|
||||
try:
|
||||
restore_files(files=files_to_restore, reboot=True, lockdown_client=self.data_singleton.current_device.ld)
|
||||
QMessageBox.information(None, "Success!", "All done! Your device will now restart.")
|
||||
update_label("Success!")
|
||||
except Exception as e:
|
||||
if "Find My" in str(e):
|
||||
detailsBox = QMessageBox()
|
||||
detailsBox.setIcon(QMessageBox.Critical)
|
||||
detailsBox.setWindowTitle("Error!")
|
||||
detailsBox.setText("Find My must be disabled in order to use this tool.")
|
||||
detailsBox.setDetailedText("Disable Find My from Settings (Settings -> [Your Name] -> Find My) and then try again.")
|
||||
detailsBox.exec()
|
||||
else:
|
||||
print(traceback.format_exc())
|
||||
update_label("Failed to restore")
|
||||
show_error_msg(type(e).__name__)
|
||||
|
||||
## RESETTING MOBILE GESTALT
|
||||
def reset_mobilegestalt(self, update_label=lambda x: None):
|
||||
# restore to the device
|
||||
update_label("Restoring to device...")
|
||||
try:
|
||||
restore_files(files=[FileToRestore(
|
||||
contents=b"",
|
||||
restore_path="/var/containers/Shared/SystemGroup/systemgroup.com.apple.mobilegestaltcache/Library/Caches/",
|
||||
restore_name="com.apple.MobileGestalt.plist"
|
||||
)], reboot=True, lockdown_client=self.data_singleton.current_device.ld)
|
||||
QMessageBox.information(None, "Success!", "All done! Your device will now restart.")
|
||||
update_label("Success!")
|
||||
except Exception as e:
|
||||
if "Find My" in str(e):
|
||||
detailsBox = QMessageBox()
|
||||
detailsBox.setIcon(QMessageBox.Critical)
|
||||
detailsBox.setWindowTitle("Error!")
|
||||
detailsBox.setText("Find My must be disabled in order to use this tool.")
|
||||
detailsBox.setDetailedText("Disable Find My from Settings (Settings -> [Your Name] -> Find My) and then try again.")
|
||||
detailsBox.exec()
|
||||
else:
|
||||
print(traceback.format_exc())
|
||||
update_label("Failed to restore")
|
||||
show_error_msg(type(e).__name__)
|
||||
Reference in New Issue
Block a user