
#import <Foundation/Foundation.h>
#import <sys/utsname.h>
#include <sys/sysctl.h>
#import <mach/mach_time.h>
#import <UIKit/UIKit.h>
#import <WebKit/WebKit.h>
#import <ifaddrs.h> // 获取ip
#import <arpa/inet.h> // 获取ip
#import <net/if.h> // 获取ip
#import <net/if_dl.h>
#import <SystemConfiguration/CaptiveNetwork.h>
#import <CoreTelephony/CTCarrier.h>
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
#import <SystemConfiguration/SystemConfiguration.h>
// #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 140000
#import <AppTrackingTransparency/AppTrackingTransparency.h>
// #endif
#import <SpringBoard/SpringBoard.h>
#import <CoreMotion/CoreMotion.h>
#import <objc/runtime.h>
#import "XSLog.h"

__attribute__((constructor)) static void SetupXSLog() {
    XSLogSetupLogWithFilePath(@"/var/mobile/Documents/App.log", 50 * 1024 * 1024);
    XSLogRedirectNSLog();
}


typedef void (^tryGetValCallback)(id parameter);


// iOS版本检查宏
#define iOS14_OR_LATER() (@available(iOS 14, *))


@interface SBLockScreenManager : NSObject
- (BOOL)unlockUIFromSource:(int)source withOptions:(id)options;
- (void)lockUIFromSource:(int)source withOptions:(id)options;
@end



NSDictionary *settings;



NSUUID* str2uuid(NSString *str) {
    return [[NSUUID alloc] initWithUUIDString:str];
} 

NSInteger str2int(NSString *str) {
   return [str integerValue];
}
float str2float(NSString *str) {
    return [str floatValue];
}
double str2double(NSString *str) {
    return [str doubleValue];
}

unsigned long long str2ull(NSString *str)  { 
    return [str longLongValue];
}

void tryGetVal(NSString *key, tryGetValCallback block) {
    @try {
        if (!key || !block || !settings) return;
        
        id data = settings[key];
        if (data) {
            block(data);
        }
    } @catch (NSException *exception) {
        NSLog(@"Error in tryGetVal for key %@: %@", key, exception);
    }
}

const char* str2chars(NSString *str) {
    const char *cString = [str UTF8String];
    return cString; 
}


%group ohno

// #if __IPHONE_OS_VERSION_MAX_ALLOWED < 140000


// #endif

// group ohho start


// #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 140000

%hook ATTrackingManager

+ (ATTrackingManagerAuthorizationStatus)trackingAuthorizationStatus {
    __block ATTrackingManagerAuthorizationStatus originalStatus = %orig;
    NSLog(@"start hook trackingAuthorizationStatus");
    NSLog(@"[ATTrackingManager Hook] Original trackingAuthorizationStatus: %lu", (unsigned long)originalStatus);
    
    // 你可以在这里修改返回值
    // 例如，总是返回已授权状态：
    // return 3; // ATTrackingManagerAuthorizationStatusAuthorized
    tryGetVal(@"trackingStatus", ^(id parameter) {
        NSLog(@"[ATTrackingManager Hook] API trackingAuthorizationStatus: %@", parameter); 
        originalStatus = str2int(parameter); 
    });

      NSLog(@"[ATTrackingManager Hook] New trackingAuthorizationStatus: %lu", (unsigned long)originalStatus); 
    // 或者，你可以直接返回原始值
    return originalStatus;

}

+ (void)requestTrackingAuthorizationWithCompletionHandler:(void (^)(ATTrackingManagerAuthorizationStatus status))completion {
    NSLog(@"[ATTrackingManager Hook] requestTrackingAuthorizationWithCompletionHandler called");
    __block ATTrackingManagerAuthorizationStatus attStatus = 3;
    tryGetVal(@"trackingStatus", ^(id parameter) {
        NSLog(@"[ATTrackingManager Hook] API trackingAuthorizationStatus: %@", parameter); 
        attStatus = str2int(parameter); 
    });
     // 模拟延迟（真实的授权对话框有延迟）
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        if (completion) {
            completion(attStatus);
        }
    });
    
    // 调用原始方法
    // %orig(completion);
}

