Skip to content
This repository has been archived by the owner on Jan 20, 2025. It is now read-only.

Commit

Permalink
all of nugget's features
Browse files Browse the repository at this point in the history
  • Loading branch information
leminlimez committed Sep 18, 2024
1 parent 347a34e commit df5dd5d
Show file tree
Hide file tree
Showing 73 changed files with 20,376 additions and 176 deletions.
43 changes: 37 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,47 @@
# CODENAME Nugget
# Nugget
Unlock your device's full potential! Works on all versions iOS 17.0+

This uses the sparserestore exploit to write to files outside of the intended restore location, like mobilegestalt.

Note: I am not responsible if your device bootloops. Please back up your data before using.

## Features
- Enable Dynamic Island on any device
- Change Device Model Name
- Enable iPhone X gestures on iPhone SEs
- Change Device Model Name (ie what shows in the Settings app)
- Enable Boot Chime
- Enable Charge Limit
- Enable Tap to Wake on unsupported devices (ie iPhone SEs)
- Enable iPhone 16 Settings
- Enable Collision SOS
- Enable Stage Manager
- Disable the Wallpaper Parallax
- Disable Region Restrictions (ie. Shutter Sound)
- Note: This does not include enabling EU sideloading outside the EU. That will come later.
- Enable AOD on any device
- Show the Apple Pencil options in Settings app
- Show the Action Button options in Settings app
- Show Internal Storage info (Might cause problems on some devices, use at your own risk)
- Enabling lock screen clock animation, lock screen page duplication button, and more!
- Disabling the new iOS 18 Photos UI
- EU Enabler

## Running the Program
Requirements:
- pymobiledevice3
- Python 3.8 or newer

Note: It is highly recommended to use a virtual environment:
```
python -m venv .env # only needed once
source .env/bin/activate
pip install -r requirements.txt # only needed once
python main_app.py
python3 -m venv .env # only needed once
# macOS/Linux: source .env/bin/activate
# Windows: .env/Scripts/activate.bat
pip3 install -r requirements.txt # only needed once
python3 main_app.py
```
Note: It may be either `python`/`pip` or `python3`/`pip3` depending on your path.

The CLI version can be ran with `python3 cli_app.py`.

## Getting the File
You need to get the mobilegestalt file that is specific to your device. To do that, follow these steps:
Expand All @@ -29,7 +50,17 @@ You need to get the mobilegestalt file that is specific to your device. To do th
3. Save the file and share it to your computer.
4. Place it in the same folder as the python file (or specify the path in the program)

## Building
To compile `mainwindow.ui` for Python, run the following command:
`pyside6-uic qt/mainwindow.ui -o qt/ui_mainwindow.py`

To compile the resources file for Python, run the following command:
`pyside6-rcc qt/resources.qrc -o resources_rc.py`

The application itself can be compiled by running `compile.py`.

