From a007e33b447f468a0aa431325b8d0d322344118a Mon Sep 17 00:00:00 2001 From: Cameron Katri Date: Sun, 6 Dec 2020 19:23:50 -0500 Subject: Remove uicache dependency Don't use NSTask Reorganize --- .gitignore | 2 +- Makefile | 39 +++++++-------- NSTask.h | 43 ----------------- README.md | 5 +- ent.xml | 17 ------- include/IOKit | 1 + include/libkern | 1 + snaprestore.control | 8 ---- snaprestore.m | 112 ------------------------------------------- src/ent.xml | 17 +++++++ src/snaprestore.control | 7 +++ src/snaprestore.m | 123 ++++++++++++++++++++++++++++++++++++++++++++++++ 12 files changed, 174 insertions(+), 201 deletions(-) delete mode 100644 NSTask.h delete mode 100644 ent.xml create mode 120000 include/IOKit create mode 120000 include/libkern delete mode 100644 snaprestore.control delete mode 100644 snaprestore.m create mode 100644 src/ent.xml create mode 100644 src/snaprestore.control create mode 100644 src/snaprestore.m diff --git a/.gitignore b/.gitignore index 91b2e23..be56d42 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -snaprestore +build staging *.deb compile_commands.json diff --git a/Makefile b/Makefile index f164042..a6255fb 100644 --- a/Makefile +++ b/Makefile @@ -1,43 +1,44 @@ -CC = aarch64-apple-darwin-clang -STRIP = aarch64-apple-darwin-strip -LDID = ldid -CFLAGS = -arch arm64 -isysroot /home/cameron/Documents/SDK/iPhoneOS14.2.sdk -miphoneos-version-min=13.0 -isystem /home/cameron/Documents/Procursus/build_base/iphoneos-arm64/1600/usr/include -isystem /home/cameron/Documents/Procursus/build_base/iphoneos-arm64/1600/usr/local/include -F/home/cameron/Documents/Procursus/build_base/iphoneos-arm64/1600/System/Library/Frameworks -INSTALL = install -FAKEROOT = fakeroot +CC ?= aarch64-apple-darwin-clang +STRIP ?= aarch64-apple-darwin-strip +LDID ?= ldid +CFLAGS ?= -arch arm64 -isysroot /home/cameron/Documents/SDK/iPhoneOS14.2.sdk -miphoneos-version-min=13.0 -Iinclude +INSTALL ?= install +FAKEROOT ?= fakeroot PREFIX ?= /usr DESTDIR ?= DEB_MAINTAINER ?= Cameron Katri DEB_ARCH ?= iphoneos-arm -SNAPRESTORE_V := 0.1 +SNAPRESTORE_V := 0.2 DEB_SNAPRESTORE := $(SNAPRESTORE_V) -all: snaprestore +all: build/snaprestore -snaprestore: snaprestore.m ent.xml NSTask.h - $(CC) $(CFLAGS) -o snaprestore snaprestore.m -framework IOKit -framework Foundation -fobjc-arc - $(STRIP) snaprestore - $(LDID) -Sent.xml snaprestore +build/snaprestore: src/snaprestore.m src/ent.xml + mkdir -p build + $(CC) $(CFLAGS) -o build/snaprestore src/snaprestore.m -framework IOKit -framework Foundation -framework MobileCoreServices -fobjc-arc + $(STRIP) build/snaprestore + $(LDID) -Ssrc/ent.xml build/snaprestore -install: snaprestore - $(INSTALL) -Dm755 snaprestore $(DESTDIR)$(PREFIX)/bin/snaprestore +install: build/snaprestore + $(INSTALL) -Dm755 build/snaprestore $(DESTDIR)$(PREFIX)/bin/snaprestore $(INSTALL) -Dm644 LICENSE $(DESTDIR)$(PREFIX)/share/snaprestore/LICENSE -package: snaprestore +package: build/snaprestore rm -rf staging - $(INSTALL) -Dm755 snaprestore staging$(PREFIX)/bin/snaprestore + $(INSTALL) -Dm755 build/snaprestore staging$(PREFIX)/bin/snaprestore $(INSTALL) -Dm644 LICENSE staging$(PREFIX)/share/snaprestore/LICENSE $(FAKEROOT) chown -R 0:0 staging SIZE=$$(du -s staging | cut -f 1); \ - $(INSTALL) -Dm755 snaprestore.control staging/DEBIAN/control; \ + $(INSTALL) -Dm755 src/snaprestore.control staging/DEBIAN/control; \ sed -i ':a; s/@DEB_SNAPRESTORE@/$(DEB_SNAPRESTORE)/g; ta' staging/DEBIAN/control; \ sed -i ':a; s/@DEB_MAINTAINER@/$(DEB_MAINTAINER)/g; ta' staging/DEBIAN/control; \ sed -i ':a; s/@DEB_ARCH@/$(DEB_ARCH)/g; ta' staging/DEBIAN/control; \ cd staging && find . -type f ! -regex '.*.hg.*' ! -regex '.*?debian-binary.*' ! -regex '.*?DEBIAN.*' -printf '"%P" ' | xargs md5sum > DEBIAN/md5sum; \ cd ..; \ echo "Installed-Size: $$SIZE" >> staging/DEBIAN/control - $(FAKEROOT) dpkg-deb -z9 -b staging . + $(FAKEROOT) dpkg-deb -z9 -b staging build rm -rf staging clean: - rm -f snaprestore + rm -f build/snaprestore diff --git a/NSTask.h b/NSTask.h deleted file mode 100644 index 7b51c23..0000000 --- a/NSTask.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -* This header is generated by classdump-dyld 1.0 -* on Thursday, January 25, 2018 at 11:20:38 PM Eastern European Standard Time -* Operating System: Version 11.1.2 (Build 15B202) -* Image Source: /System/Library/Frameworks/Foundation.framework/Foundation -* classdump-dyld is licensed under GPLv3, Copyright © 2013-2016 by Elias Limneos. -*/ - -#import - -@interface NSTask : NSObject - -@property (copy) NSURL * executableURL; -@property (copy) NSArray * arguments; -@property (copy) NSDictionary * environment; -@property (copy) NSURL * currentDirectoryURL; -@property (retain) id standardInput; -@property (retain) id standardOutput; -@property (retain) id standardError; -@property (readonly) int processIdentifier; -@property (getter=isRunning, readonly) BOOL running; -@property (readonly) int terminationStatus; -@property (readonly) long long terminationReason; -@property (copy) id terminationHandler; -@property (assign) long long qualityOfService; -+ (id)currentTaskDictionary; -+ (id)launchedTaskWithDictionary:(id)arg1; -+ (id)launchedTaskWithLaunchPath:(id)arg1 arguments:(id)arg2; -+ (id)launchedTaskWithExecutableURL:(id)arg1 arguments:(id)arg2 error:(out id*)arg3 terminationHandler:(/*^block*/id)arg4; -- (void)waitUntilExit; -- (id)currentDirectoryPath; -- (void)setCurrentDirectoryPath:(id)arg1; -- (id)launchPath; -- (void)setLaunchPath:(id)arg1; -- (void)launch; -- (BOOL)launchAndReturnError:(id*)arg1; -- (void)interrupt; -- (long long)suspendCount; -- (BOOL)suspend; -- (BOOL)resume; -- (void)terminate; -- (NSArray *)arguments; -@end diff --git a/README.md b/README.md index a30191a..f91175b 100644 --- a/README.md +++ b/README.md @@ -2,4 +2,7 @@ `Usage: snaprestore [volume] [snapshot]` -not tested, obviously +Fair amount of testing +Renames snapshot to original name +Removes jailbreak apps from icon cache +Works on any jailbreak (hopefully) diff --git a/ent.xml b/ent.xml deleted file mode 100644 index ea437c4..0000000 --- a/ent.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - platform-application - - com.apple.private.security.no-container - - com.apple.private.skip-library-validation - - com.apple.private.apfs.revert-to-snapshot - - com.apple.private.security.disk-device-access - - com.apple.private.vfs.snapshot - - - diff --git a/include/IOKit b/include/IOKit new file mode 120000 index 0000000..0900dbf --- /dev/null +++ b/include/IOKit @@ -0,0 +1 @@ +/home/cameron/Documents/SDK/MacOSX11.0.sdk/System/Library/Frameworks/IOKit.framework/Headers \ No newline at end of file diff --git a/include/libkern b/include/libkern new file mode 120000 index 0000000..a19ad08 --- /dev/null +++ b/include/libkern @@ -0,0 +1 @@ +/home/cameron/Documents/SDK/MacOSX11.0.sdk/usr/include/libkern \ No newline at end of file diff --git a/snaprestore.control b/snaprestore.control deleted file mode 100644 index 2624641..0000000 --- a/snaprestore.control +++ /dev/null @@ -1,8 +0,0 @@ -Package: snaprestore -Section: Utilities -Maintainer: @DEB_MAINTAINER@ -Architecture: @DEB_ARCH@ -Version: @DEB_SNAPRESTORE@ -Description: Easily restore rootfs from the command line - I wholeheartly don't recommend it -Depends: uikittools (>= 2.0.3) diff --git a/snaprestore.m b/snaprestore.m deleted file mode 100644 index 51b9c85..0000000 --- a/snaprestore.m +++ /dev/null @@ -1,112 +0,0 @@ -#import -#import -#import -#import -#import -#import "NSTask.h" - -void usage(char *name) { - printf( - "Usage: %s [volume] [snapshot]\n", name); -} - -NSString *bootsnapshot() { - const io_registry_entry_t chosen = IORegistryEntryFromPath(0, "IODeviceTree:/chosen"); - const NSData *data = (__bridge const NSData *)IORegistryEntryCreateCFProperty(chosen, (__bridge CFStringRef)@"boot-manifest-hash", kCFAllocatorDefault, 0); - IOObjectRelease(chosen); - - NSMutableString *manifestHash = [NSMutableString stringWithString:@""]; - NSUInteger len = [data length]; - Byte *buf = (Byte*)malloc(len); - memcpy(buf, [data bytes], len); - int buf2; - for (buf2 = 0; buf2 <= 19; buf2++) { - [manifestHash appendFormat:@"%02X", buf[buf2]]; - } - // add com.apple.os.update- - return [NSString stringWithFormat:@"%@%@", @"com.apple.os.update-", manifestHash]; -} - -int restore(const char *vol, const char *snap) { - int fd = open(vol, O_RDONLY, 0); - - int ret = fs_snapshot_revert(fd, snap, 0); - return ret; -} - -int mount(const char *vol, const char *snap, const char *mnt) { - int fd = open(vol, O_RDONLY, 0); - - BOOL isDir; - NSFileManager *fileManager = [NSFileManager defaultManager]; - if(![fileManager fileExistsAtPath:[NSString stringWithUTF8String:mnt] isDirectory:&isDir]) - if(![fileManager createDirectoryAtPath:[NSString stringWithUTF8String:mnt] withIntermediateDirectories:YES attributes:nil error:NULL]) - NSLog(@"Error: Create folder failed %s", mnt); - - int ret = fs_snapshot_mount(fd, mnt, snap, 0); - - return ret; -} - -NSMutableSet *findApps(const char *root, const char *mnt) { - NSMutableString *rootApplications = [NSMutableString stringWithUTF8String:root]; - rootApplications = [[rootApplications stringByAppendingString:@"/Applications"] mutableCopy]; - - NSMutableString *mntApplications = [NSMutableString stringWithUTF8String:mnt]; - mntApplications = [[mntApplications stringByAppendingString:@"/Applications"] mutableCopy]; - - NSArray *rootApps = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:rootApplications error:nil]; - NSArray *mntApps = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:mntApplications error:nil]; - - NSMutableSet *ret = [[NSMutableSet alloc] init]; - for (NSString *app in rootApps) { - if (![mntApps containsObject:app]) { - [ret addObject:[@"/Applications/" stringByAppendingString:app]]; - } - } - - return ret; -} - -int rename(const char *vol, const char *snap) { - int fd = open(vol, O_RDONLY, 0); - - int ret = fs_snapshot_rename(fd, snap, [bootsnapshot() UTF8String], 0); - return ret; -} - -int main(int argc, char *argv[]) { - if (argc != 3) { - usage(argv[0]); - return 0; - } - - char *vol = argv[1]; - char *snap = argv[2]; - char *mnt = "/tmp/rootfsmnt"; - - printf("Restoring snapshot %s...\n", snap); - restore(vol, snap); - printf("Restored snapshot...\n"); - printf("Mounting rootfs...\n"); - mount(vol, snap, mnt); - printf("Mounted %s at %s\n", snap, mnt); - NSMutableSet *appSet = findApps(vol, mnt); - if ([appSet count]) { - printf("Refreshing icon cache...\n"); - NSMutableArray *argArray = [[NSMutableArray alloc] init]; - for (NSString *app in appSet) { - [argArray addObject:@"-u"]; - [argArray addObject:app]; - } - NSTask *task = [[NSTask alloc] init]; - [task setLaunchPath:@"/usr/bin/uicache"]; - [task setArguments:argArray]; - [task launch]; - [task waitUntilExit]; - } - printf("Renaming snapshot...\n"); - rename(vol, snap); - printf("Restoring %s on %s has succeeded\n", snap, vol); - return 0; -} diff --git a/src/ent.xml b/src/ent.xml new file mode 100644 index 0000000..ea437c4 --- /dev/null +++ b/src/ent.xml @@ -0,0 +1,17 @@ + + + + platform-application + + com.apple.private.security.no-container + + com.apple.private.skip-library-validation + + com.apple.private.apfs.revert-to-snapshot + + com.apple.private.security.disk-device-access + + com.apple.private.vfs.snapshot + + + diff --git a/src/snaprestore.control b/src/snaprestore.control new file mode 100644 index 0000000..7a7c329 --- /dev/null +++ b/src/snaprestore.control @@ -0,0 +1,7 @@ +Package: snaprestore +Section: Utilities +Maintainer: @DEB_MAINTAINER@ +Architecture: @DEB_ARCH@ +Version: @DEB_SNAPRESTORE@ +Description: Easily restore rootfs from the command line + Usage: snaprestore [volume] [snapshot] diff --git a/src/snaprestore.m b/src/snaprestore.m new file mode 100644 index 0000000..deda1bc --- /dev/null +++ b/src/snaprestore.m @@ -0,0 +1,123 @@ +#import +#import +#import +#import +#import + +@interface LSApplicationWorkspace : NSObject ++ (id)defaultWorkspace; +- (BOOL)_LSPrivateRebuildApplicationDatabasesForSystemApps:(BOOL)arg1 internal:(BOOL)arg2 user:(BOOL)arg3; +- (BOOL)registerApplicationDictionary:(NSDictionary *)applicationDictionary; +- (BOOL)registerBundleWithInfo:(NSDictionary *)bundleInfo options:(NSDictionary *)options type:(unsigned long long)arg3 progress:(id)arg4 ; +- (BOOL)registerApplication:(NSURL *)url; +- (BOOL)registerPlugin:(NSURL *)url; +- (BOOL)unregisterApplication:(NSURL *)url; +- (NSArray *)installedPlugins; +-(void)_LSPrivateSyncWithMobileInstallation; +@end + +void usage(char *name) { + printf( + "Usage: %s [volume] [snapshot]\n", name); +} + +NSString *bootsnapshot() { + const io_registry_entry_t chosen = IORegistryEntryFromPath(0, "IODeviceTree:/chosen"); + const NSData *data = (__bridge const NSData *)IORegistryEntryCreateCFProperty(chosen, (__bridge CFStringRef)@"boot-manifest-hash", kCFAllocatorDefault, 0); + IOObjectRelease(chosen); + + NSMutableString *manifestHash = [NSMutableString stringWithString:@""]; + NSUInteger len = [data length]; + Byte *buf = (Byte*)malloc(len); + memcpy(buf, [data bytes], len); + int buf2; + for (buf2 = 0; buf2 <= 19; buf2++) { + [manifestHash appendFormat:@"%02X", buf[buf2]]; + } + // add com.apple.os.update- + return [NSString stringWithFormat:@"%@%@", @"com.apple.os.update-", manifestHash]; +} + +int restore(const char *vol, const char *snap) { + int fd = open(vol, O_RDONLY, 0); + + int ret = fs_snapshot_revert(fd, snap, 0); + return ret; +} + +int mount(const char *vol, const char *snap, const char *mnt) { + int fd = open(vol, O_RDONLY, 0); + + BOOL isDir; + NSFileManager *fileManager = [NSFileManager defaultManager]; + if(![fileManager fileExistsAtPath:[NSString stringWithUTF8String:mnt] isDirectory:&isDir]) + if(![fileManager createDirectoryAtPath:[NSString stringWithUTF8String:mnt] withIntermediateDirectories:YES attributes:nil error:NULL]) + NSLog(@"Error: Create folder failed %s", mnt); + + int ret = fs_snapshot_mount(fd, mnt, snap, 0); + + return ret; +} + +NSMutableSet *findApps(const char *root, const char *mnt) { + NSMutableString *rootApplications = [NSMutableString stringWithUTF8String:root]; + rootApplications = [[rootApplications stringByAppendingString:@"/Applications"] mutableCopy]; + + NSMutableString *mntApplications = [NSMutableString stringWithUTF8String:mnt]; + mntApplications = [[mntApplications stringByAppendingString:@"/Applications"] mutableCopy]; + + NSArray *rootApps = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:rootApplications error:nil]; + NSArray *mntApps = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:mntApplications error:nil]; + + NSMutableSet *ret = [[NSMutableSet alloc] init]; + for (NSString *app in rootApps) { + if (![mntApps containsObject:app]) { + [ret addObject:[@"/Applications/" stringByAppendingString:app]]; + } + } + + return ret; +} + +int unregisterPath(NSString *path) { + path = [path stringByResolvingSymlinksInPath]; + NSURL *url = [NSURL fileURLWithPath:path]; + LSApplicationWorkspace *workspace = [LSApplicationWorkspace defaultWorkspace]; + return [workspace unregisterApplication:url]; +} + +int rename(const char *vol, const char *snap) { + int fd = open(vol, O_RDONLY, 0); + + int ret = fs_snapshot_rename(fd, snap, [bootsnapshot() UTF8String], 0); + return ret; +} + +int main(int argc, char *argv[]) { + if (argc != 3) { + usage(argv[0]); + return 0; + } + + char *vol = argv[1]; + char *snap = argv[2]; + char *mnt = "/tmp/rootfsmnt"; + + printf("Restoring snapshot %s...\n", snap); + restore(vol, snap); + printf("Restored snapshot...\n"); + printf("Mounting rootfs...\n"); + mount(vol, snap, mnt); + printf("Mounted %s at %s\n", snap, mnt); + NSMutableSet *appSet = findApps(vol, mnt); + if ([appSet count]) { + for (NSString *app in appSet) { + printf("unregistering %s\n", [app UTF8String]); + unregisterPath(app); + } + } + printf("Renaming snapshot...\n"); + rename(vol, snap); + printf("Restoring %s on %s has succeeded\n", snap, vol); + return 0; +} -- cgit v1.2.3-56-ge451