%end
// #endif

%hook ASIdentifierManager

-(NSUUID*)advertisingIdentifier
{
    // 修改IDFA
	NSLog(@"start hook idfa");
	__block NSUUID *idfa = %orig;
    // reloadConfig();
    tryGetVal(@"idfa", ^(id parameter) {
        idfa = str2uuid(parameter);
    });
    NSLog(@"hook idfa: %@", idfa);
    return idfa;
}
-(BOOL) isAdvertisingTrackingEnabled {
     NSLog(@"[ATTrackingManager Hook] isAdvertisingTrackingEnabled called");
    __block BOOL res = %orig; 
    tryGetVal(@"trackingStatus", ^(id parameter) {
        NSLog(@"[ATTrackingManager Hook] API isAdvertisingTrackingEnabled: %@", parameter);  
        NSInteger status = str2int(parameter);
        res = (status >= 3 ? YES : NO);
    }); 
    return res;
}

%end

// static BOOL orientationMonitoringEnabled = NO;

%hook UIDevice
// IDFV
-(NSUUID*)identifierForVendor{
    NSLog(@"start hook idfv");
    __block NSUUID *idfv = %orig;
    tryGetVal(@"idfv", ^(id parameter) {
        idfv = str2uuid(parameter);
    });
    NSLog(@"hook idfv: %@", idfv);
    return idfv;
}

- (NSString *)name{
    NSLog(@"start hook device name");
    __block NSString *name = %orig;
    tryGetVal(@"deviceName", ^(id parameter) {
        name = parameter;
    });
    NSLog(@"hook device name: %@", name);
    return name;
}

- (NSString *)model{
    return %orig;
}

- (NSString *)localizedModel{
    return %orig;
}

- (NSString *)systemName{
    return %orig;
}

- (NSString *)systemVersion{
    NSLog(@"start hook system version");
    __block NSString *systemVersion = %orig;
    tryGetVal(@"osVersion", ^(id parameter) {
        systemVersion = parameter;
    });
    NSLog(@"hook system version: %@", systemVersion);
    return systemVersion; 
}

- (UIDeviceBatteryState)batteryState {
    NSLog(@"start hook batteryState");
    __block UIDeviceBatteryState res = %orig;
    tryGetVal(@"batteryState", ^(id parameter) {
        NSInteger intVal = str2int(parameter);
        res = (UIDeviceBatteryState)intVal; 
    });
    return res;
}

- (float)batteryLevel {
    // 随机电量
    NSLog(@"start hook batteryLevel");
    __block float res = %orig;
    tryGetVal(@"batteryLevel", ^(id parameter) {
        res = str2float(parameter);
    });  
    return res;
}

- (UIDeviceOrientation)orientation {
    return UIDeviceOrientationPortrait;
}

%end

%hook NSProcessInfo

- (NSTimeInterval) systemUptime {
  // 开机时间
  NSLog(@"start hook systemUptime"); 
    __block NSTimeInterval res = %orig;
    tryGetVal(@"systemUptime", ^(id parameter) {
        double v = str2double(parameter);
        if(v > -1.0f) {
            res = v + res;
        }
    });
    return res;
}

- (unsigned long long) physicalMemory {
    // 内存
    NSLog(@"start hook physicalMemory"); 
    __block unsigned long long memory = %orig;
    tryGetVal(@"physicalMemory", ^(id parameter) {
       unsigned long long t = str2ull(parameter);
       if(t > 1000) {
        memory = t;
       }
    });
    NSLog(@"hook physicalMemory: %llu", memory);
    return memory;
}

