Skip to content

Commit fac213e

Browse files
committed
Add offset finder for iPadOS override
1 parent a899ed6 commit fac213e

File tree

3 files changed

+58
-3
lines changed

3 files changed

+58
-3
lines changed

FindCacheDataOffset.m

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
@import Foundation;
2+
@import Darwin;
3+
@import MachO;
4+
5+
__attribute__((constructor)) void FindCacheDataOffset() {
6+
/*
7+
* TL;DR: finding CacheData value offset is as follows:
8+
* - Get a pointer to the corresponding obfuscated key in libMobileGestalt
9+
* - Get a pointer to an unknown struct, whose first pointer is the pointer to the obfuscated key
10+
* - Offset it by 0x9a (FIXME this lol), read it as uint16_t
11+
* - Shift left the resulting offset by 3 bits
12+
*/
13+
14+
const struct mach_header_64 *header = NULL;
15+
const char *mgName = "/usr/lib/libMobileGestalt.dylib";
16+
const char *mgKey = "mtrAoWJ3gsq+I90ZnQ0vQw";
17+
dlopen(mgName, RTLD_GLOBAL);
18+
19+
for (int i = 0; i < _dyld_image_count(); i++) {
20+
if (!strncmp(mgName, _dyld_get_image_name(i), strlen(mgName))) {
21+
header = (const struct mach_header_64 *)_dyld_get_image_header(i);
22+
break;
23+
}
24+
}
25+
assert(header);
26+
27+
// Get a pointer to the corresponding obfuscated key in libMobileGestalt
28+
size_t textCStringSize;
29+
const char *textCStringSection = (const char *)getsectiondata(header, "__TEXT", "__cstring", &textCStringSize);
30+
for (size_t size = 0; size < textCStringSize; size += strlen(textCStringSection + size) + 1) {
31+
if (!strncmp(mgKey, textCStringSection + size, strlen(mgKey))) {
32+
textCStringSection += size;
33+
break;
34+
}
35+
}
36+
37+
// Get a pointer to an unknown struct, whose first pointer is the pointer to the obfuscated key
38+
size_t constSize;
39+
// arm64e
40+
const uintptr_t *constSection = (const uintptr_t *)getsectiondata(header, "__AUTH_CONST", "__const", &constSize);
41+
if (!constSection) {
42+
// arm64, FIXME: is this correct?
43+
constSection = (const uintptr_t *)getsectiondata(header, "__DATA_CONST", "__const", &constSize);
44+
}
45+
for (int i = 0; i < constSize / 8; i++) {
46+
if (constSection[i] == (uintptr_t)textCStringSection) {
47+
constSection += i;
48+
break;
49+
}
50+
}
51+
52+
// FIXME: is offset of offset consistent?
53+
off_t offset = (off_t)((uint16_t *)constSection)[0x9a/2] << 3;
54+
[NSUserDefaults.standardUserDefaults setInteger:offset forKey:@"MGCacheDataDeviceClassNumberOffset"];
55+
}

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ libEMProxy_FRAMEWORKS = Security
1414
libEMProxy_INSTALL_PATH = /Applications/$(APPLICATION_NAME).app/Frameworks
1515

1616
# libimobiledevice + minimuxer
17-
libimobiledevice_FILES = idevicebackup2.c
18-
libimobiledevice_CFLAGS = -Iinclude
17+
libimobiledevice_FILES = idevicebackup2.c FindCacheDataOffset.m
18+
libimobiledevice_CFLAGS = -Iinclude -fobjc-arc
1919
libimobiledevice_LDFLAGS = \
2020
-force_load lib/libimobiledevice-1.0.a \
2121
-force_load lib/libimobiledevice-glue-1.0.a \

Sources/ContentView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ Thanks to:
251251
func bindingForTrollPad() -> Binding<Bool> {
252252
// We're going to overwrite DeviceClassNumber but we can't do it via CacheExtra, so we need to do it via CacheData instead
253253
// However, CacheData is still a black box, as nobody has yet to document this data, so we're leaving a hardcoded offset for now
254-
let valueOffset = 0x2e0
254+
let valueOffset = UserDefaults.standard.integer(forKey: "MGCacheDataDeviceClassNumberOffset")
255255
let cacheData = mobileGestalt["CacheData"] as! NSMutableData
256256
//print("Read value from \(cacheData.mutableBytes.load(fromByteOffset: valueOffset, as: Int.self))")
257257

0 commit comments

Comments
 (0)