198 lines
5.3 KiB
Objective-C
198 lines
5.3 KiB
Objective-C
//
|
|
// SecurityChecks.m
|
|
// Runner
|
|
//
|
|
// Created by Hamza Aleghwairyeen on 12/03/2025.
|
|
//
|
|
|
|
#import <Foundation/Foundation.h>
|
|
|
|
|
|
|
|
#import "SecurityChecks.h"
|
|
#import <sys/stat.h>
|
|
#include <dlfcn.h>
|
|
#import <sys/sysctl.h>
|
|
#include <mach-o/dyld.h> // For _dyld_image_count and _dyld_get_image_name
|
|
#include <unistd.h> // for fork()
|
|
#include <sys/socket.h> //for socket, connect
|
|
#include <netinet/in.h> // for sockaddr_in
|
|
#include <arpa/inet.h> // 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
|