Skip to content

Commit 7f2ea9d

Browse files
committed
Fix #72, the pain is over
1 parent 6c3c394 commit 7f2ea9d

File tree

6 files changed

+157
-34
lines changed

6 files changed

+157
-34
lines changed

src/AppDelegate.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ - (BOOL)application:(UIApplication*)application openURL:(nonnull NSURL*)url opti
232232
if (NO) {
233233
NSURL* bundlePath = [[LCPath bundlePath] URLByAppendingPathComponent:[Utils gdBundleName]];
234234
[Patcher patchGDBinary:[bundlePath URLByAppendingPathComponent:@"GeometryOriginal"] to:[bundlePath URLByAppendingPathComponent:@"GeometryJump"]
235-
withHandlerAddress:0x88d000
235+
withHandlerAddress:0x8b8000
236236
force:NO
237237
withSafeMode:NO
238238
withEntitlements:NO completionHandler:^(BOOL success, NSString* error) {

src/EnterpriseCompare.m

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,13 @@
33

44
@implementation EnterpriseCompare
55
+ (NSString*)getChecksum:(BOOL)helper {
6-
NSURL* from = [[NSBundle mainBundle] executableURL];
7-
NSURL* docPath = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask].lastObject;
8-
NSURL* bundlePath = [[docPath URLByAppendingPathComponent:@"Applications"] URLByAppendingPathComponent:@"com.robtop.geometryjump.app"];
9-
if (!helper) {
10-
from = [bundlePath URLByAppendingPathComponent:@"GeometryOriginal"];
11-
}
126
NSFileManager* fm = [NSFileManager defaultManager];
13-
NSError* error;
14-
if (![fm fileExistsAtPath:from.path]) return nil;
15-
NSMutableData* data = [NSMutableData dataWithContentsOfURL:from options:0 error:&error];
16-
if (!data || error) {
17-
NSLog(@"[Patcher] Couldn't read binary: %@", error);
18-
return nil;
19-
}
207
NSMutableSet<NSString*>* modIDs = [NSMutableSet new];
218
NSMutableSet<NSString*>* modDict = [NSMutableSet new];
22-
239
NSArray* modsDir = [fm contentsOfDirectoryAtPath:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"mods"] error:nil];
2410
if (!helper) {
11+
NSURL* docPath = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask].lastObject;
12+
NSURL* bundlePath = [[docPath URLByAppendingPathComponent:@"Applications"] URLByAppendingPathComponent:@"com.robtop.geometryjump.app"];
2513
modsDir = [fm contentsOfDirectoryAtPath:[bundlePath.path stringByAppendingPathComponent:@"mods"] error:nil];
2614
}
2715
for (NSString *file in modsDir) {
@@ -38,15 +26,13 @@ + (NSString*)getChecksum:(BOOL)helper {
3826
[modIDSorted removeObjectAtIndex:i];
3927
}
4028
}
41-
42-
NSData* stringData = [[NSString stringWithFormat:@"%@",[modIDSorted componentsJoinedByString:@","]] dataUsingEncoding:NSUTF8StringEncoding];
29+
NSData* data = [[NSString stringWithFormat:@"%@",[modIDSorted componentsJoinedByString:@","]] dataUsingEncoding:NSUTF8StringEncoding];
4330
unsigned char digest[CC_SHA256_DIGEST_LENGTH];
44-
CC_SHA256(stringData.bytes, (CC_LONG)stringData.length, digest);
31+
CC_SHA256(data.bytes, (CC_LONG)data.length, digest);
4532
NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
4633
for (int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
4734
[output appendFormat:@"%02x", digest[i]];
4835
}
49-
5036
return output;
5137
}
5238
@end

src/Patcher.mm