- (NSUInteger) processorCount {
    NSLog(@"start hook processorCount"); 
    __block NSUInteger res = %orig;
     tryGetVal(@"cpuCore", ^(id parameter) {
       NSUInteger t = str2int(parameter);
       if(t > 0) {
        res = t;
       }
    }); 
    return res;
}

- (NSOperatingSystemVersion)operatingSystemVersion {
    NSOperatingSystemVersion version = %orig;
     __block NSString *versionString = @"";
    tryGetVal(@"osVersion", ^(id parameter) {
        versionString = parameter;
    });
    
    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

%hook UIWindow
-  (UIEdgeInsets) safeAreaInsets {
    NSLog(@"start hook safeAreaInsets"); 
    __block UIEdgeInsets originalInsets = %orig;
    %log(@"Original safeAreaInsets: %@", NSStringFromUIEdgeInsets(originalInsets));
    
    tryGetVal(@"safeAreaInsets", ^(id parameter) {
       NSDictionary *dic = parameter;
        // 修改 safeAreaInsets
        UIEdgeInsets modifiedInsets = UIEdgeInsetsMake(
            originalInsets.top = str2double(dic[@"top"]),    // 增加顶部安全区域
            originalInsets.left = 0,    // 增加左侧安全区域
            originalInsets.bottom = str2double(dic[@"bottom"]), // 增加底部安全区域
            originalInsets.right  = 0    // 增加右侧安全区域
        );
        originalInsets = modifiedInsets;
    }); 
    
    %log(@"Modified safeAreaInsets: %@", NSStringFromUIEdgeInsets(originalInsets));
    return originalInsets;
}
%end

%hook UIScreen
- (CGFloat) brightness {
    // 随机亮度
    NSLog(@"start hook brightness"); 
    __block CGFloat originalBrightness = %orig;
     tryGetVal(@"screenBrightness", ^(id parameter) {
        double fat = str2double(parameter);
        if(fat > -1.0f) {
            originalBrightness = fat;
        } 
     });
    
    return originalBrightness;
}
- (CGRect)bounds {
     NSLog(@"start hook bounds"); 
    __block CGRect originalBounds = %orig;
    tryGetVal(@"screenBounds", ^(id parameter) {
        NSDictionary *dic = parameter;
        double w = str2double(dic[@"x"]);
        double h = str2double(dic[@"y"]);
        CGRect newBounds = {
            .origin = {.x = 0, .y = 0},
            .size = {.width = w, .height = h},
        }; 
        originalBounds = newBounds;
    });
    return originalBounds;
}
- (CGFloat) scale {
    NSLog(@"start hook scale"); 
    __block CGFloat originalScale = %orig;
    tryGetVal(@"screenScale", ^(id parameter) {
        double fat = str2double(parameter);
        if(fat > -1.0f) {
            originalScale = fat;
        }
    });
    return originalScale;
}
- (CGRect)nativeBounds {
     NSLog(@"start hook nativeBounds"); 
     __block CGRect originalBounds = %orig;
    tryGetVal(@"screenBounds", ^(id parameter) {
        NSDictionary *dic = parameter;
        double w = str2double(dic[@"nx"]);
        double h = str2double(dic[@"ny"]);
        CGRect newBounds = {
            .origin = {.x = 0, .y = 0},
            .size = {.width = w, .height = h},
        }; 
        originalBounds = newBounds;
    });
    return originalBounds;
}

- (BOOL)isCaptured {
    // 总是返回NO,表示屏幕没有被捕获(镜像)
    return NO;
}

- (UIScreen *)mirroredScreen {
    // 总是返回nil,表示没有镜像屏幕
    return nil;
}

%end

%hook AVAudioSession
- (float) outputVolume {
    // 音量
     NSLog(@"start hook outputVolume"); 
    __block float originalVolume = %orig;
    tryGetVal(@"outputVolume", ^(id parameter) {
        float fat = str2float(parameter);
        if(fat > -1.0f) {
            originalVolume = fat;
        }
    });
    return originalVolume;
}
%end

%hook UIScreenMode

- (CGSize)size {
    // 修改屏幕大小信息
     NSLog(@"start hook bounds"); 
    __block CGSize originalSize = %orig;
    tryGetVal(@"screenBounds", ^(id parameter) {
        NSDictionary *dic = parameter;
        double w = str2double(dic[@"x"]);
        double h = str2double(dic[@"y"]);
        CGSize newBounds = {
             .width = w,
              .height = h
        }; 
        originalSize = newBounds;
    });
    return originalSize; 
}

%end

%hook NSFileManager
- (NSDictionary<NSFileAttributeKey, id> *) attributesOfFileSystemForPath:(NSString *)path error:(NSError **)error {
    // 磁盘信息
    NSLog(@"start hook disk info");
    NSDictionary<NSFileAttributeKey, id> *res = %orig;
    // int64_t size = [info[NSFileSystemSize] longLongValue]; // 总大小
    // int64_t space =  [[info objectForKey:NSFileSystemFreeSize] longLongValue];
    if ([path isEqualToString:NSHomeDirectory()]) {
        NSMutableDictionary *modifiedAttributes = [res mutableCopy];
        // 修改或添加属性
        tryGetVal(@"diskSize", ^(id parameter) {
            int64_t fat = str2ull(parameter);
            if(fat > 0) {
                modifiedAttributes[NSFileSystemSize] = @(fat); // 1 GB
            }
        });
        tryGetVal(@"diskFreeSize", ^(id parameter) {
            int64_t fat = str2ull(parameter);
            if(fat > 0) {
                modifiedAttributes[NSFileSystemFreeSize] = @(fat); // 1 GB
            }
        }); 
     
        return [modifiedAttributes copy];
    }
    
    return res;
}
// 反越狱检测
- (BOOL)fileExistsAtPath:(NSString *)event {
    NSLog(@"start hook fileExistsAtPath"); 
    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) {
        NSLog(@"9999999==%@=",event);
        return NO;
    }
    return  %orig;
}
%end

