iOS开发安全 - 防重签名、越狱、调试检测

文章目录

一、判断Mach-O文件否被篡改

二次签名会篡改信息文件

public static func isSecondIPA() -> Bool {
        let bundle = Bundle.main
        let info = bundle.infoDictionary
        if info?["SignerIdentity"] != nil {
            return true
        }
        return false
    }

二、重签名检测

检测包签名是否和已知自己签名一致

public static func checkCodeSign(_ provisionID: String) -> Bool {
        // 描述文件路径
        let embededPath = Bundle.main.path(forResource: "embedded", ofType: "mobileprovision")
        guard let embededPath = embededPath,
              FileManager.default.fileExists(atPath: embededPath) == true
        else {
            return true
        }
        // 读取application-identifier
        guard let embeddedProvisioning = try? String.init(contentsOfFile: embededPath, encoding: .ascii) else {
            return true
        }
        let embeddedProvisioningLines = embeddedProvisioning.components(separatedBy: CharacterSet.newlines)
        for i in 0..<embeddedProvisioningLines.count {
            let emStr = embeddedProvisioningLines[i]
            guard let index = emStr.range(of: "application-identifier")?.lowerBound,
                  index.hashValue != NSNotFound
            else {
                continue
            }
            let positionStr = embeddedProvisioningLines[i + 1]
            let fromPosition = positionStr.range(of: "<string>")?.upperBound ?? positionStr.startIndex
            let toPosition = positionStr.range(of: "</string>")?.lowerBound ?? positionStr.endIndex
            
            let range = Range(uncheckedBounds: (fromPosition, toPosition))
            
            let fullIdentifier = positionStr[range]
            let identifierComponents = fullIdentifier.components(separatedBy: ".")
            let appIdentifier = identifierComponents.first
            // 对比签名ID
            if appIdentifier == provisionID {
                return false
            } else {
                return true
            }
            
        }
        return false
    }

三、是否越狱

public static func isJailbreak() -> Bool {
        guard TARGET_OS_SIMULATOR == 0 else {
            return false
        }
        // 越狱检查
        // CanOpenURL检查
        let fakeURL = URL(string: "cydia://package/com.fake.package")
        if UIApplication.shared.canOpenURL(fakeURL!) == true {
            return true
        }
        
        // Cydia应用检查
        var stat_info: stat
        // 使用stat系列函数检测Cydia等工具
        if stat("/Applications/Cydia.app", &stat_info) == 0 {
            return true
        }
        
        // fork函数检查
//        if fork()>=0 {
//            return true
//        }
        
        // 注入动态库检查
        if let env = getenv("DYLD_INSERT_LIBRARIES") {
            return true
        }
        
        // 无法访问文件检查
        let files = ["/Applications/Cydia.app",
                     "/Applications/limera1n.app",
                     "/Applications/greenpois0n.app",
                     "/Applications/blackra1n.app",
                     "/Applications/blacksn0w.app",
                     "/Applications/redsn0w.app",
                     "/Applications/Absinthe.app",
                     "/Library/MobileSubstrate/MobileSubstrate.dylib",
                     "/bin/bash",
                     "/usr/sbin/sshd",
                     "/etc/apt",
                     "/private/var/lib/apt/"]
        for fileName in files {
            if FileManager.default.fileExists(atPath: fileName) {
                return true
            }
        }
        return false
    }

四、防止抓包

发起请求之前判断是否存在代理,存在代理就直接返回,请求失败

+ (BOOL)getProxyStatus {
    NSDictionary *proxySettings =  (__bridge NSDictionary *)(CFNetworkCopySystemProxySettings());
    NSArray *proxies = (__bridge NSArray *)(CFNetworkCopyProxiesForURL((__bridge CFURLRef _Nonnull)([NSURL URLWithString:@"http://www.baidu.com"]), (__bridge CFDictionaryRef _Nonnull)(proxySettings)));
    NSDictionary *settings = [proxies objectAtIndex:0];
    
    NSLog(@"host=%@", [settings objectForKey:(NSString *)kCFProxyHostNameKey]);
    NSLog(@"port=%@", [settings objectForKey:(NSString *)kCFProxyPortNumberKey]);
    NSLog(@"type=%@", [settings objectForKey:(NSString *)kCFProxyTypeKey]);
    
    if ([[settings objectForKey:(NSString *)kCFProxyTypeKey] isEqualToString:@"kCFProxyTypeNone"]){
        //没有设置代理
        return NO;
    }else{
        //设置代理了
        return YES;
    }
}

五、防调试

+ (void)antiDebug {
    
    gx_disable_gdb();

    gx_AntiDebugASM();

    gx_AntiDebug_isatty();
    
}

/// ptrace反调试,阻止GDB依附
typedef int (*ptrace_ptr_t)(int _request, pid_t pid, caddr_t _addr, int _data);
#if !defined(PT_DENT_ATTACH)
#define PT_DENT_ATTACH 31
#endif
void gx_disable_gdb() {
    void * handle = dlopen(0, RTLD_GLOBAL|RTLD_NOW);
    ptrace_ptr_t ptrace_ptr = dlsym(handle, "ptrace");
    ptrace_ptr(PT_DENT_ATTACH, 0, 0, 0);
    dlclose(handle);
}


/// 内联 svc + ptrace 实现和内联 svc + syscall + ptrace 实现
// 使用inline方式将函数在调用处强制展开,防止被hook和追踪符号
__attribute__((always_inline)) void gx_AntiDebugASM() {
#ifdef __arm__
    asm volatile(
                 "mov r0,#31\n"
                 "mov r1,#0\n"
                 "mov r2,#0\n"
                 "mov r12,#26\n"
                 "svc #80\n"
                 );
#endif
#ifdef __arm64__
    asm volatile(
                 "mov x0,#26\n"
                 "mov x1,#31\n"
                 "mov x2,#0\n"
                 "mov x3,#0\n"
                 "mov x16,#0\n"
                 "svc #128\n"
                 );
#endif
}

/// isatty检测是否正在被调试
//需要头文件#include <unistd.h>
void gx_AntiDebug_isatty() {
    if (isatty(1)) {
        _exit(1);
    } else {
    }
}
相关推荐
冰淇淋百宝箱2 小时前
AI 安全时代:SDL与大模型结合的“王炸组合”——技术落地与实战指南
人工智能·安全
网络安全(king)2 小时前
网络安全知识:网络安全网格架构
安全·web安全·架构
anddddoooo2 小时前
域内证书维权
服务器·网络·网络协议·安全·网络安全·https·ssl
Dyan_csdn2 小时前
【Python项目】基于Python的Web漏洞挖掘系统
网络·python·安全·web安全
openinstall全渠道统计3 小时前
免填邀请码工具:赋能六大核心场景,重构App增长新模型
android·ios·harmonyos
Moyo2036 小时前
前端web安全
前端·安全·web安全
JSZNZZ7 小时前
汽车软件︱AUTO TECH China 2025 广州国际汽车软件与安全技术展览会:开启汽车科技新时代
科技·安全·汽车
爱编程的小庄7 小时前
web安全:跨站请求伪造 (CSRF)
安全·web安全·csrf
早起的年轻人7 小时前
Flutter CupertinoNavigationBar iOS 风格导航栏的组件
flutter·ios
貂蝉空大10 小时前
uni-app开发安卓和ios app 真机调试
android·ios·uni-app