Lines changed: 134 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,136 @@ BOOL appendNewSection(NSMutableData* data) {
157157
newSect.size = sectSize;
158158
newSect.offset = newSeg.fileoff;
159159
newSect.align = sectSize < 16 ? 0 : 4;
160-
newSect.flags = 0x80000400; // S_REGULAR | S_ATTR_PURE_INSTRUCTIONS;
160+
newSect.flags = 0x80000400; // S_REGULAR | S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS;
161+
162+
linkSeg->vmaddr += alignedSize;
163+
linkSeg->fileoff += alignedSize;
164+
165+
// i love mach-o (most of this was assist because this has been giving me a headache) just to shift the linkedit cmds
166+
searchPtr = lcPtr;
167+
for (uint32_t i = 0; i < ncmds; i++) {
168+
struct load_command* lc = (struct load_command*)searchPtr;
169+
if (lc->cmd == LC_DYLD_INFO_ONLY || lc->cmd == LC_DYLD_INFO) {
170+
struct dyld_info_command* dc = (struct dyld_info_command*)searchPtr;
171+
#define SHIFT(field) if (dc->field >= linkFileOff) dc->field += alignedSize
172+
SHIFT(rebase_off);
173+
SHIFT(bind_off);
174+
SHIFT(weak_bind_off);
175+
SHIFT(lazy_bind_off);
176+
SHIFT(export_off);
177+
#undef SHIFT
178+
} else if (lc->cmd == LC_SYMTAB) {
179+
struct symtab_command* sc = (struct symtab_command*)searchPtr;
180+
if (sc->symoff >= linkFileOff)
181+
sc->symoff += alignedSize;
182+
if (sc->stroff >= linkFileOff)
183+
sc->stroff += alignedSize;
184+
} else if (lc->cmd == LC_DYSYMTAB) {
185+
struct dysymtab_command* dc = (struct dysymtab_command*)searchPtr;
186+
#define DS(field) if (dc->field >= linkFileOff) dc->field += alignedSize
187+
DS(tocoff);
188+
DS(modtaboff);
189+
DS(extrefsymoff);
190+
DS(indirectsymoff);
191+
DS(extreloff);
192+
DS(locreloff);
193+
#undef DS
194+
} else if (lc->cmd == LC_CODE_SIGNATURE || lc->cmd == LC_SEGMENT_SPLIT_INFO || lc->cmd == LC_FUNCTION_STARTS || lc->cmd == LC_DATA_IN_CODE ||
195+
lc->cmd == LC_DYLIB_CODE_SIGN_DRS) {
196+
struct linkedit_data_command* ld = (struct linkedit_data_command*)searchPtr;
197+
if (ld->dataoff >= linkFileOff)
198+
ld->dataoff += alignedSize;
199+
}
200+
searchPtr += lc->cmdsize;
201+
}
202+
header->ncmds += 1;
203+
header->sizeofcmds += newSeg.cmdsize;
204+
205+
// rebuilding just in case because binary shifts are wacky
206+
NSMutableData* out = [NSMutableData data];
207+
[out appendBytes:buf length:sizeof(*header)];
208+
lcPtr = buf + sizeof(*header);
209+
for (uint32_t i = 0; i < ncmds; i++) {
210+
struct load_command* lc = (struct load_command*)lcPtr;
211+
if (i == linkIndex) {
212+
[out appendBytes:&newSeg length:sizeof(newSeg)];
213+
[out appendBytes:&newSect length:sizeof(newSect)];
214+
}
215+
[out appendBytes:lcPtr length:lc->cmdsize];
216+
lcPtr += lc->cmdsize;
217+
}
218+
NSUInteger headerLen = out.length;
219+
if (headerLen < linkFileOff) {
220+
NSUInteger copySize = linkFileOff - headerLen;
221+
[out appendBytes:buf + headerLen length:copySize];
222+
}
223+
uint8_t* dead = (uint8_t*)calloc(1, alignedSize);
224+
[out appendBytes:dead length:sectSize];
225+
if (alignedSize > sectSize) {
226+
[out appendBytes:dead + sectSize length:(alignedSize - sectSize)];
227+
}
228+
free(dead);
229+
[out appendBytes:buf + linkFileOff length:origSize - linkFileOff];
230+
[data setData:out];
231+
return YES;
232+
}
233+
BOOL appendNewRWSection(NSMutableData* data) {
234+
NSUInteger origSize = data.length;
235+
const char* segNameC = "__STORAGE";
236+
const char* sectNameC = "__storage";
237+
uint64_t sectSize = sizeof(uintptr_t);
238+
239+
uint8_t* buf = (uint8_t*)data.mutableBytes;
240+
struct mach_header_64* header = (struct mach_header_64*)buf;
241+
242+
uint8_t* lcPtr = buf + sizeof(*header);
243+
uint32_t ncmds = header->ncmds;
244+
245+
struct segment_command_64* linkSeg = NULL;
246+
uint32_t linkIndex = 0;
247+
uint64_t linkFileOff = 0;
248+
uint8_t* searchPtr = lcPtr;
249+
for (uint32_t i = 0; i < ncmds; i++) {
250+
struct load_command* lc = (struct load_command*)searchPtr;
251+
if (lc->cmd == LC_SEGMENT_64) {
252+
struct segment_command_64* sc = (struct segment_command_64*)searchPtr;
253+
if (strncmp(sc->segname, "__LINKEDIT", 16) == 0) {
254+
linkSeg = sc;
255+
linkIndex = i;
256+
linkFileOff = sc->fileoff;
257+
break;
258+
}
259+
}
260+
searchPtr += lc->cmdsize;
261+
}
262+
if (!linkSeg) {
263+
AppLog(@"Couldn't find __LINKEDIT segment.");
264+
return NO;
265+
}
266+
267+
uint64_t alignedSize = align(MAX(sectSize, 0x4000), 0x1000);
268+
struct segment_command_64 newSeg;
269+
struct section_64 newSect;
270+
memset(&newSeg, 0, sizeof(newSeg));
271+
memset(&newSect, 0, sizeof(newSect));
272+
newSeg.cmd = LC_SEGMENT_64;
273+
newSeg.cmdsize = sizeof(newSeg) + sizeof(newSect);
274+
strncpy(newSeg.segname, segNameC, 16);
275+
newSeg.vmaddr = linkSeg->vmaddr;
276+
newSeg.vmsize = alignedSize;
277+
newSeg.fileoff = linkFileOff;
278+
newSeg.filesize = alignedSize;
279+
newSeg.maxprot = VM_PROT_READ | VM_PROT_WRITE;
280+
newSeg.initprot = VM_PROT_READ | VM_PROT_WRITE;
281+
newSeg.nsects = 1;
282+
283+
strncpy(newSect.sectname, sectNameC, 16);
284+
strncpy(newSect.segname, segNameC, 16);
285+
newSect.addr = newSeg.vmaddr;
286+
newSect.size = sectSize;
287+
newSect.offset = newSeg.fileoff;
288+
newSect.align = 3;
289+
newSect.flags = 0x0; // S_REGULAR
161290

162291
linkSeg->vmaddr += alignedSize;
163292
linkSeg->fileoff += alignedSize;
@@ -496,6 +625,10 @@ + (void)patchGDBinary:(NSURL*)from to:(NSURL*)to withHandlerAddress:(uint64_t)ha
496625
AppLog(@"Something went wrong when writing a new executable region.");
497626
return completionHandler(NO, @"Couldn't write new RX region.");
498627
}
628+
if (!appendNewRWSection(data)) {
629+
AppLog(@"Something went wrong when writing a new writable region.");
630+
return completionHandler(NO, @"Couldn't write new RW region.");
631+
}
499632