%hook NSLocale
+ (NSArray *) preferredLanguages {
    // 语言
    NSLog(@"start hook preferredLanguages"); 
    return @[@"en-US"];
}
+ (NSLocale *)currentLocale {
    // 如果你想修改返回的 locale，可以在这里进行修改
    // 例如，强制返回一个特定的 locale：
     NSLog(@"start hook currentLocale"); 
    __block NSLocale *res = %orig;
    tryGetVal(@"locale", ^(id parameter) {
        NSString *loc = parameter;
        res = [[NSLocale alloc] initWithLocaleIdentifier:loc]; 
    });  
    return res;
}
+ (NSLocale *)systemLocale {
    NSLog(@"start hook systemLocale"); 
    __block NSLocale *res = %orig;
    tryGetVal(@"locale", ^(id parameter) {
        NSString *loc = parameter;
        res = [[NSLocale alloc] initWithLocaleIdentifier:loc]; 
    });  
    return res;
}

%end

%hook NSTimeZone


+ (NSTimeZone *)localTimeZone {
    // NSTimeZone *originalTimeZone = %orig;
    // NSLog(@"[HOOK] Local time zone accessed: %@", [originalTimeZone name]);
    
    // 如果你想修改返回的时区，可以在这里进行修改
    // 例如，强制返回一个特定的时区：
    NSLog(@"start hook localTimeZone"); 
     __block NSTimeZone *res = %orig;
    tryGetVal(@"timeZone", ^(id parameter) {
        NSString *loc = parameter;
        res = [NSTimeZone timeZoneWithName:loc]; 
    });  
    return res; 
    // return originalTimeZone;
}

+ (NSTimeZone *)systemTimeZone {
    NSLog(@"start hook systemTimeZone"); 
    __block NSTimeZone *res = %orig;
    tryGetVal(@"timeZone", ^(id parameter) {
        NSString *loc = parameter;
        res = [NSTimeZone timeZoneWithName:loc]; 
    });  
    return res; 
}

