sysctl、反HOOK

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);
}

//检测是否被调试
BOOL isDebugger(){
    //控制码
    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);
    assert(error == 0);//0就是没有错误,其他就是错误码
    //p_flag 有很多二进制信息
    //例如:1011 1000 1010 1010 1101 0101 1101 0101
    //&
    //0000 0000 0000 1000 0000 0000 0000 0000
    // 第32位 == 0 ? 没有  有!!
    return ((info.kp_proc.p_flag & P_TRACED) != 0);
}

- (void)viewDidLoad {
    [super viewDidLoad];
    debugCheck();
}

2.破解sysctl - fishHook

#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){
    if (namelen == 4
        //检查内核
        && name[0] == CTL_KERN
        //检查内核的进程
        && name[1] == KERN_PROC
         //传递的参数是PID
        && 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){
            //使用异或取反
            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, 1);
}

@end

3. ptrace&sysctl提前执行

#import "antiDebugCode.h"
#import "fishhook.h"
#import "MyPtraceHeader.h"
#import <sys/sysctl.h>

static dispatch_source_t timer;
@implementation antiDebugCode

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);
}

//检测是否被调试
BOOL isDebugger(){
    //控制码
    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);
    assert(error == 0);//0就是没有错误,其他就是错误码
    
    //1011 1000 1010 1010 1101 0101 1101 0101
    //&
    //0000 0000 0000 1000 0000 0000 0000 0000
    // == 0 ? 没有  有!!
    return ((info.kp_proc.p_flag & P_TRACED) != 0);
}

void debugerCheck(){
    if (isDebugger()) {
        NSLog(@"进程被调试!!");
    }
    
    //开启反调试
    ptrace(PT_DENY_ATTACH, getpid(), 0, 0);
}

+(void)load
{
    debugerCheck();
}

@end

4. 攻防博弈!找到你就赢

//只要调用就可以断住
ptrace
//bt查看函数真实。相对于动态库偏移地址。指令地址,pc寄存器永远指向下一条
//image list 找到动态库地址
//偏移地址减去动态库地址,拿到指令地址
//hopper查看,指令地址的上一条即为调用地址
//寄存器前三句(保护寄存器)直接跳到后三句(恢复寄存器)。不执行中间option+A修改
//导出file/Produce New Executable
//替换Macho

5. 破解悬疑已久的反HOOK

//拿到的地址
bt 
//查看汇编
dis -s 地址