500633
// === PATCH STEP 1 ====
501634
struct segment_command_64* textSeg = NULL;

src/RootViewController.m

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,7 @@ - (void)downloadGame {
530530
- (void)signAppWithSafeMode:(void (^)(BOOL success, NSString* error))completionHandler {
531531
NSURL* bundlePath = [[LCPath bundlePath] URLByAppendingPathComponent:[Utils gdBundleName]];
532532
if ([[Utils getPrefs] boolForKey:@"JITLESS"]) {
533-
[Patcher patchGDBinary:[bundlePath URLByAppendingPathComponent:@"GeometryOriginal"] to:[bundlePath URLByAppendingPathComponent:@"GeometryJump"] withHandlerAddress:0x88d000
533+
[Patcher patchGDBinary:[bundlePath URLByAppendingPathComponent:@"GeometryOriginal"] to:[bundlePath URLByAppendingPathComponent:@"GeometryJump"] withHandlerAddress:0x8b8000
534534
force:NO
535535
withSafeMode:YES
536536
withEntitlements:NO completionHandler:^(BOOL success, NSString* error) {
@@ -595,7 +595,7 @@ - (void)signApp:(BOOL)forceSign completionHandler:(void (^)(BOOL success, NSStri
595595

596596
NSURL* bundlePath = [[LCPath bundlePath] URLByAppendingPathComponent:[Utils gdBundleName]];
597597
if ([[Utils getPrefs] boolForKey:@"JITLESS"]) {
598-
[Patcher patchGDBinary:[bundlePath URLByAppendingPathComponent:@"GeometryOriginal"] to:[bundlePath URLByAppendingPathComponent:@"GeometryJump"] withHandlerAddress:0x88d000
598+
[Patcher patchGDBinary:[bundlePath URLByAppendingPathComponent:@"GeometryOriginal"] to:[bundlePath URLByAppendingPathComponent:@"GeometryJump"] withHandlerAddress:0x8b8000
599599
force:NO
600600
withSafeMode:NO
601601
withEntitlements:NO completionHandler:^(BOOL success, NSString* error) {
@@ -658,7 +658,7 @@ - (void)signApp:(BOOL)forceSign completionHandler:(void (^)(BOOL success, NSStri
658658
});
659659
}];
660660
} else {
661-
[Patcher patchGDBinary:[bundlePath URLByAppendingPathComponent:@"GeometryOriginal"] to:[bundlePath URLByAppendingPathComponent:@"GeometryJump"] withHandlerAddress:0x88d000
661+
[Patcher patchGDBinary:[bundlePath URLByAppendingPathComponent:@"GeometryOriginal"] to:[bundlePath URLByAppendingPathComponent:@"GeometryJump"] withHandlerAddress:0x8b8000
662662
force:NO
663663
withSafeMode:NO
664664
withEntitlements:NO completionHandler:^(BOOL success, NSString* error) { completionHandler(success, error); }];
@@ -671,9 +671,9 @@ - (void)launchHelper2:(BOOL)safeMode patchCheck:(BOOL)patchCheck {
671671
env = launchArgs;
672672
}
673673
if (safeMode) {
674-
env = @"--geode:use-common-handler-offset=88d000 --geode:safe-mode";
674+
env = @"--geode:use-common-handler-offset=8b8000 --geode:safe-mode";
675675
} else {
676-
env = @"--geode:use-common-handler-offset=88d000";
676+
env = @"--geode:use-common-handler-offset=8b8000";
677677
}
678678
NSString* b64 = [[env dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:0];
679679
NSMutableString* encodedUrl = [b64 mutableCopy];
@@ -705,9 +705,9 @@ - (void)launchHelper:(BOOL)safeMode {
705705
env = launchArgs;
706706
}
707707
if (safeMode) {
708-
env = @"--geode:use-common-handler-offset=88d000 --geode:safe-mode";
708+
env = @"--geode:use-common-handler-offset=8b8000 --geode:safe-mode";
709709
} else {
710-
env = @"--geode:use-common-handler-offset=88d000";
710+
env = @"--geode:use-common-handler-offset=8b8000";
711711
}
712712
NSString* b64 = [[env dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:0];
713713
NSMutableString* encodedUrl = [b64 mutableCopy];
@@ -846,7 +846,7 @@ - (BOOL)bundleIPAWithPatch:(BOOL)safeMode withLaunch:(BOOL)launch {
846846
NSString* uniqId = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
847847
[fm createFileAtPath:[bundlePath URLByAppendingPathComponent:@"sf.bd"].path contents:[uniqId dataUsingEncoding:NSUTF8StringEncoding] attributes:@{}];
848848

849-
[Patcher patchGDBinary:[bundlePath URLByAppendingPathComponent:@"GeometryOriginal"] to:[bundlePath URLByAppendingPathComponent:@"GeometryJump"] withHandlerAddress:0x88d000
849+
[Patcher patchGDBinary:[bundlePath URLByAppendingPathComponent:@"GeometryOriginal"] to:[bundlePath URLByAppendingPathComponent:@"GeometryJump"] withHandlerAddress:0x8b8000
850850
force:[[Utils getPrefs] boolForKey:@"IS_COMPRESSING_IPA"]
851851
withSafeMode:safeMode
852852
withEntitlements:YES completionHandler:^(BOOL success, NSString* error) {

src/SettingsVC.m

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,7 +1126,7 @@ - (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)
11261126
[Utils showError:self title:@"Original Binary not found." error:nil];
11271127
} else {
11281128
[Patcher patchGDBinary:[bundlePath URLByAppendingPathComponent:@"GeometryOriginal"] to:[bundlePath URLByAppendingPathComponent:@"GeometryJump"]
1129-
withHandlerAddress:0x88d000
1129+
withHandlerAddress:0x8b8000
11301130
force:YES
11311131
withSafeMode:NO
11321132
withEntitlements:YES completionHandler:^(BOOL success, NSString* error) {
@@ -1222,7 +1222,7 @@ - (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)
12221222
break;
12231223
}
12241224
[Patcher patchGDBinary:[bundlePath URLByAppendingPathComponent:@"GeometryOriginal"] to:[bundlePath URLByAppendingPathComponent:@"GeometryJump"]
1225-
withHandlerAddress:0x88d000
1225+
withHandlerAddress:0x8b8000
12261226
force:YES
12271227
withSafeMode:YES
12281228
withEntitlements:YES completionHandler:^(BOOL success, NSString* error) {
@@ -1249,7 +1249,7 @@ - (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)
12491249
break;
12501250
}
12511251
[Patcher patchGDBinary:[bundlePath URLByAppendingPathComponent:@"GeometryOriginal"] to:[bundlePath URLByAppendingPathComponent:@"GeometryJump"]
1252-
withHandlerAddress:0x88d000
1252+
withHandlerAddress:0x8b8000
12531253
force:YES
12541254
withSafeMode:YES
12551255
withEntitlements:NO completionHandler:^(BOOL success, NSString* error) {

src/main.m

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -285,8 +285,12 @@ static void overwriteExecPath(const char* newExecPath) {
285285
usleep(1000 * 100);
286286
}
287287
if (!checkJITEnabled()) {
288-
appError = @"JIT was not enabled. Please ensure that you launched the Geode launcher with JIT. You can enable \"Manual reopen with JIT\" for manually enabling JIT "
288+
if (@available(iOS 26.0, *)) {
289+
appError = @"JIT is not supported on iOS 26. Please wait until a future update for this to be possible.";
290+
} else {
291+
appError = @"JIT was not enabled. Please ensure that you launched the Geode launcher with JIT. You can enable \"Manual reopen with JIT\" for manually enabling JIT "
289292
@"(Pressing launch, closing app, open with JIT).";
293+
}
290294
// appError = @"JIT was not enabled. If you want to use Geode without JIT, setup JITLess mode in settings.";
291295
return appError;
292296
}
@@ -442,9 +446,9 @@ static void overwriteExecPath(const char* newExecPath) {
442446
// safe mode
443447
if ([gcUserDefaults boolForKey:@"JITLESS"] || [gcUserDefaults boolForKey:@"FORCE_PATCHING"]) {
444448
if (safeMode) {
445-
setenv("LAUNCHARGS", "--geode:use-common-handler-offset=88d000 --geode:safe-mode", 1);
449+
setenv("LAUNCHARGS", "--geode:use-common-handler-offset=8b8000 --geode:safe-mode", 1);
446450
} else {
447-
setenv("LAUNCHARGS", "--geode:use-common-handler-offset=88d000", 1);
451+
setenv("LAUNCHARGS", "--geode:use-common-handler-offset=8b8000", 1);
448452
}
449453
} else {
450454
if (safeMode) {

0 commit comments

Comments
 (0)