ios-hooks/ios-change-info/Tweak.x
2025-11-13 17:40:14 +08:00

1241 lines
38 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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();
}