iOS sysctl的防护与破解

作者: heart_领 | 来源:发表于2018-06-12 17:15 被阅读288次

    1.sysctl的防护

    #import "ViewController.h"
    #import <sys/sysctl.h>
    
    @interface ViewController ()
    
    @end
    static dispatch_source_t timer;
    @implementation ViewController
    
    void debugCheck(){
        timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
        dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0.0 * NSEC_PER_SEC);
        dispatch_source_set_event_handler(timer, ^{
            if (isDebugger()) {
                NSLog(@"检测到了!!");
            }else{
                NSLog(@"正常!!");
            }
        });
        dispatch_resume(timer);
        
        dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
        dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
        dispatch_source_set_event_handler(timer, ^{
            
        });
        dispatch_resume(timer);
    }
    //int    sysctl(int *, u_int, void *, size_t *, void *, size_t);
    //检测是否被调试
    BOOL isDebugger(){
        //控制码
    //    方式一
    //    int name[] = {
    //        CTL_KERN,
    //        KERN_PROC,
    //        KERN_PROC_PID,
    //        getpid()
    //    };
    //    方式二
        int name[4];//里面放字节码.查询信息
        name[0] = CTL_KERN;//内核查看
        name[1] = KERN_PROC;//查询进程
        name[2] = KERN_PROC_PID;//传递的参数是进程的ID(PID)
        name[3] = getpid();//PID的值告诉
        
        struct kinfo_proc info;//接受进程查询结果信息的结构体
        size_t info_size = sizeof(info);//结构体的大小
        int error = sysctl(name, sizeof(name)/sizeof(*name), &info, &info_size, 0, 0);//sizeof(name)/sizeof(*name)或者sizeof(name)/sizeof(int)
        assert(error == 0);//0就是没有错误,其他就是错误码
        /**
         0000 0000 0000 0000 0100 1000 0000 0100//有调试(info.kp_proc.p_flag=18436)
         &
         0000 0000 0000 0000 0000 1000 0000 0000 (P_TRACED)
         结果:
         0000 0000 0000 0000 0000 1000 0000 0000 (不为0)
         
         
         0000 0000 0000 0000 0100 0000 0000 0100//没有调试(info.kp_proc.p_flag=16388)
         &
         0000 0000 0000 0000 0000 1000 0000 0000   (P_TRACED)
         结果:
         0000 0000 0000 0000 0000 0000 0000 0000 (为0)
         
         结果为0没有调试,结果不为0有调试
         */
        return ((info.kp_proc.p_flag & P_TRACED) != 0);
        
    }
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        debugCheck();
        
        
    }
    @end
    
    调试.png

    2.使用动态库破解sysctl

    #import "injectCode.h"//自己创建的动态库
    #import "fishhook.h"
    #import <sys/sysctl.h>
    @implementation injectCode
    //原始函数的地址
    int (*sysctl_p)(int *, u_int, void *, size_t *, void *, size_t);
    //自定义函数
    int mySysctl(int *name, u_int namelen, void *info, size_t *infosize, void *newinfo, size_t newinfosize){
        struct kinfo_proc *myInfo1 = (struct kinfo_proc *)info;
        NSLog(@"哈哈哈哈哈哈哈哈哈:%d",myInfo1->kp_proc.p_flag);//结果为1
        if (namelen == 4
            && name[0] == CTL_KERN
            && name[1] == KERN_PROC
            && name[2] == KERN_PROC_PID
            && info
            && (int)*infosize == sizeof(struct kinfo_proc))
        {
            int err = sysctl_p(name, namelen, info, infosize, newinfo, newinfosize);
            //拿出info做判断
            struct kinfo_proc *myInfo = (struct kinfo_proc *)info;
            if((myInfo->kp_proc.p_flag & P_TRACED) != 0){
                NSLog(@"哈哈哈哈哈哈哈哈哈22:%d",myInfo1->kp_proc.p_flag);//结果为18436(被调试)
                //使用异或取反(使第12位由1标为0)
                myInfo->kp_proc.p_flag ^= P_TRACED;
            }
            return err;
        }
        return sysctl_p(name, namelen, info, infosize, newinfo, newinfosize);
    }
    +(void)load
    {
        //交换
        rebind_symbols((struct rebinding[1]){{"sysctl",mySysctl,(void *)&sysctl_p}}, 1);
    }
    @end
    
    动态库破解.png

    3.使用动态库防护(把sysctl的防护代码写到动态库中)
    原理:防护代码的执行先于hook的代码


    反破解.png

    4.通过修改MachO文件破解动态库的防护
    运行重签名的app闪退,源代码中很有可能使用了exit或者ptrace


    [图片上传中...(给ptrace下符号断点.png-2aea1d-1528811285916-0)]
    给ptrace下符号断点.png
    使用了ptrace.png
    栈信息.png
    ptrace的相对地址.png
    跳转1.png
    ![快捷键位置.png](https://img.haomeiwen.com/i1732937/2f4e3cc02d04a139.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    导出新文件.png
    快捷键位置.png

    攻防博弈

    相关文章

      网友评论

        本文标题:iOS sysctl的防护与破解

        本文链接:https://www.haomeiwen.com/subject/fsnleftx.html