+ (NSTimeZone *)defaultTimeZone {
    NSLog(@"start hook defaultTimeZone"); 
    __block NSTimeZone *res = %orig;
    tryGetVal(@"timeZone", ^(id parameter) {
        NSString *loc = parameter;
        res = [NSTimeZone timeZoneWithName:loc]; 
    });  
    return res; 
}


%end

// 状态栏
%hook UIStatusBarManager
- (CGRect) statusBarFrame {
    NSLog(@"start hook statusBarFrame"); 
    __block CGRect originalFrame = %orig;
    tryGetVal(@"safeAreaInsets", ^(id parameter) {
        NSDictionary *dic = parameter;
        double barHeight = str2double(dic[@"height"]);
        CGSize tempSize = {.width = originalFrame.size.width, .height = barHeight};
        originalFrame.size = tempSize; 
    });
    return originalFrame; 
}
%end

%hook NSMutableURLRequest
// Maybe server side checks the user agent?
- (instancetype)initWithURL:(NSURL *)URL {
    self = %orig(URL);
    if (self) {
        tryGetVal(@"userAgent", ^(id parameter) {
            [self setValue:parameter forHTTPHeaderField:@"User-Agent"];  
        });
    }
    return self;
}

- (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field {
    __block NSString *_userAgent = value;
    if ([field isEqualToString:@"User-Agent"]) {
        // 修改User Agent
        tryGetVal(@"userAgent", ^(id parameter) {
            _userAgent = parameter;
        });
    }
    %orig(_userAgent, field);
}

%end

%hook NSURLSession

+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration {
    NSLog(@"start hook sessionWithConfiguration"); 
    //if (configuration.HTTPAdditionalHeaders[@"User-Agent"]) {
        tryGetVal(@"userAgent", ^(id parameter) { 
            configuration.HTTPAdditionalHeaders = @{@"User-Agent": parameter};
        }); 
    //}
    return %orig;
}

- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request 
                           completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler {
    NSMutableURLRequest *mutableRequest = [request mutableCopy];
       tryGetVal(@"userAgent", ^(id parameter) { 
        [mutableRequest setValue:parameter forHTTPHeaderField:@"User-Agent"];
    }); 
    
    return %orig(mutableRequest, completionHandler);
}

%end

%hook WKWebView

- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^)(id, NSError *error))completionHandler {
     NSLog(@"start hook evaluateJavaScript"); 
    %log(@"Evaluating JavaScript: %@", javaScriptString);
    __block NSString *userAgent = nil;
    tryGetVal(@"userAgent", ^(id parameter) { 
        userAgent = parameter;
    }); 
    if(userAgent) {
        [self setCustomUserAgent:userAgent]; 
    }
    %orig(javaScriptString, completionHandler);
}

- (void)setCustomUserAgent:(NSString *)userAgent {
    __block NSString *_userAgent = userAgent;
    tryGetVal(@"userAgent", ^(id parameter) { 
        _userAgent = parameter;
    }); 
    %orig(_userAgent);
}

- (NSString *)customUserAgent {
    // 获取原来的 User-Agent
    __block NSString *userAgent = %orig;

    tryGetVal(@"userAgent", ^(id parameter) { 
        userAgent = parameter;
    }); 
    
    // 返回修改后的 User-Agent
    return userAgent;
}

%end



