ios-hooks/ios-change-info/Tweak.x
2025-12-01 11:21:01 +08:00

904 lines
26 KiB
Plaintext

//
// Tweak.x
// 主入口文件 - 包含所有 Hooks
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <WebKit/WebKit.h>
#import <CoreMotion/CoreMotion.h>
#import <CoreTelephony/CTCarrier.h>
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
#import <SystemConfiguration/SystemConfiguration.h>
#import <AppTrackingTransparency/AppTrackingTransparency.h>
#import <AVFoundation/AVFoundation.h>
#import <sys/utsname.h>
#include <sys/sysctl.h>
#import <ifaddrs.h>
#import <arpa/inet.h>
#import <net/if.h>
#import <objc/runtime.h>
#import "XSLog.h"
#import "XHookSettingsManager.h"
// 设置日志
void SetupXSLog() {
XSLogSetupLogWithFilePath(@"/var/mobile/Documents/App.log", 50 * 1024 * 1024);
XSLogRedirectNSLog();
}
#pragma mark - ============== HOOKS GROUP ==============
%group XHooks
#pragma mark - ATTrackingManager Hook
%hook ATTrackingManager
+ (ATTrackingManagerAuthorizationStatus)trackingAuthorizationStatus {
ATTrackingManagerAuthorizationStatus originalStatus = %orig;
NSUInteger status = [XHookSettings trackingStatus];
return (ATTrackingManagerAuthorizationStatus)status;
}
+ (void)requestTrackingAuthorizationWithCompletionHandler:(void (^)(ATTrackingManagerAuthorizationStatus status))completion {
ATTrackingManagerAuthorizationStatus attStatus = (ATTrackingManagerAuthorizationStatus)[XHookSettings trackingStatus];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if (completion) {
completion(attStatus);
}
});
}
%end
#pragma mark - ASIdentifierManager Hook
%hook ASIdentifierManager
- (NSUUID *)advertisingIdentifier {
NSUUID *idfa = [XHookSettings idfa];
return idfa ?: %orig;
}
- (BOOL)isAdvertisingTrackingEnabled {
NSUInteger status = [XHookSettings trackingStatus];
return (status >= 3);
}
%end
#pragma mark - UIDevice Hook
%hook UIDevice
- (NSUUID *)identifierForVendor {
NSUUID *idfv = [XHookSettings idfv];
return idfv ?: %orig;
}
- (NSString *)name {
NSString *name = [XHookSettings deviceName];
return name ?: %orig;
}
- (NSString *)model {
return %orig;
}
- (NSString *)localizedModel {
return %orig;
}
- (NSString *)systemName {
return %orig;
}
- (NSString *)systemVersion {
NSString *version = [XHookSettings osVersion];
return version ?: %orig;
}
- (UIDeviceBatteryState)batteryState {
UIDeviceBatteryState state = [XHookSettings batteryState];
return (state != UIDeviceBatteryStateUnknown) ? state : %orig;
}
- (float)batteryLevel {
float level = [XHookSettings batteryLevel];
return (level > -1.0f) ? level : %orig;
}
- (UIDeviceOrientation)orientation {
return UIDeviceOrientationPortrait;
}
%end
#pragma mark - NSProcessInfo Hook
%hook NSProcessInfo
- (NSTimeInterval)systemUptime {
NSTimeInterval res = %orig;
double offset = [XHookSettings systemUptimeOffset];
if (offset > -1.0) {
res += offset;
}
return res;
}
- (unsigned long long)physicalMemory {
unsigned long long memory = [XHookSettings physicalMemory];
return (memory > 1000) ? memory : %orig;
}
- (NSUInteger)processorCount {
NSUInteger cores = [XHookSettings cpuCore];
return (cores > 0) ? cores : %orig;
}
- (NSOperatingSystemVersion)operatingSystemVersion {
NSOperatingSystemVersion version = %orig;
NSString *versionString = [XHookSettings osVersion];
if (!versionString || ![versionString length]) {
return version;
}
NSArray *components = [versionString componentsSeparatedByString:@"."];
if (components.count == 0 || components.count > 3) {
return version;
}
for (NSString *component in components) {
if (![[NSScanner scannerWithString:component] scanInteger:NULL]) {
return version;
}
}
version.majorVersion = [components[0] integerValue];
version.minorVersion = components.count > 1 ? [components[1] integerValue] : 0;
version.patchVersion = components.count > 2 ? [components[2] integerValue] : 0;
return version;
}
%end
#pragma mark - UIWindow Hook
%hook UIWindow
- (UIEdgeInsets)safeAreaInsets {
UIEdgeInsets originalInsets = %orig;
NSDictionary *dic = [XHookSettings safeAreaInsets];
if (dic) {
CGFloat top = [dic[@"top"] doubleValue];
CGFloat bottom = [dic[@"bottom"] doubleValue];
originalInsets = UIEdgeInsetsMake(top, 0, bottom, 0);
}
return originalInsets;
}
%end
#pragma mark - UIScreen Hook
%hook UIScreen
- (CGFloat)brightness {
CGFloat brightness = [XHookSettings screenBrightness];
return (brightness > -1.0) ? brightness : %orig;
}
- (CGRect)bounds {
NSDictionary *dic = [XHookSettings screenBounds];
if (dic) {
double w = [dic[@"x"] doubleValue];
double h = [dic[@"y"] doubleValue];
return CGRectMake(0, 0, w, h);
}
return %orig;
}
- (CGFloat)scale {
CGFloat scale = [XHookSettings screenScale];
return (scale > -1.0) ? scale : %orig;
}
- (CGRect)nativeBounds {
NSDictionary *dic = [XHookSettings screenBounds];
if (dic) {
double w = [dic[@"nx"] doubleValue];
double h = [dic[@"ny"] doubleValue];
return CGRectMake(0, 0, w, h);
}
return %orig;
}
- (BOOL)isCaptured {
return NO;
}
- (UIScreen *)mirroredScreen {
return nil;
}
%end
#pragma mark - UIScreenMode Hook
%hook UIScreenMode
- (CGSize)size {
NSDictionary *dic = [XHookSettings screenBounds];
if (dic) {
double w = [dic[@"x"] doubleValue];
double h = [dic[@"y"] doubleValue];
return CGSizeMake(w, h);
}
return %orig;
}
%end
#pragma mark - UIStatusBarManager Hook
%hook UIStatusBarManager
- (CGRect)statusBarFrame {
CGRect originalFrame = %orig;
NSDictionary *dic = [XHookSettings safeAreaInsets];
if (dic && dic[@"height"]) {
double barHeight = [dic[@"height"] doubleValue];
originalFrame.size.height = barHeight;
}
return originalFrame;
}
%end
#pragma mark - AVAudioSession Hook
%hook AVAudioSession
- (float)outputVolume {
float volume = [XHookSettings outputVolume];
return (volume > -1.0f) ? volume : %orig;
}
%end
#pragma mark - NSFileManager Hook
%hook NSFileManager
- (NSDictionary<NSFileAttributeKey, id> *)attributesOfFileSystemForPath:(NSString *)path error:(NSError **)error {
NSDictionary<NSFileAttributeKey, id> *res = %orig;
if ([path isEqualToString:NSHomeDirectory()]) {
NSMutableDictionary *modifiedAttributes = [res mutableCopy];
unsigned long long diskSize = [XHookSettings diskSize];
if (diskSize > 0) {
modifiedAttributes[NSFileSystemSize] = @(diskSize);
}
unsigned long long diskFreeSize = [XHookSettings diskFreeSize];
if (diskFreeSize > 0) {
modifiedAttributes[NSFileSystemFreeSize] = @(diskFreeSize);
}
return [modifiedAttributes copy];
}
return res;
}
- (BOOL)fileExistsAtPath:(NSString *)event {
NSArray<NSString *> *array = @[@"/Application/Cydia.app",
@"/Application/Sileo.app",
@"/usr/lib/TweakInject",
@"/Library/TweakInject",
@"/Library/MobileSubstrate/MobileSubstrate.dylib",
@"/bin/bash",
@"/usr/sbin/sshd",
@"/etc/apt",
@"/usr/bin/ssh",
@"/private/var/lib/apt",
@"/private/var/lib/cydia",
@"/private/var/tmp/cydia.log",
@"/Applications/WinterBoard.app",
@"/var/lib/cydia",
@"/private/etc/dpkg/origins/debian",
@"/bin.sh",
@"/private/etc/apt",
@"/etc/ssh/sshd_config",
@"/private/etc/ssh/sshd_config",
@"/Applications/SBSetttings.app",
@"/private/var/mobileLibrary/SBSettingsThemes/",
@"/private/var/stash",
@"/usr/libexec/sftp-server",
@"/usr/libexec/cydia/",
@"/usr/sbin/frida-server",
@"/usr/bin/cycript",
@"/usr/local/bin/cycript",
@"/usr/lib/libcycript.dylib",
@"/System/Library/LaunchDaemons/com.saurik.Cydia.Startup.plist",
@"/System/Library/LaunchDaemons/com.ikey.bbot.plist",
@"/Applications/FakeCarrier.app",
@"/Library/MobileSubstrate/DynamicLibraries/Veency.plist",
@"/Library/MobileSubstrate/DynamicLibraries/LiveClock.plist",
@"/usr/libexec/ssh-keysign",
@"/usr/libexec/sftp-server",
@"/Applications/blackra1n.app",
@"/Applications/IntelliScreen.app",
@"/Applications/Snoop-itConfig.app",
@"/var/lib/dpkg/info",
@"/User/Applications"];
NSInteger index = [array indexOfObjectPassingTest:^BOOL(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
BOOL ret = [event hasPrefix:obj];
if (ret) {
*stop = YES;
}
return ret;
}];
if (index != NSNotFound) {
return NO;
}
return %orig;
}
%end
#pragma mark - NSLocale Hook
%hook NSLocale
+ (NSArray *)preferredLanguages {
return @[@"en-US"];
}
+ (NSLocale *)currentLocale {
NSString *loc = [XHookSettings locale];
if (loc) {
return [[NSLocale alloc] initWithLocaleIdentifier:loc];
}
return %orig;
}
+ (NSLocale *)systemLocale {
NSString *loc = [XHookSettings locale];
if (loc) {
return [[NSLocale alloc] initWithLocaleIdentifier:loc];
}
return %orig;
}
%end
#pragma mark - NSTimeZone Hook
%hook NSTimeZone
+ (NSTimeZone *)localTimeZone {
NSString *tz = [XHookSettings timeZone];
if (tz) {
return [NSTimeZone timeZoneWithName:tz];
}
return %orig;
}
+ (NSTimeZone *)systemTimeZone {
NSString *tz = [XHookSettings timeZone];
if (tz) {
return [NSTimeZone timeZoneWithName:tz];
}
return %orig;
}
+ (NSTimeZone *)defaultTimeZone {
NSString *tz = [XHookSettings timeZone];
if (tz) {
return [NSTimeZone timeZoneWithName:tz];
}
return %orig;
}
%end
#pragma mark - NSMutableURLRequest Hook
%hook NSMutableURLRequest
- (instancetype)initWithURL:(NSURL *)URL {
self = %orig(URL);
if (self) {
NSString *userAgent = [XHookSettings userAgent];
if (userAgent) {
[self setValue:userAgent forHTTPHeaderField:@"User-Agent"];
}
}
return self;
}
- (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field {
NSString *finalValue = value;
if ([field isEqualToString:@"User-Agent"]) {
NSString *userAgent = [XHookSettings userAgent];
if (userAgent) {
finalValue = userAgent;
}
}
%orig(finalValue, field);
}
%end
#pragma mark - NSURLSession Hook
%hook NSURLSession
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration {
NSString *userAgent = [XHookSettings userAgent];
if (userAgent) {
configuration.HTTPAdditionalHeaders = @{@"User-Agent": userAgent};
}
return %orig;
}
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler {
NSMutableURLRequest *mutableRequest = [request mutableCopy];
NSString *userAgent = [XHookSettings userAgent];
if (userAgent) {
[mutableRequest setValue:userAgent forHTTPHeaderField:@"User-Agent"];
}
return %orig(mutableRequest, completionHandler);
}
%end
#pragma mark - WKWebView Hook
%hook WKWebView
- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^)(id, NSError *error))completionHandler {
NSString *userAgent = [XHookSettings userAgent];
if (userAgent) {
[self setCustomUserAgent:userAgent];
}
%orig(javaScriptString, completionHandler);
}
- (void)setCustomUserAgent:(NSString *)userAgent {
NSString *customUA = [XHookSettings userAgent];
%orig(customUA ?: userAgent);
}
- (NSString *)customUserAgent {
NSString *userAgent = [XHookSettings userAgent];
return userAgent ?: %orig;
}
%end
#pragma mark - CTTelephonyNetworkInfo Hook
%hook CTTelephonyNetworkInfo
- (NSDictionary<NSString *, NSString *> *)serviceCurrentRadioAccessTechnology {
NSDictionary<NSString *, NSString *> *originalTechnologies = %orig;
NSDictionary *simInfoDic = [XHookSettings simInfo];
if (!simInfoDic) {
return originalTechnologies;
}
NSMutableDictionary<NSString *, NSString *> *modifiedProviders = [[NSMutableDictionary alloc] init];
for (NSString *service in simInfoDic.allKeys) {
NSDictionary *dic = simInfoDic[service];
NSString *wwan = dic[@"wwan"];
if ([wwan isEqual:@"5G"]) {
modifiedProviders[service] = @"CTRadioAccessTechnologyNR";
} else {
modifiedProviders[service] = @"CTRadioAccessTechnologyLTE";
}
}
return [modifiedProviders count] > 0 ? [modifiedProviders copy] : originalTechnologies;
}
- (NSDictionary<NSString *, CTCarrier *> *)serviceSubscriberCellularProviders {
NSDictionary<NSString *, CTCarrier *> *originalProviders = %orig;
NSDictionary *simInfoDic = [XHookSettings simInfo];
if (!simInfoDic) {
return originalProviders;
}
NSMutableDictionary<NSString *, CTCarrier *> *modifiedProviders = [[NSMutableDictionary alloc] init];
for (NSString *service in simInfoDic.allKeys) {
NSDictionary *dic = simInfoDic[service];
if (!dic) continue;
if (dic[@"id"] && ![dic[@"id"] isEqual:[NSNull null]]) {
[[NSUserDefaults standardUserDefaults] setValue:dic[@"id"] forKey:@"XHook-carrier-id"];
}
CTCarrier *carrier = [[CTCarrier alloc] init];
[carrier setValue:dic[@"carrierName"] forKey:@"carrierName"];
[carrier setValue:dic[@"mobileCountryCode"] forKey:@"mobileCountryCode"];
[carrier setValue:dic[@"mobileNetworkCode"] forKey:@"mobileNetworkCode"];
[carrier setValue:dic[@"isoCountryCode"] forKey:@"isoCountryCode"];
modifiedProviders[service] = carrier;
}
return [modifiedProviders count] > 0 ? [modifiedProviders copy] : originalProviders;
}
%end
#pragma mark - CMMotionManager Hook (陀螺仪)
static double randomRadiansPerSecond() {
double randomValue = (double)arc4random() / UINT32_MAX;
return (randomValue * 20.0) - 10.0;
}
@interface CustomCMGyroData : CMGyroData
@property (nonatomic, assign) CMRotationRate customRotationRate;
@end
@implementation CustomCMGyroData
- (CMRotationRate)rotationRate {
return self.customRotationRate;
}
@end
%hook CMMotionManager
- (void)startGyroUpdatesToQueue:(NSOperationQueue *)queue withHandler:(CMGyroHandler)handler {
if (!queue || !handler) return %orig;
CMGyroHandler newHandler = ^(CMGyroData *gyroData, NSError *error) {
CMRotationRate randomRate;
randomRate.x = randomRadiansPerSecond();
randomRate.y = randomRadiansPerSecond();
randomRate.z = randomRadiansPerSecond();
CustomCMGyroData *customGyroData = (CustomCMGyroData *)[[objc_getClass("CMGyroData") alloc] init];
customGyroData.customRotationRate = randomRate;
if (handler) {
handler((CMGyroData *)customGyroData, error);
}
};
%orig(queue, newHandler);
}
%end
#pragma mark - C Function Hooks
%hookf(int, uname, struct utsname *systemInfo) {
int nRet = %orig;
NSString *productStr = [XHookSettings productStr];
if (productStr) {
char str_machine_name[100];
[productStr getCString:str_machine_name maxLength:100 encoding:NSUTF8StringEncoding];
strcpy(systemInfo->machine, str_machine_name);
}
return nRet;
}
%hookf(int, sysctl, const int *name, u_int namelen, void *oldp, size_t *oldlenp, const void *newp, size_t newlen) {
if (namelen < 2) {
return %orig;
}
if (name[0] == CTL_KERN && name[1] == KERN_BOOTTIME) {
int nRet = %orig;
if (nRet == 0 && oldp && oldlenp && *oldlenp >= sizeof(struct timeval)) {
struct timeval *a = (struct timeval *)oldp;
NSInteger kernBootTimeOffset = [XHookSettings kernBootTimeOffset];
if (kernBootTimeOffset != 0) {
a->tv_sec += kernBootTimeOffset;
}
}
return nRet;
}
else if (name[0] == CTL_HW && name[1] == HW_MACHINE) {
NSString *modelName = [XHookSettings productStr];
const char *spoofedModel = [modelName UTF8String];
if (!spoofedModel) {
return %orig;
}
size_t modelLen = strlen(spoofedModel) + 1;
if (!oldp && oldlenp) {
*oldlenp = modelLen;
return 0;
}
if (oldp && oldlenp) {
if (*oldlenp < modelLen) {
return ENOMEM;
}
strlcpy((char *)oldp, spoofedModel, *oldlenp);
*oldlenp = modelLen;
return 0;
}
return EINVAL;
}
return %orig;
}
%hookf(int, sysctlbyname, const char *name, void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
if (strcmp(name, "hw.machine") == 0) {
int ret = %orig;
NSString *machine = [XHookSettings productStr];
if (oldp && machine) {
const char *hwMachineCh = [machine UTF8String];
if (hwMachineCh) {
size_t len = strlen(hwMachineCh);
if (*oldlenp > len) {
strlcpy((char *)oldp, hwMachineCh, *oldlenp);
*oldlenp = len;
}
}
}
return ret;
} else if (strcmp(name, "hw.model") == 0) {
int ret = %orig;
NSString *modelStr = [XHookSettings hwModel];
if (oldp && modelStr) {
const char *modelStrCh = [modelStr UTF8String];
if (modelStrCh) {
size_t len = strlen(modelStrCh);
if (*oldlenp > len) {
strlcpy((char *)oldp, modelStrCh, *oldlenp);
*oldlenp = len;
}
}
}
return ret;
}
return %orig;
}
%hookf(int, clock_gettime, clockid_t __clock_id, struct timespec *__tp) {
int nret = %orig;
if(__clock_id == CLOCK_MONOTONIC_RAW) {
// Reserved
}
return nret;
}
#pragma mark - Network Interface Helpers
static struct ifaddrs* createInterface(const char* name, const char* ipv4, const char* ipv6) {
if (!name || !ipv4 || !ipv6) return NULL;
@try {
struct ifaddrs *new_ifaddr = (struct ifaddrs *)calloc(1, sizeof(struct ifaddrs));
if (!new_ifaddr) return NULL;
new_ifaddr->ifa_name = strdup(name);
if (!new_ifaddr->ifa_name) {
free(new_ifaddr);
return NULL;
}
new_ifaddr->ifa_flags = IFF_UP | IFF_RUNNING;
struct sockaddr_in *addr_in = (struct sockaddr_in *)calloc(1, sizeof(struct sockaddr_in));
if (!addr_in) {
free(new_ifaddr->ifa_name);
free(new_ifaddr);
return NULL;
}
addr_in->sin_family = AF_INET;
if (inet_pton(AF_INET, ipv4, &addr_in->sin_addr) != 1) {
free(addr_in);
free(new_ifaddr->ifa_name);
free(new_ifaddr);
return NULL;
}
new_ifaddr->ifa_addr = (struct sockaddr *)addr_in;
struct ifaddrs *next_ifaddr = (struct ifaddrs *)calloc(1, sizeof(struct ifaddrs));
if (!next_ifaddr) {
free(addr_in);
free(new_ifaddr->ifa_name);
free(new_ifaddr);
return NULL;
}
next_ifaddr->ifa_name = strdup(name);
if (!next_ifaddr->ifa_name) {
free(next_ifaddr);
free(addr_in);
free(new_ifaddr->ifa_name);
free(new_ifaddr);
return NULL;
}
next_ifaddr->ifa_flags = IFF_UP | IFF_RUNNING;
struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)calloc(1, sizeof(struct sockaddr_in6));
if (!addr_in6) {
free(next_ifaddr->ifa_name);
free(next_ifaddr);
free(addr_in);
free(new_ifaddr->ifa_name);
free(new_ifaddr);
return NULL;
}
addr_in6->sin6_family = AF_INET6;
if (inet_pton(AF_INET6, ipv6, &addr_in6->sin6_addr) != 1) {
free(addr_in6);
free(next_ifaddr->ifa_name);
free(next_ifaddr);
free(addr_in);
free(new_ifaddr->ifa_name);
free(new_ifaddr);
return NULL;
}
next_ifaddr->ifa_addr = (struct sockaddr *)addr_in6;
new_ifaddr->ifa_next = next_ifaddr;
return new_ifaddr;
} @catch (NSException *exception) {
return NULL;
}
}
static void modifyInterfaceIP(struct ifaddrs *interface, const char *ipv4, const char *ipv6) {
if (!interface || !ipv4 || !ipv6) return;
@try {
if (interface->ifa_addr) {
if (((struct sockaddr_in*)interface->ifa_addr)->sin_family == AF_INET) {
struct sockaddr_in *addr = (struct sockaddr_in*)interface->ifa_addr;
inet_pton(AF_INET, ipv4, &addr->sin_addr);
} else if (((struct sockaddr_in*)interface->ifa_addr)->sin_family == AF_INET6) {
struct sockaddr_in6 *addr6 = (struct sockaddr_in6*)interface->ifa_addr;
inet_pton(AF_INET6, ipv6, &addr6->sin6_addr);
}
}
} @catch (NSException *exception) {
}
}
%hookf(int, getifaddrs, struct ifaddrs **interfaces) {
if (!interfaces) return EINVAL;
int nRet = %orig;
if (nRet != 0) return nRet;
@try {
NSDictionary *networkConfig = [XHookSettings networkInterfacesInfo];
if (!networkConfig) {
return nRet;
}
struct ifaddrs *interface;
bool isHookEn0IpV4 = false;
for (interface = *interfaces; interface; interface = interface->ifa_next) {
if (!interface->ifa_name) continue;
NSString *name = @(interface->ifa_name);
if ([name isEqualToString:@"en0"]) {
NSDictionary *en0Config = networkConfig[@"en0"];
if (en0Config) {
const char *ipv4 = [en0Config[@"ipv4"] UTF8String];
const char *ipv6 = [en0Config[@"ipv6"] UTF8String];
if (ipv4 && ipv6) {
modifyInterfaceIP(interface, ipv4, ipv6);
isHookEn0IpV4 = true;
}
}
}
}
if (!isHookEn0IpV4) {
NSDictionary *en0Config = networkConfig[@"en0"];
if (en0Config) {
const char *ipv4 = [en0Config[@"ipv4"] UTF8String];
const char *ipv6 = [en0Config[@"ipv6"] UTF8String];
struct ifaddrs *new_en0 = createInterface("en0", ipv4, ipv6);
if (new_en0) {
new_en0->ifa_next->ifa_next = *interfaces;
*interfaces = new_en0;
}
}
}
NSDictionary *pdpConfig = networkConfig[@"pdp_ip0"];
if (pdpConfig) {
const char *ipv4 = [pdpConfig[@"ipv4"] UTF8String];
const char *ipv6 = [pdpConfig[@"ipv6"] UTF8String];
struct ifaddrs *new_pdp = createInterface("pdp_ip0", ipv4, ipv6);
if (new_pdp) {
new_pdp->ifa_next->ifa_next = *interfaces;
*interfaces = new_pdp;
}
}
} @catch (NSException *exception) {
}
return nRet;
}
%hookf(Boolean, SCNetworkReachabilityGetFlags, SCNetworkReachabilityRef target, SCNetworkReachabilityFlags *flags) {
Boolean result = %orig(target, flags);
if (result && flags != NULL) {
*flags |= kSCNetworkReachabilityFlagsReachable;
*flags |= kSCNetworkReachabilityFlagsIsWWAN;
}
return result;
}
%hookf(BOOL, UIAccessibilityIsClosedCaptioningEnabled) {
return YES;
}
%hookf(BOOL, UIAccessibilityIsMonoAudioEnabled) {
return YES;
}
%end // end of %group XHooks
#pragma mark - ============== CONSTRUCTOR & DESTRUCTOR ==============
%ctor {
NSLog(@"XHook: Starting...");
@try {
@autoreleasepool {
NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
NSString *jsonPath = @"/var/mobile/Documents/changeapp.json";
BOOL loaded = [XHookSettings loadSettingsFromPath:jsonPath];
if (!loaded) {
NSLog(@"XHook: Failed to load settings from %@", jsonPath);
return;
}
if ([XHookSettings shouldHookApp:bundleIdentifier]) {
NSUUID *idfa = [XHookSettings idfa];
SetupXSLog();
NSLog(@"XHook: Hooks started for %@; IDFA: %@", bundleIdentifier, idfa);
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"kXHookSSFaceKey"];
%init(XHooks);
} else {
NSLog(@"XHook: App %@ not in hook list, skipping", bundleIdentifier);
}
}
} @catch (NSException *exception) {
NSLog(@"XHook: Error in ctor: %@", exception);
}
}
%dtor {
NSLog(@"XHook: Cleaning up...");
[XHookSettings cleanup];
}