// // ZZHUtils.m // HD wallpaper // // Created by aaa on 2024/7/16. // #import "ZZHUtils.h" #include #include #import #import #import #import #import #import #import #import #import #import #import #import #import #import #include #include #include #include #include #import "ifaddrs.h" #import #import #import "resolv.h" @implementation ZZHUtils + (long long)collectKernelBootTimeMillis { struct timeval bootTime; int mib[2] = {CTL_KERN,KERN_BOOTTIME}; size_t size = sizeof(bootTime); if (sysctl(mib, 2, &bootTime, &size, NULL, 0) != -1) { return bootTime.tv_sec * 1000;///秒 }; return 0; } + (long long)collectMonotonicRawClockTimeMillis { struct timespec tp; if(clock_gettime(CLOCK_MONOTONIC_RAW, &tp) != -1) { long xx = tp.tv_sec*1000 + tp.tv_nsec/1000000; return xx; } return 0; } + (unsigned long long)collectAccessibilityFeatures { NSInteger features = 0; if (UIAccessibilityIsClosedCaptioningEnabled()) { features |= 0x2; } if (UIAccessibilityIsMonoAudioEnabled()) { features |= 0x4; } if (UIAccessibilityIsReduceMotionEnabled()) { features |= 0x8; } if (UIAccessibilityIsGuidedAccessEnabled()) { features |= 0x10; } if (UIAccessibilityIsInvertColorsEnabled()) { features |= 0x20; } if (UIAccessibilityIsVoiceOverRunning()) { features |= 0x40; } if (UIAccessibilityDarkerSystemColorsEnabled()) { features |= 0x80; } if (UIAccessibilityIsBoldTextEnabled()) { features |= 0x100; } if (UIAccessibilityIsGrayscaleEnabled()) { features |= 0x200; } if (UIAccessibilityIsReduceTransparencyEnabled()) { features |= 0x400; } if (UIAccessibilityIsSpeakScreenEnabled()) { features |= 0x800; } if (UIAccessibilityIsSpeakSelectionEnabled()) { features |= 0x1000; } if (UIAccessibilityIsSwitchControlRunning()) { features |= 0x2000; } if (UIAccessibilityIsShakeToUndoEnabled()) { features |= 0x4000; } if (UIAccessibilityIsAssistiveTouchRunning()) { features |= 0x8000; } if (UIAccessibilityHearingDevicePairedEar() != 0) { features |= 0x400000; } if (@available(iOS 13.0, *)) { if ([UITraitCollection currentTraitCollection].userInterfaceStyle == UIUserInterfaceStyleDark) { features |= 0x10000; } if (UIAccessibilityIsOnOffSwitchLabelsEnabled()) { features |= 0x20000; } if (UIAccessibilityIsVideoAutoplayEnabled()) { features |= 0x40000; } if (UIAccessibilityShouldDifferentiateWithoutColor()) { features |= 0x80000; } if (@available(iOS 14.0, *)) { if (UIAccessibilityPrefersCrossFadeTransitions()) { features |= 0x100000; } if (UIAccessibilityButtonShapesEnabled()) { features |= 0x200000; } } } NSLog(@"features:\n%ld",features); return features; } + (NSString *)collectDeviceKeyboards{ NSArray *lanagues = [NSLocale preferredLanguages]; __block NSString *str = @""; [lanagues enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { if (idx < lanagues.count-1) { str = [str stringByAppendingFormat:@"%@,",obj]; } else { str = [str stringByAppendingFormat:@"%@",obj]; } }]; return str; } + (void)userAgent { static WKWebView *webView = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ webView = [WKWebView new]; }); [webView evaluateJavaScript:@"function getAgent() {return navigator.userAgent;} getAgent(); " completionHandler:^(id _Nullable result, NSError * _Nullable error) { NSLog(@"zzh the useragent:%@ ",result); }]; // NSString *geoStr = @"if (\"geolocation\" in navigator) { navigator.geolocation.getCurrentPosition(function(position) { console.log(\"Latitude is :\", position.coords.latitude);console.log(\"Longitude is :\", position.coords.longitude);}, function(error) {console.error(\"Error Code = \" + error.code + \" - \" + error.message);});"; // // [webView evaluateJavaScript:geoStr completionHandler:^(id _Nullable result, NSError * _Nullable error) { // NSLog(@"zzh the geo err:%@ ",error); // }]; } + (BOOL)isReachableViaWWAN { SCNetworkReachabilityFlags flags; struct sockaddr_in zeroAddress; bzero(&zeroAddress, sizeof(zeroAddress)); zeroAddress.sin_len = sizeof(zeroAddress); zeroAddress.sin_family = AF_INET; SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress); if (SCNetworkReachabilityGetFlags(reachability, &flags)) { if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN) { return YES; } } return NO; } + (BOOL)isReachableViaWiFi { SCNetworkReachabilityFlags flags; BOOL result = NO; struct sockaddr_in zeroAddress; bzero(&zeroAddress, sizeof(zeroAddress)); zeroAddress.sin_len = sizeof(zeroAddress); zeroAddress.sin_family = AF_INET; SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress); if (SCNetworkReachabilityGetFlags(reachability, &flags)) { BOOL isReachable = (flags & kSCNetworkReachabilityFlagsReachable) != 0; BOOL needsConnection = (flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0; BOOL isWiFi = (flags & kSCNetworkReachabilityFlagsIsWWAN) == 0; result = isReachable && !needsConnection && isWiFi; } NSLog(@"result:%d",result); return result; } +(BOOL)isReachable { // 获取 SCNetworkReachabilityRef 对象 // 注意:这里直接从内存地址获取的方式在实际开发中是不安全的, // 应该通过正确的途径获取该对象,例如使用 SCNetworkReachabilityCreateWithAddress 或 SCNetworkReachabilityCreateWithName struct sockaddr_in zeroAddress; bzero(&zeroAddress, sizeof(zeroAddress)); zeroAddress.sin_len = sizeof(zeroAddress); zeroAddress.sin_family = AF_INET; SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress); // 获取网络状态标志 SCNetworkReachabilityFlags flags; BOOL success = SCNetworkReachabilityGetFlags(reachability, &flags); if (!success) { return NO; } // 判断网络是否可达,并调用 ALReachability 的方法 return [ZZHUtils isReachableWithFlags:flags]; } + (int)isReachableWithFlags:(int)arg2 { int result = 5; if ((result & ~arg2) != 0) { result = (result != 0) ? 1 : 5; } return result & ((arg2 & 2) >> 1); } + (id)collectTimeZoneOffset { NSTimeZone *tz = [NSTimeZone localTimeZone]; NSInteger sec = [tz secondsFromGMT]; double hoursFromGMT = (double)sec / 3600.0; return @(hoursFromGMT); } //获取电池数据 + (NSDictionary *)collectBatteryInfoIfNeeded { NSMutableDictionary *dictionary = [NSMutableDictionary new]; UIDevice *device = [UIDevice currentDevice]; BOOL originalBatteryMonitoringEnabled = device.isBatteryMonitoringEnabled; [device setBatteryMonitoringEnabled:YES]; UIDeviceBatteryState batteryState = device.batteryState; NSNumber *batteryStateNumber = [NSNumber numberWithInteger:batteryState]; [dictionary setObject:batteryStateNumber forKey:@"ict"]; float batteryLevel = device.batteryLevel; int batteryPercentage = (int)(batteryLevel * 100); if (batteryPercentage > 0) { batteryPercentage = batteryPercentage ^ 0x10101010; NSNumber *batteryLevelNumber = @(batteryPercentage); [dictionary setObject:batteryLevelNumber forKey:@"icm"]; } else { [dictionary setObject:@"-1" forKey:@"icm"]; } [device setBatteryMonitoringEnabled:originalBatteryMonitoringEnabled]; return dictionary; } + (NSString *)collectModelRevision { struct utsname systemInfo; if (uname(&systemInfo) == 0) { NSString *modelString = [NSString stringWithUTF8String:systemInfo.machine]; return modelString; } return nil; } + (CGFloat)getScreenBrightness { return [UIScreen mainScreen].brightness; } + (CBManagerState)bluetoothState { CBCentralManager *manager = [[CBCentralManager alloc] init]; return manager.state; } //设备型号 + (NSDictionary *)collectModel { NSMutableDictionary *arg2 = [NSMutableDictionary new]; UIDevice *device = [UIDevice currentDevice]; NSString *model = [device model]; [arg2 setObject:model forKeyedSubscript:@"model"]; return arg2; } + (NSString *)collectSubplatform { if (@available(iOS 14.0, *)) { if ([[NSProcessInfo processInfo] isiOSAppOnMac]) { return @"ios_on_mac"; } } if (@available(iOS 13.0, *)) { if ([[NSProcessInfo processInfo] isMacCatalystApp]) { return @"mac_catalyst"; } } return @"ios"; } + (id)collectOrientationLock { // [[[[UIApplication sharedApplication] windows].firstObject windowScene] interfaceOrientation] return nil; } + (NSMutableDictionary *)collectScreenDimensions{ NSMutableDictionary *dict = [NSMutableDictionary new]; UIScreen *mainScreen = [UIScreen mainScreen]; CGRect bounds = [mainScreen bounds]; CGRect nativeBounds = [mainScreen nativeBounds]; CGFloat scale = [mainScreen scale]; [dict setObject:@(bounds.size.width) forKeyedSubscript:@"dx"]; [dict setObject:@(bounds.size.height) forKeyedSubscript:@"dy"]; [dict setObject:@(nativeBounds.size.width) forKeyedSubscript:@"ndx"]; [dict setObject:@(nativeBounds.size.height) forKeyedSubscript:@"ndy"]; [dict setObject:@(scale) forKeyedSubscript:@"scale"]; return dict; } + (NSString *)systemVersion { UIDevice *device = [UIDevice currentDevice]; NSString *version = [device systemVersion]; return version; } + (NSMutableDictionary *)collectLocale{ NSMutableDictionary *arg2 = [NSMutableDictionary new]; NSLocale *currentLocale = [NSLocale currentLocale]; NSString *localeIdentifier = [currentLocale localeIdentifier]; [arg2 setObject:localeIdentifier forKeyedSubscript:@"locale"]; return arg2; } + (NSNumber *)volume { AVAudioSession *audioSession = [AVAudioSession sharedInstance]; float outputVolume = [audioSession outputVolume]; NSNumber *volumeNumber = [NSNumber numberWithFloat:outputVolume]; return volumeNumber; } + (void)appInfoFromBundle { NSBundle *bundle = [NSBundle mainBundle]; NSArray *arr = [NSBundle allBundles]; NSArray *frameworks = [NSBundle allFrameworks]; NSURL *appStoreReceiptURL = [bundle appStoreReceiptURL]; NSLog(@"the bundle:%@",bundle); } + (BOOL)isVPNConnected { CFDictionaryRef proxySettings = CFNetworkCopySystemProxySettings(); if (proxySettings == NULL) { return NO; } NSDictionary *settings = (__bridge_transfer NSDictionary *)proxySettings; NSDictionary *scoped = settings[@"__SCOPED__"]; if (!scoped) { return NO; } NSArray *allKeys = [scoped allKeys]; __block BOOL rr = NO; [allKeys enumerateObjectsUsingBlock:^(NSString * _Nonnull interface, NSUInteger idx, BOOL * _Nonnull stop) { if ([interface containsString:@"tun"] || [interface containsString:@"ppp"]) { rr = YES; } else { rr = [interface containsString:@"ipsec"]; } }]; return rr; } + (SystemSoundID)muteSoundID { SystemSoundID _muteSoundID = 0; NSURL *soundURL = [[NSBundle mainBundle] URLForResource:@"mute" withExtension:@"aiff"]; if (soundURL) { OSStatus status = AudioServicesCreateSystemSoundID((__bridge CFURLRef)soundURL, &_muteSoundID); if (status == noErr) { // 设置声音为静音 UInt32 yes = 1; AudioServicesSetProperty(kAudioServicesPropertyIsUISound, sizeof(_muteSoundID), &_muteSoundID, sizeof(yes), &yes); } } return _muteSoundID; } + (NSString *)getIDFA { if ([[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled]) { NSString *idfa = [[ASIdentifierManager sharedManager].advertisingIdentifier UUIDString]; return idfa; } else { return @""; } } + (NSString *)getIDFV { NSString *idfv = [[[UIDevice currentDevice] identifierForVendor] UUIDString]; return idfv; } #pragma mark - 获取网络运营商 + (NSString *)getCarrierName{ CTTelephonyNetworkInfo *telephonyInfo = [[CTTelephonyNetworkInfo alloc] init]; CTCarrier *carrier = [telephonyInfo subscriberCellularProvider]; NSString *currentCountry=[carrier carrierName]; return currentCountry; } #pragma mark - 获取当前可用内存 /** 获取当前可用内存 @return 当前可用内存大小 */ +(long long)getAvailableMemorySize { vm_statistics_data_t vmStats; mach_msg_type_number_t infoCount = HOST_VM_INFO_COUNT; kern_return_t kernReturn = host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vmStats, &infoCount); if (kernReturn != KERN_SUCCESS) { return NSNotFound; } return ((vm_page_size * vmStats.free_count + vm_page_size * vmStats.inactive_count)); } #pragma mark - 获取磁盘容量 /** 获取磁盘容量 @return 磁盘容量 */ +(long long)getTotalDiskSize{ struct statfs buf; unsigned long long freeSpace = -1; if (statfs("/var", &buf) >= 0) { freeSpace = (unsigned long long)(buf.f_bsize * buf.f_blocks); } return freeSpace; } #pragma mark - 获取可用磁盘容量 /** 获取可用磁盘容量 @return 可用磁盘容量 */ +(long long)getAvailableDiskSize{ struct statfs buf; unsigned long long freeSpace = -1; if (statfs("/var", &buf) >= 0) { freeSpace = (unsigned long long)(buf.f_bsize * buf.f_bavail); } return freeSpace; } /// 获取本机DNS服务器 /// libresolv.tbd需要添加这个库 + (NSArray *)outPutDNSServers { res_state res = malloc( sizeof(struct __res_state) ); NSMutableArray *dnsArray = [NSMutableArray new]; if (res_ninit(res) == 0) { for (int i = 0; i < res->nscount; i++ ) { NSString *s = [NSString stringWithUTF8String:inet_ntoa(res->nsaddr_list[i].sin_addr)]; [dnsArray addObject:s]; } } res_ndestroy(res);//!!改了这里 free(res); return dnsArray.mutableCopy; } //是否有刘海屏 + (BOOL)hasNotch { return [UIScreen mainScreen].nativeBounds.size.height != UIScreen.mainScreen.bounds.size.height; } //获取系统字号 + (NSNumber *)getSystemFontSize { UIFont *font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; UIFontDescriptor *ctFont = font.fontDescriptor; NSNumber *fontSize = [ctFont objectForKey:@"NSFontSizeAttribute"]; return fontSize; } //获取processInfo + (NSDictionary *)processInfo { NSProcessInfo *processInfo = [NSProcessInfo processInfo]; return processInfo.environment; } #define IOS_CELLULAR @"pdp_ip0"//有些分配的地址为en0 有些分配的en1 #define IOS_WIFI2 @"en2" #define IOS_WIFI1 @"en1" #define IOS_WIFI @"en0"// #define IOS_VPN @"utun0" vpn很少用到可以注释 #define IP_ADDR_IPv4 @"ipv4" #define IP_ADDR_IPv6 @"ipv6" //获取所有相关IP信息 + (NSDictionary *)getIPAddresses{ NSMutableDictionary *addresses = [NSMutableDictionary dictionaryWithCapacity:8]; // retrieve the current interfaces - returns 0 on success struct ifaddrs *interfaces; if(!getifaddrs(&interfaces)) { // Loop through linked list of interfaces struct ifaddrs *interface; for(interface=interfaces; interface; interface=interface->ifa_next) { if(!(interface->ifa_flags & IFF_UP) /* || (interface->ifa_flags & IFF_LOOPBACK) */ ) { continue; // deeply nested code harder to read } const struct sockaddr_in *addr = (const struct sockaddr_in*)interface->ifa_addr; char addrBuf[ MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) ]; if(addr && (addr->sin_family==AF_INET || addr->sin_family==AF_INET6)) { NSString *name = [NSString stringWithUTF8String:interface->ifa_name]; NSString *type; if(addr->sin_family == AF_INET) { if(inet_ntop(AF_INET, &addr->sin_addr, addrBuf, INET_ADDRSTRLEN)) { type = IP_ADDR_IPv4; } } else { const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)interface->ifa_addr; if(inet_ntop(AF_INET6, &addr6->sin6_addr, addrBuf, INET6_ADDRSTRLEN)) { type = IP_ADDR_IPv6; } } if(type) { NSString *key = [NSString stringWithFormat:@"%@/%@", name, type]; addresses[key] = [NSString stringWithUTF8String:addrBuf]; } } } // Free memory freeifaddrs(interfaces); } return [addresses count] ? addresses : nil; } #warning -----暂时还未去成功获取 + (NSDictionary *)wifiInfo { NSArray *ifs = (__bridge_transfer id)CNCopySupportedInterfaces(); NSLog(@"interfaces:%@",ifs); NSDictionary *info = nil; for (NSString *ifname in ifs) { info = (__bridge_transfer NSDictionary *)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifname); NSLog(@"wifiInfo %@ => %@",ifname,info); } return info; } #warning -----暂时还未去处理的伪代码 //- (NSDictionary *)collectAdServerInfo { // NSMutableDictionary *result = [NSMutableDictionary dictionary]; // // // Server Cache // [result setObject:[self.sdk stringForKey:[ALSetting serverCache]] forKeyedSubscript:@"sc"]; // // // Server Cache 2 // [result setObject:[self.sdk stringForKey:[ALSetting serverCache2]] forKeyedSubscript:@"sc2"]; // // // Server Cache 3 // [result setObject:[self.sdk stringForKey:[ALSetting serverCache3]] forKeyedSubscript:@"sc3"]; // // // Server Installed At // [result setObject:[self.sdk stringForKey:[ALSetting serverInstalledAt]] forKeyedSubscript:@"server_installed_at"]; // // // Server Installed At V2 // [result setObject:[self.sdk stringForKey:[ALSetting serverInstalledAtV2]] forKeyedSubscript:@"server_installed_at_v2"]; // // // Persisted Data // NSString *persistedData = [[self.sdk userDefaults] stringForKey:[ALUserDefaultsKey persistedData]]; // [result al_setStringValueIfValid:persistedData forKey:@"persisted_data"]; // // return [result copy]; //} #warning ----还未检测到该方法的调用... + (NSString *)collectCurrentRadioAccessTechnologyIfNeeded{ return @""; } #pragma mark ----检测是否越狱 + (BOOL)isJailbroken { if ([self checkCommonJailbreakFiles] || [self checkSuspiciousApps] || [self canWriteToSystemDirectories]) { return YES; } return NO; } + (BOOL)checkCommonJailbreakFiles { NSArray *jailbreakFiles = @[ @"/Applications/Cydia.app", @"/Library/MobileSubstrate/MobileSubstrate.dylib", @"/bin/bash", @"/usr/sbin/sshd", @"/etc/apt", @"/private/var/lib/apt/" ]; for (NSString *path in jailbreakFiles) { if ([[NSFileManager defaultManager] fileExistsAtPath:path]) { return YES; } } return NO; } + (BOOL)checkSuspiciousApps { if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"cydia://package/com.example.package"]]) { return YES; } return NO; } + (BOOL)canWriteToSystemDirectories { NSError *error; NSString *stringToWrite = @"Jailbreak Test"; NSString *filePath = @"/private/jailbreakTest.txt"; [stringToWrite writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:&error]; if (error == nil) { [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil]; return YES; } return NO; } @end