%hook CTTelephonyNetworkInfo
- (NSDictionary<NSString *, NSString *> *) serviceCurrentRadioAccessTechnology {
    NSLog(@"start hook serviceCurrentRadioAccessTechnology"); 
   NSDictionary<NSString *, NSString *> *originalTechnologies = %orig;
    %log(@"Original Radio Access Technologies: %@", originalTechnologies);

   NSMutableDictionary<NSString *, NSString *> *modifiedProviders = [[NSMutableDictionary alloc] init];
  
   tryGetVal(@"simInfo", ^(id parameter) {
        NSDictionary *simInfoDic = parameter; 
        for(NSString *service in simInfoDic.allKeys) {
            NSDictionary *dic = simInfoDic[service]; 
            NSString *wwan = dic[@"wwan"]; 
            if([wwan isEqual:@"5G"]) {
                [modifiedProviders setValue:@"CTRadioAccessTechnologyNR" forKey:service];
            } else {
               [modifiedProviders setValue:@"CTRadioAccessTechnologyLTE" forKey:service]; 
            } 
        }
    });  

    if([modifiedProviders count] > 0) {
        return [modifiedProviders copy]; 
    }
    return originalTechnologies; 
}
- (NSDictionary<NSString *, CTCarrier *> *)serviceSubscriberCellularProviders {
    NSLog(@"start hook serviceSubscriberCellularProviders"); 
    NSDictionary<NSString *, CTCarrier *> *originalProviders = %orig;
    %log(@"Original Cellular Providers: %@", originalProviders);

   NSMutableDictionary<NSString *, CTCarrier *> *modifiedProviders = [[NSMutableDictionary alloc] init];
  
   tryGetVal(@"simInfo", ^(id parameter) {
        NSDictionary *simInfoDic = parameter; 
        for(NSString *service in simInfoDic.allKeys) {
            NSDictionary *dic = simInfoDic[service]; 
            if (!dic) {
                continue;
            }
            if (![dic[@"id"] isEqual:[NSNull null]]) {
                [[NSUserDefaults standardUserDefaults] setValue:dic[@"id"] forKey:@"lux-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 setValue:carrier forKey:service];
        }
    });  

    if([modifiedProviders count] > 0) {
        return [modifiedProviders copy]; 
    }
    return originalProviders;
}
%end

// 添加随机函数
static double randomRadiansPerSecond() {
    double randomValue = (double)arc4random() / UINT32_MAX;
    return (randomValue * 20.0) - 10.0;
}
// 创建 CMGyroData 的子类
@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) {
        
        if(gyroData) {
            CMRotationRate originalRate = gyroData.rotationRate;
            
            // 在这里，你可以修改或记录 rotationRate
            NSLog(@"Gyro RotationRate - x: %f, y: %f, z: %f", 
                  originalRate.x, originalRate.y, originalRate.z);
        }
             // 设置随机的旋转速率
            CMRotationRate randomRate;
            randomRate.x = randomRadiansPerSecond();
            randomRate.y = randomRadiansPerSecond();
            randomRate.z = randomRadiansPerSecond();

            // 如果你想修改值，可以这样做：
            // 创建自定义的 CMGyroData 对象
            CustomCMGyroData *customGyroData = (CustomCMGyroData *)[[objc_getClass("CMGyroData") alloc] init];
            // Objective-C 没有直接的方法来修改 CMGyroData 的值，所以这里我们只是记录
                // 设置自定义数据
            customGyroData.customRotationRate = randomRate;
             // 调用原始处理程序，但使用我们的自定义数据
            if (handler) {
                handler((CMGyroData *)customGyroData, error);
            }
    };
    
    %orig(queue, newHandler);
}

%end


// int uname(struct utsname *);
%hookf(int, uname, struct utsname * systemInfo) {
    NSLog(@"start hook uname");
	int nRet = %orig; 
    tryGetVal(@"productStr", ^(id parameter) { 
        char str_machine_name[100];
        [parameter getCString:str_machine_name maxLength:100 encoding:NSUTF8StringEncoding];
        strcpy(systemInfo->machine,str_machine_name);
    }); 
	return nRet; // Call the original implementation of this function
    
}

