iOS逆向安防 调试与反调试

2,240 阅读2分钟

保护调试

防止App被重签名调试

代码:

#import <sys/sysctl.h>
- (void)done{
    if([self isDebug]){
        NSLog(@"存在调试器");
        
        //存在工具调试操作直接退出
        exit(0);
    }else{
        NSLog(@"不存在调试器");
    }
}

- (BOOL)isDebug{
    int name[4];//里面存放字节码
    name[0] = CTL_KERN;//内核查询
    name[1] = KERN_PROC;//查询进程
    name[2] = KERN_PROC_PID;//传递的参数是进程ID
    name[3] = getpid();//PID 进程ID
    
    struct kinfo_proc info;//查询到的结果放到此结构体
    
    size_t info_size = sizeof(info);
    
    //调试信息
    sysctl(name, sizeof(name)/sizeof(*name), &info, &info_size, 0, 0);
    
    //info.kp_proc.p_flag 第12位若为1则存在调试
    
    return ((info.kp_proc.p_flag & P_TRACED) !=0);
}

攻击保护调试

步骤(hook方式)

1.重签名应用进行调试

2.增加symbolic Breakpoint断点并筛选方法名关键字,例如:(exit)

3.进入断点后,输出(lldb)bt 指令,查看函数调用栈,找到根方法的内存地址

4.进入断点后,输出(lldb)image list 镜像(可执行)文件列表指令,找到文件首地址(第一条 )

5.用内存地址减去文件首地址计算出偏移量

6.找到可执行文件(exec)使用反汇编工具(hopper diaassembler v4)进行分析,并用计算出的偏移量进行查询

7.由于寄存器的原因需减掉4字节,所以真实调用的为查询结果的上一条

8.选择汇编代码,点击空格查看调用流程(保护调试方式为sysctl)

9.建立framework使用脚本进行fishHook注入,方法交换

代码:

#import "fishhook.h"
//原是函数指针
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){

    //反调试操作过滤
    if (namelen == 4 && name[0] == CTL_KERN && name[1] == KERN_PROC && name[2] == KERN_PROC_PID && info) {
    
        //暂时保留
        int error = 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){//存在调试
        
            //使用异或取反
            myinfo->kp_proc.p_flag ^= P_TRACED;
            
        }
        
        return error;
    }
    
    return  sysctl_p(name,namelen,info,infoSize,newInfo,newInfoSize);
}
+(void)load{

    //方法交换
    rebind_symblos((struct rebinding[1]{{"sysctl",mySysctl,(void *)&sysctl_p}},1);
    
}