From 3ace7367b5ab7dca6b53975df9538e16f066f4f8 Mon Sep 17 00:00:00 2001 From: 82Flex <82flex@gmail.com> Date: Fri, 11 Jun 2021 22:57:10 +0800 Subject: [PATCH 001/155] Add foulwrapper --- .gitignore | 33 +++ Makefile | 13 +- control | 4 +- entitlements.plist | 58 ++--- foulwrapper.m | 211 ++++++++++++++++++ include/AppList/ALApplicationList.h | 30 +++ .../AppList/ALApplicationTableDataSource.h | 45 ++++ include/AppList/ALValueCell.h | 40 ++++ include/AppList/AppList.h | 3 + include/MobileContainerManager/MCMContainer.h | 56 +++++ .../MCMContainerManager.h | 28 +++ lib/libapplist.dylib | Bin 0 -> 470704 bytes 12 files changed, 491 insertions(+), 30 deletions(-) create mode 100644 foulwrapper.m create mode 100644 include/AppList/ALApplicationList.h create mode 100644 include/AppList/ALApplicationTableDataSource.h create mode 100644 include/AppList/ALValueCell.h create mode 100644 include/AppList/AppList.h create mode 100644 include/MobileContainerManager/MCMContainer.h create mode 100644 include/MobileContainerManager/MCMContainerManager.h create mode 100644 lib/libapplist.dylib diff --git a/.gitignore b/.gitignore index 2b6fba8..11513b8 100755 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,36 @@ packages other's proj priv_include +CMakeLists.txt +.idea/ +cmake-build-*/ + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + diff --git a/Makefile b/Makefile index 5070c86..ff9dd3e 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,9 @@ -TARGET := iphone:clang:latest:7.0 +TARGET := iphone:clang:12.2:7.0 ARCHS = arm64 arm64e include $(THEOS)/makefiles/common.mk -TOOL_NAME = fouldecrypt flexdecrypt2 +TOOL_NAME = fouldecrypt flexdecrypt2 foulwrapper fouldecrypt_FILES = main.cpp foulmain.cpp fouldecrypt_CFLAGS = -fobjc-arc -Wno-unused-variable # -Ipriv_include @@ -23,4 +23,13 @@ flexdecrypt2_SUBPROJECTS = kerninfra flexdecrypt2_LDFLAGS += -Lkerninfra/libs flexdecrypt2_CCFLAGS += -std=c++2a +foulwrapper_FILES = foulwrapper.m +foulwrapper_CFLAGS = -fobjc-arc -Wno-unused-variable -Iinclude +foulwrapper_CCFLAGS = $(foulwrapper_CFLAGS) +foulwrapper_CODESIGN_FLAGS = -Sentitlements.plist +foulwrapper_INSTALL_PATH = /usr/local/bin +foulwrapper_FRAMEWORKS = Foundation MobileCoreServices +foulwrapper_PRIVATE_FRAMEWORKS = MobileContainerManager +foulwrapper_LIBRARIES = applist + include $(THEOS_MAKE_PATH)/tool.mk diff --git a/control b/control index 6159f42..d225213 100644 --- a/control +++ b/control @@ -2,8 +2,8 @@ Package: moe.misty.fouldecrypt Name: fouldecrypt Version: 0.0.3 Architecture: iphoneos-arm -Depends: libkrw (>= 1.0.0) -Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 14 +Depends: libkrw (>= 1.0.0), zip, applist +Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 14. Maintainer: misty Author: misty Section: System diff --git a/entitlements.plist b/entitlements.plist index 73f3176..af68853 100644 --- a/entitlements.plist +++ b/entitlements.plist @@ -2,31 +2,37 @@ - application-identifier - - - com.apple.developer.team-identifier - - - com.apple.diagnosticd.diagnostic - - com.apple.frontboard.debugapplications - - com.apple.multitasking.termination - - com.apple.private.cs.debugger - - com.apple.private.security.no-sandbox - - com.apple.private.skip-library-validation - - com.apple.springboard.launchapplications - - dynamic-codesigning - - get-task-allow - - platform-application - - task_for_pid-allow - + application-identifier + - + com.apple.developer.team-identifier + - + com.apple.diagnosticd.diagnostic + + com.apple.frontboard.debugapplications + + com.apple.multitasking.termination + + com.apple.private.cs.debugger + + com.apple.private.security.no-sandbox + + com.apple.private.skip-library-validation + + com.apple.private.MobileContainerManager.allowed + + com.apple.private.MobileContainerManager.lookup + + com.apple.private.MobileContainerManager.otherIdLookup + + com.apple.springboard.launchapplications + + dynamic-codesigning + + get-task-allow + + platform-application + + task_for_pid-allow + diff --git a/foulwrapper.m b/foulwrapper.m new file mode 100644 index 0000000..c6decbd --- /dev/null +++ b/foulwrapper.m @@ -0,0 +1,211 @@ +#import +#import +#import + +#import +#import + +#import +#import + +static int VERBOSE = 0; + +#define MH_MAGIC_64 0xfeedfacf /* the 64-bit mach magic number */ +#define MH_CIGAM_64 0xcffaedfe /* NXSwapInt(MH_MAGIC_64) */ + +#define FAT_MAGIC_64 0xcafebabf +#define FAT_CIGAM_64 0xbfbafeca /* NXSwapLong(FAT_MAGIC_64) */ + +extern char **environ; + +int +my_system(const char *ctx) +{ + const char *args[] = { + "/bin/sh", + "-c", + ctx, + NULL + }; + pid_t pid; + int posix_status = posix_spawn(&pid, "/bin/sh", NULL, NULL, (char **) args, environ); + if (posix_status != 0) + { + errno = posix_status; + fprintf(stderr, "posix_spawn, %s (%d)\n", strerror(errno), errno); + return posix_status; + } + pid_t w; + int status; + do + { + w = waitpid(pid, &status, WUNTRACED | WCONTINUED); + if (w == -1) + { + fprintf(stderr, "waitpid %d, %s (%d)\n", pid, strerror(errno), errno); + return errno; + } + if (WIFEXITED(status)) + { + fprintf(stderr, "pid %d exited, status=%d\n", pid, WEXITSTATUS(status)); + } + else if (WIFSIGNALED(status)) + { + fprintf(stderr, "pid %d killed by signal %d\n", pid, WTERMSIG(status)); + } + else if (WIFSTOPPED(status)) + { + fprintf(stderr, "pid %d stopped by signal %d\n", pid, WSTOPSIG(status)); + } + else if (WIFCONTINUED(status)) + { + fprintf(stderr, "pid %d continued\n", pid); + } + } + while (!WIFEXITED(status) && !WIFSIGNALED(status)); + if (WIFSIGNALED(status)) + { + return WTERMSIG(status); + } + return WEXITSTATUS(status); +} + +NSString * +escape_arg(NSString *arg) +{ + return [arg stringByReplacingOccurrencesOfString:@"\'" withString:@"'\\\''"]; +} + +@interface LSApplicationProxy () +- (NSString *)shortVersionString; +@end + +int +main(int argc, char *argv[]) +{ + if (argc < 2) + { + fprintf(stderr, "usage: foulwrapper (application name or application bundle identifier)\n"); + return 1; + } + + + /* AppList: convert app name to app identifier */ + /* or, you can use APIs in `LSApplicationWorkspace`. */ + NSArray *sortedDisplayIdentifiers = nil; + NSDictionary *appMaps = + [[ALApplicationList sharedApplicationList] applicationsFilteredUsingPredicate:[NSPredicate predicateWithFormat:@"isSystemApplication = FALSE"] + onlyVisible:YES titleSortedIdentifiers:&sortedDisplayIdentifiers]; + + NSString *targetIdOrName = [NSString stringWithUTF8String:argv[1]]; + NSString *targetId = nil; + for (NSString *appId in appMaps) + { + if ([appId isEqualToString:targetIdOrName] || [appMaps[appId] isEqualToString:targetIdOrName]) + { + targetId = appId; + break; + } + } + + if (!targetId) + { + fprintf(stderr, "application \"%s\" not found\n", argv[1]); + return 1; + } + + + /* MobileContainerManager: locate app bundle container path */ + /* `LSApplicationProxy` cannot provide correct values of container URLs since iOS 12. */ + NSError *error = nil; + id aClass = objc_getClass("MCMAppContainer"); + assert([aClass respondsToSelector:@selector(containerWithIdentifier:error:)]); + + MCMContainer *container = [aClass containerWithIdentifier:targetId error:&error]; + NSString *targetPath = [[container url] path]; + if (!targetPath) + { + fprintf(stderr, + "application \"%s\" does not have a bundle container: %s\n", + argv[1], + [[error localizedDescription] UTF8String]); + return 1; + } + + + /* Make a copy of app bundle. */ + NSURL *tempURL = [[NSFileManager defaultManager] URLForDirectory:NSItemReplacementDirectory + inDomain:NSUserDomainMask + appropriateForURL:[NSURL fileURLWithPath:[[NSFileManager defaultManager] currentDirectoryPath]] + create:YES error:&error]; + if (!tempURL) + { + fprintf(stderr, + "cannot create appropriate item replacement directory: %s\n", + [[error localizedDescription] UTF8String]); + return 1; + } + + NSString *tempPath = [[tempURL path] stringByAppendingPathComponent:@"Payload"]; + BOOL didCopy = [[NSFileManager defaultManager] copyItemAtPath:targetPath toPath:tempPath error:&error]; + if (!didCopy) + { + fprintf(stderr, "cannot copy app bundle: %s\n", [[error localizedDescription] UTF8String]); + return 1; + } + + /* Enumerate entire app bundle to find all Mach-Os. */ + targetPath = tempPath; + NSEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtPath:targetPath]; + NSString *objectPath = nil; + while (objectPath = [enumerator nextObject]) + { + NSString *objectFullPath = [targetPath stringByAppendingPathComponent:objectPath]; + FILE *fp = fopen(objectFullPath.UTF8String, "rb"); + if (!fp) + { + perror("fopen"); + continue; + } + + int num = getw(fp); + if (num == EOF) + { + fclose(fp); + continue; + } + + if (num == MH_MAGIC_64 || num == FAT_MAGIC_64) + { + NSString *objectBackupPath = [objectFullPath stringByAppendingPathExtension:@"bak"]; + BOOL didBackup = + [[NSFileManager defaultManager] copyItemAtPath:objectFullPath toPath:objectBackupPath error:nil]; + assert(didBackup); + + int decryptStatus = + my_system([[NSString stringWithFormat:@"fouldecrypt -v '%@' '%@'", escape_arg(objectBackupPath), escape_arg( + objectFullPath)] UTF8String]); + BOOL didClean = [[NSFileManager defaultManager] removeItemAtPath:objectBackupPath error:nil]; + assert(didClean); + } + + fclose(fp); + } + + /* LSApplicationProxy: get app info */ + LSApplicationProxy *appProxy = [LSApplicationProxy applicationProxyForIdentifier:targetId]; + assert(appProxy); + + /* zip: archive */ + NSString *archiveName = + [NSString stringWithFormat:@"%@_%@_dumped.ipa", [appProxy localizedName], [appProxy shortVersionString]]; + NSString *archivePath = + [[[NSFileManager defaultManager] currentDirectoryPath] stringByAppendingPathComponent:archiveName]; + BOOL didClean = [[NSFileManager defaultManager] removeItemAtPath:archivePath error:nil]; + assert(didClean); + int zipStatus = + my_system([[NSString stringWithFormat:@"set -e; shopt -s dotglob; cd '%@'; zip -r '%@' .; shopt -u dotglob;", escape_arg([tempURL path]), escape_arg( + archivePath)] UTF8String]); + + return zipStatus; +} diff --git a/include/AppList/ALApplicationList.h b/include/AppList/ALApplicationList.h new file mode 100644 index 0000000..91d7eba --- /dev/null +++ b/include/AppList/ALApplicationList.h @@ -0,0 +1,30 @@ +#import +#import +#import + +enum { + ALApplicationIconSizeSmall = 29, + ALApplicationIconSizeLarge = 59 +}; +typedef NSUInteger ALApplicationIconSize; + +@interface ALApplicationList : NSObject ++ (ALApplicationList *)sharedApplicationList; + +@property (nonatomic, readonly) NSDictionary *applications; +- (NSDictionary *)applicationsFilteredUsingPredicate:(NSPredicate *)predicate; +- (NSDictionary *)applicationsFilteredUsingPredicate:(NSPredicate *)predicate onlyVisible:(BOOL)onlyVisible titleSortedIdentifiers:(NSArray **)outSortedByTitle; + +- (id)valueForKeyPath:(NSString *)keyPath forDisplayIdentifier:(NSString *)displayIdentifier; +- (id)valueForKey:(NSString *)keyPath forDisplayIdentifier:(NSString *)displayIdentifier; +- (BOOL)applicationWithDisplayIdentifierIsHidden:(NSString *)displayIdentifier; + +- (CGImageRef)copyIconOfSize:(ALApplicationIconSize)iconSize forDisplayIdentifier:(NSString *)displayIdentifier; +- (UIImage *)iconOfSize:(ALApplicationIconSize)iconSize forDisplayIdentifier:(NSString *)displayIdentifier; +- (BOOL)hasCachedIconOfSize:(ALApplicationIconSize)iconSize forDisplayIdentifier:(NSString *)displayIdentifier; + +@end + +extern NSString *const ALIconLoadedNotification; +extern NSString *const ALDisplayIdentifierKey; +extern NSString *const ALIconSizeKey; diff --git a/include/AppList/ALApplicationTableDataSource.h b/include/AppList/ALApplicationTableDataSource.h new file mode 100644 index 0000000..1fd38ce --- /dev/null +++ b/include/AppList/ALApplicationTableDataSource.h @@ -0,0 +1,45 @@ +#import +#import + +@class ALApplicationList; + +@interface ALApplicationTableDataSource : NSObject { +@private + NSMutableArray *_sectionDescriptors; + UITableView *_tableView; + NSBundle *_localizationBundle; + BOOL _loadsAsynchronously; +} + ++ (NSArray *)standardSectionDescriptors; + ++ (id)dataSource; +- (id)init; + +@property (nonatomic, copy) NSArray *sectionDescriptors; +@property (nonatomic, retain) UITableView *tableView; +@property (nonatomic, retain) NSBundle *localizationBundle; +@property (nonatomic, assign) BOOL loadsAsynchronously; + +- (id)cellDescriptorForIndexPath:(NSIndexPath *)indexPath; // NSDictionary if custom cell; NSString if app cell; nil if loading +- (NSString *)displayIdentifierForIndexPath:(NSIndexPath *)indexPath; + +- (void)insertSectionDescriptor:(NSDictionary *)sectionDescriptor atIndex:(NSInteger)index; +- (void)removeSectionDescriptorAtIndex:(NSInteger)index; +- (void)removeSectionDescriptorsAtIndexes:(NSIndexSet *)indexSet; + +- (BOOL)waitUntilDate:(NSDate *)date forContentInSectionAtIndex:(NSInteger)sectionIndex; + +@end + +extern const NSString *ALSectionDescriptorTitleKey; +extern const NSString *ALSectionDescriptorFooterTitleKey; +extern const NSString *ALSectionDescriptorPredicateKey; +extern const NSString *ALSectionDescriptorCellClassNameKey; +extern const NSString *ALSectionDescriptorIconSizeKey; +extern const NSString *ALSectionDescriptorSuppressHiddenAppsKey; +extern const NSString *ALSectionDescriptorVisibilityPredicateKey; + +extern const NSString *ALItemDescriptorTextKey; +extern const NSString *ALItemDescriptorDetailTextKey; +extern const NSString *ALItemDescriptorImageKey; diff --git a/include/AppList/ALValueCell.h b/include/AppList/ALValueCell.h new file mode 100644 index 0000000..bd07c9f --- /dev/null +++ b/include/AppList/ALValueCell.h @@ -0,0 +1,40 @@ +#import + +@protocol ALValueCellDelegate; + +@interface ALValueCell : UITableViewCell { +@private + id delegate; +} + +@property (nonatomic, assign) id delegate; + +- (void)loadValue:(id)value; // Deprecated +- (void)loadValue:(id)value withTitle:(NSString *)title; + +- (void)didSelect; + +@end + +@protocol ALValueCellDelegate +@required +- (void)valueCell:(ALValueCell *)valueCell didChangeToValue:(id)newValue; +@end + +@interface ALSwitchCell : ALValueCell { +@private + UISwitch *switchView; +} + +@property (nonatomic, readonly) UISwitch *switchView; + +@end + +@interface ALCheckCell : ALValueCell + +@end + +@interface ALDisclosureIndicatedCell : ALValueCell + +@end + diff --git a/include/AppList/AppList.h b/include/AppList/AppList.h new file mode 100644 index 0000000..73418fc --- /dev/null +++ b/include/AppList/AppList.h @@ -0,0 +1,3 @@ +#import "ALApplicationList.h" +#import "ALApplicationTableDataSource.h" +#import "ALValueCell.h" diff --git a/include/MobileContainerManager/MCMContainer.h b/include/MobileContainerManager/MCMContainer.h new file mode 100644 index 0000000..f221880 --- /dev/null +++ b/include/MobileContainerManager/MCMContainer.h @@ -0,0 +1,56 @@ +// +// MCMContainer.h +// edgbackup +// +// Created by Mason Rachel on 10/30/19. +// + +#ifndef MCMContainer_h +#define MCMContainer_h + +#import + +@interface MCMContainer : NSObject { + long long _containerClass; + NSString *_identifier; + unsigned int _userId; + NSUUID *_uuid; +} + +@property (nonatomic, readonly) long long containerClass; +@property (nonatomic, readonly) NSString *identifier; +@property (nonatomic, readonly) NSDictionary *info; +@property (getter=isTemporary, nonatomic, readonly) bool temporary; +@property (nonatomic, readonly) NSURL *url; +@property (nonatomic, readonly) NSUUID *uuid; + ++ (id)containerWithIdentifier:(id)arg1 createIfNecessary:(bool)arg2 existed:(bool*)arg3 error:(id*)arg4; ++ (id)containerWithIdentifier:(id)arg1 error:(id*)arg2; ++ (id)temporaryContainerWithIdentifier:(id)arg1 existed:(bool*)arg2 error:(id*)arg3; ++ (long long)typeContainerClass; + +- (void)_errorOccurred; +- (long long)containerClass; +- (void)dealloc; +- (id)description; +- (id)destroyContainerWithCompletion:(id /* block */)arg1; +- (unsigned long long)diskUsageWithError:(id*)arg1; +- (unsigned long long)hash; +- (id)identifier; +- (id)info; +- (id)infoValueForKey:(id)arg1 error:(id*)arg2; +- (id)init; +- (id)initWithIdentifier:(id)arg1 createIfNecessary:(bool)arg2 existed:(bool*)arg3 temp:(bool)arg4 error:(id*)arg5; +- (id)initWithIdentifier:(id)arg1 userId:(unsigned int)arg2 uuid:(id)arg3 error:(id*)arg4; +- (bool)isEqual:(id)arg1; +- (bool)isTemporary; +- (void)markDeleted; +- (bool)recreateDefaultStructureWithError:(id*)arg1; +- (bool)regenerateDirectoryUUIDWithError:(id*)arg1; +- (bool)setInfoValue:(id)arg1 forKey:(id)arg2 error:(id*)arg3; +- (id)url; +- (id)uuid; + +@end + +#endif /* MCMContainer_h */ diff --git a/include/MobileContainerManager/MCMContainerManager.h b/include/MobileContainerManager/MCMContainerManager.h new file mode 100644 index 0000000..35571a3 --- /dev/null +++ b/include/MobileContainerManager/MCMContainerManager.h @@ -0,0 +1,28 @@ +// +// MCMContainerManager.h +// edgbackup +// +// Created by Mason Rachel on 10/31/19. +// + +#ifndef MCMContainerManager_h +#define MCMContainerManager_h + +@interface MCMContainerManager : NSObject + ++ (id)defaultManager; + +- (id)_containersWithClass:(long long)arg1 temporary:(bool)arg2 error:(id*)arg3; +- (id)containerWithContentClass:(long long)arg1 identifier:(id)arg2 createIfNecessary:(bool)arg3 existed:(bool*)arg4 error:(id*)arg5; +- (id)containerWithContentClass:(long long)arg1 identifier:(id)arg2 error:(id*)arg3; +- (id)containersWithClass:(long long)arg1 error:(id*)arg2; +- (id)deleteContainers:(id)arg1 withCompletion:(id /* block */)arg2; +- (id)init; +- (bool)replaceContainer:(id)arg1 withContainer:(id)arg2 error:(id*)arg3; +- (bool)replaceContainer:(id)arg1 withContainer:(id)arg2 error:(id*)arg3 withCompletion:(id /* block */)arg4; +- (id)temporaryContainerWithContentClass:(long long)arg1 identifier:(id)arg2 existed:(bool*)arg3 error:(id*)arg4; +- (id)temporaryContainersWithClass:(long long)arg1 error:(id*)arg2; + +@end + +#endif /* MCMContainerManager_h */ diff --git a/lib/libapplist.dylib b/lib/libapplist.dylib new file mode 100644 index 0000000000000000000000000000000000000000..e50136265ef2c02d060d8f53e2f6134d6890bb5a GIT binary patch literal 470704 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®<#khvChSARGWNcvcF!~u=7`HICF>YgQXWY)% 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 NkR(Hq4mmn-{s+@Co=pG% literal 0 HcmV?d00001 From 6ec006c3b2bb9be825a565dafd988e18ca8369e7 Mon Sep 17 00:00:00 2001 From: 82Flex <82flex@gmail.com> Date: Fri, 11 Jun 2021 22:58:22 +0800 Subject: [PATCH 002/155] Add foulwrapper --- foulwrapper.m | 3 +++ 1 file changed, 3 insertions(+) diff --git a/foulwrapper.m b/foulwrapper.m index c6decbd..0ad272f 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -154,6 +154,7 @@ - (NSString *)shortVersionString; return 1; } + /* Enumerate entire app bundle to find all Mach-Os. */ targetPath = tempPath; NSEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtPath:targetPath]; @@ -192,10 +193,12 @@ - (NSString *)shortVersionString; fclose(fp); } + /* LSApplicationProxy: get app info */ LSApplicationProxy *appProxy = [LSApplicationProxy applicationProxyForIdentifier:targetId]; assert(appProxy); + /* zip: archive */ NSString *archiveName = [NSString stringWithFormat:@"%@_%@_dumped.ipa", [appProxy localizedName], [appProxy shortVersionString]]; From f8fca4e253019bee7a50021bda471c48037c83db Mon Sep 17 00:00:00 2001 From: 82Flex <82flex@gmail.com> Date: Fri, 11 Jun 2021 23:15:13 +0800 Subject: [PATCH 003/155] Add foulwrapper --- foulwrapper.m | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/foulwrapper.m b/foulwrapper.m index 0ad272f..bcdfdb6 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -131,6 +131,7 @@ - (NSString *)shortVersionString; [[error localizedDescription] UTF8String]); return 1; } + NSLog(@"%@", targetPath); /* Make a copy of app bundle. */ @@ -156,12 +157,11 @@ - (NSString *)shortVersionString; /* Enumerate entire app bundle to find all Mach-Os. */ - targetPath = tempPath; - NSEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtPath:targetPath]; + NSEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtPath:tempPath]; NSString *objectPath = nil; while (objectPath = [enumerator nextObject]) { - NSString *objectFullPath = [targetPath stringByAppendingPathComponent:objectPath]; + NSString *objectFullPath = [tempPath stringByAppendingPathComponent:objectPath]; FILE *fp = fopen(objectFullPath.UTF8String, "rb"); if (!fp) { @@ -178,16 +178,14 @@ - (NSString *)shortVersionString; if (num == MH_MAGIC_64 || num == FAT_MAGIC_64) { - NSString *objectBackupPath = [objectFullPath stringByAppendingPathExtension:@"bak"]; - BOOL didBackup = - [[NSFileManager defaultManager] copyItemAtPath:objectFullPath toPath:objectBackupPath error:nil]; - assert(didBackup); + NSString *objectRawPath = [targetPath stringByAppendingPathComponent:objectPath]; int decryptStatus = - my_system([[NSString stringWithFormat:@"fouldecrypt -v '%@' '%@'", escape_arg(objectBackupPath), escape_arg( + my_system([[NSString stringWithFormat:@"fouldecrypt -v '%@' '%@'", escape_arg(objectRawPath), escape_arg( objectFullPath)] UTF8String]); - BOOL didClean = [[NSFileManager defaultManager] removeItemAtPath:objectBackupPath error:nil]; - assert(didClean); + if (decryptStatus != 0) { + break; + } } fclose(fp); From 4c5dee73b69f3e1e74fd2953c18a364aafc6700d Mon Sep 17 00:00:00 2001 From: 82Flex <82flex@gmail.com> Date: Thu, 18 Nov 2021 16:18:05 +0800 Subject: [PATCH 004/155] Fix compile errors for noobs --- Makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 084fd13..6dd2f71 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,14 @@ TARGET := iphone:clang:12.2:7.0 ARCHS = arm64 arm64e +export ADDITIONAL_CFLAGS = -DTHEOS_LEAN_AND_MEAN -fobjc-arc include $(THEOS)/makefiles/common.mk TOOL_NAME = fouldecrypt flexdecrypt2 foulwrapper -# USE_TFP0 = 1 -# USE_LIBKRW = 1 -# USE_LIBKERNRW = 1 +export USE_TFP0 = 1 +# export USE_LIBKRW = 1 +# export USE_LIBKERNRW = 1 fouldecrypt_FILES = main.cpp foulmain.cpp fouldecrypt_CFLAGS = -fobjc-arc -Wno-unused-variable # -Ipriv_include From dc3639b74484db08437ef0eac2a7ff906e47f5fe Mon Sep 17 00:00:00 2001 From: 82Flex <82flex@gmail.com> Date: Thu, 18 Nov 2021 16:24:19 +0800 Subject: [PATCH 005/155] Fix `make package` command by creating layout directory --- control.template => layout/DEBIAN/control | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename control.template => layout/DEBIAN/control (100%) diff --git a/control.template b/layout/DEBIAN/control similarity index 100% rename from control.template rename to layout/DEBIAN/control From e8494e174cdd536ae14d0d9a5ea6c8cd8eb8633e Mon Sep 17 00:00:00 2001 From: 82Flex <82flex@gmail.com> Date: Thu, 18 Nov 2021 16:27:24 +0800 Subject: [PATCH 006/155] Fix `make package` command by creating layout directory --- control.template | 10 ++++++++++ layout/DEBIAN/control | 1 - 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 control.template diff --git a/control.template b/control.template new file mode 100644 index 0000000..203ec00 --- /dev/null +++ b/control.template @@ -0,0 +1,10 @@ +Package: moe.misty.fouldecrypt +Name: fouldecrypt +Version: 0.0.4 +Architecture: iphoneos-arm +Depends: {{.depends}} +Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 14 +Maintainer: misty +Author: misty +Section: System +Tag: role::hacker diff --git a/layout/DEBIAN/control b/layout/DEBIAN/control index 203ec00..509465e 100644 --- a/layout/DEBIAN/control +++ b/layout/DEBIAN/control @@ -2,7 +2,6 @@ Package: moe.misty.fouldecrypt Name: fouldecrypt Version: 0.0.4 Architecture: iphoneos-arm -Depends: {{.depends}} Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 14 Maintainer: misty Author: misty From 8f48fa41f4864bd7590acee795e7487612b79872 Mon Sep 17 00:00:00 2001 From: 82Flex <82flex@gmail.com> Date: Thu, 18 Nov 2021 16:30:05 +0800 Subject: [PATCH 007/155] Add `link_theos.sh` to link against theos makefiles for noobs --- link_theos.sh | 4 ++++ 1 file changed, 4 insertions(+) create mode 100755 link_theos.sh diff --git a/link_theos.sh b/link_theos.sh new file mode 100755 index 0000000..3b38bcd --- /dev/null +++ b/link_theos.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +ln -s $THEOS/makefiles makefiles +exit 0 From 4506bf19c9cd1049764e2c21277957f521beced3 Mon Sep 17 00:00:00 2001 From: 82Flex <82flex@gmail.com> Date: Thu, 18 Nov 2021 16:33:00 +0800 Subject: [PATCH 008/155] Add `applist` as `foulwrapper`'s package dependencies --- control.template | 2 +- layout/DEBIAN/control | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/control.template b/control.template index 203ec00..e1488de 100644 --- a/control.template +++ b/control.template @@ -2,7 +2,7 @@ Package: moe.misty.fouldecrypt Name: fouldecrypt Version: 0.0.4 Architecture: iphoneos-arm -Depends: {{.depends}} +Depends: applist {{.depends}} Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 14 Maintainer: misty Author: misty diff --git a/layout/DEBIAN/control b/layout/DEBIAN/control index 509465e..4094112 100644 --- a/layout/DEBIAN/control +++ b/layout/DEBIAN/control @@ -2,6 +2,7 @@ Package: moe.misty.fouldecrypt Name: fouldecrypt Version: 0.0.4 Architecture: iphoneos-arm +Depends: applist Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 14 Maintainer: misty Author: misty From 36cf8c6c96c33bddb2bf218cafd9691c75533a2b Mon Sep 17 00:00:00 2001 From: 82Flex <82flex@gmail.com> Date: Thu, 18 Nov 2021 16:38:15 +0800 Subject: [PATCH 009/155] Add `zip` as `foulwrapper`'s dependencies --- control.template | 2 +- foulwrapper.m | 2 +- layout/DEBIAN/control | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/control.template b/control.template index e1488de..4239ac6 100644 --- a/control.template +++ b/control.template @@ -2,7 +2,7 @@ Package: moe.misty.fouldecrypt Name: fouldecrypt Version: 0.0.4 Architecture: iphoneos-arm -Depends: applist {{.depends}} +Depends: applist zip {{.depends}} Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 14 Maintainer: misty Author: misty diff --git a/foulwrapper.m b/foulwrapper.m index bcdfdb6..6330809 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -203,7 +203,7 @@ - (NSString *)shortVersionString; NSString *archivePath = [[[NSFileManager defaultManager] currentDirectoryPath] stringByAppendingPathComponent:archiveName]; BOOL didClean = [[NSFileManager defaultManager] removeItemAtPath:archivePath error:nil]; - assert(didClean); + // assert(didClean); int zipStatus = my_system([[NSString stringWithFormat:@"set -e; shopt -s dotglob; cd '%@'; zip -r '%@' .; shopt -u dotglob;", escape_arg([tempURL path]), escape_arg( archivePath)] UTF8String]); diff --git a/layout/DEBIAN/control b/layout/DEBIAN/control index 4094112..ea98491 100644 --- a/layout/DEBIAN/control +++ b/layout/DEBIAN/control @@ -2,7 +2,7 @@ Package: moe.misty.fouldecrypt Name: fouldecrypt Version: 0.0.4 Architecture: iphoneos-arm -Depends: applist +Depends: applist zip Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 14 Maintainer: misty Author: misty From 3c49b2b438b7526dfcc79bddfff8a4aaf3472ed2 Mon Sep 17 00:00:00 2001 From: 82Flex <82flex@gmail.com> Date: Thu, 18 Nov 2021 16:39:31 +0800 Subject: [PATCH 010/155] Fix control syntax --- control.template | 2 +- layout/DEBIAN/control | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/control.template b/control.template index 4239ac6..1657766 100644 --- a/control.template +++ b/control.template @@ -2,7 +2,7 @@ Package: moe.misty.fouldecrypt Name: fouldecrypt Version: 0.0.4 Architecture: iphoneos-arm -Depends: applist zip {{.depends}} +Depends: applist,zip,{{.depends}} Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 14 Maintainer: misty Author: misty diff --git a/layout/DEBIAN/control b/layout/DEBIAN/control index ea98491..9ab7fa5 100644 --- a/layout/DEBIAN/control +++ b/layout/DEBIAN/control @@ -2,7 +2,7 @@ Package: moe.misty.fouldecrypt Name: fouldecrypt Version: 0.0.4 Architecture: iphoneos-arm -Depends: applist zip +Depends: applist,zip Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 14 Maintainer: misty Author: misty From b493eeb760e03498ca1f5be11bb1e16c79ad0ca7 Mon Sep 17 00:00:00 2001 From: 82Flex <82flex@gmail.com> Date: Thu, 18 Nov 2021 16:47:02 +0800 Subject: [PATCH 011/155] Add usage for `foulwrapper` --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index e0334b7..5e5e736 100755 --- a/README.md +++ b/README.md @@ -31,6 +31,12 @@ Install the correct version: Run `fouldecrypt` on an encrypted binary. +## About `foulwrapper` + +`foulwrapper` will find all Mach-Os in a specific application and decrypt them using `fouldecrypt`: + +`usage: foulwrapper (application name or bundle identifier)` + ## Credits @meme: foulplay @JohnCoates: flexdecrypt From f9c01553748637bbdc46b63744b63c0ee639b92c Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 09:32:57 +0700 Subject: [PATCH 012/155] remove zip --- foulwrapper.m | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/foulwrapper.m b/foulwrapper.m index 6330809..ad8a619 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -181,32 +181,34 @@ - (NSString *)shortVersionString; NSString *objectRawPath = [targetPath stringByAppendingPathComponent:objectPath]; int decryptStatus = - my_system([[NSString stringWithFormat:@"fouldecrypt -v '%@' '%@'", escape_arg(objectRawPath), escape_arg( + my_system([[NSString stringWithFormat:@"fouldecrypt '%@' '%@'", escape_arg(objectRawPath), escape_arg( objectFullPath)] UTF8String]); if (decryptStatus != 0) { break; } + NSLog(@"%@: Success", objectRawPath); } fclose(fp); } + return 0 - /* LSApplicationProxy: get app info */ - LSApplicationProxy *appProxy = [LSApplicationProxy applicationProxyForIdentifier:targetId]; - assert(appProxy); + // /* LSApplicationProxy: get app info */ + // LSApplicationProxy *appProxy = [LSApplicationProxy applicationProxyForIdentifier:targetId]; + // assert(appProxy); - /* zip: archive */ - NSString *archiveName = - [NSString stringWithFormat:@"%@_%@_dumped.ipa", [appProxy localizedName], [appProxy shortVersionString]]; - NSString *archivePath = - [[[NSFileManager defaultManager] currentDirectoryPath] stringByAppendingPathComponent:archiveName]; - BOOL didClean = [[NSFileManager defaultManager] removeItemAtPath:archivePath error:nil]; - // assert(didClean); - int zipStatus = - my_system([[NSString stringWithFormat:@"set -e; shopt -s dotglob; cd '%@'; zip -r '%@' .; shopt -u dotglob;", escape_arg([tempURL path]), escape_arg( - archivePath)] UTF8String]); + // /* zip: archive */ + // NSString *archiveName = + // [NSString stringWithFormat:@"%@_%@_dumped.ipa", [appProxy localizedName], [appProxy shortVersionString]]; + // NSString *archivePath = + // [[[NSFileManager defaultManager] currentDirectoryPath] stringByAppendingPathComponent:archiveName]; + // BOOL didClean = [[NSFileManager defaultManager] removeItemAtPath:archivePath error:nil]; + // // assert(didClean); + // int zipStatus = + // my_system([[NSString stringWithFormat:@"set -e; shopt -s dotglob; cd '%@'; zip -r '%@' .; shopt -u dotglob;", escape_arg([tempURL path]), escape_arg( + // archivePath)] UTF8String]); - return zipStatus; + // return zipStatus; } From 6a6e2a42fbc740dd1f910b03e1d29f265b48036d Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 09:38:46 +0700 Subject: [PATCH 013/155] Update build-deb.yml --- .github/workflows/build-deb.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index dc8da07..dc6552d 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -9,7 +9,7 @@ on: jobs: build: - runs-on: macos-latest + runs-on: self-hosted strategy: matrix: provider: [TFP0, LIBKRW, LIBKERNRW] From 3c11bb6d0a01fbbf0d6c2766deb459800557f7ad Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 09:58:45 +0700 Subject: [PATCH 014/155] update version --- control.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/control.template b/control.template index 1657766..7de53d8 100644 --- a/control.template +++ b/control.template @@ -1,6 +1,6 @@ Package: moe.misty.fouldecrypt Name: fouldecrypt -Version: 0.0.4 +Version: 0.0.5 Architecture: iphoneos-arm Depends: applist,zip,{{.depends}} Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 14 From 5e8f1f475abf6e8f1c5c2c22fd1a6b45c37c56b0 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 10:12:57 +0700 Subject: [PATCH 015/155] update actions --- .github/workflows/build-deb.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index dc6552d..3771da6 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -20,7 +20,8 @@ jobs: submodules: recursive - name: Prepare Theos - uses: Randomblock1/theos-action@v1 + uses: und3fined/theos-action@main + - name: Build package run: | From d6acd54c7ade43808820dd332d5b703b19fba366 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 10:27:30 +0700 Subject: [PATCH 016/155] debug controk --- .github/workflows/build-deb.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 3771da6..ed293ac 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -26,7 +26,9 @@ jobs: - name: Build package run: | rm -f packages/* + ls -lah cp control.template control + ls -lah if [[ ${{matrix.provider}} == TFP0 ]]; then USE_TFP0=1 make package FINALPACKAGE=1 elif [[ ${{matrix.provider}} == LIBKRW ]]; then From 1cda46caeb9e400f0eff3d41067c5ee8b5c08d7c Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 10:30:55 +0700 Subject: [PATCH 017/155] ignore control file --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 11513b8..d19e342 100755 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,4 @@ Network Trash Folder Temporary Items .apdisk +control \ No newline at end of file From a8c761cbe335d9caf4b5776d3c2147f34b82e761 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 10:31:01 +0700 Subject: [PATCH 018/155] update workflow --- .github/workflows/build-deb.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index ed293ac..4ed5ecf 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -32,10 +32,10 @@ jobs: if [[ ${{matrix.provider}} == TFP0 ]]; then USE_TFP0=1 make package FINALPACKAGE=1 elif [[ ${{matrix.provider}} == LIBKRW ]]; then - sed -i '' 's/{{.depends}}/libkrw/g' control + sed -i 's/{{.depends}}/libkrw/g' control USE_LIBKRW=1 make package FINALPACKAGE=1 elif [[ ${{matrix.provider}} == LIBKERNRW ]]; then - sed -i '' 's/{{.depends}}/libkernrw0/g' control + sed -i 's/{{.depends}}/libkernrw0/g' control USE_LIBKERNRW=1 make package FINALPACKAGE=1 fi - name: Publish artifact From a105aa09c7fc52e3a388ab98a77a78abd5eec309 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 10:33:07 +0700 Subject: [PATCH 019/155] remove other log and older os --- .github/workflows/build-deb.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 4ed5ecf..818f387 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -12,7 +12,7 @@ jobs: runs-on: self-hosted strategy: matrix: - provider: [TFP0, LIBKRW, LIBKERNRW] + provider: [LIBKRW, LIBKERNRW] steps: - uses: actions/checkout@v2 @@ -26,12 +26,8 @@ jobs: - name: Build package run: | rm -f packages/* - ls -lah cp control.template control - ls -lah - if [[ ${{matrix.provider}} == TFP0 ]]; then - USE_TFP0=1 make package FINALPACKAGE=1 - elif [[ ${{matrix.provider}} == LIBKRW ]]; then + if [[ ${{matrix.provider}} == LIBKRW ]]; then sed -i 's/{{.depends}}/libkrw/g' control USE_LIBKRW=1 make package FINALPACKAGE=1 elif [[ ${{matrix.provider}} == LIBKERNRW ]]; then From 5866fe82b6f3464c1744ec12ba614d724dab59b6 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 10:35:00 +0700 Subject: [PATCH 020/155] upgrade to ios 14.0 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6dd2f71..e5f8225 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -TARGET := iphone:clang:12.2:7.0 +TARGET := iphone:clang:12.2:14.0 ARCHS = arm64 arm64e export ADDITIONAL_CFLAGS = -DTHEOS_LEAN_AND_MEAN -fobjc-arc From c0495cc0b94966abd1b3d8e267d18ff1a56dfdbd Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 10:35:29 +0700 Subject: [PATCH 021/155] rever tfp --- .github/workflows/build-deb.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 818f387..6dd0080 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -12,7 +12,7 @@ jobs: runs-on: self-hosted strategy: matrix: - provider: [LIBKRW, LIBKERNRW] + provider: [TFP0, LIBKRW, LIBKERNRW] steps: - uses: actions/checkout@v2 @@ -27,7 +27,9 @@ jobs: run: | rm -f packages/* cp control.template control - if [[ ${{matrix.provider}} == LIBKRW ]]; then + if [[ ${{matrix.provider}} == TFP0 ]]; then + USE_TFP0=1 make package FINALPACKAGE=1 + elif [[ ${{matrix.provider}} == LIBKRW ]]; then sed -i 's/{{.depends}}/libkrw/g' control USE_LIBKRW=1 make package FINALPACKAGE=1 elif [[ ${{matrix.provider}} == LIBKERNRW ]]; then From 480224411a786385c4f4bdeebdaa9dc4baedcc04 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 10:39:30 +0700 Subject: [PATCH 022/155] revert theos --- .github/workflows/build-deb.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 6dd0080..2f3fc47 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -20,7 +20,7 @@ jobs: submodules: recursive - name: Prepare Theos - uses: und3fined/theos-action@main + uses: Randomblock1/theos-action@v1 - name: Build package From 1f8deede9f2899dad309c11e16165bdcd8e4ff8e Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 10:44:06 +0700 Subject: [PATCH 023/155] check env --- .github/workflows/build-deb.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 2f3fc47..344a1ad 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -22,9 +22,9 @@ jobs: - name: Prepare Theos uses: Randomblock1/theos-action@v1 - - name: Build package run: | + echo "theos: $THEOS" rm -f packages/* cp control.template control if [[ ${{matrix.provider}} == TFP0 ]]; then From 631b3a59619049d36537fb7549c03414040a020b Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 10:46:57 +0700 Subject: [PATCH 024/155] update theos --- .github/workflows/build-deb.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 344a1ad..ce0a9b2 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -24,7 +24,7 @@ jobs: - name: Build package run: | - echo "theos: $THEOS" + $THEOS/bin/update-theos rm -f packages/* cp control.template control if [[ ${{matrix.provider}} == TFP0 ]]; then From b354d6ffbfeecaa8e259ba79ee49d37ee5b2a60e Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 11:41:34 +0700 Subject: [PATCH 025/155] update sdk --- .github/workflows/build-deb.yml | 2 +- Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index ce0a9b2..2f0079c 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -24,7 +24,7 @@ jobs: - name: Build package run: | - $THEOS/bin/update-theos + echo $SYSROOT rm -f packages/* cp control.template control if [[ ${{matrix.provider}} == TFP0 ]]; then diff --git a/Makefile b/Makefile index e5f8225..f65a6ef 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -TARGET := iphone:clang:12.2:14.0 +TARGET := iphone:clang:12.2:13.0 ARCHS = arm64 arm64e export ADDITIONAL_CFLAGS = -DTHEOS_LEAN_AND_MEAN -fobjc-arc From e41197ced11bea1755ca49ccfa0628d6cccd0ba2 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 11:47:46 +0700 Subject: [PATCH 026/155] update theos --- .github/workflows/build-deb.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 2f0079c..338d7c1 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -20,7 +20,7 @@ jobs: submodules: recursive - name: Prepare Theos - uses: Randomblock1/theos-action@v1 + uses: und3fined/theos-action@main # Randomblock1/theos-action@v1 - name: Build package run: | From b944572a52c4671c03bd5e06df48831819043247 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 11:49:02 +0700 Subject: [PATCH 027/155] update to ios 14.0 --- .github/workflows/build-deb.yml | 2 +- Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 338d7c1..2de8c9e 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -24,7 +24,7 @@ jobs: - name: Build package run: | - echo $SYSROOT + echo "SYSROOT -> $SYSROOT" rm -f packages/* cp control.template control if [[ ${{matrix.provider}} == TFP0 ]]; then diff --git a/Makefile b/Makefile index f65a6ef..e5f8225 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -TARGET := iphone:clang:12.2:13.0 +TARGET := iphone:clang:12.2:14.0 ARCHS = arm64 arm64e export ADDITIONAL_CFLAGS = -DTHEOS_LEAN_AND_MEAN -fobjc-arc From 81536f429b248cbc639f90ae1bff8951e57c40f6 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 12:04:28 +0700 Subject: [PATCH 028/155] add DEVELOPER_DIR env --- .github/workflows/build-deb.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 2de8c9e..776209f 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -25,6 +25,7 @@ jobs: - name: Build package run: | echo "SYSROOT -> $SYSROOT" + echo "DEVELOPER_DIR -> $DEVELOPER_DIR" rm -f packages/* cp control.template control if [[ ${{matrix.provider}} == TFP0 ]]; then From d228d94866f2b417daf987301945caf80ae4a097 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 12:07:17 +0700 Subject: [PATCH 029/155] update xcode env --- .github/workflows/build-deb.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 776209f..2e497dc 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -37,6 +37,8 @@ jobs: sed -i 's/{{.depends}}/libkernrw0/g' control USE_LIBKERNRW=1 make package FINALPACKAGE=1 fi + env: + DEVELOPER_DIR: ${{ secrets.DEVELOPER_DIR_12 }} - name: Publish artifact uses: actions/upload-artifact@v2 with: From dc7a9d3f5ce2aeaf99be2cb9a9f5b2545dde4443 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 12:07:38 +0700 Subject: [PATCH 030/155] add note --- .github/workflows/build-deb.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 2e497dc..97aa8f3 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -38,6 +38,7 @@ jobs: USE_LIBKERNRW=1 make package FINALPACKAGE=1 fi env: + # DEVELOPER_DIR=/Applications/Xcode-11.7.app/Contents/Developer DEVELOPER_DIR: ${{ secrets.DEVELOPER_DIR_12 }} - name: Publish artifact uses: actions/upload-artifact@v2 From e94989a2fda2dc881f5333e34357a92b71a4e412 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 12:12:14 +0700 Subject: [PATCH 031/155] update target --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e5f8225..ed17008 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -TARGET := iphone:clang:12.2:14.0 +TARGET := iphone:clang:12.2:13.7 ARCHS = arm64 arm64e export ADDITIONAL_CFLAGS = -DTHEOS_LEAN_AND_MEAN -fobjc-arc From 6619b3f1ca321d6da33c7bd6dd4b97410aae03ba Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 12:14:24 +0700 Subject: [PATCH 032/155] update sdk_version:deployment_version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ed17008..46c30b7 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -TARGET := iphone:clang:12.2:13.7 +TARGET := iphone:clang:13.7:14.0 ARCHS = arm64 arm64e export ADDITIONAL_CFLAGS = -DTHEOS_LEAN_AND_MEAN -fobjc-arc From 27ca6f46f28c3455b1d39a5a8131efcf341f5d04 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 12:16:59 +0700 Subject: [PATCH 033/155] remove log --- .github/workflows/build-deb.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 97aa8f3..e419578 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -24,8 +24,6 @@ jobs: - name: Build package run: | - echo "SYSROOT -> $SYSROOT" - echo "DEVELOPER_DIR -> $DEVELOPER_DIR" rm -f packages/* cp control.template control if [[ ${{matrix.provider}} == TFP0 ]]; then From 9ecfad991ed92983bb891760782f68b2d850a7ae Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 12:24:27 +0700 Subject: [PATCH 034/155] update include --- Makefile | 2 +- {include => x_include}/AppList/ALApplicationList.h | 0 {include => x_include}/AppList/ALApplicationTableDataSource.h | 0 {include => x_include}/AppList/ALValueCell.h | 0 {include => x_include}/AppList/AppList.h | 0 {include => x_include}/MobileContainerManager/MCMContainer.h | 0 .../MobileContainerManager/MCMContainerManager.h | 0 7 files changed, 1 insertion(+), 1 deletion(-) rename {include => x_include}/AppList/ALApplicationList.h (100%) rename {include => x_include}/AppList/ALApplicationTableDataSource.h (100%) rename {include => x_include}/AppList/ALValueCell.h (100%) rename {include => x_include}/AppList/AppList.h (100%) rename {include => x_include}/MobileContainerManager/MCMContainer.h (100%) rename {include => x_include}/MobileContainerManager/MCMContainerManager.h (100%) diff --git a/Makefile b/Makefile index 46c30b7..6a3555f 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ flexdecrypt2_LDFLAGS += -Lkerninfra/libs flexdecrypt2_CCFLAGS += -std=c++2a foulwrapper_FILES = foulwrapper.m -foulwrapper_CFLAGS = -fobjc-arc -Wno-unused-variable -Iinclude +foulwrapper_CFLAGS = -fobjc-arc -Wno-unused-variable -Ix_include foulwrapper_CCFLAGS = $(foulwrapper_CFLAGS) foulwrapper_CODESIGN_FLAGS = -Sentitlements.plist foulwrapper_INSTALL_PATH = /usr/local/bin diff --git a/include/AppList/ALApplicationList.h b/x_include/AppList/ALApplicationList.h similarity index 100% rename from include/AppList/ALApplicationList.h rename to x_include/AppList/ALApplicationList.h diff --git a/include/AppList/ALApplicationTableDataSource.h b/x_include/AppList/ALApplicationTableDataSource.h similarity index 100% rename from include/AppList/ALApplicationTableDataSource.h rename to x_include/AppList/ALApplicationTableDataSource.h diff --git a/include/AppList/ALValueCell.h b/x_include/AppList/ALValueCell.h similarity index 100% rename from include/AppList/ALValueCell.h rename to x_include/AppList/ALValueCell.h diff --git a/include/AppList/AppList.h b/x_include/AppList/AppList.h similarity index 100% rename from include/AppList/AppList.h rename to x_include/AppList/AppList.h diff --git a/include/MobileContainerManager/MCMContainer.h b/x_include/MobileContainerManager/MCMContainer.h similarity index 100% rename from include/MobileContainerManager/MCMContainer.h rename to x_include/MobileContainerManager/MCMContainer.h diff --git a/include/MobileContainerManager/MCMContainerManager.h b/x_include/MobileContainerManager/MCMContainerManager.h similarity index 100% rename from include/MobileContainerManager/MCMContainerManager.h rename to x_include/MobileContainerManager/MCMContainerManager.h From 3ecf8fec19cd2896ce217e4bee46305ee2142509 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 12:26:37 +0700 Subject: [PATCH 035/155] disable include --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6a3555f..9177510 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ flexdecrypt2_LDFLAGS += -Lkerninfra/libs flexdecrypt2_CCFLAGS += -std=c++2a foulwrapper_FILES = foulwrapper.m -foulwrapper_CFLAGS = -fobjc-arc -Wno-unused-variable -Ix_include +foulwrapper_CFLAGS = -fobjc-arc -Wno-unused-variable # -Ix_include foulwrapper_CCFLAGS = $(foulwrapper_CFLAGS) foulwrapper_CODESIGN_FLAGS = -Sentitlements.plist foulwrapper_INSTALL_PATH = /usr/local/bin From 1403f6e6b310e43e775cc00886d0b2951a5dbea3 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 12:32:12 +0700 Subject: [PATCH 036/155] update include --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9177510..75546cf 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,8 @@ include $(THEOS)/makefiles/common.mk TOOL_NAME = fouldecrypt flexdecrypt2 foulwrapper +EXTRAINCDIRS="./x_include" + export USE_TFP0 = 1 # export USE_LIBKRW = 1 # export USE_LIBKERNRW = 1 @@ -29,7 +31,7 @@ flexdecrypt2_LDFLAGS += -Lkerninfra/libs flexdecrypt2_CCFLAGS += -std=c++2a foulwrapper_FILES = foulwrapper.m -foulwrapper_CFLAGS = -fobjc-arc -Wno-unused-variable # -Ix_include +foulwrapper_CFLAGS = -fobjc-arc -Wno-unused-variable $(patsubst %,-I%,$(EXTRAINCDIRS)) -I. foulwrapper_CCFLAGS = $(foulwrapper_CFLAGS) foulwrapper_CODESIGN_FLAGS = -Sentitlements.plist foulwrapper_INSTALL_PATH = /usr/local/bin From 33c44b4cdbfd210d131493dac55c24b555995b3a Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 12:35:00 +0700 Subject: [PATCH 037/155] add debug --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 75546cf..b95bfe8 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,13 @@ TARGET := iphone:clang:13.7:14.0 ARCHS = arm64 arm64e +DEBUG = 1 export ADDITIONAL_CFLAGS = -DTHEOS_LEAN_AND_MEAN -fobjc-arc include $(THEOS)/makefiles/common.mk TOOL_NAME = fouldecrypt flexdecrypt2 foulwrapper -EXTRAINCDIRS="./x_include" +EXTRAINCDIRS="x_include" export USE_TFP0 = 1 # export USE_LIBKRW = 1 From ad1c0ac361332ea622a359bdeea9abd914a3bb22 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 12:38:36 +0700 Subject: [PATCH 038/155] update sdk --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index b95bfe8..be01ada 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -TARGET := iphone:clang:13.7:14.0 +TARGET := iphone:clang:14.5:14.0 ARCHS = arm64 arm64e DEBUG = 1 export ADDITIONAL_CFLAGS = -DTHEOS_LEAN_AND_MEAN -fobjc-arc @@ -32,7 +32,7 @@ flexdecrypt2_LDFLAGS += -Lkerninfra/libs flexdecrypt2_CCFLAGS += -std=c++2a foulwrapper_FILES = foulwrapper.m -foulwrapper_CFLAGS = -fobjc-arc -Wno-unused-variable $(patsubst %,-I%,$(EXTRAINCDIRS)) -I. +foulwrapper_CFLAGS = -fobjc-arc -Wno-unused-variable -I. -Ix_include foulwrapper_CCFLAGS = $(foulwrapper_CFLAGS) foulwrapper_CODESIGN_FLAGS = -Sentitlements.plist foulwrapper_INSTALL_PATH = /usr/local/bin From ee2731ec64af74dd14891195937fad6dbc268df1 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 12:44:39 +0700 Subject: [PATCH 039/155] update CFLAFS --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index be01ada..c81bd16 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ -TARGET := iphone:clang:14.5:14.0 +TARGET := iphone:clang:12.4:14.0 ARCHS = arm64 arm64e DEBUG = 1 -export ADDITIONAL_CFLAGS = -DTHEOS_LEAN_AND_MEAN -fobjc-arc +export ADDITIONAL_CFLAGS = -DTHEOS_LEAN_AND_MEAN -fobjc-arc -Ix_include include $(THEOS)/makefiles/common.mk @@ -32,7 +32,7 @@ flexdecrypt2_LDFLAGS += -Lkerninfra/libs flexdecrypt2_CCFLAGS += -std=c++2a foulwrapper_FILES = foulwrapper.m -foulwrapper_CFLAGS = -fobjc-arc -Wno-unused-variable -I. -Ix_include +foulwrapper_CFLAGS = -fobjc-arc -Wno-unused-variable # -Ix_include foulwrapper_CCFLAGS = $(foulwrapper_CFLAGS) foulwrapper_CODESIGN_FLAGS = -Sentitlements.plist foulwrapper_INSTALL_PATH = /usr/local/bin From 140a2716090b605f767d40de6a6c47b4334ac62a Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 12:47:58 +0700 Subject: [PATCH 040/155] override theos AppList --- .github/workflows/build-deb.yml | 1 + {x_include => include}/AppList/ALApplicationList.h | 0 {x_include => include}/AppList/ALApplicationTableDataSource.h | 0 {x_include => include}/AppList/ALValueCell.h | 0 {x_include => include}/AppList/AppList.h | 0 {x_include => include}/MobileContainerManager/MCMContainer.h | 0 .../MobileContainerManager/MCMContainerManager.h | 0 7 files changed, 1 insertion(+) rename {x_include => include}/AppList/ALApplicationList.h (100%) rename {x_include => include}/AppList/ALApplicationTableDataSource.h (100%) rename {x_include => include}/AppList/ALValueCell.h (100%) rename {x_include => include}/AppList/AppList.h (100%) rename {x_include => include}/MobileContainerManager/MCMContainer.h (100%) rename {x_include => include}/MobileContainerManager/MCMContainerManager.h (100%) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index e419578..45c6b02 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -24,6 +24,7 @@ jobs: - name: Build package run: | + cp -rf include/* $THEOS/include/ rm -f packages/* cp control.template control if [[ ${{matrix.provider}} == TFP0 ]]; then diff --git a/x_include/AppList/ALApplicationList.h b/include/AppList/ALApplicationList.h similarity index 100% rename from x_include/AppList/ALApplicationList.h rename to include/AppList/ALApplicationList.h diff --git a/x_include/AppList/ALApplicationTableDataSource.h b/include/AppList/ALApplicationTableDataSource.h similarity index 100% rename from x_include/AppList/ALApplicationTableDataSource.h rename to include/AppList/ALApplicationTableDataSource.h diff --git a/x_include/AppList/ALValueCell.h b/include/AppList/ALValueCell.h similarity index 100% rename from x_include/AppList/ALValueCell.h rename to include/AppList/ALValueCell.h diff --git a/x_include/AppList/AppList.h b/include/AppList/AppList.h similarity index 100% rename from x_include/AppList/AppList.h rename to include/AppList/AppList.h diff --git a/x_include/MobileContainerManager/MCMContainer.h b/include/MobileContainerManager/MCMContainer.h similarity index 100% rename from x_include/MobileContainerManager/MCMContainer.h rename to include/MobileContainerManager/MCMContainer.h diff --git a/x_include/MobileContainerManager/MCMContainerManager.h b/include/MobileContainerManager/MCMContainerManager.h similarity index 100% rename from x_include/MobileContainerManager/MCMContainerManager.h rename to include/MobileContainerManager/MCMContainerManager.h From d29b9ab6153f1585b167e383a709807d8b477a39 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 12:48:31 +0700 Subject: [PATCH 041/155] save --- .github/workflows/build-deb.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 45c6b02..a016686 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -24,7 +24,7 @@ jobs: - name: Build package run: | - cp -rf include/* $THEOS/include/ + cp -rf include/* $THEOS/vendor/include/ rm -f packages/* cp control.template control if [[ ${{matrix.provider}} == TFP0 ]]; then From 449150b6add6e559e7b5a523554d0a1e6de35e5d Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 12:50:42 +0700 Subject: [PATCH 042/155] fix synxtax --- foulwrapper.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foulwrapper.m b/foulwrapper.m index ad8a619..cadd0c3 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -192,7 +192,7 @@ - (NSString *)shortVersionString; fclose(fp); } - return 0 + return 0; // /* LSApplicationProxy: get app info */ // LSApplicationProxy *appProxy = [LSApplicationProxy applicationProxyForIdentifier:targetId]; From d48d35faa14428a6dd4c5406f197dd6728a20a54 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 12:54:42 +0700 Subject: [PATCH 043/155] update --- control.template | 2 +- foulwrapper.m | 18 ------------------ layout/DEBIAN/control | 4 ++-- 3 files changed, 3 insertions(+), 21 deletions(-) diff --git a/control.template b/control.template index 7de53d8..5589ed7 100644 --- a/control.template +++ b/control.template @@ -1,7 +1,7 @@ Package: moe.misty.fouldecrypt Name: fouldecrypt Version: 0.0.5 -Architecture: iphoneos-arm +Architecture: iphoneos-arm64e Depends: applist,zip,{{.depends}} Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 14 Maintainer: misty diff --git a/foulwrapper.m b/foulwrapper.m index cadd0c3..012cf1f 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -193,22 +193,4 @@ - (NSString *)shortVersionString; } return 0; - - // /* LSApplicationProxy: get app info */ - // LSApplicationProxy *appProxy = [LSApplicationProxy applicationProxyForIdentifier:targetId]; - // assert(appProxy); - - - // /* zip: archive */ - // NSString *archiveName = - // [NSString stringWithFormat:@"%@_%@_dumped.ipa", [appProxy localizedName], [appProxy shortVersionString]]; - // NSString *archivePath = - // [[[NSFileManager defaultManager] currentDirectoryPath] stringByAppendingPathComponent:archiveName]; - // BOOL didClean = [[NSFileManager defaultManager] removeItemAtPath:archivePath error:nil]; - // // assert(didClean); - // int zipStatus = - // my_system([[NSString stringWithFormat:@"set -e; shopt -s dotglob; cd '%@'; zip -r '%@' .; shopt -u dotglob;", escape_arg([tempURL path]), escape_arg( - // archivePath)] UTF8String]); - - // return zipStatus; } diff --git a/layout/DEBIAN/control b/layout/DEBIAN/control index 9ab7fa5..70f42b0 100644 --- a/layout/DEBIAN/control +++ b/layout/DEBIAN/control @@ -1,7 +1,7 @@ Package: moe.misty.fouldecrypt Name: fouldecrypt -Version: 0.0.4 -Architecture: iphoneos-arm +Version: 0.0.5 +Architecture: iphoneos-arm64e Depends: applist,zip Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 14 Maintainer: misty From 8a8aeec55523514e7ee99594f4040a7bd62e350a Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 12:59:50 +0700 Subject: [PATCH 044/155] clean --- Makefile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Makefile b/Makefile index c81bd16..9889518 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,12 @@ TARGET := iphone:clang:12.4:14.0 ARCHS = arm64 arm64e DEBUG = 1 -export ADDITIONAL_CFLAGS = -DTHEOS_LEAN_AND_MEAN -fobjc-arc -Ix_include +export ADDITIONAL_CFLAGS = -DTHEOS_LEAN_AND_MEAN -fobjc-arc include $(THEOS)/makefiles/common.mk TOOL_NAME = fouldecrypt flexdecrypt2 foulwrapper -EXTRAINCDIRS="x_include" - export USE_TFP0 = 1 # export USE_LIBKRW = 1 # export USE_LIBKERNRW = 1 From 4ffecb8b4fed91f64ac829ee32b624b84eefc86a Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 13:03:50 +0700 Subject: [PATCH 045/155] update std c --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 9889518..14fb54f 100644 --- a/Makefile +++ b/Makefile @@ -37,5 +37,6 @@ foulwrapper_INSTALL_PATH = /usr/local/bin foulwrapper_FRAMEWORKS = Foundation MobileCoreServices foulwrapper_PRIVATE_FRAMEWORKS = MobileContainerManager foulwrapper_LIBRARIES = applist +foulwrapper_CCFLAGS += -std=c++2a include $(THEOS_MAKE_PATH)/tool.mk From 2a67323c5f94ea528b88009c61e8b9fc6ef57555 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 13:06:53 +0700 Subject: [PATCH 046/155] use xcode system --- .github/workflows/build-deb.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index a016686..3eb9abd 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -36,9 +36,9 @@ jobs: sed -i 's/{{.depends}}/libkernrw0/g' control USE_LIBKERNRW=1 make package FINALPACKAGE=1 fi - env: + # env: # DEVELOPER_DIR=/Applications/Xcode-11.7.app/Contents/Developer - DEVELOPER_DIR: ${{ secrets.DEVELOPER_DIR_12 }} + # DEVELOPER_DIR: ${{ secrets.DEVELOPER_DIR_12 }} - name: Publish artifact uses: actions/upload-artifact@v2 with: From 99af060e5f03dfcc8472388e5f37f4092fca529c Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 13:15:34 +0700 Subject: [PATCH 047/155] update --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 14fb54f..a9c4d09 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -TARGET := iphone:clang:12.4:14.0 +TARGET := iphone:clang:12.4:7.0 ARCHS = arm64 arm64e DEBUG = 1 export ADDITIONAL_CFLAGS = -DTHEOS_LEAN_AND_MEAN -fobjc-arc From 349c11caba0d9d82fd9472ee158b34d978a7cd7e Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 13:23:02 +0700 Subject: [PATCH 048/155] disable debug --- Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile b/Makefile index a9c4d09..0a42032 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,5 @@ TARGET := iphone:clang:12.4:7.0 ARCHS = arm64 arm64e -DEBUG = 1 export ADDITIONAL_CFLAGS = -DTHEOS_LEAN_AND_MEAN -fobjc-arc include $(THEOS)/makefiles/common.mk From 82c908401e8b634ef058a28abd189d7d16e7a914 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 13:29:52 +0700 Subject: [PATCH 049/155] back to arm --- Makefile | 1 - control.template | 2 +- layout/DEBIAN/control | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 0a42032..bdae012 100644 --- a/Makefile +++ b/Makefile @@ -36,6 +36,5 @@ foulwrapper_INSTALL_PATH = /usr/local/bin foulwrapper_FRAMEWORKS = Foundation MobileCoreServices foulwrapper_PRIVATE_FRAMEWORKS = MobileContainerManager foulwrapper_LIBRARIES = applist -foulwrapper_CCFLAGS += -std=c++2a include $(THEOS_MAKE_PATH)/tool.mk diff --git a/control.template b/control.template index 5589ed7..7de53d8 100644 --- a/control.template +++ b/control.template @@ -1,7 +1,7 @@ Package: moe.misty.fouldecrypt Name: fouldecrypt Version: 0.0.5 -Architecture: iphoneos-arm64e +Architecture: iphoneos-arm Depends: applist,zip,{{.depends}} Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 14 Maintainer: misty diff --git a/layout/DEBIAN/control b/layout/DEBIAN/control index 70f42b0..6b9e87e 100644 --- a/layout/DEBIAN/control +++ b/layout/DEBIAN/control @@ -1,7 +1,7 @@ Package: moe.misty.fouldecrypt Name: fouldecrypt Version: 0.0.5 -Architecture: iphoneos-arm64e +Architecture: iphoneos-arm Depends: applist,zip Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 14 Maintainer: misty From a64617a778ab70db3268f992d1091846c24de07e Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 13:30:52 +0700 Subject: [PATCH 050/155] build one --- .github/workflows/build-deb.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 3eb9abd..6ae1231 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -12,7 +12,8 @@ jobs: runs-on: self-hosted strategy: matrix: - provider: [TFP0, LIBKRW, LIBKERNRW] + #provider: [TFP0, LIBKRW, LIBKERNRW] + provider: [TFP0] steps: - uses: actions/checkout@v2 From 5cd634001aee0a9d8dd0b1f54457d77ee6c396cb Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 13:34:45 +0700 Subject: [PATCH 051/155] remove deps --- .github/workflows/build-deb.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 6ae1231..2008463 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -29,6 +29,7 @@ jobs: rm -f packages/* cp control.template control if [[ ${{matrix.provider}} == TFP0 ]]; then + sed -i 's/,{{.depends}}//g' control USE_TFP0=1 make package FINALPACKAGE=1 elif [[ ${{matrix.provider}} == LIBKRW ]]; then sed -i 's/{{.depends}}/libkrw/g' control From 4f6a32fd13f15bc569241c68a2e284b6612a92b7 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 13:46:31 +0700 Subject: [PATCH 052/155] remove other log --- foulwrapper.m | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/foulwrapper.m b/foulwrapper.m index 012cf1f..f1b72fe 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -47,7 +47,11 @@ } if (WIFEXITED(status)) { - fprintf(stderr, "pid %d exited, status=%d\n", pid, WEXITSTATUS(status)); + if (WEXITSTATUS(status) != 0) + { + fprintf(stderr, "pid %d, exited with status %d\n", pid, WEXITSTATUS(status)); + return WEXITSTATUS(status); + } } else if (WIFSIGNALED(status)) { @@ -57,10 +61,10 @@ { fprintf(stderr, "pid %d stopped by signal %d\n", pid, WSTOPSIG(status)); } - else if (WIFCONTINUED(status)) - { - fprintf(stderr, "pid %d continued\n", pid); - } + // else if (WIFCONTINUED(status)) + // { + // // fprintf(stderr, "pid %d continued\n", pid); + // } } while (!WIFEXITED(status) && !WIFSIGNALED(status)); if (WIFSIGNALED(status)) @@ -186,7 +190,7 @@ - (NSString *)shortVersionString; if (decryptStatus != 0) { break; } - NSLog(@"%@: Success", objectRawPath); + NSLog(@"%@: Success", objectPath); } fclose(fp); From b3819f3e569c7e4c24b1be7db1a9697ae1f63ae1 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 14:17:08 +0700 Subject: [PATCH 053/155] add more log --- foulwrapper.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/foulwrapper.m b/foulwrapper.m index f1b72fe..f22ca7a 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -196,5 +196,7 @@ - (NSString *)shortVersionString; fclose(fp); } + NSLog(@"Done. Saved in %@", tempPath); + return 0; } From 2f8dea3d528d17cbf28551323c5bfd7b3f08a92b Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 14:19:44 +0700 Subject: [PATCH 054/155] update maintainer --- control.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/control.template b/control.template index 7de53d8..dee2aa9 100644 --- a/control.template +++ b/control.template @@ -4,7 +4,7 @@ Version: 0.0.5 Architecture: iphoneos-arm Depends: applist,zip,{{.depends}} Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 14 -Maintainer: misty +Maintainer: und3fined Author: misty Section: System Tag: role::hacker From 8aaf8b51e017ebca151f2b7a613eab650d72d6c4 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 14:30:12 +0700 Subject: [PATCH 055/155] disable VERBOSE --- foulwrapper.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foulwrapper.m b/foulwrapper.m index f22ca7a..ab5bc8d 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -8,7 +8,7 @@ #import #import -static int VERBOSE = 0; +// static int VERBOSE = 0; #define MH_MAGIC_64 0xfeedfacf /* the 64-bit mach magic number */ #define MH_CIGAM_64 0xcffaedfe /* NXSwapInt(MH_MAGIC_64) */ From 0dee6d9a6121f567f1c4a68bb30ab399e6f5c034 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 14:47:02 +0700 Subject: [PATCH 056/155] allow send tmp path --- foulwrapper.m | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/foulwrapper.m b/foulwrapper.m index ab5bc8d..96b928c 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -135,14 +135,17 @@ - (NSString *)shortVersionString; [[error localizedDescription] UTF8String]); return 1; } - NSLog(@"%@", targetPath); - + fprintf(stdout, "Target path: %s", targetPath); + NSString *outDir = [NSString stringWithUTF8String:argv[2]]; + NSURL *outURL = [NSURL fileURLWithPath:outDir + isDirectory:YES]; /* Make a copy of app bundle. */ NSURL *tempURL = [[NSFileManager defaultManager] URLForDirectory:NSItemReplacementDirectory inDomain:NSUserDomainMask - appropriateForURL:[NSURL fileURLWithPath:[[NSFileManager defaultManager] currentDirectoryPath]] - create:YES error:&error]; + appropriateForURL:outURL + create:YES + error:&error]; if (!tempURL) { fprintf(stderr, @@ -190,13 +193,13 @@ - (NSString *)shortVersionString; if (decryptStatus != 0) { break; } - NSLog(@"%@: Success", objectPath); + fprintf(stdout, "%s: Success", objectPath); } fclose(fp); } - NSLog(@"Done. Saved in %@", tempPath); + fprintf(stdout, "Done. Saved in %s", tempPath); return 0; } From cb08d7b79d552466a2bef44766d83b227e54e01f Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 14:55:27 +0700 Subject: [PATCH 057/155] build new log --- foulwrapper.m | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/foulwrapper.m b/foulwrapper.m index 96b928c..77c4733 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -135,7 +135,7 @@ - (NSString *)shortVersionString; [[error localizedDescription] UTF8String]); return 1; } - fprintf(stdout, "Target path: %s", targetPath); + fprintf(stdout, "Target path: %s", [targetPath UTF8String]); NSString *outDir = [NSString stringWithUTF8String:argv[2]]; NSURL *outURL = [NSURL fileURLWithPath:outDir isDirectory:YES]; @@ -193,13 +193,23 @@ - (NSString *)shortVersionString; if (decryptStatus != 0) { break; } - fprintf(stdout, "%s: Success", objectPath); + fprintf(stdout, "%s: Success", [objectPath UTF8String]); } fclose(fp); } - fprintf(stdout, "Done. Saved in %s", tempPath); + // create new file with content + NSFileManager *fileX = [NSFileManager defaultManager]; + NSString *newFilePath = [tempURL stringByAppendingPathComponent:@"decrypt.day"]; +     NSError *error; +     if ([fileX createFileAtPath:newFilePath contents:[@"und3fined" dataUsingEncoding:NSUTF8StringEncoding] attributes:nil]){ + } + else{ +     NSLog(@"Create error: %@", error); + }       + + fprintf(stdout, "Done. Saved in %s", [tempPath UTF8String]); return 0; } From 6eab0125820177c52e03ee6bee90625da226289f Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 14:56:49 +0700 Subject: [PATCH 058/155] update tempPath --- foulwrapper.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foulwrapper.m b/foulwrapper.m index 77c4733..a66b207 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -201,7 +201,7 @@ - (NSString *)shortVersionString; // create new file with content NSFileManager *fileX = [NSFileManager defaultManager]; - NSString *newFilePath = [tempURL stringByAppendingPathComponent:@"decrypt.day"]; + NSString *newFilePath = [tempPath stringByAppendingPathComponent:@"decrypt.day"];     NSError *error;     if ([fileX createFileAtPath:newFilePath contents:[@"und3fined" dataUsingEncoding:NSUTF8StringEncoding] attributes:nil]){ } From 9255c2c4c93e96d911e243107e7532191a241907 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 14:59:17 +0700 Subject: [PATCH 059/155] remove create file --- foulwrapper.m | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/foulwrapper.m b/foulwrapper.m index a66b207..614556e 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -200,14 +200,14 @@ - (NSString *)shortVersionString; } // create new file with content - NSFileManager *fileX = [NSFileManager defaultManager]; - NSString *newFilePath = [tempPath stringByAppendingPathComponent:@"decrypt.day"]; -     NSError *error; -     if ([fileX createFileAtPath:newFilePath contents:[@"und3fined" dataUsingEncoding:NSUTF8StringEncoding] attributes:nil]){ - } - else{ -     NSLog(@"Create error: %@", error); - }       + // NSFileManager *fileX = [NSFileManager defaultManager]; + // NSString *newFilePath = [tempPath stringByAppendingPathComponent:@"decrypt.day"]; + //     NSError *error; + //     if ([fileX createFileAtPath:newFilePath contents:[@"und3fined" dataUsingEncoding:NSUTF8StringEncoding] attributes:nil]){ + // } + // else{ + //     NSLog(@"Create error: %@", error); + // }       fprintf(stdout, "Done. Saved in %s", [tempPath UTF8String]); From bf1cf0f19ba91ff4d56cdeb9f568fe3d2f1d94b8 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 18:16:42 +0700 Subject: [PATCH 060/155] move from stdout to stderr --- foulwrapper.m | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/foulwrapper.m b/foulwrapper.m index 614556e..8050cab 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -135,7 +135,7 @@ - (NSString *)shortVersionString; [[error localizedDescription] UTF8String]); return 1; } - fprintf(stdout, "Target path: %s", [targetPath UTF8String]); + fprintf(stderr, "Target path: %s", [targetPath UTF8String]); NSString *outDir = [NSString stringWithUTF8String:argv[2]]; NSURL *outURL = [NSURL fileURLWithPath:outDir isDirectory:YES]; @@ -193,23 +193,13 @@ - (NSString *)shortVersionString; if (decryptStatus != 0) { break; } - fprintf(stdout, "%s: Success", [objectPath UTF8String]); + fprintf(stderr, "%s: Success", [objectPath UTF8String]); } fclose(fp); } - // create new file with content - // NSFileManager *fileX = [NSFileManager defaultManager]; - // NSString *newFilePath = [tempPath stringByAppendingPathComponent:@"decrypt.day"]; - //     NSError *error; - //     if ([fileX createFileAtPath:newFilePath contents:[@"und3fined" dataUsingEncoding:NSUTF8StringEncoding] attributes:nil]){ - // } - // else{ - //     NSLog(@"Create error: %@", error); - // }       - - fprintf(stdout, "Done. Saved in %s", [tempPath UTF8String]); + fprintf(stderr, "Done. Saved in %s", [tempPath UTF8String]); return 0; } From e8753f799214312f7424ba34cee510a1e5da7fd2 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 18:19:16 +0700 Subject: [PATCH 061/155] log outdir --- foulwrapper.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/foulwrapper.m b/foulwrapper.m index 8050cab..40cb546 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -140,6 +140,8 @@ - (NSString *)shortVersionString; NSURL *outURL = [NSURL fileURLWithPath:outDir isDirectory:YES]; + NSLog(@"outDir %@", outDir); + /* Make a copy of app bundle. */ NSURL *tempURL = [[NSFileManager defaultManager] URLForDirectory:NSItemReplacementDirectory inDomain:NSUserDomainMask From 89d8fbbb4f86cc6a67577df74a91009d0154217d Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 18:27:11 +0700 Subject: [PATCH 062/155] revert zip --- foulwrapper.m | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/foulwrapper.m b/foulwrapper.m index 40cb546..286b60a 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -135,7 +135,7 @@ - (NSString *)shortVersionString; [[error localizedDescription] UTF8String]); return 1; } - fprintf(stderr, "Target path: %s", [targetPath UTF8String]); + fprintf(stderr, "Target path: %s\n", [targetPath UTF8String]); NSString *outDir = [NSString stringWithUTF8String:argv[2]]; NSURL *outURL = [NSURL fileURLWithPath:outDir isDirectory:YES]; @@ -195,13 +195,29 @@ - (NSString *)shortVersionString; if (decryptStatus != 0) { break; } - fprintf(stderr, "%s: Success", [objectPath UTF8String]); + fprintf(stderr, "%s: Success\n", [objectPath UTF8String]); } fclose(fp); } - fprintf(stderr, "Done. Saved in %s", [tempPath UTF8String]); + LSApplicationProxy *appProxy = [LSApplicationProxy applicationProxyForIdentifier:targetId]; + assert(appProxy); - return 0; + /* zip: archive */ + NSString *archiveName = + [NSString stringWithFormat:@"%@_%@_dump.ipa", targetId, [appProxy shortVersionString]]; + + BOOL didClean = [[NSFileManager defaultManager] removeItemAtPath:archivePath error:nil]; + + int zipStatus = + my_system([[ + NSString stringWithFormat:@"set -e; shopt -s dotglob; cd '%@'; zip -qrX '%@' .; shopt -u dotglob;", + escape_arg([tempURL path]), + escape_arg(archivePath) + ] UTF8String]); + + fprintf(stderr, "Done.\n"); + + return zipStatus; } From 88a47d74a7ccc9e8eb984c3f023d2a43c35e0d93 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 18:31:30 +0700 Subject: [PATCH 063/155] update more --- foulwrapper.m | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/foulwrapper.m b/foulwrapper.m index 286b60a..c9dc134 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -207,6 +207,8 @@ - (NSString *)shortVersionString; /* zip: archive */ NSString *archiveName = [NSString stringWithFormat:@"%@_%@_dump.ipa", targetId, [appProxy shortVersionString]]; + NSString *archivePath = + [[[NSFileManager defaultManager] currentDirectoryPath] stringByAppendingPathComponent:archiveName]; BOOL didClean = [[NSFileManager defaultManager] removeItemAtPath:archivePath error:nil]; @@ -217,6 +219,17 @@ - (NSString *)shortVersionString; escape_arg(archivePath) ] UTF8String]); + if (zipStatus != 0) { + fprintf(stderr, "cannot create archive: %s\n", [[error localizedDescription] UTF8String]); + + my_system([[ + NSString stringWithFormat:@"set -e; shopt -s dotglob; rm -rf '%@'; shopt -u dotglob;", + escape_arg([tempURL path]) + ] UTF8String]); + + return 1; + } + fprintf(stderr, "Done.\n"); return zipStatus; From 39ab997c2f0bb65624b04448fa89a6bcc792c44f Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 18:40:14 +0700 Subject: [PATCH 064/155] add clean --- foulwrapper.m | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/foulwrapper.m b/foulwrapper.m index c9dc134..af92cc7 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -135,21 +135,16 @@ - (NSString *)shortVersionString; [[error localizedDescription] UTF8String]); return 1; } - fprintf(stderr, "Target path: %s\n", [targetPath UTF8String]); - NSString *outDir = [NSString stringWithUTF8String:argv[2]]; - NSURL *outURL = [NSURL fileURLWithPath:outDir - isDirectory:YES]; - NSLog(@"outDir %@", outDir); + fprintf(stderr, "Target app -> %s\n", [targetId UTF8String]); /* Make a copy of app bundle. */ NSURL *tempURL = [[NSFileManager defaultManager] URLForDirectory:NSItemReplacementDirectory inDomain:NSUserDomainMask - appropriateForURL:outURL + appropriateForURL:[NSURL fileURLWithPath:[[NSFileManager defaultManager] currentDirectoryPath]] create:YES error:&error]; - if (!tempURL) - { + if (!tempURL) { fprintf(stderr, "cannot create appropriate item replacement directory: %s\n", [[error localizedDescription] UTF8String]); @@ -158,13 +153,11 @@ - (NSString *)shortVersionString; NSString *tempPath = [[tempURL path] stringByAppendingPathComponent:@"Payload"]; BOOL didCopy = [[NSFileManager defaultManager] copyItemAtPath:targetPath toPath:tempPath error:&error]; - if (!didCopy) - { + if (!didCopy) { fprintf(stderr, "cannot copy app bundle: %s\n", [[error localizedDescription] UTF8String]); return 1; } - /* Enumerate entire app bundle to find all Mach-Os. */ NSEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtPath:tempPath]; NSString *objectPath = nil; @@ -185,8 +178,7 @@ - (NSString *)shortVersionString; continue; } - if (num == MH_MAGIC_64 || num == FAT_MAGIC_64) - { + if (num == MH_MAGIC_64 || num == FAT_MAGIC_64) { NSString *objectRawPath = [targetPath stringByAppendingPathComponent:objectPath]; int decryptStatus = @@ -195,7 +187,7 @@ - (NSString *)shortVersionString; if (decryptStatus != 0) { break; } - fprintf(stderr, "%s: Success\n", [objectPath UTF8String]); + fprintf(stderr, "[dump] %s: Success\n", [objectPath UTF8String]); } fclose(fp); @@ -219,17 +211,16 @@ - (NSString *)shortVersionString; escape_arg(archivePath) ] UTF8String]); + fprintf(stderr, "Archive -> %s\n", [archivePath UTF8String]); + fprintf(stderr, "Clean %s.\n", [tempPath UTF8String]); + [[NSFileManager defaultManager] removeItemAtPath:tempPath error:nil]; + if (zipStatus != 0) { fprintf(stderr, "cannot create archive: %s\n", [[error localizedDescription] UTF8String]); - - my_system([[ - NSString stringWithFormat:@"set -e; shopt -s dotglob; rm -rf '%@'; shopt -u dotglob;", - escape_arg([tempURL path]) - ] UTF8String]); - return 1; } + fprintf(stderr, "Done.\n"); return zipStatus; From 098d5586c90b78e8319c4caaea4b0db883f3352b Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 18:45:36 +0700 Subject: [PATCH 065/155] add sign --- foulwrapper.m | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/foulwrapper.m b/foulwrapper.m index af92cc7..fa64bd7 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -196,7 +196,12 @@ - (NSString *)shortVersionString; LSApplicationProxy *appProxy = [LSApplicationProxy applicationProxyForIdentifier:targetId]; assert(appProxy); - /* zip: archive */ + /* Sign the app bundle. */ + NSString *decryptSign = [tempPath stringByAppendingPathComponent:@"decrypt.day"]; + NSFileManager *fileSign = [NSFileManager defaultManager]; + [fileSign createFileAtPath:decryptSign contents:[@"und3fined" dataUsingEncoding:NSUTF8StringEncoding] attributes:nil]; + + /* zip: archive */ NSString *archiveName = [NSString stringWithFormat:@"%@_%@_dump.ipa", targetId, [appProxy shortVersionString]]; NSString *archivePath = @@ -220,7 +225,6 @@ - (NSString *)shortVersionString; return 1; } - fprintf(stderr, "Done.\n"); return zipStatus; From 2e0555d0ddb51a9a7dcdcf25b5af91e5e625e23a Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 18:47:49 +0700 Subject: [PATCH 066/155] clean code --- foulwrapper.m | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/foulwrapper.m b/foulwrapper.m index fa64bd7..981b5bb 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -198,8 +198,7 @@ - (NSString *)shortVersionString; /* Sign the app bundle. */ NSString *decryptSign = [tempPath stringByAppendingPathComponent:@"decrypt.day"]; - NSFileManager *fileSign = [NSFileManager defaultManager]; - [fileSign createFileAtPath:decryptSign contents:[@"und3fined" dataUsingEncoding:NSUTF8StringEncoding] attributes:nil]; + [[NSFileManager defaultManager] createFileAtPath:decryptSign contents:[@"und3fined" dataUsingEncoding:NSUTF8StringEncoding] attributes:nil]; /* zip: archive */ NSString *archiveName = From ba6d4b62d4c2049c72a9c90788563de7a438317c Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 18:54:10 +0700 Subject: [PATCH 067/155] Just zip Payload --- foulwrapper.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/foulwrapper.m b/foulwrapper.m index 981b5bb..0c6b5b0 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -210,14 +210,14 @@ - (NSString *)shortVersionString; int zipStatus = my_system([[ - NSString stringWithFormat:@"set -e; shopt -s dotglob; cd '%@'; zip -qrX '%@' .; shopt -u dotglob;", + NSString stringWithFormat:@"set -e; shopt -s dotglob; cd '%@'; zip -qrX '%@' ./Payload; shopt -u dotglob;", escape_arg([tempURL path]), escape_arg(archivePath) ] UTF8String]); - fprintf(stderr, "Archive -> %s\n", [archivePath UTF8String]); - fprintf(stderr, "Clean %s.\n", [tempPath UTF8String]); - [[NSFileManager defaultManager] removeItemAtPath:tempPath error:nil]; + fprintf(stderr, "Archive -> %s\n", [archiveName UTF8String]); + fprintf(stderr, "Remove temp %s.\n", [tempURL UTF8String]); + [[NSFileManager defaultManager] removeItemAtPath:tempURL error:nil]; if (zipStatus != 0) { fprintf(stderr, "cannot create archive: %s\n", [[error localizedDescription] UTF8String]); From 7534d13876e78b3e791a5f49ea12dc6d3b9a45d7 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 19:21:09 +0700 Subject: [PATCH 068/155] update remove and remove default code --- foulwrapper.m | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/foulwrapper.m b/foulwrapper.m index 0c6b5b0..3af8e55 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -200,6 +200,15 @@ - (NSString *)shortVersionString; NSString *decryptSign = [tempPath stringByAppendingPathComponent:@"decrypt.day"]; [[NSFileManager defaultManager] createFileAtPath:decryptSign contents:[@"und3fined" dataUsingEncoding:NSUTF8StringEncoding] attributes:nil]; + /* remove other files */ + NSString *mobileContainerManager = [tempPath stringByAppendingPathComponent:@".com.apple.mobile_container_manager.metadata.plist"]; + NSString *bundleMetadata = [tempPath stringByAppendingPathComponent:@"BundleMetadata.plist"]; + NSString *iTunesMetadata = [tempPath stringByAppendingPathComponent:@"iTunesMetadata.plist"]; + [[NSFileManager defaultManager] removeItemAtPath:mobileContainerManager error:nil]; + [[NSFileManager defaultManager] removeItemAtPath:bundleMetadata error:nil]; + [[NSFileManager defaultManager] removeItemAtPath:iTunesMetadata error:nil]; + + /* zip: archive */ NSString *archiveName = [NSString stringWithFormat:@"%@_%@_dump.ipa", targetId, [appProxy shortVersionString]]; @@ -207,6 +216,7 @@ - (NSString *)shortVersionString; [[[NSFileManager defaultManager] currentDirectoryPath] stringByAppendingPathComponent:archiveName]; BOOL didClean = [[NSFileManager defaultManager] removeItemAtPath:archivePath error:nil]; + fprintf("Creating %s file...\n", [archiveName UTF8String]); int zipStatus = my_system([[ @@ -217,7 +227,7 @@ - (NSString *)shortVersionString; fprintf(stderr, "Archive -> %s\n", [archiveName UTF8String]); fprintf(stderr, "Remove temp %s.\n", [tempURL UTF8String]); - [[NSFileManager defaultManager] removeItemAtPath:tempURL error:nil]; + [[NSFileManager defaultManager] removeItemAtPath:[tempURL path] error:nil]; if (zipStatus != 0) { fprintf(stderr, "cannot create archive: %s\n", [[error localizedDescription] UTF8String]); From 15b5a12d3c577b323460e355c88a6dedb0e2f252 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 19:22:56 +0700 Subject: [PATCH 069/155] lean --- foulwrapper.m | 1 - 1 file changed, 1 deletion(-) diff --git a/foulwrapper.m b/foulwrapper.m index 3af8e55..8c3266b 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -235,6 +235,5 @@ - (NSString *)shortVersionString; } fprintf(stderr, "Done.\n"); - return zipStatus; } From e4bd62f1e341122200907c63061746d86c6b9d89 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 19:26:38 +0700 Subject: [PATCH 070/155] update log --- foulwrapper.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/foulwrapper.m b/foulwrapper.m index 8c3266b..180a565 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -136,7 +136,7 @@ - (NSString *)shortVersionString; return 1; } - fprintf(stderr, "Target app -> %s\n", [targetId UTF8String]); + fprintf(stderr, "[start] Target app -> %s\n", [targetId UTF8String]); /* Make a copy of app bundle. */ NSURL *tempURL = [[NSFileManager defaultManager] URLForDirectory:NSItemReplacementDirectory @@ -216,7 +216,7 @@ - (NSString *)shortVersionString; [[[NSFileManager defaultManager] currentDirectoryPath] stringByAppendingPathComponent:archiveName]; BOOL didClean = [[NSFileManager defaultManager] removeItemAtPath:archivePath error:nil]; - fprintf("Creating %s file...\n", [archiveName UTF8String]); + fprintf(stderr, "[archive] Creating %s file...\n", [archiveName UTF8String]); int zipStatus = my_system([[ @@ -225,8 +225,8 @@ - (NSString *)shortVersionString; escape_arg(archivePath) ] UTF8String]); - fprintf(stderr, "Archive -> %s\n", [archiveName UTF8String]); - fprintf(stderr, "Remove temp %s.\n", [tempURL UTF8String]); + fprintf(stderr, "[archive] Archive -> %s\n", [archiveName UTF8String]); + fprintf(stderr, "[clean] Remove temp %s.\n", [tempURL path]); [[NSFileManager defaultManager] removeItemAtPath:[tempURL path] error:nil]; if (zipStatus != 0) { From 2d10ae40b1efa1070380a7273fe4a17ea924bb5b Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 19:30:48 +0700 Subject: [PATCH 071/155] fix path string --- foulwrapper.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/foulwrapper.m b/foulwrapper.m index 180a565..6921083 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -226,7 +226,8 @@ - (NSString *)shortVersionString; ] UTF8String]); fprintf(stderr, "[archive] Archive -> %s\n", [archiveName UTF8String]); - fprintf(stderr, "[clean] Remove temp %s.\n", [tempURL path]); + NSString *tempURLString = [[tempURL path] stringByAppendingPathComponent:@"."]; + fprintf(stderr, "[clean] Remove temp %s.\n", [tempURLString UTF8String]); [[NSFileManager defaultManager] removeItemAtPath:[tempURL path] error:nil]; if (zipStatus != 0) { From a64fcdda8fad07492d1b4936812579815e0e7385 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 20:07:09 +0700 Subject: [PATCH 072/155] update remove temp path --- foulwrapper.m | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/foulwrapper.m b/foulwrapper.m index 6921083..b138110 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -226,8 +226,7 @@ - (NSString *)shortVersionString; ] UTF8String]); fprintf(stderr, "[archive] Archive -> %s\n", [archiveName UTF8String]); - NSString *tempURLString = [[tempURL path] stringByAppendingPathComponent:@"."]; - fprintf(stderr, "[clean] Remove temp %s.\n", [tempURLString UTF8String]); + fprintf(stderr, "[clean] Remove temp %s.\n", [[tempURL path] UTF8String]); [[NSFileManager defaultManager] removeItemAtPath:[tempURL path] error:nil]; if (zipStatus != 0) { From 15a40c8b55becfbdc77a7313e42ac4d57fd4b2bd Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 20:11:49 +0700 Subject: [PATCH 073/155] lean --- foulwrapper.m | 1 - 1 file changed, 1 deletion(-) diff --git a/foulwrapper.m b/foulwrapper.m index b138110..53cd89d 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -207,7 +207,6 @@ - (NSString *)shortVersionString; [[NSFileManager defaultManager] removeItemAtPath:mobileContainerManager error:nil]; [[NSFileManager defaultManager] removeItemAtPath:bundleMetadata error:nil]; [[NSFileManager defaultManager] removeItemAtPath:iTunesMetadata error:nil]; - /* zip: archive */ NSString *archiveName = From 03b638012ceb899d65aa7bdc1762b2c1e5b9d90b Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 20:24:49 +0700 Subject: [PATCH 074/155] update log --- foulwrapper.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foulwrapper.m b/foulwrapper.m index 53cd89d..581e633 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -225,7 +225,7 @@ - (NSString *)shortVersionString; ] UTF8String]); fprintf(stderr, "[archive] Archive -> %s\n", [archiveName UTF8String]); - fprintf(stderr, "[clean] Remove temp %s.\n", [[tempURL path] UTF8String]); + fprintf(stderr, "[clean] Remove temp %s\n", [[tempURL path] UTF8String]); [[NSFileManager defaultManager] removeItemAtPath:[tempURL path] error:nil]; if (zipStatus != 0) { From ec6d6fbfe69ed7fbec3e7d40c643ba858564be55 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 25 Nov 2022 23:16:42 +0700 Subject: [PATCH 075/155] revert LIBKRW and LIBKERNRW --- .github/workflows/build-deb.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 2008463..753bd6c 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -12,8 +12,8 @@ jobs: runs-on: self-hosted strategy: matrix: - #provider: [TFP0, LIBKRW, LIBKERNRW] - provider: [TFP0] + provider: [TFP0, LIBKRW, LIBKERNRW] + # provider: [TFP0] steps: - uses: actions/checkout@v2 From aa121357c379c525b1e94af305b50aac382c8628 Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 26 Nov 2022 09:50:07 +0700 Subject: [PATCH 076/155] handle decrypt failed --- foulwrapper.m | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/foulwrapper.m b/foulwrapper.m index 581e633..7153116 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -161,6 +161,7 @@ - (NSString *)shortVersionString; /* Enumerate entire app bundle to find all Mach-Os. */ NSEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtPath:tempPath]; NSString *objectPath = nil; + BOOL didError = 0; while (objectPath = [enumerator nextObject]) { NSString *objectFullPath = [tempPath stringByAppendingPathComponent:objectPath]; @@ -185,6 +186,8 @@ - (NSString *)shortVersionString; my_system([[NSString stringWithFormat:@"fouldecrypt '%@' '%@'", escape_arg(objectRawPath), escape_arg( objectFullPath)] UTF8String]); if (decryptStatus != 0) { + didError = decryptStatus; + fprintf(stderr, "[dump] %s: Failed\n", [objectPath UTF8String]); break; } fprintf(stderr, "[dump] %s: Success\n", [objectPath UTF8String]); @@ -193,6 +196,10 @@ - (NSString *)shortVersionString; fclose(fp); } + if (didError) { + return didError; + } + LSApplicationProxy *appProxy = [LSApplicationProxy applicationProxyForIdentifier:targetId]; assert(appProxy); From 273e9480de638a8b390800115b2a07df36d48d18 Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 26 Nov 2022 10:12:12 +0700 Subject: [PATCH 077/155] add handle log --- foulwrapper.m | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/foulwrapper.m b/foulwrapper.m index 7153116..342c71e 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -162,6 +162,7 @@ - (NSString *)shortVersionString; NSEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtPath:tempPath]; NSString *objectPath = nil; BOOL didError = 0; + NSNumber decryptCount = [NSNumber numberWithInteger: 0]; while (objectPath = [enumerator nextObject]) { NSString *objectFullPath = [tempPath stringByAppendingPathComponent:objectPath]; @@ -190,6 +191,8 @@ - (NSString *)shortVersionString; fprintf(stderr, "[dump] %s: Failed\n", [objectPath UTF8String]); break; } + + decryptCount = [NSNumber numberWithInteger: [decryptCount integerValue] + 1]; fprintf(stderr, "[dump] %s: Success\n", [objectPath UTF8String]); } @@ -198,6 +201,9 @@ - (NSString *)shortVersionString; if (didError) { return didError; + } else if (decryptCount == 0) { + fprintf(stderr, "[dump] no Mach-O found\n"); + return 1; } LSApplicationProxy *appProxy = [LSApplicationProxy applicationProxyForIdentifier:targetId]; From dfec10ff5f7708c689f8166dc5ec18485892a805 Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 26 Nov 2022 10:15:17 +0700 Subject: [PATCH 078/155] update decryptCount tyoe --- foulwrapper.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foulwrapper.m b/foulwrapper.m index 342c71e..645d393 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -162,7 +162,7 @@ - (NSString *)shortVersionString; NSEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtPath:tempPath]; NSString *objectPath = nil; BOOL didError = 0; - NSNumber decryptCount = [NSNumber numberWithInteger: 0]; + NSNumber *decryptCount = [NSNumber numberWithInteger: 0]; while (objectPath = [enumerator nextObject]) { NSString *objectFullPath = [tempPath stringByAppendingPathComponent:objectPath]; From be0ee23a6b00e40bf984ab97079cbe00d0160b4e Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 26 Nov 2022 10:28:21 +0700 Subject: [PATCH 079/155] revert verbose --- foulwrapper.m | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/foulwrapper.m b/foulwrapper.m index 645d393..2dcc780 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -8,7 +8,7 @@ #import #import -// static int VERBOSE = 0; +static int VERBOSE = 0; #define MH_MAGIC_64 0xfeedfacf /* the 64-bit mach magic number */ #define MH_CIGAM_64 0xcffaedfe /* NXSwapInt(MH_MAGIC_64) */ @@ -201,7 +201,11 @@ - (NSString *)shortVersionString; if (didError) { return didError; - } else if (decryptCount == 0) { + } + + fprintf(stderr, "[dump] Total: %d\n", [decryptCount integerValue]); + + if ([decryptCount integerValue] == 0) { fprintf(stderr, "[dump] no Mach-O found\n"); return 1; } From 259a8b1d588f5dc1a2f990f2f2e2576ec774d077 Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 26 Nov 2022 10:32:07 +0700 Subject: [PATCH 080/155] save --- foulwrapper.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foulwrapper.m b/foulwrapper.m index 2dcc780..f33b754 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -203,7 +203,7 @@ - (NSString *)shortVersionString; return didError; } - fprintf(stderr, "[dump] Total: %d\n", [decryptCount integerValue]); + fprintf(stderr, "[dump] Total: %s\n", [NSString stringWithFormat:@"%i", decryptCount.intValue]); if ([decryptCount integerValue] == 0) { fprintf(stderr, "[dump] no Mach-O found\n"); From 691dbc0a362cb8743db581b9eab26f556736c36a Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 26 Nov 2022 10:36:32 +0700 Subject: [PATCH 081/155] update print --- foulwrapper.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foulwrapper.m b/foulwrapper.m index f33b754..f2f913b 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -203,7 +203,7 @@ - (NSString *)shortVersionString; return didError; } - fprintf(stderr, "[dump] Total: %s\n", [NSString stringWithFormat:@"%i", decryptCount.intValue]); + fprintf(stderr, "[dump] Total: %ld\n", [decryptCount integerValue]); if ([decryptCount integerValue] == 0) { fprintf(stderr, "[dump] no Mach-O found\n"); From 830b3af5f53fdfd7f01a974762aa13e9c74eb9d1 Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 26 Nov 2022 10:37:55 +0700 Subject: [PATCH 082/155] strinf value --- foulwrapper.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foulwrapper.m b/foulwrapper.m index f2f913b..ffb65ee 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -203,7 +203,7 @@ - (NSString *)shortVersionString; return didError; } - fprintf(stderr, "[dump] Total: %ld\n", [decryptCount integerValue]); + fprintf(stderr, "[dump] Total: %s\n", [decryptCount stringValue]); if ([decryptCount integerValue] == 0) { fprintf(stderr, "[dump] no Mach-O found\n"); From e143c27153523aa4ce9585fd4f9e46f0672e586d Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 26 Nov 2022 10:44:43 +0700 Subject: [PATCH 083/155] remove other log --- foulwrapper.m | 2 -- 1 file changed, 2 deletions(-) diff --git a/foulwrapper.m b/foulwrapper.m index ffb65ee..b0d50ac 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -202,8 +202,6 @@ - (NSString *)shortVersionString; if (didError) { return didError; } - - fprintf(stderr, "[dump] Total: %s\n", [decryptCount stringValue]); if ([decryptCount integerValue] == 0) { fprintf(stderr, "[dump] no Mach-O found\n"); From a17f4b16b91aa3a59d251aa33015b2ce42ddf5a1 Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 26 Nov 2022 11:09:30 +0700 Subject: [PATCH 084/155] update detect encrypt file --- foulwrapper.m | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/foulwrapper.m b/foulwrapper.m index b0d50ac..48fa7b5 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -10,12 +10,21 @@ static int VERBOSE = 0; +#define MH_MAGIC 0xfeedface +#define MH_CIGAM 0xcefaedfe #define MH_MAGIC_64 0xfeedfacf /* the 64-bit mach magic number */ #define MH_CIGAM_64 0xcffaedfe /* NXSwapInt(MH_MAGIC_64) */ +#define FAT_MAGIC 0xcafebabe +#define FAT_CIGAM 0xbebafeca #define FAT_MAGIC_64 0xcafebabf #define FAT_CIGAM_64 0xbfbafeca /* NXSwapLong(FAT_MAGIC_64) */ +#define LC_SEGMENT 0x1 +#define LC_SEGMENT_64 0x19 +#define LC_ENCRYPTION_INFO 0x21 +#define LC_ENCRYPTION_INFO_64 0x2C + extern char **environ; int @@ -180,7 +189,7 @@ - (NSString *)shortVersionString; continue; } - if (num == MH_MAGIC_64 || num == FAT_MAGIC_64) { + if (num == MH_MAGIC_64 || num == MH_CIGAM_64 || num == MH_MAGIC || num == MH_CIGAM) { NSString *objectRawPath = [targetPath stringByAppendingPathComponent:objectPath]; int decryptStatus = From d216da23f9a28f6e6f0c8f8f9e6a086dcbfe6251 Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 26 Nov 2022 11:52:22 +0700 Subject: [PATCH 085/155] dont check magic --- foulwrapper.m | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/foulwrapper.m b/foulwrapper.m index 48fa7b5..0ddb8c5 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -189,22 +189,22 @@ - (NSString *)shortVersionString; continue; } - if (num == MH_MAGIC_64 || num == MH_CIGAM_64 || num == MH_MAGIC || num == MH_CIGAM) { - NSString *objectRawPath = [targetPath stringByAppendingPathComponent:objectPath]; - - int decryptStatus = - my_system([[NSString stringWithFormat:@"fouldecrypt '%@' '%@'", escape_arg(objectRawPath), escape_arg( - objectFullPath)] UTF8String]); - if (decryptStatus != 0) { - didError = decryptStatus; - fprintf(stderr, "[dump] %s: Failed\n", [objectPath UTF8String]); - break; - } - - decryptCount = [NSNumber numberWithInteger: [decryptCount integerValue] + 1]; - fprintf(stderr, "[dump] %s: Success\n", [objectPath UTF8String]); + // if (num == MH_MAGIC_64 || num == MH_CIGAM_64 || num == MH_MAGIC || num == MH_CIGAM) { + NSString *objectRawPath = [targetPath stringByAppendingPathComponent:objectPath]; + + int decryptStatus = + my_system([[NSString stringWithFormat:@"fouldecrypt '%@' '%@'", escape_arg(objectRawPath), escape_arg( + objectFullPath)] UTF8String]); + if (decryptStatus != 0) { + didError = decryptStatus; + fprintf(stderr, "[dump] %s: Failed\n", [objectPath UTF8String]); + break; } + decryptCount = [NSNumber numberWithInteger: [decryptCount integerValue] + 1]; + fprintf(stderr, "[dump] %s: Success\n", [objectPath UTF8String]); + // } + fclose(fp); } From c1b42b3ab3ad25359877d376fd84607179519c80 Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 26 Nov 2022 11:53:28 +0700 Subject: [PATCH 086/155] allow get all apps --- foulwrapper.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foulwrapper.m b/foulwrapper.m index 0ddb8c5..67a9ac7 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -108,7 +108,7 @@ - (NSString *)shortVersionString; NSArray *sortedDisplayIdentifiers = nil; NSDictionary *appMaps = [[ALApplicationList sharedApplicationList] applicationsFilteredUsingPredicate:[NSPredicate predicateWithFormat:@"isSystemApplication = FALSE"] - onlyVisible:YES titleSortedIdentifiers:&sortedDisplayIdentifiers]; + onlyVisible:NO titleSortedIdentifiers:&sortedDisplayIdentifiers]; NSString *targetIdOrName = [NSString stringWithUTF8String:argv[1]]; NSString *targetId = nil; From 1a37a196cff924c7ed3e1b8f90c36d5071261d52 Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 26 Nov 2022 12:10:13 +0700 Subject: [PATCH 087/155] skip static file --- foulwrapper.m | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/foulwrapper.m b/foulwrapper.m index 67a9ac7..7289f19 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -189,6 +189,21 @@ - (NSString *)shortVersionString; continue; } + // check suffix + if ( + objectFullPath.hasSuffix(@".bundle") || + objectFullPath.hasSuffix(@".momd") || + objectFullPath.hasSuffix(@".strings") || + objectFullPath.hasSuffix(@".appex") || + objectFullPath.hasSuffix(@".app") || + objectFullPath.hasSuffix(@".lproj") || + objectFullPath.hasSuffix(@".storyboardc") || + ) { + fclose(fp); + continue; + } + + // if (num == MH_MAGIC_64 || num == MH_CIGAM_64 || num == MH_MAGIC || num == MH_CIGAM) { NSString *objectRawPath = [targetPath stringByAppendingPathComponent:objectPath]; From 68f333287bd974704a8d3076279d2b5ad6f5b9dd Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 26 Nov 2022 12:20:38 +0700 Subject: [PATCH 088/155] update ignore static --- foulwrapper.m | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/foulwrapper.m b/foulwrapper.m index 7289f19..bebb1ef 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -191,19 +191,33 @@ - (NSString *)shortVersionString; // check suffix if ( - objectFullPath.hasSuffix(@".bundle") || - objectFullPath.hasSuffix(@".momd") || - objectFullPath.hasSuffix(@".strings") || - objectFullPath.hasSuffix(@".appex") || - objectFullPath.hasSuffix(@".app") || - objectFullPath.hasSuffix(@".lproj") || - objectFullPath.hasSuffix(@".storyboardc") || + [objectPath containsString:@"/Data/"] || + [objectPath containsString:@"/Assets"] || + [objectPath UTF8String].hasSuffix(@".bundle") || + [objectPath UTF8String].hasSuffix(@".momd") || + [objectPath UTF8String].hasSuffix(@".strings") || + [objectPath UTF8String].hasSuffix(@".appex") || + [objectPath UTF8String].hasSuffix(@".app") || + [objectPath UTF8String].hasSuffix(@".lproj") || + [objectPath UTF8String].hasSuffix(@".storyboardc") || + [objectPath UTF8String].hasSuffix(@".framework") || + [objectPath UTF8String].hasSuffix(@".png") || + [objectPath UTF8String].hasSuffix(@".jpg") || + [objectPath UTF8String].hasSuffix(@".jpeg") || + [objectPath UTF8String].hasSuffix(@".png") || + [objectPath UTF8String].hasSuffix(@".json") || + [objectPath UTF8String].hasSuffix(@".assets") || + [objectPath UTF8String].hasSuffix(@".xml") || + [objectPath UTF8String].hasSuffix(@".resource") || + [objectPath UTF8String].hasSuffix(@".plist") || + [objectPath UTF8String].hasSuffix(@"PkgInfo") || + [objectPath UTF8String].hasSuffix(@".car") || + [objectPath UTF8String].hasSuffix(@".config") || ) { fclose(fp); continue; } - // if (num == MH_MAGIC_64 || num == MH_CIGAM_64 || num == MH_MAGIC || num == MH_CIGAM) { NSString *objectRawPath = [targetPath stringByAppendingPathComponent:objectPath]; From 22a73f189d6aefd68345ce3a8dd61d7fa3a15c17 Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 26 Nov 2022 12:23:39 +0700 Subject: [PATCH 089/155] update more static --- foulwrapper.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/foulwrapper.m b/foulwrapper.m index bebb1ef..f18c4fe 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -193,6 +193,8 @@ - (NSString *)shortVersionString; if ( [objectPath containsString:@"/Data/"] || [objectPath containsString:@"/Assets"] || + [objectPath containsString:@"/res/"] || + [objectPath containsString:@".bundle"] || [objectPath UTF8String].hasSuffix(@".bundle") || [objectPath UTF8String].hasSuffix(@".momd") || [objectPath UTF8String].hasSuffix(@".strings") || From 69704189e64b7d11923173a36e40e2c1258c42fd Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 26 Nov 2022 12:24:25 +0700 Subject: [PATCH 090/155] more static added --- foulwrapper.m | 1 + 1 file changed, 1 insertion(+) diff --git a/foulwrapper.m b/foulwrapper.m index f18c4fe..6281d33 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -192,6 +192,7 @@ - (NSString *)shortVersionString; // check suffix if ( [objectPath containsString:@"/Data/"] || + [objectPath containsString:@"/data/"] || [objectPath containsString:@"/Assets"] || [objectPath containsString:@"/res/"] || [objectPath containsString:@".bundle"] || From ab5adb4b0dc0af9a371eb25e66cfbfc7fbb31fbe Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 26 Nov 2022 12:27:32 +0700 Subject: [PATCH 091/155] update more --- .github/workflows/build-deb.yml | 4 ++-- foulwrapper.m | 42 ++++++++++++++++----------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 753bd6c..1e2a448 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -12,8 +12,8 @@ jobs: runs-on: self-hosted strategy: matrix: - provider: [TFP0, LIBKRW, LIBKERNRW] - # provider: [TFP0] + # provider: [TFP0, LIBKRW, LIBKERNRW] + provider: [TFP0] steps: - uses: actions/checkout@v2 diff --git a/foulwrapper.m b/foulwrapper.m index 6281d33..5dc2e1c 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -195,27 +195,27 @@ - (NSString *)shortVersionString; [objectPath containsString:@"/data/"] || [objectPath containsString:@"/Assets"] || [objectPath containsString:@"/res/"] || - [objectPath containsString:@".bundle"] || - [objectPath UTF8String].hasSuffix(@".bundle") || - [objectPath UTF8String].hasSuffix(@".momd") || - [objectPath UTF8String].hasSuffix(@".strings") || - [objectPath UTF8String].hasSuffix(@".appex") || - [objectPath UTF8String].hasSuffix(@".app") || - [objectPath UTF8String].hasSuffix(@".lproj") || - [objectPath UTF8String].hasSuffix(@".storyboardc") || - [objectPath UTF8String].hasSuffix(@".framework") || - [objectPath UTF8String].hasSuffix(@".png") || - [objectPath UTF8String].hasSuffix(@".jpg") || - [objectPath UTF8String].hasSuffix(@".jpeg") || - [objectPath UTF8String].hasSuffix(@".png") || - [objectPath UTF8String].hasSuffix(@".json") || - [objectPath UTF8String].hasSuffix(@".assets") || - [objectPath UTF8String].hasSuffix(@".xml") || - [objectPath UTF8String].hasSuffix(@".resource") || - [objectPath UTF8String].hasSuffix(@".plist") || - [objectPath UTF8String].hasSuffix(@"PkgInfo") || - [objectPath UTF8String].hasSuffix(@".car") || - [objectPath UTF8String].hasSuffix(@".config") || + [objectPath containsString:@".bundle"] + // [objectPath UTF8String].hasSuffix(@".bundle") || + // [objectPath UTF8String].hasSuffix(@".momd") || + // [objectPath UTF8String].hasSuffix(@".strings") || + // [objectPath UTF8String].hasSuffix(@".appex") || + // [objectPath UTF8String].hasSuffix(@".app") || + // [objectPath UTF8String].hasSuffix(@".lproj") || + // [objectPath UTF8String].hasSuffix(@".storyboardc") || + // [objectPath UTF8String].hasSuffix(@".framework") || + // [objectPath UTF8String].hasSuffix(@".png") || + // [objectPath UTF8String].hasSuffix(@".jpg") || + // [objectPath UTF8String].hasSuffix(@".jpeg") || + // [objectPath UTF8String].hasSuffix(@".png") || + // [objectPath UTF8String].hasSuffix(@".json") || + // [objectPath UTF8String].hasSuffix(@".assets") || + // [objectPath UTF8String].hasSuffix(@".xml") || + // [objectPath UTF8String].hasSuffix(@".resource") || + // [objectPath UTF8String].hasSuffix(@".plist") || + // [objectPath UTF8String].hasSuffix(@"PkgInfo") || + // [objectPath UTF8String].hasSuffix(@".car") || + // [objectPath UTF8String].hasSuffix(@".config") || ) { fclose(fp); continue; From f458bdd7956c3b02b6159541e143d64054227f2c Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 26 Nov 2022 12:42:58 +0700 Subject: [PATCH 092/155] update sufffix --- foulwrapper.m | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/foulwrapper.m b/foulwrapper.m index 5dc2e1c..ea465ad 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -195,7 +195,9 @@ - (NSString *)shortVersionString; [objectPath containsString:@"/data/"] || [objectPath containsString:@"/Assets"] || [objectPath containsString:@"/res/"] || - [objectPath containsString:@".bundle"] + [objectPath containsString:@".bundle"] || + [objectPath hasSuffix:@".lproj"] || + [objectPath hasSuffix:@"PkgInfo"] // [objectPath UTF8String].hasSuffix(@".bundle") || // [objectPath UTF8String].hasSuffix(@".momd") || // [objectPath UTF8String].hasSuffix(@".strings") || @@ -221,21 +223,21 @@ - (NSString *)shortVersionString; continue; } - // if (num == MH_MAGIC_64 || num == MH_CIGAM_64 || num == MH_MAGIC || num == MH_CIGAM) { - NSString *objectRawPath = [targetPath stringByAppendingPathComponent:objectPath]; + if (num == MH_MAGIC_64 || num == MH_CIGAM_64 || num == MH_MAGIC || num == MH_CIGAM) { + NSString *objectRawPath = [targetPath stringByAppendingPathComponent:objectPath]; - int decryptStatus = - my_system([[NSString stringWithFormat:@"fouldecrypt '%@' '%@'", escape_arg(objectRawPath), escape_arg( - objectFullPath)] UTF8String]); - if (decryptStatus != 0) { - didError = decryptStatus; - fprintf(stderr, "[dump] %s: Failed\n", [objectPath UTF8String]); - break; - } + int decryptStatus = + my_system([[NSString stringWithFormat:@"fouldecrypt '%@' '%@'", escape_arg(objectRawPath), escape_arg( + objectFullPath)] UTF8String]); + if (decryptStatus != 0) { + didError = decryptStatus; + fprintf(stderr, "[dump] %s: Failed\n", [objectPath UTF8String]); + break; + } - decryptCount = [NSNumber numberWithInteger: [decryptCount integerValue] + 1]; - fprintf(stderr, "[dump] %s: Success\n", [objectPath UTF8String]); - // } + decryptCount = [NSNumber numberWithInteger: [decryptCount integerValue] + 1]; + fprintf(stderr, "[dump] %s: Success\n", [objectPath UTF8String]); + } fclose(fp); } From 99b2075b2957303de160b3f49c56a3b1d9e045da Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 26 Nov 2022 13:12:51 +0700 Subject: [PATCH 093/155] update condition --- foulwrapper.m | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/foulwrapper.m b/foulwrapper.m index ea465ad..046263e 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -223,7 +223,16 @@ - (NSString *)shortVersionString; continue; } - if (num == MH_MAGIC_64 || num == MH_CIGAM_64 || num == MH_MAGIC || num == MH_CIGAM) { + if ( + num == MH_MAGIC_64 || + num == MH_MAGIC || + num == FAT_MAGIC_64 || + num == FAT_MAGIC || + num == MH_CIGAM || + num == MH_CIGAM_64 || + num == FAT_CIGAM || + num == FAT_CIGAM_64 + ) { NSString *objectRawPath = [targetPath stringByAppendingPathComponent:objectPath]; int decryptStatus = From f24063915a4e242bd20bc3a02b91bcfbfa254395 Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 26 Nov 2022 16:09:09 +0700 Subject: [PATCH 094/155] revert build --- .github/workflows/build-deb.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 1e2a448..753bd6c 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -12,8 +12,8 @@ jobs: runs-on: self-hosted strategy: matrix: - # provider: [TFP0, LIBKRW, LIBKERNRW] - provider: [TFP0] + provider: [TFP0, LIBKRW, LIBKERNRW] + # provider: [TFP0] steps: - uses: actions/checkout@v2 From 742c7e1c91aaca3281658b9278a285a59e53288b Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 1 Dec 2022 15:12:53 +0700 Subject: [PATCH 095/155] support direct container dump --- foulwrapper.m | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/foulwrapper.m b/foulwrapper.m index 046263e..1984db5 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -121,6 +121,10 @@ - (NSString *)shortVersionString; } } + if (!targetId) { + targetId = [NSString stringWithUTF8String:argv[2]] + } + if (!targetId) { fprintf(stderr, "application \"%s\" not found\n", argv[1]); From b096d7b98f670d073f5f6a357b962760f762395a Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 1 Dec 2022 15:59:47 +0700 Subject: [PATCH 096/155] disable applist --- Makefile | 2 +- control.template | 2 +- foulwrapper.m | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index bdae012..17087ac 100644 --- a/Makefile +++ b/Makefile @@ -35,6 +35,6 @@ foulwrapper_CODESIGN_FLAGS = -Sentitlements.plist foulwrapper_INSTALL_PATH = /usr/local/bin foulwrapper_FRAMEWORKS = Foundation MobileCoreServices foulwrapper_PRIVATE_FRAMEWORKS = MobileContainerManager -foulwrapper_LIBRARIES = applist +# foulwrapper_LIBRARIES = applist include $(THEOS_MAKE_PATH)/tool.mk diff --git a/control.template b/control.template index dee2aa9..8cccb06 100644 --- a/control.template +++ b/control.template @@ -2,7 +2,7 @@ Package: moe.misty.fouldecrypt Name: fouldecrypt Version: 0.0.5 Architecture: iphoneos-arm -Depends: applist,zip,{{.depends}} +Depends: zip,{{.depends}} Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 14 Maintainer: und3fined Author: misty diff --git a/foulwrapper.m b/foulwrapper.m index 1984db5..30ef0bd 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -2,7 +2,7 @@ #import #import -#import +// #import #import #import From 76c7bb27c037fb2b9956690e77d3783a58ff67f9 Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 1 Dec 2022 16:00:44 +0700 Subject: [PATCH 097/155] update --- .github/workflows/build-deb.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 753bd6c..1e2a448 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -12,8 +12,8 @@ jobs: runs-on: self-hosted strategy: matrix: - provider: [TFP0, LIBKRW, LIBKERNRW] - # provider: [TFP0] + # provider: [TFP0, LIBKRW, LIBKERNRW] + provider: [TFP0] steps: - uses: actions/checkout@v2 From 56e7e234198803e558840015ea69d8c35bccb41c Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 1 Dec 2022 16:32:30 +0700 Subject: [PATCH 098/155] update --- foulwrapper.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foulwrapper.m b/foulwrapper.m index 30ef0bd..7e1224d 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -122,7 +122,7 @@ - (NSString *)shortVersionString; } if (!targetId) { - targetId = [NSString stringWithUTF8String:argv[2]] + targetId = [NSString stringWithUTF8String:argv[2]]; } if (!targetId) From a8e5c4745f593fce6a679c02fa8c3021e241f0f1 Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 1 Dec 2022 16:37:21 +0700 Subject: [PATCH 099/155] fix build --- Makefile | 2 +- control.template | 2 +- foulwrapper.m | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 17087ac..bdae012 100644 --- a/Makefile +++ b/Makefile @@ -35,6 +35,6 @@ foulwrapper_CODESIGN_FLAGS = -Sentitlements.plist foulwrapper_INSTALL_PATH = /usr/local/bin foulwrapper_FRAMEWORKS = Foundation MobileCoreServices foulwrapper_PRIVATE_FRAMEWORKS = MobileContainerManager -# foulwrapper_LIBRARIES = applist +foulwrapper_LIBRARIES = applist include $(THEOS_MAKE_PATH)/tool.mk diff --git a/control.template b/control.template index 8cccb06..dee2aa9 100644 --- a/control.template +++ b/control.template @@ -2,7 +2,7 @@ Package: moe.misty.fouldecrypt Name: fouldecrypt Version: 0.0.5 Architecture: iphoneos-arm -Depends: zip,{{.depends}} +Depends: applist,zip,{{.depends}} Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 14 Maintainer: und3fined Author: misty diff --git a/foulwrapper.m b/foulwrapper.m index 7e1224d..2b921d2 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -2,7 +2,7 @@ #import #import -// #import +#import #import #import From 5283fe5efbbac7f4076d94234f64da311405ffb2 Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 3 Dec 2022 01:17:53 +0700 Subject: [PATCH 100/155] remove AppList --- .github/workflows/build-deb.yml | 4 ++-- control.template | 2 +- foulwrapper.m | 28 ++++++++++++++-------------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 1e2a448..753bd6c 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -12,8 +12,8 @@ jobs: runs-on: self-hosted strategy: matrix: - # provider: [TFP0, LIBKRW, LIBKERNRW] - provider: [TFP0] + provider: [TFP0, LIBKRW, LIBKERNRW] + # provider: [TFP0] steps: - uses: actions/checkout@v2 diff --git a/control.template b/control.template index dee2aa9..8cccb06 100644 --- a/control.template +++ b/control.template @@ -2,7 +2,7 @@ Package: moe.misty.fouldecrypt Name: fouldecrypt Version: 0.0.5 Architecture: iphoneos-arm -Depends: applist,zip,{{.depends}} +Depends: zip,{{.depends}} Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 14 Maintainer: und3fined Author: misty diff --git a/foulwrapper.m b/foulwrapper.m index 2b921d2..c382b09 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -2,7 +2,7 @@ #import #import -#import +// #import #import #import @@ -105,21 +105,21 @@ - (NSString *)shortVersionString; /* AppList: convert app name to app identifier */ /* or, you can use APIs in `LSApplicationWorkspace`. */ - NSArray *sortedDisplayIdentifiers = nil; - NSDictionary *appMaps = - [[ALApplicationList sharedApplicationList] applicationsFilteredUsingPredicate:[NSPredicate predicateWithFormat:@"isSystemApplication = FALSE"] - onlyVisible:NO titleSortedIdentifiers:&sortedDisplayIdentifiers]; + // NSArray *sortedDisplayIdentifiers = nil; + // NSDictionary *appMaps = + // [[ALApplicationList sharedApplicationList] applicationsFilteredUsingPredicate:[NSPredicate predicateWithFormat:@"isSystemApplication = FALSE"] + // onlyVisible:NO titleSortedIdentifiers:&sortedDisplayIdentifiers]; - NSString *targetIdOrName = [NSString stringWithUTF8String:argv[1]]; + // NSString *targetIdOrName = [NSString stringWithUTF8String:argv[1]]; NSString *targetId = nil; - for (NSString *appId in appMaps) - { - if ([appId isEqualToString:targetIdOrName] || [appMaps[appId] isEqualToString:targetIdOrName]) - { - targetId = appId; - break; - } - } + // for (NSString *appId in appMaps) + // { + // if ([appId isEqualToString:targetIdOrName] || [appMaps[appId] isEqualToString:targetIdOrName]) + // { + // targetId = appId; + // break; + // } + // } if (!targetId) { targetId = [NSString stringWithUTF8String:argv[2]]; From 24eab4e13a96b0b64f8f168bb884f36cc953c2d4 Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 3 Dec 2022 01:18:51 +0700 Subject: [PATCH 101/155] remove AppList again --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index bdae012..17087ac 100644 --- a/Makefile +++ b/Makefile @@ -35,6 +35,6 @@ foulwrapper_CODESIGN_FLAGS = -Sentitlements.plist foulwrapper_INSTALL_PATH = /usr/local/bin foulwrapper_FRAMEWORKS = Foundation MobileCoreServices foulwrapper_PRIVATE_FRAMEWORKS = MobileContainerManager -foulwrapper_LIBRARIES = applist +# foulwrapper_LIBRARIES = applist include $(THEOS_MAKE_PATH)/tool.mk From 82562c9994a6ce4afa189f2a8872e2acca168914 Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 3 Dec 2022 11:15:03 +0700 Subject: [PATCH 102/155] revert AppList --- .github/workflows/build-deb.yml | 4 +-- Makefile | 2 +- control.template | 2 +- foulwrapper.m | 53 ++++++++++++--------------------- 4 files changed, 23 insertions(+), 38 deletions(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 753bd6c..1e2a448 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -12,8 +12,8 @@ jobs: runs-on: self-hosted strategy: matrix: - provider: [TFP0, LIBKRW, LIBKERNRW] - # provider: [TFP0] + # provider: [TFP0, LIBKRW, LIBKERNRW] + provider: [TFP0] steps: - uses: actions/checkout@v2 diff --git a/Makefile b/Makefile index 17087ac..bdae012 100644 --- a/Makefile +++ b/Makefile @@ -35,6 +35,6 @@ foulwrapper_CODESIGN_FLAGS = -Sentitlements.plist foulwrapper_INSTALL_PATH = /usr/local/bin foulwrapper_FRAMEWORKS = Foundation MobileCoreServices foulwrapper_PRIVATE_FRAMEWORKS = MobileContainerManager -# foulwrapper_LIBRARIES = applist +foulwrapper_LIBRARIES = applist include $(THEOS_MAKE_PATH)/tool.mk diff --git a/control.template b/control.template index 8cccb06..dee2aa9 100644 --- a/control.template +++ b/control.template @@ -2,7 +2,7 @@ Package: moe.misty.fouldecrypt Name: fouldecrypt Version: 0.0.5 Architecture: iphoneos-arm -Depends: zip,{{.depends}} +Depends: applist,zip,{{.depends}} Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 14 Maintainer: und3fined Author: misty diff --git a/foulwrapper.m b/foulwrapper.m index c382b09..a4eaa02 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -2,7 +2,7 @@ #import #import -// #import +#import #import #import @@ -105,21 +105,21 @@ - (NSString *)shortVersionString; /* AppList: convert app name to app identifier */ /* or, you can use APIs in `LSApplicationWorkspace`. */ - // NSArray *sortedDisplayIdentifiers = nil; - // NSDictionary *appMaps = - // [[ALApplicationList sharedApplicationList] applicationsFilteredUsingPredicate:[NSPredicate predicateWithFormat:@"isSystemApplication = FALSE"] - // onlyVisible:NO titleSortedIdentifiers:&sortedDisplayIdentifiers]; + NSArray *sortedDisplayIdentifiers = nil; + NSDictionary *appMaps = + [[ALApplicationList sharedApplicationList] applicationsFilteredUsingPredicate:[NSPredicate predicateWithFormat:@"isSystemApplication = FALSE"] + onlyVisible:NO titleSortedIdentifiers:&sortedDisplayIdentifiers]; - // NSString *targetIdOrName = [NSString stringWithUTF8String:argv[1]]; + NSString *targetIdOrName = [NSString stringWithUTF8String:argv[1]]; NSString *targetId = nil; - // for (NSString *appId in appMaps) - // { - // if ([appId isEqualToString:targetIdOrName] || [appMaps[appId] isEqualToString:targetIdOrName]) - // { - // targetId = appId; - // break; - // } - // } + for (NSString *appId in appMaps) + { + if ([appId isEqualToString:targetIdOrName] || [appMaps[appId] isEqualToString:targetIdOrName]) + { + targetId = appId; + break; + } + } if (!targetId) { targetId = [NSString stringWithUTF8String:argv[2]]; @@ -132,6 +132,11 @@ - (NSString *)shortVersionString; } + fprintf(stderr, "target: %s\n", [targetId UTF8String]); + + return 1; + + /* MobileContainerManager: locate app bundle container path */ /* `LSApplicationProxy` cannot provide correct values of container URLs since iOS 12. */ NSError *error = nil; @@ -202,26 +207,6 @@ - (NSString *)shortVersionString; [objectPath containsString:@".bundle"] || [objectPath hasSuffix:@".lproj"] || [objectPath hasSuffix:@"PkgInfo"] - // [objectPath UTF8String].hasSuffix(@".bundle") || - // [objectPath UTF8String].hasSuffix(@".momd") || - // [objectPath UTF8String].hasSuffix(@".strings") || - // [objectPath UTF8String].hasSuffix(@".appex") || - // [objectPath UTF8String].hasSuffix(@".app") || - // [objectPath UTF8String].hasSuffix(@".lproj") || - // [objectPath UTF8String].hasSuffix(@".storyboardc") || - // [objectPath UTF8String].hasSuffix(@".framework") || - // [objectPath UTF8String].hasSuffix(@".png") || - // [objectPath UTF8String].hasSuffix(@".jpg") || - // [objectPath UTF8String].hasSuffix(@".jpeg") || - // [objectPath UTF8String].hasSuffix(@".png") || - // [objectPath UTF8String].hasSuffix(@".json") || - // [objectPath UTF8String].hasSuffix(@".assets") || - // [objectPath UTF8String].hasSuffix(@".xml") || - // [objectPath UTF8String].hasSuffix(@".resource") || - // [objectPath UTF8String].hasSuffix(@".plist") || - // [objectPath UTF8String].hasSuffix(@"PkgInfo") || - // [objectPath UTF8String].hasSuffix(@".car") || - // [objectPath UTF8String].hasSuffix(@".config") || ) { fclose(fp); continue; From 045a1d79b1cb596c3660a1c76367b5effd4491a1 Mon Sep 17 00:00:00 2001 From: und3fined Date: Tue, 13 Dec 2022 08:18:25 +0700 Subject: [PATCH 103/155] remove check suffix --- foulwrapper.m | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/foulwrapper.m b/foulwrapper.m index a4eaa02..878b6e4 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -198,19 +198,19 @@ - (NSString *)shortVersionString; continue; } - // check suffix - if ( - [objectPath containsString:@"/Data/"] || - [objectPath containsString:@"/data/"] || - [objectPath containsString:@"/Assets"] || - [objectPath containsString:@"/res/"] || - [objectPath containsString:@".bundle"] || - [objectPath hasSuffix:@".lproj"] || - [objectPath hasSuffix:@"PkgInfo"] - ) { - fclose(fp); - continue; - } + // // check suffix + // if ( + // [objectPath containsString:@"/Data/"] || + // [objectPath containsString:@"/data/"] || + // [objectPath containsString:@"/Assets"] || + // [objectPath containsString:@"/res/"] || + // [objectPath containsString:@".bundle"] || + // [objectPath hasSuffix:@".lproj"] || + // [objectPath hasSuffix:@"PkgInfo"] + // ) { + // fclose(fp); + // continue; + // } if ( num == MH_MAGIC_64 || From ac6167920e571ef26b81eeda56fa084661267a8c Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 25 Mar 2023 18:50:32 +0700 Subject: [PATCH 104/155] add remove UISupportedDevices --- foulwrapper.m | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/foulwrapper.m b/foulwrapper.m index 878b6e4..8ed3d4b 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -256,6 +256,14 @@ - (NSString *)shortVersionString; NSString *decryptSign = [tempPath stringByAppendingPathComponent:@"decrypt.day"]; [[NSFileManager defaultManager] createFileAtPath:decryptSign contents:[@"und3fined" dataUsingEncoding:NSUTF8StringEncoding] attributes:nil]; + NSString *infoPlistPath = [tempPath stringByAppendingPathComponent:@"Info.plist"]; + NSMutableDictionary *infoPlist = [NSMutableDictionary dictionaryWithContentsOfFile:infoPlistPath]; + assert(infoPlist); + + /* Remove UISupportedDevices in Info.plist file */ + [infoPlist removeObjectForKey:@"UISupportedDevices"]; + [infoPlist writeToFile:infoPlistPath atomically:YES]; + /* remove other files */ NSString *mobileContainerManager = [tempPath stringByAppendingPathComponent:@".com.apple.mobile_container_manager.metadata.plist"]; NSString *bundleMetadata = [tempPath stringByAppendingPathComponent:@"BundleMetadata.plist"]; From 6351e79d6f8e4d09923930812dabc62acdda9552 Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 25 Mar 2023 21:25:58 +0700 Subject: [PATCH 105/155] patch UISupportedDevices --- foulwrapper.m | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/foulwrapper.m b/foulwrapper.m index 8ed3d4b..eca1a3d 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -212,6 +212,20 @@ - (NSString *)shortVersionString; // continue; // } + if ( + [objectPath containsString:@".app/Info.plist"] + ) { + fclose(fp); + + NSMutableDictionary *infoPlist = [NSMutableDictionary dictionaryWithContentsOfFile:objectPath]; + [infoPlist removeObjectForKey:@"UISupportedDevices"]; + [infoPlist writeToFile:infoPlistPath atomically:YES]; + + fprintf(stderr, "[change] Remove UISupportedDevices: %s Success\n", [objectPath UTF8String]); + + continue; + } + if ( num == MH_MAGIC_64 || num == MH_MAGIC || From 0b8d50a530e82342aa55a5ad84d8386aa471fb1f Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 25 Mar 2023 21:29:30 +0700 Subject: [PATCH 106/155] fix infoPlistPath --- foulwrapper.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foulwrapper.m b/foulwrapper.m index eca1a3d..d58d8fa 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -219,7 +219,7 @@ - (NSString *)shortVersionString; NSMutableDictionary *infoPlist = [NSMutableDictionary dictionaryWithContentsOfFile:objectPath]; [infoPlist removeObjectForKey:@"UISupportedDevices"]; - [infoPlist writeToFile:infoPlistPath atomically:YES]; + [infoPlist writeToFile:objectPath atomically:YES]; fprintf(stderr, "[change] Remove UISupportedDevices: %s Success\n", [objectPath UTF8String]); From 25e84670774c24953e96f84bdf91ceb6f3ab851c Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 25 Mar 2023 21:34:23 +0700 Subject: [PATCH 107/155] add log --- foulwrapper.m | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/foulwrapper.m b/foulwrapper.m index d58d8fa..d252c48 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -217,11 +217,13 @@ - (NSString *)shortVersionString; ) { fclose(fp); + fprintf(stderr, "[change] Start remove UISupportedDevices: %s \n", [objectPath UTF8String]); + NSMutableDictionary *infoPlist = [NSMutableDictionary dictionaryWithContentsOfFile:objectPath]; [infoPlist removeObjectForKey:@"UISupportedDevices"]; [infoPlist writeToFile:objectPath atomically:YES]; - fprintf(stderr, "[change] Remove UISupportedDevices: %s Success\n", [objectPath UTF8String]); + fprintf(stderr, "[change] Done UISupportedDevices\n", [objectPath UTF8String]); continue; } @@ -270,13 +272,13 @@ - (NSString *)shortVersionString; NSString *decryptSign = [tempPath stringByAppendingPathComponent:@"decrypt.day"]; [[NSFileManager defaultManager] createFileAtPath:decryptSign contents:[@"und3fined" dataUsingEncoding:NSUTF8StringEncoding] attributes:nil]; - NSString *infoPlistPath = [tempPath stringByAppendingPathComponent:@"Info.plist"]; - NSMutableDictionary *infoPlist = [NSMutableDictionary dictionaryWithContentsOfFile:infoPlistPath]; - assert(infoPlist); + // NSString *infoPlistPath = [tempPath stringByAppendingPathComponent:@"Info.plist"]; + // NSMutableDictionary *infoPlist = [NSMutableDictionary dictionaryWithContentsOfFile:infoPlistPath]; + // assert(infoPlist); - /* Remove UISupportedDevices in Info.plist file */ - [infoPlist removeObjectForKey:@"UISupportedDevices"]; - [infoPlist writeToFile:infoPlistPath atomically:YES]; + // /* Remove UISupportedDevices in Info.plist file */ + // [infoPlist removeObjectForKey:@"UISupportedDevices"]; + // [infoPlist writeToFile:infoPlistPath atomically:YES]; /* remove other files */ NSString *mobileContainerManager = [tempPath stringByAppendingPathComponent:@".com.apple.mobile_container_manager.metadata.plist"]; From 7e0c21d7c29d20d7b9a34d755022e67b3c3def89 Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 25 Mar 2023 21:39:30 +0700 Subject: [PATCH 108/155] fix syntax --- foulwrapper.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/foulwrapper.m b/foulwrapper.m index d252c48..fadf2f8 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -217,13 +217,13 @@ - (NSString *)shortVersionString; ) { fclose(fp); - fprintf(stderr, "[change] Start remove UISupportedDevices: %s \n", [objectPath UTF8String]); + fprintf(stderr, "[change] Start remove UISupportedDevices -> %s \n", [objectPath UTF8String]); - NSMutableDictionary *infoPlist = [NSMutableDictionary dictionaryWithContentsOfFile:objectPath]; + NSMutableDictionary *infoPlist = [NSMutableDictionary dictionaryWithContentsOfFile:objectFullPath]; [infoPlist removeObjectForKey:@"UISupportedDevices"]; [infoPlist writeToFile:objectPath atomically:YES]; - fprintf(stderr, "[change] Done UISupportedDevices\n", [objectPath UTF8String]); + fprintf(stderr, "[change] Done UISupportedDevices\n"); continue; } From 76d9e2eb44e853dfed33c50b98f47fa32bfb5d30 Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 25 Mar 2023 21:47:22 +0700 Subject: [PATCH 109/155] remove return --- foulwrapper.m | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/foulwrapper.m b/foulwrapper.m index fadf2f8..3d3c7e1 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -134,9 +134,6 @@ - (NSString *)shortVersionString; fprintf(stderr, "target: %s\n", [targetId UTF8String]); - return 1; - - /* MobileContainerManager: locate app bundle container path */ /* `LSApplicationProxy` cannot provide correct values of container URLs since iOS 12. */ NSError *error = nil; @@ -198,20 +195,6 @@ - (NSString *)shortVersionString; continue; } - // // check suffix - // if ( - // [objectPath containsString:@"/Data/"] || - // [objectPath containsString:@"/data/"] || - // [objectPath containsString:@"/Assets"] || - // [objectPath containsString:@"/res/"] || - // [objectPath containsString:@".bundle"] || - // [objectPath hasSuffix:@".lproj"] || - // [objectPath hasSuffix:@"PkgInfo"] - // ) { - // fclose(fp); - // continue; - // } - if ( [objectPath containsString:@".app/Info.plist"] ) { From e9a39671521b778713f516cb5da499c5ed1c5306 Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 25 Mar 2023 21:49:26 +0700 Subject: [PATCH 110/155] remove other log --- foulwrapper.m | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/foulwrapper.m b/foulwrapper.m index 3d3c7e1..17745e6 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -127,13 +127,10 @@ - (NSString *)shortVersionString; if (!targetId) { - fprintf(stderr, "application \"%s\" not found\n", argv[1]); + fprintf(stderr, "Application \"%s\" not found\n", argv[1]); return 1; } - - fprintf(stderr, "target: %s\n", [targetId UTF8String]); - /* MobileContainerManager: locate app bundle container path */ /* `LSApplicationProxy` cannot provide correct values of container URLs since iOS 12. */ NSError *error = nil; @@ -145,7 +142,7 @@ - (NSString *)shortVersionString; if (!targetPath) { fprintf(stderr, - "application \"%s\" does not have a bundle container: %s\n", + "Application \"%s\" does not have a bundle container: %s\n", argv[1], [[error localizedDescription] UTF8String]); return 1; From c82d7705cc5f57cb0faddd9a562615a6644da5cc Mon Sep 17 00:00:00 2001 From: und3fined Date: Sat, 25 Mar 2023 21:57:20 +0700 Subject: [PATCH 111/155] update other log --- foulwrapper.m | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/foulwrapper.m b/foulwrapper.m index 17745e6..ba6f32f 100644 --- a/foulwrapper.m +++ b/foulwrapper.m @@ -196,15 +196,10 @@ - (NSString *)shortVersionString; [objectPath containsString:@".app/Info.plist"] ) { fclose(fp); - - fprintf(stderr, "[change] Start remove UISupportedDevices -> %s \n", [objectPath UTF8String]); - + fprintf(stderr, "[change] %s: Remove UISupportedDevices\n", [objectPath UTF8String]); NSMutableDictionary *infoPlist = [NSMutableDictionary dictionaryWithContentsOfFile:objectFullPath]; [infoPlist removeObjectForKey:@"UISupportedDevices"]; [infoPlist writeToFile:objectPath atomically:YES]; - - fprintf(stderr, "[change] Done UISupportedDevices\n"); - continue; } From e4daabac0fcfe87a0b14c2968de1be35c31c95e2 Mon Sep 17 00:00:00 2001 From: und3fined Date: Mon, 27 Mar 2023 18:14:39 +0700 Subject: [PATCH 112/155] add LIBKERNRW --- .github/workflows/build-deb.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 1e2a448..617a856 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: # provider: [TFP0, LIBKRW, LIBKERNRW] - provider: [TFP0] + provider: [TFP0, LIBKERNRW] steps: - uses: actions/checkout@v2 From 44d61251af32aa71ff6b2095be09ebf5c656dfb9 Mon Sep 17 00:00:00 2001 From: und3fined Date: Mon, 24 Apr 2023 15:47:20 +0700 Subject: [PATCH 113/155] Update build for rootless --- .github/workflows/build-deb.yml | 4 ++-- control.template | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 617a856..1e7acf2 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: # provider: [TFP0, LIBKRW, LIBKERNRW] - provider: [TFP0, LIBKERNRW] + provider: [LIBKRW] steps: - uses: actions/checkout@v2 @@ -33,7 +33,7 @@ jobs: USE_TFP0=1 make package FINALPACKAGE=1 elif [[ ${{matrix.provider}} == LIBKRW ]]; then sed -i 's/{{.depends}}/libkrw/g' control - USE_LIBKRW=1 make package FINALPACKAGE=1 + USE_LIBKRW=1 make package FINALPACKAGE=1 THEOS_PACKAGE_SCHEME=rootless elif [[ ${{matrix.provider}} == LIBKERNRW ]]; then sed -i 's/{{.depends}}/libkernrw0/g' control USE_LIBKERNRW=1 make package FINALPACKAGE=1 diff --git a/control.template b/control.template index dee2aa9..1f570f8 100644 --- a/control.template +++ b/control.template @@ -1,9 +1,9 @@ -Package: moe.misty.fouldecrypt +Package: dev.und3fy.fouldecrypt Name: fouldecrypt -Version: 0.0.5 -Architecture: iphoneos-arm +Version: 0.0.1 +Architecture: iphoneos-arm64 Depends: applist,zip,{{.depends}} -Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 14 +Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 16 Maintainer: und3fined Author: misty Section: System From b51e6a8c6eb05fe470a62300afb9fe30839856e4 Mon Sep 17 00:00:00 2001 From: und3fined Date: Mon, 24 Apr 2023 15:54:23 +0700 Subject: [PATCH 114/155] remove applist --- control.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/control.template b/control.template index 1f570f8..82467de 100644 --- a/control.template +++ b/control.template @@ -2,7 +2,7 @@ Package: dev.und3fy.fouldecrypt Name: fouldecrypt Version: 0.0.1 Architecture: iphoneos-arm64 -Depends: applist,zip,{{.depends}} +Depends: zip,{{.depends}} Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 16 Maintainer: und3fined Author: misty From 0785190ddc1b1eb76811fb975ed2c4e875177612 Mon Sep 17 00:00:00 2001 From: und3fined Date: Mon, 24 Apr 2023 16:08:06 +0700 Subject: [PATCH 115/155] save --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index bdae012..36f88b9 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ include $(THEOS)/makefiles/common.mk TOOL_NAME = fouldecrypt flexdecrypt2 foulwrapper -export USE_TFP0 = 1 +# export USE_TFP0 = 1 # export USE_LIBKRW = 1 # export USE_LIBKERNRW = 1 From 3d7b6f3f06295c5fce9ad992f9a62a72a804666c Mon Sep 17 00:00:00 2001 From: und3fined Date: Mon, 24 Apr 2023 16:11:01 +0700 Subject: [PATCH 116/155] update submdoule --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index e7745a3..f3f0070 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "kerninfra"] path = kerninfra - url = https://github.com/NyaMisty/KernInfra + url = git@github.com:und3fined/KernInfra.git From b21ae826455313c075d4491fa9a3c843622dd1fd Mon Sep 17 00:00:00 2001 From: und3fined Date: Mon, 24 Apr 2023 16:17:48 +0700 Subject: [PATCH 117/155] Update kern support rootless --- kerninfra | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kerninfra b/kerninfra index 67e1e2d..e1c64f8 160000 --- a/kerninfra +++ b/kerninfra @@ -1 +1 @@ -Subproject commit 67e1e2dd7deda9146aca7a3fb437f6885c6bbd93 +Subproject commit e1c64f8ef639e6ee5484ea6b3ef617b395824de0 From 57aceac2240280f808b3841400508fbf756becb8 Mon Sep 17 00:00:00 2001 From: und3fined Date: Mon, 24 Apr 2023 16:22:16 +0700 Subject: [PATCH 118/155] add LIBKERNRW build --- .github/workflows/build-deb.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 1e7acf2..d0833b9 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: # provider: [TFP0, LIBKRW, LIBKERNRW] - provider: [LIBKRW] + provider: [LIBKRW, LIBKERNRW] steps: - uses: actions/checkout@v2 From 1ed4ecae9287b0965f06e646b04ac703d7c36a10 Mon Sep 17 00:00:00 2001 From: und3fined Date: Mon, 24 Apr 2023 17:07:41 +0700 Subject: [PATCH 119/155] enable USE_LIBKRW in Makefile --- Makefile | 4 ++-- kerninfra | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 36f88b9..d052529 100644 --- a/Makefile +++ b/Makefile @@ -7,8 +7,8 @@ include $(THEOS)/makefiles/common.mk TOOL_NAME = fouldecrypt flexdecrypt2 foulwrapper # export USE_TFP0 = 1 -# export USE_LIBKRW = 1 -# export USE_LIBKERNRW = 1 +export USE_LIBKRW = 1 +export USE_LIBKERNRW = 1 fouldecrypt_FILES = main.cpp foulmain.cpp fouldecrypt_CFLAGS = -fobjc-arc -Wno-unused-variable # -Ipriv_include diff --git a/kerninfra b/kerninfra index e1c64f8..880d5d3 160000 --- a/kerninfra +++ b/kerninfra @@ -1 +1 @@ -Subproject commit e1c64f8ef639e6ee5484ea6b3ef617b395824de0 +Subproject commit 880d5d36eb22f9654c84794405da2292f65ecfaf From 5fa49efc2f54ddd7c216c6747e4f3c107eee2f1f Mon Sep 17 00:00:00 2001 From: und3fined Date: Mon, 24 Apr 2023 17:24:11 +0700 Subject: [PATCH 120/155] use USE_LIBKRW and USE_LIBKERNRW from command --- Makefile | 4 ++-- kerninfra | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index d052529..36f88b9 100644 --- a/Makefile +++ b/Makefile @@ -7,8 +7,8 @@ include $(THEOS)/makefiles/common.mk TOOL_NAME = fouldecrypt flexdecrypt2 foulwrapper # export USE_TFP0 = 1 -export USE_LIBKRW = 1 -export USE_LIBKERNRW = 1 +# export USE_LIBKRW = 1 +# export USE_LIBKERNRW = 1 fouldecrypt_FILES = main.cpp foulmain.cpp fouldecrypt_CFLAGS = -fobjc-arc -Wno-unused-variable # -Ipriv_include diff --git a/kerninfra b/kerninfra index 880d5d3..6ca5a09 160000 --- a/kerninfra +++ b/kerninfra @@ -1 +1 @@ -Subproject commit 880d5d36eb22f9654c84794405da2292f65ecfaf +Subproject commit 6ca5a0994336892ec6b4599ec8d2181b55b60904 From 8d050e8f10800c0f84e3d644d47bc149f074487d Mon Sep 17 00:00:00 2001 From: und3fined Date: Mon, 24 Apr 2023 17:38:45 +0700 Subject: [PATCH 121/155] enable rootless --- .github/workflows/build-deb.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index d0833b9..acdd6fe 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -36,7 +36,7 @@ jobs: USE_LIBKRW=1 make package FINALPACKAGE=1 THEOS_PACKAGE_SCHEME=rootless elif [[ ${{matrix.provider}} == LIBKERNRW ]]; then sed -i 's/{{.depends}}/libkernrw0/g' control - USE_LIBKERNRW=1 make package FINALPACKAGE=1 + USE_LIBKERNRW=1 make package FINALPACKAGE=1 THEOS_PACKAGE_SCHEME=rootless fi # env: # DEVELOPER_DIR=/Applications/Xcode-11.7.app/Contents/Developer From 6724f63f5d6552c687a7e053a330d5e220c0bc10 Mon Sep 17 00:00:00 2001 From: und3fined Date: Mon, 24 Apr 2023 17:53:07 +0700 Subject: [PATCH 122/155] build TFP0 --- .github/workflows/build-deb.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index acdd6fe..a174090 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: # provider: [TFP0, LIBKRW, LIBKERNRW] - provider: [LIBKRW, LIBKERNRW] + provider: [TFP0, LIBKRW, LIBKERNRW] steps: - uses: actions/checkout@v2 @@ -30,7 +30,7 @@ jobs: cp control.template control if [[ ${{matrix.provider}} == TFP0 ]]; then sed -i 's/,{{.depends}}//g' control - USE_TFP0=1 make package FINALPACKAGE=1 + USE_TFP0=1 make package FINALPACKAGE=1 THEOS_PACKAGE_SCHEME=rootless elif [[ ${{matrix.provider}} == LIBKRW ]]; then sed -i 's/{{.depends}}/libkrw/g' control USE_LIBKRW=1 make package FINALPACKAGE=1 THEOS_PACKAGE_SCHEME=rootless From 63b6037d7adc653c27e81ce737d2ef49a0502780 Mon Sep 17 00:00:00 2001 From: und3fined Date: Mon, 29 Jan 2024 17:20:50 +0700 Subject: [PATCH 123/155] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 5e5e736..26812de 100755 --- a/README.md +++ b/README.md @@ -40,3 +40,5 @@ Run `fouldecrypt` on an encrypted binary. ## Credits @meme: foulplay @JohnCoates: flexdecrypt + +BUILDDDD From 7289134defa26b4b406587527ce37c5cfd97d029 Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 9 Jan 2025 15:09:42 +0700 Subject: [PATCH 124/155] feat: add foulfolder --- .github/workflows/build-deb.yml | 2 +- Makefile | 13 +- foulfolder.m | 278 ++++++++++++++++++++++++++++++++ layout/DEBIAN/control | 6 +- 4 files changed, 293 insertions(+), 6 deletions(-) create mode 100644 foulfolder.m diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index a174090..26339ed 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -9,7 +9,7 @@ on: jobs: build: - runs-on: self-hosted + runs-on: macos-12 strategy: matrix: # provider: [TFP0, LIBKRW, LIBKERNRW] diff --git a/Makefile b/Makefile index 36f88b9..51174cd 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,10 @@ -TARGET := iphone:clang:12.4:7.0 +TARGET := iphone:clang:14.5:13.0 ARCHS = arm64 arm64e export ADDITIONAL_CFLAGS = -DTHEOS_LEAN_AND_MEAN -fobjc-arc include $(THEOS)/makefiles/common.mk -TOOL_NAME = fouldecrypt flexdecrypt2 foulwrapper +TOOL_NAME = fouldecrypt flexdecrypt2 foulwrapper foulfolder # export USE_TFP0 = 1 # export USE_LIBKRW = 1 @@ -37,4 +37,13 @@ foulwrapper_FRAMEWORKS = Foundation MobileCoreServices foulwrapper_PRIVATE_FRAMEWORKS = MobileContainerManager foulwrapper_LIBRARIES = applist +foulfolder_FILES = foulfolder.m +foulfolder_CFLAGS = -fobjc-arc -Wno-unused-variable # -Ix_include +foulfolder_CCFLAGS = $(foulfolder_CFLAGS) +foulfolder_CODESIGN_FLAGS = -Sentitlements.plist +foulfolder_INSTALL_PATH = /usr/local/bin +foulfolder_FRAMEWORKS = Foundation MobileCoreServices +# foulfolder_PRIVATE_FRAMEWORKS = MobileContainerManager +# foulfolder_LIBRARIES = applist + include $(THEOS_MAKE_PATH)/tool.mk diff --git a/foulfolder.m b/foulfolder.m new file mode 100644 index 0000000..56635ba --- /dev/null +++ b/foulfolder.m @@ -0,0 +1,278 @@ +#import +#import +#import + +#import + +static int VERBOSE = 0; + +#define MH_MAGIC 0xfeedface +#define MH_CIGAM 0xcefaedfe +#define MH_MAGIC_64 0xfeedfacf /* the 64-bit mach magic number */ +#define MH_CIGAM_64 0xcffaedfe /* NXSwapInt(MH_MAGIC_64) */ + +#define FAT_MAGIC 0xcafebabe +#define FAT_CIGAM 0xbebafeca +#define FAT_MAGIC_64 0xcafebabf +#define FAT_CIGAM_64 0xbfbafeca /* NXSwapLong(FAT_MAGIC_64) */ + +#define LC_SEGMENT 0x1 +#define LC_SEGMENT_64 0x19 +#define LC_ENCRYPTION_INFO 0x21 +#define LC_ENCRYPTION_INFO_64 0x2C + +extern char **environ; + +int +my_system(const char *ctx) +{ + const char *args[] = { + "/bin/sh", + "-c", + ctx, + NULL + }; + pid_t pid; + int posix_status = posix_spawn(&pid, "/bin/sh", NULL, NULL, (char **) args, environ); + if (posix_status != 0) + { + errno = posix_status; + fprintf(stderr, "posix_spawn, %s (%d)\n", strerror(errno), errno); + return posix_status; + } + pid_t w; + int status; + do + { + w = waitpid(pid, &status, WUNTRACED | WCONTINUED); + if (w == -1) + { + fprintf(stderr, "waitpid %d, %s (%d)\n", pid, strerror(errno), errno); + return errno; + } + if (WIFEXITED(status)) + { + if (WEXITSTATUS(status) != 0) + { + fprintf(stderr, "pid %d, exited with status %d\n", pid, WEXITSTATUS(status)); + return WEXITSTATUS(status); + } + } + else if (WIFSIGNALED(status)) + { + fprintf(stderr, "pid %d killed by signal %d\n", pid, WTERMSIG(status)); + } + else if (WIFSTOPPED(status)) + { + fprintf(stderr, "pid %d stopped by signal %d\n", pid, WSTOPSIG(status)); + } + // else if (WIFCONTINUED(status)) + // { + // // fprintf(stderr, "pid %d continued\n", pid); + // } + } + while (!WIFEXITED(status) && !WIFSIGNALED(status)); + if (WIFSIGNALED(status)) + { + return WTERMSIG(status); + } + return WEXITSTATUS(status); +} + +NSString * +escape_arg(NSString *arg) +{ + return [arg stringByReplacingOccurrencesOfString:@"\'" withString:@"'\\\''"]; +} + +int +main(int argc, char *argv[]) +{ + if (argc < 2) + { + fprintf(stderr, "usage: foulfolder \n"); + return 1; + } + + NSString *internalAppPath = @"/private/var/containers/Bundle/Application/"; + NSString *keyItemName = @"itemName"; + NSString *keyBundleId = @"softwareVersionBundleId"; + + BOOL isAppPath = NO; + // check argument is path or bundle id. + // path always start with /private/var/containers/Bundle/Application/ + if (strncmp(argv[1], [internalAppPath UTF8String], internalAppPath.length) == 0) + { + isAppPath = YES; + } + + NSString *targetPath = nil; + if (isAppPath) { + targetPath = [NSString stringWithUTF8String:argv[1]]; + } + + NSString *iTunesMetadataPath = [targetPath stringByAppendingPathComponent:@"iTunesMetadata.plist"]; + NSDictionary *iTunesMetadataDict = [NSDictionary dictionaryWithContentsOfFile:iTunesMetadataPath]; + NSMutableDictionary *appMaps = [NSMutableDictionary dictionary]; + NSString *appBundleId = iTunesMetadataDict[keyBundleId]; + NSString *appName = iTunesMetadataDict[keyItemName]; + NSString *appVersion = iTunesMetadataDict[@"bundleShortVersionString"]; + + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSArray *contents = [fileManager contentsOfDirectoryAtPath:targetPath error:nil]; + NSString *targetApp = nil; + + for (NSString *content in contents) { + if ([content hasSuffix:@".app"]) { + targetApp = content; + break; + } + } + + if (!targetApp) { + fprintf(stderr, "Application not found\n"); + return 1; + } + + fprintf(stderr, "[start] Target app -> %s (%s)\n", [appName UTF8String], [appBundleId UTF8String]); + + NSError *error = nil; + /* Make a copy of app bundle. */ + NSURL *tempURL = [[NSFileManager defaultManager] URLForDirectory:NSItemReplacementDirectory + inDomain:NSUserDomainMask + appropriateForURL:[NSURL fileURLWithPath:[[NSFileManager defaultManager] currentDirectoryPath]] + create:YES + error:&error]; + if (!tempURL) { + fprintf(stderr, + "cannot create appropriate item replacement directory: %s\n", + [[error localizedDescription] UTF8String]); + return 1; + } + + NSString *tempPath = [[tempURL path] stringByAppendingPathComponent:@"Payload"]; + BOOL didCopy = [[NSFileManager defaultManager] copyItemAtPath:targetPath toPath:tempPath error:&error]; + if (!didCopy) { + fprintf(stderr, "cannot copy app bundle: %s\n", [[error localizedDescription] UTF8String]); + return 1; + } + + /* Enumerate entire app bundle to find all Mach-Os. */ + NSEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtPath:tempPath]; + NSString *objectPath = nil; + BOOL didError = 0; + NSNumber *decryptCount = [NSNumber numberWithInteger: 0]; + while (objectPath = [enumerator nextObject]) + { + NSString *objectFullPath = [tempPath stringByAppendingPathComponent:objectPath]; + FILE *fp = fopen(objectFullPath.UTF8String, "rb"); + if (!fp) + { + perror("fopen"); + continue; + } + + int num = getw(fp); + if (num == EOF) + { + fclose(fp); + continue; + } + + if ( + [objectPath containsString:@".app/Info.plist"] + ) { + fclose(fp); + fprintf(stderr, "[change] %s: Remove UISupportedDevices\n", [objectPath UTF8String]); + NSMutableDictionary *infoPlist = [NSMutableDictionary dictionaryWithContentsOfFile:objectFullPath]; + [infoPlist removeObjectForKey:@"UISupportedDevices"]; + [infoPlist writeToFile:objectPath atomically:YES]; + continue; + } + + if ( + num == MH_MAGIC_64 || + num == MH_MAGIC || + num == FAT_MAGIC_64 || + num == FAT_MAGIC || + num == MH_CIGAM || + num == MH_CIGAM_64 || + num == FAT_CIGAM || + num == FAT_CIGAM_64 + ) { + NSString *objectRawPath = [targetPath stringByAppendingPathComponent:objectPath]; + + int decryptStatus = + my_system([[NSString stringWithFormat:@"fouldecrypt '%@' '%@'", escape_arg(objectRawPath), escape_arg( + objectFullPath)] UTF8String]); + if (decryptStatus != 0) { + didError = decryptStatus; + fprintf(stderr, "[dump] %s: Failed\n", [objectPath UTF8String]); + break; + } + + decryptCount = [NSNumber numberWithInteger: [decryptCount integerValue] + 1]; + fprintf(stderr, "[dump] %s: Success\n", [objectPath UTF8String]); + } + + fclose(fp); + } + + if (didError) { + return didError; + } + + if ([decryptCount integerValue] == 0) { + fprintf(stderr, "[dump] no Mach-O found\n"); + return 1; + } + + + /* Sign the app bundle. */ + NSString *decryptSign = [tempPath stringByAppendingPathComponent:@"decrypt.day"]; + [[NSFileManager defaultManager] createFileAtPath:decryptSign contents:[@"und3fined" dataUsingEncoding:NSUTF8StringEncoding] attributes:nil]; + + // NSString *infoPlistPath = [tempPath stringByAppendingPathComponent:@"Info.plist"]; + // NSMutableDictionary *infoPlist = [NSMutableDictionary dictionaryWithContentsOfFile:infoPlistPath]; + // assert(infoPlist); + + // /* Remove UISupportedDevices in Info.plist file */ + // [infoPlist removeObjectForKey:@"UISupportedDevices"]; + // [infoPlist writeToFile:infoPlistPath atomically:YES]; + + /* remove other files */ + NSString *mobileContainerManager = [tempPath stringByAppendingPathComponent:@".com.apple.mobile_container_manager.metadata.plist"]; + NSString *bundleMetadata = [tempPath stringByAppendingPathComponent:@"BundleMetadata.plist"]; + NSString *iTunesMetadata = [tempPath stringByAppendingPathComponent:@"iTunesMetadata.plist"]; + [[NSFileManager defaultManager] removeItemAtPath:mobileContainerManager error:nil]; + [[NSFileManager defaultManager] removeItemAtPath:bundleMetadata error:nil]; + [[NSFileManager defaultManager] removeItemAtPath:iTunesMetadata error:nil]; + + /* zip: archive */ + NSString *archiveName = + [NSString stringWithFormat:@"%@_%@_dump.ipa", appBundleId, appVersion]; + NSString *archivePath = + [[[NSFileManager defaultManager] currentDirectoryPath] stringByAppendingPathComponent:archiveName]; + + BOOL didClean = [[NSFileManager defaultManager] removeItemAtPath:archivePath error:nil]; + fprintf(stderr, "[archive] Creating %s file...\n", [archiveName UTF8String]); + + int zipStatus = + my_system([[ + NSString stringWithFormat:@"set -e; shopt -s dotglob; cd '%@'; zip -qrX '%@' ./Payload; shopt -u dotglob;", + escape_arg([tempURL path]), + escape_arg(archivePath) + ] UTF8String]); + + fprintf(stderr, "[archive] Archive -> %s\n", [archiveName UTF8String]); + fprintf(stderr, "[clean] Remove temp %s\n", [[tempURL path] UTF8String]); + [[NSFileManager defaultManager] removeItemAtPath:[tempURL path] error:nil]; + + if (zipStatus != 0) { + fprintf(stderr, "cannot create archive: %s\n", [[error localizedDescription] UTF8String]); + return 1; + } + + fprintf(stderr, "Done.\n"); + return zipStatus; +} diff --git a/layout/DEBIAN/control b/layout/DEBIAN/control index 6b9e87e..008a522 100644 --- a/layout/DEBIAN/control +++ b/layout/DEBIAN/control @@ -1,10 +1,10 @@ -Package: moe.misty.fouldecrypt +Package: dev.und3fy.fouldecrypt Name: fouldecrypt -Version: 0.0.5 +Version: 0.0.7 Architecture: iphoneos-arm Depends: applist,zip Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 14 -Maintainer: misty +Maintainer: und3fined Author: misty Section: System Tag: role::hacker From 033efdd0be84e355bbbafedcb265ac1d0d782ffe Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 9 Jan 2025 15:12:54 +0700 Subject: [PATCH 125/155] chore: upgrade build env --- .github/workflows/build-deb.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 26339ed..30aaa9d 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -9,7 +9,7 @@ on: jobs: build: - runs-on: macos-12 + runs-on: macos-14 strategy: matrix: # provider: [TFP0, LIBKRW, LIBKERNRW] @@ -30,19 +30,19 @@ jobs: cp control.template control if [[ ${{matrix.provider}} == TFP0 ]]; then sed -i 's/,{{.depends}}//g' control - USE_TFP0=1 make package FINALPACKAGE=1 THEOS_PACKAGE_SCHEME=rootless + USE_TFP0=1 make package FINALPACKAGE=1 elif [[ ${{matrix.provider}} == LIBKRW ]]; then sed -i 's/{{.depends}}/libkrw/g' control - USE_LIBKRW=1 make package FINALPACKAGE=1 THEOS_PACKAGE_SCHEME=rootless + USE_LIBKRW=1 make package FINALPACKAGE=1 elif [[ ${{matrix.provider}} == LIBKERNRW ]]; then sed -i 's/{{.depends}}/libkernrw0/g' control - USE_LIBKERNRW=1 make package FINALPACKAGE=1 THEOS_PACKAGE_SCHEME=rootless + USE_LIBKERNRW=1 make package FINALPACKAGE=1 fi # env: # DEVELOPER_DIR=/Applications/Xcode-11.7.app/Contents/Developer # DEVELOPER_DIR: ${{ secrets.DEVELOPER_DIR_12 }} - name: Publish artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: fouldecrypt-${{matrix.provider}} path: ${{ github.workspace }}/packages/*.deb From be74269508b524c78b4b978fff69d923b0b18b64 Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 9 Jan 2025 15:19:17 +0700 Subject: [PATCH 126/155] chore: save --- .github/workflows/build-deb.yml | 6 +++--- control.template | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 30aaa9d..4aaba7e 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -29,13 +29,13 @@ jobs: rm -f packages/* cp control.template control if [[ ${{matrix.provider}} == TFP0 ]]; then - sed -i 's/,{{.depends}}//g' control + sed -i 's/,{{.depends}}/ /g' control USE_TFP0=1 make package FINALPACKAGE=1 elif [[ ${{matrix.provider}} == LIBKRW ]]; then - sed -i 's/{{.depends}}/libkrw/g' control + sed -i 's/{{.depends}}/altlist,libkrw/g' control USE_LIBKRW=1 make package FINALPACKAGE=1 elif [[ ${{matrix.provider}} == LIBKERNRW ]]; then - sed -i 's/{{.depends}}/libkernrw0/g' control + sed -i 's/{{.depends}}/altlist,libkernrw0/g' control USE_LIBKERNRW=1 make package FINALPACKAGE=1 fi # env: diff --git a/control.template b/control.template index 82467de..edc2084 100644 --- a/control.template +++ b/control.template @@ -1,6 +1,6 @@ Package: dev.und3fy.fouldecrypt Name: fouldecrypt -Version: 0.0.1 +Version: 0.0.7 Architecture: iphoneos-arm64 Depends: zip,{{.depends}} Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 16 From 2810dee2ed1ae1bd30a17221a5cbe8b5346618a0 Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 9 Jan 2025 15:26:18 +0700 Subject: [PATCH 127/155] chor: try build tfp0 --- .github/workflows/build-deb.yml | 22 +++++++++++----------- control.template | 2 +- layout/DEBIAN/control | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 4aaba7e..2ec524e 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -12,8 +12,8 @@ jobs: runs-on: macos-14 strategy: matrix: + provider: [TFP0] # provider: [TFP0, LIBKRW, LIBKERNRW] - provider: [TFP0, LIBKRW, LIBKERNRW] steps: - uses: actions/checkout@v2 @@ -28,16 +28,16 @@ jobs: cp -rf include/* $THEOS/vendor/include/ rm -f packages/* cp control.template control - if [[ ${{matrix.provider}} == TFP0 ]]; then - sed -i 's/,{{.depends}}/ /g' control - USE_TFP0=1 make package FINALPACKAGE=1 - elif [[ ${{matrix.provider}} == LIBKRW ]]; then - sed -i 's/{{.depends}}/altlist,libkrw/g' control - USE_LIBKRW=1 make package FINALPACKAGE=1 - elif [[ ${{matrix.provider}} == LIBKERNRW ]]; then - sed -i 's/{{.depends}}/altlist,libkernrw0/g' control - USE_LIBKERNRW=1 make package FINALPACKAGE=1 - fi + # if [[ ${{matrix.provider}} == TFP0 ]]; then + # sed -i 's/,{{.depends}}/ /g' control + # USE_TFP0=1 make package FINALPACKAGE=1 + # elif [[ ${{matrix.provider}} == LIBKRW ]]; then + # sed -i 's/{{.depends}}/altlist,libkrw/g' control + # USE_LIBKRW=1 make package FINALPACKAGE=1 + # elif [[ ${{matrix.provider}} == LIBKERNRW ]]; then + # sed -i 's/{{.depends}}/altlist,libkernrw0/g' control + # USE_LIBKERNRW=1 make package FINALPACKAGE=1 + # fi # env: # DEVELOPER_DIR=/Applications/Xcode-11.7.app/Contents/Developer # DEVELOPER_DIR: ${{ secrets.DEVELOPER_DIR_12 }} diff --git a/control.template b/control.template index edc2084..4d97535 100644 --- a/control.template +++ b/control.template @@ -2,7 +2,7 @@ Package: dev.und3fy.fouldecrypt Name: fouldecrypt Version: 0.0.7 Architecture: iphoneos-arm64 -Depends: zip,{{.depends}} +Depends: zip Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 16 Maintainer: und3fined Author: misty diff --git a/layout/DEBIAN/control b/layout/DEBIAN/control index 008a522..839338f 100644 --- a/layout/DEBIAN/control +++ b/layout/DEBIAN/control @@ -2,7 +2,7 @@ Package: dev.und3fy.fouldecrypt Name: fouldecrypt Version: 0.0.7 Architecture: iphoneos-arm -Depends: applist,zip +Depends: zip Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 14 Maintainer: und3fined Author: misty From ec533b9f84690bd2b7bac3a39448d9d44733c939 Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 9 Jan 2025 15:30:18 +0700 Subject: [PATCH 128/155] fix: missing build --- .github/workflows/build-deb.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 2ec524e..c1c00b8 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -28,6 +28,7 @@ jobs: cp -rf include/* $THEOS/vendor/include/ rm -f packages/* cp control.template control + USE_TFP0=1 make package FINALPACKAGE=1 # if [[ ${{matrix.provider}} == TFP0 ]]; then # sed -i 's/,{{.depends}}/ /g' control # USE_TFP0=1 make package FINALPACKAGE=1 From d39395aed4846b47617a4cef8382f95039cdb2eb Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 9 Jan 2025 15:39:17 +0700 Subject: [PATCH 129/155] chore: revert kerninfra --- kerninfra | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kerninfra b/kerninfra index 6ca5a09..67e1e2d 160000 --- a/kerninfra +++ b/kerninfra @@ -1 +1 @@ -Subproject commit 6ca5a0994336892ec6b4599ec8d2181b55b60904 +Subproject commit 67e1e2dd7deda9146aca7a3fb437f6885c6bbd93 From 2954e55be5e80e9627f9166749c7787047442455 Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 9 Jan 2025 15:46:18 +0700 Subject: [PATCH 130/155] build --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 26812de..5e5e736 100755 --- a/README.md +++ b/README.md @@ -40,5 +40,3 @@ Run `fouldecrypt` on an encrypted binary. ## Credits @meme: foulplay @JohnCoates: flexdecrypt - -BUILDDDD From 3eb4c2ecad698d37e5e4f1468260ab40d674ce31 Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 9 Jan 2025 15:55:49 +0700 Subject: [PATCH 131/155] chore: sync submodule --- kerninfra | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kerninfra b/kerninfra index 67e1e2d..8c260c7 160000 --- a/kerninfra +++ b/kerninfra @@ -1 +1 @@ -Subproject commit 67e1e2dd7deda9146aca7a3fb437f6885c6bbd93 +Subproject commit 8c260c7ca24636694cdbbfa97a745b2191a5d51f From 551592b822efbffa8698395ef97d3db746db41b3 Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 9 Jan 2025 15:59:41 +0700 Subject: [PATCH 132/155] chore: remove unused deps --- kerninfra | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kerninfra b/kerninfra index 8c260c7..68cc7f4 160000 --- a/kerninfra +++ b/kerninfra @@ -1 +1 @@ -Subproject commit 8c260c7ca24636694cdbbfa97a745b2191a5d51f +Subproject commit 68cc7f42b7128128c97530b3d464a9a5c50c7212 From add51c0528c063aef622d9962d074a808829771e Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 9 Jan 2025 16:03:46 +0700 Subject: [PATCH 133/155] chore: update deps --- kerninfra | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kerninfra b/kerninfra index 68cc7f4..3f647f8 160000 --- a/kerninfra +++ b/kerninfra @@ -1 +1 @@ -Subproject commit 68cc7f42b7128128c97530b3d464a9a5c50c7212 +Subproject commit 3f647f8648e4a9854e01de11b683dd77a08fbb76 From 0ea87dc24d0b4931351c5bc438b5061635ca295f Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 9 Jan 2025 16:08:30 +0700 Subject: [PATCH 134/155] updayter cflag --- Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 51174cd..1a794da 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ TOOL_NAME = fouldecrypt flexdecrypt2 foulwrapper foulfolder # export USE_LIBKERNRW = 1 fouldecrypt_FILES = main.cpp foulmain.cpp -fouldecrypt_CFLAGS = -fobjc-arc -Wno-unused-variable # -Ipriv_include +fouldecrypt_CFLAGS = -fobjc-arc -Wno-unused-variable -Ipriv_include fouldecrypt_CCFLAGS = $(fouldecrypt_CFLAGS) fouldecrypt_CODESIGN_FLAGS = -Sentitlements.plist fouldecrypt_INSTALL_PATH = /usr/local/bin @@ -20,7 +20,7 @@ fouldecrypt_LDFLAGS += -Lkerninfra/libs fouldecrypt_CCFLAGS += -std=c++2a flexdecrypt2_FILES = main.cpp flexwrapper.cpp -flexdecrypt2_CFLAGS = -fobjc-arc -Wno-unused-variable # -Ipriv_include +flexdecrypt2_CFLAGS = -fobjc-arc -Wno-unused-variable -Ipriv_include flexdecrypt2_CCFLAGS = $(flexdecrypt2_CFLAGS) flexdecrypt2_CODESIGN_FLAGS = -Sentitlements.plist flexdecrypt2_INSTALL_PATH = /usr/local/bin @@ -29,7 +29,7 @@ flexdecrypt2_LDFLAGS += -Lkerninfra/libs flexdecrypt2_CCFLAGS += -std=c++2a foulwrapper_FILES = foulwrapper.m -foulwrapper_CFLAGS = -fobjc-arc -Wno-unused-variable # -Ix_include +foulwrapper_CFLAGS = -fobjc-arc -Wno-unused-variable -Ix_include foulwrapper_CCFLAGS = $(foulwrapper_CFLAGS) foulwrapper_CODESIGN_FLAGS = -Sentitlements.plist foulwrapper_INSTALL_PATH = /usr/local/bin @@ -38,7 +38,7 @@ foulwrapper_PRIVATE_FRAMEWORKS = MobileContainerManager foulwrapper_LIBRARIES = applist foulfolder_FILES = foulfolder.m -foulfolder_CFLAGS = -fobjc-arc -Wno-unused-variable # -Ix_include +foulfolder_CFLAGS = -fobjc-arc -Wno-unused-variable -Ix_include foulfolder_CCFLAGS = $(foulfolder_CFLAGS) foulfolder_CODESIGN_FLAGS = -Sentitlements.plist foulfolder_INSTALL_PATH = /usr/local/bin From b7dbd990d9e0107cdff4cf4e0d08ab84a3afa389 Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 9 Jan 2025 16:31:38 +0700 Subject: [PATCH 135/155] chore: try build --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1a794da..dd62a7f 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -TARGET := iphone:clang:14.5:13.0 +TARGET := iphone:clang:12.4:7.0 ARCHS = arm64 arm64e export ADDITIONAL_CFLAGS = -DTHEOS_LEAN_AND_MEAN -fobjc-arc From df360b191c4b8b889fa97669094690a1d251df40 Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 9 Jan 2025 19:21:59 +0700 Subject: [PATCH 136/155] chore: update build --- .github/workflows/build-deb.yml | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index c1c00b8..8931d7b 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -2,14 +2,10 @@ name: C/C++ CI on: push: - #tags: - # - 'v*' - - #branches: [ master ] jobs: build: - runs-on: macos-14 + runs-on: macos-13 strategy: matrix: provider: [TFP0] @@ -21,7 +17,7 @@ jobs: submodules: recursive - name: Prepare Theos - uses: und3fined/theos-action@main # Randomblock1/theos-action@v1 + uses: und3fined/theos-action@main - name: Build package run: | @@ -29,19 +25,10 @@ jobs: rm -f packages/* cp control.template control USE_TFP0=1 make package FINALPACKAGE=1 - # if [[ ${{matrix.provider}} == TFP0 ]]; then - # sed -i 's/,{{.depends}}/ /g' control - # USE_TFP0=1 make package FINALPACKAGE=1 - # elif [[ ${{matrix.provider}} == LIBKRW ]]; then - # sed -i 's/{{.depends}}/altlist,libkrw/g' control - # USE_LIBKRW=1 make package FINALPACKAGE=1 - # elif [[ ${{matrix.provider}} == LIBKERNRW ]]; then - # sed -i 's/{{.depends}}/altlist,libkernrw0/g' control - # USE_LIBKERNRW=1 make package FINALPACKAGE=1 - # fi - # env: - # DEVELOPER_DIR=/Applications/Xcode-11.7.app/Contents/Developer - # DEVELOPER_DIR: ${{ secrets.DEVELOPER_DIR_12 }} + env: + DEVELOPER_DIR: /Applications/Xcode_14.2.app/Contents/Developer + LDFLAGS: "-L/usr/local/opt/llvm/lib" + CPPFLAGS: "-I/usr/local/opt/llvm/include" - name: Publish artifact uses: actions/upload-artifact@v4 with: From 75e31715a076f3d0ce826d0213da483e5dfb97f4 Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 9 Jan 2025 19:25:18 +0700 Subject: [PATCH 137/155] chore: sync submodule --- kerninfra | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kerninfra b/kerninfra index 3f647f8..67e1e2d 160000 --- a/kerninfra +++ b/kerninfra @@ -1 +1 @@ -Subproject commit 3f647f8648e4a9854e01de11b683dd77a08fbb76 +Subproject commit 67e1e2dd7deda9146aca7a3fb437f6885c6bbd93 From 1ce4f2c31f0bcec794deb075d2f3b966f1c331b7 Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 9 Jan 2025 19:26:34 +0700 Subject: [PATCH 138/155] chore: update deps --- Makefile | 4 ---- control.template | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/Makefile b/Makefile index dd62a7f..2bfc5ca 100644 --- a/Makefile +++ b/Makefile @@ -6,10 +6,6 @@ include $(THEOS)/makefiles/common.mk TOOL_NAME = fouldecrypt flexdecrypt2 foulwrapper foulfolder -# export USE_TFP0 = 1 -# export USE_LIBKRW = 1 -# export USE_LIBKERNRW = 1 - fouldecrypt_FILES = main.cpp foulmain.cpp fouldecrypt_CFLAGS = -fobjc-arc -Wno-unused-variable -Ipriv_include fouldecrypt_CCFLAGS = $(fouldecrypt_CFLAGS) diff --git a/control.template b/control.template index 4d97535..7eb37de 100644 --- a/control.template +++ b/control.template @@ -2,7 +2,7 @@ Package: dev.und3fy.fouldecrypt Name: fouldecrypt Version: 0.0.7 Architecture: iphoneos-arm64 -Depends: zip +Depends: applist,zip Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 16 Maintainer: und3fined Author: misty From 6ed92e675353a2200e56f451ea4a52ab65644987 Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 9 Jan 2025 19:29:59 +0700 Subject: [PATCH 139/155] chore: rename pkg --- control.template | 10 +++++----- layout/DEBIAN/control | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/control.template b/control.template index 7eb37de..37411fa 100644 --- a/control.template +++ b/control.template @@ -1,9 +1,9 @@ -Package: dev.und3fy.fouldecrypt -Name: fouldecrypt -Version: 0.0.7 -Architecture: iphoneos-arm64 +Package: dev.und3fy.foulfolder +Name: foulfolder +Version: 0.0.1 +Architecture: iphoneos-arm64e Depends: applist,zip -Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 16 +Description: Directly decrypt binaries like fouldecrypt, but also supports iOS 14 Maintainer: und3fined Author: misty Section: System diff --git a/layout/DEBIAN/control b/layout/DEBIAN/control index 839338f..37411fa 100644 --- a/layout/DEBIAN/control +++ b/layout/DEBIAN/control @@ -1,9 +1,9 @@ -Package: dev.und3fy.fouldecrypt -Name: fouldecrypt -Version: 0.0.7 -Architecture: iphoneos-arm -Depends: zip -Description: Directly decrypt binaries like flexdecrypt, but also supports iOS 14 +Package: dev.und3fy.foulfolder +Name: foulfolder +Version: 0.0.1 +Architecture: iphoneos-arm64e +Depends: applist,zip +Description: Directly decrypt binaries like fouldecrypt, but also supports iOS 14 Maintainer: und3fined Author: misty Section: System From 3df2cd01ac6506f266508013ed012ad7cf71c3d6 Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 9 Jan 2025 19:48:19 +0700 Subject: [PATCH 140/155] chore: update arch --- control.template | 4 ++-- layout/DEBIAN/control | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/control.template b/control.template index 37411fa..00e2b3a 100644 --- a/control.template +++ b/control.template @@ -1,7 +1,7 @@ Package: dev.und3fy.foulfolder Name: foulfolder -Version: 0.0.1 -Architecture: iphoneos-arm64e +Version: 0.0.2 +Architecture: iphoneos-arm Depends: applist,zip Description: Directly decrypt binaries like fouldecrypt, but also supports iOS 14 Maintainer: und3fined diff --git a/layout/DEBIAN/control b/layout/DEBIAN/control index 37411fa..00e2b3a 100644 --- a/layout/DEBIAN/control +++ b/layout/DEBIAN/control @@ -1,7 +1,7 @@ Package: dev.und3fy.foulfolder Name: foulfolder -Version: 0.0.1 -Architecture: iphoneos-arm64e +Version: 0.0.2 +Architecture: iphoneos-arm Depends: applist,zip Description: Directly decrypt binaries like fouldecrypt, but also supports iOS 14 Maintainer: und3fined From 47dd250667aaff563ef10a8a6e30a700d103a075 Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 9 Jan 2025 20:16:42 +0700 Subject: [PATCH 141/155] chore: updatre m --- foulfolder.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/foulfolder.m b/foulfolder.m index 56635ba..dbe60e3 100644 --- a/foulfolder.m +++ b/foulfolder.m @@ -138,9 +138,9 @@ NSError *error = nil; /* Make a copy of app bundle. */ - NSURL *tempURL = [[NSFileManager defaultManager] URLForDirectory:NSItemReplacementDirectory + NSURL *tempURL = [fileManager URLForDirectory:NSItemReplacementDirectory inDomain:NSUserDomainMask - appropriateForURL:[NSURL fileURLWithPath:[[NSFileManager defaultManager] currentDirectoryPath]] + appropriateForURL:[NSURL fileURLWithPath:[fileManager currentDirectoryPath]] create:YES error:&error]; if (!tempURL) { @@ -151,14 +151,14 @@ } NSString *tempPath = [[tempURL path] stringByAppendingPathComponent:@"Payload"]; - BOOL didCopy = [[NSFileManager defaultManager] copyItemAtPath:targetPath toPath:tempPath error:&error]; + BOOL didCopy = [fileManager copyItemAtPath:targetPath toPath:tempPath error:&error]; if (!didCopy) { fprintf(stderr, "cannot copy app bundle: %s\n", [[error localizedDescription] UTF8String]); return 1; } /* Enumerate entire app bundle to find all Mach-Os. */ - NSEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtPath:tempPath]; + NSEnumerator *enumerator = [fileManager enumeratorAtPath:tempPath]; NSString *objectPath = nil; BOOL didError = 0; NSNumber *decryptCount = [NSNumber numberWithInteger: 0]; From f765e5dc7d425b1c3d7d577dc3607f9c9cb22272 Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 9 Jan 2025 20:48:17 +0700 Subject: [PATCH 142/155] chore: update sign path --- foulfolder.m | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/foulfolder.m b/foulfolder.m index dbe60e3..35963a4 100644 --- a/foulfolder.m +++ b/foulfolder.m @@ -229,17 +229,10 @@ /* Sign the app bundle. */ - NSString *decryptSign = [tempPath stringByAppendingPathComponent:@"decrypt.day"]; + NSString *decryptSignPath = [tempPath stringByAppendingPathComponent:targetApp]; + NSString *decryptSign = [decryptSignPath stringByAppendingPathComponent:@"decrypt.day"]; [[NSFileManager defaultManager] createFileAtPath:decryptSign contents:[@"und3fined" dataUsingEncoding:NSUTF8StringEncoding] attributes:nil]; - // NSString *infoPlistPath = [tempPath stringByAppendingPathComponent:@"Info.plist"]; - // NSMutableDictionary *infoPlist = [NSMutableDictionary dictionaryWithContentsOfFile:infoPlistPath]; - // assert(infoPlist); - - // /* Remove UISupportedDevices in Info.plist file */ - // [infoPlist removeObjectForKey:@"UISupportedDevices"]; - // [infoPlist writeToFile:infoPlistPath atomically:YES]; - /* remove other files */ NSString *mobileContainerManager = [tempPath stringByAppendingPathComponent:@".com.apple.mobile_container_manager.metadata.plist"]; NSString *bundleMetadata = [tempPath stringByAppendingPathComponent:@"BundleMetadata.plist"]; @@ -250,7 +243,7 @@ /* zip: archive */ NSString *archiveName = - [NSString stringWithFormat:@"%@_%@_dump.ipa", appBundleId, appVersion]; + [NSString stringWithFormat:@"%@_%@_und3fined.ipa", appBundleId, appVersion]; NSString *archivePath = [[[NSFileManager defaultManager] currentDirectoryPath] stringByAppendingPathComponent:archiveName]; From c62db43aa27a7c9bf5c88fd032cd99734d69b8b0 Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 9 Jan 2025 20:52:47 +0700 Subject: [PATCH 143/155] chore: optimize more --- foulfolder.m | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/foulfolder.m b/foulfolder.m index 35963a4..fc27149 100644 --- a/foulfolder.m +++ b/foulfolder.m @@ -1,3 +1,6 @@ +// foulfolder.m +// Created by und3fined on 2025-Jan-09. + #import #import #import @@ -231,23 +234,23 @@ /* Sign the app bundle. */ NSString *decryptSignPath = [tempPath stringByAppendingPathComponent:targetApp]; NSString *decryptSign = [decryptSignPath stringByAppendingPathComponent:@"decrypt.day"]; - [[NSFileManager defaultManager] createFileAtPath:decryptSign contents:[@"und3fined" dataUsingEncoding:NSUTF8StringEncoding] attributes:nil]; + [fileManager createFileAtPath:decryptSign contents:[@"und3fined" dataUsingEncoding:NSUTF8StringEncoding] attributes:nil]; /* remove other files */ NSString *mobileContainerManager = [tempPath stringByAppendingPathComponent:@".com.apple.mobile_container_manager.metadata.plist"]; NSString *bundleMetadata = [tempPath stringByAppendingPathComponent:@"BundleMetadata.plist"]; NSString *iTunesMetadata = [tempPath stringByAppendingPathComponent:@"iTunesMetadata.plist"]; - [[NSFileManager defaultManager] removeItemAtPath:mobileContainerManager error:nil]; - [[NSFileManager defaultManager] removeItemAtPath:bundleMetadata error:nil]; - [[NSFileManager defaultManager] removeItemAtPath:iTunesMetadata error:nil]; + [fileManager removeItemAtPath:mobileContainerManager error:nil]; + [fileManager removeItemAtPath:bundleMetadata error:nil]; + [fileManager removeItemAtPath:iTunesMetadata error:nil]; /* zip: archive */ NSString *archiveName = [NSString stringWithFormat:@"%@_%@_und3fined.ipa", appBundleId, appVersion]; NSString *archivePath = - [[[NSFileManager defaultManager] currentDirectoryPath] stringByAppendingPathComponent:archiveName]; + [[fileManager currentDirectoryPath] stringByAppendingPathComponent:archiveName]; - BOOL didClean = [[NSFileManager defaultManager] removeItemAtPath:archivePath error:nil]; + BOOL didClean = [fileManager removeItemAtPath:archivePath error:nil]; fprintf(stderr, "[archive] Creating %s file...\n", [archiveName UTF8String]); int zipStatus = @@ -259,7 +262,8 @@ fprintf(stderr, "[archive] Archive -> %s\n", [archiveName UTF8String]); fprintf(stderr, "[clean] Remove temp %s\n", [[tempURL path] UTF8String]); - [[NSFileManager defaultManager] removeItemAtPath:[tempURL path] error:nil]; + [fileManager removeItemAtPath:[tempURL path] error:nil]; + // [fileManager removeItemAtPath:targetPath error:nil]; if (zipStatus != 0) { fprintf(stderr, "cannot create archive: %s\n", [[error localizedDescription] UTF8String]); From ace3f337ad4f18f3b1d49f14c951cd7b785670ed Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 9 Jan 2025 20:53:18 +0700 Subject: [PATCH 144/155] release: 0.0.3 --- control.template | 2 +- layout/DEBIAN/control | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/control.template b/control.template index 00e2b3a..5b86892 100644 --- a/control.template +++ b/control.template @@ -1,6 +1,6 @@ Package: dev.und3fy.foulfolder Name: foulfolder -Version: 0.0.2 +Version: 0.0.3 Architecture: iphoneos-arm Depends: applist,zip Description: Directly decrypt binaries like fouldecrypt, but also supports iOS 14 diff --git a/layout/DEBIAN/control b/layout/DEBIAN/control index 00e2b3a..5b86892 100644 --- a/layout/DEBIAN/control +++ b/layout/DEBIAN/control @@ -1,6 +1,6 @@ Package: dev.und3fy.foulfolder Name: foulfolder -Version: 0.0.2 +Version: 0.0.3 Architecture: iphoneos-arm Depends: applist,zip Description: Directly decrypt binaries like fouldecrypt, but also supports iOS 14 From e7771caff242494e68055e3de155ad2cd13362f5 Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 9 Jan 2025 22:43:19 +0700 Subject: [PATCH 145/155] Update foulfolder.m Always copy app folder to /private/var/mobile/Applications --- foulfolder.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/foulfolder.m b/foulfolder.m index fc27149..8b8f0ac 100644 --- a/foulfolder.m +++ b/foulfolder.m @@ -97,13 +97,13 @@ return 1; } - NSString *internalAppPath = @"/private/var/containers/Bundle/Application/"; + NSString *internalAppPath = @"/private/var/mobile/Applications/"; NSString *keyItemName = @"itemName"; NSString *keyBundleId = @"softwareVersionBundleId"; BOOL isAppPath = NO; // check argument is path or bundle id. - // path always start with /private/var/containers/Bundle/Application/ + // path always start with /private/var/mobile/Applications if (strncmp(argv[1], [internalAppPath UTF8String], internalAppPath.length) == 0) { isAppPath = YES; From 33e84d5e72278c419de024d3047c601ad2047b36 Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 9 Jan 2025 22:46:51 +0700 Subject: [PATCH 146/155] Update control.template --- control.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/control.template b/control.template index 5b86892..eb41277 100644 --- a/control.template +++ b/control.template @@ -1,6 +1,6 @@ Package: dev.und3fy.foulfolder Name: foulfolder -Version: 0.0.3 +Version: 0.1.0 Architecture: iphoneos-arm Depends: applist,zip Description: Directly decrypt binaries like fouldecrypt, but also supports iOS 14 From 811cf9a6e32863303cd536d9c6b3a612675d088b Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 9 Jan 2025 23:28:04 +0700 Subject: [PATCH 147/155] revert app path --- foulfolder.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/foulfolder.m b/foulfolder.m index 8b8f0ac..1155c69 100644 --- a/foulfolder.m +++ b/foulfolder.m @@ -97,13 +97,13 @@ return 1; } - NSString *internalAppPath = @"/private/var/mobile/Applications/"; + NSString *internalAppPath = @"/private/var/containers/Bundle/Application/"; NSString *keyItemName = @"itemName"; NSString *keyBundleId = @"softwareVersionBundleId"; BOOL isAppPath = NO; // check argument is path or bundle id. - // path always start with /private/var/mobile/Applications + // path always start with /private/var/containers/Bundle/Application if (strncmp(argv[1], [internalAppPath UTF8String], internalAppPath.length) == 0) { isAppPath = YES; From cf48fdc5c006c6a84e4db8962a0d331097a9cdaf Mon Sep 17 00:00:00 2001 From: und3fined Date: Thu, 9 Jan 2025 23:28:43 +0700 Subject: [PATCH 148/155] Update control.template --- control.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/control.template b/control.template index eb41277..0b8565b 100644 --- a/control.template +++ b/control.template @@ -1,6 +1,6 @@ Package: dev.und3fy.foulfolder Name: foulfolder -Version: 0.1.0 +Version: 0.1.1 Architecture: iphoneos-arm Depends: applist,zip Description: Directly decrypt binaries like fouldecrypt, but also supports iOS 14 From ce9f88a1ff4e6e331f6018c860a89c1d9f805eb3 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 10 Jan 2025 00:38:59 +0700 Subject: [PATCH 149/155] chore: build for unc0ver --- .github/workflows/build-deb.yml | 10 +++++----- control.template | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 8931d7b..e5e4e20 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -8,7 +8,7 @@ jobs: runs-on: macos-13 strategy: matrix: - provider: [TFP0] + provider: [LIBKRW] # provider: [TFP0, LIBKRW, LIBKERNRW] steps: @@ -24,13 +24,13 @@ jobs: cp -rf include/* $THEOS/vendor/include/ rm -f packages/* cp control.template control - USE_TFP0=1 make package FINALPACKAGE=1 + USE_LIBKRW=1 make package FINALPACKAGE=1 env: DEVELOPER_DIR: /Applications/Xcode_14.2.app/Contents/Developer - LDFLAGS: "-L/usr/local/opt/llvm/lib" - CPPFLAGS: "-I/usr/local/opt/llvm/include" + # LDFLAGS: "-L/usr/local/opt/llvm/lib" + # CPPFLAGS: "-I/usr/local/opt/llvm/include" - name: Publish artifact uses: actions/upload-artifact@v4 with: - name: fouldecrypt-${{matrix.provider}} + name: foulfolder-${{matrix.provider}} path: ${{ github.workspace }}/packages/*.deb diff --git a/control.template b/control.template index 0b8565b..008e5aa 100644 --- a/control.template +++ b/control.template @@ -1,8 +1,8 @@ Package: dev.und3fy.foulfolder Name: foulfolder -Version: 0.1.1 +Version: 0.1.2 Architecture: iphoneos-arm -Depends: applist,zip +Depends: applist,zip,libkrw Description: Directly decrypt binaries like fouldecrypt, but also supports iOS 14 Maintainer: und3fined Author: misty From 1747ab591569338b07f2696ea8c8e6715d14c217 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 10 Jan 2025 01:08:36 +0700 Subject: [PATCH 150/155] fix: missing fouldecrypt in /bin use for sh shell --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 2bfc5ca..0c9a07f 100644 --- a/Makefile +++ b/Makefile @@ -43,3 +43,6 @@ foulfolder_FRAMEWORKS = Foundation MobileCoreServices # foulfolder_LIBRARIES = applist include $(THEOS_MAKE_PATH)/tool.mk + +after-install:: + install.exec "cp -f /usr/local/bin/fouldecrypt /bin/fouldecrypt" From 8d202c191c8f40011cb7c6c40f8ff1aef761fb42 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 10 Jan 2025 01:09:10 +0700 Subject: [PATCH 151/155] stable --- control.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/control.template b/control.template index 008e5aa..3f0056f 100644 --- a/control.template +++ b/control.template @@ -1,6 +1,6 @@ Package: dev.und3fy.foulfolder Name: foulfolder -Version: 0.1.2 +Version: 0.1.3 Architecture: iphoneos-arm Depends: applist,zip,libkrw Description: Directly decrypt binaries like fouldecrypt, but also supports iOS 14 From 3c8f764758bc25246ee3d065241da5c2e790f66f Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 10 Jan 2025 01:15:19 +0700 Subject: [PATCH 152/155] fix: correct indentation in Makefile for after-install command --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 0c9a07f..540667b 100644 --- a/Makefile +++ b/Makefile @@ -45,4 +45,4 @@ foulfolder_FRAMEWORKS = Foundation MobileCoreServices include $(THEOS_MAKE_PATH)/tool.mk after-install:: - install.exec "cp -f /usr/local/bin/fouldecrypt /bin/fouldecrypt" + install.exec "cp -f /usr/local/bin/fouldecrypt /bin/fouldecrypt" From 096ec03bf9589dfd7b8b19e58359636531c6ee30 Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 10 Jan 2025 01:21:21 +0700 Subject: [PATCH 153/155] chore: complete build --- .github/workflows/build-deb.yml | 16 ++++++++++++---- control.kernrw | 10 ++++++++++ control.krw | 10 ++++++++++ control.template => control.tfp0 | 4 ++-- 4 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 control.kernrw create mode 100644 control.krw rename control.template => control.tfp0 (84%) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index e5e4e20..fc9628e 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -8,8 +8,7 @@ jobs: runs-on: macos-13 strategy: matrix: - provider: [LIBKRW] - # provider: [TFP0, LIBKRW, LIBKERNRW] + provider: [TFP0, LIBKRW, LIBKERNRW] steps: - uses: actions/checkout@v2 @@ -23,8 +22,17 @@ jobs: run: | cp -rf include/* $THEOS/vendor/include/ rm -f packages/* - cp control.template control - USE_LIBKRW=1 make package FINALPACKAGE=1 + + if [[ ${{matrix.provider}} == TFP0 ]]; then + cp control.tfp0 control + USE_TFP0=1 make package FINALPACKAGE=1 + elif [[ ${{matrix.provider}} == LIBKRW ]]; then + cp control.krw control + USE_LIBKRW=1 make package FINALPACKAGE=1 + elif [[ ${{matrix.provider}} == LIBKERNRW ]]; then + cp control.kernrw control + USE_LIBKERNRW=1 make package FINALPACKAGE=1 + fi env: DEVELOPER_DIR: /Applications/Xcode_14.2.app/Contents/Developer # LDFLAGS: "-L/usr/local/opt/llvm/lib" diff --git a/control.kernrw b/control.kernrw new file mode 100644 index 0000000..91537d1 --- /dev/null +++ b/control.kernrw @@ -0,0 +1,10 @@ +Package: dev.und3fy.foulfolder.tauri +Name: foulfolder (Tauri) +Version: 0.1.4 +Architecture: iphoneos-arm +Depends: applist,zip,libkernrw0 +Description: Directly decrypt binaries like fouldecrypt, but also supports iOS 14 +Maintainer: und3fined +Author: misty +Section: System +Tag: role::hacker diff --git a/control.krw b/control.krw new file mode 100644 index 0000000..62378c3 --- /dev/null +++ b/control.krw @@ -0,0 +1,10 @@ +Package: dev.und3fy.foulfolder.unc0ver +Name: foulfolder (unc0ver) +Version: 0.1.4 +Architecture: iphoneos-arm +Depends: applist,zip,libkrw +Description: Directly decrypt binaries like fouldecrypt, but also supports iOS 14 +Maintainer: und3fined +Author: misty +Section: System +Tag: role::hacker diff --git a/control.template b/control.tfp0 similarity index 84% rename from control.template rename to control.tfp0 index 3f0056f..f34e17d 100644 --- a/control.template +++ b/control.tfp0 @@ -1,8 +1,8 @@ Package: dev.und3fy.foulfolder Name: foulfolder -Version: 0.1.3 +Version: 0.1.4 Architecture: iphoneos-arm -Depends: applist,zip,libkrw +Depends: applist,zip Description: Directly decrypt binaries like fouldecrypt, but also supports iOS 14 Maintainer: und3fined Author: misty From 5ecaf7b1bde6facdf8eb96318037f3ccd44291bc Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 10 Jan 2025 14:59:02 +0700 Subject: [PATCH 154/155] Squashed commit of the following: commit 17bfdfd4d9cf3a6f3d8800a83236fabecc793e81 Author: und3fined Date: Fri Jan 10 14:48:11 2025 +0700 fix: inmvalid syntax commit e99b3fb13039d342b3c150bd83f00b533f6f8430 Author: und3fined Date: Fri Jan 10 14:44:11 2025 +0700 chore: support enable verbose in command commit 90fa1e2e6ec1d55540c1a183a2f7b5b79de9f276 Author: und3fined Date: Fri Jan 10 14:20:34 2025 +0700 chore: revert perror mremap_encrypted commit 4dad42d62f9e7c1ddc76a969f8ef54c28e5897e8 Author: und3fined Date: Fri Jan 10 14:04:06 2025 +0700 fix: missing file c commit 2b67c315d6f66df5daa6380cff176c6fc0ea4803 Author: und3fined Date: Fri Jan 10 13:59:42 2025 +0700 debug more commit b187b8144189a9a0aff81f17f93b1a31af082923 Author: und3fined Date: Fri Jan 10 13:28:31 2025 +0700 chore: enable debug commit d37ace2e881e333d1e87ff70c80405c615d2298f Author: und3fined Date: Fri Jan 10 13:07:43 2025 +0700 chore: debug foulfolder --- .github/workflows/build-deb.yml | 2 +- Makefile | 10 +- control.krw | 2 +- fouldlopen.c | 11 + foulfolder.m | 166 ++++++--- main.cpp | 593 +++++++++++++++++--------------- 6 files changed, 448 insertions(+), 336 deletions(-) create mode 100644 fouldlopen.c diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index fc9628e..81bb894 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -8,7 +8,7 @@ jobs: runs-on: macos-13 strategy: matrix: - provider: [TFP0, LIBKRW, LIBKERNRW] + provider: [LIBKRW] steps: - uses: actions/checkout@v2 diff --git a/Makefile b/Makefile index 540667b..93c0690 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ export ADDITIONAL_CFLAGS = -DTHEOS_LEAN_AND_MEAN -fobjc-arc include $(THEOS)/makefiles/common.mk -TOOL_NAME = fouldecrypt flexdecrypt2 foulwrapper foulfolder +TOOL_NAME = fouldecrypt flexdecrypt2 foulwrapper foulfolder fouldlopen fouldecrypt_FILES = main.cpp foulmain.cpp fouldecrypt_CFLAGS = -fobjc-arc -Wno-unused-variable -Ipriv_include @@ -39,10 +39,8 @@ foulfolder_CCFLAGS = $(foulfolder_CFLAGS) foulfolder_CODESIGN_FLAGS = -Sentitlements.plist foulfolder_INSTALL_PATH = /usr/local/bin foulfolder_FRAMEWORKS = Foundation MobileCoreServices -# foulfolder_PRIVATE_FRAMEWORKS = MobileContainerManager -# foulfolder_LIBRARIES = applist -include $(THEOS_MAKE_PATH)/tool.mk +fouldlopen_FILES = fouldlopen.c +fouldlopen_INSTALL_PATH = /usr/local/bin -after-install:: - install.exec "cp -f /usr/local/bin/fouldecrypt /bin/fouldecrypt" +include $(THEOS_MAKE_PATH)/tool.mk diff --git a/control.krw b/control.krw index 62378c3..d336641 100644 --- a/control.krw +++ b/control.krw @@ -1,6 +1,6 @@ Package: dev.und3fy.foulfolder.unc0ver Name: foulfolder (unc0ver) -Version: 0.1.4 +Version: 0.1.5d Architecture: iphoneos-arm Depends: applist,zip,libkrw Description: Directly decrypt binaries like fouldecrypt, but also supports iOS 14 diff --git a/fouldlopen.c b/fouldlopen.c new file mode 100644 index 0000000..35fa05b --- /dev/null +++ b/fouldlopen.c @@ -0,0 +1,11 @@ +#include +#include + +int main(int argc, char **argv) { + void *(*sym_dlopen)(const char *, int) = dlsym(RTLD_DEFAULT, "dlopen"); + for (int i = 1; i < argc; i++) { + void *handle = sym_dlopen(argv[i], RTLD_NOW); + dlclose(handle); + } + return 0; +} diff --git a/foulfolder.m b/foulfolder.m index 1155c69..32fd09b 100644 --- a/foulfolder.m +++ b/foulfolder.m @@ -26,66 +26,103 @@ extern char **environ; +static NSString *shared_shell_path(void) +{ + static NSString *_sharedShellPath = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ @autoreleasepool { + NSArray *possibleShells = @[ + @"/usr/bin/bash", + @"/bin/bash", + @"/usr/bin/sh", + @"/bin/sh", + @"/usr/bin/zsh", + @"/bin/zsh", + @"/var/jb/usr/bin/bash", + @"/var/jb/bin/bash", + @"/var/jb/usr/bin/sh", + @"/var/jb/bin/sh", + @"/var/jb/usr/bin/zsh", + @"/var/jb/bin/zsh", + ]; + NSFileManager *fileManager = [NSFileManager defaultManager]; + for (NSString *shellPath in possibleShells) { + // check if the shell exists and is regular file (not symbolic link) and executable + NSDictionary *shellAttrs = [fileManager attributesOfItemAtPath:shellPath error:nil]; + if ([shellAttrs[NSFileType] isEqualToString:NSFileTypeSymbolicLink]) { + continue; + } + if (![fileManager isExecutableFileAtPath:shellPath]) { + continue; + } + _sharedShellPath = shellPath; + break; + } + } }); + return _sharedShellPath; +} + int my_system(const char *ctx) { - const char *args[] = { - "/bin/sh", - "-c", - ctx, - NULL - }; - pid_t pid; - int posix_status = posix_spawn(&pid, "/bin/sh", NULL, NULL, (char **) args, environ); - if (posix_status != 0) + const char *shell_path = [shared_shell_path() UTF8String]; + const char *args[] = { + shell_path, + "-c", + ctx, + NULL + }; + pid_t pid; + int posix_status = posix_spawn(&pid, shell_path, NULL, NULL, (char **) args, environ); + if (posix_status != 0) + { + errno = posix_status; + fprintf(stderr, "posix_spawn, %s (%d)\n", strerror(errno), errno); + return posix_status; + } + pid_t w; + int status; + do + { + w = waitpid(pid, &status, WUNTRACED | WCONTINUED); + if (w == -1) { - errno = posix_status; - fprintf(stderr, "posix_spawn, %s (%d)\n", strerror(errno), errno); - return posix_status; + fprintf(stderr, "waitpid %d, %s (%d)\n", pid, strerror(errno), errno); + return errno; } - pid_t w; - int status; - do + if (WIFEXITED(status)) { - w = waitpid(pid, &status, WUNTRACED | WCONTINUED); - if (w == -1) - { - fprintf(stderr, "waitpid %d, %s (%d)\n", pid, strerror(errno), errno); - return errno; - } - if (WIFEXITED(status)) - { - if (WEXITSTATUS(status) != 0) - { - fprintf(stderr, "pid %d, exited with status %d\n", pid, WEXITSTATUS(status)); - return WEXITSTATUS(status); - } - } - else if (WIFSIGNALED(status)) - { - fprintf(stderr, "pid %d killed by signal %d\n", pid, WTERMSIG(status)); - } - else if (WIFSTOPPED(status)) - { - fprintf(stderr, "pid %d stopped by signal %d\n", pid, WSTOPSIG(status)); - } - // else if (WIFCONTINUED(status)) - // { - // // fprintf(stderr, "pid %d continued\n", pid); - // } + if (WEXITSTATUS(status) != 0) + { + fprintf(stderr, "pid %d, exited with status %d\n", pid, WEXITSTATUS(status)); + return WEXITSTATUS(status); + } + } + else if (WIFSIGNALED(status)) + { + fprintf(stderr, "pid %d killed by signal %d\n", pid, WTERMSIG(status)); } - while (!WIFEXITED(status) && !WIFSIGNALED(status)); - if (WIFSIGNALED(status)) + else if (WIFSTOPPED(status)) { - return WTERMSIG(status); + fprintf(stderr, "pid %d stopped by signal %d\n", pid, WSTOPSIG(status)); } - return WEXITSTATUS(status); + // else if (WIFCONTINUED(status)) + // { + // // fprintf(stderr, "pid %d continued\n", pid); + // } + } + while (!WIFEXITED(status) && !WIFSIGNALED(status)); + if (WIFSIGNALED(status)) + { + return WTERMSIG(status); + } + return WEXITSTATUS(status); } NSString * escape_arg(NSString *arg) { - return [arg stringByReplacingOccurrencesOfString:@"\'" withString:@"'\\\''"]; + return [arg stringByReplacingOccurrencesOfString:@"\'" withString:@"'\\\''"]; } int @@ -93,19 +130,30 @@ { if (argc < 2) { - fprintf(stderr, "usage: foulfolder \n"); + fprintf(stderr, "usage: foulfolder [-v] \n"); return 1; } - NSString *internalAppPath = @"/private/var/containers/Bundle/Application/"; + if (argc == 3 && strcmp(argv[1], "-v") == 0) + { + VERBOSE = 1; + argv++; + } + + NSString *internalAppPath = @"/var/containers/Bundle/Application/"; NSString *keyItemName = @"itemName"; NSString *keyBundleId = @"softwareVersionBundleId"; BOOL isAppPath = NO; // check argument is path or bundle id. // path always start with /private/var/containers/Bundle/Application - if (strncmp(argv[1], [internalAppPath UTF8String], internalAppPath.length) == 0) - { + + // private var path always start with /private/var and join with internalAppPath + NSString *privateVarAppPath = [@"/private" stringByAppendingPathComponent:internalAppPath]; + if ( + strncmp(argv[1], [internalAppPath UTF8String], internalAppPath.length) == 0 || + strncmp(argv[1], [privateVarAppPath UTF8String], privateVarAppPath.length) == 0 + ) { isAppPath = YES; } @@ -206,8 +254,22 @@ NSString *objectRawPath = [targetPath stringByAppendingPathComponent:objectPath]; int decryptStatus = - my_system([[NSString stringWithFormat:@"fouldecrypt '%@' '%@'", escape_arg(objectRawPath), escape_arg( - objectFullPath)] UTF8String]); + my_system([[NSString stringWithFormat:@"fouldlopen '%@'", escape_arg(objectRawPath)] UTF8String]); + + if (VERBOSE) { + decryptStatus = my_system([[ + NSString stringWithFormat:@"fouldecrypt -v '%@' '%@'", + escape_arg(objectRawPath), + escape_arg(objectFullPath) + ] UTF8String]); + } else { + decryptStatus = my_system([[ + NSString stringWithFormat:@"fouldecrypt '%@' '%@'", + escape_arg(objectRawPath), + escape_arg(objectFullPath) + ] UTF8String]); + } + if (decryptStatus != 0) { didError = decryptStatus; fprintf(stderr, "[dump] %s: Failed\n", [objectPath UTF8String]); diff --git a/main.cpp b/main.cpp index 809b7ed..211bd7c 100644 --- a/main.cpp +++ b/main.cpp @@ -1,18 +1,18 @@ #include #include +#include +#include +#include +#include +#include #include #include #include #include #include -#include -#include -#include -#include -#include -#include #include -#include +#include +#include #include @@ -23,314 +23,355 @@ #define EXEC_PAGE_SIZE 0x1000 int VERBOSE = 0; -#define DLOG(f_, ...) \ -{ \ - if (VERBOSE) { \ - struct tm _tm123_; \ - struct timeval _xxtv123_; \ - gettimeofday(&_xxtv123_, NULL); \ - localtime_r(&_xxtv123_.tv_sec, &_tm123_); \ - printf("%02d:%02d:%02d.%06d\t", _tm123_.tm_hour, _tm123_.tm_min, _tm123_.tm_sec, _xxtv123_.tv_usec); \ - printf((f_), ##__VA_ARGS__); \ - printf("\n"); \ - } \ -}; - - -static uint8_t* -map(const char *path, bool _mutable, size_t *size, int *descriptor) -{ - int f = open(path, _mutable ? O_CREAT | O_TRUNC | O_RDWR : O_RDONLY, 0755); - if (f < 0) { - perror(_mutable ? "open(map-ro)" : "open(map-rw)"); - return NULL; - } - - if (_mutable) { - if (ftruncate(f, *size) < 0) { - perror("ftruncate(map)"); - return NULL; - } +#define DLOG(f_, ...) \ + { \ + if (VERBOSE) { \ + struct tm _tm123_; \ + struct timeval _xxtv123_; \ + gettimeofday(&_xxtv123_, NULL); \ + localtime_r(&_xxtv123_.tv_sec, &_tm123_); \ + printf("%02d:%02d:%02d.%06d\t", _tm123_.tm_hour, _tm123_.tm_min, \ + _tm123_.tm_sec, _xxtv123_.tv_usec); \ + printf((f_), ##__VA_ARGS__); \ + printf("\n"); \ + } \ + }; + +static uint8_t *map(const char *path, bool _mutable, size_t *size, + int *descriptor) { + int f = open(path, _mutable ? O_CREAT | O_TRUNC | O_RDWR : O_RDONLY, 0755); + if (f < 0) { + perror(_mutable ? "open(map-ro)" : "open(map-rw)"); + return NULL; + } + + if (_mutable) { + if (ftruncate(f, *size) < 0) { + perror("ftruncate(map)"); + return NULL; } - - struct stat s; - if (fstat(f, &s) < 0) { - perror("fstat(map)"); - close(f); - return NULL; - } - - uint8_t *base = (uint8_t *)mmap(NULL, s.st_size, _mutable ? PROT_READ | PROT_WRITE : PROT_READ, - _mutable ? MAP_SHARED : MAP_PRIVATE, f, 0); - if (base == MAP_FAILED) { - perror(_mutable ? "mmap(map-ro)" : "mmap(map-rw)"); - close(f); - return NULL; - } - - *size = s.st_size; - if (descriptor) { - *descriptor = f; - } else { - close(f); - } - return base; + } + + struct stat s; + if (fstat(f, &s) < 0) { + perror("fstat(map)"); + close(f); + return NULL; + } + + uint8_t *base = (uint8_t *)mmap(NULL, s.st_size, + _mutable ? PROT_READ | PROT_WRITE : PROT_READ, + _mutable ? MAP_SHARED : MAP_PRIVATE, f, 0); + if (base == MAP_FAILED) { + perror(_mutable ? "mmap(map-ro)" : "mmap(map-rw)"); + close(f); + return NULL; + } + + *size = s.st_size; + if (descriptor) { + *descriptor = f; + } else { + close(f); + } + return base; } bool has_prep_kernel = false; int prepare_kernel() { - if (!has_prep_kernel) { - int ret = init_kerninfra(KERNLOG_NONE); - if (ret) return ret; - has_prep_kernel = true; - } - return 0; + if (!has_prep_kernel) { + int ret = init_kerninfra(KERNLOG_NONE); + if (ret) + return ret; + has_prep_kernel = true; + } + return 0; } -extern "C" int mremap_encrypted(void*, size_t, uint32_t, uint32_t, uint32_t); - -extern "C" kern_return_t mach_vm_remap(vm_map_t, mach_vm_address_t *, mach_vm_size_t, - mach_vm_offset_t, int, vm_map_t, mach_vm_address_t, - boolean_t, vm_prot_t *, vm_prot_t *, vm_inherit_t); - -void *__mmap(const char *info, void *base, size_t size, int prot, int flags, int fd, size_t off) { - DLOG("-->> %s mmaping(%p, 0x%zx, %d, 0x%x, %d, 0x%zx)", info, base, size, prot, flags, fd, off); - void *ret = mmap(base, size, prot, flags, fd, off); - if (ret == MAP_FAILED) { - perror("mmap"); - } - DLOG("<<-- %s mmaping(%p, 0x%zx, %d, 0x%x, %d, 0x%zx) = %p", info, base, size, prot, flags, fd, off, ret); - return ret; +extern "C" int mremap_encrypted(void *, size_t, uint32_t, uint32_t, uint32_t); + +extern "C" kern_return_t mach_vm_remap(vm_map_t, mach_vm_address_t *, + mach_vm_size_t, mach_vm_offset_t, int, + vm_map_t, mach_vm_address_t, boolean_t, + vm_prot_t *, vm_prot_t *, vm_inherit_t); + +void *__mmap(const char *info, void *base, size_t size, int prot, int flags, + int fd, size_t off) { + DLOG("-->> %s mmaping(%p, 0x%zx, %d, 0x%x, %d, 0x%zx)", info, base, size, + prot, flags, fd, off); + void *ret = mmap(base, size, prot, flags, fd, off); + if (ret == MAP_FAILED) { + perror("mmap"); + } + DLOG("<<-- %s mmaping(%p, 0x%zx, %d, 0x%x, %d, 0x%zx) = %p", info, base, size, + prot, flags, fd, off, ret); + return ret; } -int __mremap_encrypted(const char *info, void *base, size_t cryptsize, uint32_t cryptid, uint32_t cpuType, uint32_t cpuSubType) { - DLOG("<<-- %s mremap_encrypted(%p, 0x%zx, %d, 0x%x, 0x%x)", info, base, cryptsize, cryptid, cpuType, cpuSubType); - int ret = mremap_encrypted(base, cryptsize, cryptid, cpuType, cpuSubType); - if (ret) { - perror("mremap_encrypted"); - } - DLOG("-->> %s mremap_encrypted(%p, 0x%zx, %d, 0x%x, 0x%x) = %d", info, base, cryptsize, cryptid, cpuType, cpuSubType, ret); - return ret; +int __mremap_encrypted(const char *info, void *base, size_t cryptsize, + uint32_t cryptid, uint32_t cpuType, + uint32_t cpuSubType) { + DLOG("<<-- %s mremap_encrypted(%p, 0x%zx, %d, 0x%x, 0x%x)", info, base, + cryptsize, cryptid, cpuType, cpuSubType); + int ret = mremap_encrypted(base, cryptsize, cryptid, cpuType, cpuSubType); + if (ret) { + perror("mremap_encrypted"); + } + DLOG("-->> %s mremap_encrypted(%p, 0x%zx, %d, 0x%x, 0x%x) = %d", info, base, + cryptsize, cryptid, cpuType, cpuSubType, ret); + return ret; } #define LOGINDENT " " void debugprint_vme(addr_t _vmentry) { - auto encVmEntry = _vm_map_entry_p(_vmentry); - DLOG(LOGINDENT"mmaped entry: %p - %p", (void *)encVmEntry.start().load(), (void *)encVmEntry.end().load()); - DLOG(LOGINDENT"mmaped vme_offset: 0x%llx", encVmEntry.vme_offset().load()); - DLOG(LOGINDENT"mmaped vme_flags: 0x%x", encVmEntry.vme_flags().load()); - DLOG(LOGINDENT"mmaped vme_object: 0x%llx", encVmEntry.vme_object().load()); + auto encVmEntry = _vm_map_entry_p(_vmentry); + DLOG(LOGINDENT "mmaped entry: %p - %p", (void *)encVmEntry.start().load(), + (void *)encVmEntry.end().load()); + DLOG(LOGINDENT "mmaped vme_offset: 0x%llx", encVmEntry.vme_offset().load()); + DLOG(LOGINDENT "mmaped vme_flags: 0x%x", encVmEntry.vme_flags().load()); + DLOG(LOGINDENT "mmaped vme_object: 0x%llx", encVmEntry.vme_object().load()); } void debugprint_vmobj(addr_t _vmobj) { - auto vmobj = vm_object_t_p(_vmobj); - DLOG(LOGINDENT"mmaped vmobj *shadow: %p **shadow: %p", (void *)vmobj.shadow().load_addr(), (void *)vmobj.shadow().shadow().load_addr()); - DLOG(LOGINDENT"mmaped vmobj pager: %p shadow pager: %p", (void *)vmobj.pager().load_addr(), (void *)vmobj.shadow().pager().load_addr()); - DLOG(LOGINDENT"mmaped vmobj shadow pager op: %p", (void *)vmobj.shadow().pager().mo_pager_ops().load_addr()); + auto vmobj = vm_object_t_p(_vmobj); + DLOG(LOGINDENT "mmaped vmobj *shadow: %p **shadow: %p", + (void *)vmobj.shadow().load_addr(), + (void *)vmobj.shadow().shadow().load_addr()); + DLOG(LOGINDENT "mmaped vmobj pager: %p shadow pager: %p", + (void *)vmobj.pager().load_addr(), + (void *)vmobj.shadow().pager().load_addr()); + DLOG(LOGINDENT "mmaped vmobj shadow pager op: %p", + (void *)vmobj.shadow().pager().mo_pager_ops().load_addr()); } void debugprint_pager(addr_t _pager) { - auto applePager = apple_protect_pager_t_p(_pager); - DLOG(LOGINDENT"mmaped vme_object apple protect pager: ", NULL) - DLOG(LOGINDENT" backingOff %llx", applePager.backing_offset().load()) - DLOG(LOGINDENT" cryptoBackingOff %llx", applePager.crypto_backing_offset().load()) - DLOG(LOGINDENT" cryptoStart %llx", applePager.crypto_start().load()) - DLOG(LOGINDENT" cryptoEnd %llx", applePager.crypto_end().load()) - DLOG(LOGINDENT" cryptInfo %p", (void *)applePager.crypt_info().load()) + auto applePager = apple_protect_pager_t_p(_pager); + DLOG(LOGINDENT "mmaped vme_object apple protect pager: ", NULL) + DLOG(LOGINDENT " backingOff %llx", applePager.backing_offset().load()) + DLOG(LOGINDENT " cryptoBackingOff %llx", + applePager.crypto_backing_offset().load()) + DLOG(LOGINDENT " cryptoStart %llx", applePager.crypto_start().load()) + DLOG(LOGINDENT " cryptoEnd %llx", applePager.crypto_end().load()) + DLOG(LOGINDENT " cryptInfo %p", (void *)applePager.crypt_info().load()) } #undef LOGINDENT -static int -unprotect(int f, uint8_t *dupe, int cpuType, int cpuSubType, struct encryption_info_command *info, size_t macho_off) -{ +static int unprotect(int f, uint8_t *dupe, int cpuType, int cpuSubType, + struct encryption_info_command *info, size_t macho_off) { #define LOGINDENT " " - assert((info->cryptoff & (EXEC_PAGE_SIZE - 1)) == 0); - - DLOG(LOGINDENT"Going to decrypt crypt page: off 0x%x size 0x%x cryptid %d, cpuType %x cpuSubType %x", info->cryptoff, info->cryptsize, info->cryptid, cpuType, cpuSubType); - //getchar(); - - size_t off_aligned = info->cryptoff & ~(PAGE_SIZE - 1); - //size_t size_aligned = info->cryptsize + info->cryptoff - off_aligned; - size_t map_padding = info->cryptoff - off_aligned; - - int err = 0; - void *decryptedBuf = malloc(info->cryptsize); - - if (!(info->cryptoff & (PAGE_SIZE - 1))) { - DLOG(LOGINDENT"Already 16k aligned, directly go ahead :)"); - void *cryptbase = __mmap("16k-aligned", NULL, info->cryptsize, PROT_READ | PROT_EXEC, MAP_PRIVATE, f, info->cryptoff + macho_off); - // old-school mremap_encrypted - if (__mremap_encrypted("unprotect", cryptbase, info->cryptsize, info->cryptid, cpuType, cpuSubType)) { - munmap(cryptbase, info->cryptsize); - return 1; - } - DLOG(LOGINDENT" copying %p to %p, size %x", (char *)decryptedBuf, cryptbase, info->cryptsize); - memmove(decryptedBuf, cryptbase, info->cryptsize); - munmap(cryptbase, info->cryptsize); + assert((info->cryptoff & (EXEC_PAGE_SIZE - 1)) == 0); + + DLOG(LOGINDENT "Going to decrypt crypt page: off 0x%x size 0x%x cryptid %d, " + "cpuType %x cpuSubType %x", + info->cryptoff, info->cryptsize, info->cryptid, cpuType, cpuSubType); + // getchar(); + + size_t off_aligned = info->cryptoff & ~(PAGE_SIZE - 1); + // size_t size_aligned = info->cryptsize + info->cryptoff - off_aligned; + size_t map_padding = info->cryptoff - off_aligned; + + int err = 0; + void *decryptedBuf = malloc(info->cryptsize); + + if (!(info->cryptoff & (PAGE_SIZE - 1))) { + DLOG(LOGINDENT "Already 16k aligned, directly go ahead :)"); + void *cryptbase = + __mmap("16k-aligned", NULL, info->cryptsize, PROT_READ | PROT_EXEC, + MAP_PRIVATE, f, info->cryptoff + macho_off); + // old-school mremap_encrypted + if (__mremap_encrypted("unprotect", cryptbase, info->cryptsize, + info->cryptid, cpuType, cpuSubType) == 1) { + munmap(cryptbase, info->cryptsize); + return 1; + } + DLOG(LOGINDENT " copying %p to %p, size %x", (char *)decryptedBuf, + cryptbase, info->cryptsize); + memmove(decryptedBuf, cryptbase, info->cryptsize); + munmap(cryptbase, info->cryptsize); + } else { + DLOG(LOGINDENT "Not 16k aligned, trying to do the hack :O"); + + if (!!prepare_kernel()) { + fprintf(stderr, "Failed to init kerninfra!!\n"); + exit(1); } else { - DLOG(LOGINDENT"Not 16k aligned, trying to do the hack :O"); - - if (!!prepare_kernel()) { - fprintf(stderr, "Failed to init kerninfra!!\n"); - exit(1); - } else { - DLOG(LOGINDENT"successfully initialized kerninfra!"); - } - - for (size_t off = off_aligned; off < info->cryptoff + info->cryptsize; off += PAGE_SIZE) { - size_t off_end = MIN(off + PAGE_SIZE, info->cryptoff + info->cryptsize); - size_t curMapLen = (off_end - off) & (PAGE_SIZE - 1); if (!curMapLen) curMapLen = PAGE_SIZE; - size_t inPageStart = off < info->cryptoff ? info->cryptoff - off : 0; - size_t inPageEnd = curMapLen; - size_t cryptOff = off + inPageStart; - DLOG(LOGINDENT" processing file off %lx-%lx, curPage len: %lx, inPageStart: %lx, inPageEnd: %lx", off, off_end, curMapLen, inPageStart, inPageEnd); - char *cryptbase = (char *)__mmap("directly 16k-aligned mmap", NULL, curMapLen, PROT_READ | PROT_EXEC, MAP_PRIVATE, f, off + macho_off); - - if (__mremap_encrypted("unprotect", cryptbase, curMapLen, info->cryptid, cpuType, cpuSubType)) { - munmap(cryptbase, curMapLen); - return 1; - } - - auto curp = proc_t_p(current_proc()); - addr_t _encVmEntry = lookup_vm_map_entry(curp.task()._map().load_addr(), (addr_t)(cryptbase)); - DLOG(LOGINDENT" Got mmaped entry: %p", (void*)_encVmEntry); - debugprint_vme(_encVmEntry); - - auto encVmEntry = _vm_map_entry_p(_encVmEntry); - auto vmobj = encVmEntry.vme_object(); - debugprint_vmobj(vmobj.load_addr()); - auto applePager = apple_protect_pager_t_p(vmobj.shadow().pager().load_addr()); - DLOG(LOGINDENT" mmaped vme_object apple protect pager: ", NULL); - debugprint_pager(applePager.addr()); - - applePager.crypto_backing_offset().store(macho_off + cryptOff); - applePager.crypto_start().store(inPageStart); - - DLOG(LOGINDENT" patched mmaped vme_object apple protect pager: ", NULL) - debugprint_pager(applePager.addr()); - - DLOG(LOGINDENT" copying %p to %p, size %lx", (char *)decryptedBuf + cryptOff - info->cryptoff, cryptbase + inPageStart, curMapLen - inPageStart); - memmove((char *)decryptedBuf + cryptOff - info->cryptoff, cryptbase + inPageStart, curMapLen - inPageStart); - - munmap(cryptbase, curMapLen); - } + DLOG(LOGINDENT "successfully initialized kerninfra!"); } - if (err) { + for (size_t off = off_aligned; off < info->cryptoff + info->cryptsize; + off += PAGE_SIZE) { + size_t off_end = MIN(off + PAGE_SIZE, info->cryptoff + info->cryptsize); + size_t curMapLen = (off_end - off) & (PAGE_SIZE - 1); + if (!curMapLen) + curMapLen = PAGE_SIZE; + size_t inPageStart = off < info->cryptoff ? info->cryptoff - off : 0; + size_t inPageEnd = curMapLen; + size_t cryptOff = off + inPageStart; + DLOG(LOGINDENT " processing file off %lx-%lx, curPage len: %lx, " + "inPageStart: %lx, inPageEnd: %lx", + off, off_end, curMapLen, inPageStart, inPageEnd); + char *cryptbase = (char *)__mmap("directly 16k-aligned mmap", NULL, + curMapLen, PROT_READ | PROT_EXEC, + MAP_PRIVATE, f, off + macho_off); + + if (__mremap_encrypted("unprotect", cryptbase, curMapLen, info->cryptid, + cpuType, cpuSubType)) { + munmap(cryptbase, curMapLen); return 1; + } + + auto curp = proc_t_p(current_proc()); + addr_t _encVmEntry = lookup_vm_map_entry(curp.task()._map().load_addr(), + (addr_t)(cryptbase)); + DLOG(LOGINDENT " Got mmaped entry: %p", (void *)_encVmEntry); + debugprint_vme(_encVmEntry); + + auto encVmEntry = _vm_map_entry_p(_encVmEntry); + auto vmobj = encVmEntry.vme_object(); + debugprint_vmobj(vmobj.load_addr()); + auto applePager = + apple_protect_pager_t_p(vmobj.shadow().pager().load_addr()); + DLOG(LOGINDENT " mmaped vme_object apple protect pager: ", NULL); + debugprint_pager(applePager.addr()); + + applePager.crypto_backing_offset().store(macho_off + cryptOff); + applePager.crypto_start().store(inPageStart); + + DLOG(LOGINDENT " patched mmaped vme_object apple protect pager: ", + NULL) + debugprint_pager(applePager.addr()); + + DLOG(LOGINDENT " copying %p to %p, size %lx", + (char *)decryptedBuf + cryptOff - info->cryptoff, + cryptbase + inPageStart, curMapLen - inPageStart); + memmove((char *)decryptedBuf + cryptOff - info->cryptoff, + cryptbase + inPageStart, curMapLen - inPageStart); + + munmap(cryptbase, curMapLen); } + } - DLOG(LOGINDENT"copying enc pages, size: 0x%x..", info->cryptsize); - memcpy(dupe + info->cryptoff, decryptedBuf, info->cryptsize); + if (err) { + return 1; + } - DLOG(LOGINDENT"cleaning up..."); - free(decryptedBuf); - return 0; + DLOG(LOGINDENT "copying enc pages, size: 0x%x..", info->cryptsize); + memcpy(dupe + info->cryptoff, decryptedBuf, info->cryptsize); + + DLOG(LOGINDENT "cleaning up..."); + free(decryptedBuf); + return 0; #undef LOGINDENT } -int -decrypt_macho_slide(int f, uint8_t *inputData, uint8_t *outputData, size_t macho_off) { +int decrypt_macho_slide(int f, uint8_t *inputData, uint8_t *outputData, + size_t macho_off) { #define LOGINDENT " " - uint32_t offset = 0; - int cpuType = 0, cpuSubType = 0; - int ncmds = 0; - if (*(uint32_t *)inputData == MH_MAGIC_64) { // 64bit - struct mach_header_64* header = (struct mach_header_64*) inputData; - cpuType = header->cputype; - cpuSubType = header->cpusubtype; - ncmds = header->ncmds; - offset = sizeof(struct mach_header_64); - } else if (*(uint32_t *)inputData == MH_MAGIC) { // 32bit - struct mach_header* header = (struct mach_header*) inputData; - cpuType = header->cputype; - cpuSubType = header->cpusubtype; - ncmds = header->ncmds; - offset = sizeof(struct mach_header); + uint32_t offset = 0; + int cpuType = 0, cpuSubType = 0; + int ncmds = 0; + if (*(uint32_t *)inputData == MH_MAGIC_64) { // 64bit + struct mach_header_64 *header = (struct mach_header_64 *)inputData; + cpuType = header->cputype; + cpuSubType = header->cpusubtype; + ncmds = header->ncmds; + offset = sizeof(struct mach_header_64); + } else if (*(uint32_t *)inputData == MH_MAGIC) { // 32bit + struct mach_header *header = (struct mach_header *)inputData; + cpuType = header->cputype; + cpuSubType = header->cpusubtype; + ncmds = header->ncmds; + offset = sizeof(struct mach_header); + } + + DLOG(LOGINDENT "finding encryption_info segment in slide..."); + + // Enumerate all load commands and check for the encryption header, if found + // start "unprotect"'ing the contents. + + struct encryption_info_command *encryption_info = + NULL; // for both 32bit and 64bit macho, the command layout are the same + for (uint32_t i = 0; i < ncmds; i++) { + struct load_command *command = (struct load_command *)(inputData + offset); + + if (command->cmd == LC_ENCRYPTION_INFO || + command->cmd == LC_ENCRYPTION_INFO_64) { + DLOG(LOGINDENT " found encryption_info segment at offset %x", offset); + encryption_info = (struct encryption_info_command *)command; + // There should only be ONE header present anyways, so stop after + // the first one. + // + break; } - DLOG(LOGINDENT"finding encryption_info segment in slide..."); - - // Enumerate all load commands and check for the encryption header, if found - // start "unprotect"'ing the contents. - - struct encryption_info_command *encryption_info = NULL; // for both 32bit and 64bit macho, the command layout are the same - for (uint32_t i = 0; i < ncmds; i++) { - struct load_command* command = (struct load_command*) (inputData + offset); - - if (command->cmd == LC_ENCRYPTION_INFO || command->cmd == LC_ENCRYPTION_INFO_64) { - DLOG(LOGINDENT" found encryption_info segment at offset %x", offset); - encryption_info = (struct encryption_info_command*) command; - // There should only be ONE header present anyways, so stop after - // the first one. - // - break; - } - - offset += command->cmdsize; - } - if (!encryption_info || !encryption_info->cryptid) { - DLOG(LOGINDENT"this slide is not encrypted!"); - return 0; - } - - // If "unprotect"'ing is successful, then change the "cryptid" so that - // the loader does not attempt to decrypt decrypted pages. - // - - DLOG(LOGINDENT"decrypting encrypted data..."); - if (unprotect(f, outputData, cpuType, cpuSubType, encryption_info, macho_off) == 0) { - encryption_info = (struct encryption_info_command*) (outputData + offset); - encryption_info->cryptid = 0; - } else { - return 1; - } - + offset += command->cmdsize; + } + if (!encryption_info || !encryption_info->cryptid) { + DLOG(LOGINDENT "this slide is not encrypted!"); return 0; + } + + // If "unprotect"'ing is successful, then change the "cryptid" so that + // the loader does not attempt to decrypt decrypted pages. + // + + DLOG(LOGINDENT "decrypting encrypted data..."); + if (unprotect(f, outputData, cpuType, cpuSubType, encryption_info, + macho_off) == 0) { + encryption_info = (struct encryption_info_command *)(outputData + offset); + encryption_info->cryptid = 0; + } else { + return 1; + } + + return 0; #undef LOGINDENT } -int -decrypt_macho(const char *inputFile, const char *outputFile) -{ - DLOG("mapping input file: %s", inputFile); - size_t base_size; - int f; - uint8_t *base = map(inputFile, false, &base_size, &f); - if (base == NULL) { - return 1; - } - - DLOG("mapping output file: %s", outputFile); - size_t dupe_size = base_size; - uint8_t *dupe = map(outputFile, true, &dupe_size, NULL); - if (dupe == NULL) { - munmap(base, base_size); - return 1; - } - - DLOG("copying original data of size 0x%zx...", base_size); - memcpy(dupe, base, base_size); - - if (*(uint32_t *)base == FAT_CIGAM || *(uint32_t *)base == FAT_MAGIC) { - bool isBe = *(uint32_t *)base == FAT_CIGAM; - struct fat_header *fat_header = (struct fat_header *) base; - struct fat_arch *fatarches = (struct fat_arch *) (fat_header + 1); - auto fatInt = [isBe](int t) -> int {return isBe ? OSSwapInt32(t) : t;}; - - DLOG("handling %d fat arches...", fatInt(fat_header->nfat_arch)); - for (int fat_i = 0; fat_i < fatInt(fat_header->nfat_arch); fat_i++) { - auto curFatArch = &fatarches[fat_i]; - DLOG(" handling fat arch %d, cpuType 0x%x, cpuSubType 0x%x, fileOff 0x%x, size 0x%x, align 0x%x", fat_i, - fatInt(curFatArch->cputype), fatInt(curFatArch->cpusubtype), fatInt(curFatArch->offset), fatInt(curFatArch->size), fatInt(curFatArch->align)); - decrypt_macho_slide(f, base + fatInt(curFatArch->offset), dupe + fatInt(curFatArch->offset), fatInt(curFatArch->offset)); - } - } else { - DLOG(" not fat binary, directly decrypting it!"); - decrypt_macho_slide(f, base, dupe, 0); - } - +int decrypt_macho(const char *inputFile, const char *outputFile) { + DLOG("mapping input file: %s", inputFile); + size_t base_size; + int f; + uint8_t *base = map(inputFile, false, &base_size, &f); + if (base == NULL) { + return 1; + } + + DLOG("mapping output file: %s", outputFile); + size_t dupe_size = base_size; + uint8_t *dupe = map(outputFile, true, &dupe_size, NULL); + if (dupe == NULL) { munmap(base, base_size); - munmap(dupe, dupe_size); - return 0; + return 1; + } + + DLOG("copying original data of size 0x%zx...", base_size); + memcpy(dupe, base, base_size); + + if (*(uint32_t *)base == FAT_CIGAM || *(uint32_t *)base == FAT_MAGIC) { + bool isBe = *(uint32_t *)base == FAT_CIGAM; + struct fat_header *fat_header = (struct fat_header *)base; + struct fat_arch *fatarches = (struct fat_arch *)(fat_header + 1); + auto fatInt = [isBe](int t) -> int { return isBe ? OSSwapInt32(t) : t; }; + + DLOG("handling %d fat arches...", fatInt(fat_header->nfat_arch)); + for (int fat_i = 0; fat_i < fatInt(fat_header->nfat_arch); fat_i++) { + auto curFatArch = &fatarches[fat_i]; + DLOG(" handling fat arch %d, cpuType 0x%x, cpuSubType 0x%x, fileOff " + "0x%x, size 0x%x, align 0x%x", + fat_i, fatInt(curFatArch->cputype), fatInt(curFatArch->cpusubtype), + fatInt(curFatArch->offset), fatInt(curFatArch->size), + fatInt(curFatArch->align)); + decrypt_macho_slide(f, base + fatInt(curFatArch->offset), + dupe + fatInt(curFatArch->offset), + fatInt(curFatArch->offset)); + } + } else { + DLOG(" not fat binary, directly decrypting it!"); + decrypt_macho_slide(f, base, dupe, 0); + } + + munmap(base, base_size); + munmap(dupe, dupe_size); + return 0; } From d9727424212554561a8bd75211e3055a3b6062cd Mon Sep 17 00:00:00 2001 From: und3fined Date: Fri, 10 Jan 2025 15:00:07 +0700 Subject: [PATCH 155/155] feat: release 0.2.0 - Support verbose log --- .github/workflows/build-deb.yml | 2 +- control.kernrw | 2 +- control.krw | 2 +- control.tfp0 | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 81bb894..fc9628e 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -8,7 +8,7 @@ jobs: runs-on: macos-13 strategy: matrix: - provider: [LIBKRW] + provider: [TFP0, LIBKRW, LIBKERNRW] steps: - uses: actions/checkout@v2 diff --git a/control.kernrw b/control.kernrw index 91537d1..ee94f82 100644 --- a/control.kernrw +++ b/control.kernrw @@ -1,6 +1,6 @@ Package: dev.und3fy.foulfolder.tauri Name: foulfolder (Tauri) -Version: 0.1.4 +Version: 0.2.0 Architecture: iphoneos-arm Depends: applist,zip,libkernrw0 Description: Directly decrypt binaries like fouldecrypt, but also supports iOS 14 diff --git a/control.krw b/control.krw index d336641..da4d085 100644 --- a/control.krw +++ b/control.krw @@ -1,6 +1,6 @@ Package: dev.und3fy.foulfolder.unc0ver Name: foulfolder (unc0ver) -Version: 0.1.5d +Version: 0.2.0 Architecture: iphoneos-arm Depends: applist,zip,libkrw Description: Directly decrypt binaries like fouldecrypt, but also supports iOS 14 diff --git a/control.tfp0 b/control.tfp0 index f34e17d..ec2af41 100644 --- a/control.tfp0 +++ b/control.tfp0 @@ -1,6 +1,6 @@ Package: dev.und3fy.foulfolder Name: foulfolder -Version: 0.1.4 +Version: 0.2.0 Architecture: iphoneos-arm Depends: applist,zip Description: Directly decrypt binaries like fouldecrypt, but also supports iOS 14