%hookf(int, sysctl, const int *name, u_int namelen, void *oldp, size_t *oldlenp, const void *newp, size_t newlen) {
    NSLog(@"start hook sysctl");
    
    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;
            tryGetVal(@"kernBootTime", ^(id parameter) { 
                int kernBootTime = str2int(parameter);
                a->tv_sec = kernBootTime + a->tv_sec;
            }); 
        }
        return nRet;
    } 
    else if(name[0] == CTL_HW && name[1] == HW_MACHINE) {
        __block NSString *modelName = @"iPhone14,2";
        tryGetVal(@"productStr", ^(id parameter) { 
            if(parameter) {
                modelName = parameter;    
            }
        });
        
        const char *spoofedModel = [modelName UTF8String];
        if (!spoofedModel) {
            return %orig;
        }
        
        size_t modelLen = strlen(spoofedModel) + 1; // +1 for null terminator
        
        // 查询缓冲区大小
        if (!oldp && oldlenp) {
            *oldlenp = modelLen;
            return 0;
        }
        
        // 复制数据
        if (oldp && oldlenp) {
            if (*oldlenp < modelLen) {
                // 缓冲区太小，返回错误
                return ENOMEM;
            }
            
            // 安全复制字符串
            strlcpy((char*)oldp, spoofedModel, *oldlenp);
            *oldlenp = modelLen;
            NSLog(@"sysctl model copied: %@", modelName);
            return 0;
        }
        
        return EINVAL;
    }
    
    // 其他情况调用原函数
    return %orig;
}

// 安全的字符串复制函数
static BOOL safe_copy_string(void *dst, size_t *dstlen, const char *src) {
    if (!dst || !dstlen || !src) return NO;
    
    size_t srclen = strlen(src);
    size_t needed = srclen + 1;
    
    if (*dstlen < needed) {
        *dstlen = needed;
        return NO;
    }
    
    strlcpy(dst, src, *dstlen);
    *dstlen = srclen;
    return YES;
}

%hookf(int, sysctlbyname, const char *name, void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
    NSLog(@"start hook sysctlbyname");
	if (strcmp(name, "hw.machine") == 0) {
        NSLog(@"start hook sysctlbyname new machine");
        int ret = %orig;
        __block NSString *machine = nil;
        tryGetVal(@"productStr", ^(id parameter) {
            if (parameter) { 
                NSString *temp = parameter;
                machine = [temp copy];
                NSLog(@"machine,%@", temp);
            }
        });
        if (oldp && machine) {
            NSLog(@"machine,1");
                // char str_machine_name[100];
            const char *hwMachineCh = [machine UTF8String];
                // [parameter getCString:str_machine_name maxLength:100 encoding:NSUTF8StringEncoding];
                //strcpy((char *)oldp, hwMachineCh);
            if (hwMachineCh) {

                 NSLog(@"machine,2,%@", machine);
                 size_t len = strlen(hwMachineCh);
                if (*oldlenp > len) {
                    strlcpy((char *)oldp, hwMachineCh, *oldlenp); // 使用安全的字符串复制
                    *oldlenp = len;
                }
                //strncpy((char *)oldp, hwMachineCh, strlen(hwMachineCh));
            }
        }
        return ret;
    } else if (strcmp(name, "hw.model") == 0)  {
        NSLog(@"start hook sysctlbyname new model");
        int ret = %orig;
        __block NSString *modelStr = nil;
        tryGetVal(@"hwModel", ^(id parameter) {
            if (parameter) { 
                NSString *temp = parameter;
                modelStr = [temp copy];
                NSLog(@"model,%@", temp); 
            }
        });
        if (oldp && modelStr) {
            NSLog(@"model,1");
                // char str_machine_name[100];
            const char *modelStrCh = [modelStr UTF8String];
                // [parameter getCString:str_machine_name maxLength:100 encoding:NSUTF8StringEncoding];
                //strcpy((char *)oldp, hwMachineCh);
            if (modelStrCh) {
                NSLog(@"model,2");
                strncpy((char *)oldp, modelStrCh, strlen(modelStrCh));
            }
        }
        return ret;
    } else {
        NSLog(@"start hook sysctlbyname old");
        return %orig;
    }
}

