#import <Foundation/Foundation.
h>
#import <UIKit/UIKit.h>
#import <Security/Security.h>
#import <sys/types.h>
#import <sys/stat.h>
#import <dlfcn.h>
#import <mach-o/dyld.h>
#import <objc/runtime.h>
#import <objc/message.h>
#import "PatchNonJB/dobby.h"
#include "hook/fishhook.h"
#import <mach/mach.h>
#import <sys/mman.h>
#import <sys/sysctl.h>
#import <fcntl.h>
#import <unistd.h>
#import <CoreFoundation/CoreFoundation.h>
#import <string.h>
#include <sys/utsname.h>
struct dl_phdr_info {
uintptr_t dlpi_addr;
const char *dlpi_name;
const void *dlpi_phdr;
uint16_t dlpi_phnum;
};
extern "C" void objc_msgSend(void);
#include <sys/types.h>
#include <sys/stat.h>
#include <spawn.h>
#include <zlib.h>
#include <sys/syscall.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#import "PatchNonJB/PatchNonJB.h"
extern "C" kern_return_t mach_vm_protect(vm_map_t target_task, mach_vm_address_t
address, mach_vm_size_t size, boolean_t set_maximum, vm_prot_t new_protection);
#ifndef DYLD_INTERPOSE
#define DYLD_INTERPOSE(_replacement,_replacee) \
__attribute__((used)) static struct{ const void* replacement; const void*
replacee;} _interpose_##_replacee \
__attribute__ ((section ("__DATA,__interpose"))) = { (const void*)
(unsigned long)&_replacement, (const void*)(unsigned long)&_replacee };
#endif
extern "C" int csops(pid_t pid, unsigned int ops, void *useraddr, size_t usersize);
extern "C" int ptrace(int request, pid_t pid, void* addr, int data);
static void* (*orig_dlsym)(void *handle, const char *symbol) = NULL;
#define ORIGINAL_BUNDLE_ID @"[Link]"
#define ORIGINAL_APP_PREFIX @"UTR4MP4KWL"
static bool is_safe_string(const char *ptr);
static bool is_sys_path_banned(const char *path) {
if (!is_safe_string(path)) return false;
if (strstr(path, "AppSync") ||
strstr(path, "TrollStore") ||
strstr(path, "Cydia") ||
strstr(path, "Substrate") ||
strstr(path, "MobileSubstrate") ||
strstr(path, "limera1n") ||
strstr(path, "greenpois0n") ||
strstr(path, "blackra1n") ||
strstr(path, "blacksn0w") ||
strstr(path, "redsn0w") ||
strstr(path, "Absinthe") ||
strstr(path, "Sileo") ||
strstr(path, "Zebra") ||
strstr(path, "dpkg") ||
strstr(path, "sshd") ||
strstr(path, "libdobby") ||
strstr(path, "frida") ||
strstr(path, "/var/jb/")) {
return true;
}
return false;
}
extern "C" char g_spoofDir[1024];
char g_spoofDir[1024] = {0};
struct raw_syscall_ret {
uint64_t x0;
uint64_t x1;
uint64_t nzcv;
};
static struct raw_syscall_ret my_raw_syscall(uint64_t num, uint64_t p1, uint64_t
p2, uint64_t p3, uint64_t p4, uint64_t p5, uint64_t p6) {
register uint64_t _x16 __asm__("x16") = num;
register uint64_t _x0 __asm__("x0") = p1;
register uint64_t _x1 __asm__("x1") = p2;
register uint64_t _x2 __asm__("x2") = p3;
register uint64_t _x3 __asm__("x3") = p4;
register uint64_t _x4 __asm__("x4") = p5;
register uint64_t _x5 __asm__("x5") = p6;
uint64_t nzcv;
__asm__ volatile(
"SVC #0x80\n"
"MRS %3, NZCV\n"
: "+r"(_x0), "+r"(_x1), "+r"(_x16), "=r"(nzcv), "+r"(_x2), "+r"(_x3),
"+r"(_x4), "+r"(_x5)
:
: "memory", "x6", "x7"
);
struct raw_syscall_ret ret;
ret.x0 = _x0;
ret.x1 = _x1;
[Link] = nzcv;
return ret;
}
static bool is_safe_string(const char *ptr) {
if (!ptr || (uintptr_t)ptr < 0x10000000) return false;
return true;
}
static bool spoof_path_if_needed(const char *original_path, char *out_path, size_t
max_len) {
if (!is_safe_string(original_path) || g_spoofDir[0] == '\0') return false;
if (strstr(original_path, g_spoofDir)) {
return false;
}
const char *range = strstr(original_path, "/[Link]/");
if (range != NULL) {
size_t prefix_len = strlen("/[Link]/");
const char *subPath = range + prefix_len;
snprintf(out_path, max_len, "%s/%s", g_spoofDir, subPath);
return true;
}
const char *lastSlash = strrchr(original_path, '/');
const char *fileName = lastSlash ? lastSlash + 1 : original_path;
if (
strcmp(fileName, "crossfirelegends") == 0 ||
strcmp(fileName, "[Link]") == 0 ||
strstr(fileName, "[Link]") != NULL ||
strcmp(fileName, "CodeResources") == 0) {
snprintf(out_path, max_len, "%s/%s", g_spoofDir, fileName);
return true;
}
return false;
}
static int (*orig_stat)(const char *path, struct stat *buf);
int my_stat(const char *path, struct stat *buf) {
if (!orig_stat) return -1;
if (is_sys_path_banned(path)) {
errno = ENOENT;
return -1;
}
if (path && is_safe_string(path) && strstr(path, "[Link]")) {
NSString *fakeVersionPath = [[Link]
stringByAppendingPathComponent:@"[Link]"];
return orig_stat([fakeVersionPath UTF8String], buf);
}
char spoofed_path[1024];
if (spoof_path_if_needed(path, spoofed_path, sizeof(spoofed_path))) {
return orig_stat(spoofed_path, buf);
}
return orig_stat(path, buf);
}
void (*o_fixban)(void* ins);
void fixban(void* ins){
return;
}
static char* (*orig_realpath)(const char* path, char* resolved_path);
char* my_realpath(const char* path, char* resolved_path) {
if (!orig_realpath) return NULL;
if (is_sys_path_banned(path)) { errno = ENOENT; return NULL; }
char spoofed[1024];
if (spoof_path_if_needed(path, spoofed, sizeof(spoofed))) {
return orig_realpath(spoofed, resolved_path);
}
return orig_realpath(path, resolved_path);
}
static char* (*orig_realpath_EXTSN)(const char* path, char* resolved_path);
char* my_realpath_EXTSN(const char* path, char* resolved_path) {
if (!orig_realpath_EXTSN) return NULL;
if (is_sys_path_banned(path)) { errno = ENOENT; return NULL; }
char spoofed[1024];
if (spoof_path_if_needed(path, spoofed, sizeof(spoofed))) {
return orig_realpath_EXTSN(spoofed, resolved_path);
}
return orig_realpath_EXTSN(path, resolved_path);
}
static char* (*orig_getcwd)(char *buf, size_t size);
char* my_getcwd(char *buf, size_t size) {
if (!orig_getcwd) return NULL;
char* ret = orig_getcwd(buf, size);
if (ret && buf) {
char spoofed[1024];
if (spoof_path_if_needed(buf, spoofed, sizeof(spoofed))) {
size_t len = strlen(spoofed) + 1;
if (len <= size) {
memcpy(buf, spoofed, len);
}
}
}
return ret;
}
static char* (*orig_getwd)(char *buf);
char* my_getwd(char *buf) {
if (!orig_getwd) return NULL;
char* ret = orig_getwd(buf);
if (ret && buf) {
char spoofed[1024];
if (spoof_path_if_needed(buf, spoofed, sizeof(spoofed))) {
strcpy(buf, spoofed);
}
}
return ret;
}
static int (*orig_lstat)(const char *path, struct stat *buf);
int my_lstat(const char *path, struct stat *buf) {
if (!orig_lstat) return -1;
if (is_sys_path_banned(path)) {
errno = ENOENT;
return -1;
}
if (path && is_safe_string(path) && strstr(path, "[Link]")) {
NSString *fakeVersionPath = [[Link]
stringByAppendingPathComponent:@"[Link]"];
return orig_lstat([fakeVersionPath UTF8String], buf);
}
char spoofed_path[1024];
if (spoof_path_if_needed(path, spoofed_path, sizeof(spoofed_path))) {
return orig_lstat(spoofed_path, buf);
}
return orig_lstat(path, buf);
}
static int (*orig_access)(const char *path, int amode);
int my_access(const char *path, int amode) {
if (!orig_access) return -1;
if (is_sys_path_banned(path)) {
errno = ENOENT;
return -1;
}
if (path && is_safe_string(path) && strstr(path, "[Link]")) {
NSString *fakeVersionPath = [[Link]
stringByAppendingPathComponent:@"[Link]"];
return orig_access([fakeVersionPath UTF8String], amode);
}
char spoofed_path[1024];
if (spoof_path_if_needed(path, spoofed_path, sizeof(spoofed_path))) {
return orig_access(spoofed_path, amode);
}
return orig_access(path, amode);
}
static int (*orig_fstatat)(int fd, const char *path, struct stat *buf, int flag);
int my_fstatat(int fd, const char *path, struct stat *buf, int flag) {
if (!orig_fstatat) return -1;
if (is_sys_path_banned(path)) {
errno = ENOENT;
return -1;
}
char spoofed_path[1024];
if (spoof_path_if_needed(path, spoofed_path, sizeof(spoofed_path))) {
return orig_fstatat(AT_FDCWD, spoofed_path, buf, flag);
}
return orig_fstatat(fd, path, buf, flag);
}
static int (*orig_open)(const char *path, int oflag, mode_t mode);
int my_open(const char *path, int oflag, mode_t mode) {
if (!orig_open) return -1;
if (is_sys_path_banned(path)) {
errno = ENOENT;
return -1;
}
if (path && is_safe_string(path) && strstr(path, "[Link]")) {
NSString *fakeVersionPath = [[Link]
stringByAppendingPathComponent:@"[Link]"];
return orig_open([fakeVersionPath UTF8String], oflag, mode);
}
char spoofed_path[1024];
if (spoof_path_if_needed(path, spoofed_path, sizeof(spoofed_path))) {
return orig_open(spoofed_path, oflag, mode);
}
return orig_open(path, oflag, mode);
}
static int (*orig_openat)(int fd, const char *path, int oflag, mode_t mode);
int my_openat(int fd, const char *path, int oflag, mode_t mode) {
if (!orig_openat) return -1;
if (is_sys_path_banned(path)) {
errno = ENOENT;
return -1;
}
char spoofed_path[1024];
if (spoof_path_if_needed(path, spoofed_path, sizeof(spoofed_path))) {
if (orig_open) return orig_open(spoofed_path, oflag, mode);
return -1;
}
return orig_openat(fd, path, oflag, mode);
}
static int (*orig_open_NOCANCEL)(const char *path, int oflag, mode_t mode);
int my_open_NOCANCEL(const char *path, int oflag, mode_t mode) {
if (!orig_open_NOCANCEL) return -1;
if (is_sys_path_banned(path)) {
errno = ENOENT;
return -1;
}
char spoofed_path[1024];
if (spoof_path_if_needed(path, spoofed_path, sizeof(spoofed_path))) {
return orig_open_NOCANCEL(spoofed_path, oflag, mode);
}
return orig_open_NOCANCEL(path, oflag, mode);
}
static FILE *(*orig_fopen_UNIX2003)(const char * filename, const char * mode);
FILE *my_fopen_UNIX2003(const char * filename, const char * mode) {
if (!orig_fopen_UNIX2003) return NULL;
if (is_sys_path_banned(filename)) {
errno = ENOENT;
return NULL;
}
char spoofed_path[1024];
if (spoof_path_if_needed(filename, spoofed_path, sizeof(spoofed_path))) {
return orig_fopen_UNIX2003(spoofed_path, mode);
}
return orig_fopen_UNIX2003(filename, mode);
}
static int (*orig_sysctl)(int *name, u_int namelen, void *oldp, size_t *oldlenp,
void *newp, size_t newlen);
int my_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
size_t newlen) {
if (!orig_sysctl) return -1;
int ret = orig_sysctl(name, namelen, oldp, oldlenp, newp, newlen);
if (ret == 0 && namelen >= 3 && name[0] == CTL_KERN && name[1] == KERN_PROC &&
oldp != NULL && oldlenp != NULL) {
if (name[2] == KERN_PROC_ALL || name[2] == KERN_PROC_PID) {
struct kinfo_proc *kinfo = (struct kinfo_proc *)oldp;
size_t num_procs = *oldlenp / sizeof(struct kinfo_proc);
size_t valid_count = 0;
for (size_t i = 0; i < num_procs; i++) {
if (kinfo[i].kp_proc.p_flag & 0x800) {
kinfo[i].kp_proc.p_flag &= ~0x800;
}
if (kinfo[i].kp_proc.p_pid == getpid()) {
kinfo[i].kp_eproc.e_ppid = 1;
}
char safe_comm[17] = {0};
memcpy(safe_comm, kinfo[i].kp_proc.p_comm, 16);
if (strstr(safe_comm, "frida") || strstr(safe_comm, "Cydia") ||
strstr(safe_comm, "debugserver") || strstr(safe_comm, "Electra") ||
strstr(safe_comm, "checkra") || strstr(safe_comm, "MobileSubstrate")) {
continue;
}
if (valid_count != i) {
kinfo[valid_count] = kinfo[i];
}
valid_count++;
}
if (valid_count < num_procs) {
*oldlenp = valid_count * sizeof(struct kinfo_proc);
} else {
}
}
}
else if (ret == 0 && namelen >= 3 && name[0] == CTL_KERN && name[1] ==
KERN_PROCARGS2 && oldp != NULL && oldlenp != NULL && *oldlenp > 0) {
char *args = (char *)oldp;
size_t size = *oldlenp;
const char *bad_strings[] = {"CydiaSubstrate", "MobileSubstrate", "frida",
"Dobby", "debugserver", "cycript", "checkra", "Electra", "anogs_bypass"};
for (int i = 0; i < sizeof(bad_strings) / sizeof(bad_strings[0]); i++) {
char *found;
while ((found = strcasestr(args, bad_strings[i])) != NULL) {
size_t len = strlen(bad_strings[i]);
if ((found - args) + len <= size) {
memset(found, 'X', len);
} else {
break;
}
}
}
}
return ret;
}
static kern_return_t (*orig_thread_get_state)(thread_act_t target_act,
thread_state_flavor_t flavor, thread_state_t old_state, mach_msg_type_number_t
*old_stateCnt);
kern_return_t my_thread_get_state(thread_act_t target_act, thread_state_flavor_t
flavor, thread_state_t old_state, mach_msg_type_number_t *old_stateCnt) {
kern_return_t ret = orig_thread_get_state(target_act, flavor, old_state,
old_stateCnt);
if (ret == KERN_SUCCESS && flavor == ARM_DEBUG_STATE64 && old_state != NULL) {
arm_debug_state64_t *debug_state = (arm_debug_state64_t *)old_state;
for (int i = 0; i < 16; i++) {
debug_state->__bvr[i] = 0;
debug_state->__bcr[i] = 0;
debug_state->__wvr[i] = 0;
debug_state->__wcr[i] = 0;
}
}
return ret;
}
static kern_return_t (*orig_task_get_exception_ports)(task_t task, exception_mask_t
exception_mask, exception_mask_array_t masks, mach_msg_type_number_t *masksCnt,
exception_handler_array_t old_handlers, exception_behavior_array_t old_behaviors,
exception_flavor_array_t old_flavors);
kern_return_t my_task_get_exception_ports(task_t task, exception_mask_t
exception_mask, exception_mask_array_t masks, mach_msg_type_number_t *masksCnt,
exception_handler_array_t old_handlers, exception_behavior_array_t old_behaviors,
exception_flavor_array_t old_flavors) {
kern_return_t ret = orig_task_get_exception_ports(task, exception_mask, masks,
masksCnt, old_handlers, old_behaviors, old_flavors);
if (ret == KERN_SUCCESS && masksCnt && old_handlers) {
for (mach_msg_type_number_t i = 0; i < *masksCnt; i++) {
if (masks[i] & (EXC_MASK_BREAKPOINT | EXC_MASK_MACH_SYSCALL |
EXC_MASK_SOFTWARE)) {
old_handlers[i] = MACH_PORT_NULL;
}
}
}
return ret;
}
static CFStringRef (*orig_CFBundleGetIdentifier)(CFBundleRef bundle);
CFStringRef my_CFBundleGetIdentifier(CFBundleRef bundle) {
return (__bridge CFStringRef)ORIGINAL_BUNDLE_ID;
}
static CFTypeRef (*orig_CFBundleGetValueForInfoDictionaryKey)(CFBundleRef bundle,
CFStringRef key);
CFTypeRef my_CFBundleGetValueForInfoDictionaryKey(CFBundleRef bundle, CFStringRef
key) {
if (key) {
NSString *nsKey = (__bridge NSString *)key;
if ([nsKey isEqualToString:@"CFBundleIdentifier"]) {
return (__bridge CFTypeRef)ORIGINAL_BUNDLE_ID;
}
if ([nsKey isEqualToString:@"CFBundleName"] || [nsKey
isEqualToString:@"CFBundleExecutable"]) {
return (__bridge CFTypeRef)@"crossfirelegends";
}
if ([nsKey isEqualToString:@"CFBundleDisplayName"]) {
return (__bridge CFTypeRef)@"Crossfire: Legends";
}
}
return orig_CFBundleGetValueForInfoDictionaryKey(bundle, key);
}
static char* (*orig_getenv)(const char *name);
char* my_getenv(const char *name) {
if (!orig_getenv) return NULL;
if (name) {
if (strcmp(name, "DYLD_INSERT_LIBRARIES") == 0 ||
strcmp(name, "Cydia") == 0 ||
strcmp(name, "_MSSafeMode") == 0 ||
strcmp(name, "DYLD_FRAMEWORK_PATH") == 0 ||
strcmp(name, "DYLD_LIBRARY_PATH") == 0 ||
strcmp(name, "DYLD_SHARED_REGION") == 0) {
return NULL;
}
}
return orig_getenv(name);
}
struct my_dl_iterate_phdr_data {
int (*original_callback)(struct dl_phdr_info *info, size_t size, void *data);
void *original_data;
};
static int my_dl_iterate_callback(struct dl_phdr_info *info, size_t size, void
*data) {
struct my_dl_iterate_phdr_data *my_data = (struct my_dl_iterate_phdr_data
*)data;
if (info && info->dlpi_name) {
if (strstr(info->dlpi_name, "libdobby") || strstr(info->dlpi_name,
"PatchNonJB") || strstr(info->dlpi_name, "frida") ||
strstr(info->dlpi_name, "CydiaSubstrate") || strstr(info->dlpi_name,
"MobileSubstrate")) {
return 0;
}
}
return my_data->original_callback(info, size, my_data->original_data);
}
typedef int (*dl_iterate_phdr_t)(int (*callback)(struct dl_phdr_info *info, size_t
size, void *data), void *data);
static dl_iterate_phdr_t orig_dl_iterate_phdr = NULL;
int my_dl_iterate_phdr(int (*callback)(struct dl_phdr_info *info, size_t size, void
*data), void *data) {
if (!orig_dl_iterate_phdr) return 0;
struct my_dl_iterate_phdr_data wrap_data;
wrap_data.original_callback = callback;
wrap_data.original_data = data;
return orig_dl_iterate_phdr(my_dl_iterate_callback, &wrap_data);
}
#import <mach/mach.h>
extern "C" kern_return_t mach_vm_region(vm_map_t target_task, mach_vm_address_t
*address, mach_vm_size_t *size, vm_region_flavor_t flavor, vm_region_info_t info,
mach_msg_type_number_t *infoCnt, mach_port_t *object_name);
extern "C" kern_return_t mach_vm_read(vm_map_t target_task, mach_vm_address_t
address, mach_vm_size_t size, vm_offset_t *data, mach_msg_type_number_t *dataCnt);
static void* g_clean_anogs_base = NULL;
static size_t g_clean_anogs_size = 0;
static void* g_clean_app_base = NULL;
static size_t g_clean_app_size = 0;
static kern_return_t (*orig_mach_vm_region)(vm_map_t target_task, mach_vm_address_t
*address, mach_vm_size_t *size, vm_region_flavor_t flavor, vm_region_info_t info,
mach_msg_type_number_t *infoCnt, mach_port_t *object_name);
kern_return_t my_mach_vm_region(vm_map_t target_task, mach_vm_address_t *address,
mach_vm_size_t *size, vm_region_flavor_t flavor, vm_region_info_t info,
mach_msg_type_number_t *infoCnt, mach_port_t *object_name) {
if (!orig_mach_vm_region) return KERN_FAILURE;
kern_return_t ret = orig_mach_vm_region(target_task, address, size, flavor,
info, infoCnt, object_name);
if (ret == KERN_SUCCESS && flavor == VM_REGION_BASIC_INFO_64) {
vm_region_basic_info_64_t binfo = (vm_region_basic_info_64_t)info;
if (binfo->protection != (VM_PROT_READ | VM_PROT_EXECUTE)) {
if (binfo->protection & VM_PROT_WRITE && binfo->protection &
VM_PROT_EXECUTE) {
binfo->protection = (VM_PROT_READ | VM_PROT_EXECUTE);
}
}
}
return ret;
}
static uintptr_t get_anogs_base() {
static uintptr_t s_anogs_base = 0;
if (s_anogs_base != 0) return s_anogs_base;
uint32_t count = _dyld_image_count();
for (uint32_t i = 0; i < count; i++) {
const char *name = _dyld_get_image_name(i);
if (name && strstr(name, "anogs")) {
s_anogs_base = (uintptr_t)_dyld_get_image_header(i);
break;
}
}
return s_anogs_base;
}
static uintptr_t get_app_base() {
static uintptr_t s_app_base = 0;
if (s_app_base != 0) return s_app_base;
uint32_t count = _dyld_image_count();
for (uint32_t i = 0; i < count; i++) {
const char *name = _dyld_get_image_name(i);
if (name && strstr(name, "crossfirelegends")) {
s_app_base = (uintptr_t)_dyld_get_image_header(i);
break;
}
}
return s_app_base;
}
static bool spoof_vm_read_if_needed(mach_vm_address_t address, mach_vm_size_t size,
void* dest) {
if (g_clean_anogs_base && g_clean_anogs_size > 0) {
uintptr_t anogs_mem_base = get_anogs_base();
if (anogs_mem_base != 0 && (uintptr_t)address >= anogs_mem_base &&
(uintptr_t)address < (anogs_mem_base + g_clean_anogs_size)) {
ptrdiff_t offset = (uintptr_t)address - anogs_mem_base;
if (offset + size <= g_clean_anogs_size) {
memcpy(dest, (void*)((uintptr_t)g_clean_anogs_base + offset),
size);
return true;
}
}
}
if (g_clean_app_base && g_clean_app_size > 0) {
uintptr_t app_mem_base = get_app_base();
if (app_mem_base != 0 && (uintptr_t)address >= app_mem_base &&
(uintptr_t)address < (app_mem_base + g_clean_app_size)) {
ptrdiff_t offset = (uintptr_t)address - app_mem_base;
if (offset + size <= g_clean_app_size) {
memcpy(dest, (void*)((uintptr_t)g_clean_app_base + offset), size);
return true;
}
}
}
return false;
}
static kern_return_t (*orig_mach_vm_read)(vm_map_t target_task, mach_vm_address_t
address, mach_vm_size_t size, vm_offset_t *data, mach_msg_type_number_t *dataCnt);
kern_return_t my_mach_vm_read(vm_map_t target_task, mach_vm_address_t address,
mach_vm_size_t size, vm_offset_t *data, mach_msg_type_number_t *dataCnt) {
if (!orig_mach_vm_read) return KERN_FAILURE;
kern_return_t ret = orig_mach_vm_read(target_task, address, size, data,
dataCnt);
if (ret == KERN_SUCCESS) {
if (spoof_vm_read_if_needed(address, size, (void*)*data)) {
}
}
return ret;
}
extern "C" kern_return_t mach_vm_read_overwrite(vm_map_t target_task,
mach_vm_address_t address, mach_vm_size_t size, mach_vm_address_t data,
mach_vm_size_t *outsize);
static kern_return_t (*orig_mach_vm_read_overwrite)(vm_map_t target_task,
mach_vm_address_t address, mach_vm_size_t size, mach_vm_address_t data,
mach_vm_size_t *outsize);
kern_return_t my_mach_vm_read_overwrite(vm_map_t target_task, mach_vm_address_t
address, mach_vm_size_t size, mach_vm_address_t data, mach_vm_size_t *outsize) {
if (!orig_mach_vm_read_overwrite) return KERN_FAILURE;
kern_return_t ret = orig_mach_vm_read_overwrite(target_task, address, size,
data, outsize);
if (ret == KERN_SUCCESS) {
spoof_vm_read_if_needed(address, size, (void*)data);
}
return ret;
}
extern "C" kern_return_t vm_read(vm_map_t target_task, vm_address_t address,
vm_size_t size, vm_offset_t *data, mach_msg_type_number_t *dataCnt);
static kern_return_t (*orig_vm_read)(vm_map_t target_task, vm_address_t address,
vm_size_t size, vm_offset_t *data, mach_msg_type_number_t *dataCnt);
kern_return_t my_vm_read(vm_map_t target_task, vm_address_t address, vm_size_t
size, vm_offset_t *data, mach_msg_type_number_t *dataCnt) {
if (!orig_vm_read) return KERN_FAILURE;
kern_return_t ret = orig_vm_read(target_task, address, size, data, dataCnt);
if (ret == KERN_SUCCESS) {
spoof_vm_read_if_needed(address, size, (void*)*data);
}
return ret;
}
extern "C" kern_return_t vm_read_overwrite(vm_map_t target_task, vm_address_t
address, vm_size_t size, vm_address_t data, vm_size_t *outsize);
static kern_return_t (*orig_vm_read_overwrite)(vm_map_t target_task, vm_address_t
address, vm_size_t size, vm_address_t data, vm_size_t *outsize);
kern_return_t my_vm_read_overwrite(vm_map_t target_task, vm_address_t address,
vm_size_t size, vm_address_t data, vm_size_t *outsize) {
if (!orig_vm_read_overwrite) return KERN_FAILURE;
kern_return_t ret = orig_vm_read_overwrite(target_task, address, size, data,
outsize);
if (ret == KERN_SUCCESS && g_clean_anogs_base && g_clean_anogs_size > 0) {
uintptr_t anogs_mem_base = get_anogs_base();
if (anogs_mem_base != 0 && (uintptr_t)address >= anogs_mem_base &&
(uintptr_t)address < (anogs_mem_base + g_clean_anogs_size)) {
ptrdiff_t offset = (uintptr_t)address - anogs_mem_base;
if (offset + size <= g_clean_anogs_size) {
memcpy((void*)data, (void*)((uintptr_t)g_clean_anogs_base +
offset), size);
}
}
}
return ret;
}
static OSStatus (*orig_SecItemCopyMatching)(CFDictionaryRef query, CFTypeRef
*result);
OSStatus my_SecItemCopyMatching(CFDictionaryRef query, CFTypeRef *result) {
if (query) {
NSMutableDictionary *modifiedQuery = [(__bridge NSDictionary *)query
mutableCopy];
modifiedQuery[(id)kSecAttrAccessGroup] = @"UTR4MP4KWL.*";
return orig_SecItemCopyMatching((__bridge CFDictionaryRef)modifiedQuery,
result);
}
return orig_SecItemCopyMatching(query, result);
}
static OSStatus (*orig_SecItemAdd)(CFDictionaryRef attributes, CFTypeRef *result);
OSStatus my_SecItemAdd(CFDictionaryRef attributes, CFTypeRef *result) {
if (attributes) {
NSMutableDictionary *modifiedQuery = [(__bridge NSDictionary *)attributes
mutableCopy];
modifiedQuery[(id)kSecAttrAccessGroup] = @"UTR4MP4KWL.*";
return orig_SecItemAdd((__bridge CFDictionaryRef)modifiedQuery, result);
}
return orig_SecItemAdd(attributes, result);
}
extern "C" void* orig_objc_msgSend;
void* orig_objc_msgSend = NULL;
extern "C" void my_objc_msgSend_handler(id self, SEL _cmd, uintptr_t lr) {
if (g_clean_anogs_base && g_clean_anogs_size > 0) {
if (lr >= (uintptr_t)g_clean_anogs_base && lr <
(uintptr_t)g_clean_anogs_base + g_clean_anogs_size) {
const char* selName = sel_getName(_cmd);
if (selName) {
if (strcmp(selName, "bundleIdentifier") == 0 ||
strcmp(selName, "infoDictionary") == 0 ||
strstr(selName, "pathForResource") != NULL) {
}
}
}
}
}
__attribute__((naked)) void my_objc_msgSend_trampoline() {
__asm__ volatile (
"stp x0, x1, [sp, #-16]!\n"
"stp x2, x3, [sp, #-16]!\n"
"stp x4, x5, [sp, #-16]!\n"
"stp x6, x7, [sp, #-16]!\n"
"stp x8, x9, [sp, #-16]!\n"
"str x30, [sp, #-16]!\n"
"mov x2, x30\n"
"bl _my_objc_msgSend_handler\n"
"ldr x30, [sp], #16\n"
"ldp x8, x9, [sp], #16\n"
"ldp x6, x7, [sp], #16\n"
"ldp x4, x5, [sp], #16\n"
"ldp x2, x3, [sp], #16\n"
"ldp x0, x1, [sp], #16\n"
"adrp x16, _orig_objc_msgSend@PAGE\n"
"add x16, x16, _orig_objc_msgSend@PAGEOFF\n"
"ldr x16, [x16]\n"
"br x16\n"
);
}
static char g_spoof_ring[8][1024];
static int g_spoof_ring_idx = 0;
static const char* get_spoofed_static_path(const char* path) {
int idx = __atomic_fetch_add(&g_spoof_ring_idx, 1, __ATOMIC_SEQ_CST) % 8;
strncpy(g_spoof_ring[idx], path, 1023);
g_spoof_ring[idx][1023] = '\0';
return g_spoof_ring[idx];
}
static int (*orig_dladdr)(const void *addr, Dl_info *info);
int my_dladdr(const void *addr, Dl_info *info) {
if (!orig_dladdr) return 0;
static thread_local bool in_my_dladdr = false;
if (in_my_dladdr) return orig_dladdr(addr, info);
in_my_dladdr = true;
int ret = orig_dladdr(addr, info);
if (ret != 0 && info && info->dli_fname) {
if (strstr(info->dli_fname, "anogs")) {
char spoofed[1024];
if (spoof_path_if_needed(info->dli_fname, spoofed, sizeof(spoofed))) {
info->dli_fname = get_spoofed_static_path(spoofed);
if (g_clean_anogs_base) {
if (info->dli_fbase) {
if (info->dli_saddr) {
ptrdiff_t offset = (char *)info->dli_saddr - (char
*)info->dli_fbase;
info->dli_saddr = (void*)((char *)g_clean_anogs_base +
offset);
}
if (info->dli_sname) {
ptrdiff_t offset_name = (char *)info->dli_sname - (char
*)info->dli_fbase;
if (offset_name > 0 && offset_name < 0x8000000) { //
sanity check
info->dli_sname = (const char*)((char
*)g_clean_anogs_base + offset_name);
}
}
}
info->dli_fbase = g_clean_anogs_base;
}
}
}
}
in_my_dladdr = false;
return ret;
}
static FILE *(*orig_fopen)(const char *filename, const char *mode);
FILE *my_fopen(const char *filename, const char *mode) {
if (!orig_fopen) return NULL;
if (is_sys_path_banned(filename)) {
errno = ENOENT;
return NULL;
}
if (filename && is_safe_string(filename) && strstr(filename,
"[Link]")) {
NSString *fakeVersionPath = [[Link]
stringByAppendingPathComponent:@"[Link]"];
return orig_fopen([fakeVersionPath UTF8String], mode);
}
char spoofed_path[1024];
if (spoof_path_if_needed(filename, spoofed_path, sizeof(spoofed_path))) {
return orig_fopen(spoofed_path, mode);
}
return orig_fopen(filename, mode);
}
#include <dirent.h>
static struct dirent *(*orig_readdir)(DIR *dirp);
struct dirent *my_readdir(DIR *dirp) {
if (!orig_readdir) return NULL;
struct dirent *ent;
while ((ent = orig_readdir(dirp)) != NULL) {
if (ent->d_name && (strstr(ent->d_name, "libdobby") || strstr(ent->d_name,
"PatchNonJB") || strstr(ent->d_name, "frida") || strstr(ent->d_name,
"CydiaSubstrate"))) {
continue;
}
break;
}
return ent;
}
#undef getdirentries
typedef int (*my_getdirentries_t)(int fd, char *buf, int nbytes, long *basep);
static my_getdirentries_t orig_getdirentries = NULL;
int my_getdirentries(int fd, char *buf, int nbytes, long *basep) {
if (!orig_getdirentries) return -1;
int ret = orig_getdirentries(fd, buf, nbytes, basep);
if (ret > 0) {
int bpos = 0;
int new_len = 0;
char *temp_buf = (char *)malloc(ret);
if (!temp_buf) return ret;
while (bpos < ret) {
struct dirent *d = (struct dirent *)(buf + bpos);
int reclen = d->d_reclen;
if (reclen == 0) break;
if (d->d_name && (strstr(d->d_name, "libdobby") || strstr(d->d_name,
"PatchNonJB") || strstr(d->d_name, "frida") || strstr(d->d_name, "anogs"))) {
} else {
memcpy(temp_buf + new_len, d, reclen);
new_len += reclen;
}
bpos += reclen;
}
memcpy(buf, temp_buf, new_len);
free(temp_buf);
return new_len;
}
return ret;
}
extern "C" int fstat(int fildes, struct stat *buf);
static int (*orig_fstat)(int fildes, struct stat *buf);
int my_fstat(int fildes, struct stat *buf) {
if (!orig_fstat) return -1;
int ret = orig_fstat(fildes, buf);
if (ret == 0) {
char path[1024];
if (fcntl(fildes, F_GETPATH, path) != -1) {
if (is_safe_string(path) && (strstr(path, "libdobby") || strstr(path,
"PatchNonJB") || strstr(path, "frida"))) {
memset(buf, 0, sizeof(struct stat));
errno = ENOENT;
return -1;
}
}
}
return ret;
}
#ifndef SYS_csops
#define SYS_csops 169
#endif
#ifndef CS_OPS_STATUS
#define CS_OPS_STATUS 0
#endif
#define CS_VALID 0x00000001
#define CS_HARD 0x00000100
#define CS_KILL 0x00000200
#define CS_ENFORCEMENT 0x00001000
#define CS_GET_TASK_ALLOW 0x00000004
#define CS_DEBUGGED 0x10000000
#define CS_PLATFORM_BINARY 0x04000000
#ifndef CS_OPS_ENTITLEMENTS_BLOB
#define CS_OPS_ENTITLEMENTS_BLOB 7
#endif
static int (*orig_csops)(pid_t pid, unsigned int ops, void *useraddr, size_t
usersize);
int my_csops(pid_t pid, unsigned int ops, void *useraddr, size_t usersize) {
if (ops == CS_OPS_STATUS && useraddr != NULL) {
uint32_t *status = (uint32_t *)useraddr;
*status = (CS_VALID | 0x2 | CS_PLATFORM_BINARY | 0x8);
return 0;
} else if (ops == CS_OPS_ENTITLEMENTS_BLOB) {
errno = EINVAL;
return -1;
}
return syscall(169, pid, ops, useraddr, usersize);
}
// csops_audittoken
extern "C" int csops_audittoken(pid_t pid, unsigned int ops, void *useraddr, size_t
usersize, void *token);
static int (*orig_csops_audittoken)(pid_t pid, unsigned int ops, void *useraddr,
size_t usersize, void *token);
int my_csops_audittoken(pid_t pid, unsigned int ops, void *useraddr, size_t
usersize, void *token) {
if (!orig_csops_audittoken) return -1;
if (ops == CS_OPS_STATUS && useraddr != NULL) {
int ret = orig_csops_audittoken(pid, ops, useraddr, usersize, token);
uint32_t *status = (uint32_t *)useraddr;
*status |= (CS_VALID | CS_HARD | CS_KILL | CS_ENFORCEMENT |
CS_PLATFORM_BINARY);
*status &= ~(CS_GET_TASK_ALLOW | CS_DEBUGGED);
return ret;
} else if (ops == CS_OPS_ENTITLEMENTS_BLOB) {
errno = EINVAL;
return -1;
}
return orig_csops_audittoken(pid, ops, useraddr, usersize, token);
}
#ifndef F_ADDSIGS
#define F_ADDSIGS 59
#endif
#ifndef F_ADDFILESIGS
#define F_ADDFILESIGS 61
#endif
#ifndef F_ADDFILESIGS_RETURN
#define F_ADDFILESIGS_RETURN 97
#endif
static int (*orig_fcntl)(int fildes, int cmd, ...);
int my_fcntl(int fildes, int cmd, ...) {
va_list args;
va_start(args, cmd);
void *arg = va_arg(args, void *);
va_end(args);
if (cmd == F_ADDSIGS || cmd == F_ADDFILESIGS || cmd == F_ADDFILESIGS_RETURN) {
return 0; // Fake success
}
if (!orig_fcntl) return -1;
return orig_fcntl(fildes, cmd, arg);
}
static kern_return_t (*orig_task_info)(task_name_t target_task, task_flavor_t
flavor, task_info_t task_info_out, mach_msg_type_number_t *task_info_outCnt);
kern_return_t my_task_info(task_name_t target_task, task_flavor_t flavor,
task_info_t task_info_out, mach_msg_type_number_t *task_info_outCnt) {
if (!orig_task_info) return KERN_FAILURE;
kern_return_t ret = orig_task_info(target_task, flavor, task_info_out,
task_info_outCnt);
if (ret == KERN_SUCCESS) {
if (flavor == TASK_DYLD_INFO) {
struct task_dyld_info *dyld_info = (struct task_dyld_info
*)task_info_out;
if (dyld_info) {
dyld_info->all_image_info_addr = 0;
dyld_info->all_image_info_size = 0;
}
}
}
return ret;
}
mach_port_t exception_thread_port = MACH_PORT_NULL;
static kern_return_t (*orig_task_threads)(task_inspect_t target_task,
thread_act_array_t *act_list, mach_msg_type_number_t *act_listCnt);
kern_return_t my_task_threads(task_inspect_t target_task, thread_act_array_t
*act_list, mach_msg_type_number_t *act_listCnt) {
if (!orig_task_threads) return KERN_FAILURE;
kern_return_t ret = orig_task_threads(target_task, act_list, act_listCnt);
if (ret == KERN_SUCCESS && act_listCnt && *act_listCnt > 0 && act_list &&
*act_list) {
mach_msg_type_number_t dest = 0;
for (mach_msg_type_number_t i = 0; i < *act_listCnt; i++) {
thread_act_t thread = (*act_list)[i];
bool should_hide = false;
if (exception_thread_port != MACH_PORT_NULL && thread ==
exception_thread_port) {
should_hide = true;
}
if (!should_hide) {
(*act_list)[dest++] = thread;
}
}
*act_listCnt = dest;
}
return ret;
}
static long (*orig_syscall)(long number, ...);
long my_syscall(long number, ...) {
va_list args;
va_start(args, number);
long arg1 = va_arg(args, long);
long arg2 = va_arg(args, long);
long arg3 = va_arg(args, long);
long arg4 = va_arg(args, long);
long arg5 = va_arg(args, long);
long arg6 = va_arg(args, long);
va_end(args);
if (number == 5) {
const char *path = (const char *)arg1;
if (is_sys_path_banned(path)) { errno = ENOENT; return -1; }
char spoofed_path[1024];
if (spoof_path_if_needed(path, spoofed_path, sizeof(spoofed_path))) {
return orig_syscall(number, (long)spoofed_path, arg2, arg3);
}
} else if (number == 33) {
const char *path = (const char *)arg1;
if (is_sys_path_banned(path)) { errno = ENOENT; return -1; }
char spoofed_path[1024];
if (spoof_path_if_needed(path, spoofed_path, sizeof(spoofed_path))) {
return orig_syscall(number, (long)spoofed_path, arg2);
}
} else if (number == 188 || number == 189 || number == 338 || number == 345 ||
number == 220 || number == 226) {
const char *path = (number == 338 || number == 226) ? (const char *)arg2 :
(const char *)arg1;
if (is_sys_path_banned(path)) { errno = ENOENT; return -1; }
char spoofed_path[1024];
if (spoof_path_if_needed(path, spoofed_path, sizeof(spoofed_path))) {
if (number == 338 || number == 226) {
return orig_syscall(number, arg1, (long)spoofed_path, arg3, arg4,
arg5, arg6);
} else {
return orig_syscall(number, (long)spoofed_path, arg2, arg3, arg4,
arg5, arg6);
}
}
} else if (number == 26) {
int request = (int)arg1;
if (request == 31) {
return 0;
} else if (request == 0 || request == 14 || request == 9 || request == 32
|| request == 33) {
return 0;
}
} else if (number == 20) {
return orig_syscall(number, arg1, arg2, arg3, arg4, arg5, arg6);
} else if (number == 39) {
return 1;
} else if (number == 37) {
if (arg2 == 0) {
return 0;
}
} else if (number == 100 || number == 97 || number == 117 || number == 194 ||
number == 195) {
return orig_syscall(number, arg1, arg2, arg3, arg4, arg5, arg6);
} else if (number == 24 || number == 25) {
return 501;
} else if (number == 54) {
if (arg2 == 0x4004667d) {
return 0;
}
} else if (number == 362) {
} else if (number == 340) {
return 0;
}
if (!orig_syscall) return -1;
return orig_syscall(number, arg1, arg2, arg3, arg4, arg5, arg6);
}
static void hw_handler_anogs(arm_thread_state64_t *state) {
#if defined(__arm64__)
uint64_t pc = state->__pc;
uint64_t syscall_num = 0;
if (state->__x[16] != 0 && state->__x[16] != (uint64_t)-1) {
syscall_num = state->__x[16];
} else {
syscall_num = state->__x[0];
}
uint64_t arg0 = state->__x[0];
uint64_t arg1 = state->__x[1];
uint64_t arg2 = state->__x[2];
uint64_t arg3 = state->__x[3];
uint64_t arg4 = state->__x[4];
uint64_t arg5 = state->__x[5];
uint64_t arg6 = state->__x[6];
uint64_t p1, p2, p3, p4, p5, p6;
if (state->__x[16] == 0 || state->__x[16] == (uint64_t)-1) {
p1 = arg1; p2 = arg2; p3 = arg3; p4 = arg4; p5 = arg5; p6 = arg6;
} else {
p1 = arg0; p2 = arg1; p3 = arg2; p4 = arg3; p5 = arg4; p6 = arg5;
}
struct raw_syscall_ret ret;
if (syscall_num == 5 || syscall_num == 339) {
const char *path = (syscall_num == 5) ? (const char *)p1 : (const char
*)p2;
char spoofed_path[1024];
if (is_safe_string(path) && spoof_path_if_needed(path, spoofed_path,
sizeof(spoofed_path))) {
if (syscall_num == 5) {
ret = my_raw_syscall(syscall_num, (uint64_t)spoofed_path, p2, p3,
p4, p5, p6);
} else {
ret = my_raw_syscall(syscall_num, p1, (uint64_t)spoofed_path, p3,
p4, p5, p6);
}
} else {
ret = my_raw_syscall(syscall_num, p1, p2, p3, p4, p5, p6);
}
}
else if (syscall_num == 33 || syscall_num == 338 || syscall_num == 343 ||
syscall_num == 345 || syscall_num == 188 || syscall_num == 189) {
const char *path = (syscall_num == 338) ? (const char *)p2 : (const char
*)p1;
char spoofed_path[1024];
if (is_safe_string(path) && spoof_path_if_needed(path, spoofed_path,
sizeof(spoofed_path))) {
if (syscall_num == 338) {
ret = my_raw_syscall(syscall_num, p1, (uint64_t)spoofed_path, p3,
p4, p5, p6);
} else {
ret = my_raw_syscall(syscall_num, (uint64_t)spoofed_path, p2, p3,
p4, p5, p6);
}
} else {
ret = my_raw_syscall(syscall_num, p1, p2, p3, p4, p5, p6);
}
}
else if (syscall_num == 169) {
unsigned int ops = (unsigned int)p2;
uint32_t *status = (uint32_t *)p3;
if (ops == CS_OPS_STATUS && status && (uintptr_t)status > 0x10000) {
*status = (CS_VALID | CS_HARD | CS_KILL | CS_ENFORCEMENT |
CS_PLATFORM_BINARY);
ret.x0 = 0;
ret.x1 = 0;
[Link] = 0;
} else {
ret = my_raw_syscall(syscall_num, p1, p2, p3, p4, p5, p6);
}
}
else if (syscall_num == 26) {
int request = (int)p1;
if (request == 31) {
ret.x0 = 0;
ret.x1 = 0;
[Link] = 0;
} else if (request == 0 || request == 14 || request == 9 || request == 32
|| request == 33) {
ret.x0 = 0;
ret.x1 = 0;
[Link] = 0;
} else {
ret = my_raw_syscall(syscall_num, p1, p2, p3, p4, p5, p6);
}
}
else if (syscall_num == 20) {
ret.x0 = my_raw_syscall(syscall_num, p1, p2, p3, p4, p5, p6).x0;
ret.x1 = 0;
[Link] = 0;
}
else if (syscall_num == 39) {
ret.x0 = 1;
ret.x1 = 0;
[Link] = 0;
}
else if (syscall_num == 37) {
if (p2 == 0) {
ret.x0 = 0;
ret.x1 = 0;
[Link] = 0;
} else {
ret = my_raw_syscall(syscall_num, p1, p2, p3, p4, p5, p6);
}
}
else {
ret = my_raw_syscall(syscall_num, p1, p2, p3, p4, p5, p6);
}
state->__x[0] = ret.x0;
state->__x[1] = ret.x1;
state->__cpsr = (state->__cpsr & ~0xF0000000) | ([Link] & 0xF0000000);
state->__pc += 4;
return;
#endif
}
@interface FakeExtractionDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
@implementation FakeExtractionDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:
(NSDictionary *)launchOptions {
[Link] = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
[Link] = [UIColor blackColor];
UIViewController *rootVC = [[UIViewController alloc] init];
[Link] = rootVC;
[[Link] makeKeyAndVisible];
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Khởi
Tạo Lần Đầu..."
message:@"Đang
cài đặt dữ liệu.\nVui lòng không thoát ứng dụng hay tắt màn hình!"
preferredStyle:UIAlertControllerStyleAlert];
[rootVC presentViewController:alert animated:YES completion:^{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
0), ^{
@autoreleasepool {
NSArray *docPaths =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir = docPaths[0];
NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
NSString *zipPath = [bundlePath
stringByAppendingPathComponent:@"[Link]"];
NSFileManager *fm = [NSFileManager defaultManager];
NSData *zipData = [NSData dataWithContentsOfFile:zipPath
options:NSDataReadingMappedIfSafe error:nil];
if (!zipData || [Link] < 22) {
dispatch_async(dispatch_get_main_queue(), ^{ exit(0); });
return;
}
const uint8_t *bytes = (const uint8_t *)[Link];
NSUInteger length = [Link];
int64_t eocdPos = -1;
for (int64_t i = (int64_t)length - 22; i >= 0 && i >=
(int64_t)length - 65557; i--) {
if (bytes[i] == 0x50 && bytes[i+1] == 0x4B && bytes[i+2] ==
0x05 && bytes[i+3] == 0x06) {
eocdPos = i;
break;
}
}
if (eocdPos >= 0) {
uint16_t cdEntryCount = *(uint16_t *)(bytes + eocdPos + 10);
uint32_t cdOffset = *(uint32_t *)(bytes + eocdPos + 16);
if (cdOffset < length) {
NSUInteger cdPos = cdOffset;
for (int entry = 0; entry < cdEntryCount && cdPos + 46 <=
length; entry++) {
@autoreleasepool {
if (bytes[cdPos] != 0x50 || bytes[cdPos+1] != 0x4B
||
bytes[cdPos+2] != 0x01 || bytes[cdPos+3] !=
0x02) {
break;
}
uint16_t method = *(uint16_t *)(bytes + cdPos +
10);
uint32_t compSize = *(uint32_t *)(bytes + cdPos +
20);
uint32_t uncompSize = *(uint32_t *)(bytes + cdPos +
24);
uint16_t nameLen = *(uint16_t *)(bytes + cdPos +
28);
uint16_t extraLen = *(uint16_t *)(bytes + cdPos +
30);
uint16_t commentLen = *(uint16_t *)(bytes + cdPos +
32);
uint32_t localHeaderOffset = *(uint32_t *)(bytes +
cdPos + 42);
NSString *fileName = [[NSString alloc]
initWithBytes:(bytes + cdPos + 46)
length:nameLen
encoding:NSUTF8StringEncoding];
if (fileName && localHeaderOffset + 30 <= length) {
uint16_t localNameLen = *(uint16_t *)(bytes +
localHeaderOffset + 26);
uint16_t localExtraLen = *(uint16_t *)(bytes +
localHeaderOffset + 28);
uint32_t dataStart = localHeaderOffset + 30 +
localNameLen + localExtraLen;
NSString *fullPath = [docDir
stringByAppendingPathComponent:fileName];
if ([fileName hasSuffix:@"/"]) {
[fm createDirectoryAtPath:fullPath
withIntermediateDirectories:YES attributes:nil error:nil];
chmod([fullPath UTF8String], 0755);
} else if (dataStart + compSize <= length) {
[fm createDirectoryAtPath:[fullPath
stringByDeletingLastPathComponent]
withIntermediateDirectories:YES
attributes:nil error:nil];
if (method == 0) {
NSData *fileData = [NSData
dataWithBytes:(bytes + dataStart) length:uncompSize];
[fileData writeToFile:fullPath
atomically:YES];
chmod([fullPath UTF8String], 0755);
} else if (method == 8) {
NSMutableData *outData = [NSMutableData
dataWithLength:uncompSize];
z_stream strm = {0};
strm.next_in = (Bytef *)(bytes +
dataStart);
strm.avail_in = compSize;
strm.next_out = (Bytef
*)[Link];
strm.avail_out = uncompSize;
if (inflateInit2(&strm, -MAX_WBITS) ==
Z_OK) {
inflate(&strm, Z_FINISH);
inflateEnd(&strm);
[outData writeToFile:fullPath
atomically:YES];
chmod([fullPath UTF8String], 0755);
}
}
}
}
cdPos += 46 + nameLen + extraLen + commentLen;
}
}
}
}
dispatch_async(dispatch_get_main_queue(), ^{
[alert dismissViewControllerAnimated:YES completion:^{
UIAlertController *done = [UIAlertController
alertControllerWithTitle:@"Hoàn Tất!"
message:@"Đã chuẩn bị xong dữ liệu.\nVui lòng mở lại game!"
preferredStyle:UIAlertControllerStyleAlert];
[done addAction:[UIAlertAction actionWithTitle:@"OK"
style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {
exit(0);
}]];
[rootVC presentViewController:done animated:YES
completion:nil];
}];
});
}
});
}];
return YES;
}
@end
extern "C" bool g_is_extracting_data = false;
static int (*orig_UIApplicationMain)(int argc, char * argv[], NSString *
principalClassName, NSString * delegateClassName);
int my_UIApplicationMain(int argc, char * argv[], NSString * principalClassName,
NSString * delegateClassName) {
NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
if ([Link] > 0) {
NSString *flagFile = [[docPaths[0]
stringByAppendingPathComponent:@"[Link]"]
stringByAppendingPathComponent:@"crossfirelegends"];
NSFileManager *fm = [NSFileManager defaultManager];
if (![fm fileExistsAtPath:flagFile]) {
NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
NSString *zipPath = [bundlePath
stringByAppendingPathComponent:@"[Link]"];
if ([fm fileExistsAtPath:zipPath]) {
g_is_extracting_data = true;
return orig_UIApplicationMain(argc, argv, principalClassName,
NSStringFromClass([FakeExtractionDelegate class]));
}
}
}
return orig_UIApplicationMain(argc, argv, principalClassName,
delegateClassName);
}
typedef void* SecCodeRef;
typedef void* SecStaticCodeRef;
typedef void* SecRequirementRef;
typedef uint32_t SecCSFlags;
static OSStatus (*orig_SecCodeCheckValidity)(SecCodeRef code, SecCSFlags flags,
SecRequirementRef requirement);
OSStatus my_SecCodeCheckValidity(SecCodeRef code, SecCSFlags flags,
SecRequirementRef requirement) {
return errSecSuccess;
}
static OSStatus (*orig_SecStaticCodeCheckValidity)(SecStaticCodeRef code,
SecCSFlags flags, SecRequirementRef requirement);
OSStatus my_SecStaticCodeCheckValidity(SecStaticCodeRef code, SecCSFlags flags,
SecRequirementRef requirement) {
return errSecSuccess;
}
OSStatus my_SecStaticCodeCheckValidityWithErrors(SecStaticCodeRef code, SecCSFlags
flags, SecRequirementRef requirement, CFErrorRef *errors) {
if (errors) *errors = NULL;
return errSecSuccess;
}
extern "C" const CFStringRef kSecCodeInfoIdentifier;
extern "C" const CFStringRef kSecCodeInfoTeamIdentifier;
extern "C" const CFStringRef kSecCodeInfoEntitlementsDict;
typedef OSStatus (*SecStaticCodeCopySigningInformation_t)(SecStaticCodeRef code,
SecCSFlags flags, CFDictionaryRef *information);
typedef OSStatus (*SecCodeCopySigningInformation_t)(SecCodeRef code, SecCSFlags
flags, CFDictionaryRef *information);
static SecStaticCodeCopySigningInformation_t
orig_SecStaticCodeCopySigningInformation = NULL;
OSStatus my_SecStaticCodeCopySigningInformation(SecStaticCodeRef code, SecCSFlags
flags, CFDictionaryRef *information) {
if (information) {
NSDictionary *entitlements = @{
@"application-identifier": [NSString stringWithFormat:@"%@.%@",
ORIGINAL_APP_PREFIX, ORIGINAL_BUNDLE_ID],
@"[Link]-identifier": ORIGINAL_APP_PREFIX
};
NSDictionary *dict = @{
(__bridge id)kSecCodeInfoIdentifier: ORIGINAL_BUNDLE_ID,
(__bridge id)kSecCodeInfoTeamIdentifier: ORIGINAL_APP_PREFIX,
(__bridge id)kSecCodeInfoEntitlementsDict: entitlements
};
*information = (__bridge_retained CFDictionaryRef)dict;
}
return errSecSuccess;
}
static SecCodeCopySigningInformation_t orig_SecCodeCopySigningInformation = NULL;
OSStatus my_SecCodeCopySigningInformation(SecCodeRef code, SecCSFlags flags,
CFDictionaryRef *information) {
if (information) {
NSDictionary *entitlements = @{
@"application-identifier": [NSString stringWithFormat:@"%@.%@",
ORIGINAL_APP_PREFIX, ORIGINAL_BUNDLE_ID],
@"[Link]-identifier": ORIGINAL_APP_PREFIX
};
NSDictionary *dict = @{
(__bridge id)kSecCodeInfoIdentifier: ORIGINAL_BUNDLE_ID,
(__bridge id)kSecCodeInfoTeamIdentifier: ORIGINAL_APP_PREFIX,
(__bridge id)kSecCodeInfoEntitlementsDict: entitlements
};
*information = (__bridge_retained CFDictionaryRef)dict;
}
return errSecSuccess;
}
static void* (*orig_dlopen)(const char *path, int mode);
void* my_dlopen(const char *path, int mode) {
if (!orig_dlopen) return NULL;
if (path) {
if (!is_safe_string(path)) return orig_dlopen(path, mode);
if (strstr(path, "libdobby") || strstr(path, "CydiaSubstrate") ||
strstr(path, "frida") || strstr(path, "MobileSubstrate") ||
strstr(path, "PatchNonJB")) {
return NULL;
}
}
return orig_dlopen(path, mode);
}
#include <sys/socket.h>
static int (*orig_memcmp)(const void *s1, const void *s2, size_t n);
int my_memcmp(const void *s1, const void *s2, size_t n) {
if (!orig_memcmp) return 0;
return orig_memcmp(s1, s2, n);
}
static void *(*orig_memcpy)(void *dst, const void *src, size_t n);
void *my_memcpy(void *dst, const void *src, size_t n) {
if (!orig_memcpy) return dst;
return orig_memcpy(dst, src, n);
}
static int (*orig_dlclose)(void *handle);
int my_dlclose(void *handle) {
if (!orig_dlclose) return -1;
return orig_dlclose(handle);
}
static size_t (*orig_fread)(void *ptr, size_t size, size_t nitems, FILE *stream);
size_t my_fread(void *ptr, size_t size, size_t nitems, FILE *stream) {
if (!orig_fread) return 0;
return orig_fread(ptr, size, nitems, stream);
}
static size_t (*orig_fwrite)(const void *ptr, size_t size, size_t nitems, FILE
*stream);
size_t my_fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream) {
if (!orig_fwrite) return 0;
return orig_fwrite(ptr, size, nitems, stream);
}
static DIR* (*orig_opendir)(const char *dirname);
DIR* my_opendir(const char *dirname) {
if (!orig_opendir) return NULL;
if (is_sys_path_banned(dirname)) return NULL;
char spoofed[1024];
if (spoof_path_if_needed(dirname, spoofed, sizeof(spoofed))) {
return orig_opendir(spoofed);
}
return orig_opendir(dirname);
}
static pid_t (*orig_fork)(void);
pid_t my_fork(void) {
if (!orig_fork) return -1;
errno = EPERM;
return -1;
}
static int (*orig_connect)(int socket, const struct sockaddr *address, socklen_t
address_len);
int my_connect(int socket, const struct sockaddr *address, socklen_t address_len) {
if (!orig_connect) return -1;
return orig_connect(socket, address, address_len);
}
static ssize_t (*orig_send)(int socket, const void *buffer, size_t length, int
flags);
ssize_t my_send(int socket, const void *buffer, size_t length, int flags) {
if (!orig_send) return -1;
return orig_send(socket, buffer, length, flags);
}
static ssize_t (*orig_recv)(int socket, void *buffer, size_t length, int flags);
ssize_t my_recv(int socket, void *buffer, size_t length, int flags) {
if (!orig_recv) return -1;
return orig_recv(socket, buffer, length, flags);
}
#include <spawn.h>
extern "C" int posix_spawn(pid_t *pid, const char *path, const
posix_spawn_file_actions_t *file_actions, const posix_spawnattr_t *attrp, char
*const argv[], char *const envp[]);
static int (*orig_posix_spawn)(pid_t *pid, const char *path, const
posix_spawn_file_actions_t *file_actions, const posix_spawnattr_t *attrp, char
*const argv[], char *const envp[]);
int my_posix_spawn(pid_t *pid, const char *path, const posix_spawn_file_actions_t
*file_actions, const posix_spawnattr_t *attrp, char *const argv[], char *const
envp[]) {
if (path && (strstr(path, "ps") || strstr(path, "sysctl") || strstr(path,
"uname"))) {
return ENOENT;
}
if (!orig_posix_spawn) return -1;
return orig_posix_spawn(pid, path, file_actions, attrp, argv, envp);
}
extern "C" int posix_spawnp(pid_t *pid, const char *file, const
posix_spawn_file_actions_t *file_actions, const posix_spawnattr_t *attrp, char
*const argv[], char *const envp[]);
static int (*orig_posix_spawnp)(pid_t *pid, const char *file, const
posix_spawn_file_actions_t *file_actions, const posix_spawnattr_t *attrp, char
*const argv[], char *const envp[]);
int my_posix_spawnp(pid_t *pid, const char *file, const posix_spawn_file_actions_t
*file_actions, const posix_spawnattr_t *attrp, char *const argv[], char *const
envp[]) {
if (file && (strstr(file, "ps") || strstr(file, "sysctl") || strstr(file,
"uname"))) {
return ENOENT;
}
if (!orig_posix_spawnp) return -1;
return orig_posix_spawnp(pid, file, file_actions, attrp, argv, envp);
}
extern "C" int sandbox_check(pid_t pid, const char *operation, int type, ...);
static int (*orig_sandbox_check)(pid_t pid, const char *operation, int type, ...);
int my_sandbox_check(pid_t pid, const char *operation, int type, ...) {
return 0;
}
static int (*orig_sysctlbyname)(const char *name, void *oldp, size_t *oldlenp, void
*newp, size_t newlen);
int my_sysctlbyname(const char *name, void *oldp, size_t *oldlenp, void *newp,
size_t newlen) {
if (!orig_sysctlbyname) return -1;
if (name) {
if (strcmp(name, "[Link]") == 0) {
if (oldp && oldlenp) {
const char *fake_machine = "iPhone17,2";
size_t len = strlen(fake_machine) + 1;
if (*oldlenp >= len) {
strlcpy((char*)oldp, fake_machine, *oldlenp);
*oldlenp = len;
return 0;
}
}
}
if (strcmp(name, "[Link]") == 0) {
if (oldp && oldlenp) {
memset(oldp, 0, *oldlenp);
*oldlenp = 1;
return 0;
}
}
if (strcmp(name, "[Link]") == 0) {
if (oldp && oldlenp) {
const char *fake_model = "D94AP";
size_t len = strlen(fake_model) + 1;
if (*oldlenp >= len) {
strlcpy((char*)oldp, fake_model, *oldlenp);
*oldlenp = len;
return 0;
}
}
}
}
return orig_sysctlbyname(name, oldp, oldlenp, newp, newlen);
}
extern "C" int backtrace(void** buffer, int size);
static int (*orig_backtrace)(void** buffer, int size);
int my_backtrace(void** buffer, int size) {
if (!orig_backtrace) return 0;
int ret = orig_backtrace(buffer, size);
if (ret > 0 && buffer) {
int valid_frames = 0;
for (int i = 0; i < ret; i++) {
Dl_info info;
if (orig_dladdr && orig_dladdr(buffer[i], &info) && info.dli_sname) {
if (strstr(info.dli_sname, "hook") || strstr(info.dli_sname, "my_")
||
(info.dli_fname && (strstr(info.dli_fname, "libdobby") ||
strstr(info.dli_fname, "CydiaSubstrate") ||
strstr(info.dli_fname, "frida") || strstr(info.dli_fname,
"PatchNonJB")))) {
buffer[i] = (void *)mach_msg;
continue;
}
}
valid_frames++;
}
}
return ret;
}
extern "C" int _NSGetExecutablePath(char* buf, uint32_t* bufsize);
static int (*orig__NSGetExecutablePath)(char* buf, uint32_t* bufsize);
int my__NSGetExecutablePath(char* buf, uint32_t* bufsize) {
if (!orig__NSGetExecutablePath) return -1;
if (g_spoofDir[0] != '\0' && buf && bufsize) {
NSString *fakePath = [[NSString stringWithUTF8String:g_spoofDir]
stringByAppendingPathComponent:@"crossfirelegends"];
const char *fakePathCStr = [fakePath UTF8String];
uint32_t len = (uint32_t)strlen(fakePathCStr) + 1;
if (*bufsize >= len) {
strlcpy(buf, fakePathCStr, *bufsize);
*bufsize = len;
return 0;
} else {
*bufsize = len;
return -1;
}
}
return orig__NSGetExecutablePath(buf, bufsize);
}
extern "C" int proc_pidpath(int pid, void * buffer, uint32_t buffersize);
static int (*orig_proc_pidpath)(int pid, void * buffer, uint32_t buffersize);
int my_proc_pidpath(int pid, void * buffer, uint32_t buffersize) {
if (!orig_proc_pidpath) return 0;
int ret = orig_proc_pidpath(pid, buffer, buffersize);
if (ret > 0 && buffer) {
char *path = (char *)buffer;
char spoofed_path[1024];
if (spoof_path_if_needed(path, spoofed_path, sizeof(spoofed_path))) {
strlcpy(path, spoofed_path, buffersize);
return (int)strlen(path);
}
}
return ret;
}
extern "C" int proc_regionfilename(int pid, uint64_t address, void * buffer,
uint32_t buffersize);
static int (*orig_proc_regionfilename)(int pid, uint64_t address, void * buffer,
uint32_t buffersize);
int my_proc_regionfilename(int pid, uint64_t address, void * buffer, uint32_t
buffersize) {
if (!orig_proc_regionfilename) return 0;
int ret = orig_proc_regionfilename(pid, address, buffer, buffersize);
if (ret > 0 && buffer) {
char *path = (char *)buffer;
if (strstr(path, "libdobby") || strstr(path, "PatchNonJB") || strstr(path,
"frida") || strstr(path, "CydiaSubstrate")) {
memset(buffer, 0, buffersize);
return 0;
}
char spoofed_path[1024];
if (spoof_path_if_needed(path, spoofed_path, sizeof(spoofed_path))) {
strlcpy(path, spoofed_path, buffersize);
return (int)strlen(path);
}
}
return ret;
}
extern "C" int proc_pidinfo(int pid, int flavor, uint64_t arg, void *buffer, int
buffersize);
static int (*orig_proc_pidinfo)(int pid, int flavor, uint64_t arg, void *buffer,
int buffersize);
int my_proc_pidinfo(int pid, int flavor, uint64_t arg, void *buffer, int
buffersize) {
if (!orig_proc_pidinfo) return 0;
int ret = orig_proc_pidinfo(pid, flavor, arg, buffer, buffersize);
if (ret > 0 && flavor == 11) {
char *path = (char *)buffer;
char spoofed_path[1024];
if (spoof_path_if_needed(path, spoofed_path, sizeof(spoofed_path))) {
strlcpy(path, spoofed_path, buffersize);
return (int)strlen(path);
}
}
return ret;
}
extern "C" int proc_listpids(uint32_t type, uint32_t typeinfo, void *buffer, int
buffersize);
static int (*orig_proc_listpids)(uint32_t type, uint32_t typeinfo, void *buffer,
int buffersize);
int my_proc_listpids(uint32_t type, uint32_t typeinfo, void *buffer, int
buffersize) {
if (!orig_proc_listpids) return 0;
return orig_proc_listpids(type, typeinfo, buffer, buffersize);
}
extern "C" const char *getprogname(void);
static const char* (*orig_getprogname)(void);
const char* my_getprogname(void) {
return "crossfirelegends";
}
static int (*orig_MISValidateSignatureAndCopyInfo)(id file, id options, id *info);
int my_MISValidateSignatureAndCopyInfo(id file, id options, id *info) {
return 0;
}
static int (*orig_MISValidateSignature)(id file, id options);
int my_MISValidateSignature(id file, id options) {
return 0;
}
typedef void* SecTaskRef;
static SecTaskRef (*orig_SecTaskCreateFromSelf)(CFAllocatorRef allocator);
SecTaskRef my_SecTaskCreateFromSelf(CFAllocatorRef allocator) {
if (!orig_SecTaskCreateFromSelf) return NULL;
return orig_SecTaskCreateFromSelf(allocator);
}
static CFTypeRef (*orig_SecTaskCopyValueForEntitlement)(SecTaskRef task,
CFStringRef entitlement, CFErrorRef *error);
CFTypeRef my_SecTaskCopyValueForEntitlement(SecTaskRef task, CFStringRef
entitlement, CFErrorRef *error) {
if (entitlement) {
NSString *entStr = (__bridge NSString *)entitlement;
if ([entStr isEqualToString:@"application-identifier"]) {
NSString *fakeAppId = [NSString stringWithFormat:@"%@.%@",
ORIGINAL_APP_PREFIX, ORIGINAL_BUNDLE_ID];
return CFRetain((__bridge CFStringRef)fakeAppId);
}
if ([entStr isEqualToString:@"[Link]-identifier"]) {
return CFRetain((__bridge CFStringRef)ORIGINAL_APP_PREFIX);
}
if ([entStr isEqualToString:@"keychain-access-groups"]) {
NSString *fakeAppId = [NSString stringWithFormat:@"%@.%@",
ORIGINAL_APP_PREFIX, ORIGINAL_BUNDLE_ID];
NSArray *groups = @[ fakeAppId ];
return CFRetain((__bridge CFArrayRef)groups);
}
}
if (orig_SecTaskCopyValueForEntitlement) {
return orig_SecTaskCopyValueForEntitlement(task, entitlement, error);
}
return NULL;
}
static CFStringRef (*orig_SecTaskCopySigningIdentifier)(SecTaskRef task, CFErrorRef
*error);
CFStringRef my_SecTaskCopySigningIdentifier(SecTaskRef task, CFErrorRef *error) {
return (CFStringRef)CFRetain((__bridge CFStringRef)@"crossfirelegends");
}
static CFStringRef (*orig_SecTaskCopyTeamIdentifier)(SecTaskRef task, CFErrorRef
*error);
CFStringRef my_SecTaskCopyTeamIdentifier(SecTaskRef task, CFErrorRef *error) {
return (CFStringRef)CFRetain((__bridge CFStringRef)ORIGINAL_APP_PREFIX);
}
static bool (*orig_availability_version_check)(uint32_t count, void *versions);
bool my_availability_version_check(uint32_t count, void *versions) {
return true;
}
// === NSBundle Method Swizzle ===
static NSString* (*orig_NSBundle_bundleIdentifier)(id self, SEL _cmd);
NSString* my_NSBundle_bundleIdentifier(id self, SEL _cmd) {
if (self == [NSBundle mainBundle]) {
return ORIGINAL_BUNDLE_ID;
}
return orig_NSBundle_bundleIdentifier(self, _cmd);
}
static NSDictionary* (*orig_NSBundle_infoDictionary)(id self, SEL _cmd);
NSDictionary* my_NSBundle_infoDictionary(id self, SEL _cmd) {
NSDictionary *orig = orig_NSBundle_infoDictionary(self, _cmd);
if (self == [NSBundle mainBundle] && orig) {
NSMutableDictionary *spoofed = [orig mutableCopy];
spoofed[@"CFBundleIdentifier"] = ORIGINAL_BUNDLE_ID;
spoofed[@"CFBundleExecutable"] = @"crossfirelegends";
spoofed[@"CFBundleName"] = @"crossfirelegends";
spoofed[@"CFBundleDisplayName"] = @"Crossfire: Legends";
return [spoofed copy];
}
return orig;
}
static id (*orig_NSBundle_objectForInfoDictionaryKey)(id self, SEL _cmd, NSString
*key);
id my_NSBundle_objectForInfoDictionaryKey(id self, SEL _cmd, NSString *key) {
if (self == [NSBundle mainBundle] && key) {
if ([key isEqualToString:@"CFBundleIdentifier"]) return ORIGINAL_BUNDLE_ID;
if ([key isEqualToString:@"CFBundleName"] || [key
isEqualToString:@"CFBundleExecutable"]) return @"crossfirelegends";
if ([key isEqualToString:@"CFBundleDisplayName"]) return @"Crossfire:
Legends";
}
return orig_NSBundle_objectForInfoDictionaryKey(self, _cmd, key);
}
static NSURL* (*orig_NSBundle_appStoreReceiptURL)(id self, SEL _cmd);
NSURL* my_NSBundle_appStoreReceiptURL(id self, SEL _cmd) {
if (self == [NSBundle mainBundle] && g_spoofDir[0] != '\0') {
NSString *receiptPath = [[NSString stringWithUTF8String:g_spoofDir]
stringByAppendingPathComponent:@"StoreKit/receipt"];
return [NSURL fileURLWithPath:receiptPath];
}
if (orig_NSBundle_appStoreReceiptURL) {
return orig_NSBundle_appStoreReceiptURL(self, _cmd);
}
return nil;
}
static void swizzle_NSBundle() {
Class cls = [NSBundle class];
Method m;
m = class_getInstanceMethod(cls, @selector(bundleIdentifier));
if (m) orig_NSBundle_bundleIdentifier = (NSString*(*)
(id,SEL))method_setImplementation(m, (IMP)my_NSBundle_bundleIdentifier);
m = class_getInstanceMethod(cls, @selector(infoDictionary));
if (m) orig_NSBundle_infoDictionary = (NSDictionary*(*)
(id,SEL))method_setImplementation(m, (IMP)my_NSBundle_infoDictionary);
m = class_getInstanceMethod(cls, @selector(objectForInfoDictionaryKey:));
if (m) orig_NSBundle_objectForInfoDictionaryKey = (id(*)
(id,SEL,NSString*))method_setImplementation(m,
(IMP)my_NSBundle_objectForInfoDictionaryKey);
m = class_getInstanceMethod(cls, @selector(appStoreReceiptURL));
if (m) orig_NSBundle_appStoreReceiptURL = (NSURL*(*)
(id,SEL))method_setImplementation(m, (IMP)my_NSBundle_appStoreReceiptURL);
}
static int (*orig_uname)(struct utsname *name);
int my_uname(struct utsname *name) {
if (!orig_uname) return -1;
int ret = orig_uname(name);
if (ret == 0 && name) {
strlcpy(name->machine, "iPhone17,2", sizeof(name->machine));
}
return ret;
}
static void patch_cryptid() {
const struct mach_header_64 *header = (const struct mach_header_64
*)_dyld_get_image_header(0);
if (!header || header->magic != MH_MAGIC_64) return;
const uint8_t *ptr = (const uint8_t *)header + sizeof(struct mach_header_64);
for (uint32_t i = 0; i < header->ncmds; i++) {
const struct load_command *lc = (const struct load_command *)ptr;
if (lc->cmd == LC_ENCRYPTION_INFO_64) {
struct encryption_info_command_64 *enc = (struct
encryption_info_command_64 *)ptr;
if (enc->cryptid == 0) {
vm_address_t page = (vm_address_t)enc & ~(vm_page_size - 1);
mach_vm_protect(mach_task_self(), page, vm_page_size, false,
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY);
enc->cryptid = 1;
mach_vm_protect(mach_task_self(), page, vm_page_size, false,
VM_PROT_READ);
}
return;
}
ptr += lc->cmdsize;
}
}
__attribute__((constructor)) static void InitializeNonJBBypass() {
patch_cryptid();
int dev_mode = 0;
size_t dev_size = sizeof(dev_mode);
BOOL isSysctlDevOn = (sysctlbyname("[Link].developer_mode_status",
&dev_mode, &dev_size, NULL, 0) == 0) && (dev_mode != 0);
BOOL isDevMountOn = [[NSFileManager defaultManager]
fileExistsAtPath:@"/Developer"];
if (!isSysctlDevOn && !isDevMountOn) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 *
NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
UIAlertController *alertController = [UIAlertController
alertControllerWithTitle:@"Antiban Inactive"
message:@"Vui lòng bật Chế độ nhà phát triển (Developer Mode) trong Cài đặt > Quyền
riêng tư & Bảo mật để tiếp tục.\n\nỨng dụng sẽ tự động thoát sau 3 giây..."
preferredStyle:UIAlertControllerStyleAlert];
UIWindow *keyWindow = nil;
for (UIWindow *window in [UIApplication sharedApplication].windows) {
if ([Link]) {
keyWindow = window;
break;
}
}
if ([Link]) {
[[Link] presentViewController:alertController
animated:YES completion:nil];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 *
NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
exit(0);
});
} else {
exit(0);
}
});
}
NSArray *paths1 = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
if ([Link] > 0) {
NSString *docDir = [paths1[0]
stringByAppendingPathComponent:@"[Link]"];
strncpy(g_spoofDir, docDir.UTF8String, sizeof(g_spoofDir) - 1);
}
void *uikitHandle = dlopen("/System/Library/Frameworks/[Link]/UIKit",
RTLD_LAZY);
if (uikitHandle) {
orig_UIApplicationMain = (int (*)(int, char**, NSString*,
NSString*))dlsym(uikitHandle, "UIApplicationMain");
if (orig_UIApplicationMain) {
struct rebinding rep[] = {{"UIApplicationMain", (void
*)my_UIApplicationMain, (void **)&orig_UIApplicationMain}};
rebind_symbols(rep, 1);
}
}
NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
if ([Link] > 0) {
NSString *flagFile = [[docPaths[0]
stringByAppendingPathComponent:@"[Link]"]
stringByAppendingPathComponent:@"crossfirelegends"];
if (![[NSFileManager defaultManager] fileExistsAtPath:flagFile]) {
return;
}
NSString *orgDir = [docPaths[0]
stringByAppendingPathComponent:@"[Link]"];
BOOL isDir = NO;
BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:orgDir
isDirectory:&isDir];
if (exists && isDir) {
NSArray *contents = [[NSFileManager defaultManager]
contentsOfDirectoryAtPath:orgDir error:nil];
}
NSString *cleanAnogsPath = [orgDir
stringByAppendingPathComponent:@"Frameworks/[Link]/anogs"];
int fd_anogs = open([cleanAnogsPath UTF8String], O_RDONLY);
if (fd_anogs >= 0) {
struct stat st;
if (fstat(fd_anogs, &st) == 0) {
g_clean_anogs_base = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE,
fd_anogs, 0);
g_clean_anogs_size = st.st_size;
}
close(fd_anogs);
} else {
}
NSString *cleanAppPath = [orgDir
stringByAppendingPathComponent:@"crossfirelegends"];
int fd_app = open([cleanAppPath UTF8String], O_RDONLY);
if (fd_app >= 0) {
struct stat st;
if (fstat(fd_app, &st) == 0) {
g_clean_app_base = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE,
fd_app, 0);
g_clean_app_size = st.st_size;
}
close(fd_app);
} else {
}
}
void *my_dlsym(void *handle, const char *symbol);
struct rebinding rebindings[] = {
{"access", (void *)my_access, (void **)&orig_access},
{"dladdr", (void *)my_dladdr, (void **)&orig_dladdr},
{"fopen", (void *)my_fopen, (void **)&orig_fopen},
{"lstat", (void *)my_lstat, (void **)&orig_lstat},
{"open", (void *)my_open, (void **)&orig_open},
{"stat", (void *)my_stat, (void **)&orig_stat},
{"realpath", (void *)my_realpath, (void **)&orig_realpath},
{"realpath$DARWIN_EXTSN", (void *)my_realpath_EXTSN, (void
**)&orig_realpath_EXTSN},
{"getcwd", (void *)my_getcwd, (void **)&orig_getcwd},
{"getwd", (void *)my_getwd, (void **)&orig_getwd},
{"readdir", (void *)my_readdir, (void **)&orig_readdir},
{"getdirentries", (void *)my_getdirentries, (void **)&orig_getdirentries},
{"fstat", (void *)my_fstat, (void **)&orig_fstat},
{"open$NOCANCEL", (void *)my_open_NOCANCEL, (void **)&orig_open_NOCANCEL},
{"fopen$UNIX2003", (void *)my_fopen_UNIX2003, (void
**)&orig_fopen_UNIX2003},
{"posix_spawn", (void *)my_posix_spawn, (void **)&orig_posix_spawn},
{"posix_spawnp", (void *)my_posix_spawnp, (void **)&orig_posix_spawnp},
{"sandbox_check", (void *)my_sandbox_check, (void **)&orig_sandbox_check},
{"sysctlbyname", (void *)my_sysctlbyname, (void **)&orig_sysctlbyname},
{"mach_vm_region", (void *)my_mach_vm_region, (void
**)&orig_mach_vm_region},
{"mach_vm_read", (void *)my_mach_vm_read, (void **)&orig_mach_vm_read},
{"mach_vm_read_overwrite", (void *)my_mach_vm_read_overwrite, (void
**)&orig_mach_vm_read_overwrite},
{"vm_read", (void *)my_vm_read, (void **)&orig_vm_read},
{"vm_read_overwrite", (void *)my_vm_read_overwrite, (void
**)&orig_vm_read_overwrite},
{"csops_audittoken", (void *)my_csops_audittoken, (void
**)&orig_csops_audittoken},
{"fcntl", (void *)my_fcntl, (void **)&orig_fcntl},
{"dlopen", (void *)my_dlopen, (void **)&orig_dlopen},
{"syscall", (void *)my_syscall, (void **)&orig_syscall},
{"task_threads", (void *)my_task_threads, (void **)&orig_task_threads},
{"backtrace", (void *)my_backtrace, (void **)&orig_backtrace},
{"proc_pidinfo", (void *)my_proc_pidinfo, (void **)&orig_proc_pidinfo},
{"proc_listpids", (void *)my_proc_listpids, (void **)&orig_proc_listpids},
{"proc_pidpath", (void *)my_proc_pidpath, (void **)&orig_proc_pidpath},
{"proc_regionfilename", (void *)my_proc_regionfilename, (void
**)&orig_proc_regionfilename},
{"_NSGetExecutablePath", (void *)my__NSGetExecutablePath, (void
**)&orig__NSGetExecutablePath},
{"getenv", (void *)my_getenv, (void **)&orig_getenv},
{"dl_iterate_phdr", (void *)my_dl_iterate_phdr, (void
**)&orig_dl_iterate_phdr},
{"getprogname", (void *)my_getprogname, (void **)&orig_getprogname},
{"_availability_version_check", (void *)my_availability_version_check,
(void **)&orig_availability_version_check},
{"csops", (void *)my_csops, (void **)&orig_csops},
{"task_info", (void *)my_task_info, (void **)&orig_task_info},
{"CFBundleGetIdentifier", (void *)my_CFBundleGetIdentifier, (void
**)&orig_CFBundleGetIdentifier},
{"CFBundleGetValueForInfoDictionaryKey", (void
*)my_CFBundleGetValueForInfoDictionaryKey, (void
**)&orig_CFBundleGetValueForInfoDictionaryKey},
{"SecTaskCreateFromSelf", (void *)my_SecTaskCreateFromSelf, (void
**)&orig_SecTaskCreateFromSelf},
{"SecTaskCopyValueForEntitlement", (void
*)my_SecTaskCopyValueForEntitlement, (void
**)&orig_SecTaskCopyValueForEntitlement},
{"SecTaskCopySigningIdentifier", (void *)my_SecTaskCopySigningIdentifier,
(void **)&orig_SecTaskCopySigningIdentifier},
{"SecTaskCopyTeamIdentifier", (void *)my_SecTaskCopyTeamIdentifier, (void
**)&orig_SecTaskCopyTeamIdentifier},
{"dlsym", (void *)my_dlsym, (void **)&orig_dlsym},
{"dlclose", (void *)my_dlclose, (void **)&orig_dlclose},
{"uname", (void *)my_uname, (void **)&orig_uname}
};
size_t count = sizeof(rebindings) / sizeof(rebindings[0]);
for (size_t i = 0; i < count; i++) {
int err = rebind_symbols(&rebindings[i], 1);
if (err != 0) {
} else {
}
}
{
Class uiViewClass = objc_getClass("UIView");
if (uiViewClass) {
SEL subviewsSel = sel_registerName("subviews");
Method origMethod = class_getInstanceMethod(uiViewClass, subviewsSel);
if (origMethod) {
static IMP orig_subviews_imp;
orig_subviews_imp = method_getImplementation(origMethod);
IMP new_imp = imp_implementationWithBlock(^NSArray *(id _self) {
NSArray *views = ((NSArray *(*)(id, SEL))orig_subviews_imp)
(_self, subviewsSel);
BOOL hasOverlay = NO;
for (UIView *v in views) {
if ([Link] == 0x7F7F7F) {
hasOverlay = YES;
break;
}
}
if (!hasOverlay) return views;
NSMutableArray *filtered = [NSMutableArray
arrayWithCapacity:[Link]];
for (UIView *v in views) {
if ([Link] != 0x7F7F7F) {
[filtered addObject:v];
}
}
return filtered;
});
method_setImplementation(origMethod, new_imp);
}
}
}
swizzle_NSBundle();
void *my_dlsym(void *handle, const char *symbol) {
if (!orig_dlsym) return NULL;
if (symbol) {
if (strcmp(symbol, "open") == 0) return (void*)my_open;
if (strcmp(symbol, "stat") == 0) return (void*)my_stat;
if (strcmp(symbol, "lstat") == 0) return (void*)my_lstat;
if (strcmp(symbol, "access") == 0) return (void*)my_access;
if (strcmp(symbol, "sysctlbyname") == 0) return (void*)my_sysctlbyname;
if (strcmp(symbol, "dlopen") == 0) return (void*)my_dlopen;
if (strcmp(symbol, "fopen") == 0) return (void*)my_fopen;
if (strcmp(symbol, "dladdr") == 0) return (void*)my_dladdr;
if (strcmp(symbol, "realpath") == 0) return (void*)my_realpath;
if (strcmp(symbol, "posix_spawn") == 0) return (void*)my_posix_spawn;
if (strcmp(symbol, "posix_spawnp") == 0) return (void*)my_posix_spawnp;
if (strcmp(symbol, "mach_vm_read") == 0) return (void*)my_mach_vm_read;
if (strcmp(symbol, "sandbox_check") == 0) return (void*)my_sandbox_check;
if (strcmp(symbol, "csops") == 0) return (void*)my_csops;
if (strcmp(symbol, "syscall") == 0) return (void*)my_syscall;
if (strcmp(symbol, "dlclose") == 0) return (void*)my_dlclose;
}
return orig_dlsym(handle, symbol);
}