Skip to content

Commit

Permalink
fix khanhduytran0#338, khanhduytran0#146 for real, add don't inject t…
Browse files Browse the repository at this point in the history
…weakloader option
  • Loading branch information
hugeBlack committed Feb 8, 2025
1 parent 9146b83 commit 8677ba7
Show file tree
Hide file tree
Showing 17 changed files with 169 additions and 94 deletions.
3 changes: 2 additions & 1 deletion LiveContainerSwiftUI/LCAppInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ typedef NS_ENUM(NSInteger, LCOrientationLock){
@property bool isLocked;
@property bool isHidden;
@property bool doSymlinkInbox;
@property bool ignoreDlopenError;
//@property bool ignoreDlopenError;
@property bool fixBlackScreen;
@property bool dontInjectTweakLoader;
@property bool bypassAssertBarrierOnQueue;
@property UIColor* cachedColor;
@property Signer signer;
Expand Down
50 changes: 35 additions & 15 deletions LiveContainerSwiftUI/LCAppInfo.m
Original file line number Diff line number Diff line change
Expand Up @@ -267,12 +267,20 @@ - (void)patchExecAndSignIfNeedWithCompletionHandler:(void(^)(bool success, NSStr
return;
}

NSFileManager* fm = NSFileManager.defaultManager;
// Update patch
int currentPatchRev = 6;
if ([info[@"LCPatchRevision"] intValue] < currentPatchRev) {
NSString *execPath = [NSString stringWithFormat:@"%@/%@", appPath, _infoPlist[@"CFBundleExecutable"]];
NSString *backupPath = [NSString stringWithFormat:@"%@/%@_LiveContainerPatchBackUp", appPath, _infoPlist[@"CFBundleExecutable"]];
// copy-delete-move to avoid EXC_BAD_ACCESS (SIGKILL - CODESIGNING)
NSError *err;
[fm copyItemAtPath:execPath toPath:backupPath error:&err];
[fm removeItemAtPath:execPath error:&err];
[fm moveItemAtPath:backupPath toPath:execPath error:&err];

NSString *error = LCParseMachO(execPath.UTF8String, ^(const char *path, struct mach_header_64 *header) {
LCPatchExecSlice(path, header);
LCPatchExecSlice(path, header, ![self dontInjectTweakLoader]);
});
if (error) {
completetionHandler(NO, error);
Expand All @@ -281,7 +289,6 @@ - (void)patchExecAndSignIfNeedWithCompletionHandler:(void(^)(bool success, NSStr
info[@"LCPatchRevision"] = @(currentPatchRev);
forceSign = true;
// remove ZSign cache since hash is changed after upgrading patch
NSFileManager* fm = NSFileManager.defaultManager;
NSString* cachePath = [appPath stringByAppendingPathComponent:@"zsign_cache.json"];
if([fm fileExistsAtPath:cachePath]) {
NSError* err;
Expand Down Expand Up @@ -327,7 +334,7 @@ - (void)patchExecAndSignIfNeedWithCompletionHandler:(void(^)(bool success, NSStr
NSString *tmpExecPath = [appPath stringByAppendingPathComponent:@"LiveContainer.tmp"];
if (!info[@"LCBundleIdentifier"]) {
// Don't let main executable get entitlements
[NSFileManager.defaultManager copyItemAtPath:NSBundle.mainBundle.executablePath toPath:tmpExecPath error:nil];
[fm copyItemAtPath:NSBundle.mainBundle.executablePath toPath:tmpExecPath error:nil];

infoPlist[@"LCBundleExecutable"] = infoPlist[@"CFBundleExecutable"];
infoPlist[@"LCBundleIdentifier"] = infoPlist[@"CFBundleIdentifier"];
Expand All @@ -347,7 +354,7 @@ - (void)patchExecAndSignIfNeedWithCompletionHandler:(void(^)(bool success, NSStr
}

// Remove fake main executable
[NSFileManager.defaultManager removeItemAtPath:tmpExecPath error:nil];
[fm removeItemAtPath:tmpExecPath error:nil];


if(success && expirationDate) {
Expand Down Expand Up @@ -444,17 +451,17 @@ - (void)setDoSymlinkInbox:(bool)doSymlinkInbox {

}

- (bool)ignoreDlopenError {
if(_info[@"ignoreDlopenError"] != nil) {
return [_info[@"ignoreDlopenError"] boolValue];
} else {
return NO;
}
}
- (void)setIgnoreDlopenError:(bool)ignoreDlopenError {
_info[@"ignoreDlopenError"] = [NSNumber numberWithBool:ignoreDlopenError];
[self save];
}
//- (bool)ignoreDlopenError {
// if(_info[@"ignoreDlopenError"] != nil) {
// return [_info[@"ignoreDlopenError"] boolValue];
// } else {
// return NO;
// }
//}
//- (void)setIgnoreDlopenError:(bool)ignoreDlopenError {
// _info[@"ignoreDlopenError"] = [NSNumber numberWithBool:ignoreDlopenError];
// [self save];
//}

- (bool)fixBlackScreen {
if(_info[@"fixBlackScreen"] != nil) {
Expand All @@ -468,6 +475,19 @@ - (void)setFixBlackScreen:(bool)fixBlackScreen {
[self save];
}

- (bool)dontInjectTweakLoader {
if(_info[@"dontInjectTweakLoader"] != nil) {
return [_info[@"dontInjectTweakLoader"] boolValue];
} else {
return NO;
}
}
- (void)setDontInjectTweakLoader:(bool)dontInjectTweakLoader {
_info[@"dontInjectTweakLoader"] = [NSNumber numberWithBool:dontInjectTweakLoader];
// we have to update patch to achieve this
_info[@"LCPatchRevision"] = @(-1);
[self save];
}

- (bool)doUseLCBundleId {
if(_info[@"doUseLCBundleId"] != nil) {
Expand Down
2 changes: 1 addition & 1 deletion LiveContainerSwiftUI/LCAppListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ struct LCAppListView : View, LCAppBannerDelegate, LCAppModelDelegate {
finalNewApp.selectedLanguage = appToReplace.appInfo.selectedLanguage
finalNewApp.dataUUID = appToReplace.appInfo.dataUUID
finalNewApp.orientationLock = appToReplace.appInfo.orientationLock
finalNewApp.ignoreDlopenError = appToReplace.appInfo.ignoreDlopenError
finalNewApp.dontInjectTweakLoader = appToReplace.appInfo.dontInjectTweakLoader
finalNewApp.autoSaveDisabled = false
finalNewApp.save()
}
Expand Down
6 changes: 4 additions & 2 deletions LiveContainerSwiftUI/LCAppModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ class LCAppModel: ObservableObject, Hashable {
@Published var uiUseLCBundleId : Bool
@Published var uiBypassAssertBarrierOnQueue : Bool
@Published var uiSigner : Signer
@Published var uiIgnoreDlopenError : Bool
// @Published var uiIgnoreDlopenError : Bool
@Published var uiFixBlackScreen : Bool
@Published var uiDontInjectTweakLoader : Bool
@Published var uiOrientationLock : LCOrientationLock
@Published var uiSelectedLanguage : String
@Published var supportedLanaguages : [String]?
Expand Down Expand Up @@ -58,8 +59,9 @@ class LCAppModel: ObservableObject, Hashable {
self.uiSigner = appInfo.signer
self.uiOrientationLock = appInfo.orientationLock
self.uiUseLCBundleId = appInfo.doUseLCBundleId
self.uiIgnoreDlopenError = appInfo.ignoreDlopenError
// self.uiIgnoreDlopenError = appInfo.ignoreDlopenError
self.uiFixBlackScreen = appInfo.fixBlackScreen
self.uiDontInjectTweakLoader = appInfo.dontInjectTweakLoader

for container in uiContainers {
if container.folderName == uiDefaultDataFolder {
Expand Down
56 changes: 37 additions & 19 deletions LiveContainerSwiftUI/LCAppSettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,19 @@ struct LCAppSettingsView : View{
} footer: {
Text("lc.appSettings.useLCBundleIdDesc".loc)
}

Section {
Toggle(isOn: $model.uiFixBlackScreen) {
Text("lc.appSettings.fixBlackScreen".loc)
}
.onChange(of: model.uiFixBlackScreen, perform: { newValue in
Task { await setFixBlackScreen(newValue) }
})
} footer: {
Text("lc.appSettings.fixBlackScreenDesc".loc)
}


if sharedModel.isPhone {
Section {
Picker(selection: $model.uiOrientationLock) {
Expand All @@ -255,26 +268,26 @@ struct LCAppSettingsView : View{
}
}

Section {
Toggle(isOn: $model.uiIgnoreDlopenError) {
Text("lc.appSettings.ignoreDlopenError".loc)
}
.onChange(of: model.uiIgnoreDlopenError, perform: { newValue in
Task { await setIgnoreDlopenError(newValue) }
})
} footer: {
Text("lc.appSettings.ignoreDlopenErrorDesc".loc)
}
// Section {
// Toggle(isOn: $model.uiIgnoreDlopenError) {
// Text("lc.appSettings.ignoreDlopenError".loc)
// }
// .onChange(of: model.uiIgnoreDlopenError, perform: { newValue in
// Task { await setIgnoreDlopenError(newValue) }
// })
// } footer: {
// Text("lc.appSettings.ignoreDlopenErrorDesc".loc)
// }

Section {
Toggle(isOn: $model.uiFixBlackScreen) {
Text("lc.appSettings.fixBlackScreen".loc)
Toggle(isOn: $model.uiDontInjectTweakLoader) {
Text("lc.appSettings.dontInjectTweakLoader".loc)
}
.onChange(of: model.uiFixBlackScreen, perform: { newValue in
Task { await setFixBlackScreen(newValue) }
.onChange(of: model.uiDontInjectTweakLoader, perform: { newValue in
Task { await setDontInjectTweakLoader(newValue) }
})
} footer: {
Text("lc.appSettings.fixBlackScreenDesc".loc)
Text("lc.appSettings.dontInjectTweakLoaderDesc".loc)
}


Expand Down Expand Up @@ -518,16 +531,21 @@ struct LCAppSettingsView : View{
model.uiUseLCBundleId = doUseLCBundleId
}

func setIgnoreDlopenError(_ ignoreDlopenError : Bool) async {
appInfo.ignoreDlopenError = ignoreDlopenError
model.uiIgnoreDlopenError = ignoreDlopenError
}
// func setIgnoreDlopenError(_ ignoreDlopenError : Bool) async {
// appInfo.ignoreDlopenError = ignoreDlopenError
// model.uiIgnoreDlopenError = ignoreDlopenError
// }

func setFixBlackScreen(_ fixBlackScreen : Bool) async {
appInfo.fixBlackScreen = fixBlackScreen
model.uiFixBlackScreen = fixBlackScreen
}

func setDontInjectTweakLoader(_ dontInjectTweakLoader : Bool) async {
appInfo.dontInjectTweakLoader = dontInjectTweakLoader
model.uiDontInjectTweakLoader = dontInjectTweakLoader
}

func setOrientationLock(_ lock : LCOrientationLock) async {
appInfo.orientationLock = lock
model.uiOrientationLock = lock
Expand Down
22 changes: 14 additions & 8 deletions LiveContainerSwiftUI/LCMachOUtils.m
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ void LCPatchAddRPath(const char *path, struct mach_header_64 *header) {
insertRPathCommand("@loader_path", header);
}

void LCPatchExecSlice(const char *path, struct mach_header_64 *header) {
void LCPatchExecSlice(const char *path, struct mach_header_64 *header, bool doInject) {
uint8_t *imageHeaderPtr = (uint8_t*)header + sizeof(struct mach_header_64);

// Literally convert an executable to a dylib
Expand All @@ -59,16 +59,17 @@ void LCPatchExecSlice(const char *path, struct mach_header_64 *header) {

// Patch __PAGEZERO to map just a single zero page, fixing "out of address space"
struct segment_command_64 *seg = (struct segment_command_64 *)imageHeaderPtr;
assert(seg->cmd == LC_SEGMENT_64);
if (seg->vmaddr == 0) {
assert(seg->cmd == LC_SEGMENT_64 || seg->cmd == LC_ID_DYLIB);
if (seg->cmd == LC_SEGMENT_64 && seg->vmaddr == 0) {
assert(seg->vmsize == 0x100000000);
seg->vmaddr = 0x100000000 - 0x4000;
seg->vmsize = 0x4000;
}

BOOL hasDylibCommand = NO,
hasLoaderCommand = NO;
BOOL hasDylibCommand = NO;
struct dylib_command * dylibLoaderCommand = 0;
const char *tweakLoaderPath = "@loader_path/../../Tweaks/TweakLoader.dylib";
const char *libCppPath = "/usr/lib/libc++.1.dylib";
struct load_command *command = (struct load_command *)imageHeaderPtr;
for(int i = 0; i < header->ncmds > 0; i++) {
if(command->cmd == LC_ID_DYLIB) {
Expand All @@ -77,15 +78,20 @@ void LCPatchExecSlice(const char *path, struct mach_header_64 *header) {
struct dylib_command *dylib = (struct dylib_command *)command;
char *dylibName = (void *)dylib + dylib->dylib.name.offset;
if (!strncmp(dylibName, tweakLoaderPath, strlen(tweakLoaderPath))) {
hasLoaderCommand = YES;
dylibLoaderCommand = dylib;
}
} else if(command->cmd == 0x114514) {
dylibLoaderCommand = (struct dylib_command *)command;
}
command = (struct load_command *)((void *)command + command->cmdsize);
}

// Add LC_LOAD_DYLIB first, since LC_ID_DYLIB will change overall offsets
if (!hasLoaderCommand) {
insertDylibCommand(LC_LOAD_DYLIB, tweakLoaderPath, header);
if (dylibLoaderCommand) {
dylibLoaderCommand->cmd = doInject ? LC_LOAD_DYLIB : 0x114514;
strcpy((void *)dylibLoaderCommand + dylibLoaderCommand->dylib.name.offset, doInject ? tweakLoaderPath : libCppPath);
} else {
insertDylibCommand(doInject ? LC_LOAD_DYLIB : 0x114514, doInject ? tweakLoaderPath : libCppPath, header);
}
if (!hasDylibCommand) {
insertDylibCommand(LC_ID_DYLIB, path, header);
Expand Down
2 changes: 1 addition & 1 deletion LiveContainerSwiftUI/LCUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ typedef NS_ENUM(NSInteger, Signer){

NSString *LCParseMachO(const char *path, LCParseMachOCallback callback);
void LCPatchAddRPath(const char *path, struct mach_header_64 *header);
void LCPatchExecSlice(const char *path, struct mach_header_64 *header);
void LCPatchExecSlice(const char *path, struct mach_header_64 *header, bool doInject);
void LCPatchLibrary(const char *path, struct mach_header_64 *header);
void LCChangeExecUUID(struct mach_header_64 *header);
void LCPatchAltStore(const char *path, struct mach_header_64 *header);
Expand Down
Loading

0 comments on commit 8677ba7

Please sign in to comment.