// // SecurityChecks.m // Runner // // Created by Hamza Aleghwairyeen on 17/03/2025. // #import #import "SecurityChecks.h" #import #include #import #include // For _dyld_image_count and _dyld_get_image_name #include // for fork() #include //for socket, connect #include // for sockaddr_in #include // for inet_pton @implementation SecurityChecks + (BOOL)isDeviceJailbroken { // (Same jailbreak checks as before - from previous responses) // 1. Check for common jailbreak files NSArray *jailbreakPaths = @[ @"/Applications/Cydia.app", // #if !TARGET_IPHONE_SIMULATOR // @"/bin/bash", // #endif @"/Library/MobileSubstrate/MobileSubstrate.dylib", @"/bin/bash", @"/usr/sbin/sshd", @"/etc/apt", @"/private/var/lib/apt/", @"/private/var/tmp/cydia.log", ]; for (NSString *path in jailbreakPaths) { if ([[NSFileManager defaultManager] fileExistsAtPath:path]) { NSLog(@"Jailbreak file detected: %@", path); return YES; } } // 2. Check if we can write outside the sandbox (a strong indicator) NSError *error = nil; NSString *testPath = @"/private/jailbreaktest.txt"; [@"test" writeToFile:testPath atomically:YES encoding:NSUTF8StringEncoding error:&error]; if (!error) { // If we can write, it's jailbroken. Remove the file immediately. [[NSFileManager defaultManager] removeItemAtPath:testPath error:nil]; NSLog(@"Sandbox write test indicates jailbreak."); return YES; } //3: Check for existence of the symbolic link /Applications. struct stat s; if (lstat("/Applications", &s) == 0) { if (S_ISLNK(s.st_mode)) { NSLog(@"Symbolic link /Applications exists, jailbroken"); return YES; } } //4:Check for dyld Libraries uint32_t count = _dyld_image_count(); for (uint32_t i = 0 ; i < count ; ++i) { const char *dyld = _dyld_get_image_name(i); if (strstr(dyld, "MobileSubstrate") != NULL || strstr(dyld, "libcycript") != NULL) { NSLog(@"Suspicious dyld library found: %s", dyld); return YES; } } //5 Check if fork() is available. Sandboxed apps should not be able to call fork(). #if !TARGET_IPHONE_SIMULATOR // Don't run this on the simulator int pid = fork(); if (pid == 0) { //in child, exit immediately to avoid crashing. exit(0); } else if (pid > 0) { NSLog(@"Fork available. Likely jailbroken."); return YES; // Fork succeeded; likely jailbroken } #endif return NO; // No jailbreak indicators found } + (BOOL)isDebuggerAttached { int mib[4]; struct kinfo_proc info; size_t size = sizeof(info); mib[0] = CTL_KERN; mib[1] = KERN_PROC; mib[2] = KERN_PROC_PID; mib[3] = getpid(); sysctl(mib, 4, &info, &size, NULL, 0); return (info.kp_proc.p_flag & P_TRACED) != 0; } // Check for Frida's default port + (BOOL)isFridaListeningOnDefaultPort { int sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == -1) { return NO; // Couldn't create socket } struct sockaddr_in sa; memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_port = htons(27042); // Default Frida port inet_pton(AF_INET, "127.0.0.1", &sa.sin_addr); if (connect(sock, (struct sockaddr *)&sa, sizeof(sa)) != -1) { NSLog(@"Frida default port (27042) is open."); close(sock); return YES; } close(sock); return NO; } + (BOOL)isFridaDetected { int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 }; size_t length; struct kinfo_proc *procs, *proc; sysctl(name, 3, NULL, &length, NULL, 0); procs = malloc(length); sysctl(name, 3, procs, &length, NULL, 0); for (proc = procs; (char *)proc < (char *)procs + length; proc++) { if (strstr(proc->kp_proc.p_comm, "frida") != NULL) { free(procs); return YES; } } free(procs); return NO; } // Check for loaded dylibs that indicate Frida +(BOOL) checkForFridaDylib{ uint32_t count = _dyld_image_count(); for (uint32_t i = 0 ; i < count ; ++i) { const char *dyld = _dyld_get_image_name(i); if (strstr(dyld, "FridaGadget") != NULL) { // Look for FridaGadget NSLog(@"FridaGadget dylib found: %s", dyld); return YES; } } return NO; } // Check process name + (BOOL)checkProcessName { NSString* processName = [[NSProcessInfo processInfo] processName]; if ([processName containsString:@"Frida"]) { return YES; } return NO; } // A combined check for jailbreak and Frida + (BOOL)isDeviceCompromised { if ([SecurityChecks isDeviceJailbroken]) { return YES; } if ([SecurityChecks isFridaListeningOnDefaultPort]) { return YES; } if ([SecurityChecks checkForFridaDylib]) { return YES; } if([SecurityChecks checkProcessName]){ return YES; } if ([SecurityChecks isDebuggerAttached]) { return YES; } // if ([SecurityChecks isFridaDetected]) { // return YES; // } return NO; } @end