Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 102 additions & 18 deletions Source/iOS/App/Common/Jit/JitManager+Debugger.m
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@

#import "JitManager+Debugger.h"

#import <math.h>
#import <sys/utsname.h>
#import <unistd.h>

#define CS_OPS_STATUS 0
#define CS_DEBUGGED 0x10000000

Expand All @@ -19,7 +23,7 @@ - (bool)checkIfProcessIsDebugged {
return flags & CS_DEBUGGED;
}

// The following is taken from StikDebug.
// The following TXM detection is adapted from StikDebug.
// https://github.com/StephenDev0/StikDebug/blob/d077e232a9ff548d69a21e0e55466e8c7e9edb11/StikJIT/Views/HomeView.swift#L895-L908

- (nullable NSString*)filePathAtPath:(NSString*)path withLength:(NSUInteger)length {
Expand All @@ -35,29 +39,109 @@ - (nullable NSString*)filePathAtPath:(NSString*)path withLength:(NSUInteger)leng
return nil;
}

- (bool)checkIfDeviceUsesTXMClassic {
if (@available(iOS 14.0, *)) {
if ([[NSProcessInfo processInfo] isiOSAppOnMac]) {
return false;
}
}

// Primary: /System/Volumes/Preboot/<36>/boot/<96>/usr/.../Ap,TrustedExecutionMonitor.img4
NSString* bootUUID = [self filePathAtPath:@"/System/Volumes/Preboot" withLength:36];
if (bootUUID) {
NSString* bootDir = [bootUUID stringByAppendingPathComponent:@"boot"];
NSString* ninetySixCharPath = [self filePathAtPath:bootDir withLength:96];
if (ninetySixCharPath) {
NSString* img =
[ninetySixCharPath stringByAppendingPathComponent:
@"usr/standalone/firmware/FUD/Ap,TrustedExecutionMonitor.img4"];
return access(img.fileSystemRepresentation, F_OK) == 0;
}
}

// Fallback: /private/preboot/<96>/usr/.../Ap,TrustedExecutionMonitor.img4
NSString* fallback = [self filePathAtPath:@"/private/preboot" withLength:96];
if (fallback) {
NSString* img = [fallback stringByAppendingPathComponent:
@"usr/standalone/firmware/FUD/Ap,TrustedExecutionMonitor.img4"];
return access(img.fileSystemRepresentation, F_OK) == 0;
}

return false;
}

- (nullable NSNumber*)deviceVersionFromIdentifier:(NSString*)identifier pattern:(NSString*)pattern {
NSError* error = nil;
NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:pattern
options:0
error:&error];
if (!regex) {
return nil;
}

NSTextCheckingResult* match = [regex firstMatchInString:identifier
options:0
range:NSMakeRange(0, identifier.length)];
if (!match || match.numberOfRanges < 3) {
return nil;
}

NSRange majorRange = [match rangeAtIndex:1];
NSRange minorRange = [match rangeAtIndex:2];
if (majorRange.location == NSNotFound || minorRange.location == NSNotFound) {
return nil;
}

NSString* majorString = [identifier substringWithRange:majorRange];
NSString* minorString = [identifier substringWithRange:minorRange];
double divisor = pow(10.0, minorString.length);

return @(majorString.doubleValue + (minorString.doubleValue / divisor));
}

- (nullable NSNumber*)deviceVersionFromIdentifier:(NSString*)identifier {
NSNumber* iPhoneVersion = [self deviceVersionFromIdentifier:identifier
pattern:@"iPhone(\\d+),(\\d+)"];
if (iPhoneVersion) {
return iPhoneVersion;
}

return [self deviceVersionFromIdentifier:identifier pattern:@"iPad(\\d+),(\\d+)"];
}

- (NSString*)hardwareIdentifier {
struct utsname systemInfo;
uname(&systemInfo);

return [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding] ?: @"";
}

- (bool)checkIfDeviceUsesTXM {
// Primary: /System/Volumes/Preboot/<36>/boot/<96>/usr/.../Ap,TrustedExecutionMonitor.img4
NSString* bootUUID = [self filePathAtPath:@"/System/Volumes/Preboot" withLength:36];
if (bootUUID) {
NSString* bootDir = [bootUUID stringByAppendingPathComponent:@"boot"];
NSString* ninetySixCharPath = [self filePathAtPath:bootDir withLength:96];
if (ninetySixCharPath) {
NSString* img = [ninetySixCharPath stringByAppendingPathComponent:
@"usr/standalone/firmware/FUD/Ap,TrustedExecutionMonitor.img4"];
return access(img.fileSystemRepresentation, F_OK) == 0;
if (@available(iOS 26.0, *)) {
bool hasTXMClassic = [self checkIfDeviceUsesTXMClassic];
if (@available(iOS 26.6, *)) {
if (!hasTXMClassic) {
const double firstTXMDeviceVersion = 14.2;
const double firstIPadTXMDeviceVersion = 14.5;
NSString* identifier = [self hardwareIdentifier];
NSNumber* deviceVersion = [self deviceVersionFromIdentifier:identifier];

if (deviceVersion) {
if ([identifier hasPrefix:@"iPad"]) {
return deviceVersion.doubleValue >= firstIPadTXMDeviceVersion;
}

return deviceVersion.doubleValue >= firstTXMDeviceVersion;
}
}

// Fallback: /private/preboot/<96>/usr/.../Ap,TrustedExecutionMonitor.img4
NSString* fallback = [self filePathAtPath:@"/private/preboot" withLength:96];
if (fallback) {
NSString* img = [fallback stringByAppendingPathComponent:
@"usr/standalone/firmware/FUD/Ap,TrustedExecutionMonitor.img4"];
return access(img.fileSystemRepresentation, F_OK) == 0;
return false;
}
}

return hasTXMClassic;
} else {
return false;
}
}


@end
Loading