IOS知识积累iOS 逆向技术分享

iOS sysctl的防护与破解

2018-06-12  本文已影响288人  heart_领

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

攻防博弈

上一篇下一篇

猜你喜欢

热点阅读