From 10fd0e0c7fc4459f65c1e6029d44cd522e18becb Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Thu, 25 Jun 2015 10:19:08 +0000 Subject: On iOS 8.3, allow symbolic links as /Applications. --- .gitignore | 1 + control | 5 ++- extrainst_.mm | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ libuicache.mm | 27 +++++++++++++++ makefile | 10 ++++-- 5 files changed, 143 insertions(+), 3 deletions(-) create mode 100644 libuicache.mm diff --git a/.gitignore b/.gitignore index f891275..cfeb3bc 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ uicache uiduid uiopen uishoot +libuicache.dylib diff --git a/control b/control index 328d4f5..7fbeadb 100644 --- a/control +++ b/control @@ -4,9 +4,12 @@ Section: Utilities Maintainer: Jay Freeman (saurik) Architecture: iphoneos-arm Version: +Essential: yes Description: UIKit/GraphicsServices command line access Name: UIKit Tools Author: Jay Freeman (saurik) Depiction: http://cydia.saurik.com/info/uikittools/ -Depends: coreutils-bin +Depends: coreutils-bin, firmware (<< 8.2) | ldid +Replaces: taiguicache +Conflicts: taiguicache Tag: purpose::console, role::hacker diff --git a/extrainst_.mm b/extrainst_.mm index a938b04..8d4d15b 100644 --- a/extrainst_.mm +++ b/extrainst_.mm @@ -44,6 +44,9 @@ #include #include #include +#include +#include +#include #include "csstore.hpp" @@ -129,6 +132,99 @@ void FixCache(NSString *home, NSString *plist) { printf("you must reboot to finalize your cache.\n"); } +#define INSTALLD "/usr/libexec/installd" + +static void *(*$memmem)(const void *, size_t, const void *, size_t); + +static bool PatchInstall() { + int fd(open(INSTALLD, O_RDWR)); + if (fd == -1) + return false; + + struct stat stat; + if (fstat(fd, &stat) == -1) { + close(fd); + return false; + } + + size_t size(stat.st_size); + void *data(mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)); + close(fd); + if (data == MAP_FAILED) + return false; + + bool changed(false); + for (;;) { + void *name($memmem(data, size, "__restrict", 10)); + if (name == NULL) + break; + else { + memcpy(name, "__uicache_", 10); + changed = true; + } + } + + munmap(data, size); + + if (changed) { + system("ldid -s "INSTALLD""); + system("cp -af "INSTALLD" "INSTALLD"_"); + system("mv -f "INSTALLD"_ "INSTALLD""); + } + + return true; +} + +#define SubstrateLaunchDaemons_ "/Library/LaunchDaemons" +#define SubstrateVariable_ "DYLD_INSERT_LIBRARIES" +#define SubstrateLibrary_ "/usr/lib/libuicache.dylib" + +static bool HookInstall() { + NSString *file([NSString stringWithFormat:@"%@/%s.plist", @ SubstrateLaunchDaemons_, "com.apple.mobile.installd"]); + if (file == nil) + return false; + + NSMutableDictionary *root([NSMutableDictionary dictionaryWithContentsOfFile:file]); + if (root == nil) + return false; + + NSMutableDictionary *environment([root objectForKey:@"EnvironmentVariables"]); + if (environment == nil) { + environment = [NSMutableDictionary dictionaryWithCapacity:1]; + if (environment == nil) + return false; + + [root setObject:environment forKey:@"EnvironmentVariables"]; + } + + NSString *variable([environment objectForKey:@ SubstrateVariable_]); + if (variable == nil || [variable length] == 0) + [environment setObject:@ SubstrateLibrary_ forKey:@ SubstrateVariable_]; + else { + NSArray *dylibs([variable componentsSeparatedByString:@":"]); + if (dylibs == nil) + return false; + + NSUInteger index([dylibs indexOfObject:@ SubstrateLibrary_]); + if (index != NSNotFound) + return false; + + [environment setObject:[NSString stringWithFormat:@"%@:%@", variable, @ SubstrateLibrary_] forKey:@ SubstrateVariable_]; + } + + NSString *error; + NSData *data([NSPropertyListSerialization dataFromPropertyList:root format:NSPropertyListBinaryFormat_v1_0 errorDescription:&error]); + if (data == nil) + return false; + + if (![data writeToFile:file atomically:YES]) + return false; + + system("launchctl unload /Library/LaunchDaemons/com.apple.mobile.installd.plist"); + system("launchctl load /Library/LaunchDaemons/com.apple.mobile.installd.plist"); + return true; +} + int main(int argc, const char *argv[]) { if (argc < 2 || ( strcmp(argv[1], "install") != 0 && @@ -137,6 +233,13 @@ int main(int argc, const char *argv[]) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + $memmem = reinterpret_cast(dlsym(RTLD_DEFAULT, "memmem")); + + if (kCFCoreFoundationVersionNumber >= 1143) // XXX: iOS 8.3+ + if (PatchInstall()) + if (HookInstall()) + FinishCydia("reboot"); + if (kCFCoreFoundationVersionNumber >= 700 && kCFCoreFoundationVersionNumber < 800) { // XXX: iOS 6.x NSString *home(@"/var/mobile"); NSString *plist([NSString stringWithFormat:@"%@/Library/Caches/com.apple.mobile.installation.plist", home]); diff --git a/libuicache.mm b/libuicache.mm new file mode 100644 index 0000000..800beb9 --- /dev/null +++ b/libuicache.mm @@ -0,0 +1,27 @@ +#include +#include + +@interface MIFileManager ++ (MIFileManager *) defaultManager; +- (NSURL *) destinationOfSymbolicLinkAtURL:(NSURL *)url error:(NSError *)error; +@end + +static Class $MIFileManager; + +static NSArray *(*_MIFileManager$urlsForItemsInDirectoryAtURL$ignoringSymlinks$error$)(MIFileManager *self, SEL _cmd, NSURL *url, BOOL ignoring, NSError *error); + +static NSArray *$MIFileManager$urlsForItemsInDirectoryAtURL$ignoringSymlinks$error$(MIFileManager *self, SEL _cmd, NSURL *url, BOOL ignoring, NSError *error) { + MIFileManager *manager(reinterpret_cast([$MIFileManager defaultManager])); + if (NSURL *destiny = [manager destinationOfSymbolicLinkAtURL:url error:NULL]) + url = destiny; + return _MIFileManager$urlsForItemsInDirectoryAtURL$ignoringSymlinks$error$(self, _cmd, url, NO, error); +} + +__attribute__((__constructor__)) +static void initialize() { + $MIFileManager = objc_getClass("MIFileManager"); + SEL sel(@selector(urlsForItemsInDirectoryAtURL:ignoringSymlinks:error:)); + Method method(class_getInstanceMethod($MIFileManager, sel)); + _MIFileManager$urlsForItemsInDirectoryAtURL$ignoringSymlinks$error$ = reinterpret_cast(method_getImplementation(method)); + method_setImplementation(method, reinterpret_cast(&$MIFileManager$urlsForItemsInDirectoryAtURL$ignoringSymlinks$error$)); +} diff --git a/makefile b/makefile index 27410ef..7ba5ac8 100644 --- a/makefile +++ b/makefile @@ -1,4 +1,4 @@ -uikittools = uiduid uicache uiopen gssc sbdidlaunch sbreload cfversion iomfsetgamma +uikittools = uiduid uicache uiopen gssc sbdidlaunch sbreload cfversion iomfsetgamma libuicache.dylib all: $(uikittools) @@ -19,6 +19,10 @@ extrainst_ := -framework CoreFoundation -framework Foundation uicache: csstore.cpp extrainst_: csstore.cpp +%.dylib: %.mm + $${PKG_TARG}-g++ -Wall -Werror -dynamiclib -o $@ $^ $($@) -F"$${PKG_ROOT}"/System/Library/PrivateFrameworks -lobjc -framework CoreFoundation -framework Foundation + ldid -S $@ + %: %.mm $${PKG_TARG}-g++ -Wall -Werror -o $@ $^ $($@) -F"$${PKG_ROOT}"/System/Library/PrivateFrameworks -lobjc ldid -S$(wildcard $@.xml) $@ @@ -33,8 +37,10 @@ iomfsetgamma: iomfsetgamma.c package: all extrainst_ rm -rf _ + mkdir -p _/usr/lib + cp -a $(filter %.dylib,$(uikittools)) _/usr/lib mkdir -p _/usr/bin - cp -a $(uikittools) _/usr/bin + cp -a $(filter-out %.dylib,$(uikittools)) _/usr/bin mkdir -p _/DEBIAN ./control.sh _ >_/DEBIAN/control cp -a extrainst_ _/DEBIAN/ -- cgit v1.2.3