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
攻防博弈
网友评论