## Credits
- [JJTech](https://github.com/JJTech0130) for Sparserestore/[TrollRestore](https://github.com/JJTech0130/TrollRestore)
- [pymobiledevice3](https://github.com/doronz88/pymobiledevice3)
- [disfordottie](https://x.com/disfordottie) for some global flag features

215 changes: 215 additions & 0 deletions cli_app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
from exploit.restore import restore_files, FileToRestore, restore_file
from tweaks.tweaks import tweaks, TweakModifyType, FeatureFlagTweak, EligibilityTweak
from devicemanagement.constants import Device

from pymobiledevice3.exceptions import PyMobileDevice3Exception
from pymobiledevice3.services.diagnostics import DiagnosticsService
from pymobiledevice3 import usbmux
from pymobiledevice3.lockdown import create_using_usbmux

from pathlib import Path
import plistlib
import traceback

running = True
passed_check = False
num_tweaks = len(tweaks)

gestalt_path = Path.joinpath(Path.cwd(), "com.apple.MobileGestalt.plist")
flags_path = Path.joinpath(Path.cwd(), "Global.plist")
device = None

def print_option(num: int, active: bool, message: str):
txt = str(num) + ". "
if active:
txt = txt + "[Y] "
txt = txt + message
print(txt)

def get_apply_number(num: int) -> int:
return num + 5-num%5

while running:
print("""\n\n\n\n
,--.
,--.'| ___
,--,: : | ,--.'|_
,`--.'`| ' : ,--, | | :,'
| : : | | ,'_ /| ,----._,. ,----._,. : : ' :
: | \\ | : .--. | | : / / ' / / / ' / ,---. .;__,' /
| : ' '; |,'_ /| : . || : || : | / \\ | | |
' ' ;. ;| ' | | . .| | .\\ .| | .\\ . / / |:__,'| :
| | | \\ || | ' | | |. ; '; |. ; '; |. ' / | ' : |__
' : | ; .': | : ; ; |' . . |' . . |' ; /| | | '.'|
| | '`--' ' : `--' \\`---`-'| | `---`-'| |' | / | ; : ;
' : | : , .-./.'__/\\_: | .'__/\\_: || : | | , /
; |.' `--`----' | : : | : : \\ \\ / ---`-'
'---' \\ \\ / \\ \\ / `----'
`--`-' `--`-'
""")
print("CLI v2.2")
print("by LeminLimez")
print("Thanks @disfordottie for the clock animation and @lrdsnow for EU Enabler\n")
print("Please back up your device before using!")

while device == None:
connected_devices = usbmux.list_devices()
# Connect via usbmuxd
for current_device in connected_devices:
if current_device.is_usb:
try:
ld = create_using_usbmux(serial=current_device.serial)
vals = ld.all_values
device = Device(uuid=current_device.serial, name=vals['DeviceName'], version=vals['ProductVersion'], model=vals['ProductType'], locale=ld.locale, ld=ld)
except Exception as e:
print(traceback.format_exc())
input("Press Enter to continue...")

if device == None:
print("Please connect your device and try again!")
input("Press Enter to continue...")

print(f"Connected to {device.name}\niOS {device.version}\n")

if not passed_check and Path.exists(gestalt_path) and Path.is_file(gestalt_path):
passed_check = True

if passed_check:
count = 0
for key in tweaks:
count += 1
# do not show if the tweak is not compatible
if tweaks[key].is_compatible(device.version):
print_option(count, tweaks[key].enabled, tweaks[key].label)
if tweaks[key].divider_below:
print()

# apply will still be the number of tweaks just to keep consistency
print(f"\n{get_apply_number(num_tweaks + 1)}. Apply")
print(f"{get_apply_number(num_tweaks + 1) + 1}. Remove All Tweaks")
print(f"{get_apply_number(num_tweaks + 1) + 2}. Reset Mobile Gestalt")
print("0. Exit\n")
page = int(input("Enter a number: "))
if page == get_apply_number(num_tweaks + 1) or page == get_apply_number(num_tweaks + 1) + 1:
# either apply or reset tweaks
print()
resetting = page == (get_apply_number(num_tweaks + 1) + 1)
# set the tweaks and apply
# first open the file in read mode
with open(gestalt_path, 'rb') as in_fp:
gestalt_plist = plistlib.load(in_fp)
# create the other plists
flag_plist: dict = {}
eligibility_files = None

# verify the device credentials before continuing
if gestalt_plist["CacheExtra"]["qNNddlUK+B/YlooNoymwgA"] != device.version or gestalt_plist["CacheExtra"]["0+nc/Udy4WNG8S+Q7a/s1A"] != device.model:
print("com.apple.mobilegestalt.plist does not match the device!")
print("Please make sure you are using the correct file!")
print("If you believe this is a mistake, you can override this check.")
override = input("Do you want to overrride? (y/n) ")
if override.lower() != 'y':
continue # break applying and return to the main page

# set the plist keys
if not resetting:
for tweak in tweaks.values:
if isinstance(tweak, FeatureFlagTweak):
flag_plist = tweak.apply_tweak(flag_plist)
elif isinstance(tweak, EligibilityTweak):
tweak.set_region_code(device.locale[-2:])
eligibility_files = tweak.apply_tweak()
else:
gestalt_plist = tweak.apply_tweak(gestalt_plist)

# create the restore file list
files_to_restore = [
FileToRestore(
contents=plistlib.dumps(gestalt_plist),
restore_path="/var/containers/Shared/SystemGroup/systemgroup.com.apple.mobilegestaltcache/Library/Caches/",
restore_name="com.apple.MobileGestalt.plist"
),
FileToRestore(
contents=plistlib.dumps(flag_plist),
restore_path="/var/preferences/FeatureFlags/",
restore_name="Global.plist"
)
]
if eligibility_files != None:
files_to_restore += eligibility_files
# restore to the device
try:
restore_files(files=files_to_restore, reboot=True, lockdown_client=device.ld)
except Exception as e:
print(traceback.format_exc())
finally:
input("Press Enter to exit...")
running = False
elif page == get_apply_number(num_tweaks + 1) + 2:
# reset mobilegestalt
# restore to the 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=device.ld)
except Exception as e:
print(traceback.format_exc())
finally:
input("Press Enter to exit...")
running = False
elif page == 0:
# exit the panel
print("Goodbye!")
running = False
elif page == 42:
# restore_file(fp=Path.joinpath(Path.cwd(), "telephony_test.png"), restore_path="/var/mobile/Library/Caches/TelephonyUI-9/", restore_name="en-0---white.png", reboot=True, lockdown_client=device.ld)
restore_files(files=[FileToRestore(
contents=b"",
restore_path="/var/Managed Preferences/mobile/",
restore_name="com.apple.purplebuddy.plist"
)], reboot=True, lockdown_client=device.ld)
else:
tweak = list(tweaks.values())[page-1]
if page > 0 and page <= num_tweaks and tweak.is_compatible(device.version):
if tweak.edit_type == TweakModifyType.TEXT:
# text input
# for now it is just for set model, deal with a fix later
print("\n\nSet Model Name")
print("Leave blank to turn off custom name.\n")
name = input("Enter Model Name: ")
if name == "":
tweak.set_enabled(False)
else:
tweak.set_value(name)
elif tweak.edit_type == TweakModifyType.PICKER:
# pick between values
print("\n\nSelect a value.")
print("If you do not know which to try, start with the first option.")
values = tweak.value
for option in range(len(values)):
print_option(
num=option+1,
active=(tweak.enabled and tweak.get_selected_option() == option),
message=str(values[option])
)
print_option(num=len(values)+1, active=(not tweak.enabled), message="Disable")
picker_choice = int(input("Select option: "))
if picker_choice > 0 and picker_choice <= len(values):
tweak.set_selected_option(picker_choice-1)
elif picker_choice == len(values)+1:
tweak.set_enabled(False)
else:
tweak.toggle_enabled()
else:
print("No MobileGestalt file found!")
print(f"Please place the file in \'{Path.cwd()}\' with the name \'com.apple.MobileGestalt.plist\'")
print("Remember to make a backup of the file!!\n")
print("1. Retry")
print("2. Enter path\n")
choice = int(input("Enter number: "))
if choice == 2:
new_path = input("Enter new path to file: ")
gestalt_path = Path(new_path)
12 changes: 10 additions & 2 deletions compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,18 @@
'main_app.py',
# '--hidden-import=ipsw_parser',
'--hidden-import=zeroconf',
'--hidden-import=pyimg4',
'--hidden-import=zeroconf._utils.ipaddress',
'--hidden-import=zeroconf._handlers.answers',
'--add-data=files/:./files',
'--copy-metadata=pyimg4',
'--onedir',
'--name=CODENAME Nugget',
'--name=Nugget',
'--icon=nugget.ico'
]

PyInstaller.__main__.run(args)
if platform == "darwin":
# add --windowed arg for macOS
args.append('--windowed')

PyInstaller.__main__.run(args)
Binary file added credits/LeminLimez.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added credits/big_nugget.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file added devicemanagement/__init__.py
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading

0 comments on commit df5dd5d

Please sign in to comment.