Skip to content

Commit

Permalink
Done
Browse files Browse the repository at this point in the history
  • Loading branch information
khanhduytran0 committed Sep 12, 2024
1 parent cfff618 commit ba4d521
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 16 deletions.
2 changes: 0 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ let package = Package(
"-I\(compilerAccessiblePath)/include",
"-import-objc-header",
"\(compilerAccessiblePath)/include/minimuxer-Bridging-Header.h",
"-import-objc-header",
"\(compilerAccessiblePath)/include/libimobiledevice-Bridging-Header.h",
]),
],
linkerSettings: [
Expand Down
2 changes: 2 additions & 0 deletions Resources/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ALTDeviceID</key>
<string></string>
<key>CFBundleDisplayName</key>
<string>SparseBox</string>
<key>CFBundleExecutable</key>
Expand Down
87 changes: 83 additions & 4 deletions Sources/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@ import SwiftUI
import UniformTypeIdentifiers

struct ContentView: View {
let originalMobileGestalt: URL
let modifiedMobileGestalt: URL
@AppStorage("PairingFile") var pairingFile: String?
@State var mobileGestalt: NSMutableDictionary
@State var reboot = false
@State var showPairingFileImporter = false
@State var showErrorAlert = false
@State var lastError: String?
@State var path = NavigationPath()
var body: some View {
NavigationStack {
NavigationStack(path: $path) {
Form {
Section {
Button {
Expand All @@ -28,9 +33,36 @@ struct ContentView: View {
}
}
Section {
NavigationLink("Apply test backup") {
LogView()
Toggle("Action Button", isOn: bindingForMGKey("RingerButtonCapability"))
Toggle("Always on Display (18.0+)", isOn: bindingForMGKey("DeviceSupportsAlwaysOnTime"))
Toggle("Apple Pencil", isOn: bindingForMGKey("DeviceSupportsApplePencil"))
Toggle("Boot chime", isOn: bindingForMGKey("DeviceSupportsBootChime"))
Toggle("Charge limit", isOn: bindingForMGKey("DeviceSupports80ChargeLimit"))
Toggle("Crash Detection (might not work)", isOn: bindingForMGKey("DeviceSupportsCollisionSOS"))
Toggle("Dynamic Island (17.4+ method)", isOn: bindingForMGKey("DeviceSupportsDynamicIsland"))
Toggle("Internal Storage info", isOn: bindingForMGKey("InternalBuild"))
Toggle("Metal HUD for all apps", isOn: bindingForMGKey("apple-internal-install"))
Toggle("Stage Manager", isOn: bindingForMGKey("DeviceSupportsEnhancedMultitasking"))
Toggle("Tap to Wake", isOn: bindingForMGKey("DeviceSupportsTapToWake"))
}
Section {
Toggle("Reboot after finish restoring", isOn: $reboot)
Button("Apply changes") {
applyChanges()
}
Button("Reset changes") {
try! FileManager.default.removeItem(at: modifiedMobileGestalt)
try! FileManager.default.copyItem(at: originalMobileGestalt, to: modifiedMobileGestalt)
mobileGestalt = try! NSMutableDictionary(contentsOf: modifiedMobileGestalt, error: ())
applyChanges()
}
} footer: {
Text("""
A terrible app by @khanhduytran0. Use it at your own risk.
Thanks to:
@SideStore: em_proxy and minimuxer
@JJTech0130: SparseRestore and backup exploit
""")
}
}
.fileImporter(isPresented: $showPairingFileImporter, allowedContentTypes: [UTType(filenameExtension: "mobiledevicepairing", conformingTo: .data)!], onCompletion: { result in
Expand All @@ -47,12 +79,17 @@ struct ContentView: View {
showErrorAlert.toggle()
}
})
.navigationTitle("SparseBox")
.alert("Error", isPresented: $showErrorAlert) {
Button("OK") {}
} message: {
Text(lastError ?? "???")
}
.navigationDestination(for: String.self) { view in
if view == "ApplyChanges" {
LogView(mobileGestaltURL: modifiedMobileGestalt, reboot: reboot)
}
}
.navigationTitle("SparseBox")
}
.onAppear {
_ = start_emotional_damage("127.0.0.1:51820")
Expand All @@ -63,6 +100,48 @@ struct ContentView: View {
}
}

init() {
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
originalMobileGestalt = documentsDirectory.appendingPathComponent("OriginalMobileGestalt.plist", conformingTo: .data)
modifiedMobileGestalt = documentsDirectory.appendingPathComponent("ModifiedMobileGestalt.plist", conformingTo: .data)
if !FileManager.default.fileExists(atPath: originalMobileGestalt.path) {
let url = URL(filePath: "/var/containers/Shared/SystemGroup/systemgroup.com.apple.mobilegestaltcache/Library/Caches/com.apple.MobileGestalt.plist")
try! FileManager.default.copyItem(at: url, to: originalMobileGestalt)
try! FileManager.default.copyItem(at: url, to: modifiedMobileGestalt)
}
mobileGestalt = try! NSMutableDictionary(contentsOf: modifiedMobileGestalt, error: ())
}

func applyChanges() {
if ready() {
path.append("ApplyChanges")
} else {
lastError = "minimuxer is not ready. Ensure you have WiFi and WireGuard VPN set up."
showErrorAlert.toggle()
}
}

func bindingForMGKey<T: Equatable>(_ key: String, type: T.Type = Int.self, defaultValue: T? = 0, enableValue: T? = 1) -> Binding<Bool> {
Binding(
get: {
if let value = (mobileGestalt["CacheExtra"] as! NSMutableDictionary)[key] as? T?, let enableValue {
return value == enableValue
}
return false
},
set: { enabled in
var cacheExtra = mobileGestalt["CacheExtra"] as! NSMutableDictionary
if enabled {
cacheExtra[key] = enableValue
} else {
// we're setting human-readable keys so it does not interfere with existing keys, just remove it
cacheExtra.removeObject(forKey: key)
}
try! mobileGestalt.write(to: modifiedMobileGestalt)
}
)
}

func startMinimuxer() {
guard pairingFile != nil else {
return
Expand Down
24 changes: 14 additions & 10 deletions Sources/LogView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ let logPipe = Pipe()
struct LogView: View {
@State var log: String = ""
@State var ran = false
let willReboot: Bool
let mobileGestaltData: Data
var body: some View {
NavigationView {
ScrollViewReader { proxy in
Expand All @@ -29,34 +31,33 @@ struct LogView: View {
}

DispatchQueue.global(qos: .background).async {
print("RUNNING TEST")
runTest()
performRestore()
}
}
}
}
.navigationTitle("Log output")
}

init() {
init(mobileGestaltURL: URL, reboot: Bool) {
setvbuf(stdout, nil, _IOLBF, 0) // make stdout line-buffered
setvbuf(stderr, nil, _IONBF, 0) // make stderr unbuffered

// create the pipe and redirect stdout and stderr
dup2(logPipe.fileHandleForWriting.fileDescriptor, fileno(stdout))
dup2(logPipe.fileHandleForWriting.fileDescriptor, fileno(stderr))

mobileGestaltData = try! Data(contentsOf: mobileGestaltURL)
willReboot = reboot
}

func runTest() {
func performRestore() {
let deviceList = MobileDevice.deviceList()
guard deviceList.count == 1 else {
print("Invalid device count: \(deviceList.count)")
return
}

// Save MobileGestalt
let mobileGestaltPlist = Data()

let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let folder = documentsDirectory.appendingPathComponent(deviceList.first!, conformingTo: .data)

Expand All @@ -69,17 +70,20 @@ struct LogView: View {
Directory(path: "Library", domain: "RootDomain"),
Directory(path: "Library/Preferences", domain: "RootDomain")
]
addExploitedConcreteFile(list: &backupFiles, path: "/var/containers/Shared/SystemGroup/systemgroup.com.apple.mobilegestaltcache/Library/Caches/NOT.com.apple.MobileGestalt.plist", contents: mobileGestaltPlist)
addExploitedConcreteFile(list: &backupFiles, path: "/var/containers/Shared/SystemGroup/systemgroup.com.apple.mobilegestaltcache/Library/Caches/com.apple.MobileGestalt.plist", contents: mobileGestaltData, owner: 501, group: 501)
backupFiles.append(ConcreteFile(path: "", domain: "SysContainerDomain-../../../../../../../../crash_on_purpose", contents: Data(), owner: 501, group: 501))
let mbdb = Backup(files: backupFiles)
try mbdb.writeTo(directory: folder)

// Restore now
let restoreArgs = [
var restoreArgs = [
"idevicebackup2",
"-n", "restore", "--no-reboot", "--system",
"-n", "restore", "--system",
documentsDirectory.path(percentEncoded: false)
]
if !willReboot {
restoreArgs.insert("--no-reboot", at: 3)
}
print("Executing args: \(restoreArgs)")
var argv = restoreArgs.map{ strdup($0) }
let result = idevicebackup2_main(Int32(restoreArgs.count), &argv)
Expand Down

0 comments on commit ba4d521

Please sign in to comment.