// int clock_gettime(clockid_t __clock_id, struct timespec *__tp);
%hookf(int, clock_gettime, clockid_t __clock_id, struct timespec *__tp) {
    NSLog(@"start hook clock_gettime"); 
    int nret = %orig;
    if(__clock_id == CLOCK_MONOTONIC_RAW) {
      // __tp->tv_sec = 20;
      // __tp->tv_nsec = 20;
    }
    return nret;
}

// 修改ip

// 辅助函数：创建网络接口
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;
        
        // 创建IPv4地址结构
        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;
        }
        
        // 设置IPv4地址
        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;
        
        // 创建IPv6结构
        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;
        }
        
        // 设置IPv6名称
        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;
        
        // 创建IPv6地址结构
        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;
        }
        
        // 设置IPv6地址
        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) {
        NSLog(@"Error creating interface: %@", exception);
        return NULL;
    }
}

// 修改现有接口的IP地址
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) {
        NSLog(@"Error modifying interface IP: %@", exception);
    }
}

%hookf(int, getifaddrs, struct ifaddrs **interfaces) {
    if (!interfaces) return EINVAL;
    
    int nRet = %orig;
    if (nRet != 0) return nRet;
    
    @try {
        // 获取网络配置
        __block NSDictionary *networkConfig = nil;
        tryGetVal(@"networkInterfacesInfo", ^(id parameter) {
            if ([parameter isKindOfClass:[NSDictionary class]]) {
                networkConfig = parameter;
            }
        });
        
        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;
                }
            }
        }
        
        // 添加pdp_ip0接口
        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) {
        NSLog(@"Error in getifaddrs hook: %@", exception);
    }
    
    return nRet;
}



/* Boolean
SCNetworkReachabilityGetFlags			(
						SCNetworkReachabilityRef	target,
						SCNetworkReachabilityFlags	*flags
						)
*/

%hookf(Boolean, SCNetworkReachabilityGetFlags, SCNetworkReachabilityRef target, SCNetworkReachabilityFlags *flags) {
    NSLog(@"start hook SCNetworkReachabilityGetFlags"); 
    Boolean result = %orig(target, flags);
    
    if (result && flags != NULL) {
        // 可以在这里修改 flags 的值
        // 例如，总是添加 kSCNetworkReachabilityFlagsReachable 标志
        *flags |= kSCNetworkReachabilityFlagsReachable;
        *flags |= kSCNetworkReachabilityFlagsIsWWAN; 
    }
    
    return result;
}


%hookf(BOOL,UIAccessibilityIsClosedCaptioningEnabled) {
    return YES;
}



%hookf(BOOL,UIAccessibilityIsMonoAudioEnabled) {
    return YES;
}


// group ohho end
%end




%ctor{
    NSLog(@"start hook");
     @try {
     @autoreleasepool {
        NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
        //NSLog(@"print -- %@",bundleIdentifier);
        NSString *bundleId = @"org.xyzshell.NotNil";
        NSString *plistPath = [NSString stringWithFormat:@"/var/mobile/Library/Preferences/%@.plist", bundleId];
        // 创建文件管理器实例
        NSFileManager *fileManager = [NSFileManager defaultManager];
            
            // 检查文件是否存在
        BOOL fileExists = [fileManager fileExistsAtPath:plistPath];
        if(fileExists) {
            settings = [[NSDictionary alloc] initWithContentsOfFile:plistPath];
            NSArray *pkgs = settings[@"apps"];
    
            if([pkgs indexOfObject:bundleIdentifier] != NSNotFound){
                NSLog(@"hooks start %@", bundleIdentifier);
                // 指定需要运行的执行的分组代码，%init有两种用法，这里只展示一种
                [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"kLuxSSFaceKey"];
                %init(ohno);
            }
        }
    }
   } @catch (NSException *exception) {
        NSLog(@"Error in ctor: %@", exception);
    }
}

static void cleanup() {
    // 清理分配的资源
    if (settings) {
        settings = nil;
    }
    // 其他清理工作
}

%dtor {
    cleanup();
}